2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
10 #if !defined(_MSC_VER)
16 #include "vm/device.h"
17 #include "vm/debugger.h"
24 #ifndef FOREGROUND_BLUE
25 #define FOREGROUND_BLUE 0x0001 // text color contains blue.
27 #ifndef FOREGROUND_GREEN
28 #define FOREGROUND_GREEN 0x0002 // text color contains green.
30 #ifndef FOREGROUND_RED
31 #define FOREGROUND_RED 0x0004 // text color contains red.
33 #ifndef FOREGROUND_INTENSITY
34 #define FOREGROUND_INTENSITY 0x0008 // text color is intensified.
37 static FILEIO* logfile = NULL;
38 static FILEIO* cmdfile = NULL;
40 void my_printf(OSD *osd, const _TCHAR *format, ...)
46 my_vstprintf_s(buffer, 1024, format, ap);
49 if(logfile != NULL && logfile->IsOpened()) {
50 logfile->Fwrite(buffer, _tcslen(buffer) * sizeof(_TCHAR), 1);
52 osd->write_console(buffer, _tcslen(buffer));
55 void my_putch(OSD *osd, _TCHAR c)
57 if(logfile != NULL && logfile->IsOpened()) {
58 logfile->Fwrite(&c, sizeof(_TCHAR), 1);
60 osd->write_console(&c, 1);
63 uint32_t my_hexatoi(DEVICE *target, const _TCHAR *str)
66 symbol_t *first_symbol = NULL;
68 if(str == NULL || _tcslen(str) == 0) {
71 my_tcscpy_s(tmp, 1024, str);
74 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
76 first_symbol = debugger->first_symbol;
79 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
80 if(_tcsicmp(symbol->name, str) == 0) {
84 if(_tcslen(tmp) == 3 && tmp[0] == _T('\'') && tmp[2] == _T('\'')) {
87 } else if((s = _tcsstr(tmp, _T(":"))) != NULL) {
90 return (my_hexatoi(target, tmp) << 4) + my_hexatoi(target, s + 1);
91 } else if(tmp[0] == _T('%')) {
93 #if defined(__MINGW32__)
96 return _tstoi(tmp + 1);
99 return _tcstoul(tmp, NULL, 16);
102 uint8_t my_hexatob(char *value)
108 return (uint8_t)strtoul(tmp, NULL, 16);
111 uint16_t my_hexatow(char *value)
119 return (uint16_t)strtoul(tmp, NULL, 16);
122 const _TCHAR *my_get_symbol(DEVICE *target, uint32_t addr)
124 symbol_t *first_symbol = NULL;
127 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
129 first_symbol = debugger->first_symbol;
132 return get_symbol(first_symbol, addr);
135 const _TCHAR *my_get_value_or_symbol(DEVICE *target, const _TCHAR *format, uint32_t addr)
137 symbol_t *first_symbol = NULL;
140 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
142 first_symbol = debugger->first_symbol;
145 return get_value_or_symbol(first_symbol, format, addr);
148 const _TCHAR *my_get_value_and_symbol(DEVICE *target, const _TCHAR *format, uint32_t addr)
150 symbol_t *first_symbol = NULL;
153 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
155 first_symbol = debugger->first_symbol;
158 return get_value_and_symbol(first_symbol, format, addr);
161 break_point_t *get_break_point(DEBUGGER *debugger, const _TCHAR *command)
163 if(command[0] == _T('B') || command[0] == _T('b')) {
164 return &debugger->bp;
165 } else if(command[0] == _T('R') || command[0] == _T('r')) {
166 return &debugger->rbp;
167 } else if(command[0] == _T('W') || command[0] == _T('w')) {
168 return &debugger->wbp;
169 } else if(command[0] == _T('I') || command[0] == _T('i')) {
170 return &debugger->ibp;
171 } else if(command[0] == _T('O') || command[0] == _T('o')) {
172 return &debugger->obp;
177 unsigned __stdcall debugger_thread(void *lpx)
179 void* debugger_thread(void *lpx)
182 volatile debugger_thread_t *p = (debugger_thread_t *)lpx;
185 // initialize console
187 bool cp932 = (p->osd->get_console_code_page() == 932);
189 p->osd->open_console((_TCHAR *)create_string(_T("Debugger - %s"), _T(DEVICE_NAME)));
192 DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
193 DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
194 DEVICE *target = cpu;
195 DEBUGGER *target_debugger = debugger;
197 debugger->now_going = false;
198 debugger->now_debugging = true;
200 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
201 if((wait_count++) == 100) {
202 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
203 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
208 uint32_t dump_addr = 0;
209 uint32_t dasm_addr = cpu->get_next_pc();
211 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
212 cpu->get_debug_regs_info(buffer, 1024);
213 my_printf(p->osd, _T("%s\n"), buffer);
215 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
216 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
218 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
219 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
220 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
221 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
227 _TCHAR command[MAX_COMMAND_LENGTH + 1];
228 _TCHAR prev_command[MAX_COMMAND_LENGTH + 1];
230 memset(prev_command, 0, sizeof(prev_command));
232 while(!p->request_terminate) {
233 my_printf(p->osd, _T("- "));
239 bool enter_done = false;
241 while(!p->request_terminate && !enter_done) {
242 if(cmdfile != NULL && cmdfile->IsOpened()) {
243 if(cmdfile->Fgetts(command, array_length(command)) != NULL) {
244 while(_tcslen(command) > 0 && (command[_tcslen(command) - 1] == 0x0d || command[_tcslen(command) - 1] == 0x0a)) {
245 command[_tcslen(command) - 1] = _T('\0');
247 if(_tcslen(command) > 0) {
248 my_printf(p->osd, _T("%s\n"), command);
257 memset(ir, 0, sizeof(ir));
258 int count = p->osd->read_console_input(ir, 16);
260 for(int i = 0; i < count; i++) {
264 my_putch(p->osd, 0x08);
265 my_putch(p->osd, _T(' '));
266 my_putch(p->osd, 0x08);
268 } else if(ir[i] == 0x0d || ir[i] == 0x0a) {
269 if(enter_ptr == 0 && prev_command[0] != _T('\0')) {
270 memcpy(command, prev_command, sizeof(command));
271 my_printf(p->osd, _T("%s\n"), command);
274 } else if(enter_ptr > 0) {
275 command[enter_ptr] = _T('\0');
276 memcpy(prev_command, command, sizeof(command));
277 memcpy(debugger->history[debugger->history_ptr], command, sizeof(command));
278 if (++debugger->history_ptr >= MAX_COMMAND_HISTORY) {
279 debugger->history_ptr = 0;
281 my_printf(p->osd, _T("\n"));
285 } else if(ir[i] == 0x1b && ir[i + 1] == 0x5b) {
286 if(ir[i + 2] == _T('A') || ir[i + 2] == _T('B')) {
287 int history_ptr_stored = history_ptr;
288 if(ir[i + 2] == _T('A')) {
289 if(++history_ptr >= MAX_COMMAND_HISTORY) {
290 history_ptr = MAX_COMMAND_HISTORY;
293 if(--history_ptr < 0) {
297 int index = debugger->history_ptr - history_ptr;
299 index += MAX_COMMAND_HISTORY;
301 while(index >= MAX_COMMAND_HISTORY) {
302 index -= MAX_COMMAND_HISTORY;
304 if(debugger->history[index][0] != _T('\0')) {
305 for(int i = 0; i < enter_ptr; i++) {
306 my_putch(p->osd, 0x08);
307 my_putch(p->osd, _T(' '));
308 my_putch(p->osd, 0x08);
310 memcpy(command, debugger->history[index], sizeof(command));
311 my_printf(p->osd, _T("%s"), command);
312 enter_ptr = _tcslen(command);
314 history_ptr = history_ptr_stored;
317 i += 2; // skip 2 characters
318 } else if(ir[i] >= 0x20 && ir[i] <= 0x7e && enter_ptr < MAX_COMMAND_LENGTH && !(ir[i] == 0x20 && enter_ptr == 0)) {
319 command[enter_ptr++] = ir[i];
320 my_putch(p->osd, ir[i]);
328 if(!p->request_terminate && enter_done) {
329 _TCHAR *params[32], *token = NULL, *context = NULL;
332 if((token = my_tcstok_s(command, _T(" "), &context)) != NULL) {
333 params[num++] = token;
334 while(num < 32 && (token = my_tcstok_s(NULL, _T(" "), &context)) != NULL) {
335 params[num++] = token;
338 if(_tcsicmp(params[0], _T("D")) == 0) {
340 uint32_t start_addr = dump_addr;
342 start_addr = my_hexatoi(target, params[1]);
344 start_addr &= target->get_debug_data_addr_mask();
346 uint32_t end_addr = start_addr + 8 * 16 - 1;
348 end_addr = my_hexatoi(target, params[2]);
350 end_addr &= target->get_debug_data_addr_mask();
352 if(start_addr > end_addr) {
353 end_addr = target->get_debug_data_addr_mask();
355 for(uint64_t addr = start_addr & ~0x0f; addr <= end_addr; addr++) {
356 if(addr > target->get_debug_data_addr_mask()) {
357 end_addr = target->get_debug_data_addr_mask();
360 if((addr & 0x0f) == 0) {
361 my_printf(p->osd, _T("%08X "), addr & target->get_debug_data_addr_mask());
362 memset(buffer, 0, sizeof(buffer));
364 if(addr < start_addr) {
365 my_printf(p->osd, _T(" "));
366 buffer[addr & 0x0f] = _T(' ');
368 uint32_t data = target->read_debug_data8(addr & target->get_debug_data_addr_mask());
369 my_printf(p->osd, _T(" %02X"), data);
370 buffer[addr & 0x0f] = ((data >= 0x20 && data <= 0x7e) || (cp932 && data >= 0xa1 && data <= 0xdf)) ? data : _T('.');
372 if((addr & 0x0f) == 0x0f) {
373 my_printf(p->osd, _T(" %s\n"), buffer);
376 if((end_addr & 0x0f) != 0x0f) {
377 for(uint32_t addr = (end_addr & 0x0f) + 1; addr <= 0x0f; addr++) {
378 my_printf(p->osd, _T(" "));
380 my_printf(p->osd, _T(" %s\n"), buffer);
382 dump_addr = (end_addr + 1) & target->get_debug_data_addr_mask();
383 prev_command[1] = _T('\0'); // remove parameters to dump continuously
385 my_printf(p->osd, _T("invalid parameter number\n"));
387 } else if(_tcsicmp(params[0], _T("E")) == 0 || _tcsicmp(params[0], _T("EB")) == 0) {
389 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
390 for(int i = 2; i < num; i++) {
391 target->write_debug_data8(addr, my_hexatoi(target, params[i]) & 0xff);
392 addr = (addr + 1) & target->get_debug_data_addr_mask();
395 my_printf(p->osd, _T("invalid parameter number\n"));
397 } else if(_tcsicmp(params[0], _T("EW")) == 0) {
399 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
400 for(int i = 2; i < num; i++) {
401 target->write_debug_data16(addr, my_hexatoi(target, params[i]) & 0xffff);
402 addr = (addr + 2) & target->get_debug_data_addr_mask();
405 my_printf(p->osd, _T("invalid parameter number\n"));
407 } else if(_tcsicmp(params[0], _T("ED")) == 0) {
409 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
410 for(int i = 2; i < num; i++) {
411 target->write_debug_data32(addr, my_hexatoi(target, params[i]));
412 addr = (addr + 4) & target->get_debug_data_addr_mask();
415 my_printf(p->osd, _T("invalid parameter number\n"));
417 } else if(_tcsicmp(params[0], _T("EA")) == 0) {
419 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
420 my_tcscpy_s(buffer, 1024, prev_command);
421 if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
422 int len = _tcslen(token);
423 for(int i = 0; i < len; i++) {
424 target->write_debug_data8(addr, token[i] & 0xff);
425 addr = (addr + 1) & target->get_debug_data_addr_mask();
428 my_printf(p->osd, _T("invalid parameter\n"));
431 my_printf(p->osd, _T("invalid parameter number\n"));
433 } else if(_tcsicmp(params[0], _T("I")) == 0 || _tcsicmp(params[0], _T("IB")) == 0) {
435 my_printf(p->osd, _T("%02X\n"), target->read_debug_io8(my_hexatoi(target, params[1])) & 0xff);
437 my_printf(p->osd, _T("invalid parameter number\n"));
439 } else if(_tcsicmp(params[0], _T("IW")) == 0) {
441 my_printf(p->osd, _T("%02X\n"), target->read_debug_io16(my_hexatoi(target, params[1])) & 0xffff);
443 my_printf(p->osd, _T("invalid parameter number\n"));
445 } else if(_tcsicmp(params[0], _T("ID")) == 0) {
447 my_printf(p->osd, _T("%02X\n"), target->read_debug_io32(my_hexatoi(target, params[1])));
449 my_printf(p->osd, _T("invalid parameter number\n"));
451 } else if(_tcsicmp(params[0], _T("O")) == 0 || _tcsicmp(params[0], _T("OB")) == 0) {
453 target->write_debug_io8(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]) & 0xff);
455 my_printf(p->osd, _T("invalid parameter number\n"));
457 } else if(_tcsicmp(params[0], _T("OW")) == 0) {
459 target->write_debug_io16(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]) & 0xffff);
461 my_printf(p->osd, _T("invalid parameter number\n"));
463 } else if(_tcsicmp(params[0], _T("OD")) == 0) {
465 target->write_debug_io32(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]));
467 my_printf(p->osd, _T("invalid parameter number\n"));
469 } else if(_tcsicmp(params[0], _T("R")) == 0) {
471 target->get_debug_regs_info(buffer, 1024);
472 my_printf(p->osd, _T("%s\n"), buffer);
473 } else if(num == 3) {
474 if(!target->write_debug_reg(params[1], my_hexatoi(target, params[2]))) {
475 my_printf(p->osd, _T("unknown register %s\n"), params[1]);
478 my_printf(p->osd, _T("invalid parameter number\n"));
480 } else if(_tcsicmp(params[0], _T("S")) == 0) {
482 uint32_t start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
483 uint32_t end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
485 for(int i = 3, j = 0; i < num; i++, j++) {
486 list[j] = my_hexatoi(target, params[i]);
488 for(uint64_t addr = start_addr; addr <= end_addr; addr++) {
490 for(int i = 3, j = 0; i < num; i++, j++) {
491 if(target->read_debug_data8((uint32_t)((addr + j) & target->get_debug_data_addr_mask())) != list[j]) {
497 my_printf(p->osd, _T("%s\n"), my_get_value_and_symbol(target, _T("%08X"), (uint32_t)addr));
501 my_printf(p->osd, _T("invalid parameter number\n"));
503 } else if(_tcsicmp(params[0], _T("U")) == 0) {
506 dasm_addr = my_hexatoi(target, params[1]) & target->get_debug_prog_addr_mask();
509 uint32_t end_addr = my_hexatoi(target, params[2]) & target->get_debug_prog_addr_mask();
510 while(dasm_addr <= end_addr) {
511 const _TCHAR *name = my_get_symbol(target, dasm_addr & target->get_debug_prog_addr_mask());
512 int len = target->debug_dasm(dasm_addr & target->get_debug_prog_addr_mask(), buffer, 1024);
514 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
515 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
516 my_printf(p->osd, _T("%s:\n"), name);
517 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
519 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
520 for(int i = 0; i < len; i++) {
521 my_printf(p->osd, _T("%02X"), target->read_debug_data8((dasm_addr + i) & target->get_debug_prog_addr_mask()));
523 for(int i = len; i < 8; i++) {
524 my_printf(p->osd, _T(" "));
526 my_printf(p->osd, _T(" %s\n"), buffer);
530 for(int i = 0; i < 16; i++) {
531 const _TCHAR *name = my_get_symbol(target, dasm_addr & target->get_debug_prog_addr_mask());
532 int len = target->debug_dasm(dasm_addr & target->get_debug_prog_addr_mask(), buffer, 1024);
534 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
535 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
536 my_printf(p->osd, _T("%s:\n"), name);
537 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
539 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
540 for(int i = 0; i < len; i++) {
541 my_printf(p->osd, _T("%02X"), target->read_debug_data8((dasm_addr + i) & target->get_debug_prog_addr_mask()));
543 for(int i = len; i < 8; i++) {
544 my_printf(p->osd, _T(" "));
546 my_printf(p->osd, _T(" %s\n"), buffer);
550 prev_command[1] = _T('\0'); // remove parameters to disassemble continuously
552 my_printf(p->osd, _T("invalid parameter number\n"));
554 } else if(_tcsicmp(params[0], _T("UT")) == 0) {
555 if(target_debugger == NULL) {
556 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
557 } else if(num <= 3) {
560 steps = min((int)my_hexatoi(target, params[1]), MAX_CPU_TRACE);
562 for(int i = MAX_CPU_TRACE - steps; i < MAX_CPU_TRACE; i++) {
563 int index = (target_debugger->cpu_trace_ptr + i) & (MAX_CPU_TRACE - 1);
564 if(!(target_debugger->cpu_trace[index] & ~target->get_debug_prog_addr_mask())) {
565 const _TCHAR *name = my_get_symbol(target, target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
566 int len = target->debug_dasm(target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask(), buffer, 1024);
568 my_printf(p->osd, _T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
569 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
570 my_printf(p->osd, _T("%s:\n"), name);
571 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
573 my_printf(p->osd, _T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
574 for(int i = 0; i < len; i++) {
575 my_printf(p->osd, _T("%02X"), target->read_debug_data8((target_debugger->cpu_trace[index] + i) & target->get_debug_prog_addr_mask()));
577 for(int i = len; i < 8; i++) {
578 my_printf(p->osd, _T(" "));
580 my_printf(p->osd, _T(" %s\n"), buffer);
584 my_printf(p->osd, _T("invalid parameter number\n"));
586 } else if(_tcsicmp(params[0], _T("H")) == 0) {
588 uint32_t l = my_hexatoi(target, params[1]);
589 uint32_t r = my_hexatoi(target, params[2]);
590 my_printf(p->osd, _T("%08X %08X\n"), l + r, l - r);
592 my_printf(p->osd, _T("invalid parameter number\n"));
594 } else if(_tcsicmp(params[0], _T("N")) == 0) {
595 if(num >= 2 && params[1][0] == _T('\"')) {
596 my_tcscpy_s(buffer, 1024, prev_command);
597 if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
598 my_tcscpy_s(debugger->file_path, _MAX_PATH, create_absolute_path(token));
600 my_printf(p->osd, _T("invalid parameter\n"));
602 } else if(num == 2) {
603 my_tcscpy_s(debugger->file_path, _MAX_PATH, create_absolute_path(params[1]));
605 my_printf(p->osd, _T("invalid parameter number\n"));
607 } else if(_tcsicmp(params[0], _T("L")) == 0) {
608 FILEIO* fio = new FILEIO();
609 if(check_file_extension(debugger->file_path, _T(".sym"))) {
610 if(target_debugger == NULL) {
611 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
612 } else if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
613 target_debugger->release_symbols();
615 while(fio->Fgetts(line, array_length(line)) != NULL) {
617 _TCHAR *addr = my_tcstok_s(line, _T("\t #$*,;"), &next);
618 while(addr != NULL) {
619 if(_tcslen(addr) > 0) {
620 _TCHAR *name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
621 while(name != NULL) {
622 while(_tcslen(name) > 0 && (name[_tcslen(name) - 1] == 0x0d || name[_tcslen(name) - 1] == 0x0a)) {
623 name[_tcslen(name) - 1] = _T('\0');
625 if(_tcslen(name) > 0) {
626 target_debugger->add_symbol(my_hexatoi(NULL, addr), name);
629 name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
632 addr = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
637 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
639 } else if(check_file_extension(debugger->file_path, _T(".hex"))) {
640 if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
641 uint32_t start_addr = 0, linear = 0, segment = 0;
643 start_addr = my_hexatoi(target, params[1]);
646 while(fio->Fgets(line, sizeof(line)) != NULL) {
647 if(line[0] != ':') continue;
648 int type = my_hexatob(line + 7);
650 uint32_t bytes = my_hexatob(line + 1);
651 uint32_t addr = my_hexatow(line + 3) + start_addr + linear + segment;
652 for(uint32_t i = 0; i < bytes; i++) {
653 target->write_debug_data8((addr + i) & target->get_debug_data_addr_mask(), my_hexatob(line + 9 + 2 * i));
655 } else if(type == 0x01) {
657 } else if(type == 0x02) {
658 segment = my_hexatow(line + 9) << 4;
660 } else if(type == 0x04) {
661 linear = my_hexatow(line + 9) << 16;
667 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
670 if(fio->Fopen(debugger->file_path, FILEIO_READ_BINARY)) {
671 uint32_t start_addr = 0x100, end_addr = target->get_debug_data_addr_mask();
673 start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
676 end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
678 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
679 int data = fio->Fgetc();
683 target->write_debug_data8(addr & target->get_debug_data_addr_mask(), data);
687 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
691 } else if(_tcsicmp(params[0], _T("W")) == 0) {
693 uint32_t start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask(), end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
694 FILEIO* fio = new FILEIO();
695 if(check_file_extension(debugger->file_path, _T(".hex"))) {
696 // write intel hex format file
697 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_ASCII)) {
698 uint32_t addr = start_addr;
699 while(addr <= end_addr) {
700 uint32_t len = min(end_addr - addr + 1, (uint32_t)16);
701 uint32_t sum = len + ((addr >> 8) & 0xff) + (addr & 0xff) + 0x00;
702 fio->Fprintf(":%02X%04X%02X", len, addr & 0xffff, 0x00);
703 for(uint32_t i = 0; i < len; i++) {
704 uint8_t data = target->read_debug_data8((addr++) & target->get_debug_data_addr_mask());
706 fio->Fprintf("%02X", data);
708 fio->Fprintf("%02X\n", (0x100 - (sum & 0xff)) & 0xff);
710 fio->Fprintf(":00000001FF\n");
713 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
716 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_BINARY)) {
717 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
718 fio->Fputc(target->read_debug_data8(addr & target->get_debug_data_addr_mask()));
722 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
727 my_printf(p->osd, _T("invalid parameter number\n"));
729 } else if(_tcsicmp(params[0], _T("SC")) == 0) {
730 if(target_debugger == NULL) {
731 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
732 } else if(num == 1) {
733 target_debugger->release_symbols();
735 my_printf(p->osd, _T("invalid parameter number\n"));
737 } else if(_tcsicmp(params[0], _T("SL")) == 0) {
738 if(target_debugger == NULL) {
739 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
740 } else if(num == 1) {
741 for(symbol_t* symbol = debugger->first_symbol; symbol; symbol = symbol->next_symbol) {
742 my_printf(p->osd, _T("%08X %s\n"), symbol->addr, symbol->name);
745 my_printf(p->osd, _T("invalid parameter number\n"));
747 } else if(_tcsicmp(params[0], _T( "BP")) == 0 || _tcsicmp(params[0], _T("RBP")) == 0 || _tcsicmp(params[0], _T("WBP")) == 0) {
748 break_point_t *bp = get_break_point(debugger, params[0]);
750 uint32_t addr = my_hexatoi(cpu, params[1]);
752 for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
753 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == cpu->get_debug_prog_addr_mask())) {
754 bp->table[i].addr = addr;
755 bp->table[i].mask = cpu->get_debug_prog_addr_mask();
756 bp->table[i].status = 1;
761 my_printf(p->osd, _T("too many break points\n"));
764 my_printf(p->osd, _T("invalid parameter number\n"));
766 } else if(_tcsicmp(params[0], _T("IBP")) == 0 || _tcsicmp(params[0], _T("OBP")) == 0) {
767 break_point_t *bp = get_break_point(debugger, params[0]);
768 if(num == 2 || num == 3) {
769 uint32_t addr = my_hexatoi(cpu, params[1]), mask = 0xff;
771 mask = my_hexatoi(cpu, params[2]);
774 for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
775 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == mask)) {
776 bp->table[i].addr = addr;
777 bp->table[i].mask = mask;
778 bp->table[i].status = 1;
783 my_printf(p->osd, _T("too many break points\n"));
786 my_printf(p->osd, _T("invalid parameter number\n"));
788 } else if(_tcsicmp(params[0], _T("BC")) == 0 || _tcsicmp(params[0], _T("RBC")) == 0 || _tcsicmp(params[0], _T("WBC")) == 0 || _tcsicmp(params[0], _T("IBC")) == 0 || _tcsicmp(params[0], _T("OBC")) == 0) {
789 break_point_t *bp = get_break_point(debugger, params[0]);
790 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
791 memset(bp->table, 0, sizeof(bp->table));
792 } else if(num >= 2) {
793 for(int i = 1; i < num; i++) {
794 int index = my_hexatoi(cpu, params[i]);
795 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
796 my_printf(p->osd, _T("invalid index %x\n"), index);
798 bp->table[index - 1].addr = bp->table[index - 1].mask = 0;
799 bp->table[index - 1].status = 0;
803 my_printf(p->osd, _T("invalid parameter number\n"));
805 } else if(_tcsicmp(params[0], _T("BD")) == 0 || _tcsicmp(params[0], _T("RBD")) == 0 || _tcsicmp(params[0], _T("WBD")) == 0 || _tcsicmp(params[0], _T("IBD")) == 0 || _tcsicmp(params[0], _T("OBD")) == 0 ||
806 _tcsicmp(params[0], _T("BE")) == 0 || _tcsicmp(params[0], _T("RBE")) == 0 || _tcsicmp(params[0], _T("WBE")) == 0 || _tcsicmp(params[0], _T("IBE")) == 0 || _tcsicmp(params[0], _T("OBE")) == 0) {
807 break_point_t *bp = get_break_point(debugger, params[0]);
808 bool enabled = (params[0][1] == _T('E') || params[0][1] == _T('e') || params[0][2] == _T('E') || params[0][2] == _T('e'));
809 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
810 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
811 if(bp->table[i].status != 0) {
812 bp->table[i].status = enabled ? 1 : -1;
815 } else if(num >= 2) {
816 for(int i = 1; i < num; i++) {
817 int index = my_hexatoi(cpu, params[i]);
818 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
819 my_printf(p->osd, _T("invalid index %x\n"), index);
820 } else if(bp->table[index - 1].status == 0) {
821 my_printf(p->osd, _T("break point %x is null\n"), index);
823 bp->table[index - 1].status = enabled ? 1 : -1;
827 my_printf(p->osd, _T("invalid parameter number\n"));
829 } else if(_tcsicmp(params[0], _T("BL")) == 0 || _tcsicmp(params[0], _T("RBL")) == 0 || _tcsicmp(params[0], _T("WBL")) == 0) {
831 break_point_t *bp = get_break_point(debugger, params[0]);
832 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
833 if(bp->table[i].status) {
834 my_printf(p->osd, _T("%d %c %s\n"), i + 1, bp->table[i].status == 1 ? _T('e') : _T('d'), my_get_value_and_symbol(cpu, _T("%08X"), bp->table[i].addr));
838 my_printf(p->osd, _T("invalid parameter number\n"));
840 } else if(_tcsicmp(params[0], _T("IBL")) == 0 || _tcsicmp(params[0], _T("OBL")) == 0) {
842 break_point_t *bp = get_break_point(debugger, params[0]);
843 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
844 if(bp->table[i].status) {
845 my_printf(p->osd, _T("%d %c %08X %08X\n"), i + 1, bp->table[i].status == 1 ? _T('e') : _T('d'), bp->table[i].addr, bp->table[i].mask);
849 my_printf(p->osd, _T("invalid parameter number\n"));
851 } else if(_tcsicmp(params[0], _T("G")) == 0 || _tcsicmp(params[0], _T("P")) == 0) {
852 if(num == 1 || num == 2) {
853 bool break_points_stored = false;
854 if(_tcsicmp(params[0], _T("P")) == 0) {
855 debugger->store_break_points();
856 debugger->bp.table[0].addr = (cpu->get_next_pc() + cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024)) & cpu->get_debug_prog_addr_mask();
857 debugger->bp.table[0].mask = cpu->get_debug_prog_addr_mask();
858 debugger->bp.table[0].status = 1;
859 break_points_stored = true;
860 } else if(num >= 2) {
861 debugger->store_break_points();
862 debugger->bp.table[0].addr = my_hexatoi(cpu, params[1]) & cpu->get_debug_prog_addr_mask();
863 debugger->bp.table[0].mask = cpu->get_debug_prog_addr_mask();
864 debugger->bp.table[0].status = 1;
865 break_points_stored = true;
867 debugger->now_going = true;
868 debugger->now_suspended = false;
869 #if defined(_MSC_VER)
870 while(!p->request_terminate && !debugger->now_suspended) {
871 if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) {
876 #elif defined(OSD_QT)
877 while(!p->request_terminate && !debugger->now_suspended) {
878 if(p->osd->console_input_string() != NULL && p->osd->is_console_active()) {
879 p->osd->clear_console_input_string();
886 debugger->now_going = false;
888 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
889 if((wait_count++) == 100) {
890 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
891 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
896 dasm_addr = cpu->get_next_pc();
899 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
900 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
901 my_printf(p->osd, _T("done\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer);
903 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
904 cpu->get_debug_regs_info(buffer, 1024);
905 my_printf(p->osd, _T("%s\n"), buffer);
908 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
909 if(target->debug_dasm(target->get_next_pc(), buffer, 1024) != 0) {
910 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(target, _T("%08X"), target->get_next_pc()), buffer);
912 target->get_debug_regs_info(buffer, 1024);
913 my_printf(p->osd, _T("%s\n"), buffer);
916 if(debugger->hit()) {
917 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
918 if(debugger->bp.hit) {
919 if(_tcsicmp(params[0], _T("G")) == 0) {
920 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
922 } else if(debugger->rbp.hit) {
923 my_printf(p->osd, _T("breaked at %s: memory %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
924 my_get_value_and_symbol(cpu, _T("%08X"), debugger->rbp.hit_addr),
925 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
926 } else if(debugger->wbp.hit) {
927 my_printf(p->osd, _T("breaked at %s: memory %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
928 my_get_value_and_symbol(cpu, _T("%08X"), debugger->wbp.hit_addr),
929 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
930 } else if(debugger->ibp.hit) {
931 my_printf(p->osd, _T("breaked at %s: port %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
932 my_get_value_and_symbol(cpu, _T("%08X"), debugger->ibp.hit_addr),
933 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
934 } else if(debugger->obp.hit) {
935 my_printf(p->osd, _T("breaked at %s: port %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
936 my_get_value_and_symbol(cpu, _T("%08X"), debugger->obp.hit_addr),
937 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
939 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
941 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
942 my_printf(p->osd, _T("breaked at %s: esc key was pressed\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
944 if(break_points_stored) {
945 debugger->restore_break_points();
947 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
948 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
949 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
950 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
952 my_printf(p->osd, _T("invalid parameter number\n"));
954 } else if(_tcsicmp(params[0], _T("T")) == 0) {
955 if(num == 1 || num == 2) {
958 steps = my_hexatoi(cpu, params[1]);
960 for(int i = 0; i < steps; i++) {
961 debugger->now_going = false;
962 debugger->now_suspended = false;
964 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
965 if((wait_count++) == 100) {
966 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
967 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
972 dasm_addr = cpu->get_next_pc();
975 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
976 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
977 my_printf(p->osd, _T("done\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer);
979 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
980 cpu->get_debug_regs_info(buffer, 1024);
981 my_printf(p->osd, _T("%s\n"), buffer);
984 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
985 if(target->debug_dasm(target->get_next_pc(), buffer, 1024) != 0) {
986 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(target, _T("%08X"), target->get_next_pc()), buffer);
988 target->get_debug_regs_info(buffer, 1024);
989 my_printf(p->osd, _T("%s\n"), buffer);
992 if(debugger->hit() || (p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active())) {
996 if(debugger->hit()) {
997 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
998 if(debugger->bp.hit) {
999 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
1000 } else if(debugger->rbp.hit) {
1001 my_printf(p->osd, _T("breaked at %s: memory %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1002 my_get_value_and_symbol(cpu, _T("%08X"), debugger->rbp.hit_addr),
1003 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1004 } else if(debugger->wbp.hit) {
1005 my_printf(p->osd, _T("breaked at %s: memory %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1006 my_get_value_and_symbol(cpu, _T("%08X"), debugger->wbp.hit_addr),
1007 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1008 } else if(debugger->ibp.hit) {
1009 my_printf(p->osd, _T("breaked at %s: port %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1010 my_get_value_and_symbol(cpu, _T("%08X"), debugger->ibp.hit_addr),
1011 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1012 } else if(debugger->obp.hit) {
1013 my_printf(p->osd, _T("breaked at %s: port %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1014 my_get_value_and_symbol(cpu, _T("%08X"), debugger->obp.hit_addr),
1015 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1017 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
1019 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1020 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
1021 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
1022 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1024 my_printf(p->osd, _T("invalid parameter number\n"));
1026 } else if(_tcsicmp(params[0], _T("Q")) == 0) {
1027 p->osd->close_debugger_console();
1029 } else if(_tcsicmp(params[0], _T(">")) == 0) {
1031 if(logfile != NULL) {
1032 if(logfile->IsOpened()) {
1038 logfile = new FILEIO();
1039 logfile->Fopen(create_absolute_path(params[1]), FILEIO_WRITE_ASCII);
1041 my_printf(p->osd, _T("invalid parameter number\n"));
1043 } else if(_tcsicmp(params[0], _T("<")) == 0) {
1045 if(cmdfile != NULL) {
1046 if(cmdfile->IsOpened()) {
1050 cmdfile = new FILEIO();
1052 if(!cmdfile->Fopen(create_absolute_path(params[1]), FILEIO_READ_ASCII)) {
1055 my_printf(p->osd, _T("can't open %s\n"), params[1]);
1058 my_printf(p->osd, _T("invalid parameter number\n"));
1060 } else if(_tcsicmp(params[0], _T("!")) == 0) {
1062 my_printf(p->osd, _T("invalid parameter number\n"));
1063 } else if(_tcsicmp(params[1], _T("RESET")) == 0) {
1066 } else if(num == 3) {
1067 if(_tcsicmp(params[2], _T("ALL")) == 0) {
1069 } if(_tcsicmp(params[2], _T("CPU")) == 0) {
1071 } if(_tcsicmp(params[2], _T("TARGET")) == 0) {
1074 my_printf(p->osd, _T("unknown device %s\n"), params[2]);
1077 my_printf(p->osd, _T("invalid parameter number\n"));
1079 } else if(_tcsicmp(params[1], _T("KEY")) == 0) {
1080 if(num == 3 || num == 4) {
1081 int code = my_hexatoi(target, params[2]) & 0xff, msec = 100;
1083 msec = my_hexatoi(target, params[3]);
1085 #ifdef SUPPORT_VARIABLE_TIMING
1086 int frames = (int)(p->vm->get_frame_rate() * (double)msec / 1000.0 + 0.5);
1088 int frames = (int)(FRAMES_PER_SEC * (double)msec / 1000.0 + 0.5);
1090 p->osd->get_key_buffer()[code] &= 0x7f;
1091 p->osd->get_key_buffer()[code] |= max(1, min(127, frames));
1092 #ifdef NOTIFY_KEY_DOWN
1093 p->vm->key_down(code, false);
1096 my_printf(p->osd, _T("invalid parameter number\n"));
1098 } else if(_tcsicmp(params[1], _T("DEVICE")) == 0) {
1100 for(DEVICE* device = p->vm->first_device; device; device = device->next_device) {
1101 my_printf(p->osd, _T("ID=%02X %s"), device->this_device_id, device->this_device_name);
1102 if(device == target) {
1103 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1104 my_printf(p->osd, _T(" <=== target"));
1105 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1107 my_printf(p->osd, _T("\n"));
1109 } else if(num == 3) {
1110 DEVICE *device = NULL;
1111 if(_tcsicmp(params[2], _T("CPU")) == 0) {
1114 device = p->vm->get_device(my_hexatoi(NULL, params[2]));
1116 if(device != NULL) {
1117 if(device != target) {
1119 target_debugger = (DEBUGGER *)target->get_debugger();
1121 dasm_addr = target->get_next_pc();
1124 my_printf(p->osd, _T("device not found\n"));
1127 my_printf(p->osd, _T("invalid parameter number\n"));
1129 } else if(_tcsicmp(params[1], _T("CPU")) == 0) {
1131 for(DEVICE* device = p->vm->first_device; device; device = device->next_device) {
1132 if(device->get_debugger() != NULL) {
1133 my_printf(p->osd, _T("ID=%02X %s"), device->this_device_id, device->this_device_name);
1135 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1136 my_printf(p->osd, _T(" <=== target"));
1137 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1139 my_printf(p->osd, _T("\n"));
1142 } else if(num == 3) {
1143 DEVICE *device = p->vm->get_device(my_hexatoi(NULL, params[2]));
1144 if(device != NULL && device->get_debugger() != NULL) {
1146 DEBUGGER *prev_debugger = debugger;
1148 debugger = (DEBUGGER *)cpu->get_debugger();
1149 debugger->now_going = false;
1150 debugger->now_debugging = true;
1151 prev_debugger->now_debugging = prev_debugger->now_going = prev_debugger->now_suspended = prev_debugger->now_waiting = false;
1153 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
1154 if((wait_count++) == 100) {
1155 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1156 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
1161 dasm_addr = cpu->get_next_pc();
1163 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1164 cpu->get_debug_regs_info(buffer, 1024);
1165 my_printf(p->osd, _T("%s\n"), buffer);
1167 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1168 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
1170 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1171 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
1172 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
1173 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1176 my_printf(p->osd, _T("device not found\n"));
1179 my_printf(p->osd, _T("invalid parameter number\n"));
1182 my_printf(p->osd, _T("unknown command ! %s\n"), params[1]);
1184 } else if(_tcsicmp(params[0], _T("?")) == 0) {
1185 my_printf(p->osd, _T("D [<range>] - dump memory\n"));
1186 my_printf(p->osd, _T("E[{B,W,D}] <address> <list> - edit memory (byte,word,dword)\n"));
1187 my_printf(p->osd, _T("EA <address> \"<value>\" - edit memory (ascii)\n"));
1188 my_printf(p->osd, _T("I[{B,W,D}] <port> - input port (byte,word,dword)\n"));
1189 my_printf(p->osd, _T("O[{B,W,D}] <port> <value> - output port (byte,word,dword)\n"));
1190 my_printf(p->osd, _T("R - show register(s)\n"));
1191 my_printf(p->osd, _T("R <reg> <value> - edit register\n"));
1192 my_printf(p->osd, _T("S <range> <list> - search\n"));
1193 my_printf(p->osd, _T("U [<range>] - unassemble\n"));
1194 my_printf(p->osd, _T("UT [<steps>] - unassemble trace\n"));
1196 my_printf(p->osd, _T("H <value> <value> - hexadd\n"));
1197 my_printf(p->osd, _T("N <filename> - name\n"));
1198 my_printf(p->osd, _T("L [<range>] - load binary/hex/symbol file\n"));
1199 my_printf(p->osd, _T("W <range> - write binary/hex file\n"));
1201 my_printf(p->osd, _T("SC - clear symbol(s)\n"));
1202 my_printf(p->osd, _T("SL - list symbol(s)\n"));
1204 my_printf(p->osd, _T("BP <address> - set breakpoint\n"));
1205 my_printf(p->osd, _T("{R,W}BP <address> - set breakpoint (break at memory access)\n"));
1206 my_printf(p->osd, _T("{I,O}BP <port> [<mask>] - set breakpoint (break at i/o access)\n"));
1207 my_printf(p->osd, _T("[{R,W,I,O}]B{C,D,E} {*,<list>} - clear/disable/enable breakpoint(s)\n"));
1208 my_printf(p->osd, _T("[{R,W,I,O}]BL - list breakpoint(s)\n"));
1210 my_printf(p->osd, _T("G - go (press esc key to break)\n"));
1211 my_printf(p->osd, _T("G <address> - go and break at address\n"));
1212 my_printf(p->osd, _T("P - trace one opcode (step over)\n"));
1213 my_printf(p->osd, _T("T [<count>] - trace (step in)\n"));
1214 my_printf(p->osd, _T("Q - quit\n"));
1216 my_printf(p->osd, _T("> <filename> - output logfile\n"));
1217 my_printf(p->osd, _T("< <filename> - input commands from file\n"));
1219 my_printf(p->osd, _T("! reset [all/cpu/target] - reset\n"));
1220 my_printf(p->osd, _T("! key <code> [<msec>] - press key\n"));
1221 my_printf(p->osd, _T("! device - enumerate device\n"));
1222 my_printf(p->osd, _T("! device <id/cpu> - select target device\n"));
1223 my_printf(p->osd, _T("! cpu - enumerate cpu\n"));
1224 my_printf(p->osd, _T("! cpu <id> - select target cpu\n"));
1226 my_printf(p->osd, _T("<value> - hexa, decimal(%%d), ascii('a')\n"));
1228 my_printf(p->osd, _T("unknown command %s\n"), params[0]);
1235 debugger->now_debugging = debugger->now_going = debugger->now_suspended = debugger->now_waiting = false;
1240 if(logfile != NULL) {
1241 if(logfile->IsOpened()) {
1247 if(cmdfile != NULL) {
1248 if(cmdfile->IsOpened()) {
1256 p->osd->close_console();
1263 //pthread_exit(NULL);
1268 void EMU::initialize_debugger()
1270 now_debugging = false;
1274 void EMU::release_debugger()
1279 void EMU::open_debugger(int cpu_index)
1281 if(!(now_debugging && debugger_thread_param.cpu_index == cpu_index)) {
1283 if(vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL) {
1284 // debugger_thread_param.emu = this;
1285 debugger_thread_param.osd = osd;
1286 debugger_thread_param.vm = vm;
1287 debugger_thread_param.cpu_index = cpu_index;
1288 debugger_thread_param.request_terminate = false;
1290 if((hDebuggerThread = (HANDLE)_beginthreadex(NULL, 0, debugger_thread, &debugger_thread_param, 0, NULL)) != (HANDLE)0) {
1292 //#elif !defined(_USE_QT)
1293 if(pthread_create(&debugger_thread_id, NULL, debugger_thread, &debugger_thread_param) == 0) {
1297 stop_record_sound();
1298 stop_record_video();
1299 now_debugging = true;
1305 void EMU::close_debugger()
1308 if(debugger_thread_param.running) {
1309 debugger_thread_param.request_terminate = true;
1312 WaitForSingleObject(hDebuggerThread, INFINITE);
1313 CloseHandle(hDebuggerThread);
1314 //#elif !defined(_USE_QT)
1316 pthread_join(debugger_thread_id, NULL);
1318 // volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param);
1319 // p->running = false;
1321 //if(logfile != NULL && logfile->IsOpened()) {
1322 // logfile->Fclose();
1324 // initialize logfile
1327 now_debugging = false;
1331 bool EMU::is_debugger_enabled(int cpu_index)
1333 return (vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL);