36 #define DEBUGMATRIX(...)
51 #define MATRIX(...) do { \
52 char _buf_for_msg_[4096]; \
53 CHECK_SNPRINTF(snprintf(_buf_for_msg_, sizeof _buf_for_msg_, __VA_ARGS__), sizeof _buf_for_msg_); \
54 matrix_write_string(_buf_for_msg_); \
57 #define CURSOR_CHAR 0xDB
58 #define CURSOR_COLOUR 4
59 #define CLI_START_LINE 4
60 #define NORMAL_COLOUR 1
61 #define BANNER_COLOUR 2
63 static const Uint8 console_colours[] = {
64 0x00, 0x00, 0x00, 0x80,
65 0x00, 0xFF, 0x00, 0xFF,
66 0xFF, 0xFF, 0x00, 0xFF,
67 0x00, 0x00, 0x00, 0x00,
68 0xFF, 0x00, 0x00, 0xFF
70 static Uint32 colour_mappings[16];
71 static Uint8 current_colour;
73 static int backend_xsize, backend_ysize;
74 static Uint32 *backend_pixels;
75 static int chrscreen_xsize, chrscreen_ysize;
77 static int current_x = 0, current_y = 0;
78 static const char *prompt = NULL;
79 static int need_update = 0;
80 static int reserve_top_lines = 0;
81 static int init_done = 0;
82 static Uint8 queued_input;
85 #define PARTIAL_OSD_TEXTURE_UPDATE
88 static void matrix_update (
void )
95 #ifdef PARTIAL_OSD_TEXTURE_UPDATE
96 int region = 0, x_min[2] = { 1000, 1000 }, y_min[2] = { 1000, 1000 }, x_max[2] = { -1, -1 }, y_max[2] = { -1, -1 };
98 for (
int y = 0;
y < chrscreen_ysize;
y++) {
99 #ifdef PARTIAL_OSD_TEXTURE_UPDATE
103 for (
int x = 0;
x < chrscreen_xsize;
x++, vp += 2)
104 if (need_update || (vp[1] & 0x80)) {
108 Uint32 *pix = backend_pixels + (
y * 8) * backend_xsize + (
x * 8);
109 for (
int line = 0; line < 8; line++, font++, pix += backend_xsize - 8)
111 *pix++ = colour_mappings[(vp[1] >> ((
data & 0x80) ? 0 : 4)) & 0xF];
112 #ifdef PARTIAL_OSD_TEXTURE_UPDATE
113 if (
x < x_min[region]) x_min[region] =
x;
114 if (
x > x_max[region]) x_max[region] =
x;
115 if (
y < y_min[region]) y_min[region] =
y;
116 if (
y > y_max[region]) y_max[region] =
y;
122 #ifdef PARTIAL_OSD_TEXTURE_UPDATE
124 for (
int i = 0; i < 2; i++)
126 const SDL_Rect rect = {
129 .w = (x_max[i] - x_min[i] + 1) * 8,
130 .h = (y_max[i] - y_min[i] + 1) * 8
132 DEBUGMATRIX(
"MATRIX: update rectangle region #%d is %dx%d character wide at %d,%d" NL, i, x_max[i] - x_min[i] + 1, y_max[i] - y_min[i] + 1, x_min[i], y_min[i]);
133 DEBUGMATRIX(
"MATRIX: update rectangle region #%d in pixels is %dx%d pixels at %d,%d" NL, i, rect.w, rect.h, rect.x, rect.y);
135 area += rect.w * rect.h / 64;
138 int area = chrscreen_xsize * chrscreen_ysize;
141 DEBUGMATRIX(
"MATRIX: updated %d characters, %d OSD chars (=%.03f%%)" NL, updated, area, (
double)(area * 100) / (
double)(chrscreen_xsize * chrscreen_ysize));
146 static void write_char_raw (
const int x,
const int y,
const Uint8 ch,
const Uint8 col )
148 if (
XEMU_UNLIKELY(
x < 0 || y < 0 || x >= chrscreen_xsize ||
y >= chrscreen_ysize))
152 v[0] = ch, v[1] = col | 0x80;
159 static void matrix_clear (
void )
161 for (
Uint8 *vp =
vmem, *ve =
vmem + chrscreen_xsize * chrscreen_ysize * 2; vp < ve; vp += 2)
162 vp[0] = 0x20, vp[1] = current_colour;
167 static void matrix_write_char (
const Uint8 c )
169 if (c ==
'\n' || c ==
'\r') {
176 write_char_raw(current_x, current_y, c, current_colour);
178 if (current_x >= chrscreen_xsize) {
183 if (current_y >= chrscreen_ysize) {
184 current_y = chrscreen_ysize - 1;
185 DEBUGMATRIX(
"MATRIX: scrolling ... reserved=%d lines" NL, reserve_top_lines);
187 vmem + 2 * chrscreen_xsize * reserve_top_lines,
188 vmem + 2 * chrscreen_xsize * (reserve_top_lines + 1),
189 chrscreen_xsize * (chrscreen_ysize - 1 - reserve_top_lines) * 2
191 for (
Uint8 x = 0, *vp =
vmem + (chrscreen_ysize - 1) * chrscreen_xsize * 2;
x < chrscreen_xsize;
x++, vp += 2)
192 vp[0] = 0x20, vp[1] = current_colour;
198 static inline void matrix_write_string (
const char *s )
201 matrix_write_char(*s++);
205 static void dump_regs (
const char rot_fig )
207 static const Uint8 io_mode_xlat[4] = { 2, 3, 0, 4 };
209 MATRIX(
"PC:%04X A:%02X X:%02X Y:%02X Z:%02X SP:%04X B:%02X %c%c%c%c%c%c%c%c IO:%d (%c) %c %s %s ",
210 cpu65.pc, cpu65.a, cpu65.x, cpu65.y, cpu65.z,
211 cpu65.sphi + cpu65.s, cpu65.bphi >> 8,
232 static void cmd_off (
char *p )
238 static void cmd_uname (
char *p )
244 static void cmd_ver (
char *p )
250 static void cmd_reg (
char *p )
256 static Uint16 addr_hiword = 0, addr_loword = 0;
257 static Uint8 data_byte;
260 static int mem_args (
const char *p,
int need_data )
263 int ret = sscanf((*p ==
'!' || *p ==
'?' || *p ==
'=') ? p + 1 : p,
"%x %x", &
addr , &
data);
265 matrix_write_string(
"?MISSING ARG OR HEX SYNTAX ERROR");
268 if (need_data && ret == 1) {
269 matrix_write_string(
"?MISSING SECOND ARG OR HEX SYNTAX ERROR");
272 if (!need_data && ret > 1) {
273 matrix_write_string(
"?EXTRA UNKNOWN ARG");
279 matrix_write_string(
"?CPU ADDRESS MUST BE 16-BIT");
282 addr_hiword = 0xFFFF;
283 }
else if (
addr > 0xFFFF || *p ==
'=') {
284 if (
addr >= 0xFFFFFFFU) {
285 matrix_write_string(
"?LINEAR ADDRESS MUST BE 28-BIT");
288 addr_hiword = (
addr >> 16) & 0xFFF;
290 addr_loword =
addr & 0xFFFF;
293 matrix_write_string(
"?IO ADDRESS MUST BE 12-BIT");
297 addr_loword = (addr_loword & 0xFFF) + 0x3000;
303 matrix_write_string(
"?DATA ARG MUST BE 8-BIT");
306 data_byte =
data & 0xFF;
313 static void cmd_log (
char *p )
319 static void cmd_write (
char *p )
321 if (mem_args(p, 1) != 2)
323 if (addr_hiword == 0xFFFF) {
332 static void cmd_show (
char *p )
334 if (mem_args(p, 0) != 1)
336 if (addr_hiword == 0xFFFF) {
345 static void cmd_dump (
char *p )
347 if (*p && mem_args(p, 0) != 1)
350 memset(chardump, 0,
sizeof chardump);
351 for (
int lines = 0; lines < 16; lines++) {
352 if (addr_hiword != 0xFFFF) {
354 addr_hiword &= 0xFFF;
355 sprintf(chardump + 1,
"%03X:%04X", addr_hiword, addr_loword);
357 sprintf(chardump + 1,
"cpu:%04X", addr_loword);
358 for (
int i = 0; i < 16; i++) {
360 if (addr_hiword == 0xFFFF)
368 sprintf(chardump + 12 + i * 3,
"%02X",
data);
369 chardump[61 + i] =
data >= 32 ?
data :
'.';
371 for (
int i = 0; i <
sizeof(chardump) - 2; i++)
374 chardump[
sizeof(chardump) - 2] =
'\n';
375 matrix_write_string(chardump);
380 static void cmd_help (
char *p );
383 static const struct command_tab_st {
386 const char *shortnames;
388 {
"dump", cmd_dump,
"d" },
389 {
"exit", cmd_off,
"x" },
390 {
"help", cmd_help,
"h?" },
391 {
"log", cmd_log, NULL },
392 {
"reg", cmd_reg,
"r" },
393 {
"show", cmd_show,
"s" },
394 {
"uname", cmd_uname, NULL },
395 {
"ver", cmd_ver, NULL },
396 {
"write", cmd_write,
"w" },
401 static void cmd_help (
char *p )
403 matrix_write_string(
"Available commands:");
404 for (
const struct command_tab_st *p = command_tab; p->cmdname; p++) {
405 MATRIX(
" %s", p->cmdname);
407 MATRIX(
"(%s)", p->shortnames);
412 static void execute (
char *cmd )
414 char *sp = strchr(cmd,
' ');
419 const int sname = !cmd[1] ? tolower(*cmd) : 1;
420 for (
const struct command_tab_st *p = command_tab; p->cmdname; p++)
421 if ((p->shortnames && strchr(p->shortnames, sname)) || !strcasecmp(p->cmdname, cmd)) {
425 MATRIX(
"?SYNTAX ERROR IN \"%s\"", cmd);
429 static void input (
const char c )
432 static Uint8 prev_char;
434 matrix_write_string(prompt && *prompt ? prompt :
"Xemu>");
440 if (current_x < chrscreen_xsize - 1 && (c >= 33 || (c == 32 && current_x > start_x && prev_char != 32))) {
441 matrix_write_char(c);
443 }
else if (current_x > start_x && c == 8) {
444 static const char backspace_seq_str[] = { 8, 32, 8, 0 };
445 matrix_write_string(backspace_seq_str);
446 }
else if (c ==
'\r' || c ==
'\n') {
447 const int len = current_x - start_x;
449 for (
int i = 0, j = (current_y * chrscreen_xsize + start_x) << 1; i < len; i++, j += 2)
451 cmd[len - (prev_char == 32)] = 0;
452 matrix_write_char(
'\n');
456 matrix_write_char(
'\n');
463 static void matrix_updater_callback (
void )
467 write_char_raw(current_x, current_y,
' ', current_colour);
468 const int saved_x = current_x, saved_y = current_y;
471 static const char rotator[4] = {
'-',
'\\',
'|',
'/' };
472 static Uint32 counter = 0;
473 dump_regs(rotator[(counter >> 3) & 3]);
477 DEBUGMATRIX(
"MATRIX-INPUT: [%c] (%d)" NL, queued_input >= 32 ? queued_input :
' ', queued_input);
480 }
else if (current_x == 0)
495 static int kbd_cb_keyevent ( SDL_KeyboardEvent *ev )
497 if (ev->state == SDL_PRESSED && ev->keysym.sym > 0 && ev->keysym.sym < 32 && !queued_input) {
500 if (ev->keysym.sym == 9 && (ev->keysym.mod & KMOD_RALT))
503 queued_input = ev->keysym.sym;
509 static int kbd_cb_textevent ( SDL_TextInputEvent *ev )
511 const uint8_t c = ev->text[0];
512 if (c >= 32 && c < 128 && !queued_input)
524 static int saved_allow_mouse_grab;
527 osd_hijack(matrix_updater_callback, &backend_xsize, &backend_ysize, &backend_pixels);
530 for (
int i = 0; i <
sizeof(console_colours) / 4; i++)
531 colour_mappings[i] = SDL_MapRGBA(
sdl_pix_fmt, console_colours[i * 4], console_colours[i * 4 + 1], console_colours[i * 4 + 2], console_colours[i * 4 + 3]);
532 chrscreen_xsize = backend_xsize / 8;
533 chrscreen_ysize = backend_ysize / 8;
538 static const char banner_msg[] =
"*** Xemu's pre-matrix ... press right-ALT + TAB to exit ***";
539 current_x = (chrscreen_xsize - strlen(banner_msg)) >> 1;
540 matrix_write_string(banner_msg);
545 matrix_write_string(
"INFO: Remember, there is no spoon.\nINFO: Hot-keys do not work in matrix mode!\nINFO: Matrix mode bypasses emulation keyboard mappings.\n");
549 DEBUGPRINT(
"MATRIX: ON (%dx%d OSD texture pixels, %dx%d character resolution)" NL,
550 backend_xsize, backend_ysize, chrscreen_xsize, chrscreen_ysize
560 matrix_write_string(
"WARN: mouse grab/emu is released for matrix mode\n");