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(symbol_t *first_symbol, const _TCHAR *str)
67 if(str == NULL || _tcslen(str) == 0) {
70 my_tcscpy_s(tmp, 1024, str);
72 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
73 if(_tcsicmp(symbol->name, str) == 0) {
77 if(_tcslen(tmp) == 3 && tmp[0] == _T('\'') && tmp[2] == _T('\'')) {
80 } else if((s = _tcsstr(tmp, _T(":"))) != NULL) {
83 return (my_hexatoi(first_symbol, tmp) << 4) + my_hexatoi(first_symbol, s + 1);
84 } else if(tmp[0] == _T('%')) {
86 #if defined(__MINGW32__)
89 return _tstoi(tmp + 1);
92 return _tcstoul(tmp, NULL, 16);
95 uint8_t my_hexatob(char *value)
101 return (uint8_t)strtoul(tmp, NULL, 16);
104 uint16_t my_hexatow(char *value)
112 return (uint16_t)strtoul(tmp, NULL, 16);
115 break_point_t *get_break_point(DEBUGGER *debugger, const _TCHAR *command)
117 if(command[0] == _T('B') || command[0] == _T('b')) {
118 return &debugger->bp;
119 } else if(command[0] == _T('R') || command[0] == _T('r')) {
120 return &debugger->rbp;
121 } else if(command[0] == _T('W') || command[0] == _T('w')) {
122 return &debugger->wbp;
123 } else if(command[0] == _T('I') || command[0] == _T('i')) {
124 return &debugger->ibp;
125 } else if(command[0] == _T('O') || command[0] == _T('o')) {
126 return &debugger->obp;
132 unsigned __stdcall debugger_thread(void *lpx)
134 void* debugger_thread(void *lpx)
137 volatile debugger_thread_t *p = (debugger_thread_t *)lpx;
140 // initialize console
142 bool cp932 = (p->osd->get_console_code_page() == 932);
144 p->osd->open_console((_TCHAR *)create_string(_T("Debugger - %s"), _T(DEVICE_NAME)));
147 DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
148 DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
150 debugger->now_going = false;
151 debugger->now_debugging = true;
153 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
154 if((wait_count++) == 100) {
155 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
156 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
160 uint32_t prog_addr_mask = cpu->get_debug_prog_addr_mask();
161 uint32_t data_addr_mask = cpu->get_debug_data_addr_mask();
162 uint32_t dump_addr = 0;
163 uint32_t dasm_addr = cpu->get_next_pc();
165 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
166 cpu->get_debug_regs_info(buffer, 1024);
167 my_printf(p->osd, _T("%s\n"), buffer);
169 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
170 my_printf(p->osd, _T("breaked at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()));
172 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
173 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
174 my_printf(p->osd, _T("next\t%s %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()), buffer);
175 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
181 _TCHAR command[MAX_COMMAND_LENGTH + 1];
182 _TCHAR prev_command[MAX_COMMAND_LENGTH + 1];
184 memset(prev_command, 0, sizeof(prev_command));
186 while(!p->request_terminate) {
187 my_printf(p->osd, _T("- "));
193 bool enter_done = false;
195 while(!p->request_terminate && !enter_done) {
196 if(cmdfile != NULL && cmdfile->IsOpened()) {
197 if(cmdfile->Fgetts(command, array_length(command)) != NULL) {
198 while(_tcslen(command) > 0 && (command[_tcslen(command) - 1] == 0x0d || command[_tcslen(command) - 1] == 0x0a)) {
199 command[_tcslen(command) - 1] = _T('\0');
201 if(_tcslen(command) > 0) {
202 my_printf(p->osd, _T("%s\n"), command);
211 memset(ir, 0, sizeof(ir));
212 int count = p->osd->read_console_input(ir, 16);
214 for(int i = 0; i < count; i++) {
218 my_putch(p->osd, 0x08);
219 my_putch(p->osd, _T(' '));
220 my_putch(p->osd, 0x08);
222 } else if(ir[i] == 0x0d || ir[i] == 0x0a) {
223 if(enter_ptr == 0 && prev_command[0] != _T('\0')) {
224 memcpy(command, prev_command, sizeof(command));
225 my_printf(p->osd, _T("%s\n"), command);
228 } else if(enter_ptr > 0) {
229 command[enter_ptr] = _T('\0');
230 memcpy(prev_command, command, sizeof(command));
231 memcpy(debugger->history[debugger->history_ptr], command, sizeof(command));
232 if (++debugger->history_ptr >= MAX_COMMAND_HISTORY) {
233 debugger->history_ptr = 0;
235 my_printf(p->osd, _T("\n"));
239 } else if(ir[i] == 0x1b && ir[i + 1] == 0x5b) {
240 if(ir[i + 2] == _T('A') || ir[i + 2] == _T('B')) {
241 int history_ptr_stored = history_ptr;
242 if(ir[i + 2] == _T('A')) {
243 if(++history_ptr >= MAX_COMMAND_HISTORY) {
244 history_ptr = MAX_COMMAND_HISTORY;
247 if(--history_ptr < 0) {
251 int index = debugger->history_ptr - history_ptr;
253 index += MAX_COMMAND_HISTORY;
255 while(index >= MAX_COMMAND_HISTORY) {
256 index -= MAX_COMMAND_HISTORY;
258 if(debugger->history[index][0] != _T('\0')) {
259 for(int i = 0; i < enter_ptr; i++) {
260 my_putch(p->osd, 0x08);
261 my_putch(p->osd, _T(' '));
262 my_putch(p->osd, 0x08);
264 memcpy(command, debugger->history[index], sizeof(command));
265 my_printf(p->osd, _T("%s"), command);
266 enter_ptr = _tcslen(command);
268 history_ptr = history_ptr_stored;
271 i += 2; // skip 2 characters
272 } else if(ir[i] >= 0x20 && ir[i] <= 0x7e && enter_ptr < MAX_COMMAND_LENGTH && !(ir[i] == 0x20 && enter_ptr == 0)) {
273 command[enter_ptr++] = ir[i];
274 my_putch(p->osd, ir[i]);
282 if(!p->request_terminate && enter_done) {
283 _TCHAR *params[32], *token = NULL, *context = NULL;
286 if((token = my_tcstok_s(command, _T(" "), &context)) != NULL) {
287 params[num++] = token;
288 while(num < 32 && (token = my_tcstok_s(NULL, _T(" "), &context)) != NULL) {
289 params[num++] = token;
292 if(_tcsicmp(params[0], _T("D")) == 0) {
294 uint32_t start_addr = dump_addr;
296 start_addr = my_hexatoi(debugger->first_symbol, params[1]);
298 start_addr &= data_addr_mask;
300 uint32_t end_addr = start_addr + 8 * 16 - 1;
302 end_addr = my_hexatoi(debugger->first_symbol, params[2]);
304 end_addr &= data_addr_mask;
306 if(start_addr > end_addr) {
307 end_addr = data_addr_mask;
309 for(uint64_t addr = start_addr & ~0x0f; addr <= end_addr; addr++) {
310 if(addr > data_addr_mask) {
311 end_addr = data_addr_mask;
314 if((addr & 0x0f) == 0) {
315 my_printf(p->osd, _T("%08X "), addr & data_addr_mask);
316 memset(buffer, 0, sizeof(buffer));
318 if(addr < start_addr) {
319 my_printf(p->osd, _T(" "));
320 buffer[addr & 0x0f] = _T(' ');
322 uint32_t data = cpu->read_debug_data8(addr & data_addr_mask);
323 my_printf(p->osd, _T(" %02X"), data);
324 buffer[addr & 0x0f] = ((data >= 0x20 && data <= 0x7e) || (cp932 && data >= 0xa1 && data <= 0xdf)) ? data : _T('.');
326 if((addr & 0x0f) == 0x0f) {
327 my_printf(p->osd, _T(" %s\n"), buffer);
330 if((end_addr & 0x0f) != 0x0f) {
331 for(uint32_t addr = (end_addr & 0x0f) + 1; addr <= 0x0f; addr++) {
332 my_printf(p->osd, _T(" "));
334 my_printf(p->osd, _T(" %s\n"), buffer);
336 dump_addr = (end_addr + 1) & data_addr_mask;
337 prev_command[1] = _T('\0'); // remove parameters to dump continuously
339 my_printf(p->osd, _T("invalid parameter number\n"));
341 } else if(_tcsicmp(params[0], _T("E")) == 0 || _tcsicmp(params[0], _T("EB")) == 0) {
343 uint32_t addr = my_hexatoi(debugger->first_symbol, params[1]) & data_addr_mask;
344 for(int i = 2; i < num; i++) {
345 cpu->write_debug_data8(addr, my_hexatoi(debugger->first_symbol, params[i]) & 0xff);
346 addr = (addr + 1) & data_addr_mask;
349 my_printf(p->osd, _T("invalid parameter number\n"));
351 } else if(_tcsicmp(params[0], _T("EW")) == 0) {
353 uint32_t addr = my_hexatoi(debugger->first_symbol, params[1]) & data_addr_mask;
354 for(int i = 2; i < num; i++) {
355 cpu->write_debug_data16(addr, my_hexatoi(debugger->first_symbol, params[i]) & 0xffff);
356 addr = (addr + 2) & data_addr_mask;
359 my_printf(p->osd, _T("invalid parameter number\n"));
361 } else if(_tcsicmp(params[0], _T("ED")) == 0) {
363 uint32_t addr = my_hexatoi(debugger->first_symbol, params[1]) & data_addr_mask;
364 for(int i = 2; i < num; i++) {
365 cpu->write_debug_data32(addr, my_hexatoi(debugger->first_symbol, params[i]));
366 addr = (addr + 4) & data_addr_mask;
369 my_printf(p->osd, _T("invalid parameter number\n"));
371 } else if(_tcsicmp(params[0], _T("EA")) == 0) {
373 uint32_t addr = my_hexatoi(debugger->first_symbol, params[1]) & data_addr_mask;
374 my_tcscpy_s(buffer, 1024, prev_command);
375 if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
376 int len = _tcslen(token);
377 for(int i = 0; i < len; i++) {
378 cpu->write_debug_data8(addr, token[i] & 0xff);
379 addr = (addr + 1) & data_addr_mask;
382 my_printf(p->osd, _T("invalid parameter\n"));
385 my_printf(p->osd, _T("invalid parameter number\n"));
387 } else if(_tcsicmp(params[0], _T("I")) == 0 || _tcsicmp(params[0], _T("IB")) == 0) {
389 my_printf(p->osd, _T("%02X\n"), cpu->read_debug_io8(my_hexatoi(debugger->first_symbol, params[1])) & 0xff);
391 my_printf(p->osd, _T("invalid parameter number\n"));
393 } else if(_tcsicmp(params[0], _T("IW")) == 0) {
395 my_printf(p->osd, _T("%02X\n"), cpu->read_debug_io16(my_hexatoi(debugger->first_symbol, params[1])) & 0xffff);
397 my_printf(p->osd, _T("invalid parameter number\n"));
399 } else if(_tcsicmp(params[0], _T("ID")) == 0) {
401 my_printf(p->osd, _T("%02X\n"), cpu->read_debug_io32(my_hexatoi(debugger->first_symbol, params[1])));
403 my_printf(p->osd, _T("invalid parameter number\n"));
405 } else if(_tcsicmp(params[0], _T("O")) == 0 || _tcsicmp(params[0], _T("OB")) == 0) {
407 cpu->write_debug_io8(my_hexatoi(debugger->first_symbol, params[1]), my_hexatoi(debugger->first_symbol, params[2]) & 0xff);
409 my_printf(p->osd, _T("invalid parameter number\n"));
411 } else if(_tcsicmp(params[0], _T("OW")) == 0) {
413 cpu->write_debug_io16(my_hexatoi(debugger->first_symbol, params[1]), my_hexatoi(debugger->first_symbol, params[2]) & 0xffff);
415 my_printf(p->osd, _T("invalid parameter number\n"));
417 } else if(_tcsicmp(params[0], _T("OD")) == 0) {
419 cpu->write_debug_io32(my_hexatoi(debugger->first_symbol, params[1]), my_hexatoi(debugger->first_symbol, params[2]));
421 my_printf(p->osd, _T("invalid parameter number\n"));
423 } else if(_tcsicmp(params[0], _T("R")) == 0) {
425 cpu->get_debug_regs_info(buffer, 1024);
426 my_printf(p->osd, _T("%s\n"), buffer);
427 } else if(num == 3) {
428 if(!cpu->write_debug_reg(params[1], my_hexatoi(debugger->first_symbol, params[2]))) {
429 my_printf(p->osd, _T("unknown register %s\n"), params[1]);
432 my_printf(p->osd, _T("invalid parameter number\n"));
434 } else if(_tcsicmp(params[0], _T("S")) == 0) {
436 uint32_t start_addr = my_hexatoi(debugger->first_symbol, params[1]) & data_addr_mask;
437 uint32_t end_addr = my_hexatoi(debugger->first_symbol, params[2]) & data_addr_mask;
439 for(int i = 3, j = 0; i < num; i++, j++) {
440 list[j] = my_hexatoi(debugger->first_symbol, params[i]);
442 for(uint64_t addr = start_addr; addr <= end_addr; addr++) {
444 for(int i = 3, j = 0; i < num; i++, j++) {
445 if(cpu->read_debug_data8((addr + j) & data_addr_mask) != list[j]) {
451 my_printf(p->osd, _T("%s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), (uint32_t)addr));
455 my_printf(p->osd, _T("invalid parameter number\n"));
457 } else if(_tcsicmp(params[0], _T("U")) == 0) {
460 dasm_addr = my_hexatoi(debugger->first_symbol, params[1]) & prog_addr_mask;
463 uint32_t end_addr = my_hexatoi(debugger->first_symbol, params[2]) & prog_addr_mask;
464 while(dasm_addr <= end_addr) {
465 const _TCHAR *name = get_symbol(debugger->first_symbol, dasm_addr & prog_addr_mask);
466 int len = cpu->debug_dasm(dasm_addr & prog_addr_mask, buffer, 1024);
468 my_printf(p->osd, _T("%08X "), dasm_addr & prog_addr_mask);
469 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
470 my_printf(p->osd, _T("%s:\n"), name);
471 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
473 my_printf(p->osd, _T("%08X "), dasm_addr & prog_addr_mask);
474 for(int i = 0; i < len; i++) {
475 my_printf(p->osd, _T("%02X"), cpu->read_debug_data8((dasm_addr + i) & data_addr_mask));
477 for(int i = len; i < 8; i++) {
478 my_printf(p->osd, _T(" "));
480 my_printf(p->osd, _T(" %s\n"), buffer);
484 for(int i = 0; i < 16; i++) {
485 const _TCHAR *name = get_symbol(debugger->first_symbol, dasm_addr & prog_addr_mask);
486 int len = cpu->debug_dasm(dasm_addr & prog_addr_mask, buffer, 1024);
488 my_printf(p->osd, _T("%08X "), dasm_addr & prog_addr_mask);
489 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
490 my_printf(p->osd, _T("%s:\n"), name);
491 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
493 my_printf(p->osd, _T("%08X "), dasm_addr & prog_addr_mask);
494 for(int i = 0; i < len; i++) {
495 my_printf(p->osd, _T("%02X"), cpu->read_debug_data8((dasm_addr + i) & data_addr_mask));
497 for(int i = len; i < 8; i++) {
498 my_printf(p->osd, _T(" "));
500 my_printf(p->osd, _T(" %s\n"), buffer);
504 prev_command[1] = _T('\0'); // remove parameters to disassemble continuously
506 my_printf(p->osd, _T("invalid parameter number\n"));
508 } else if(_tcsicmp(params[0], _T("UT")) == 0) {
512 steps = min(my_hexatoi(debugger->first_symbol, params[1]), (uint32_t)MAX_CPU_TRACE);
514 for(int i = MAX_CPU_TRACE - steps; i < MAX_CPU_TRACE; i++) {
515 int index = (debugger->cpu_trace_ptr + i) & (MAX_CPU_TRACE - 1);
516 if(!(debugger->cpu_trace[index] & ~prog_addr_mask)) {
517 const _TCHAR *name = get_symbol(debugger->first_symbol, debugger->cpu_trace[index] & prog_addr_mask);
518 int len = cpu->debug_dasm(debugger->cpu_trace[index] & prog_addr_mask, buffer, 1024);
520 my_printf(p->osd, _T("%08X "), debugger->cpu_trace[index] & prog_addr_mask);
521 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
522 my_printf(p->osd, _T("%s:\n"), name);
523 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
525 my_printf(p->osd, _T("%08X "), debugger->cpu_trace[index] & prog_addr_mask);
526 for(int i = 0; i < len; i++) {
527 my_printf(p->osd, _T("%02X"), cpu->read_debug_data8((debugger->cpu_trace[index] + i) & data_addr_mask));
529 for(int i = len; i < 8; i++) {
530 my_printf(p->osd, _T(" "));
532 my_printf(p->osd, _T(" %s\n"), buffer);
536 my_printf(p->osd, _T("invalid parameter number\n"));
538 } else if(_tcsicmp(params[0], _T("H")) == 0) {
540 uint32_t l = my_hexatoi(debugger->first_symbol, params[1]);
541 uint32_t r = my_hexatoi(debugger->first_symbol, params[2]);
542 my_printf(p->osd, _T("%08X %08X\n"), l + r, l - r);
544 my_printf(p->osd, _T("invalid parameter number\n"));
546 } else if(_tcsicmp(params[0], _T("N")) == 0) {
547 if(num >= 2 && params[1][0] == _T('\"')) {
548 my_tcscpy_s(buffer, 1024, prev_command);
549 if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
550 my_tcscpy_s(debugger->file_path, _MAX_PATH, token);
552 my_printf(p->osd, _T("invalid parameter\n"));
554 } else if(num == 2) {
555 my_tcscpy_s(debugger->file_path, _MAX_PATH, params[1]);
557 my_printf(p->osd, _T("invalid parameter number\n"));
559 } else if(_tcsicmp(params[0], _T("L")) == 0) {
560 FILEIO* fio = new FILEIO();
561 if(check_file_extension(debugger->file_path, _T(".sym"))) {
562 if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
563 debugger->release_symbols();
565 while(fio->Fgetts(line, array_length(line)) != NULL) {
567 _TCHAR *addr = my_tcstok_s(line, _T("\t #$*,;"), &next);
568 while(addr != NULL) {
569 if(_tcslen(addr) > 0) {
570 _TCHAR *name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
571 while(name != NULL) {
572 while(_tcslen(name) > 0 && (name[_tcslen(name) - 1] == 0x0d || name[_tcslen(name) - 1] == 0x0a)) {
573 name[_tcslen(name) - 1] = _T('\0');
575 if(_tcslen(name) > 0) {
576 debugger->add_symbol(my_hexatoi(NULL, addr), name);
579 name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
582 addr = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
587 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
589 } else if(check_file_extension(debugger->file_path, _T(".hex"))) {
590 if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
591 uint32_t start_addr = 0, linear = 0, segment = 0;
593 start_addr = my_hexatoi(debugger->first_symbol, params[1]);
596 while(fio->Fgets(line, sizeof(line)) != NULL) {
597 if(line[0] != ':') continue;
598 int type = my_hexatob(line + 7);
600 uint32_t bytes = my_hexatob(line + 1);
601 uint32_t addr = my_hexatow(line + 3) + start_addr + linear + segment;
602 for(uint32_t i = 0; i < bytes; i++) {
603 cpu->write_debug_data8((addr + i) & data_addr_mask, my_hexatob(line + 9 + 2 * i));
605 } else if(type == 0x01) {
607 } else if(type == 0x02) {
608 segment = my_hexatow(line + 9) << 4;
610 } else if(type == 0x04) {
611 linear = my_hexatow(line + 9) << 16;
617 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
620 if(fio->Fopen(debugger->file_path, FILEIO_READ_BINARY)) {
621 uint32_t start_addr = 0x100, end_addr = data_addr_mask;
623 start_addr = my_hexatoi(debugger->first_symbol, params[1]) & data_addr_mask;
626 end_addr = my_hexatoi(debugger->first_symbol, params[2]) & data_addr_mask;
628 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
629 int data = fio->Fgetc();
633 cpu->write_debug_data8(addr & data_addr_mask, data);
637 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
641 } else if(_tcsicmp(params[0], _T("W")) == 0) {
643 uint32_t start_addr = my_hexatoi(debugger->first_symbol, params[1]) & data_addr_mask, end_addr = my_hexatoi(debugger->first_symbol, params[2]) & data_addr_mask;
644 FILEIO* fio = new FILEIO();
645 if(check_file_extension(debugger->file_path, _T(".hex"))) {
646 // write intel hex format file
647 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_ASCII)) {
648 uint32_t addr = start_addr;
649 while(addr <= end_addr) {
650 uint32_t len = min(end_addr - addr + 1, (uint32_t)16);
651 uint32_t sum = len + ((addr >> 8) & 0xff) + (addr & 0xff) + 0x00;
652 fio->Fprintf(":%02X%04X%02X", len, addr & 0xffff, 0x00);
653 for(uint32_t i = 0; i < len; i++) {
654 uint8_t data = cpu->read_debug_data8((addr++) & data_addr_mask);
656 fio->Fprintf("%02X", data);
658 fio->Fprintf("%02X\n", (0x100 - (sum & 0xff)) & 0xff);
660 fio->Fprintf(":00000001FF\n");
663 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
666 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_BINARY)) {
667 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
668 fio->Fputc(cpu->read_debug_data8(addr & data_addr_mask));
672 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
677 my_printf(p->osd, _T("invalid parameter number\n"));
679 } else if(_tcsicmp(params[0], _T("SC")) == 0) {
681 debugger->release_symbols();
683 my_printf(p->osd, _T("invalid parameter number\n"));
685 } else if(_tcsicmp(params[0], _T("SL")) == 0) {
687 for(symbol_t* symbol = debugger->first_symbol; symbol; symbol = symbol->next_symbol) {
688 my_printf(p->osd, _T("%08X %s\n"), symbol->addr, symbol->name);
691 my_printf(p->osd, _T("invalid parameter number\n"));
693 } else if(_tcsicmp(params[0], _T( "BP")) == 0 || _tcsicmp(params[0], _T("RBP")) == 0 || _tcsicmp(params[0], _T("WBP")) == 0) {
694 break_point_t *bp = get_break_point(debugger, params[0]);
696 uint32_t addr = my_hexatoi(debugger->first_symbol, params[1]);
698 for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
699 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == prog_addr_mask)) {
700 bp->table[i].addr = addr;
701 bp->table[i].mask = prog_addr_mask;
702 bp->table[i].status = 1;
707 my_printf(p->osd, _T("too many break points\n"));
710 my_printf(p->osd, _T("invalid parameter number\n"));
712 } else if(_tcsicmp(params[0], _T("IBP")) == 0 || _tcsicmp(params[0], _T("OBP")) == 0) {
713 break_point_t *bp = get_break_point(debugger, params[0]);
714 if(num == 2 || num == 3) {
715 uint32_t addr = my_hexatoi(debugger->first_symbol, params[1]), mask = 0xff;
717 mask = my_hexatoi(debugger->first_symbol, params[2]);
720 for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
721 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == mask)) {
722 bp->table[i].addr = addr;
723 bp->table[i].mask = mask;
724 bp->table[i].status = 1;
729 my_printf(p->osd, _T("too many break points\n"));
732 my_printf(p->osd, _T("invalid parameter number\n"));
734 } 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) {
735 break_point_t *bp = get_break_point(debugger, params[0]);
736 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
737 memset(bp->table, 0, sizeof(bp->table));
738 } else if(num >= 2) {
739 for(int i = 1; i < num; i++) {
740 int index = my_hexatoi(debugger->first_symbol, params[i]);
741 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
742 my_printf(p->osd, _T("invalid index %x\n"), index);
744 bp->table[index - 1].addr = bp->table[index - 1].mask = 0;
745 bp->table[index - 1].status = 0;
749 my_printf(p->osd, _T("invalid parameter number\n"));
751 } 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 ||
752 _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) {
753 break_point_t *bp = get_break_point(debugger, params[0]);
754 bool enabled = (params[0][1] == _T('E') || params[0][1] == _T('e') || params[0][2] == _T('E') || params[0][2] == _T('e'));
755 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
756 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
757 if(bp->table[i].status != 0) {
758 bp->table[i].status = enabled ? 1 : -1;
761 } else if(num >= 2) {
762 for(int i = 1; i < num; i++) {
763 int index = my_hexatoi(debugger->first_symbol, params[i]);
764 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
765 my_printf(p->osd, _T("invalid index %x\n"), index);
766 } else if(bp->table[index - 1].status == 0) {
767 my_printf(p->osd, _T("break point %x is null\n"), index);
769 bp->table[index - 1].status = enabled ? 1 : -1;
773 my_printf(p->osd, _T("invalid parameter number\n"));
775 } else if(_tcsicmp(params[0], _T("BL")) == 0 || _tcsicmp(params[0], _T("RBL")) == 0 || _tcsicmp(params[0], _T("WBL")) == 0) {
777 break_point_t *bp = get_break_point(debugger, params[0]);
778 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
779 if(bp->table[i].status) {
780 my_printf(p->osd, _T("%d %c %s\n"), i + 1, bp->table[i].status == 1 ? _T('e') : _T('d'), get_value_and_symbol(debugger->first_symbol, _T("%08X"), bp->table[i].addr));
784 my_printf(p->osd, _T("invalid parameter number\n"));
786 } else if(_tcsicmp(params[0], _T("IBL")) == 0 || _tcsicmp(params[0], _T("OBL")) == 0) {
788 break_point_t *bp = get_break_point(debugger, params[0]);
789 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
790 if(bp->table[i].status) {
791 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);
795 my_printf(p->osd, _T("invalid parameter number\n"));
797 } else if(_tcsicmp(params[0], _T("G")) == 0 || _tcsicmp(params[0], _T("P")) == 0) {
798 if(num == 1 || num == 2) {
799 bool break_points_stored = false;
800 if(_tcsicmp(params[0], _T("P")) == 0) {
801 debugger->store_break_points();
802 debugger->bp.table[0].addr = (cpu->get_next_pc() + cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024)) & prog_addr_mask;
803 debugger->bp.table[0].mask = prog_addr_mask;
804 debugger->bp.table[0].status = 1;
805 break_points_stored = true;
806 } else if(num >= 2) {
807 debugger->store_break_points();
808 debugger->bp.table[0].addr = my_hexatoi(debugger->first_symbol, params[1]) & prog_addr_mask;
809 debugger->bp.table[0].mask = prog_addr_mask;
810 debugger->bp.table[0].status = 1;
811 break_points_stored = true;
813 debugger->now_going = true;
814 debugger->now_suspended = false;
815 #if defined(_MSC_VER)
816 while(!p->request_terminate && !debugger->now_suspended) {
817 if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) {
822 #elif defined(OSD_QT)
823 while(!p->request_terminate && !debugger->now_suspended) {
824 if(p->osd->console_input_string() != NULL && p->osd->is_console_active()) {
825 p->osd->clear_console_input_string();
832 debugger->now_going = false;
834 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
835 if((wait_count++) == 100) {
836 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
837 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
841 dasm_addr = cpu->get_next_pc();
843 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
844 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
845 my_printf(p->osd, _T("done\t%s %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()), buffer);
847 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
848 cpu->get_debug_regs_info(buffer, 1024);
849 my_printf(p->osd, _T("%s\n"), buffer);
851 if(debugger->hit()) {
852 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
853 if(debugger->bp.hit) {
854 if(_tcsicmp(params[0], _T("G")) == 0) {
855 my_printf(p->osd, _T("breaked at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()));
857 } else if(debugger->rbp.hit) {
858 my_printf(p->osd, _T("breaked at %s: memory %s was read at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
859 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->rbp.hit_addr),
860 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
861 } else if(debugger->wbp.hit) {
862 my_printf(p->osd, _T("breaked at %s: memory %s was written at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
863 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->wbp.hit_addr),
864 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
865 } else if(debugger->ibp.hit) {
866 my_printf(p->osd, _T("breaked at %s: port %s was read at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
867 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->ibp.hit_addr),
868 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
869 } else if(debugger->obp.hit) {
870 my_printf(p->osd, _T("breaked at %s: port %s was written at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
871 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->obp.hit_addr),
872 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
874 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
876 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
877 my_printf(p->osd, _T("breaked at %s: esc key was pressed\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()));
879 if(break_points_stored) {
880 debugger->restore_break_points();
882 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
883 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
884 my_printf(p->osd, _T("next\t%s %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()), buffer);
885 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
887 my_printf(p->osd, _T("invalid parameter number\n"));
889 } else if(_tcsicmp(params[0], _T("T")) == 0) {
890 if(num == 1 || num == 2) {
893 steps = my_hexatoi(debugger->first_symbol, params[1]);
895 for(int i = 0; i < steps; i++) {
896 debugger->now_going = false;
897 debugger->now_suspended = false;
899 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
900 if((wait_count++) == 100) {
901 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
902 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
906 dasm_addr = cpu->get_next_pc();
908 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
909 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
910 my_printf(p->osd, _T("done\t%s %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()), buffer);
912 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
913 cpu->get_debug_regs_info(buffer, 1024);
914 my_printf(p->osd, _T("%s\n"), buffer);
916 if(debugger->hit() || (p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active())) {
920 if(debugger->hit()) {
921 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
922 if(debugger->bp.hit) {
923 my_printf(p->osd, _T("breaked at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()));
924 } else if(debugger->rbp.hit) {
925 my_printf(p->osd, _T("breaked at %s: memory %s was read at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
926 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->rbp.hit_addr),
927 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
928 } else if(debugger->wbp.hit) {
929 my_printf(p->osd, _T("breaked at %s: memory %s was written at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
930 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->wbp.hit_addr),
931 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
932 } else if(debugger->ibp.hit) {
933 my_printf(p->osd, _T("breaked at %s: port %s was read at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
934 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->ibp.hit_addr),
935 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
936 } else if(debugger->obp.hit) {
937 my_printf(p->osd, _T("breaked at %s: port %s was written at %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()),
938 get_value_and_symbol(debugger->first_symbol, _T("%08X"), debugger->obp.hit_addr),
939 get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_pc()));
941 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
943 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
944 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
945 my_printf(p->osd, _T("next\t%s %s\n"), get_value_and_symbol(debugger->first_symbol, _T("%08X"), cpu->get_next_pc()), buffer);
946 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
948 my_printf(p->osd, _T("invalid parameter number\n"));
950 } else if(_tcsicmp(params[0], _T("Q")) == 0) {
951 p->osd->close_debugger_console();
953 } else if(_tcsicmp(params[0], _T(">")) == 0) {
955 if(logfile != NULL) {
956 if(logfile->IsOpened()) {
962 logfile = new FILEIO();
963 logfile->Fopen(params[1], FILEIO_WRITE_ASCII);
965 my_printf(p->osd, _T("invalid parameter number\n"));
967 } else if(_tcsicmp(params[0], _T("<")) == 0) {
969 if(cmdfile != NULL) {
970 if(cmdfile->IsOpened()) {
974 cmdfile = new FILEIO();
976 if(!cmdfile->Fopen(params[1], FILEIO_READ_ASCII)) {
979 my_printf(p->osd, _T("can't open %s\n"), params[1]);
982 my_printf(p->osd, _T("invalid parameter number\n"));
984 } else if(_tcsicmp(params[0], _T("!")) == 0) {
986 my_printf(p->osd, _T("invalid parameter number\n"));
987 } else if(_tcsicmp(params[1], _T("RESET")) == 0) {
990 } else if(num == 3) {
991 if(_tcsicmp(params[2], _T("ALL")) == 0) {
993 } if(_tcsicmp(params[2], _T("CPU")) == 0) {
996 my_printf(p->osd, _T("unknown device %s\n"), params[2]);
999 my_printf(p->osd, _T("invalid parameter number\n"));
1001 } else if(_tcsicmp(params[1], _T("KEY")) == 0) {
1002 if(num == 3 || num == 4) {
1003 int code = my_hexatoi(debugger->first_symbol, params[2]) & 0xff, msec = 100;
1005 msec = my_hexatoi(debugger->first_symbol, params[3]);
1007 #ifdef SUPPORT_VARIABLE_TIMING
1008 int frames = (int)(p->vm->get_frame_rate() * (double)msec / 1000.0 + 0.5);
1010 int frames = (int)(FRAMES_PER_SEC * (double)msec / 1000.0 + 0.5);
1012 p->osd->get_key_buffer()[code] &= 0x7f;
1013 p->osd->get_key_buffer()[code] |= max(1, min(127, frames));
1014 #ifdef NOTIFY_KEY_DOWN
1015 p->vm->key_down(code, false);
1018 my_printf(p->osd, _T("invalid parameter number\n"));
1021 my_printf(p->osd, _T("unknown command ! %s\n"), params[1]);
1023 } else if(_tcsicmp(params[0], _T("?")) == 0) {
1024 my_printf(p->osd, _T("D [<range>] - dump memory\n"));
1025 my_printf(p->osd, _T("E[{B,W,D}] <address> <list> - edit memory (byte,word,dword)\n"));
1026 my_printf(p->osd, _T("EA <address> \"<value>\" - edit memory (ascii)\n"));
1027 my_printf(p->osd, _T("I[{B,W,D}] <port> - input port (byte,word,dword)\n"));
1028 my_printf(p->osd, _T("O[{B,W,D}] <port> <value> - output port (byte,word,dword)\n"));
1029 my_printf(p->osd, _T("R - show register(s)\n"));
1030 my_printf(p->osd, _T("R <reg> <value> - edit register\n"));
1031 my_printf(p->osd, _T("S <range> <list> - search\n"));
1032 my_printf(p->osd, _T("U [<range>] - unassemble\n"));
1033 my_printf(p->osd, _T("UT [<steps>] - unassemble trace\n"));
1035 my_printf(p->osd, _T("H <value> <value> - hexadd\n"));
1036 my_printf(p->osd, _T("N <filename> - name\n"));
1037 my_printf(p->osd, _T("L [<range>] - load binary/hex/symbol file\n"));
1038 my_printf(p->osd, _T("W <range> - write binary/hex file\n"));
1040 my_printf(p->osd, _T("SC - clear symbol(s)\n"));
1041 my_printf(p->osd, _T("SL - list symbol(s)\n"));
1043 my_printf(p->osd, _T("BP <address> - set breakpoint\n"));
1044 my_printf(p->osd, _T("{R,W}BP <address> - set breakpoint (break at memory access)\n"));
1045 my_printf(p->osd, _T("{I,O}BP <port> [<mask>] - set breakpoint (break at i/o access)\n"));
1046 my_printf(p->osd, _T("[{R,W,I,O}]B{C,D,E} {*,<list>} - clear/disable/enable breakpoint(s)\n"));
1047 my_printf(p->osd, _T("[{R,W,I,O}]BL - list breakpoint(s)\n"));
1049 my_printf(p->osd, _T("G - go (press esc key to break)\n"));
1050 my_printf(p->osd, _T("G <address> - go and break at address\n"));
1051 my_printf(p->osd, _T("P - trace one opcode (step over)\n"));
1052 my_printf(p->osd, _T("T [<count>] - trace (step in)\n"));
1053 my_printf(p->osd, _T("Q - quit\n"));
1055 my_printf(p->osd, _T("> <filename> - output logfile\n"));
1056 my_printf(p->osd, _T("< <filename> - input commands from file\n"));
1058 my_printf(p->osd, _T("! reset [cpu] - reset\n"));
1059 my_printf(p->osd, _T("! key <code> [<msec>] - press key\n"));
1061 my_printf(p->osd, _T("<value> - hexa, decimal(%%d), ascii('a')\n"));
1063 my_printf(p->osd, _T("unknown command %s\n"), params[0]);
1070 debugger->now_debugging = debugger->now_going = debugger->now_suspended = debugger->now_waiting = false;
1075 if(logfile != NULL) {
1076 if(logfile->IsOpened()) {
1082 if(cmdfile != NULL) {
1083 if(cmdfile->IsOpened()) {
1091 p->osd->close_console();
1098 //pthread_exit(NULL);
1103 void EMU::initialize_debugger()
1105 now_debugging = false;
1108 void EMU::release_debugger()
1113 void EMU::open_debugger(int cpu_index)
1115 if(!(now_debugging && debugger_thread_param.cpu_index == cpu_index)) {
1117 if(vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL) {
1118 // debugger_thread_param.emu = this;
1119 debugger_thread_param.osd = osd;
1120 debugger_thread_param.vm = vm;
1121 debugger_thread_param.cpu_index = cpu_index;
1122 debugger_thread_param.request_terminate = false;
1124 if((hDebuggerThread = (HANDLE)_beginthreadex(NULL, 0, debugger_thread, &debugger_thread_param, 0, NULL)) != (HANDLE)0) {
1126 //#elif !defined(_USE_QT)
1127 if(pthread_create(&debugger_thread_id, NULL, debugger_thread, &debugger_thread_param) == 0) {
1131 stop_record_sound();
1132 stop_record_video();
1133 now_debugging = true;
1139 void EMU::close_debugger()
1142 if(debugger_thread_param.running) {
1143 debugger_thread_param.request_terminate = true;
1146 WaitForSingleObject(hDebuggerThread, INFINITE);
1147 CloseHandle(hDebuggerThread);
1148 //#elif !defined(_USE_QT)
1150 pthread_join(debugger_thread_id, NULL);
1152 // volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param);
1153 // p->running = false;
1155 //if(logfile != NULL && logfile->IsOpened()) {
1156 // logfile->Fclose();
1158 // initialize logfile
1161 now_debugging = false;
1165 bool EMU::is_debugger_enabled(int cpu_index)
1167 return (vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL);