Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
emu_monitor.c
Go to the documentation of this file.
1 /* Xep128: Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Copyright (C)2015-2019 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3  http://xep128.lgb.hu/
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 #define XEP128_NEED_SDL_WMINFO
20 
21 #include "xep128.h"
22 #include "emu_monitor.h"
23 #include "xemu/../rom/ep128/xep_rom_syms.h"
24 #include "xemu/z80_dasm.h"
25 #include "cpu.h"
26 #include "z180.h"
27 #include "configuration.h"
28 #include "emu_rom_interface.h"
29 #include "fileio.h"
30 #include "screen.h"
31 #include "console.h"
32 #include "nick.h"
33 #include "input.h"
34 #include "primoemu.h"
35 #include "dave.h"
36 #include "sdext.h"
37 
38 #include "main.h"
39 
40 #include <SDL.h>
41 #include <SDL_syswm.h>
42 
43 #ifdef _WIN32
44 #include <sysinfoapi.h>
45 #endif
46 
47 #include <dirent.h>
48 #include <sys/stat.h>
49 #include <unistd.h>
50 
51 
52 
53 
54 struct commands_st {
55  const char *name;
56  const char *alias;
57  const int allowed;
58  const char *help;
59  void (*handler)(void);
60 };
61 
62 static const char SHORT_HELP[] = "XEP version " VERSION " (Xep128 EMU)\n";
63 static const char TOO_LONG_OUTPUT_BUFFER[] = " ...%s*** Too long output%s";
64 static const char *_dave_ws_descrs[4] = {
65  "all", "M1", "no", "no"
66 };
67 
68 static volatile int is_queued_command = 0;
69 static char queued_command[256];
70 
71 static char input_buffer[256];
72 static char *input_p;
73 static char *output_p;
74 static char *output_limit;
75 static const char *output_nl;
76 
77 static Uint16 dump_addr1 = 0;
78 static Uint8 dump_addr2 = 0;
79 static int dump_pagerel = 0;
80 static Uint16 disasm_addr1 = 0;
81 static Uint8 disasm_addr2 = 0;
82 static int disasm_pagerel = 0;
83 
84 
85 
86 #define MPRINTF(...) do { \
87  char __mprintf__buffer__[0x4000]; \
88  snprintf(__mprintf__buffer__, sizeof __mprintf__buffer__, __VA_ARGS__); \
89  __mprintf_append_helper(__mprintf__buffer__); \
90 } while(0)
91 
92 #define ARG_ONE 33
93 #define ARG_SPACE 32
94 
95 
96 
97 static void __mprintf_append_helper ( char *s )
98 {
99  while (*s) {
100  if (output_p >= output_limit) {
101  sprintf(output_limit - strlen(TOO_LONG_OUTPUT_BUFFER), TOO_LONG_OUTPUT_BUFFER, output_nl, output_nl);
102  output_p = NULL;
103  return;
104  } else if (!output_p)
105  return;
106  if (*s == '\n') {
107  const char *n = output_nl;
108  while (*n)
109  *(output_p++) = *(n++);
110  s++;
111  } else
112  *(output_p++) = *(s++);
113  }
114  *output_p = '\0';
115 }
116 
117 
118 // Use ARG_ONE to return one parameter, or ARG_SPACE (can contain space(s) but not eg TAB)
119 static char *get_mon_arg ( int limitrangecode )
120 {
121  char *r;
122  while (*input_p && *input_p <= 32)
123  input_p++;
124  if (!*input_p)
125  return NULL; // no argument left
126  r = input_p; // remember position of first printable character ...
127  while (*input_p >= limitrangecode)
128  input_p++;
129  if (*input_p)
130  *(input_p++) = '\0'; // terminate argument
131  return r;
132 }
133 
134 
135 
136 static int get_mon_arg_hex ( int *hex1, int *hex2 )
137 {
138  char *h = get_mon_arg(ARG_ONE);
139  *hex1 = *hex2 = -1;
140  if (h == NULL)
141  return 0;
142  return sscanf(h, "%x:%x", hex1, hex2);
143 }
144 
145 
146 
147 static void cmd_testargs ( void ) {
148  int h1, h2, r;
149  r = get_mon_arg_hex(&h1, &h2);
150  MPRINTF("Tried to parse first arg as hex, result: r=%d, h1=%x, h2=%x\n",
151  r, h1, h2
152  );
153  for (;;) {
154  char *p = get_mon_arg(ARG_ONE);
155  if (!p) {
156  MPRINTF("No more args found!\n");
157  break;
158  }
159  MPRINTF("Another arg found: \"%s\"\n", p);
160  }
161 }
162 
163 
164 #define SEGMENT_OF_Z80_ADDR(n) ports[0xB0 | (((n) & 0xFFFF) >> 14)]
165 
166 
167 static void set_memaddr_by_arg ( Uint16 *da1, Uint8 *da2, int *dm )
168 {
169  int h1, h2;
170  get_mon_arg_hex(&h1, &h2);
171  if (h1 >= 0)
172  *da1 = h1;
173  if (h2 >= 0) {
174  *dm = 0;
175  *da2 = h2;
176  MPRINTF("; Absolute addresses from %04X:%02X\n", *da1, *da2);
177  } else if (h1 >= 0) {
178  MPRINTF("; CPU paging relative from %04X\n", *da1);
179  *dm = 1;
180  }
181  if (*dm)
182  *da2 = SEGMENT_OF_Z80_ADDR(*da1);
183 }
184 
185 
186 
187 static void cmd_memdump ( void )
188 {
189  int row;
190  set_memaddr_by_arg(&dump_addr1, &dump_addr2, &dump_pagerel);
191  for (row = 0; row < 10; row++) {
192  int col;
193  char asciibuf[17];
194  MPRINTF("%04X:%c%02X ",
195  dump_addr1,
196  dump_pagerel ? '*' : '=',
197  dump_addr2
198  );
199  for (col = 0; col < 16; col++) {
200  Uint8 byte = memory[(dump_addr2 << 14) | (dump_addr1 & 0x3FFF)];
201  asciibuf[col] = (byte >= 32 && byte < 127) ? byte : '.';
202  MPRINTF(" %02X", byte);
203  dump_addr1++;
204  if (!(dump_addr1 & 0x3FFF)) {
205  if (dump_pagerel)
206  dump_addr2 = SEGMENT_OF_Z80_ADDR(dump_addr1);
207  else
208  dump_addr2++;
209  }
210  }
211  asciibuf[col] = 0;
212  MPRINTF(" %s\n", asciibuf);
213  }
214 }
215 
216 
217 
218 static Z80EX_BYTE byte_reader ( Z80EX_WORD addr ) {
219  if (disasm_pagerel)
220  return memory[(SEGMENT_OF_Z80_ADDR(addr) << 14) | (addr & 0x3FFF)];
221  else
222  //return memory[((int)user_data + addr - disasm_addr1) & 0x3FFFFF];
223  return memory[((disasm_addr2 << 14) + (disasm_addr1 & 0x3FFF) + (addr - disasm_addr1)) & 0x3FFFFF];
224 }
225 
226 
227 
228 static void cmd_disasm ( void )
229 {
230  int lines;
231  set_memaddr_by_arg(&disasm_addr1, &disasm_addr2, &disasm_pagerel);
232  for (lines = 0; lines < 10; lines++) {
233  char dasm_out_buffer[128];
234  char hex_out_buffer[32];
235  char asc_out_buffer[16];
236  int t_states, t_states2, r, h;
237  //int disasm_base = (disasm_addr2 << 14) | (disasm_addr1 & 0x3FFF);
238  char *p;
239  r = z80ex_dasm(dasm_out_buffer, sizeof dasm_out_buffer, 0, &t_states, &t_states2, byte_reader, disasm_addr1);
240  if (byte_reader(disasm_addr1) == 0xF7) { // the EXOS call hack!
241  h = byte_reader(disasm_addr1 + 1);
242  r = 2;
243  snprintf(dasm_out_buffer, sizeof dasm_out_buffer, "EXOS $%02X", h);
244  }
245  for (h = 0, hex_out_buffer[0] = 0, asc_out_buffer[0] = '\''; h < r; h++) {
246  Uint8 byte = byte_reader(disasm_addr1 + h);
247  sprintf(hex_out_buffer + h * 3, "%02X ", byte);
248  asc_out_buffer[h + 1] = (byte >= 32 && byte < 127) ? byte : '.';
249  asc_out_buffer[h + 2] = '\0';
250  }
251  strcat(asc_out_buffer, "'");
252  p = strchr(dasm_out_buffer, ' ');
253  if (p)
254  *(p++) = '\0';
255  MPRINTF("%04X:%c%02X %-12s%-4s %-16s ; %-6s L=%d T=%d/%d\n",
256  disasm_addr1,
257  disasm_pagerel ? '*' : '=',
258  disasm_addr2,
259  hex_out_buffer,
260  dasm_out_buffer,
261  p ? p : "",
262  asc_out_buffer,
263  r, t_states, t_states2
264  );
265  if (disasm_addr1 >> 14 != ((disasm_addr1 + r) >> 14)) {
266  if (disasm_pagerel)
267  disasm_addr2 = SEGMENT_OF_Z80_ADDR(disasm_addr1 + r);
268  else
269  disasm_addr2++;
270  }
271  disasm_addr1 += r;
272  }
273 }
274 
275 
276 
277 static void cmd_registers ( void ) {
278  MPRINTF(
279  "AF =%04X BC =%04X DE =%04X HL =%04X IX=%04X IY=%04X F=%c%c%c%c%c%c%c%c IM=%d IFF=%d,%d\n"
280  "AF'=%04X BC'=%04X DE'=%04X HL'=%04X PC=%04X SP=%04X Prefix=%02X P=%02X,%02X,%02X,%02X\n",
282  (Z80_F & 0x80) ? 'S' : 's',
283  (Z80_F & 0x40) ? 'Z' : 'z',
284  (Z80_F & 0x20) ? '1' : '0',
285  (Z80_F & 0x10) ? 'H' : 'h',
286  (Z80_F & 0x08) ? '1' : '0',
287  (Z80_F & 0x04) ? 'V' : 'v',
288  (Z80_F & 0x02) ? 'N' : 'n',
289  (Z80_F & 0x01) ? 'C' : 'c',
290  Z80_IM, Z80_IFF1 ? 1 : 0, Z80_IFF2 ? 1 : 0,
292  z80ex.prefix,
293  ports[0xB0], ports[0xB1], ports[0xB2], ports[0xB3]
294  );
295 
296 }
297 
298 
299 
300 static void cmd_setdate ( void ) {
301  char buffer[64];
302  xep_set_time_consts(buffer);
303  MPRINTF("EXOS time set: %s\n", buffer);
304 }
305 
306 
307 
308 static void cmd_ddn ( void ) {
309  char *arg = get_mon_arg(ARG_ONE);
310  if (arg) {
312  } else
313  MPRINTF("Command needs an argument, the default device name to be set\n");
314 }
315 
316 
317 
318 static void cmd_ram ( void ) {
319  char *arg = get_mon_arg(ARG_ONE);
320  int r = arg ? *arg : 0;
321  switch (r) {
322  case 0:
323  MPRINTF("%s\nDave: WS=%s CLK=%dMHz P=%02X/%02X/%02X/%02X\n\n",
324  mem_desc,
325  _dave_ws_descrs[(ports[0xBF] >> 2) & 3],
326  ports[0xBF] & 1 ? 12 : 8,
327  ports[0xB0], ports[0xB1], ports[0xB2], ports[0xB3]
328  );
329  break;
330  case '!':
331  INFO_WINDOW("Setting total sum of RAM size to %dKbytes\nEP will reboot now!\nYou can use :XEP EMU command then to check the result.", ep_set_ram_config(arg + 1) << 4);
332  ep_reset();
333  return;
334  default:
335  MPRINTF(
336  "*** Bad command syntax.\nUse no parameter to query or !128 to set 128K memory, "
337  "or even !@E0,E3-E5 (no spaces ever!) to specify given RAM segments. Using '!' is "
338  "only for safity not to re-configure or re-boot your EP with no intent. Not so "
339  "much error handling is done on the input!\n"
340  );
341  break;
342  }
343 }
344 
345 
346 
347 static void cmd_cpu ( void ) {
348  //char buf[512] = "";
349  char *arg = get_mon_arg(ARG_ONE);
350  if (arg) {
351  if (!strcasecmp(arg, "z80"))
353  else if (!strcasecmp(arg, "z80c"))
355 #ifdef CONFIG_Z180
356  else if (!strcasecmp(arg, "z180")) {
358  // Zozo's EXOS would set this up, but our on-the-fly change is something can't happen for real, thus we fake it here:
359  z180_port_write(0x32, 0x00);
360  z180_port_write(0x3F, 0x40);
361  }
362 #endif
363  else {
364  int clk = atof(arg) * 1000000;
365  if (clk < 1000000 || clk > 12000000)
366  MPRINTF("*** Unknown CPU type to set or it's not a clock value either (1-12 is OK in MHz): %s\n", arg);
367  else {
368  INFO_WINDOW("Setting CPU clock to %.2fMhz",
369  set_cpu_clock(clk) / 1000000.0
370  );
371  }
372  }
373  }
374  MPRINTF("CPU : %s %s @ %.2fMHz\n",
375 #ifdef CONFIG_Z180
376  z80ex.z180 ? "Z180" : "Z80",
377 #else
378  "Z80",
379 #endif
380  z80ex.nmos ? "NMOS" : "CMOS",
381  CPU_CLOCK / 1000000.0
382  );
383 }
384 
385 
386 
387 static void cmd_emu ( void )
388 {
389  char buf[1024];
390 #ifdef _WIN32
391 
392  DWORD siz = sizeof buf;
393 #endif
394  //SDL_VERSION(&sdlver_c);
395  //SDL_GetVersion(&sdlver_l);
396 #ifdef _WIN32
397  //GetUserName(buf, &siz);
398  GetComputerNameEx(ComputerNamePhysicalNetBIOS, buf, &siz);
399 #define OS_KIND "Win32"
400 #else
401  gethostname(buf, sizeof buf);
402 #define OS_KIND "POSIX"
403 #endif
404  MPRINTF(
405  "Run by: %s@%s %s %s\n"
406  "Drivers: %s %s\n"
407  "SDL c/l: %d.%d.%d %d.%d.%d\n"
408  "Base path: %s\nPref path: %s\nStart dir: %s\nSD img: %s [%dM]\n",
409 #ifdef _WIN32
410  getenv("USERNAME"),
411 #else
412  getenv("USER"),
413 #endif
414  buf, OS_KIND, SDL_GetPlatform(), SDL_GetCurrentVideoDriver(), SDL_GetCurrentAudioDriver(),
415  sdlver_compiled.major, sdlver_compiled.minor, sdlver_compiled.patch,
416  sdlver_linked.major, sdlver_linked.minor, sdlver_linked.patch,
419  sdimg_path, (int)(sd_card_size >> 20)
420 #else
421  "<not-supported>", 0
422 #endif
423  );
424 #ifdef __EMSCRIPTEN__
425  // This assumes, that the "JS booter" sets these ENV variables ...
426  MPRINTF("Browser: %s\n", getenv("XEMU_EN_BROWSER"));
427  MPRINTF("Origin: %s\n", getenv("XEMU_EN_ORIGIN"));
428 #endif
429 }
430 
431 
432 
433 static void cmd_exit ( void )
434 {
435  INFO_WINDOW("XEP ROM/monitor command directs shutting down.");
436  XEMUEXIT(0);
437 }
438 
439 
440 
441 static void cmd_mouse ( void )
442 {
443  char *arg = get_mon_arg(ARG_ONE);
444  int c = arg ? *arg : 0;
445  char buffer[256];
446  switch (c) {
447  case '1': case '2': case '3': case '4': case '5': case '6':
448  mouse_setup(c - '0');
449  break;
450  case '\0':
451  break;
452  default:
453  MPRINTF("*** Give values 1 ... 6 for mode, or no parameter for query.\n");
454  return;
455  }
456  mouse_mode_description(0, buffer);
457  MPRINTF("%s\n", buffer);
458 }
459 
460 
461 
462 static void cmd_audio ( void )
463 {
464  audio_init(1); // NOTE: later it shouldn't be here!
465  audio_start();
466 }
467 
468 
469 
470 static void cmd_primo ( void )
471 {
472  if (primo_rom_seg == -1) {
473  MPRINTF("*** Primo ROM not found in the loaded ROM set.\n");
474  return;
475  }
477 }
478 
479 
480 
481 static void cmd_showkeys ( void )
482 {
483  show_keys = !show_keys;
484  MPRINTF("SDL show keys info has been turned %s.\n", show_keys ? "ON" : "OFF");
485 }
486 
487 
488 static void cmd_close ( void )
489 {
491 }
492 
493 
494 static void cmd_romname ( void )
495 {
496  MPRINTF("%s", SHORT_HELP);
497 }
498 
499 
500 static void cmd_exos ( void )
501 {
502  if (exos_version == 0)
503  MPRINTF("*** XEP ROM was not called yet\n");
504  else {
505  char status_line[41];
506  exos_get_status_line(status_line);
507  MPRINTF("EXOS version: %d.%d\nStatus line: %s\n", exos_version >> 4, exos_version & 0xF, status_line);
508  MPRINTF("Working/non-working RAM segs: %d / %d\n", exos_info[5], exos_info[6]);
509  }
510 }
511 
512 
513 static void cmd_lpt ( void )
514 {
515  char *p = nick_dump_lpt("\n");
516  __mprintf_append_helper(p);
517  free(p);
518 }
519 
520 
521 static void cmd_pause ( void )
522 {
523  paused = !paused;
524  OSD("Emulation %s", paused ? "paused" : "resumed");
525 }
526 
527 
528 static void cmd_sdl ( void )
529 {
530  SDL_RendererInfo info;
531  SDL_Renderer *rendererp;
532  SDL_DisplayMode display;
533  const char *subsystem;
534  int a;
535  MPRINTF("Available SDL renderers:\n");
536  for (a = 0; a < SDL_GetNumRenderDrivers(); a++ ) {
537  int r = SDL_GetRenderDriverInfo(a, &info);
538  if (r)
539  MPRINTF(" (%d) *** CANNOT QUERY ***\n", a);
540  else
541  MPRINTF(" (%d) \"%s\"\n", a, info.name);
542  }
543  rendererp = SDL_GetRenderer(sdl_win);
544  if (rendererp && !SDL_GetRendererInfo(rendererp, &info))
545  MPRINTF(" used: \"%s\"\n", info.name);
546  MPRINTF("Available SDL video drivers:");
547  for (a = 0; a < SDL_GetNumVideoDrivers(); a++ )
548  MPRINTF(" (%d)%s", a, SDL_GetVideoDriver(a) ? SDL_GetVideoDriver(a) : "*** CANNOT QUERY ***");
549  MPRINTF("\n used: \"%s\"\n", SDL_GetCurrentVideoDriver());
550  MPRINTF("Available SDL audio drivers:");
551  for (a = 0; a < SDL_GetNumAudioDrivers(); a++ )
552  MPRINTF(" (%d)%s", a, SDL_GetAudioDriver(a) ? SDL_GetAudioDriver(a) : "*** CANNOT QUERY ***");
553  MPRINTF("\n used: \"%s\"\n", SDL_GetCurrentAudioDriver());
554  for (a = 0; a < SDL_GetNumDisplayModes(0); a++ )
555  if (!SDL_GetCurrentDisplayMode(a, &display))
556  MPRINTF("Display #%d %dx%dpx @ %dHz %i bpp (%s)\n", a, display.w, display.h, display.refresh_rate,
557  SDL_BITSPERPIXEL(display.format), SDL_GetPixelFormatName(display.format)
558  );
559  switch (sdl_wminfo.subsystem) {
560  default:
561  case SDL_SYSWM_UNKNOWN:
562  subsystem = "Unknown System";
563  break;
564  case SDL_SYSWM_WINDOWS: subsystem = "Microsoft Windows(TM)"; break;
565  case SDL_SYSWM_X11: subsystem = "X Window System"; break;
566  case SDL_SYSWM_WINRT: subsystem = "WinRT"; break;
567  case SDL_SYSWM_DIRECTFB:subsystem = "DirectFB"; break;
568  case SDL_SYSWM_COCOA: subsystem = "Apple OS X"; break;
569  case SDL_SYSWM_UIKIT: subsystem = "UIKit"; break;
570  case SDL_SYSWM_WAYLAND: subsystem = "Wayland"; break;
571  case SDL_SYSWM_MIR: subsystem = "Mir"; break;
572  case SDL_SYSWM_ANDROID: subsystem = "Android"; break;
573  }
574  MPRINTF(WINDOW_TITLE " is running with SDL version %d.%d.%d on %s (id=%d)\n",
575  (int)sdl_wminfo.version.major,
576  (int)sdl_wminfo.version.minor,
577  (int)sdl_wminfo.version.patch,
578  subsystem,
579  sdl_wminfo.subsystem
580  );
581 }
582 
583 
584 
585 static void cmd_ports ( void )
586 {
587  int a;
588  MPRINTF(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
589  for (a = 0; a < 0x100; a++) {
590  if (!(a & 15))
591  MPRINTF("\n%02X -", a);
592  MPRINTF(" %02X", ports[a]);
593  }
594  MPRINTF("\n");
595 }
596 
597 
598 
599 static void cmd_cd ( void )
600 {
601  int r_cd = 0;
602  char *arg = get_mon_arg(ARG_SPACE);
603  if (arg) {
604  char cwd_old[PATH_MAX + 1];
605  char *r_scwd = getcwd(cwd_old, PATH_MAX); // Save working directory
606  int r;
607  if (chdir(fileio_cwd)) // set old FILE: dir
608  r = chdir(DIRSEP);
609  r_cd = chdir(arg); // do the CD - maybe relative - to the old one
610  if (!r_cd) {
611  if (getcwd(fileio_cwd, PATH_MAX)) { // store result directory as new FILE: dir
612  if (fileio_cwd[strlen(fileio_cwd) - 1] != DIRSEP[0])
613  strcat(fileio_cwd, DIRSEP);
614  }
615  }
616  if (!r_scwd)
617  r = chdir(cwd_old); // restore current working directory
618  (void)r; // make GCC happy, we DO NOT need value of r, and some retvals, sorry!!
619  }
620  if (r_cd)
621  MPRINTF("*** Cannot change directory to %s\n", arg);
622  else if (!arg)
623  MPRINTF("%s\n", fileio_cwd);
624 }
625 
626 
627 
628 static void cmd_dir ( void )
629 {
630  struct dirent *entry;
631  DIR *dir;
632  if (get_mon_arg(ARG_ONE)) {
633  MPRINTF("*** DIR command does not have parameter\n");
634  return;
635  }
636  dir = opendir(fileio_cwd);
637  if (!dir) {
638  MPRINTF("*** Cannot open host OS directory: %s\n", fileio_cwd);
639  return;
640  }
641  MPRINTF("Directory of %s\n", fileio_cwd);
642  while ((entry = readdir(dir))) {
643  char fn[PATH_MAX + 1];
644  struct stat st;
645  if (entry->d_name[0] == '.')
646  continue;
647  if (CHECK_SNPRINTF(snprintf(fn, sizeof fn, "%s%s%s", fileio_cwd, DIRSEP, entry->d_name), sizeof fn))
648  continue;
649  if (!stat(fn, &st)) {
650  char size_info[10];
651  if (S_ISDIR(st.st_mode))
652  strcpy(size_info, "<dir>");
653  else if (st.st_size < 65536)
654  snprintf(size_info, sizeof size_info, "%d", (int)st.st_size);
655  else
656  size_info[0] = 0;
657  if (size_info[0])
658  MPRINTF("%-12s %6s\n", entry->d_name, size_info);
659  }
660  }
661  closedir(dir);
662 }
663 
664 
665 
666 static void cmd_help ( void );
667 
668 static const struct commands_st commands[] = {
669  { "AUDIO", "", 3, "Tries to turn crude audio emulation", cmd_audio },
670  { "CD", "", 3, "Host OS directory change/query for FILE:", cmd_cd },
671  { "CLOSE", "", 3, "Close console/monitor window", cmd_close },
672  { "CPU", "", 3, "Set/query CPU type/clock", cmd_cpu },
673  { "DDN", "", 1, "Set default device name via EXOS 19", cmd_ddn },
674  { "DIR", "", 3, "Directory listing from host OS for FILE:", cmd_dir },
675  { "DISASM", "D", 3, "Disassembly memory", cmd_disasm },
676  { "EMU", "", 3, "Emulation info", cmd_emu },
677  { "EXIT", "", 3, "Exit Xep128", cmd_exit },
678  { "EXOS", "", 3, "EXOS information", cmd_exos },
679  { "HELP", "?", 3, "Guess, what ;-)", cmd_help },
680  { "LPT", "", 3, "Shows LPT (can be long!)", cmd_lpt },
681  { "MEMDUMP", "M", 3, "Memory dump", cmd_memdump },
682  { "MOUSE", "", 3, "Configure or query mouse mode", cmd_mouse },
683  { "PAUSE", "", 2, "Pause/resume emulation", cmd_pause },
684  { "PORTS", "", 3, "I/O port values (written)", cmd_ports },
685  { "PRIMO", "", 3, "Primo emulation", cmd_primo },
686  { "RAM", "", 3, "Set RAM size/report", cmd_ram },
687  { "REGS", "R", 3, "Show Z80 registers", cmd_registers },
688  { "ROMNAME", "", 3, "ROM id string", cmd_romname },
689  { "SDL", "", 3, "Get SDL related info", cmd_sdl },
690  { "SETDATE", "", 1, "Set EXOS time/date by emulator" , cmd_setdate },
691  { "SHOWKEYS", "", 3, "Show/hide PC/SDL key symbols", cmd_showkeys },
692  { "TESTARGS", "", 3, "Just for testing monitor statement parsing, not so useful for others", cmd_testargs },
693  { NULL, NULL, 0, NULL, NULL }
694 };
695 static const char help_for_all_desc[] = "\nFor help on all comamnds: (:XEP) HELP\n";
696 
697 
698 
699 static void cmd_help ( void ) {
700  const struct commands_st *cmds = commands;
701  char *arg = get_mon_arg(ARG_ONE);
702  if (arg) {
703  while (cmds->name) {
704  if ((!strcasecmp(arg, cmds->name) || !strcasecmp(arg, cmds->alias)) && cmds->help) {
705  MPRINTF("%s: [%s] %s%s",
706  cmds->name,
707  cmds->alias[0] ? cmds->alias : "-",
708  cmds->help,
709  help_for_all_desc
710  );
711  return;
712  }
713  cmds++;
714  }
715  MPRINTF("*** No help/command found '%s'%s", arg, help_for_all_desc);
716  } else {
717  MPRINTF("Helper ROM: %s%s %s %s\nBuilt on: %s\n%s\nGIT: %s\nCompiler: %s %s\n\nCommands:",
718  SHORT_HELP, WINDOW_TITLE, VERSION, COPYRIGHT,
720  );
721  while (cmds->name) {
722  if (cmds->help)
723  MPRINTF(" %s%s%s%s", cmds->name,
724  cmds->alias[0] ? "[" : "",
725  cmds->alias,
726  cmds->alias[0] ? "]" : ""
727  );
728  cmds++;
729  }
730  MPRINTF("\n\nFor help on a command: (:XEP) HELP CMD\n");
731  }
732 }
733 
734 
735 
736 void monitor_execute ( char *in_input_buffer, int in_source, char *in_output_buffer, int in_output_max_size, const char *in_output_nl )
737 {
738  char *cmd_name;
739  const struct commands_st *cmds = commands;
740  /* initialize output parameters for the answer */
741  output_p = in_output_buffer;
742  *output_p = '\0';
743  output_limit = output_p + in_output_max_size;
744  output_nl = in_output_nl;
745  /* input pre-stuffs */
746  strcpy(input_buffer, in_input_buffer);
747  input_p = input_buffer;
748  /* OK, now it's time to do something ... */
749  cmd_name = get_mon_arg(ARG_ONE);
750  if (!cmd_name) {
751  if (in_source == 1)
752  MPRINTF("*** Use: XEP HELP\n");
753  return; // empty command line
754  }
755  while (cmds->name) {
756  if (!strcasecmp(cmds->name, cmd_name) || !strcasecmp(cmds->alias, cmd_name)) {
757  if (cmds->allowed & in_source)
758  return (void)(cmds->handler)();
759  else {
760  MPRINTF("*** Command cannot be used here: %s\n", cmd_name);
761  return;
762  }
763  }
764  cmds++;
765  }
766  MPRINTF("*** Unknown command: %s\n", cmd_name);
767 }
768 
769 
770 
771 /* this should be called by the emulator (main thread) regularly, to check console/monitor events queued by the console/monitor thread */
773 {
774  if (is_queued_command) {
775  char buffer[8192];
776  monitor_execute(queued_command, 2, buffer, sizeof buffer, NL);
777 #ifdef __EMSCRIPTEN__
778  EM_ASM_INT({
779  Module.Xemu.getFromMonitor(Pointer_stringify($0));
780  }, buffer);
781 #else
782  printf("%s", buffer); // TODO, maybe we should ask for sync on stdout?
783 #endif
784  is_queued_command = 0;
785  }
786 }
787 
788 
789 /* for use by the console input thread */
790 int monitor_queue_used ( void )
791 {
792  return is_queued_command;
793 }
794 
795 
796 /* for use by the console input thread */
797 int monitor_queue_command ( char *buffer )
798 {
799  if (XEMU_UNLIKELY(is_queued_command))
800  return 1;
801  is_queued_command = 1;
802  strcpy(queued_command, buffer);
803  return 0;
804 }
805 
z80_dasm.h
COPYRIGHT
#define COPYRIGHT
Definition: xep128.h:52
Z80_DE
#define Z80_DE
Definition: z80ex.h:85
Z80_AF
#define Z80_AF
Definition: z80ex.h:77
Z80_AF_
#define Z80_AF_
Definition: z80ex.h:93
ep_reset
void ep_reset(void)
Definition: cpu.c:621
xep_set_time_consts
void xep_set_time_consts(char *descbuffer)
Definition: emu_rom_interface.c:75
_z80_cpu_context::nmos
int nmos
Definition: z80ex.h:175
commands_st
Definition: emu_monitor.c:50
CC_TYPE
#define CC_TYPE
Definition: emutools_basicdefs.h:104
sdl_win
SDL_Window * sdl_win
Definition: screen.c:43
ARG_SPACE
#define ARG_SPACE
Definition: emu_monitor.c:93
Z80_SP
#define Z80_SP
Definition: z80ex.h:117
console.h
screen.h
MPRINTF
#define MPRINTF(...)
Definition: emu_monitor.c:86
Z80_HL_
#define Z80_HL_
Definition: z80ex.h:105
monitor_queue_used
int monitor_queue_used(void)
Definition: emu_monitor.c:784
Z80_HL
#define Z80_HL
Definition: z80ex.h:89
set_ep_cpu
void set_ep_cpu(int type)
Definition: cpu.c:74
mouse_mode_description
int mouse_mode_description(int cfg, char *buffer)
Definition: input_devices.c:231
INFO_WINDOW
#define INFO_WINDOW(...)
Definition: xep128.h:114
addr
int addr
Definition: dma65.c:81
monitor_process_queued
void monitor_process_queued(void)
Definition: emu_monitor.c:766
fn
const char * fn
Definition: roms.c:42
app_pref_path
char * app_pref_path
Definition: configuration.c:84
XEMU_BUILDINFO_GIT
const char XEMU_BUILDINFO_GIT[]
Definition: emutools_basicdefs.h:251
Z80_IY
#define Z80_IY
Definition: z80ex.h:113
dave.h
CONFIG_Z180
#define CONFIG_Z180
Definition: xemu-target.h:3
Z80EX_WORD
unsigned short Z80EX_WORD
Definition: z80ex.h:51
mem_desc
char * mem_desc
Definition: cpu.c:58
paused
int paused
Definition: enterprise128.c:53
sdext.h
Z80_IFF1
#define Z80_IFF1
Definition: z80ex.h:127
Uint8
uint8_t Uint8
Definition: fat32.c:51
exos_get_status_line
void exos_get_status_line(char *buffer)
Definition: emu_rom_interface.c:54
set_cpu_clock
int set_cpu_clock(int hz)
Definition: enterprise128.c:91
emu_rom_interface.h
cpu.h
exos_version
Uint8 exos_version
Definition: emu_rom_interface.c:45
Z80_IFF2
#define Z80_IFF2
Definition: z80ex.h:128
XEMU_BUILDINFO_CC
const char XEMU_BUILDINFO_CC[]
Definition: emutools_basicdefs.h:251
CPU_Z180
#define CPU_Z180
Definition: cpu.h:26
primo_rom_seg
int primo_rom_seg
Definition: primoemu.c:32
xep_set_default_device_name
void xep_set_default_device_name(const char *name)
Definition: emu_rom_interface.c:95
OS_KIND
#define OS_KIND
DIRSEP
#define DIRSEP
Definition: xep128.h:27
CPU_Z80
#define CPU_Z80
Definition: cpu.h:24
CONFIG_SDEXT_SUPPORT
#define CONFIG_SDEXT_SUPPORT
Definition: xemu-target.h:11
dir
DIR * dir
Definition: cpmfs.c:46
sdlver_linked
SDL_version sdlver_linked
Definition: configuration.c:86
Z80EX_BYTE
unsigned char Z80EX_BYTE
Definition: z80ex.h:49
SEGMENT_OF_Z80_ADDR
#define SEGMENT_OF_Z80_ADDR(n)
Definition: emu_monitor.c:164
sdlver_compiled
SDL_version sdlver_compiled
Definition: configuration.c:86
CPU_Z80C
#define CPU_Z80C
Definition: cpu.h:25
Z80_BC_
#define Z80_BC_
Definition: z80ex.h:97
nick_dump_lpt
char * nick_dump_lpt(const char *newline_seq)
Definition: nick.c:507
monitor_execute
void monitor_execute(char *in_input_buffer, int in_source, char *in_output_buffer, int in_output_max_size, const char *in_output_nl)
Definition: emu_monitor.c:730
Z80_F
#define Z80_F
Definition: z80ex.h:76
NL
#define NL
Definition: fat32.c:37
compress_sd_image.r
def r
Definition: compress_sd_image.py:76
audio_init
void audio_init(int enable)
Definition: dave.c:153
memory
Uint8 memory[0x100000]
Definition: commodore_65.c:43
sdl_wminfo
SDL_SysWMinfo sdl_wminfo
Definition: screen.c:44
audio_start
void audio_start(void)
Definition: dave.c:123
_z80_cpu_context::prefix
Z80EX_BYTE prefix
Definition: z80ex.h:163
XEMUEXIT
#define XEMUEXIT(n)
Definition: emutools_basicdefs.h:246
primo_emulator_execute
void primo_emulator_execute(void)
Definition: primoemu.c:211
Z80_IM
#define Z80_IM
Definition: z80ex.h:129
console_close_window
void console_close_window(void)
Definition: console.c:189
xep128.h
Z80_DE_
#define Z80_DE_
Definition: z80ex.h:101
Z80_BC
#define Z80_BC
Definition: z80ex.h:81
Z80_IX
#define Z80_IX
Definition: z80ex.h:109
main.h
Z80_PC
#define Z80_PC
Definition: z80ex.h:121
CPU_CLOCK
#define CPU_CLOCK
Definition: tvc.h:30
commands_st::name
const char * name
Definition: emu_monitor.c:51
show_keys
int show_keys
Definition: input_devices.c:39
monitor_queue_command
int monitor_queue_command(char *buffer)
Definition: emu_monitor.c:791
OSD
#define OSD(...)
Definition: xep128.h:100
XEMU_BUILDINFO_ON
const char XEMU_BUILDINFO_ON[]
ARG_ONE
#define ARG_ONE
Definition: emu_monitor.c:92
configuration.h
z180.h
Uint16
uint16_t Uint16
Definition: fat32.c:50
commands_st::handler
void(* handler)(void)
Definition: emu_monitor.c:55
fileio.h
z80ex_dasm
int z80ex_dasm(char *output, int output_size, unsigned flags, int *t_states, int *t_states2, z80ex_dasm_readbyte_cb readbyte_cb, Z80EX_WORD addr)
Definition: z80ex_dasm.c:42
z80ex
Z80EX_CONTEXT z80ex
Definition: primo.c:37
XEMU_BUILDINFO_AT
const char XEMU_BUILDINFO_AT[]
Definition: emutools_basicdefs.h:251
primoemu.h
app_base_path
char * app_base_path
Definition: configuration.c:84
WINDOW_TITLE
#define WINDOW_TITLE
Definition: xep128.h:50
current_directory
char current_directory[PATH_MAX+1]
Definition: configuration.c:85
ep_set_ram_config
int ep_set_ram_config(const char *spec)
Definition: cpu.c:131
commands_st::alias
const char * alias
Definition: emu_monitor.c:52
VERSION
#define VERSION
Definition: xep128.h:51
emu_monitor.h
sdimg_path
char sdimg_path[PATH_MAX+1]
input.h
commands_st::help
const char * help
Definition: emu_monitor.c:54
XEMU_UNLIKELY
#define XEMU_UNLIKELY(__x__)
Definition: emutools_basicdefs.h:125
commands_st::allowed
const int allowed
Definition: emu_monitor.c:53
exos_info
Uint8 exos_info[8]
Definition: emu_rom_interface.c:46
mouse_setup
int mouse_setup(int cfg)
Definition: input_devices.c:500
nick.h
buf
Uint8 buf[512]
Definition: fat32.c:155
st
struct stat st
Definition: cpmfs.c:43
fileio_cwd
char fileio_cwd[PATH_MAX+1]
Definition: fileio.c:44