1 /***************************************************************************
3 * ZXEmuT -- ZX Spectrum Emulator with Tcl scripting
5 * Copyright (C) 2012-2022 Ketmar Dark <ketmar@ketmar.no-ip.org>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 3 of the License ONLY.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **************************************************************************/
26 #include <sys/types.h>
29 #include "libvideo/video.h"
38 #include "zxkeyinfo.h"
41 #include "libboots/libboots.h"
44 ////////////////////////////////////////////////////////////////////////////////
45 #define JIMAPI_FN(name) static int jim_##name (Jim_Interp *interp, int argc, Jim_Obj *const *argv)
46 #define JIMAPI_REGISTER(name) Jim_CreateCommand(jim, #name, jim_##name, NULL, NULL)
49 ////////////////////////////////////////////////////////////////////////////////
50 #include "jimapi_utils.c"
51 #include "jimapi_sdlkeys.c"
54 ////////////////////////////////////////////////////////////////////////////////
56 JIMAPI_FN(consetstr
) {
58 Jim_WrongNumArgs(interp
, 1, argv
, "string");
61 conSetInputString(Jim_String(argv
[1]));
62 Jim_SetResultBool(interp
, 1);
70 Jim_WrongNumArgs(interp
, 1, argv
, "?-nonewline? string");
75 if (Jim_CompareStringImmediate(interp
, argv
[1], "-nonewline")) { donl
= 0; ++argp
; }
76 for (; argp
< argc
; ++argp
) cprintf("%s", Jim_String(argv
[argp
]));
77 if (donl
) cprintf("\n");
78 Jim_SetResultBool(interp
, 1);
86 Jim_WrongNumArgs(interp
, 1, argv
, "?-nonewline? string");
91 if (Jim_CompareStringImmediate(interp
, argv
[1], "-nonewline")) { donl
= 0; ++argp
; }
92 for (; argp
< argc
; ++argp
) cprintf("%s", Jim_String(argv
[argp
]));
93 if (donl
) cprintf("\n");
95 for (; argp
< argc
; ++argp
) fprintf(stderr
, "%s", Jim_String(argv
[argp
]));
96 if (donl
) fprintf(stderr
, "\n");
97 Jim_SetResultBool(interp
, 1);
104 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
105 if (argc
!= 2) { Jim_WrongNumArgs(interp
, 1, argv
, "name"); return JIM_ERR
; }
106 jimEvalFile(Jim_String(argv
[1]), 0);
107 Jim_SetResultBool(interp
, 1);
112 // won't fail if the file is absent
113 JIMAPI_FN(softload
) {
114 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
115 if (argc
!= 2) { Jim_WrongNumArgs(interp
, 1, argv
, "name"); return JIM_ERR
; }
116 jimEvalFile(Jim_String(argv
[1]), 1);
117 Jim_SetResultBool(interp
, 1);
122 ////////////////////////////////////////////////////////////////////////////////
124 JIMAPI_FN(vid_scale
) {
125 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
126 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
127 //char *a0 = completeAbbrev((argc > 1 ? Jim_String(argv[1]) : ""), "keep", NULL);
128 jimapiStrAppendAbbrev(interp
, res
, "");
130 jimapiAppendRestArgs(res
, 2);
131 Jim_SetResult(interp
, res
);
136 jim_SetResStrf(interp
, "%s: wut?!", Jim_String(argv
[0]));
141 Jim_SetResultInt(interp
, vidScale
);
145 int newval
= jimGetIntVal(interp
, argv
[1]);
146 if (newval
== JIM_INVALID_INTVAL
) {
147 jim_SetResStrf(interp
, "%s: invalid numeric value: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
150 if (newval
< 1 || newval
> 4) {
151 jim_SetResStrf(interp
, "%s: scale value out of bounds: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
162 ////////////////////////////////////////////////////////////////////////////////
164 JIMAPI_FN(vid_rescaler
) {
165 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
166 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
167 //char *a0 = completeAbbrev((argc > 1 ? Jim_String(argv[1]) : ""), "keep", NULL);
168 jimapiStrAppendAbbrev(interp
, res
, "");
170 jimapiAppendRestArgs(res
, 2);
171 Jim_SetResult(interp
, res
);
176 jim_SetResStrf(interp
, "%s: wut?!", Jim_String(argv
[0]));
181 Jim_SetResultInt(interp
, vid_scaler_type
);
185 int newval
= jimGetIntVal(interp
, argv
[1]);
186 if (newval
== JIM_INVALID_INTVAL
) {
187 jim_SetResStrf(interp
, "%s: invalid numeric value: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
191 if (newval
< 0 || newval
>= VID_SCALER_MAX
) {
192 jim_SetResStrf(interp
, "%s: scale value out of bounds: '%s' (max is %d)",
193 Jim_String(argv
[0]), Jim_String(argv
[1]), VID_SCALER_MAX
-1);
196 vid_scaler_type
= newval
;
205 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
206 //if (argc != 1) { Jim_WrongNumArgs(interp, 1, argv, "no args expected"); return JIM_ERR; }
208 Jim_SetResultBool(interp
, 1);
213 // reset [forced] [model] [issue] [memory] [trdos]
215 // 48k: [issue2|issue3|2|3]
216 // pentagon: [128|512|1024]
220 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
221 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
222 if (argc
== 1) Jim_AppendString(interp
, res
, " ", -1);
223 for (int f
= 1; f
< argc
; ++f
) {
226 a0
= completeAbbrev(Jim_String(argv
[f
]), "48k", "pentagon", "scorpion", "trdos", "forced", NULL
);
228 a0
= completeAbbrev(Jim_String(argv
[f
]), "48k", "128k", "plus2", "plus2a", "plus3", "pentagon", "scorpion", "issue2", "issue3", "trdos", "forced", NULL
);
229 if (strEqu(a0
, "pentagon")) was_penta
= 1;
231 jimapiStrAppendAbbrev(interp
, res
, a0
);
234 Jim_SetResult(interp
, res
);
238 int model
= -1, forced
= 0, issue
= optZXIssue
, pmem
= -1/*128*//*zxPentagonMemory*/, trdos
= 0;
240 //if (argc < 1) { Jim_WrongNumArgs(interp, 1, argv, "string"); return JIM_ERR; }
241 for (int f
= 1; f
< argc
; ++f
) {
245 a0
= parseAbbrev(Jim_String(argv
[f
]), "48k", "pentagon", "scorpion", NULL
);
247 a0
= parseAbbrev(Jim_String(argv
[f
]), "48k", "128k", "plus2", "plus2a", "plus3", "pentagon", "scorpion", NULL
);
251 if (strEqu(a0
, "48k")) model
= ZX_MACHINE_48K
;
252 else if (strEqu(a0
, "128k")) model
= ZX_MACHINE_128K
;
253 else if (strEqu(a0
, "plus2")) model
= ZX_MACHINE_PLUS2
;
254 else if (strEqu(a0
, "plus2a")) model
= ZX_MACHINE_PLUS2A
;
255 else if (strEqu(a0
, "plus3")) model
= ZX_MACHINE_PLUS3
;
256 else if (strEqu(a0
, "pentagon")) {
257 model
= ZX_MACHINE_PENTAGON
;
258 if (pmem
< 0) pmem
= 128;
260 } else if (strEqu(a0
, "scorpion")) model
= ZX_MACHINE_SCORPION
;
263 jim_SetResStrf(interp
, "%s: duplicate model name: '%s'", Jim_String(argv
[0]), Jim_String(argv
[f
]));
268 if ((a0
= parseAbbrev(Jim_String(argv
[f
]), "forced", NULL
)) != NULL
) {
273 if ((a0
= parseAbbrev(Jim_String(argv
[f
]), "trdos", NULL
)) != NULL
) {
278 if ((a0
= parseAbbrev(Jim_String(argv
[f
]), "issue2", "issue3", NULL
)) != NULL
) {
283 if (Jim_GetLong(interp
, argv
[f
], &val
) == JIM_OK
) {
284 if (val
== 2 || val
== 3) { issue
= val
-2; continue; }
285 if (val
== 128 || val
== 512 || val
== 1024) { pmem
= val
; continue; }
288 jim_SetResStrf(interp
, "%s: invalid option: '%s'", Jim_String(argv
[0]), Jim_String(argv
[f
]));
292 if (model
< 0) model
= zxModel
;
293 if (pmem
< 0) pmem
= zxPentagonMemory
;
294 if (model
== ZX_MACHINE_PENTAGON
&& pmem
!= zxPentagonMemory
) forced
= 1;
297 zxPentagonMemory
= pmem
;
298 emuSetModel(model
, forced
);
302 case ZX_MACHINE_48K
: jim_SetResStrf(interp
, "48k (issue %d)", optZXIssue
+2); break;
303 case ZX_MACHINE_128K
: Jim_SetResultString(interp
, "128k", -1); break;
304 case ZX_MACHINE_PLUS2
: Jim_SetResultString(interp
, "128k+2", -1); break;
305 case ZX_MACHINE_PLUS2A
: Jim_SetResultString(interp
, "128k+2a", -1); break;
306 case ZX_MACHINE_PLUS3
: Jim_SetResultString(interp
, "128k+3", -1); break;
307 case ZX_MACHINE_PENTAGON
: jim_SetResStrf(interp
, "pentagon%d", zxPentagonMemory
); break;
308 case ZX_MACHINE_SCORPION
: Jim_SetResultString(interp
, "scorpion", -1); break;
309 default: Jim_SetResultBool(interp
, 0); break;
317 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
318 if (argc
!= 1) { Jim_WrongNumArgs(interp
, 1, argv
, "too many args"); return JIM_ERR
; }
320 case ZX_MACHINE_48K
: jim_SetResStrf(interp
, "48k (issue %d), %d tstates per frame", optZXIssue
+2, machineInfo
.tsperframe
); break;
321 case ZX_MACHINE_128K
: jim_SetResStrf(interp
, "128k, %d tstates per frame", machineInfo
.tsperframe
); break;
322 case ZX_MACHINE_PLUS2
: jim_SetResStrf(interp
, "128k+2, %d tstates per frame", machineInfo
.tsperframe
); break;
323 case ZX_MACHINE_PLUS2A
: jim_SetResStrf(interp
, "128k+2a, %d tstates per frame", machineInfo
.tsperframe
); break;
324 case ZX_MACHINE_PLUS3
: jim_SetResStrf(interp
, "128k+3, %d tstates per frame", machineInfo
.tsperframe
); break;
325 case ZX_MACHINE_PENTAGON
: jim_SetResStrf(interp
, "pentagon%d, %d tstates per frame", zxPentagonMemory
, machineInfo
.tsperframe
); break;
326 case ZX_MACHINE_SCORPION
: jim_SetResStrf(interp
, "scorpion, %d tstates per frame", machineInfo
.tsperframe
); break;
327 default: Jim_SetResultString(interp
, "unknown", -1); break;
335 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
336 if (argc
!= 1) { Jim_WrongNumArgs(interp
, 1, argv
, "too many args"); return JIM_ERR
; }
338 Jim_SetResultBool(interp
, 1);
343 // grab [set|reset|toggle]
345 int v
= (SDL_WM_GrabInput(SDL_GRAB_QUERY
) == SDL_GRAB_ON
);
346 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "set", "reset", 1);
347 if (res
!= JIM_ERR
) {
348 SDL_WM_GrabInput(v
? SDL_GRAB_ON
: SDL_GRAB_OFF
);
349 emuRealizeRealMouseCursorState();
355 // maxspeedugly [on|off|toogle]
356 JIMAPI_FN(maxspeedugly
) {
357 int v
= optMaxSpeedBadScreen
;
358 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
359 optMaxSpeedBadScreen
= v
;
364 // fps [on|off|toogle]
367 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
373 // trdos [on|off|toggle]
375 int da
= !!optTRDOSenabled
;
376 int res
= jim_onoff_option(&da
, interp
, argc
, argv
, "on", "off", 1);
377 if (!da
) zxTRDOSpageout();
378 optTRDOSenabled
= da
;
383 // swapbuttons [on|off|toggle]
384 JIMAPI_FN(swapbuttons
) {
385 int da
= optKMouseSwapButtons
;
386 int res
= jim_onoff_option(&da
, interp
, argc
, argv
, "on", "off", 1);
387 optKMouseSwapButtons
= da
;
392 //FIXME: separate to two commands
393 // kmouse [on|off|toggle|sens]
397 int res = jim_onoff_option(&da, interp, argc, argv, "on", "off", 1);
401 int res
= jim_AlphaArg(&optKMouse
, &zxKMouseSpeed
, interp
, argc
, argv
);
402 if (zxKMouseSpeed
< 1) zxKMouseSpeed
= 1; else if (zxKMouseSpeed
> 255) zxKMouseSpeed
= 255;
407 // kspanish [on|off|toggle]
408 // toggles kempston mouse between strict (on) or normal (off)
409 JIMAPI_FN(kspanish
) {
410 int da
= optKMouseStrict
;
411 int res
= jim_onoff_option(&da
, interp
, argc
, argv
, "on", "off", 1);
412 optKMouseStrict
= da
;
417 // kjoystick [on|off|toggle]
418 JIMAPI_FN(kjoystick
) {
419 int da
= optKJoystick
;
420 int res
= jim_onoff_option(&da
, interp
, argc
, argv
, "on", "off", 1);
426 // speed [max|normal|toggle|percents|shade|noshade]
428 if (!jimapiWantsCompletion(interp
, argc
, argv
)) {
429 if (argc
== 2 && strEquCI(Jim_String(argv
[1]), "shade")) {
431 Jim_SetResultBool(interp
, 1);
434 if (argc
== 2 && strEquCI(Jim_String(argv
[1]), "noshade")) {
436 Jim_SetResultBool(interp
, 1);
441 int val
= jimGetIntLitVal(interp
, argv
[1]);
442 if (val
!= JIM_INVALID_INTVAL
) {
444 if (val
< 1) val
= 1; else if (val
> 1000) val
= 1000;
447 if (jimapiFromConsole(interp
)) cprintf("speed: %d%%\n", optSpeed
);
448 jim_SetResStrf(interp
, "%d", optSpeed
);
456 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "max", "normal", 0);
462 // pause [set|reset|toggle]
464 int v
= ((optPaused
&PAUSE_PERMANENT_MASK
) != 0);
465 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "set", "reset", 1);
466 emuSetPaused(v
? PAUSE_PERMANENT_SET
: PAUSE_PERMANENT_RESET
);
471 // temppause [set|reset|toggle]
472 JIMAPI_FN(temppause
) {
473 int v
= ((optPaused
&PAUSE_TEMPORARY_MASK
) != 0);
474 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "set", "reset", 1);
475 emuSetPaused(v
? PAUSE_TEMPORARY_SET
: PAUSE_TEMPORARY_RESET
);
480 // timings [early|late|toggle]
482 int v
= zxLateTimings
;
483 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "late", "early", 0);
484 emuSetLateTimings(v
);
489 // console [show|hide|toggle|<alpha>]
491 return jim_AlphaArg(&conVisible
, &conAlpha
, interp
, argc
, argv
);
495 // kbleds [on|off|toggle|<alpha>]
497 return jim_AlphaArg(&optDrawKeyLeds
, &klAlpha
, interp
, argc
, argv
);
501 // debugger [on|off|toggle|<alpha>]
502 //TODO: add 'debugger traps on|off' -- for optAllowZXEmuTraps
503 JIMAPI_FN(debugger
) {
504 int da
= debuggerActive
;
505 int res
= jim_AlphaArg(&da
, &dbgAlpha
, interp
, argc
, argv
);
506 if (da
) { memviewSetActive(0); sprviewSetActive(0); }
512 // memview [on|off|toggle|hex|text|32|42|51|64|max|7bit|cp-866|cp-1251]
514 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
515 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
516 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""),
517 "on", "off", "toggle",
519 "32", "42", "51", "64", "max",
520 "7bit", "cp866", "cp1251",
521 "blue", "red", "magenta", "green", "cyan",
522 "yellow", "white", "gray", "bright",
524 jimapiStrAppendAbbrev(interp
, res
, a0
);
526 jimapiAppendRestArgs(res
, 2);
527 Jim_SetResult(interp
, res
);
531 if (argc
< 1) { Jim_WrongNumArgs(interp
, 1, argv
, "option"); return JIM_ERR
; }
536 for (int f
= 1; f
< argc
; ++f
) {
537 const char *a0
= parseAbbrev(Jim_String(argv
[f
]),
538 "on", "off", "tan", "ona", "toggle",
540 "32", "42", "51", "64", "max",
541 "7bit", "cp866", "cp1251",
542 "blue", "red", "magenta", "green", "cyan",
543 "yellow", "white", "gray", "grey", "bright",
546 if (strEquCI(a0
, "on") || strEquCI(a0
, "tan")) onoff
= 1;
547 else if (strEquCI(a0
, "off") || strEquCI(a0
, "ona")) onoff
= 0;
548 else if (strEquCI(a0
, "toggle")) onoff
= !memviewActive
;
549 else if (strEquCI(a0
, "hex")) mv_viewmode
= MV_MODE_HEX
;
550 else if (strEquCI(a0
, "text")) mv_viewmode
= MV_MODE_TEXT
;
551 else if (strEquCI(a0
, "32")) mv_textwidth
= 32;
552 else if (strEquCI(a0
, "42")) mv_textwidth
= 42;
553 else if (strEquCI(a0
, "51")) mv_textwidth
= 51;
554 else if (strEquCI(a0
, "64")) mv_textwidth
= 64;
555 else if (strEquCI(a0
, "max")) mv_textwidth
= MV_MAX_TEXT_WIDTH
;
556 else if (strEquCI(a0
, "7bit")) mv_encoding
= MV_ENC_7BIT
;
557 else if (strEquCI(a0
, "cp866")) mv_encoding
= MV_ENC_866
;
558 else if (strEquCI(a0
, "cp1251")) mv_encoding
= MV_ENC_1251
;
559 else if (strEquCI(a0
, "blue")) { if (bright
< 0) bright
= 0; mv_textcolor
= 1; }
560 else if (strEquCI(a0
, "red")) { if (bright
< 0) bright
= 0; mv_textcolor
= 2; }
561 else if (strEquCI(a0
, "magenta")) { if (bright
< 0) bright
= 0; mv_textcolor
= 3; }
562 else if (strEquCI(a0
, "green")) { if (bright
< 0) bright
= 0; mv_textcolor
= 4; }
563 else if (strEquCI(a0
, "cyan")) { if (bright
< 0) bright
= 0; mv_textcolor
= 5; }
564 else if (strEquCI(a0
, "yellow")) { if (bright
< 0) bright
= 0; mv_textcolor
= 6; }
565 else if (strEquCI(a0
, "white")) { if (bright
< 0) bright
= 0; mv_textcolor
= 7; }
566 else if (strEquCI(a0
, "gray")) { if (bright
< 0) bright
= 0; mv_textcolor
= 7; }
567 else if (strEquCI(a0
, "grey")) { if (bright
< 0) bright
= 0; mv_textcolor
= 7; }
568 else if (strEquCI(a0
, "bright")) bright
= 1;
570 jim_SetResStrf(interp
, "%s: invalid mode: '%s'", Jim_String(argv
[0]), Jim_String(argv
[f
]));
574 int addr
= jimGetIntValEx(interp
, argv
[f
], 1/*allowpgaddr*/);
575 //FIXME: this check is wrong
576 //FIXME: write correct page parsing
577 if (addr
>= 0 && addr
< (zxMaxMemoryBank
+4)<<14) {
578 mv_staddr
= (uint32_t)addr
;
581 jim_SetResStrf(interp
, "%s: wtf is '%s'?", Jim_String(argv
[0]), Jim_String(argv
[f
]));
587 if (bright
) mv_textcolor
|= 8; else mv_textcolor
&= 7;
591 if (onoff
> 0) { dbgSetActive(0); sprviewSetActive(0); }
592 memviewSetActive(onoff
);
595 Jim_SetResultInt(interp
, memviewActive
);
600 // sprview [on|off|toggle]
602 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
603 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
604 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""),
605 "on", "off", "toggle",
607 jimapiStrAppendAbbrev(interp
, res
, a0
);
609 jimapiAppendRestArgs(res
, 2);
610 Jim_SetResult(interp
, res
);
614 if (argc
< 1) { Jim_WrongNumArgs(interp
, 1, argv
, "option"); return JIM_ERR
; }
618 for (int f
= 1; f
< argc
; ++f
) {
619 const char *a0
= parseAbbrev(Jim_String(argv
[f
]),
620 "on", "off", "tan", "ona", "toggle",
623 if (strEquCI(a0
, "on") || strEquCI(a0
, "tan")) onoff
= 1;
624 else if (strEquCI(a0
, "off") || strEquCI(a0
, "ona")) onoff
= 0;
625 else if (strEquCI(a0
, "toggle")) onoff
= !sprviewActive
;
627 jim_SetResStrf(interp
, "%s: invalid mode: '%s'", Jim_String(argv
[0]), Jim_String(argv
[f
]));
631 int addr
= jimGetIntValEx(interp
, argv
[f
], 1/*allowpgaddr*/);
632 //FIXME: this check is wrong
633 //FIXME: write correct page parsing
634 if (addr
>= 0 && addr
< (zxMaxMemoryBank
+4)<<14) {
635 spr_staddr
= (uint32_t)addr
;
638 jim_SetResStrf(interp
, "%s: wtf is '%s'?", Jim_String(argv
[0]), Jim_String(argv
[f
]));
644 if (onoff
> 0) { dbgSetActive(0); memviewSetActive(0); }
645 sprviewSetActive(onoff
);
648 Jim_SetResultInt(interp
, sprviewActive
);
653 // useplus3 [on|off|toggle]
654 JIMAPI_FN(useplus3
) {
655 if (machineInfo
.origContention
) {
656 int v
= machineInfo
.usePlus3Contention
;
657 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
658 if (machineInfo
.usePlus3Contention
!= v
) {
659 machineInfo
.usePlus3Contention
= v
;
660 emuBuildContentionTable();
664 Jim_SetResultBool(interp
, machineInfo
.usePlus3Contention
);
669 // genuine [on|off|toggle]
671 int v
= machineInfo
.genuine
;
672 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
673 if (machineInfo
.genuine
!= v
) {
674 machineInfo
.genuine
= v
;
677 Jim_SetResultBool(interp
, machineInfo
.genuine
);
682 // contention [on|off|toggle]
683 JIMAPI_FN(contention
) {
684 if (machineInfo
.origContention
) {
685 int v
= machineInfo
.contention
;
686 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
687 machineInfo
.contention
= v
;
688 if (machineInfo
.origIOContention
) machineInfo
.iocontention
= v
;
691 Jim_SetResultBool(interp
, machineInfo
.contention
);
696 // memcontention [on|off|toggle]
697 JIMAPI_FN(memcontention
) {
698 if (machineInfo
.origContention
) {
699 int v
= machineInfo
.contention
;
700 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
701 machineInfo
.contention
= v
;
704 Jim_SetResultBool(interp
, machineInfo
.contention
);
709 // iocontention [on|off|toggle]
710 JIMAPI_FN(iocontention
) {
711 if (machineInfo
.origIOContention
) {
712 int v
= machineInfo
.iocontention
;
713 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
714 machineInfo
.iocontention
= v
;
717 Jim_SetResultBool(interp
, machineInfo
.iocontention
);
722 // snow [on|off|toggle]
724 int v
= optEmulateSnow
;
725 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
726 if (v
!= optEmulateSnow
) {
728 memset(zxUlaSnow
, 0, sizeof(zxUlaSnow
));
735 // noflic [on|off|toggle]
737 //int da = optNoFlic;
738 //int res = jim_onoff_option(&da, interp, argc, argv, "on", "off", "detect", 1);
740 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
741 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
742 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "on", "off", "detect", NULL
);
743 jimapiStrAppendAbbrev(interp
, res
, a0
);
745 jimapiAppendRestArgs(res
, 2);
746 Jim_SetResult(interp
, res
);
750 if (argc
< 1 || argc
> 2) { Jim_WrongNumArgs(interp
, 1, argv
, "string"); return JIM_ERR
; }
752 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "on", "off", "detect", "tan", "ona", NULL
);
754 if (strEqu(a0
, "on") || strEqu(a0
, "yes") || strEqu(a0
, "tan")) optNoFlic
= 1;
755 else if (strEqu(a0
, "off") || strEqu(a0
, "no") || strEqu(a0
, "ona")) optNoFlic
= 0;
756 else if (strEqu(a0
, "detect")) optNoFlic
= -1;
758 jim_SetResStrf(interp
, "%s: invalid mode: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
762 if (jimapiFromConsole(interp
)) cprintf("%s: %d\n", Jim_String(argv
[0]), optNoFlic
);
764 Jim_SetResultInt(interp
, optNoFlic
);
769 // brightblack [on|off|toggle|value]
770 JIMAPI_FN(brightblack
) {
771 const int da
= optBrightBlack
;
772 const int ovv
= optBrightBlackValue
;
773 int res
= jim_AlphaArg(&optBrightBlack
, &optBrightBlackValue
, interp
, argc
, argv
);
774 if (optBrightBlackValue
< 0) optBrightBlackValue
= 0; else if (optBrightBlackValue
> 255) optBrightBlackValue
= 255;
776 if (optBrightBlack
!= da
|| optBrightBlackValue
!= ovv
) {
777 if (optBrightBlack
) {
778 zxPalette
[8*3+0] = zxPalette
[8*3+1] = zxPalette
[8*3+2] = optBrightBlackValue
;
780 zxPalette
[8*3+0] = zxPalette
[8*3+1] = zxPalette
[8*3+2] = 0;
789 // zxpalcolor index [#rrggbb]
790 JIMAPI_FN(zxpalcolor
) {
791 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
792 if (argc
< 2 || argc
> 3) {
793 jim_SetResStrf(interp
, "%s: expected index and optional #rrggbb color", Jim_String(argv
[0]));
797 int idx
= jimGetIntLitVal(interp
, argv
[1]);
798 if (idx
< 0 || idx
> 15) {
799 jim_SetResStrf(interp
, "%s: invalid color index %s", Jim_String(argv
[0]), Jim_String(argv
[1]));
805 snprintf(stbuf
, sizeof(stbuf
), "#%02x%02x%02x", zxPalette
[idx
*3+0], zxPalette
[idx
*3+1], zxPalette
[idx
*3+2]);
806 Jim_SetResultString(interp
, stbuf
, -1);
807 if (jimapiFromConsole(interp
)) {
808 cprintf("zx palette %d is %s\n", idx
, stbuf
);
811 // try to set new color
813 const char *cc
= Jim_String(argv
[2]);
816 size_t slen
= strlen(cc
);
818 for (unsigned f
= 1; f
< 4; ++f
) {
819 int dig
= digitInBase(cc
[f
], 16);
820 if (dig
< 0) { clr
= 0xffffffffU
; break; }
821 clr
= clr
*256u+((unsigned)dig
)*16+(unsigned)dig
;
823 } else if (slen
== 7) {
824 for (unsigned f
= 1; f
< 7; ++f
) {
825 int dig
= digitInBase(cc
[f
], 16);
826 if (dig
< 0) { clr
= 0xffffffffU
; break; }
827 clr
= clr
*16u+(unsigned)dig
;
835 if (clr
== 0xffffffffU
) {
836 jim_SetResStrf(interp
, "%s: invalid color value %s", Jim_String(argv
[0]), cc
);
839 zxPalette
[idx
*3+0] = (clr
>>16)&0xffU
;
840 zxPalette
[idx
*3+1] = (clr
>>8)&0xffU
;
841 zxPalette
[idx
*3+2] = clr
&0xffU
;
848 // fullscreen [on|off|toggle]
849 JIMAPI_FN(fullscreen
) {
850 int v
= optFullscreen
;
851 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
852 if (v
!= optFullscreen
) {
854 emuFullScreenChanged();
860 // keyhelp [on|off|toggle]
862 return jim_onoff_option(&optKeyHelpVisible
, interp
, argc
, argv
, "on", "off", 1);
866 // allowother128 [on|off|toggle]
867 JIMAPI_FN(allowother128
) {
868 return jim_onoff_option(&optAllowOther128
, interp
, argc
, argv
, "on", "off", 1);
872 // keymatrix [on|off|toggle]
873 JIMAPI_FN(keymatrix
) {
874 return jim_onoff_option(&optEmulateMatrix
, interp
, argc
, argv
, "on", "off", 1);
878 // bad7ffd [on|off|toggle]
880 return jim_onoff_option(&optFDas7FFD
, interp
, argc
, argv
, "on", "off", 1);
884 // ay [on|off|toggle]
886 int prevAY
= optAYEnabled
;
887 int res
= jim_onoff_option(&optAYEnabled
, interp
, argc
, argv
, "on", "off", 1);
888 if (!optAYEnabled
&& prevAY
) emuResetAY();
898 JIMAPI_FN(autofire
) {
899 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
900 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
901 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "hold", "delay", "on", "off", "toggle", "key", NULL
);
902 jimapiStrAppendAbbrev(interp
, res
, a0
);
904 jimapiAppendRestArgs(res
, 2);
905 Jim_SetResult(interp
, res
);
909 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "hold", "delay", "on", "off", "toggle", "key", "query", NULL
);
911 jim_SetResStrf(interp
, "%s: invalid autofire command: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
912 Jim_SetResultBool(interp
, 0);
915 if (strEqu(a0
, "on")) {
919 } else if (strEqu(a0
, "off")) {
921 } else if (strEqu(a0
, "toggle")) {
922 optAutofire
= !optAutofire
;
925 } else if (strEqu(a0
, "hold") || strEqu(a0
, "delay")) {
927 if (argc
< 3 || Jim_GetLong(interp
, argv
[2], &val
) != JIM_OK
) {
928 cprintf("autofire: number expected for '%s'!", a0
);
929 Jim_SetResultBool(interp
, 0);
933 optAutofireHold
= (val
< 1 ? 1 : val
);
935 optAutofireDelay
= (val
< 0 ? 0 : val
);
939 } else if (strEqu(a0
, "key")) {
941 if (argc
!= 3 || (kn
= zxFindKeyByName(Jim_String(argv
[2]))) < 0) {
942 cprintf("autofire: zx key name expected for '%s'!", a0
);
943 Jim_SetResultBool(interp
, 0);
946 afirePortBit
= (zxKeyInfo
[kn
].port
<<8)|zxKeyInfo
[kn
].mask
;
947 } else if (strEqu(a0
, "query")) {
948 int kn
= zxFindKeyByWord(afirePortBit
);
949 cprintf("autofire is %s, hold: %d, delay: %d, key: %s", (optAutofire
? "on" : "off"), optAutofireHold
, optAutofireDelay
, (kn
>= 0 ? zxKeyInfo
[kn
].name
: "unknown"));
951 Jim_SetResultBool(interp
, 1);
956 // usesound [on|off|toggle]
957 JIMAPI_FN(usesound
) {
958 if (sndAllowUseToggle
) {
959 int v
= (sndSampleRate
!= 0);
960 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
961 if (v
!= (sndSampleRate
!= 0)) {
964 if (initSound() == 0) {
965 cprintf("ALSA: %dHz, %d channels, %d bps\n", sndSampleRate
, sndBytesPerSample
, sndChannels
);
967 cprintf("WARNING: can't initialize sound!\n");
976 jim_SetResStrf(interp
, "%s: disabled", Jim_String(argv
[0]));
983 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
984 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
985 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "off", "none", "tv", NULL
);
986 jimapiStrAppendAbbrev(interp
, res
, a0
);
988 jimapiAppendRestArgs(res
, 2);
989 Jim_SetResult(interp
, res
);
994 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "off", "none", "tv", "forcetv", NULL
);
996 if (strEqu(a0
, "tv")) optTVScaler
= 1;
997 else if (strEqu(a0
, "forcetv")) optTVScaler
= 2;
998 else optTVScaler
= 0;
1000 jim_SetResStrf(interp
, "%s: invalid filter: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
1004 jim_SetResStrf(interp
, "%s", (optTVScaler
? "tv" : "off"));
1009 // screenofs [none|0..16|speccy]
1010 JIMAPI_FN(screenofs
) {
1011 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1012 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1013 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "normal", "speccy", NULL
);
1014 jimapiStrAppendAbbrev(interp
, res
, a0
);
1016 jimapiAppendRestArgs(res
, 2);
1017 Jim_SetResult(interp
, res
);
1022 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "none", "normal", "speccy", NULL
);
1024 if (strEqu(a0
, "normal") || strEqu(a0
, "none")) zxScreenOfs
= 0;
1025 else if (strEqu(a0
, "speccy")) zxScreenOfs
= 4;
1029 if (Jim_GetLong(interp
, argv
[1], &val
) != JIM_OK
) {
1030 jim_SetResStrf(interp
, "%s: numeric value expected", Jim_String(argv
[0]));
1033 if (val
< 0 || val
> 16) {
1034 jim_SetResStrf(interp
, "%s: numeric value in range [0..16] expected", Jim_String(argv
[0]));
1041 switch (zxScreenOfs
) {
1042 case 0: Jim_SetResultString(interp
, "normal", -1); break;
1043 case 8: Jim_SetResultString(interp
, "speccy", -1); break;
1044 default: Jim_SetResultInt(interp
, zxScreenOfs
); break;
1050 // colormode [0..4]|normal|monochrome|green
1051 JIMAPI_FN(colormode
) {
1052 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1053 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1054 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""),
1055 "normal", "monochrome", "green", "yellow",
1056 "cyan", "magenta", "red",
1058 jimapiStrAppendAbbrev(interp
, res
, a0
);
1060 jimapiAppendRestArgs(res
, 2);
1061 Jim_SetResult(interp
, res
);
1066 const char *a0
= parseAbbrev(Jim_String(argv
[1]),
1067 "normal", "monochrome", "green", "yellow",
1068 "cyan", "magenta", "red",
1071 if (strEqu(a0
, "normal")) vidColorMode
= 0;
1072 else if (strEqu(a0
, "monochrome")) vidColorMode
= 1;
1073 else if (strEqu(a0
, "green")) vidColorMode
= 2;
1074 else if (strEqu(a0
, "yellow")) vidColorMode
= 3;
1075 else if (strEqu(a0
, "cyan")) vidColorMode
= 4;
1076 else if (strEqu(a0
, "magenta")) vidColorMode
= 5;
1077 else if (strEqu(a0
, "red")) vidColorMode
= 6;
1081 if (Jim_GetLong(interp
, argv
[1], &val
) != JIM_OK
) {
1082 jim_SetResStrf(interp
, "%s: numeric value expected", Jim_String(argv
[0]));
1085 if (val
< 0 || val
> 6+8) {
1086 jim_SetResStrf(interp
, "%s: numeric value in range [0..4] expected", Jim_String(argv
[0]));
1093 switch (vidColorMode
) {
1094 case 0: Jim_SetResultString(interp
, "normal", -1); break;
1095 case 1: Jim_SetResultString(interp
, "monochrome", -1); break;
1096 case 2: Jim_SetResultString(interp
, "green", -1); break;
1097 default: Jim_SetResultInt(interp
, vidColorMode
); break;
1103 // brightborder [0|5|6|7]
1104 JIMAPI_FN(brightborder
) {
1105 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1106 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1107 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "off", NULL
);
1108 jimapiStrAppendAbbrev(interp
, res
, a0
);
1110 jimapiAppendRestArgs(res
, 2);
1111 Jim_SetResult(interp
, res
);
1116 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "off", NULL
);
1118 if (strEqu(a0
, "off")) optBrightBorder
= 0;
1122 if (Jim_GetLong(interp
, argv
[1], &val
) != JIM_OK
) {
1123 jim_SetResStrf(interp
, "%s: numeric value expected", Jim_String(argv
[0]));
1126 if (val
< 5 || val
> 7) {
1127 jim_SetResStrf(interp
, "%s: numeric value in range [5..7] expected", Jim_String(argv
[0]));
1130 optBrightBorder
= val
;
1134 switch (optBrightBorder
) {
1135 case 0: Jim_SetResultString(interp
, "off", -1); break;
1136 default: Jim_SetResultInt(interp
, optBrightBorder
); break;
1142 // sound [off|beeper|ay|on|volume]
1143 // sound volume [ay|beeper] [percents]
1144 // sound ay <mono|acb|abc|on|off|query>
1145 // sound filter <tv|beeper|none>
1150 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1151 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1152 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "on", "off", "ay", "beeper", "volume", "filter", "restart", NULL
);
1153 jimapiStrAppendAbbrev(interp
, res
, a0
);
1154 const char *a5
= parseAbbrev(a0
, "ay", "volume", "filter", NULL
);
1155 if (a5
&& strEqu(a5
, "volume")) {
1158 a0
= completeAbbrev(Jim_String(argv
[2]), "ay", "beeper", NULL
);
1159 jimapiStrAppendAbbrev(interp
, res
, a0
);
1160 jimapiAppendRestArgs(res
, 3);
1162 jimapiAppendRestArgs(res
, 2);
1164 } else if (a5
&& strEqu(a5
, "ay")) {
1166 a0
= completeAbbrev((argc
> 2 ? Jim_String(argv
[2]) : ""), "on", "off", "mono", "acb", "abc", "melodik", "pentagon", "query", NULL
);
1167 jimapiStrAppendAbbrev(interp
, res
, a0
);
1168 jimapiAppendRestArgs(res
, 3);
1169 } else if (a5
&& strEqu(a5
, "filter")) {
1171 a0
= completeAbbrev((argc
> 2 ? Jim_String(argv
[2]) : ""), "tv", "beeper", "none", "query", NULL
);
1172 jimapiStrAppendAbbrev(interp
, res
, a0
);
1173 jimapiAppendRestArgs(res
, 3);
1175 jimapiAppendRestArgs(res
, 2);
1178 Jim_SetResult(interp
, res
);
1183 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "off", "no", "beeper", "ay", "on", "yes", "disabled", "enabled", "volume", "filter", "restart", NULL
);
1185 if (strEqu(a0
, "off") || strEqu(a0
, "ona") || strEqu(a0
, "disabled")) {
1188 } else if (strEqu(a0
, "filter")) {
1190 const char *a3
= parseAbbrev(Jim_String(argv
[2]), "tv", "beeper", "default", "flat", "crisp", "query", NULL
);
1192 if (strEqu(a3
, "tv")) soundSetFilter(SOUND_FILTER_TV
);
1193 else if (strEqu(a3
, "beeper")) soundSetFilter(SOUND_FILTER_BEEPER
);
1194 else if (strEqu(a3
, "none")) soundSetFilter(SOUND_FILTER_DEFAULT
);
1195 else if (strEqu(a3
, "default")) soundSetFilter(SOUND_FILTER_DEFAULT
);
1196 else if (strEqu(a3
, "flat")) soundSetFilter(SOUND_FILTER_FLAT
);
1197 else if (strEqu(a3
, "crisp")) soundSetFilter(SOUND_FILTER_CRISP
);
1200 const char *fltname
;
1201 switch (soundGetFilter()) {
1202 case SOUND_FILTER_TV
: fltname
= "tv"; break;
1203 case SOUND_FILTER_BEEPER
: fltname
= "beeper"; break;
1204 case SOUND_FILTER_DEFAULT
: fltname
= "default"; break;
1205 case SOUND_FILTER_FLAT
: fltname
= "flat"; break;
1206 case SOUND_FILTER_CRISP
: fltname
= "crisp"; break;
1207 default: fltname
= "fucked"; break;
1209 if (jimapiFromConsole(interp
)) cprintf("sound filter: %s\n", fltname
);
1210 jim_SetResStrf(interp
, "%s", fltname
);
1212 } else if (strEqu(a0
, "on") || strEqu(a0
, "tan") || strEqu(a0
, "enabled")) {
1215 } else if (strEqu(a0
, "beeper")) {
1218 } else if (strEqu(a0
, "ay")) {
1220 const char *a3
= parseAbbrev(Jim_String(argv
[2]), "mono", "acb", "abc", "melodik", "pentagon", "query", NULL
);
1222 if (strEqu(a3
, "mono")) soundSetAYStereo(SOUND_STEREO_AY_NONE
);
1223 else if (strEqu(a3
, "acb") || strEqu(a3
, "melodik")) soundSetAYStereo(SOUND_STEREO_AY_ACB
);
1224 else if (strEqu(a3
, "abc") || strEqu(a3
, "pentagon")) soundSetAYStereo(SOUND_STEREO_AY_ABC
);
1226 const char *fltname
;
1227 switch (soundGetAYStereo()) {
1228 case SOUND_STEREO_AY_NONE
: fltname
= "mono"; break;
1229 case SOUND_STEREO_AY_ACB
: fltname
= "acb"; break;
1230 case SOUND_STEREO_AY_ABC
: fltname
= "abc"; break;
1231 default: fltname
= "wutafuck"; break;
1233 if (jimapiFromConsole(interp
)) cprintf("AY mode: %s\n", fltname
);
1234 jim_SetResStrf(interp
, "%s", fltname
);
1239 } else if (strEqu(a0
, "volume")) {
1244 if ((a0
= parseAbbrev(Jim_String(argv
[2]), "beeper", "ay", NULL
)) != NULL
) {
1245 // beeper or ay volume
1247 if (Jim_GetLong(interp
, argv
[3], &val
) != JIM_OK
) {
1248 jim_SetResStrf(interp
, "%s: invalid sound volume: '%s'", Jim_String(argv
[0]), Jim_String(argv
[3]));
1251 if (val
< 0) val
= 0; else if (val
> 500) val
= 500;
1253 if (strEqu(a0
, "beeper")) {
1255 doRestart
= (optSoundVolumeBeeper
!= val
);
1256 optSoundVolumeBeeper
= val
;
1258 jim_SetResStrf(interp
, "%d", optSoundVolumeBeeper
);
1259 } else if (strEqu(a0
, "ay")) {
1261 doRestart
= (optSoundVolumeAY
!= val
);
1262 optSoundVolumeAY
= val
;
1264 jim_SetResStrf(interp
, "%d", optSoundVolumeAY
);
1268 if (Jim_GetLong(interp
, argv
[2], &val
) != JIM_OK
) {
1269 jim_SetResStrf(interp
, "%s: invalid sound volume: '%s'", Jim_String(argv
[0]), Jim_String(argv
[3]));
1272 if (val
< 0) val
= 0; else if (val
> 500) val
= 500;
1273 doRestart
= (optSoundVolume
!= val
);
1274 optSoundVolume
= val
;
1275 jim_SetResStrf(interp
, "%d", optSoundVolume
);
1277 if (doRestart
) soundApplyNewVolumes();
1279 jim_SetResStrf(interp
, "%d", optSoundVolume
);
1281 if (jimapiFromConsole(interp
)) cprintf("sound volume: %d%% (beeper:%d%%; ay:%d%%)\n", optSoundVolume
, optSoundVolumeBeeper
, optSoundVolumeAY
);
1282 } else if (strEqu(a0
, "restart")) {
1283 if (jimapiFromConsole(interp
)) cprintf("restarting sound system...\n");
1285 Jim_SetResultBool(interp
, 1);
1289 jim_SetResStrf(interp
, "%s: invalid sound mode: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
1293 Jim_SetResultBool(interp
, 1);
1296 if (optSoundBeeper
&& optSoundAY
) Jim_SetResultString(interp
, "on", -1);
1297 else if (optSoundBeeper
) Jim_SetResultString(interp
, "beeper", -1);
1298 else if (optSoundAY
) Jim_SetResultString(interp
, "ay", -1);
1299 else Jim_SetResultString(interp
, "off", -1);
1300 //jim_SetResStrf(interp, "%s", (optSoundBeeper ? (optSoundAY ? "on" : "beeper") : (optSoundAY ? "ay" : "off")));
1301 if (argc
> 1 && jimapiFromConsole(interp
)) cprintf("sound: %s\n", Jim_String(Jim_GetResult(interp
)));
1309 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1310 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1311 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "2", "3", NULL
);
1312 jimapiStrAppendAbbrev(interp
, res
, a0
);
1314 jimapiAppendRestArgs(res
, 2);
1315 Jim_SetResult(interp
, res
);
1319 long val
= optZXIssue
+2;
1320 if (argc
< 1 || argc
> 2) { Jim_WrongNumArgs(interp
, 1, argv
, "issue"); return JIM_ERR
; }
1322 if (Jim_GetLong(interp
, argv
[1], &val
) != JIM_OK
) {
1323 jim_SetResStrf(interp
, "%s: issue number expected", Jim_String(argv
[0]));
1326 if (val
< 2 || val
> 3) {
1327 jim_SetResStrf(interp
, "%s: invalid issue number: %d", Jim_String(argv
[0]), (int)val
);
1332 Jim_SetResultInt(interp
, val
);
1337 ////////////////////////////////////////////////////////////////////////////////
1338 // snapshot <load|save|clear|reset> [name]
1339 JIMAPI_FN(snapshot
) {
1340 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1341 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1342 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "load", "save", "clear", "setmodel", NULL
);
1343 jimapiStrAppendAbbrev(interp
, res
, a0
);
1344 const char *a1
= parseAbbrev(a0
, "load", "save", "setmodel", NULL
);
1346 if (strEqu(a1
, "setmodel")) {
1348 a0
= completeAbbrev((argc
> 2 ? Jim_String(argv
[2]) : ""), "yes", "no", "on", "off", "toggle", NULL
);
1349 jimapiStrAppendAbbrev(interp
, res
, a0
);
1350 jimapiAppendRestArgs(res
, 3);
1354 a0
= completeFilesWithExts((argc
> 2 ? Jim_String(argv
[2]) : ""), snapshotExtensions
);
1355 jimapiStrAppendAbbrev(interp
, res
, a0
);
1356 jimapiAppendRestArgs(res
, 3);
1359 jimapiAppendRestArgs(res
, 2);
1362 Jim_SetResult(interp
, res
);
1369 if (argc
< 2) { Jim_WrongNumArgs(interp
, 1, argv
, "action name"); return JIM_ERR
; }
1370 if ((a0
= parseAbbrev(Jim_String(argv
[1]), "load", "save", "clear", "reset", "setmodel", NULL
)) == NULL
) {
1371 jim_SetResStrf(interp
, "%s: invalid action: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
1375 if (strEqu(a0
, "load")) {
1376 if (argc
< 3) { Jim_WrongNumArgs(interp
, 1, argv
, "action name"); return JIM_ERR
; }
1377 res
= (loadSnapshot(Jim_String(argv
[2]), SNAPLOAD_ANY
) == 0);
1378 if (res
) cprintf("'%s' loaded\n", Jim_String(argv
[2])); else cprintf("failed to load '%s'\n", Jim_String(argv
[2]));
1379 } else if (strEqu(a0
, "save")) {
1380 if (argc
< 3) { Jim_WrongNumArgs(interp
, 1, argv
, "action name"); return JIM_ERR
; }
1381 res
= (saveSnapshot(Jim_String(argv
[2])) == 0);
1382 if (res
) cprintf("'%s' saved\n", Jim_String(argv
[2])); else cprintf("failed to save '%s'\n", Jim_String(argv
[2]));
1383 } else if (strEqu(a0
, "setmodel")) {
1384 //int v = optSnapSetModel, res = jim_onoff_option(&v, interp, argc, argv, "on", "off", 1);
1386 if ((a0
= parseAbbrev(Jim_String(argv
[2]), "on", "off", "yes", "no", "toggle", NULL
)) != NULL
) {
1387 if (strEqu(a0
, "on") || strEqu(a0
, "yes")) {
1388 optSnapSetModel
= 1;
1389 } else if (strEqu(a0
, "toggle")) {
1390 optSnapSetModel
= !optSnapSetModel
;
1392 optSnapSetModel
= 0;
1396 //optSnapSetModel = v;
1397 if (jimapiFromConsole(interp
)) cprintf("optSnapSetModel: %d\n", optSnapSetModel
);
1400 if (zxSLT
!= NULL
) { if (jimapiFromConsole(interp
)) cprintf("snapshot cleared\n"); }
1405 Jim_SetResultBool(interp
, res
);
1410 ////////////////////////////////////////////////////////////////////////////////
1413 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1414 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1415 char *a0
= completeAbbrev((argc
> 2 ? Jim_String(argv
[2]) : ""), "stop", NULL
);
1416 jimapiStrAppendAbbrev(interp
, res
, a0
);
1418 jimapiAppendRestArgs(res
, 2);
1419 Jim_SetResult(interp
, res
);
1426 //Jim_WrongNumArgs(interp, 1, argv, "action name");
1428 cprintf("%sRZX is playing now.\n", (zxRZX
!= NULL
? "" : "no "));
1429 Jim_SetResultBool(interp
, 1);
1432 if ((a0
= parseAbbrev(Jim_String(argv
[1]), "stop", NULL
)) == NULL
) {
1433 jim_SetResStrf(interp
, "%s: invalid action: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
1436 if (strEqu(a0
, "stop")) {
1437 if (zxRZX
!= NULL
) cprintf("RZX playback aborted!\n");
1441 Jim_SetResultBool(interp
, res
);
1446 // peek addr [bank-not-yet]
1448 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1449 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1450 jim_completeAddr(interp
, res
, argc
, argv
);
1451 Jim_SetResult(interp
, res
);
1456 if (argc
!= 2) { Jim_WrongNumArgs(interp
, 1, argv
, "addr"); return JIM_ERR
; }
1457 if ((addr
= jim_AddrArg(interp
, argv
[0], argv
[1])) < 0) return JIM_ERR
;
1458 Jim_SetResultInt(interp
, z80
.mem_read(&z80
, addr
, ZYM_MEMIO_OTHER
));
1463 // wpeek addr [bank-not-yet]
1465 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1466 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1467 jim_completeAddr(interp
, res
, argc
, argv
);
1468 Jim_SetResult(interp
, res
);
1474 if (argc
!= 2) { Jim_WrongNumArgs(interp
, 1, argv
, "addr"); return JIM_ERR
; }
1475 if ((addr
= jim_AddrArg(interp
, argv
[0], argv
[1])) < 0) return JIM_ERR
;
1476 res
= z80
.mem_read(&z80
, addr
, ZYM_MEMIO_OTHER
);
1477 res
|= ((uint16_t)z80
.mem_read(&z80
, (addr
+1)&0xffff, ZYM_MEMIO_OTHER
))<<8;
1478 Jim_SetResultInt(interp
, res
);
1485 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1486 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1487 jim_completeAddr(interp
, res
, argc
, argv
);
1488 Jim_SetResult(interp
, res
);
1493 if (argc
!= 3) { Jim_WrongNumArgs(interp
, 1, argv
, "addr"); return JIM_ERR
; }
1494 if ((addr
= jim_AddrArg(interp
, argv
[0], argv
[1])) < 0) return JIM_ERR
;
1495 if ((val
= jim_BWArg(interp
, argv
[0], argv
[2], 1)) < 0) return JIM_ERR
;
1496 z80
.mem_write(&z80
, addr
, val
, ZYM_MEMIO_OTHER
);
1497 Jim_SetResultBool(interp
, 1);
1504 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1505 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1506 jim_completeAddr(interp
, res
, argc
, argv
);
1507 Jim_SetResult(interp
, res
);
1512 if (argc
!= 3) { Jim_WrongNumArgs(interp
, 1, argv
, "addr"); return JIM_ERR
; }
1513 if ((addr
= jim_AddrArg(interp
, argv
[0], argv
[1])) < 0) return JIM_ERR
;
1514 if ((val
= jim_BWArg(interp
, argv
[0], argv
[2], 2)) < 0) return JIM_ERR
;
1515 z80
.mem_write(&z80
, addr
, val
&0xff, ZYM_MEMIO_OTHER
);
1516 z80
.mem_write(&z80
, (addr
+1)&0xffff, (val
>>8)&0xff, ZYM_MEMIO_OTHER
);
1517 Jim_SetResultBool(interp
, 1);
1522 // scrattrfill value
1523 JIMAPI_FN(scrattrfill
) {
1524 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
1527 if (argc
!= 2) { Jim_WrongNumArgs(interp
, 1, argv
, "value"); return JIM_ERR
; }
1528 if ((val
= jim_BWArg(interp
, argv
[0], argv
[1], 1)) < 0) return JIM_ERR
;
1529 for (int f
= 22528; f
< 22528+768; ++f
) z80
.mem_write(&z80
, f
, val
&0xff, ZYM_MEMIO_OTHER
);
1530 Jim_SetResultBool(interp
, 1);
1535 ////////////////////////////////////////////////////////////////////////////////
1536 #include "autotape_128.c"
1537 #include "autotape_48.c"
1538 #include "autotape_p128.c"
1539 #include "autotape_p2a.c"
1540 #include "autotape_p3.c"
1543 static void tape_do_autoload (void) {
1546 case ZX_MACHINE_48K
: fl
= fmemopen((void *)autotape_48
, sizeof(autotape_48
), "rb"); break;
1547 case ZX_MACHINE_128K
:
1548 case ZX_MACHINE_PLUS2
:
1549 fl
= fmemopen((void *)autotape_128
, sizeof(autotape_128
), "rb");
1551 case ZX_MACHINE_PLUS2A
:
1552 fl
= fmemopen((void *)autotape_p2a
, sizeof(autotape_p2a
), "rb");
1554 case ZX_MACHINE_PLUS3
:
1555 fl
= fmemopen((void *)autotape_p3
, sizeof(autotape_p3
), "rb");
1557 case ZX_MACHINE_PENTAGON
: fl
= fmemopen((void *)autotape_p128
, sizeof(autotape_p128
), "rb"); break;
1558 case ZX_MACHINE_SCORPION
: /* nothing */
1568 ////////////////////////////////////////////////////////////////////////////////
1569 // tape cmd [args...]
1571 // save filename (not yet)
1576 // rewind (doesn't stop the tape)
1582 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1583 //fprintf(stderr, "ARGC=%d\n", argc); for (int f = 0; f < argc; ++f) fprintf(stderr, " #%d: <%s>\n", f, Jim_String(argv[f]));
1584 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1586 char *a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "insert", "eject", "clear", "start", "stop", "rewind", "option", NULL
);
1587 jimapiStrAppendAbbrev(interp
, res
, a0
);
1588 const char *a1
= (isFullyCompleted(a0
) ? parseAbbrev(a0
, "insert", "save", "option", NULL
) : NULL
);
1590 // fill/autocomplete command args
1591 if (strEqu(a1
, "insert") || strEqu(a1
, "save")) {
1594 a0
= completeFilesWithExts((argc
> argp
? Jim_String(argv
[argp
++]) : ""), snapshotExtensions
);
1595 jimapiStrAppendAbbrev(interp
, res
, a0
);
1596 } else if (strEqu(a1
, "option")) {
1598 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "maxspeed", "detectloader", "flashload", "sound", "ugly", NULL
);
1599 jimapiStrAppendAbbrev(interp
, res
, a0
);
1600 if (isFullyCompleted(a0
)) {
1601 a1
= parseAbbrev(a0
, "maxspeed", "detectloader", "flashload", "sound", "ugly", NULL
);
1604 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "on", "off", "toggle", NULL
);
1605 jimapiStrAppendAbbrev(interp
, res
, a0
);
1611 jimapiAppendRestArgs(res
, argp
);
1612 Jim_SetResult(interp
, res
);
1619 //Jim_WrongNumArgs(interp, 1, argv, "cmd");
1622 " insert filename\n"
1623 " save filename (not yet)\n"
1628 " rewind (doesn't stop the tape)\n"
1635 if (strEquCI(Jim_String(argv
[1]), "_autoload")) {
1640 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "insert", "eject", "clear", "start", "go", "stop", "rewind", "list", "save", "option", NULL
);
1643 jim_SetResStrf(interp
, "%s: invalid tape command: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
1647 if (strEqu(a0
, "insert")) {
1648 if (argc
< 3) { Jim_WrongNumArgs(interp
, 1, argv
, "name"); return JIM_ERR
; }
1649 if (loadSnapshot(Jim_String(argv
[2]), SNAPLOAD_TAPES
) != 0) {
1650 cprintf("tape: can't insert '%s'\n", Jim_String(argv
[2]));
1653 cprintf("tape: inserted '%s'\n", Jim_String(argv
[2]));
1655 } else if (strEqu(a0
, "eject")) {
1657 cprintf("tape: unloaded\n");
1658 } else if (strEqu(a0
, "clear")) {
1660 cprintf("tape: cleared\n");
1661 } else if (strEqu(a0
, "start") || strEqu(a0
, "go")) {
1663 cprintf("tape: started\n");
1664 } else if (strEqu(a0
, "stop")) {
1666 cprintf("tape: stopped\n");
1667 } else if (strEqu(a0
, "rewind")) {
1669 cprintf("tape: rewound\n");
1670 } else if (strEqu(a0
, "list")) {
1671 cprintf("tape: no listing yet...\n");
1672 } else if (strEqu(a0
, "save")) {
1673 cprintf("tape: no saving yet...\n");
1674 } else if (strEqu(a0
, "option")) {
1679 " maxspeed on/off/toggle\n"
1680 " detectloader on/off/toggle\n"
1681 " autopause on/off/toggle\n"
1682 " sound on/off/toggle\n"
1683 " ugly on/off/toggle\n"
1687 a0
= parseAbbrev(Jim_String(argv
[2]), "maxspeed", "detectloader", "autopause", "flashload", "sound", "ugly", NULL
);
1689 jim_SetResStrf(interp
, "%s: invalid tape option: '%s'", Jim_String(argv
[0]), Jim_String(argv
[2]));
1692 if (strEqu(a0
, "maxspeed")) opt
= &optTapeMaxSpeed
;
1693 else if (strEqu(a0
, "detectloader")) opt
= &optTapeDetector
;
1694 else if (strEqu(a0
, "autopause")) opt
= &optTapeAutoPauseEmu
;
1695 else if (strEqu(a0
, "flashload")) opt
= &optFlashLoad
;
1696 else if (strEqu(a0
, "sound")) opt
= &optTapeSound
;
1697 else if (strEqu(a0
, "ugly")) opt
= &optTapeAllowMaxSpeedUgly
;
1703 if (jim_onoff_option(opt
, interp
, 2, xargv
, "on", "off", 1) != JIM_OK
) {
1704 jim_SetResStrf(interp
, "%s: invalid mode for '%s': '%s'", Jim_String(argv
[0]), a0
, Jim_String(argv
[1]));
1708 cprintf("tape: %s: %s\n", a0
, (*opt
? "on" : "off"));
1712 Jim_SetResultBool(interp
, res
);
1717 ////////////////////////////////////////////////////////////////////////////////
1718 // disk cmd [args...]
1722 // format [il=interleave] [sofs=sector_offset]
1723 // option autoadd_boot
1724 // boot add [name] | remove | replace [name]
1735 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
1736 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
1741 a1
= Jim_String(argv
[argp
]);
1742 if (strlen(a1
) == 2 && a1
[1] == ':' && strchr("abcdABCD", a1
[0]) != NULL
) {
1744 diskno
= tolower(a1
[0])-'a';
1745 jimapiStrAppendSpace(interp
, res
);
1746 jimapiStrAppendCStr(interp
, res
, a1
, -1);
1747 jimapiStrAppendSpace(interp
, res
);
1751 char *a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "insert", "save", "eject", "format", "boot", "option", "protect", "unprotect", "list", "extract", "add", NULL
);
1752 jimapiStrAppendAbbrev(interp
, res
, a0
);
1754 a1
= (isFullyCompleted(a0
) ? parseAbbrev(a0
, "insert", "save", "boot", "option", "extract", "add", "format", NULL
) : NULL
);
1756 // fill/autocomplete command args
1757 if (strEqu(a1
, "boot")) {
1759 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "add", "remove", "replace", NULL
);
1760 jimapiStrAppendAbbrev(interp
, res
, a0
);
1761 if (isFullyCompleted(a0
) && (strEqu(a0
, "add ") || strEqu(a0
, "replace "))) {
1763 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "stealth32", "stealth54", "onesector", "phantom", "kmouse", "ugly", NULL
);
1764 jimapiStrAppendAbbrev(interp
, res
, a0
);
1766 } else if (strEqu(a1
, "option")) {
1768 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "autoadd_boot", "turbo", "traps", NULL
);
1769 jimapiStrAppendAbbrev(interp
, res
, a0
);
1770 if (isFullyCompleted(a0
) && (strEqu(a0
, "autoadd_boot ") || strEqu(a0
, "traps "))) {
1772 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "yes", "no", "on", "off", "toggle", NULL
);
1773 jimapiStrAppendAbbrev(interp
, res
, a0
);
1774 } else if (isFullyCompleted(a0
) && strEqu(a0
, "turbo ")) {
1776 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "yes", "no", "on", "off", "normal", "toggle", NULL
);
1777 jimapiStrAppendAbbrev(interp
, res
, a0
);
1779 } else if (strEqu(a1
, "extract")) {
1781 //fprintf(stderr, "argc=%d; argp=%d; <%s>\n", argc, argp, (argc > argp ? Jim_String(argv[argp]) : ""));
1782 a0
= completeTRDiskFiles((argc
> argp
? Jim_String(argv
[argp
++]) : ""), beta_get_disk(diskno
));
1783 jimapiStrAppendAbbrev(interp
, res
, a0
);
1784 } else if (strEqu(a1
, "format")) {
1786 a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "il=", "sofs=", NULL
);
1787 jimapiStrAppendAbbrev(interp
, res
, a0
);
1788 } else if (strEqu(a1
, "insert") || strEqu(a1
, "save")) {
1791 a0
= completeFilesWithExts((argc
> argp
? Jim_String(argv
[argp
++]) : ""), snapshotExtensions
);
1792 jimapiStrAppendAbbrev(interp
, res
, a0
);
1796 jimapiAppendRestArgs(res
, argp
);
1797 Jim_SetResult(interp
, res
);
1805 a0
= Jim_String(argv
[1]);
1806 if (strlen(a0
) == 2 && a0
[1] == ':' && strchr("abcdABCD", a0
[0]) != 0) {
1808 diskno
= tolower(a0
[0])-'a';
1813 disk_t
*flp
= beta_get_disk(diskno
);
1816 //Jim_WrongNumArgs(interp, 1, argv, "cmd");
1820 if ((a0
= parseAbbrev(Jim_String(argv
[argp
++]), "insert", "eject", "format", "list", "save", "option", "boot", "protect", "unprotect", "list", "extract", "add", NULL
)) == NULL
) {
1821 jim_SetResStrf(interp
, "%s: invalid disk command: '%s'", Jim_String(argv
[0]), Jim_String(argv
[argp
-1]));
1826 if (strEqu(a0
, "insert")) {
1827 if (argp
>= argc
) { Jim_WrongNumArgs(interp
, 1, argv
, "name"); return JIM_ERR
; }
1828 if (loadSnapshot(Jim_String(argv
[argp
]), SNAPLOAD_DISKS
|(diskno
<<SNAPLOAD_FLPNOSHIFT
)) != 0) {
1829 cprintf("disk: can't insert '%s'\n", Jim_String(argv
[argp
]));
1832 cprintf("disk: inserted '%s'\n", Jim_String(argv
[argp
]));
1838 if (strEqu(a0
, "eject")) {
1839 emuDiskEject(diskno
);
1840 cprintf("disk: ejected\n");
1845 if (strEqu(a0
, "format")) {
1846 emuDiskEject(diskno
);
1847 if (emuIsUPD765()) {
1848 int fres
= p3dskFormatDisk(flp
, P3DSK_PCW_SS
);
1850 if (fres
== FLPERR_OK
) {
1851 emuDiskInsert(diskno
);
1852 cprintf("disk: formated +3DOS disk\n");
1854 cprintf("disk: +3DOS formatting error!\n");
1857 int fres
= flpFormatTRD(flp
);
1859 if (fres
== FLPERR_OK
) {
1860 emuDiskInsert(diskno
);
1861 cprintf("disk: formated TR-DOS disk\n");
1863 cprintf("disk: TR-DOS formatting error!\n");
1870 if (strEqu(a0
, "save")) {
1871 if (argp
>= argc
) { Jim_WrongNumArgs(interp
, 1, argv
, "name"); return JIM_ERR
; }
1872 const char *fname
= Jim_String(argv
[argp
++]);
1873 const int wres
= emuSaveDiskToFile(diskno
, fname
);
1874 if (wres
!= DISK_OK
) {
1875 cprintf("\4ERROR: can't save disk to file: '%s' (%s)\n", fname
, disk_strerror(wres
));
1877 cprintf("saved disk to file: '%s'\n", fname
);
1884 if (strEqu(a0
, "boot")) {
1885 if (argp
>= argc
) { Jim_WrongNumArgs(interp
, 1, argv
, "action"); return JIM_ERR
; }
1886 if ((a0
= parseAbbrev(Jim_String(argv
[argp
++]), "add", "remove", "replace", NULL
)) != NULL
) {
1887 if (strEqu(a0
, "add") || strEqu(a0
, "replace")) {
1888 int rep
= (strEqu(a0
, "replace"));
1889 const char *bootname
= (argp
>= argc
? "phantom" : Jim_String(argv
[argp
++]));
1890 a0
= parseAbbrev(bootname
, "stealth32", "stealth54", "onesector", "phantom", "kmouse", "ugly", NULL
);
1892 const uint8_t *b
= NULL
;
1894 if (strEqu(a0
, "stealth32")) { b
= sboot32
; bootsz
= (int)sizeof(sboot32
); }
1895 else if (strEqu(a0
, "stealth54")) { b
= sboot54
; bootsz
= (int)sizeof(sboot54
); }
1896 else if (strEqu(a0
, "onesector")) { b
= bootsmall
; bootsz
= (int)sizeof(bootsmall
); }
1897 else if (strEqu(a0
, "phantom")) { b
= bootph
; bootsz
= (int)sizeof(bootph
); }
1898 else if (strEqu(a0
, "kmouse")) { b
= kmboot
; bootsz
= (int)sizeof(kmboot
); }
1899 else if (strEqu(a0
, "ugly")) { b
= unrealboot
; bootsz
= (int)sizeof(unrealboot
); }
1901 if (flpDetectDiskType(flp
) == FLP_DISK_TYPE_TRDOS
) {
1902 FILE *fl
= fmemopen((void *)b
, bootsz
, "rb");
1903 res
= flpSetBootTRD(flp
, fl
, rep
);
1907 cprintf("disk: boot '%s' added\n", a0
);
1909 cprintf("disk: can't add boot '%s'\n", a0
);
1914 cprintf("disk: not a TR-DOS disk!\n");
1918 cprintf("disk: no disk in drive!\n");
1921 jim_SetResStrf(interp
, "%s: invalid disk boot name: '%s'", Jim_String(argv
[0]), bootname
);
1924 } else if (strEqu(a0
, "remove")) {
1925 if (flpRemoveBootTRD(flp
) == 0) {
1926 cprintf("disk: boot removed\n");
1930 jim_SetResStrf(interp
, "%s: invalid disk boot command: '%s'", Jim_String(argv
[0]), Jim_String(argv
[argp
-1]));
1936 if (strEqu(a0
, "protect")) {
1937 if (upd765_fdc
&& upd765_fdc
->drive
[diskno
]) {
1938 fdd_wrprot(upd765_fdc
->drive
[diskno
], 1);
1940 if (beta_get_fdd(diskno
)) {
1941 fdd_wrprot(beta_get_fdd(diskno
), 1);
1943 cprintf("disk: write-protection set\n");
1948 if (strEqu(a0
, "unprotect")) {
1949 if (upd765_fdc
&& upd765_fdc
->drive
[diskno
]) {
1950 fdd_wrprot(upd765_fdc
->drive
[diskno
], 0);
1952 if (beta_get_fdd(diskno
)) {
1953 fdd_wrprot(beta_get_fdd(diskno
), 0);
1955 cprintf("disk: write-protection reset\n");
1960 if (strEqu(a0
, "option")) {
1961 if (argp
>= argc
) { Jim_WrongNumArgs(interp
, 1, argv
, "option"); return JIM_ERR
; }
1962 if ((a0
= parseAbbrev(Jim_String(argv
[argp
++]), "autoadd_boot", "turbo", "traps", NULL
)) != NULL
) {
1963 if (strEqu(a0
, "autoadd_boot")) {
1965 if ((a0
= parseAbbrev(Jim_String(argv
[argp
++]), "yes", "no", "on", "off", "toggle", NULL
)) != NULL
) {
1966 if (strEqu(a0
, "yes") || strEqu(a0
, "on")) optAutoaddBoot
= 1;
1967 else if (strEqu(a0
, "toggle")) optAutoaddBoot
= !optAutoaddBoot
;
1968 else optAutoaddBoot
= 0;
1970 cprintf("disk: invalid 'autoadd_boot' option argument: '%s'!\n", Jim_String(argv
[argp
]));
1974 if (jimapiFromConsole(interp
)) cprintf("disk autoadd_boot: %s\n", (optAutoaddBoot
? "yes" : "no"));
1975 res
= !!optAutoaddBoot
;
1976 } else if (strEqu(a0
, "turbo")) {
1978 if ((a0
= parseAbbrev(Jim_String(argv
[argp
]), "yes", "no", "on", "off", "normal", "toggle", NULL
)) != NULL
) {
1979 if (strEqu(a0
, "yes") || strEqu(a0
, "on")) {
1980 fdd_turbo
= FDD_TURBO_SUPER
;
1981 } else if (strEqu(a0
, "toggle")) {
1982 fdd_turbo
= (fdd_turbo
? FDD_TURBO_NONE
: FDD_TURBO_SUPER
);
1983 } else if (strEqu(a0
, "normal")) {
1984 fdd_turbo
= FDD_TURBO_TURBO
;
1986 fdd_turbo
= FDD_TURBO_NONE
;
1989 upd_fdc_alloc_fdc_set_clock(upd765_fdc
, (fdd_turbo
? UPD_CLOCK_8MHZ
: UPD_CLOCK_4MHZ
));
1992 cprintf("disk: invalid 'turbo' option argument: '%s'!\n", Jim_String(argv
[argp
]));
1996 res
= (fdd_turbo
!= FDD_TURBO_NONE
);
1997 if (jimapiFromConsole(interp
)) {
1998 cprintf("disk turbo: %s\n", (fdd_turbo
== FDD_TURBO_NONE
? "none" : fdd_turbo
== FDD_TURBO_TURBO
? "normal" : "super"));
2000 } else if (strEqu(a0
, "traps")) {
2002 if ((a0
= parseAbbrev(Jim_String(argv
[argp
]), "yes", "no", "on", "off", "toggle", "debug", "nodebug", NULL
)) != NULL
) {
2003 if (strEqu(a0
, "yes") || strEqu(a0
, "on")) optTRDOSTraps
= 1;
2004 else if (strEqu(a0
, "toggle")) optTRDOSTraps
= !optTRDOSTraps
;
2005 else if (strEqu(a0
, "debug")) optTRDOSTrapDebug
= 1;
2006 else if (strEqu(a0
, "nodebug")) optTRDOSTrapDebug
= 0;
2007 else optTRDOSTraps
= 0;
2009 cprintf("disk: invalid 'traps' option argument: '%s'!\n", Jim_String(argv
[argp
]));
2013 if (jimapiFromConsole(interp
)) cprintf("disk traps: %s\n", (optTRDOSTraps
? "yes" : "no"));
2014 res
= !!optTRDOSTraps
;
2015 //cprintf("\1WARNING: TR-DOS traps are not implemented yet!\n");
2019 cprintf("disk: invalid option: '%s'!\n", Jim_String(argv
[argp
-1]));
2025 if (strEqu(a0
, "list")) {
2027 if (argp
< argc
) wantsizes
= strEquCI(Jim_String(argv
[argp
++]), "size");
2029 FloppyFileInfo
*dir
= anyDiskBuildDir(flp
, &count
);
2030 Jim_Obj
*rlist
= Jim_NewListObj(interp
, NULL
, 0);
2032 if (jimapiFromConsole(interp
)) cprintf("no files\n");
2034 if (jimapiFromConsole(interp
)) cprintf("\2=================\n");
2035 for (int f
= 0; f
< count
; ++f
) {
2036 if (jimapiFromConsole(interp
)) cprintf("\3%-8s%-4s %8u\n", dir
[f
].name
, dir
[f
].ext
, dir
[f
].size
);
2038 char *ss
= strprintf("%s%s", dir
[f
].name
, dir
[f
].ext
);
2039 Jim_Obj
*fnstr
= Jim_NewStringObj(interp
, ss
, -1);
2041 Jim_ListAppendElement(interp
, rlist
, fnstr
);
2043 Jim_Obj
*fnsize
= Jim_NewIntObj(interp
, (jim_wide
)dir
[f
].size
);
2044 Jim_ListAppendElement(interp
, rlist
, fnsize
);
2047 if (conpos >= CON_WIDTH/2) {
2050 while (conpos < CON_WIDTH/2) conPutChar(' ');
2054 //if (conpos != CON_WIDTH) cprintf("\n");
2057 Jim_SetResult(interp
, rlist
);
2062 if (strEqu(a0
, "extract")) {
2063 //cprintf("\4EXTRACTOR IS BROKEN FOR NOW\n");
2064 if (argp
>= argc
) { Jim_WrongNumArgs(interp
, 1, argv
, "name"); return JIM_ERR
; }
2065 const FloppyDiskType dtype
= flpDetectDiskType(flp
);
2066 if (dtype
== FLP_DISK_TYPE_TRDOS
) {
2068 FloppyFileInfo
*dir
= anyDiskBuildDir(flp
, &count
);
2069 for (int f
= 0; f
< count
; ++f
) {
2070 char *fname
= strprintf("%s%s", dir
[f
].name
, dir
[f
].ext
);
2072 for (n
= argp
; n
< argc
; ++n
) {
2073 if (strcasecmp(Jim_String(argv
[n
]), fname
) == 0) break;
2077 for (n
= argp
; n
< argc
; ++n
) {
2078 if (p3dskGlobMatch(fname
, Jim_String(argv
[n
]), P3DSK_GLOB_DEFAULT
)) break;
2083 FILE *fo
= fopen(fname
, "wb");
2085 int wres
= flpSaveHoBeta(flp
, fo
, dir
[f
].index
);
2087 if (wres
!= FLPERR_OK
) {
2089 cprintf("disk: error extracting '%s'!\n", fname
);
2091 cprintf("disk: extracted '%s'!\n", fname
);
2094 cprintf("disk: can't create '%s'!\n", fname
);
2097 // done with this name
2101 } else if (dtype
== FLP_DISK_TYPE_P3DOS
) {
2104 if (p3dskDetectGeom(p3d
.flp
, &p3d
.geom
) == FLPERR_OK
) {
2106 if (p3dskFindInit(&p3d
, &nfo
, "*.*") == FLPERR_OK
) {
2107 while (p3dskFindNext(&nfo
) > 0) {
2110 for (n
= argp
; n
< argc
; ++n
) {
2111 if (strcasecmp(Jim_String(argv
[n
]), nfo
.name
) == 0) break;
2115 for (n
= argp
; n
< argc
; ++n
) {
2116 if (p3dskGlobMatch(nfo
.name
, Jim_String(argv
[n
]), P3DSK_GLOB_DEFAULT
)) break;
2121 FILE *fo
= fopen(nfo
.name
, "wb");
2125 uint8_t *buf
= malloc(nfo
.size
);
2126 rd
= p3dskReadFile(&nfo
, buf
, 0, (int)nfo
.size
);
2128 if (fwrite(buf
, (size_t)rd
, 1, fo
) != 1) rd
= -1;
2135 cprintf("disk: error extracting '%s'!\n", nfo
.name
);
2137 cprintf("disk: extracted '%s'!\n", nfo
.name
);
2140 cprintf("disk: can't create '%s'!\n", nfo
.name
);
2151 Jim_SetResultBool(interp
, res
);
2156 ////////////////////////////////////////////////////////////////////////////////
2157 // fldebug [on|off|toggle]
2158 JIMAPI_FN(fldebug
) {
2159 int v
= optDebugFlashLoad
;
2160 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
2161 optDebugFlashLoad
= v
;
2162 Jim_SetResultBool(interp
, v
);
2167 ////////////////////////////////////////////////////////////////////////////////
2168 // opense [on|off|toggle]
2171 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
2173 Jim_SetResultBool(interp
, v
);
2178 // gluck [on|off|toggle]
2180 int v
= optUseGluck
;
2181 int res
= jim_onoff_option(&v
, interp
, argc
, argv
, "on", "off", 1);
2183 Jim_SetResultBool(interp
, v
);
2189 JIMAPI_FN(kbreset
) {
2191 cprintf("ZX keyboard reset.\n");
2197 JIMAPI_FN(ayreset
) {
2199 cprintf("AY reset.\n");
2205 JIMAPI_FN(curblink
) {
2206 if (jimapiDisableCompletion(interp
, argc
, argv
)) return JIM_OK
;
2207 if (argc
< 1 || argc
> 2) {
2208 jim_SetResStrf(interp
, "%s: expected cursor blink time (only)", Jim_String(argv
[0]));
2213 int idx
= jimGetIntLitVal(interp
, argv
[1]);
2214 if (idx
<= 0) idx
= 0; else if (idx
> 10000) idx
= 10000;
2215 optCurBlinkMS
= idx
;
2218 Jim_SetResultInt(interp
, optCurBlinkMS
);
2223 ////////////////////////////////////////////////////////////////////////////////
2224 // bp [type] cmd [args...]
2225 // types: exec read write in out
2234 uint8_t type
= DBG_BP_EXEC
;
2238 // 0x01u: type; 0x02u: action
2239 unsigned wasctype
= 0;
2241 const char *allcms
[] = { "set", "unset", "toggle", "clear", "xsave", "load", "exec", "read", "write", "in", "out", NULL
};
2242 const char *typecmds
[] = { "exec", "read", "write", "in", "out", NULL
};
2243 const char *actioncmds
[] = { "set", "unset", "toggle", "clear", "xsave", "load", NULL
};
2245 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
2246 const char *bpExtensions
[] = { ".bpx", NULL
};
2248 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
2249 while (argp
< argc
) {
2252 if (wasctype
== 0) ctype
= allcms
;
2253 else if (wasctype
== 1) ctype
= actioncmds
;
2254 else ctype
= typecmds
;
2256 char *a0
= completeAbbrevArray(Jim_String(argv
[argp
]), ctype
, ABBREV_CI
);
2257 if (!isFullyCompleted(a0
)) {
2261 jimapiStrAppendAbbrev(interp
, res
, a0
);
2263 const char *a1
= parseAbbrevArray(a0
, ctype
, ABBREV_CI
, NULL
);
2264 const char cmdch
= a1
[0];
2267 if (cmdch
== 'x' || cmdch
== 'l') needfname
= 1;
2268 else if (cmdch
== 'c') needfname
= -1;
2270 if (strchr("erwio", cmdch
)) wasctype
|= 0x01u
;
2271 else if (strchr("sutcxl", cmdch
)) wasctype
|= 0x02u
;
2276 while (argp
< argc
&& needfname
>= 0) {
2279 a0
= completeFilesWithExts(Jim_String(argv
[argp
++]), bpExtensions
);
2281 a0
= completeLabelName(Jim_String(argv
[argp
++]));
2283 jimapiStrAppendAbbrev(interp
, res
, a0
);
2285 if (needfname
) break;
2288 jimapiAppendRestArgs(res
, argp
);
2289 Jim_SetResult(interp
, res
);
2296 while (argp
< argc
) {
2299 if (wasctype
== 0) ctype
= allcms
;
2300 else if (wasctype
== 1) ctype
= actioncmds
;
2301 else ctype
= typecmds
;
2303 //cprintf("wasctype=%u; argp=%d; argc=%d; <%s>\n", wasctype, argp, argc, Jim_String(argv[argp]));
2305 const char *a0
= parseAbbrevArray(Jim_String(argv
[argp
]), ctype
, ABBREV_CI
, &fullcmd
);
2306 if (!fullcmd
) break;
2308 const char cmdch
= a0
[0];
2309 if (cmdch
== 'x' || cmdch
== 'l') needfname
= 1;
2310 else if (cmdch
== 'c') needfname
= -1;
2311 else if (cmdch
== 'e') { deftype
= 0; type
= DBG_BP_EXEC
; }
2312 else if (cmdch
== 'r') { deftype
= 0; type
= DBG_BP_READ
; }
2313 else if (cmdch
== 'w') { deftype
= 0; type
= DBG_BP_WRITE
; }
2314 else if (cmdch
== 'i') { deftype
= 0; type
= DBG_BP_PORTIN
; }
2315 else if (cmdch
== 'o') { deftype
= 0; type
= DBG_BP_PORTOUT
; }
2317 if (strchr("erwio", cmdch
)) wasctype
|= 0x01u
;
2318 else if (strchr("sutcxl", cmdch
)) { command
= cmdch
; wasctype
|= 0x02u
; }
2324 jim_SetResStrf(interp
, "%s: bp action expected", Jim_String(argv
[0]));
2328 if (needfname
>= 0 && argp
>= argc
) {
2329 jim_SetResStrf(interp
, "%s: bp action argument expected", Jim_String(argv
[0]));
2334 if (command
== 'c') {
2336 if (jimapiFromConsole(interp
)) cprintf("breakpoints cleared\n");
2337 Jim_SetResultBool(interp
, res
);
2341 if (needfname
> 0) {
2343 const char *name
= Jim_String(argv
[argp
]);
2344 if (name
&& name
[0]) {
2346 const char *ext
= strrchr(name
, '.');
2347 if (!ext
|| strcasecmp(ext
, ".bpx") != 0) {
2348 fname
= malloc(strlen(name
)+8);
2349 strcpy(fname
, name
);
2350 strcat(fname
, ".bpx");
2352 fname
= strdup(name
);
2354 if (command
== 'l') {
2356 if (dbgBPLoadFromFile(fname
) == 0) {
2357 cprintf("breakpoints loaded from '%s'\n", fname
);
2359 cprintf("\4ERROR loading breakpoints from '%s'\n", fname
);
2363 if (dbgBPSaveToFile(fname
) == 0) {
2364 cprintf("breakpoints saved to '%s'\n", fname
);
2366 cprintf("\4ERROR saving breakpoints to '%s'\n", fname
);
2371 } else if (needfname
== 0) {
2372 // set, unset, toggle
2373 if (command
== 'u' && deftype
) type
= 0xffu
; /* clear all */
2374 while (argp
< argc
) {
2375 int addr
= jimGetAddrOrLabel(interp
, argv
[argp
]);
2377 cprintf("\x4%s: cannot understand '%s'\n", Jim_String(argv
[0]), Jim_String(argv
[argp
]));
2380 case 's': dbgSetBPType(addr
, dbgGetBPType(addr
)|type
); break;
2381 case 'u': dbgSetBPType(addr
, dbgGetBPType(addr
)&(~type
)); break;
2382 case 't': dbgSetBPType(addr
, dbgGetBPType(addr
)^type
); break;
2384 if (dbgGetBPType(addr
)) {
2385 if (jimapiFromConsole(interp
)) cprintf("changed breakpoint at #%04X (%s)\n", (unsigned)(addr
&0xffffu
), dbgGetBPTypeStr(dbgGetBPType(addr
)));
2387 if (jimapiFromConsole(interp
)) cprintf("cleared breakpoint at #%04X\n", (unsigned)(addr
&0xffffu
));
2394 Jim_SetResultBool(interp
, res
);
2399 ////////////////////////////////////////////////////////////////////////////////
2400 // label cmd [args...]
2403 // goto addr-or-name
2408 const char *commands
[7] = { "set", "del", "goto", "get", "remove", "clear", NULL
};
2410 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
2411 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
2412 jimapiStrAppendSpace(interp
, res
);
2414 char *a0
= completeAbbrevArray((argc
> argp
? Jim_String(argv
[argp
++]) : ""), commands
, ABBREV_CI
);
2415 jimapiStrAppendAbbrev(interp
, res
, a0
);
2416 if (argc
> argp
&& isFullyCompleted(a0
)) {
2417 const char *astr
= parseAbbrevArray(a0
, commands
, ABBREV_CI
, NULL
);
2418 if (astr
&& !strEqu(astr
, "clear")) {
2420 a0
= completeLabelName(Jim_String(argv
[argp
++]));
2421 jimapiStrAppendAbbrev(interp
, res
, a0
);
2425 jimapiAppendRestArgs(res
, argp
);
2426 Jim_SetResult(interp
, res
);
2433 //Jim_WrongNumArgs(interp, 1, argv, "cmd");
2437 if ((a0
= parseAbbrevArray(Jim_String(argv
[argp
++]), commands
, ABBREV_CI
, NULL
)) == NULL
) {
2438 jim_SetResStrf(interp
, "%s: unknown command: '%s'", Jim_String(argv
[0]), Jim_String(argv
[argp
-1]));
2442 if (strEqu(a0
, "clear")) {
2444 if (jimapiFromConsole(interp
)) cprintf("labels cleared\n");
2445 Jim_SetResultBool(interp
, 1);
2450 jim_SetResStrf(interp
, "%s: invalid command: '%s'", Jim_String(argv
[0]), Jim_String(argv
[argp
-1]));
2454 if (a0
[0] == 'd' || a0
[0] == 'r') {
2456 while (argp
< argc
) {
2458 if (Jim_GetLong(interp
, argv
[argp
], &addr
) != JIM_OK
) {
2459 const char *lbl
= Jim_String(argv
[argp
]);
2460 addr
= dbgFindLabelByName(lbl
);
2462 cprintf("\x4%s: cannot understand '%s'\n", Jim_String(argv
[0]), lbl
);
2464 dbgRemoveLabel(lbl
);
2465 if (jimapiFromConsole(interp
)) cprintf("removed label '%s' at #%04X\n", lbl
, (unsigned)(addr
&0xffffu
));
2468 if (addr
< 0 || addr
> 65535) {
2469 cprintf("\x4%s: invalid address %d\n", Jim_String(argv
[0]), (int)addr
);
2471 const char *lbl
= dbgFindLabelByVal(addr
, 0/*asoffset*/);
2473 dbgRemoveLabel(lbl
);
2474 if (jimapiFromConsole(interp
)) cprintf("removed label '%s' at #%04X\n", lbl
, (unsigned)(addr
&0xffffu
));
2480 Jim_SetResultBool(interp
, 1);
2485 // goto label / get label
2487 jim_SetResStrf(interp
, "expects one argument");
2490 int addr
= jimGetAddrOrLabel(interp
, argv
[2]);
2494 cprintf("\4ERROR: no label '%s'!\n", Jim_String(argv
[2]));
2495 Jim_SetResultString(interp
, "", -1);
2498 jim_SetResStrf(interp
, "expects addr or name");
2501 if (a0
[1] != 'e') dbgSetUnasmAddr((uint16_t)(addr
&0xffffu
));
2502 if (jimapiFromConsole(interp
)) cprintf("label '%s' is %d\n", Jim_String(argv
[2]), addr
);
2503 Jim_SetResultInt(interp
, addr
);
2510 jim_SetResStrf(interp
, "expects two args");
2513 const char *lname
= Jim_String(argv
[2]);
2514 int addr
= jimGetAddrOrLabel(interp
, argv
[3]);
2516 jim_SetResStrf(interp
, "expects addr and name");
2519 if (lname
&& lname
[0] && lname
[0] != '#' && lname
[0] != '$' && digitInBase(lname
[0], 10) < 0) {
2520 dbgAddLabel(addr
&0xffffu
, lname
, 0/*asoffset*/);
2521 if (jimapiFromConsole(interp
)) cprintf("set label '%s' at address #%04X\n", lname
, (unsigned)(addr
&0xffffu
));
2523 Jim_SetResultInt(interp
, (unsigned)(addr
&0xffffu
));
2527 Jim_SetResultBool(interp
, 0);
2532 ////////////////////////////////////////////////////////////////////////////////
2533 // reffile <load|save|clear> [name]
2534 // "reference file" (urasm generates those)
2535 JIMAPI_FN(reffile
) {
2536 const char *refExtensions
[] = { ".ref", NULL
};
2539 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
2540 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
2542 char *a0
= completeAbbrev((argc
> argp
? Jim_String(argv
[argp
++]) : ""), "load", "save", "clear", NULL
);
2543 jimapiStrAppendAbbrev(interp
, res
, a0
);
2544 if (isFullyCompleted(a0
)) {
2545 const char *a1
= parseAbbrev(a0
, "load", "save", NULL
);
2549 a0
= completeFilesWithExts((argc
> argp
? Jim_String(argv
[argp
++]) : ""), refExtensions
);
2550 jimapiStrAppendAbbrev(interp
, res
, a0
);
2554 jimapiAppendRestArgs(res
, argp
);
2555 Jim_SetResult(interp
, res
);
2562 if (argc
< 2) { Jim_WrongNumArgs(interp
, 1, argv
, "action name"); return JIM_ERR
; }
2563 if ((a0
= parseAbbrev(Jim_String(argv
[1]), "load", "save", "clear", NULL
)) == NULL
) {
2564 jim_SetResStrf(interp
, "%s: invalid action: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
2568 if (strEqu(a0
, "load")) {
2569 if (argc
< 3) { Jim_WrongNumArgs(interp
, 1, argv
, "file name"); return JIM_ERR
; }
2570 res
= (dbgLoadRefFile(Jim_String(argv
[2])) == 0);
2571 if (res
) cprintf("'%s' loaded\n", Jim_String(argv
[2])); else cprintf("failed to load '%s'\n", Jim_String(argv
[2]));
2572 } else if (strEqu(a0
, "save")) {
2573 if (argc
< 3) { Jim_WrongNumArgs(interp
, 1, argv
, "file name"); return JIM_ERR
; }
2574 res
= (dbgSaveRefFile(Jim_String(argv
[2])) == 0);
2575 if (res
) cprintf("'%s' saved\n", Jim_String(argv
[2])); else cprintf("failed to save '%s'\n", Jim_String(argv
[2]));
2576 } else if (strEqu(a0
, "clear")) {
2578 cprintf("labels cleared\n");
2581 Jim_SetResultBool(interp
, res
);
2586 ////////////////////////////////////////////////////////////////////////////////
2589 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
2590 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
2591 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "force", NULL
);
2592 jimapiStrAppendAbbrev(interp
, res
, a0
);
2594 jimapiAppendRestArgs(res
, 2);
2595 Jim_SetResult(interp
, res
);
2600 jim_SetResStrf(interp
, "%s: wut?!", Jim_String(argv
[0]));
2605 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "force", NULL
);
2607 jim_SetResStrf(interp
, "%s: invalid option: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
2613 if (tsmark_active
) {
2614 cprintf("\4tstate counter is already active!\n");
2615 Jim_SetResultBool(interp
, 0);
2619 tsmark_tstart
= z80
.tstates
;
2620 if (jimapiFromConsole(interp
)) cprintf("\1tstate counter started... (ts=%d)\n", z80
.tstates
);
2621 Jim_SetResultBool(interp
, 1);
2628 ////////////////////////////////////////////////////////////////////////////////
2631 if (jimapiWantsCompletion(interp
, argc
, argv
)) {
2632 Jim_Obj
*res
= Jim_NewStringObj(interp
, Jim_String(argv
[0]), -1);
2633 char *a0
= completeAbbrev((argc
> 1 ? Jim_String(argv
[1]) : ""), "keep", NULL
);
2634 jimapiStrAppendAbbrev(interp
, res
, a0
);
2636 jimapiAppendRestArgs(res
, 2);
2637 Jim_SetResult(interp
, res
);
2642 jim_SetResStrf(interp
, "%s: wut?!", Jim_String(argv
[0]));
2649 const char *a0
= parseAbbrev(Jim_String(argv
[1]), "keep", NULL
);
2651 jim_SetResStrf(interp
, "%s: invalid option: '%s'", Jim_String(argv
[0]), Jim_String(argv
[1]));
2657 if (tsmark_active
) {
2658 if (doreset
) tsmark_active
= 0;
2659 const int tstotal
= (machineInfo
.tsperframe
? machineInfo
.tsperframe
-tsmark_tstart
+(tsmark_frames
-1)*machineInfo
.tsperframe
+z80
.tstates
: z80
.tstates
-tsmark_tstart
);
2660 const int fullfrm
= tstotal
/machineInfo
.tsperframe
;
2661 if (doreset
) { if (jimapiFromConsole(interp
)) cprintf("counter stopped!\n"); }
2662 if (jimapiFromConsole(interp
)) {
2663 cprintf("\1tstate counter: %d\n", tstotal
);
2664 cprintf("\2(%d full frame%s, %d in last frame)\n", fullfrm
, (fullfrm
!= 1 ? "s" : ""), tstotal
-fullfrm
*machineInfo
.tsperframe
);
2666 Jim_SetResultInt(interp
, tstotal
);
2668 cprintf("\4tstate counter is not active!\n");
2669 Jim_SetResultInt(interp
, 0);
2675 ////////////////////////////////////////////////////////////////////////////////
2676 // z80 -- various command to manipulate Z80 CPU from Tcl
2677 // always returns old register value
2678 // getreg <name> -- get register
2679 // setreg <name> <value> -- set register
2680 // this is not a console command (yet), so we don't need any autocompletion here
2682 if (argc
< 3 || argc
> 4) {
2683 jim_SetResStrf(interp
, "%s: wut?!", Jim_String(argv
[0]));
2687 const char *cmd
= Jim_String(argv
[1]);
2688 int cmdread
= (strEquCI(cmd
, "getreg") ? 1 : strEquCI(cmd
, "setreg") ? 0 : -1);
2690 jim_SetResStrf(interp
, "%s: invalid command: '%s'", Jim_String(argv
[0]), cmd
);
2695 void *regptr
= strFindZ80RegPtr(Jim_String(argv
[2]), &bytes
);
2697 jim_SetResStrf(interp
, "%s: invalid register: '%s'", Jim_String(argv
[2]), cmd
);
2701 if (!cmdread
&& argc
!= 4) {
2702 jim_SetResStrf(interp
, "%s: missing value for command: '%s'", Jim_String(argv
[0]), cmd
);
2707 int val
= (bytes
== 2 ? *((uint16_t *)regptr
) : *((uint8_t *)regptr
));
2708 Jim_SetResultInt(interp
, val
);
2712 int newval
= jimGetIntVal(interp
, argv
[3]);
2713 if (newval
== JIM_INVALID_INTVAL
) {
2714 jim_SetResStrf(interp
, "%s: invalid register value: '%s'", Jim_String(argv
[0]), Jim_String(argv
[3]));
2717 if ((bytes
== 2 && (newval
< -32768 || newval
> 65535)) || (bytes
== 1 && (newval
< -128 || newval
> 127))) {
2718 jim_SetResStrf(interp
, "%s: register value out of bounds: '%s'", Jim_String(argv
[0]), Jim_String(argv
[3]));
2721 if (bytes
== 2) *((uint16_t *)regptr
) = newval
&0xffff; else *((uint8_t *)regptr
) = newval
&0xff;
2728 ////////////////////////////////////////////////////////////////////////////////
2729 #include "jimapi_uiovl.c"
2732 ////////////////////////////////////////////////////////////////////////////////
2733 void jimInit (void) {
2734 if ((jim
= Jim_CreateInterp()) == NULL
) { fprintf(stderr
, "FATAL: can't init jim-tcl!\n"); exit(1); }
2735 Jim_SetGlobalVariableStr(jim
, "jim_unsafe_allowed", Jim_NewIntObj(jim
, Jim_GetAllowUnsafeExtensions()));
2736 Jim_RegisterCoreCommands(jim
);
2737 Jim_InitStaticExtensions(jim
);
2739 //Jim_SetVariableStrWithStr(jim, "emudir", binMyDir);
2740 Jim_SetGlobalVariableStr(jim
, "emudir", Jim_NewStringObj(jim
, binMyDir
, -1));
2743 Jim_SetGlobalVariableStr(jim
, "jim_internal", Jim_NewIntObj(jim
, 1));
2745 Jim_SetGlobalVariableStr(jim
, "jim_internal", Jim_NewIntObj(jim
, 0));
2748 // set by Tcl code when it neeeds to autocomplete a console command
2749 Jim_SetGlobalVariableStr(jim
, "con::autocompletion", Jim_NewIntObj(jim
, 0));
2750 // set by Tcl code when it executes a console command (via `conexec`)
2751 Jim_SetGlobalVariableStr(jim
, "con::executing", Jim_NewIntObj(jim
, 0));
2753 JIMAPI_REGISTER(cputs
);
2754 JIMAPI_REGISTER(errputs
);
2755 JIMAPI_REGISTER(load
);
2756 JIMAPI_REGISTER(softload
);
2757 JIMAPI_REGISTER(consetstr
);
2760 jimEvalFile("jimstd/0init.tcl", 0);
2763 JIMAPI_REGISTER(vid_scale
);
2764 JIMAPI_REGISTER(vid_rescaler
);
2766 JIMAPI_REGISTER(quit
);
2767 JIMAPI_REGISTER(zxbind
);
2768 JIMAPI_REGISTER(zxunbind
);
2769 JIMAPI_REGISTER(bind
);
2770 JIMAPI_REGISTER(unbind
);
2772 JIMAPI_REGISTER(reset
);
2773 JIMAPI_REGISTER(model
);
2775 JIMAPI_REGISTER(snow
);
2776 JIMAPI_REGISTER(speed
);
2777 JIMAPI_REGISTER(pause
);
2778 JIMAPI_REGISTER(temppause
);
2779 JIMAPI_REGISTER(timings
);
2780 JIMAPI_REGISTER(console
);
2781 JIMAPI_REGISTER(kbleds
);
2782 JIMAPI_REGISTER(debugger
);
2783 JIMAPI_REGISTER(memview
);
2784 JIMAPI_REGISTER(sprview
);
2785 JIMAPI_REGISTER(screenofs
);
2786 JIMAPI_REGISTER(fullscreen
);
2787 JIMAPI_REGISTER(noflic
);
2788 JIMAPI_REGISTER(brightblack
);
2789 JIMAPI_REGISTER(zxpalcolor
);
2790 JIMAPI_REGISTER(keyhelp
);
2791 JIMAPI_REGISTER(usesound
);
2792 JIMAPI_REGISTER(sound
);
2793 JIMAPI_REGISTER(filter
);
2794 JIMAPI_REGISTER(allowother128
);
2795 JIMAPI_REGISTER(keymatrix
);
2796 JIMAPI_REGISTER(issue
);
2797 JIMAPI_REGISTER(nmi
);
2798 JIMAPI_REGISTER(grab
);
2799 JIMAPI_REGISTER(swapbuttons
);
2800 JIMAPI_REGISTER(maxspeedugly
);
2801 JIMAPI_REGISTER(trdos
);
2802 JIMAPI_REGISTER(fps
);
2803 JIMAPI_REGISTER(kmouse
);
2804 JIMAPI_REGISTER(kspanish
);
2805 JIMAPI_REGISTER(kjoystick
);
2806 JIMAPI_REGISTER(bad7ffd
);
2807 JIMAPI_REGISTER(ay
);
2808 JIMAPI_REGISTER(autofire
);
2809 JIMAPI_REGISTER(genuine
);
2810 JIMAPI_REGISTER(colormode
);
2811 JIMAPI_REGISTER(brightborder
);
2812 JIMAPI_REGISTER(memcontention
);
2813 JIMAPI_REGISTER(iocontention
);
2814 JIMAPI_REGISTER(contention
);
2815 JIMAPI_REGISTER(useplus3
);
2816 JIMAPI_REGISTER(genuine
);
2818 JIMAPI_REGISTER(curblink
);
2820 JIMAPI_REGISTER(rzx
);
2821 JIMAPI_REGISTER(snapshot
);
2822 JIMAPI_REGISTER(tape
);
2823 JIMAPI_REGISTER(disk
);
2825 JIMAPI_REGISTER(peek
);
2826 JIMAPI_REGISTER(wpeek
);
2827 JIMAPI_REGISTER(poke
);
2828 JIMAPI_REGISTER(wpoke
);
2829 JIMAPI_REGISTER(scrattrfill
);
2831 JIMAPI_REGISTER(fldebug
);
2832 JIMAPI_REGISTER(opense
);
2833 JIMAPI_REGISTER(gluck
);
2834 JIMAPI_REGISTER(kbreset
);
2835 JIMAPI_REGISTER(ayreset
);
2837 JIMAPI_REGISTER(bp
);
2838 JIMAPI_REGISTER(label
);
2839 JIMAPI_REGISTER(reffile
);
2841 JIMAPI_REGISTER(tsmark
);
2842 JIMAPI_REGISTER(tsdiff
);
2844 JIMAPI_REGISTER(z80
);
2846 jimRegisterUIOverlayAPI();
2850 void jimDeinit (void) {
2851 sdlClearBindings(jim
, sdlJimBindings
);
2852 sdlJimBindings
= NULL
;
2853 Jim_FreeInterp(jim
);
2857 ////////////////////////////////////////////////////////////////////////////////
2858 int jimEvalFile (const char *fname
, int okifabsent
) {
2859 if (fname
&& fname
[0]) {
2861 if (fname
[0] == '/' || access(fname
, R_OK
) == 0) {
2862 filename
= strdup(fname
);
2864 filename
= strprintf("%s/tcl/%s", binMyDir
, fname
);
2868 if (access(filename
, R_OK
) != 0) {
2874 cprintf("JIM: loading: '%s'\n", filename
);
2875 if (Jim_EvalFile(jim
, filename
) == JIM_OK
) {
2879 Jim_MakeErrorMessage(jim
);
2880 cprintf("\4JIM ERROR: %s\n", Jim_GetString(Jim_GetResult(jim
), NULL
));
2889 int jimEvalFile1 (const char *fname
) {
2890 if (fname
!= NULL
&& fname
[0] && access(fname
, R_OK
) == 0) {
2891 cprintf("JIM: loading: '%s'\n", fname
);
2892 if (Jim_EvalFile(jim
, fname
) == JIM_OK
) return 0;
2893 Jim_MakeErrorMessage(jim
);
2894 cprintf("\4JIM ERROR: %s\n", Jim_GetString(Jim_GetResult(jim
), NULL
));
2900 ////////////////////////////////////////////////////////////////////////////////
2901 void emuInitBindings (void) {
2902 jimEvalFile("init/zxbind.tcl", 0);
2903 jimEvalFile("init/bind.tcl", 0);