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 const _TCHAR *my_absolute_path(const _TCHAR *file_name)
42 static _TCHAR file_path[_MAX_PATH];
44 if(is_absolute_path(file_name)) {
45 my_tcscpy_s(file_path, _MAX_PATH, file_name);
47 my_stprintf_s(file_path, _MAX_PATH, _T("%s%s"), get_initial_current_path(), file_name);
49 return (const _TCHAR *)file_path;
52 void my_printf(OSD *osd, const _TCHAR *format, ...)
58 my_vstprintf_s(buffer, 1024, format, ap);
61 if(logfile != NULL && logfile->IsOpened()) {
62 logfile->Fwrite(buffer, _tcslen(buffer) * sizeof(_TCHAR), 1);
64 osd->write_console(buffer, _tcslen(buffer));
67 void my_putch(OSD *osd, _TCHAR c)
69 if(logfile != NULL && logfile->IsOpened()) {
70 logfile->Fwrite(&c, sizeof(_TCHAR), 1);
72 osd->write_console(&c, 1);
75 uint32_t my_hexatoi(DEVICE *target, const _TCHAR *str)
78 symbol_t *first_symbol = NULL;
80 if(str == NULL || _tcslen(str) == 0) {
83 my_tcscpy_s(tmp, 1024, str);
86 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
88 first_symbol = debugger->first_symbol;
91 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
92 if(_tcsicmp(symbol->name, str) == 0) {
96 if(_tcslen(tmp) == 3 && tmp[0] == _T('\'') && tmp[2] == _T('\'')) {
99 } else if((s = _tcsstr(tmp, _T(":"))) != NULL) {
102 return (my_hexatoi(target, tmp) << 4) + my_hexatoi(target, s + 1);
103 } else if(tmp[0] == _T('%')) {
105 #if defined(__MINGW32__)
106 return atoi(tmp + 1);
108 return _tstoi(tmp + 1);
111 return _tcstoul(tmp, NULL, 16);
114 uint8_t my_hexatob(char *value)
120 return (uint8_t)strtoul(tmp, NULL, 16);
123 uint16_t my_hexatow(char *value)
131 return (uint16_t)strtoul(tmp, NULL, 16);
134 const _TCHAR *my_get_symbol(DEVICE *target, uint32_t addr)
136 symbol_t *first_symbol = NULL;
139 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
141 first_symbol = debugger->first_symbol;
144 return get_symbol(first_symbol, addr);
147 const _TCHAR *my_get_value_or_symbol(DEVICE *target, const _TCHAR *format, uint32_t addr)
149 symbol_t *first_symbol = NULL;
152 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
154 first_symbol = debugger->first_symbol;
157 return get_value_or_symbol(first_symbol, format, addr);
160 const _TCHAR *my_get_value_and_symbol(DEVICE *target, const _TCHAR *format, uint32_t addr)
162 symbol_t *first_symbol = NULL;
165 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
167 first_symbol = debugger->first_symbol;
170 return get_value_and_symbol(first_symbol, format, addr);
173 break_point_t *get_break_point(DEBUGGER *debugger, const _TCHAR *command)
175 if(command[0] == _T('B') || command[0] == _T('b') || command[0] == _T('C') || command[0] == _T('c')) {
176 return &debugger->bp;
177 } else if(command[0] == _T('R') || command[0] == _T('r')) {
178 return &debugger->rbp;
179 } else if(command[0] == _T('W') || command[0] == _T('w')) {
180 return &debugger->wbp;
181 } else if(command[0] == _T('I') || command[0] == _T('i')) {
182 return &debugger->ibp;
183 } else if(command[0] == _T('O') || command[0] == _T('o')) {
184 return &debugger->obp;
189 unsigned __stdcall debugger_thread(void *lpx)
191 void* debugger_thread(void *lpx)
194 volatile debugger_thread_t *p = (debugger_thread_t *)lpx;
197 // initialize console
199 bool cp932 = (p->osd->get_console_code_page() == 932);
201 p->osd->open_console((_TCHAR *)create_string(_T("Debugger - %s"), _T(DEVICE_NAME)));
204 DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
205 DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
206 DEVICE *target = cpu;
207 DEBUGGER *target_debugger = debugger;
209 debugger->now_going = false;
210 debugger->now_debugging = true;
212 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
213 if((wait_count++) == 100) {
214 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
215 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
220 uint32_t dump_addr = 0;
221 uint32_t dasm_addr = cpu->get_next_pc();
223 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
224 cpu->get_debug_regs_info(buffer, 1024);
225 my_printf(p->osd, _T("%s\n"), buffer);
227 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
228 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
230 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
231 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
232 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
233 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
239 _TCHAR command[MAX_COMMAND_LENGTH + 1];
240 _TCHAR prev_command[MAX_COMMAND_LENGTH + 1];
242 memset(prev_command, 0, sizeof(prev_command));
244 while(!p->request_terminate) {
245 my_printf(p->osd, _T("- "));
251 bool enter_done = false;
253 while(!p->request_terminate && !enter_done) {
254 if(cmdfile != NULL && cmdfile->IsOpened()) {
255 if(cmdfile->Fgetts(command, array_length(command)) != NULL) {
256 while(_tcslen(command) > 0 && (command[_tcslen(command) - 1] == 0x0d || command[_tcslen(command) - 1] == 0x0a)) {
257 command[_tcslen(command) - 1] = _T('\0');
259 if(_tcslen(command) > 0) {
260 my_printf(p->osd, _T("%s\n"), command);
269 memset(ir, 0, sizeof(ir));
270 int count = p->osd->read_console_input(ir, 16);
272 for(int i = 0; i < count; i++) {
276 my_putch(p->osd, 0x08);
277 my_putch(p->osd, _T(' '));
278 my_putch(p->osd, 0x08);
280 } else if(ir[i] == 0x0d || ir[i] == 0x0a) {
281 if(enter_ptr == 0 && prev_command[0] != _T('\0')) {
282 memcpy(command, prev_command, sizeof(command));
283 my_printf(p->osd, _T("%s\n"), command);
286 } else if(enter_ptr > 0) {
287 command[enter_ptr] = _T('\0');
288 memcpy(prev_command, command, sizeof(command));
289 memcpy(debugger->history[debugger->history_ptr], command, sizeof(command));
290 if (++debugger->history_ptr >= MAX_COMMAND_HISTORY) {
291 debugger->history_ptr = 0;
293 my_printf(p->osd, _T("\n"));
297 } else if(ir[i] == 0x1b && ir[i + 1] == 0x5b) {
298 if(ir[i + 2] == _T('A') || ir[i + 2] == _T('B')) {
299 int history_ptr_stored = history_ptr;
300 if(ir[i + 2] == _T('A')) {
301 if(++history_ptr >= MAX_COMMAND_HISTORY) {
302 history_ptr = MAX_COMMAND_HISTORY;
305 if(--history_ptr < 0) {
309 int index = debugger->history_ptr - history_ptr;
311 index += MAX_COMMAND_HISTORY;
313 while(index >= MAX_COMMAND_HISTORY) {
314 index -= MAX_COMMAND_HISTORY;
316 if(debugger->history[index][0] != _T('\0')) {
317 for(int i = 0; i < enter_ptr; i++) {
318 my_putch(p->osd, 0x08);
319 my_putch(p->osd, _T(' '));
320 my_putch(p->osd, 0x08);
322 memcpy(command, debugger->history[index], sizeof(command));
323 my_printf(p->osd, _T("%s"), command);
324 enter_ptr = _tcslen(command);
326 history_ptr = history_ptr_stored;
329 i += 2; // skip 2 characters
330 } else if(ir[i] >= 0x20 && ir[i] <= 0x7e && enter_ptr < MAX_COMMAND_LENGTH && !(ir[i] == 0x20 && enter_ptr == 0)) {
331 command[enter_ptr++] = ir[i];
332 my_putch(p->osd, ir[i]);
340 if(!p->request_terminate && enter_done) {
341 _TCHAR *params[32], *token = NULL, *context = NULL;
344 if((token = my_tcstok_s(command, _T(" "), &context)) != NULL) {
345 params[num++] = token;
346 while(num < 32 && (token = my_tcstok_s(NULL, _T(" "), &context)) != NULL) {
347 params[num++] = token;
350 if(_tcsicmp(params[0], _T("D")) == 0) {
352 uint32_t start_addr = dump_addr;
354 start_addr = my_hexatoi(target, params[1]);
356 start_addr &= target->get_debug_data_addr_mask();
358 uint32_t end_addr = start_addr + 8 * 16 - 1;
360 end_addr = my_hexatoi(target, params[2]);
362 end_addr &= target->get_debug_data_addr_mask();
364 if(start_addr > end_addr) {
365 end_addr = target->get_debug_data_addr_mask();
367 for(uint64_t addr = start_addr & ~0x0f; addr <= end_addr; addr++) {
368 if(addr > target->get_debug_data_addr_mask()) {
369 end_addr = target->get_debug_data_addr_mask();
372 if((addr & 0x0f) == 0) {
373 my_printf(p->osd, _T("%08X "), addr & target->get_debug_data_addr_mask());
374 memset(buffer, 0, sizeof(buffer));
376 if(addr < start_addr) {
377 my_printf(p->osd, _T(" "));
378 buffer[addr & 0x0f] = _T(' ');
380 uint32_t data = target->read_debug_data8(addr & target->get_debug_data_addr_mask());
381 my_printf(p->osd, _T(" %02X"), data);
382 buffer[addr & 0x0f] = ((data >= 0x20 && data <= 0x7e) || (cp932 && data >= 0xa1 && data <= 0xdf)) ? data : _T('.');
384 if((addr & 0x0f) == 0x0f) {
385 my_printf(p->osd, _T(" %s\n"), buffer);
388 if((end_addr & 0x0f) != 0x0f) {
389 for(uint32_t addr = (end_addr & 0x0f) + 1; addr <= 0x0f; addr++) {
390 my_printf(p->osd, _T(" "));
392 my_printf(p->osd, _T(" %s\n"), buffer);
394 dump_addr = (end_addr + 1) & target->get_debug_data_addr_mask();
395 prev_command[1] = _T('\0'); // remove parameters to dump continuously
397 my_printf(p->osd, _T("invalid parameter number\n"));
399 } else if(_tcsicmp(params[0], _T("E")) == 0 || _tcsicmp(params[0], _T("EB")) == 0) {
401 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
402 for(int i = 2; i < num; i++) {
403 target->write_debug_data8(addr, my_hexatoi(target, params[i]) & 0xff);
404 addr = (addr + 1) & target->get_debug_data_addr_mask();
407 my_printf(p->osd, _T("invalid parameter number\n"));
409 } else if(_tcsicmp(params[0], _T("EW")) == 0) {
411 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
412 for(int i = 2; i < num; i++) {
413 target->write_debug_data16(addr, my_hexatoi(target, params[i]) & 0xffff);
414 addr = (addr + 2) & target->get_debug_data_addr_mask();
417 my_printf(p->osd, _T("invalid parameter number\n"));
419 } else if(_tcsicmp(params[0], _T("ED")) == 0) {
421 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
422 for(int i = 2; i < num; i++) {
423 target->write_debug_data32(addr, my_hexatoi(target, params[i]));
424 addr = (addr + 4) & target->get_debug_data_addr_mask();
427 my_printf(p->osd, _T("invalid parameter number\n"));
429 } else if(_tcsicmp(params[0], _T("EA")) == 0) {
431 uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
432 my_tcscpy_s(buffer, 1024, prev_command);
433 if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
434 int len = _tcslen(token);
435 for(int i = 0; i < len; i++) {
436 target->write_debug_data8(addr, token[i] & 0xff);
437 addr = (addr + 1) & target->get_debug_data_addr_mask();
440 my_printf(p->osd, _T("invalid parameter\n"));
443 my_printf(p->osd, _T("invalid parameter number\n"));
445 } else if(_tcsicmp(params[0], _T("I")) == 0 || _tcsicmp(params[0], _T("IB")) == 0) {
447 my_printf(p->osd, _T("%02X\n"), target->read_debug_io8(my_hexatoi(target, params[1])) & 0xff);
449 my_printf(p->osd, _T("invalid parameter number\n"));
451 } else if(_tcsicmp(params[0], _T("IW")) == 0) {
453 my_printf(p->osd, _T("%02X\n"), target->read_debug_io16(my_hexatoi(target, params[1])) & 0xffff);
455 my_printf(p->osd, _T("invalid parameter number\n"));
457 } else if(_tcsicmp(params[0], _T("ID")) == 0) {
459 my_printf(p->osd, _T("%02X\n"), target->read_debug_io32(my_hexatoi(target, params[1])));
461 my_printf(p->osd, _T("invalid parameter number\n"));
463 } else if(_tcsicmp(params[0], _T("O")) == 0 || _tcsicmp(params[0], _T("OB")) == 0) {
465 target->write_debug_io8(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]) & 0xff);
467 my_printf(p->osd, _T("invalid parameter number\n"));
469 } else if(_tcsicmp(params[0], _T("OW")) == 0) {
471 target->write_debug_io16(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]) & 0xffff);
473 my_printf(p->osd, _T("invalid parameter number\n"));
475 } else if(_tcsicmp(params[0], _T("OD")) == 0) {
477 target->write_debug_io32(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]));
479 my_printf(p->osd, _T("invalid parameter number\n"));
481 } else if(_tcsicmp(params[0], _T("R")) == 0) {
483 target->get_debug_regs_info(buffer, 1024);
484 my_printf(p->osd, _T("%s\n"), buffer);
485 } else if(num == 3) {
486 if(!target->write_debug_reg(params[1], my_hexatoi(target, params[2]))) {
487 my_printf(p->osd, _T("unknown register %s\n"), params[1]);
490 my_printf(p->osd, _T("invalid parameter number\n"));
492 } else if(_tcsicmp(params[0], _T("S")) == 0) {
494 uint32_t start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
495 uint32_t end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
497 for(int i = 3, j = 0; i < num; i++, j++) {
498 list[j] = my_hexatoi(target, params[i]);
500 for(uint64_t addr = start_addr; addr <= end_addr; addr++) {
502 for(int i = 3, j = 0; i < num; i++, j++) {
503 if(target->read_debug_data8((uint32_t)((addr + j) & target->get_debug_data_addr_mask())) != list[j]) {
509 my_printf(p->osd, _T("%s\n"), my_get_value_and_symbol(target, _T("%08X"), (uint32_t)addr));
513 my_printf(p->osd, _T("invalid parameter number\n"));
515 } else if(_tcsicmp(params[0], _T("U")) == 0) {
518 dasm_addr = my_hexatoi(target, params[1]) & target->get_debug_prog_addr_mask();
521 uint32_t end_addr = my_hexatoi(target, params[2]) & target->get_debug_prog_addr_mask();
522 while(dasm_addr <= end_addr) {
523 const _TCHAR *name = my_get_symbol(target, dasm_addr & target->get_debug_prog_addr_mask());
524 int len = target->debug_dasm(dasm_addr & target->get_debug_prog_addr_mask(), buffer, 1024);
526 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
527 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
528 my_printf(p->osd, _T("%s:\n"), name);
529 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
531 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
532 for(int i = 0; i < len; i++) {
533 my_printf(p->osd, _T("%02X"), target->read_debug_data8((dasm_addr + i) & target->get_debug_prog_addr_mask()));
535 for(int i = len; i < 8; i++) {
536 my_printf(p->osd, _T(" "));
538 my_printf(p->osd, _T(" %s\n"), buffer);
542 for(int i = 0; i < 16; i++) {
543 const _TCHAR *name = my_get_symbol(target, dasm_addr & target->get_debug_prog_addr_mask());
544 int len = target->debug_dasm(dasm_addr & target->get_debug_prog_addr_mask(), buffer, 1024);
546 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
547 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
548 my_printf(p->osd, _T("%s:\n"), name);
549 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
551 my_printf(p->osd, _T("%08X "), dasm_addr & target->get_debug_prog_addr_mask());
552 for(int i = 0; i < len; i++) {
553 my_printf(p->osd, _T("%02X"), target->read_debug_data8((dasm_addr + i) & target->get_debug_prog_addr_mask()));
555 for(int i = len; i < 8; i++) {
556 my_printf(p->osd, _T(" "));
558 my_printf(p->osd, _T(" %s\n"), buffer);
562 prev_command[1] = _T('\0'); // remove parameters to disassemble continuously
564 my_printf(p->osd, _T("invalid parameter number\n"));
566 } else if(_tcsicmp(params[0], _T("UT")) == 0) {
567 if(target_debugger == NULL) {
568 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
569 } else if(num <= 3) {
572 steps = min((int)my_hexatoi(target, params[1]), MAX_CPU_TRACE);
574 for(int i = MAX_CPU_TRACE - steps; i < MAX_CPU_TRACE; i++) {
575 int index = (target_debugger->cpu_trace_ptr + i) & (MAX_CPU_TRACE - 1);
576 if(!(target_debugger->cpu_trace[index] & ~target->get_debug_prog_addr_mask())) {
577 const _TCHAR *name = my_get_symbol(target, target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
578 int len = target->debug_dasm(target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask(), buffer, 1024);
580 my_printf(p->osd, _T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
581 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
582 my_printf(p->osd, _T("%s:\n"), name);
583 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
585 my_printf(p->osd, _T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
586 for(int i = 0; i < len; i++) {
587 my_printf(p->osd, _T("%02X"), target->read_debug_data8((target_debugger->cpu_trace[index] + i) & target->get_debug_prog_addr_mask()));
589 for(int i = len; i < 8; i++) {
590 my_printf(p->osd, _T(" "));
592 my_printf(p->osd, _T(" %s\n"), buffer);
596 my_printf(p->osd, _T("invalid parameter number\n"));
598 } else if(_tcsicmp(params[0], _T("H")) == 0) {
600 uint32_t l = my_hexatoi(target, params[1]);
601 uint32_t r = my_hexatoi(target, params[2]);
602 my_printf(p->osd, _T("%08X %08X\n"), l + r, l - r);
604 my_printf(p->osd, _T("invalid parameter number\n"));
606 } else if(_tcsicmp(params[0], _T("N")) == 0) {
607 if(num >= 2 && params[1][0] == _T('\"')) {
608 my_tcscpy_s(buffer, 1024, prev_command);
609 if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
610 my_tcscpy_s(debugger->file_path, _MAX_PATH, my_absolute_path(token));
612 my_printf(p->osd, _T("invalid parameter\n"));
614 } else if(num == 2) {
615 my_tcscpy_s(debugger->file_path, _MAX_PATH, my_absolute_path(params[1]));
617 my_printf(p->osd, _T("invalid parameter number\n"));
619 } else if(_tcsicmp(params[0], _T("L")) == 0) {
620 FILEIO* fio = new FILEIO();
621 if(check_file_extension(debugger->file_path, _T(".sym"))) {
622 if(target_debugger == NULL) {
623 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
624 } else if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
625 target_debugger->release_symbols();
627 while(fio->Fgetts(line, array_length(line)) != NULL) {
629 _TCHAR *addr = my_tcstok_s(line, _T("\t #$*,;"), &next);
630 while(addr != NULL) {
631 if(_tcslen(addr) > 0) {
632 _TCHAR *name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
633 while(name != NULL) {
634 while(_tcslen(name) > 0 && (name[_tcslen(name) - 1] == 0x0d || name[_tcslen(name) - 1] == 0x0a)) {
635 name[_tcslen(name) - 1] = _T('\0');
637 if(_tcslen(name) > 0) {
638 target_debugger->add_symbol(my_hexatoi(NULL, addr), name);
641 name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
644 addr = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
649 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
651 } else if(check_file_extension(debugger->file_path, _T(".hex"))) {
652 if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
653 uint32_t start_addr = 0, linear = 0, segment = 0;
655 start_addr = my_hexatoi(target, params[1]);
658 while(fio->Fgets(line, sizeof(line)) != NULL) {
659 if(line[0] != ':') continue;
660 int type = my_hexatob(line + 7);
662 uint32_t bytes = my_hexatob(line + 1);
663 uint32_t addr = my_hexatow(line + 3) + start_addr + linear + segment;
664 for(uint32_t i = 0; i < bytes; i++) {
665 target->write_debug_data8((addr + i) & target->get_debug_data_addr_mask(), my_hexatob(line + 9 + 2 * i));
667 } else if(type == 0x01) {
669 } else if(type == 0x02) {
670 segment = my_hexatow(line + 9) << 4;
672 } else if(type == 0x04) {
673 linear = my_hexatow(line + 9) << 16;
679 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
682 if(fio->Fopen(debugger->file_path, FILEIO_READ_BINARY)) {
683 uint32_t start_addr = 0x100, end_addr = target->get_debug_data_addr_mask();
685 start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
688 end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
690 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
691 int data = fio->Fgetc();
695 target->write_debug_data8(addr & target->get_debug_data_addr_mask(), data);
699 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
703 } else if(_tcsicmp(params[0], _T("W")) == 0) {
705 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();
706 FILEIO* fio = new FILEIO();
707 if(check_file_extension(debugger->file_path, _T(".hex"))) {
708 // write intel hex format file
709 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_ASCII)) {
710 uint32_t addr = start_addr;
711 while(addr <= end_addr) {
712 uint32_t len = min(end_addr - addr + 1, (uint32_t)16);
713 uint32_t sum = len + ((addr >> 8) & 0xff) + (addr & 0xff) + 0x00;
714 fio->Fprintf(":%02X%04X%02X", len, addr & 0xffff, 0x00);
715 for(uint32_t i = 0; i < len; i++) {
716 uint8_t data = target->read_debug_data8((addr++) & target->get_debug_data_addr_mask());
718 fio->Fprintf("%02X", data);
720 fio->Fprintf("%02X\n", (0x100 - (sum & 0xff)) & 0xff);
722 fio->Fprintf(":00000001FF\n");
725 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
728 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_BINARY)) {
729 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
730 fio->Fputc(target->read_debug_data8(addr & target->get_debug_data_addr_mask()));
734 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
739 my_printf(p->osd, _T("invalid parameter number\n"));
741 } else if(_tcsicmp(params[0], _T("SC")) == 0) {
742 if(target_debugger == NULL) {
743 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
744 } else if(num == 1) {
745 target_debugger->release_symbols();
747 my_printf(p->osd, _T("invalid parameter number\n"));
749 } else if(_tcsicmp(params[0], _T("SL")) == 0) {
750 if(target_debugger == NULL) {
751 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
752 } else if(num == 1) {
753 for(symbol_t* symbol = debugger->first_symbol; symbol; symbol = symbol->next_symbol) {
754 my_printf(p->osd, _T("%08X %s\n"), symbol->addr, symbol->name);
757 my_printf(p->osd, _T("invalid parameter number\n"));
759 } else if(_tcsicmp(params[0], _T( "BP")) == 0 || _tcsicmp(params[0], _T("RBP")) == 0 || _tcsicmp(params[0], _T("WBP")) == 0 ||
760 _tcsicmp(params[0], _T( "CP")) == 0 || _tcsicmp(params[0], _T("RCP")) == 0 || _tcsicmp(params[0], _T("WCP")) == 0) {
761 break_point_t *bp = get_break_point(debugger, params[0]);
763 uint32_t addr = my_hexatoi(cpu, params[1]);
765 for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
766 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == cpu->get_debug_prog_addr_mask())) {
767 bp->table[i].addr = addr;
768 bp->table[i].mask = cpu->get_debug_prog_addr_mask();
769 bp->table[i].status = 1;
770 bp->table[i].check_point = (params[0][0] == 'C' || params[0][0] == 'c' || params[0][1] == 'C' || params[0][1] == 'c');
775 my_printf(p->osd, _T("too many break points\n"));
778 my_printf(p->osd, _T("invalid parameter number\n"));
780 } else if(_tcsicmp(params[0], _T("IBP")) == 0 || _tcsicmp(params[0], _T("OBP")) == 0 ||
781 _tcsicmp(params[0], _T("ICP")) == 0 || _tcsicmp(params[0], _T("OCP")) == 0) {
782 break_point_t *bp = get_break_point(debugger, params[0]);
783 if(num == 2 || num == 3) {
784 uint32_t addr = my_hexatoi(cpu, params[1]), mask = 0xff;
786 mask = my_hexatoi(cpu, params[2]);
789 for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
790 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == mask)) {
791 bp->table[i].addr = addr;
792 bp->table[i].mask = mask;
793 bp->table[i].status = 1;
794 bp->table[i].check_point = (params[0][1] == 'C' || params[0][1] == 'c');
799 my_printf(p->osd, _T("too many break points\n"));
802 my_printf(p->osd, _T("invalid parameter number\n"));
804 } 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) {
805 break_point_t *bp = get_break_point(debugger, params[0]);
806 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
807 memset(bp->table, 0, sizeof(bp->table));
808 } else if(num >= 2) {
809 for(int i = 1; i < num; i++) {
810 int index = my_hexatoi(cpu, params[i]);
811 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
812 my_printf(p->osd, _T("invalid index %x\n"), index);
814 bp->table[index - 1].addr = bp->table[index - 1].mask = 0;
815 bp->table[index - 1].status = 0;
819 my_printf(p->osd, _T("invalid parameter number\n"));
821 } 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 ||
822 _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) {
823 break_point_t *bp = get_break_point(debugger, params[0]);
824 bool enabled = (params[0][1] == _T('E') || params[0][1] == _T('e') || params[0][2] == _T('E') || params[0][2] == _T('e'));
825 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
826 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
827 if(bp->table[i].status != 0) {
828 bp->table[i].status = enabled ? 1 : -1;
831 } else if(num >= 2) {
832 for(int i = 1; i < num; i++) {
833 int index = my_hexatoi(cpu, params[i]);
834 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
835 my_printf(p->osd, _T("invalid index %x\n"), index);
836 } else if(bp->table[index - 1].status == 0) {
837 my_printf(p->osd, _T("break point %x is null\n"), index);
839 bp->table[index - 1].status = enabled ? 1 : -1;
843 my_printf(p->osd, _T("invalid parameter number\n"));
845 } else if(_tcsicmp(params[0], _T("BL")) == 0 || _tcsicmp(params[0], _T("RBL")) == 0 || _tcsicmp(params[0], _T("WBL")) == 0) {
847 break_point_t *bp = get_break_point(debugger, params[0]);
848 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
849 if(bp->table[i].status) {
850 my_printf(p->osd, _T("%d %c %s %s\n"), i + 1,
851 bp->table[i].status == 1 ? _T('e') : _T('d'),
852 my_get_value_and_symbol(cpu, _T("%08X"), bp->table[i].addr),
853 bp->table[i].check_point ? "checkpoint" : "");
857 my_printf(p->osd, _T("invalid parameter number\n"));
859 } else if(_tcsicmp(params[0], _T("IBL")) == 0 || _tcsicmp(params[0], _T("OBL")) == 0) {
861 break_point_t *bp = get_break_point(debugger, params[0]);
862 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
863 if(bp->table[i].status) {
864 my_printf(p->osd, _T("%d %c %s %08X %s\n"), i + 1,
865 bp->table[i].status == 1 ? _T('e') : _T('d'),
866 my_get_value_and_symbol(cpu, _T("%08X"), bp->table[i].addr),
868 bp->table[i].check_point ? "checkpoint" : "");
872 my_printf(p->osd, _T("invalid parameter number\n"));
874 } else if(_tcsicmp(params[0], _T("G")) == 0 || _tcsicmp(params[0], _T("P")) == 0) {
875 if(num == 1 || num == 2) {
876 bool break_points_stored = false;
877 if(_tcsicmp(params[0], _T("P")) == 0) {
878 debugger->store_break_points();
879 debugger->bp.table[0].addr = (cpu->get_next_pc() + cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024)) & cpu->get_debug_prog_addr_mask();
880 debugger->bp.table[0].mask = cpu->get_debug_prog_addr_mask();
881 debugger->bp.table[0].status = 1;
882 debugger->bp.table[0].check_point = false;
883 break_points_stored = true;
884 } else if(num >= 2) {
885 debugger->store_break_points();
886 debugger->bp.table[0].addr = my_hexatoi(cpu, params[1]) & cpu->get_debug_prog_addr_mask();
887 debugger->bp.table[0].mask = cpu->get_debug_prog_addr_mask();
888 debugger->bp.table[0].status = 1;
889 debugger->bp.table[0].check_point = false;
890 break_points_stored = true;
893 debugger->now_going = true;
894 debugger->now_suspended = false;
895 #if defined(_MSC_VER)
896 while(!p->request_terminate && !debugger->now_suspended) {
897 if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) {
902 #elif defined(OSD_QT)
903 while(!p->request_terminate && !debugger->now_suspended) {
904 if(p->osd->console_input_string() != NULL && p->osd->is_console_active()) {
905 p->osd->clear_console_input_string();
912 debugger->now_going = false;
914 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
915 if((wait_count++) == 100) {
916 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
917 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
922 dasm_addr = cpu->get_next_pc();
925 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
926 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
927 my_printf(p->osd, _T("done\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer);
929 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
930 cpu->get_debug_regs_info(buffer, 1024);
931 my_printf(p->osd, _T("%s\n"), buffer);
934 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
935 if(target->debug_dasm(target->get_next_pc(), buffer, 1024) != 0) {
936 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(target, _T("%08X"), target->get_next_pc()), buffer);
938 target->get_debug_regs_info(buffer, 1024);
939 my_printf(p->osd, _T("%s\n"), buffer);
942 if(debugger->hit()) {
943 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
944 if(debugger->bp.hit) {
945 if(_tcsicmp(params[0], _T("G")) == 0) {
946 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
948 debugger->bp.hit = false;
949 if(debugger->bp.restart) goto RESTART_GO;
950 } else if(debugger->rbp.hit) {
951 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()),
952 my_get_value_and_symbol(cpu, _T("%08X"), debugger->rbp.hit_addr),
953 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
954 debugger->rbp.hit = false;
955 if(debugger->rbp.restart) goto RESTART_GO;
956 } else if(debugger->wbp.hit) {
957 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()),
958 my_get_value_and_symbol(cpu, _T("%08X"), debugger->wbp.hit_addr),
959 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
960 debugger->wbp.hit = false;
961 if(debugger->wbp.restart) goto RESTART_GO;
962 } else if(debugger->ibp.hit) {
963 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()),
964 my_get_value_and_symbol(cpu, _T("%08X"), debugger->ibp.hit_addr),
965 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
966 debugger->ibp.hit = false;
967 if(debugger->ibp.restart) goto RESTART_GO;
968 } else if(debugger->obp.hit) {
969 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()),
970 my_get_value_and_symbol(cpu, _T("%08X"), debugger->obp.hit_addr),
971 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
972 debugger->obp.hit = false;
973 if(debugger->obp.restart) goto RESTART_GO;
976 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
977 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()));
979 if(break_points_stored) {
980 debugger->restore_break_points();
982 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
983 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
984 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
985 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
987 my_printf(p->osd, _T("invalid parameter number\n"));
989 } else if(_tcsicmp(params[0], _T("T")) == 0) {
990 if(num == 1 || num == 2) {
993 steps = my_hexatoi(cpu, params[1]);
995 for(int i = 0; i < steps; i++) {
996 debugger->now_going = false;
997 debugger->now_suspended = false;
999 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
1000 if((wait_count++) == 100) {
1001 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1002 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
1007 dasm_addr = cpu->get_next_pc();
1010 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1011 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
1012 my_printf(p->osd, _T("done\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer);
1014 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1015 cpu->get_debug_regs_info(buffer, 1024);
1016 my_printf(p->osd, _T("%s\n"), buffer);
1019 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
1020 if(target->debug_dasm(target->get_next_pc(), buffer, 1024) != 0) {
1021 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(target, _T("%08X"), target->get_next_pc()), buffer);
1023 target->get_debug_regs_info(buffer, 1024);
1024 my_printf(p->osd, _T("%s\n"), buffer);
1027 if(debugger->hit()) {
1028 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1029 if(debugger->bp.hit) {
1030 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
1031 debugger->bp.hit = false;
1032 if(!debugger->bp.restart) break;
1033 } else if(debugger->rbp.hit) {
1034 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()),
1035 my_get_value_and_symbol(cpu, _T("%08X"), debugger->rbp.hit_addr),
1036 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1037 debugger->rbp.hit = false;
1038 if(!debugger->rbp.restart) break;
1039 } else if(debugger->wbp.hit) {
1040 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()),
1041 my_get_value_and_symbol(cpu, _T("%08X"), debugger->wbp.hit_addr),
1042 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1043 debugger->wbp.hit = false;
1044 if(!debugger->wbp.restart) break;
1045 } else if(debugger->ibp.hit) {
1046 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()),
1047 my_get_value_and_symbol(cpu, _T("%08X"), debugger->ibp.hit_addr),
1048 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1049 debugger->ibp.hit = false;
1050 if(!debugger->ibp.restart) break;
1051 } else if(debugger->obp.hit) {
1052 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()),
1053 my_get_value_and_symbol(cpu, _T("%08X"), debugger->obp.hit_addr),
1054 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1055 debugger->obp.hit = false;
1056 if(!debugger->obp.restart) break;
1058 } else if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) {
1062 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1063 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
1064 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
1065 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1067 my_printf(p->osd, _T("invalid parameter number\n"));
1069 } else if(_tcsicmp(params[0], _T("Q")) == 0) {
1070 p->osd->close_debugger_console();
1072 } else if(_tcsicmp(params[0], _T(">")) == 0) {
1074 if(logfile != NULL) {
1075 if(logfile->IsOpened()) {
1081 logfile = new FILEIO();
1082 logfile->Fopen(my_absolute_path(params[1]), FILEIO_WRITE_ASCII);
1084 my_printf(p->osd, _T("invalid parameter number\n"));
1086 } else if(_tcsicmp(params[0], _T("<")) == 0) {
1088 if(cmdfile != NULL) {
1089 if(cmdfile->IsOpened()) {
1093 cmdfile = new FILEIO();
1095 if(!cmdfile->Fopen(my_absolute_path(params[1]), FILEIO_READ_ASCII)) {
1098 my_printf(p->osd, _T("can't open %s\n"), params[1]);
1101 my_printf(p->osd, _T("invalid parameter number\n"));
1103 } else if(_tcsicmp(params[0], _T("!")) == 0) {
1105 my_printf(p->osd, _T("invalid parameter number\n"));
1106 } else if(_tcsicmp(params[1], _T("RESET")) == 0) {
1109 } else if(num == 3) {
1110 if(_tcsicmp(params[2], _T("ALL")) == 0) {
1112 } if(_tcsicmp(params[2], _T("CPU")) == 0) {
1114 } if(_tcsicmp(params[2], _T("TARGET")) == 0) {
1117 my_printf(p->osd, _T("unknown device %s\n"), params[2]);
1120 my_printf(p->osd, _T("invalid parameter number\n"));
1122 } else if(_tcsicmp(params[1], _T("KEY")) == 0) {
1123 if(num == 3 || num == 4) {
1124 int code = my_hexatoi(target, params[2]) & 0xff, msec = 100;
1126 msec = my_hexatoi(target, params[3]);
1128 #ifdef SUPPORT_VARIABLE_TIMING
1129 int frames = (int)(p->vm->get_frame_rate() * (double)msec / 1000.0 + 0.5);
1131 int frames = (int)(FRAMES_PER_SEC * (double)msec / 1000.0 + 0.5);
1133 p->osd->get_key_buffer()[code] &= 0x7f;
1134 p->osd->get_key_buffer()[code] |= max(1, min(127, frames));
1135 #ifdef NOTIFY_KEY_DOWN
1136 p->vm->key_down(code, false);
1139 my_printf(p->osd, _T("invalid parameter number\n"));
1141 } else if(_tcsicmp(params[1], _T("DEVICE")) == 0) {
1143 for(DEVICE* device = p->vm->first_device; device; device = device->next_device) {
1144 my_printf(p->osd, _T("ID=%02X %s"), device->this_device_id, device->this_device_name);
1145 if(device == target) {
1146 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1147 my_printf(p->osd, _T(" <=== target"));
1148 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1150 my_printf(p->osd, _T("\n"));
1152 } else if(num == 3) {
1153 DEVICE *device = NULL;
1154 if(_tcsicmp(params[2], _T("CPU")) == 0) {
1157 device = p->vm->get_device(my_hexatoi(NULL, params[2]));
1159 if(device != NULL) {
1160 if(device != target) {
1162 target_debugger = (DEBUGGER *)target->get_debugger();
1164 dasm_addr = target->get_next_pc();
1167 my_printf(p->osd, _T("device not found\n"));
1170 my_printf(p->osd, _T("invalid parameter number\n"));
1172 } else if(_tcsicmp(params[1], _T("CPU")) == 0) {
1174 for(DEVICE* device = p->vm->first_device; device; device = device->next_device) {
1175 if(device->get_debugger() != NULL) {
1176 my_printf(p->osd, _T("ID=%02X %s"), device->this_device_id, device->this_device_name);
1178 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1179 my_printf(p->osd, _T(" <=== target"));
1180 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1182 my_printf(p->osd, _T("\n"));
1185 } else if(num == 3) {
1186 DEVICE *device = p->vm->get_device(my_hexatoi(NULL, params[2]));
1187 if(device != NULL && device->get_debugger() != NULL) {
1189 DEBUGGER *prev_debugger = debugger;
1191 debugger = (DEBUGGER *)cpu->get_debugger();
1192 debugger->now_going = false;
1193 debugger->now_debugging = true;
1194 prev_debugger->now_debugging = prev_debugger->now_going = prev_debugger->now_suspended = prev_debugger->now_waiting = false;
1196 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
1197 if((wait_count++) == 100) {
1198 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1199 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
1204 dasm_addr = cpu->get_next_pc();
1206 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1207 cpu->get_debug_regs_info(buffer, 1024);
1208 my_printf(p->osd, _T("%s\n"), buffer);
1210 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1211 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
1213 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1214 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
1215 my_printf(p->osd, _T("next\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
1216 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1219 my_printf(p->osd, _T("device not found\n"));
1222 my_printf(p->osd, _T("invalid parameter number\n"));
1225 my_printf(p->osd, _T("unknown command ! %s\n"), params[1]);
1227 } else if(_tcsicmp(params[0], _T("?")) == 0) {
1228 my_printf(p->osd, _T("D [<range>] - dump memory\n"));
1229 my_printf(p->osd, _T("E[{B,W,D}] <address> <list> - edit memory (byte,word,dword)\n"));
1230 my_printf(p->osd, _T("EA <address> \"<value>\" - edit memory (ascii)\n"));
1231 my_printf(p->osd, _T("I[{B,W,D}] <port> - input port (byte,word,dword)\n"));
1232 my_printf(p->osd, _T("O[{B,W,D}] <port> <value> - output port (byte,word,dword)\n"));
1233 my_printf(p->osd, _T("R - show register(s)\n"));
1234 my_printf(p->osd, _T("R <reg> <value> - edit register\n"));
1235 my_printf(p->osd, _T("S <range> <list> - search\n"));
1236 my_printf(p->osd, _T("U [<range>] - unassemble\n"));
1237 my_printf(p->osd, _T("UT [<steps>] - unassemble trace\n"));
1239 my_printf(p->osd, _T("H <value> <value> - hexadd\n"));
1240 my_printf(p->osd, _T("N <filename> - name\n"));
1241 my_printf(p->osd, _T("L [<range>] - load binary/hex/symbol file\n"));
1242 my_printf(p->osd, _T("W <range> - write binary/hex file\n"));
1244 my_printf(p->osd, _T("SC - clear symbol(s)\n"));
1245 my_printf(p->osd, _T("SL - list symbol(s)\n"));
1247 my_printf(p->osd, _T("BP <address> - set breakpoint\n"));
1248 my_printf(p->osd, _T("{R,W}BP <address> - set breakpoint (break at memory access)\n"));
1249 my_printf(p->osd, _T("{I,O}BP <port> [<mask>] - set breakpoint (break at i/o access)\n"));
1250 my_printf(p->osd, _T("[{R,W,I,O}]B{C,D,E} {*,<list>} - clear/disable/enable breakpoint(s)\n"));
1251 my_printf(p->osd, _T("[{R,W,I,O}]BL - list breakpoint(s)\n"));
1252 my_printf(p->osd, _T("[{R,W,I,O}]CP <address/port> [<mask>] - set checkpoint (don't break)\n"));
1254 my_printf(p->osd, _T("G - go (press esc key to break)\n"));
1255 my_printf(p->osd, _T("G <address> - go and break at address\n"));
1256 my_printf(p->osd, _T("P - trace one opcode (step over)\n"));
1257 my_printf(p->osd, _T("T [<count>] - trace (step in)\n"));
1258 my_printf(p->osd, _T("Q - quit\n"));
1260 my_printf(p->osd, _T("> <filename> - output logfile\n"));
1261 my_printf(p->osd, _T("< <filename> - input commands from file\n"));
1263 my_printf(p->osd, _T("! reset [all/cpu/target] - reset\n"));
1264 my_printf(p->osd, _T("! key <code> [<msec>] - press key\n"));
1265 my_printf(p->osd, _T("! device - enumerate device\n"));
1266 my_printf(p->osd, _T("! device <id/cpu> - select target device\n"));
1267 my_printf(p->osd, _T("! cpu - enumerate cpu\n"));
1268 my_printf(p->osd, _T("! cpu <id> - select target cpu\n"));
1270 my_printf(p->osd, _T("<value> - hexa, decimal(%%d), ascii('a')\n"));
1272 my_printf(p->osd, _T("unknown command %s\n"), params[0]);
1279 debugger->now_debugging = debugger->now_going = debugger->now_suspended = debugger->now_waiting = false;
1284 if(logfile != NULL) {
1285 if(logfile->IsOpened()) {
1291 if(cmdfile != NULL) {
1292 if(cmdfile->IsOpened()) {
1300 p->osd->close_console();
1307 //pthread_exit(NULL);
1312 void EMU::initialize_debugger()
1314 now_debugging = false;
1318 void EMU::release_debugger()
1323 void EMU::open_debugger(int cpu_index)
1325 if(!(now_debugging && debugger_thread_param.cpu_index == cpu_index)) {
1327 if(vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL) {
1328 // debugger_thread_param.emu = this;
1329 debugger_thread_param.osd = osd;
1330 debugger_thread_param.vm = vm;
1331 debugger_thread_param.cpu_index = cpu_index;
1332 debugger_thread_param.request_terminate = false;
1334 if((hDebuggerThread = (HANDLE)_beginthreadex(NULL, 0, debugger_thread, &debugger_thread_param, 0, NULL)) != (HANDLE)0) {
1336 //#elif !defined(_USE_QT)
1337 if(pthread_create(&debugger_thread_id, NULL, debugger_thread, &debugger_thread_param) == 0) {
1341 stop_record_sound();
1342 stop_record_video();
1343 now_debugging = true;
1349 void EMU::close_debugger()
1352 if(debugger_thread_param.running) {
1353 debugger_thread_param.request_terminate = true;
1356 WaitForSingleObject(hDebuggerThread, INFINITE);
1357 CloseHandle(hDebuggerThread);
1358 //#elif !defined(_USE_QT)
1360 pthread_join(debugger_thread_id, NULL);
1362 // volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param);
1363 // p->running = false;
1365 //if(logfile != NULL && logfile->IsOpened()) {
1366 // logfile->Fclose();
1368 // initialize logfile
1371 now_debugging = false;
1375 bool EMU::is_debugger_enabled(int cpu_index)
1377 return (vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL);