From bf120a64bb2232f037012b925b614ea2814cab30 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Mon, 21 Dec 2015 19:40:55 +0900 Subject: [PATCH] [Qt][DEBUGGER] Temporally revert changes around debugger, will use src/debugger.cpp . --- source/src/CMakeLists.txt | 2 +- source/src/debugger.cpp | 88 ++- source/src/emu.h | 4 + source/src/qt/common/emu_thread.cpp | 47 +- source/src/qt/common/emu_thread.h | 11 + source/src/qt/common/emuevents_control.cpp | 50 +- source/src/qt/debugger/CMakeLists.txt | 2 +- source/src/qt/debugger/debugger_thread.cpp | 959 +++++++++++++++++++++++++++++ source/src/qt/debugger/qt_debugger.cpp | 52 +- source/src/qt/debugger/qt_debugger.h | 55 +- source/src/qt/osd.cpp | 32 +- source/src/qt/osd.h | 19 +- source/src/qt/osd_console.cpp | 49 +- 13 files changed, 1299 insertions(+), 71 deletions(-) create mode 100644 source/src/qt/debugger/debugger_thread.cpp diff --git a/source/src/CMakeLists.txt b/source/src/CMakeLists.txt index bc1b18433..3d2d85a1d 100644 --- a/source/src/CMakeLists.txt +++ b/source/src/CMakeLists.txt @@ -8,7 +8,7 @@ add_library(common_common # emu.cpp fifo.cpp fileio.cpp - debugger.cpp +# debugger.cpp ) add_library(common_emu diff --git a/source/src/debugger.cpp b/source/src/debugger.cpp index 4edbc99f4..d833b12a4 100644 --- a/source/src/debugger.cpp +++ b/source/src/debugger.cpp @@ -18,6 +18,9 @@ #include "vm/debugger.h" #include "vm/vm.h" #include "fileio.h" +#if defined(OSD_QT) +#include "emu_thread.h" +#endif #ifdef USE_DEBUGGER @@ -48,7 +51,7 @@ void my_printf(OSD *osd, const _TCHAR *format, ...) if(logfile != NULL && logfile->IsOpened()) { logfile->Fwrite(buffer, lstrlen(buffer) * sizeof(_TCHAR), 1); } -#else +#else if(logfile != NULL && logfile->IsOpened()) { logfile->Fwrite(buffer, strlen(buffer) * sizeof(_TCHAR), 1); } @@ -124,7 +127,7 @@ break_point_t *get_break_point(DEBUGGER *debugger, const _TCHAR *command) } -static int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_command, bool cp932) +int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_command, bool cp932) { DEVICE *cpu = p->vm->get_cpu(p->cpu_index); DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger(); @@ -132,6 +135,9 @@ static int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_ uint32 data_addr_mask = cpu->debug_data_addr_mask(); uint32 dump_addr = 0; uint32 dasm_addr = cpu->get_next_pc(); + //while(!debugger->now_suspended) { + // p->osd->sleep(10); + //} // initialize console _TCHAR buffer[1024]; @@ -581,6 +587,14 @@ static int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_ } p->osd->sleep(10); } +#elif defined(OSD_QT) + while(!p->request_terminate && !debugger->now_suspended) { + if(p->osd->console_input_string() != NULL && p->osd->is_console_active()) { + p->osd->clear_console_input_string(); + break; + } + p->osd->sleep(10); + } #endif // break cpu debugger->now_going = false; @@ -650,6 +664,11 @@ static int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_ if(debugger->hit() || ((GetAsyncKeyState(VK_ESCAPE) & 0x8000) != 0 && p->osd->is_console_active())) { break; } +#elif defined(OSD_QT) + if(debugger->hit() || p->osd->console_input_string() != NULL && p->osd->is_console_active()) { + p->osd->clear_console_input_string(); + break; + } #endif } if(debugger->hit()) { @@ -824,7 +843,6 @@ int debugger_thread(void *lpx) _TCHAR prev_command[MAX_COMMAND_LEN + 1]; memset(prev_command, 0, sizeof(prev_command)); - while(!p->request_terminate) { my_printf(p->osd, _T("- ")); @@ -921,12 +939,56 @@ void EMU::open_debugger(int cpu_index) debugger_thread_param.request_terminate = false; #ifdef _WIN32 if((hDebuggerThread = (HANDLE)_beginthreadex(NULL, 0, debugger_thread, &debugger_thread_param, 0, NULL)) != (HANDLE)0) { -#else +#elif !defined(_USE_QT) if((debugger_thread_id = SDL_CreateThread(debugger_thread, "DebuggerThread", (void *)&debugger_thread_param)) != 0) { +#else // USE_QT + { + volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param); + p->running = true; + + DEVICE *cpu = p->vm->get_cpu(p->cpu_index); + DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger(); + + debugger->now_going = false; + debugger->now_debugging = true; + //while(!debugger->now_suspended) { + // p->osd->sleep(10); + //} + + uint32 prog_addr_mask = cpu->debug_prog_addr_mask(); + uint32 data_addr_mask = cpu->debug_data_addr_mask(); + uint32 dump_addr = 0; + uint32 dasm_addr = cpu->get_next_pc(); + + // initialize console + _TCHAR buffer[1024]; + my_stprintf_s(buffer, 1024, _T("Debugger - %s"), _T(DEVICE_NAME)); + + p->osd->open_console(buffer); + + bool cp932 = (p->osd->get_console_code_page() == 932); + + p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + cpu->debug_regs_info(buffer, 1024); + my_printf(p->osd, _T("%s\n"), buffer); + + p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY); + my_printf(p->osd, _T("breaked at %08X\n"), cpu->get_next_pc()); + + p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024); + my_printf(p->osd, _T("next\t%08X %s\n"), cpu->get_next_pc(), buffer); + p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + + // initialize logfile + if(logfile != NULL && logfile->IsOpened()) { + logfile->Fclose(); + } + logfile = NULL; #endif - stop_rec_sound(); - stop_rec_video(); - now_debugging = true; + stop_rec_sound(); + stop_rec_video(); + now_debugging = true; } } } @@ -941,9 +1003,19 @@ void EMU::close_debugger() #ifdef _WIN32 WaitForSingleObject(hDebuggerThread, INFINITE); CloseHandle(hDebuggerThread); -#else +#elif !defined(_USE_QT) //pthread_join(debugger_thread_id, NULL); SDL_DetachThread(debugger_thread_id); +#else + volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param); + p->running = false; + + if(logfile != NULL && logfile->IsOpened()) { + logfile->Fclose(); + } + // initialize logfile + logfile = NULL; + #endif now_debugging = false; } diff --git a/source/src/emu.h b/source/src/emu.h index 95f72b963..2d3f1a098 100644 --- a/source/src/emu.h +++ b/source/src/emu.h @@ -191,6 +191,10 @@ public: { return vm; } + OSD *get_osd() + { + return osd; + } void set_host_cpus(int v); int get_host_cpus(); #endif diff --git a/source/src/qt/common/emu_thread.cpp b/source/src/qt/common/emu_thread.cpp index e9180c431..31eccb087 100644 --- a/source/src/qt/common/emu_thread.cpp +++ b/source/src/qt/common/emu_thread.cpp @@ -487,7 +487,8 @@ void EmuThreadClass::doWork(const QString ¶ms) bool horiz_line_bak = config.opengl_scanline_horiz; bool gl_crt_filter_bak = config.use_opengl_filters; int opengl_filter_num_bak = config.opengl_filter_num; - int no_draw_count = 0; + int no_draw_count = 0; + doing_debug_command = false; ctext.clear(); draw_timing = false; @@ -694,4 +695,48 @@ void EmuThreadClass::doSaveState() { bSaveStateReq = true; } +// Debugger +#if defined(USE_DEBUGGER) +extern int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_command, bool cp932); +#endif +void EmuThreadClass::do_call_debugger_command(QString s) +{ +#if 0 +#if defined(USE_DEBUGGER) + _TCHAR command[MAX_COMMAND_LEN + 1]; + + if(doing_debug_command) { + emit sig_debugger_input(s); + return; + } + memset(command, 0x00, MAX_COMMAND_LEN + 1); + if(s.isEmpty()) { + strncpy(command, dbg_prev_command, MAX_COMMAND_LEN); + } else { + strncpy(command, s.toUtf8().constData(), MAX_COMMAND_LEN); + } + doing_debug_command = true; + if(debugger_command(&(p_emu->debugger_thread_param), command, dbg_prev_command, false) < 0) { + do_close_debugger(); + } + doing_debug_command = false; +#endif +#endif +} +void EmuThreadClass::do_close_debugger(void) +{ +#if 0 +#if defined(USE_DEBUGGER) + emit sig_quit_debugger(); +#endif +#endif +} + +bool EmuThreadClass::now_debugging() { +#if defined(USE_DEBUGGER) + return p_emu->now_debugging; +#else + return false; +#endif +} diff --git a/source/src/qt/common/emu_thread.h b/source/src/qt/common/emu_thread.h index 6715e9df5..7b55f1c49 100644 --- a/source/src/qt/common/emu_thread.h +++ b/source/src/qt/common/emu_thread.h @@ -31,6 +31,7 @@ class QWaitCondition; #endif QT_BEGIN_NAMESPACE +#define MAX_COMMAND_LEN 64 class EmuThreadClass : public QThread { Q_OBJECT @@ -40,7 +41,10 @@ private: bool tape_rec_flag; int tape_pos; bool mouse_flag; + char dbg_prev_command[MAX_COMMAND_LEN]; + int get_interval(void); + protected: EMU *p_emu; QWaitCondition *drawCond; @@ -54,6 +58,7 @@ private: bool bStartRecordSoundReq; bool bStopRecordSoundReq; bool draw_timing; + bool doing_debug_command; uint32 next_time; uint32 update_fps_time; @@ -84,6 +89,7 @@ public: void run() { doWork("");} EmuThreadClass *currentHandler(); void resize_screen(int sw, int sh, int stw, int sth); + bool now_debugging(); public slots: void doWork(const QString ¶m); void doExit(void); @@ -139,6 +145,9 @@ public slots: void do_start_auto_key(QString text); void do_stop_auto_key(void); void do_draw_timing(bool); + void do_call_debugger_command(QString s); + void do_close_debugger(void); + signals: int message_changed(QString); int sig_draw_thread(bool); @@ -170,6 +179,8 @@ signals: int sig_resize_screen(int, int); int sig_resize_uibar(int, int); int sig_auto_key_string(QByteArray); + int sig_debugger_input(QString); + int sig_quit_debugger(); }; QT_END_NAMESPACE diff --git a/source/src/qt/common/emuevents_control.cpp b/source/src/qt/common/emuevents_control.cpp index 1ed922fa9..324bfb5ef 100644 --- a/source/src/qt/common/emuevents_control.cpp +++ b/source/src/qt/common/emuevents_control.cpp @@ -65,24 +65,46 @@ void Ui_MainWindow::OnStopAutoKey(void) void Ui_MainWindow::OnOpenDebugger(int no) { if((no < 0) || (no > 3)) return; - - if(emu->now_debugging) this->OnCloseDebugger(); - emu->open_debugger(no); - OSD *p_osd = emu->debugger_thread_param.osd; - emu->hDebugger = new CSP_Debugger(this, p_osd); - connect(p_osd, SIGNAL(sig_put_string_debugger(QString)), emu->hDebugger, SLOT(put_string(QString)), Qt::DirectConnection); - emu->hDebugger->show(); - emu->hDebugger->run(); + //emu->open_debugger(no); + VM *vm = emu->get_vm(); + + if(emu->now_debugging) this->OnCloseDebugger(); + if(!(emu->now_debugging && emu->debugger_thread_param.cpu_index == no)) { + //emu->close_debugger(); + if(vm->get_cpu(no) != NULL && vm->get_cpu(no)->get_debugger() != NULL) { + + emu->hDebugger = new CSP_Debugger(this); + QString objNameStr = QString("EmuDebugThread"); + emu->hDebugger->setObjectName(objNameStr); + emu->hDebugger->debugger_thread_param.osd = emu->get_osd(); + emu->hDebugger->debugger_thread_param.vm = vm; + emu->hDebugger->debugger_thread_param.cpu_index = no; + emu->stop_rec_sound(); + emu->stop_rec_video(); + emu->now_debugging = true; + connect(this, SIGNAL(quit_debugger_thread()), emu->hDebugger, SLOT(doExit())); + //connect(this, SIGNAL(quit_debugger_thread()), emu->hDebugger, SLOT(close())); + connect(emu->hDebugger, SIGNAL(sig_finished()), this, SLOT(OnCloseDebugger())); + connect(emu->hDebugger, SIGNAL(sig_put_string(QString)), emu->hDebugger, SLOT(put_string(QString))); + emu->hDebugger->show(); + emu->hDebugger->run(); + } + } } void Ui_MainWindow::OnCloseDebugger(void ) { - if(emu->now_debugging) { - emu->close_debugger(); - if(emu->hDebugger != NULL) delete emu->hDebugger; - emu->hDebugger = NULL; - emu->now_debugging = false; - } + +// emu->close_debugger(); + if(emu->now_debugging) { + if(emu->hDebugger->debugger_thread_param.running) { + emit quit_debugger_thread(); + //emu->hDebugger->wait(); + } + delete emu->hDebugger; + emu->hDebugger = NULL; + emu->now_debugging = false; + } } #endif diff --git a/source/src/qt/debugger/CMakeLists.txt b/source/src/qt/debugger/CMakeLists.txt index 2ee432508..46c4bb270 100644 --- a/source/src/qt/debugger/CMakeLists.txt +++ b/source/src/qt/debugger/CMakeLists.txt @@ -12,7 +12,7 @@ endif() add_library(qt_debugger qt_debugger.cpp -# debugger_thread.cpp + debugger_thread.cpp ${s_qt_debugger_headers_MOC} ) diff --git a/source/src/qt/debugger/debugger_thread.cpp b/source/src/qt/debugger/debugger_thread.cpp new file mode 100644 index 000000000..f4647210f --- /dev/null +++ b/source/src/qt/debugger/debugger_thread.cpp @@ -0,0 +1,959 @@ + +#include +#include +#include +#include "./qt_debugger.h" +#include "fileio.h" + +void CSP_DebuggerThread::my_printf(const _TCHAR *format, ...) +{ + _TCHAR buffer[4096]; + va_list ap; + + memset(buffer, 0x00, sizeof(buffer)); + va_start(ap, format); + my_vstprintf_s(buffer, 4096, format, ap); + va_end(ap); + QString str(buffer); + if((logfile != NULL) && (logfile->IsOpened())) { + logfile->Fwrite(buffer, strlen(buffer) * sizeof(_TCHAR), 1); + } + emit sig_put_string(str); +} + +void CSP_DebuggerThread::my_putch(_TCHAR c) +{ + char buffer[2]; + buffer[0] = (char)c; + buffer[1] = 0x00; + QString str(buffer); + if(logfile != NULL && logfile->IsOpened()) { + logfile->Fwrite(&c, sizeof(_TCHAR), 1); + } + emit sig_put_string(str); + //text->append(str); +} + +uint32 CSP_DebuggerThread::my_hexatoi(_TCHAR *str) +{ + _TCHAR *s; + + if(str == NULL || strlen(str) == 0) { + return 0; + } else if(strlen(str) == 3 && str[0] == _T('\'') && str[2] == _T('\'')) { + // ank + return str[1] & 0xff; + } else if((s = strstr(str, _T(":"))) != NULL) { + // 0000:0000 + s[0] = _T('\0'); + return (my_hexatoi(str) << 4) + my_hexatoi(s + 1); + } else if(str[0] == _T('%')) { + // decimal + return atoi(str + 1); + } + return strtol(str, NULL, 16); +} + +break_point_t *CSP_DebuggerThread::get_break_point(DEBUGGER *debugger, _TCHAR *command) +{ + if(command[0] == _T('B') || command[0] == _T('b')) { + return &debugger->bp; + } else if(command[0] == _T('R') || command[0] == _T('r')) { + return &debugger->rbp; + } else if(command[0] == _T('W') || command[0] == _T('w')) { + return &debugger->wbp; + } else if(command[0] == _T('I') || command[0] == _T('i')) { + return &debugger->ibp; + } else if(command[0] == _T('O') || command[0] == _T('o')) { + return &debugger->obp; + } + return NULL; +} + + + +void CSP_DebuggerThread::call_debugger(QString str) +{ + //this->debugger_main(str); + this->do_string_input(str); +} + +void CSP_DebuggerThread::display_break_point(void) +{ + getRegisterInfo(); + trap_timer->stop(); +} + +void CSP_DebuggerThread::display_pc(void) +{ + _TCHAR buffer[1024]; + dasm_addr = cpu->get_next_pc(); + + cpu->debug_regs_info(buffer, 1024); + my_printf( _T("%s\n"), buffer); + cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024); + my_printf( _T("next\t%08X %s\n"), cpu->get_next_pc(), buffer); +} + +void CSP_DebuggerThread::display_break_status(void) +{ + if(debugger->bp.hit) { + my_printf( _T("breaked at %08X\n"), cpu->get_next_pc()); + } else if(debugger->rbp.hit) { + my_printf( _T("breaked at %08X: memory %08X was read at %08X\n"), cpu->get_next_pc(), debugger->rbp.hit_addr, cpu->get_pc()); + } else if(debugger->wbp.hit) { + my_printf( _T("breaked at %08X: memory %08X was written at %08X\n"), cpu->get_next_pc(), debugger->wbp.hit_addr, cpu->get_pc()); + } else if(debugger->ibp.hit) { + my_printf( _T("breaked at %08X: port %08X was read at %08X\n"), cpu->get_next_pc(), debugger->ibp.hit_addr, cpu->get_pc()); + } else if(debugger->obp.hit) { + my_printf( _T("breaked at %08X: port %08X was written at %08X\n"), cpu->get_next_pc(), debugger->obp.hit_addr, cpu->get_pc()); + } + debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false; +} + +void CSP_DebuggerThread::check_trap(void) +{ + volatile debugger_thread_t *p = d_params; + char buffer[1024]; + + memset(buffer, 0x00, sizeof(buffer)); + if(trace_steps < 0) { + printf("!\n"); + //if(!debugger->now_going) return; + if(!p->request_terminate && !debugger->now_suspended && !this->request_terminate) { + if(debugger->hit()) { + display_pc(); + display_break_status(); + } + return; + } + debugger->now_going = false; + debugger->now_suspended = true; + } + // break cpu + display_pc(); + if(debugger->hit()) { + display_break_status(); + } else if(trace_steps < 0) { + my_printf( _T("breaked at %08X: Any key was pressed\n"), cpu->get_next_pc()); + } else if(trace_steps == 0) { + my_printf("Trace OK\n"); + debugger->now_going = false; + debugger->now_suspended = true; + } + if(trace_steps > 0) { + trace_steps--; + debugger->restore_break_points(); + return; + } + //if(num >= 2) { + debugger->restore_break_points(); + //} + emit sig_end_trap(); +} + +int CSP_DebuggerThread::debugger_main(QString command) +{ + + volatile debugger_thread_t *p = d_params; + QString scmd; + p->running = true; + + //DEVICE *cpu = p->vm->get_cpu(p->cpu_index); + //DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger(); + if(debugger->now_going) { + if(!command.isEmpty()) { + debugger->now_going = false; + debugger->now_suspended = true; + my_printf("Now Suspended\n"); + display_pc(); + display_break_status(); + return -1; + } + } + + //debugger->now_going = false; + debugger->now_debugging = true; + + uint32 prog_addr_mask = cpu->debug_prog_addr_mask(); + uint32 data_addr_mask = cpu->debug_data_addr_mask(); + + // initialize console + _TCHAR buffer[1024]; + snprintf(buffer, 1024, _T("Debugger - %s"), _T(DEVICE_NAME)); + bool cp932 = false; //(GetConsoleCP() == 932); + + //while(!p->request_terminate) { + //my_printf( _T("- ")); + if(command.isEmpty()) { + my_printf(""); + scmd = prev_command; + } else { + my_printf("$%s\n", command.toUtf8().data()); + scmd = command; + } + + // get command + int ptr = 0; + // process command + if(!p->request_terminate && !this->request_terminate) { + QStringList s_params; + int num; + QString cmd; + s_params = scmd.split(" "); + num = s_params.count(); + cmd = s_params.first().toUpper(); + if(num < 1) { + cmd = prev_command; + num = 1; + } else { + prev_command = cmd; + } + if(cmd == QString::fromUtf8("D")) { + debugger->now_going = false; + if(num <= 3) { + uint32 start_addr = dump_addr; + if(num >= 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + start_addr = my_hexatoi(arg_1); + } + start_addr &= data_addr_mask; + + uint32 end_addr = start_addr + 8 * 16 - 1; + if(num == 3) { + char *arg_2 = s_params.value(2).toUtf8().data(); + end_addr = my_hexatoi(arg_2); + } + end_addr &= data_addr_mask; + + if(start_addr > end_addr) { + end_addr = data_addr_mask; + } + for(uint64 addr = start_addr & ~0x0f; addr <= end_addr; addr++) { + if(addr > data_addr_mask) { + end_addr = data_addr_mask; + break; + } + if((addr & 0x0f) == 0) { + my_printf( _T("%08X "), addr & data_addr_mask); + memset(buffer, 0, sizeof(buffer)); + } + if(addr < start_addr) { + my_printf( _T(" ")); + buffer[addr & 0x0f] = _T(' '); + } else { + uint32 data = cpu->debug_read_data8(addr & data_addr_mask); + my_printf( _T(" %02X"), data); + buffer[addr & 0x0f] = ((data >= 0x20 && data <= 0x7e) || (cp932 && data >= 0xa1 && data <= 0xdf)) ? data : _T('.'); + } + if((addr & 0x0f) == 0x0f) { + my_printf( _T(" %s\n"), buffer); + } + } + if((end_addr & 0x0f) != 0x0f) { + for(uint32 addr = (end_addr & 0x0f) + 1; addr <= 0x0f; addr++) { + my_printf( _T(" ")); + } + my_printf( _T(" %s\n"), buffer); + } + dump_addr = (end_addr + 1) & data_addr_mask; + //prev_command.clear(); // remove parameters to dump continuously + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("E") || cmd == QString::fromUtf8("EB")) { + debugger->now_going = false; + if(num >= 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + uint32 addr = my_hexatoi(arg_1) & data_addr_mask; + for(int i = 2; i < num; i++) { + char *arg_n = s_params.value(i).toUtf8().data(); + cpu->debug_write_data8(addr, my_hexatoi(arg_n) & 0xff); + addr = (addr + 1) & data_addr_mask; + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("EW")) { + debugger->now_going = false; + if(num >= 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + uint32 addr = my_hexatoi(arg_1) & data_addr_mask; + for(int i = 2; i < num; i++) { + char *arg_n = s_params.value(i).toUtf8().data(); + cpu->debug_write_data16(addr, my_hexatoi(arg_n) & 0xffff); + addr = (addr + 2) & data_addr_mask; + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("ED")) { + debugger->now_going = false; + if(num >= 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + uint32 addr = my_hexatoi(arg_1) & data_addr_mask; + for(int i = 2; i < num; i++) { + char *arg_n = s_params.value(i).toUtf8().data(); + cpu->debug_write_data32(addr, my_hexatoi(arg_n)); + addr = (addr + 4) & data_addr_mask; + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("EA")) { + debugger->now_going = false; + if(num >= 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + uint32 addr = my_hexatoi(arg_1) & data_addr_mask; + QString sbuffer; + QStringList slist; + sbuffer = prev_command; + slist = sbuffer.split("\""); + if(!slist.isEmpty()) { + char *token = slist.first().toUtf8().data(); + if(token == NULL) { + p->running = false; + emit sig_text_clear(); + return 0; + } + int len = strlen(token); + for(int i = 0; i < len; i++) { + cpu->debug_write_data8(addr, token[i] & 0xff); + addr = (addr + 1) & data_addr_mask; + } + } else { + my_printf( _T("invalid parameter\n")); + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("I") || cmd == QString::fromUtf8("IB")) { + debugger->now_going = false; + if(num == 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + my_printf( _T("%02X\n"), cpu->debug_read_io8(my_hexatoi(arg_1) & 0xff)); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("IW")) { + debugger->now_going = false; + if(num >= 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + my_printf( _T("%02X\n"), cpu->debug_read_io16(my_hexatoi(arg_1)) & 0xffff); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("ID")) { + debugger->now_going = false; + if(num >= 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + my_printf( _T("%02X\n"), cpu->debug_read_io32(my_hexatoi(arg_1))); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("O") || cmd == QString::fromUtf8("OB")) { + debugger->now_going = false; + if(num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + cpu->debug_write_io8(my_hexatoi(arg_1), my_hexatoi(arg_2) & 0xff); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("OW")) { + debugger->now_going = false; + if(num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + cpu->debug_write_io16(my_hexatoi(arg_1), my_hexatoi(arg_2) & 0xffff); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("OD")) { + debugger->now_going = false; + if(num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + cpu->debug_write_io32(my_hexatoi(arg_1), my_hexatoi(arg_2) & 0xffff); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("R")) { + debugger->now_going = false; + my_printf( _T("CPU DOMAIN=%d\n"), cpu_index); + if(num == 1) { + cpu->debug_regs_info(buffer, 1024); + my_printf( _T("%s\n"), buffer); + } else if(num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + if(!cpu->debug_write_reg(arg_1, my_hexatoi(arg_2))) { + my_printf( _T("unknown register %s\n"), arg_1); + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("S")) { + debugger->now_going = false; + if(num >= 4) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + uint32 start_addr = my_hexatoi(arg_1) & data_addr_mask; + uint32 end_addr = my_hexatoi(arg_2) & data_addr_mask; + uint8 list[32]; + char *arg_n = NULL; + for(int i = 3, j = 0; i < num; i++, j++) { + arg_n = s_params.value(i).toUtf8().data(); + if(arg_n == NULL) break; + list[j] = my_hexatoi(arg_n); + } + for(uint64 addr = start_addr; addr <= end_addr; addr++) { + bool found = true; + for(int i = 3, j = 0; i < num; i++, j++) { + if(cpu->debug_read_data8((addr + j) & data_addr_mask) != list[j]) { + found = false; + break; + } + } + if(found) { + my_printf( _T("%08X\n"), addr); + } + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("UW")) { + debugger->now_going = false; + if((num <= 4) && (num >= 2)) { + uint32 start_a, end_a; + int filename_num = 1; + start_a = dasm_addr; + if(num >= 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + start_a = my_hexatoi(arg_1) & prog_addr_mask; + filename_num = 2; + } + + if(num == 4) { + char *arg_2 = s_params.value(2).toUtf8().data(); + end_a = my_hexatoi(arg_2) & prog_addr_mask; + filename_num = 3; + } else { + end_a = start_a + 0x100; + } + char *arg_name = s_params.value(filename_num).toUtf8().data(); + + if(arg_name[0] == _T('\"')) { + QString sbuffer; + QStringList slist; + + sbuffer = prev_command; + slist = sbuffer.split("\""); + if(!slist.isEmpty()) { + strncpy(debugger->file_path, slist.first().toUtf8().data(), _MAX_PATH); + } else { + my_printf( _T("invalid parameter\n")); + filename_num = -1; + } + } + if(end_a < start_a) { + uint32 tmp_a; + tmp_a = start_a; + start_a = end_a; + end_a = tmp_a; + } + if(filename_num >= 1) { + FILEIO* fio = new FILEIO(); + _TCHAR dasm_str_buffer[1024]; + _TCHAR stream_buffer[1024]; + int addrcount = (int)(end_a - start_a); + if(fio->Fopen(debugger->file_path, FILEIO_WRITE_ASCII)) { + for(dasm_addr = start_a; addrcount > 0;) { + memset(dasm_str_buffer, 0x00, sizeof(dasm_str_buffer)); + memset(stream_buffer, 0x00, sizeof(stream_buffer)); + int len = cpu->debug_dasm(dasm_addr, dasm_str_buffer, 1024); + if(len > 0) { + snprintf(stream_buffer, 1024, _T("%08X %s\n"), dasm_addr, dasm_str_buffer); + fio->Fwrite(stream_buffer, strlen(stream_buffer), 1); + dasm_addr = (dasm_addr + len) & prog_addr_mask; + addrcount -= len; + } else { + break; + } + } + fio->Fclose(); + delete fio; + } + } + + //prev_command.clear(); // remove parameters to disassemble continuously + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("U")) { + debugger->now_going = false; + if(num <= 3) { + if(num >= 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + dasm_addr = my_hexatoi(arg_1) & prog_addr_mask; + } + if(num == 3) { + char *arg_2 = s_params.value(2).toUtf8().data(); + uint32 end_addr = my_hexatoi(arg_2) & prog_addr_mask; + while(dasm_addr <= end_addr) { + int len = cpu->debug_dasm(dasm_addr, buffer, 1024); + my_printf( _T("%08X %s\n"), dasm_addr, buffer); + dasm_addr = (dasm_addr + len) & prog_addr_mask; + } + } else { + for(int i = 0; i < 16; i++) { + int len = cpu->debug_dasm(dasm_addr, buffer, 1024); + my_printf( _T("%08X %s\n"), dasm_addr, buffer); + dasm_addr = (dasm_addr + len) & prog_addr_mask; + } + } + //prev_command.clear(); // remove parameters to disassemble continuously + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("H")) { + debugger->now_going = false; + if(num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + uint32 l = my_hexatoi(arg_1); + uint32 r = my_hexatoi(arg_2); + my_printf( _T("%08X %08X\n"), l + r, l - r); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("N")) { + debugger->now_going = false; + char *arg_1 = s_params.value(1).toUtf8().data(); + if(num >= 2 && arg_1[0] == _T('\"')) { + QString sbuffer; + QStringList slist; + sbuffer = prev_command; + slist = sbuffer.split("\""); + if(!slist.isEmpty()) { + strncpy(debugger->file_path, slist.first().toUtf8().data(), _MAX_PATH); + } else { + my_printf( _T("invalid parameter\n")); + } + } else if(num == 2) { + strncpy(debugger->file_path, arg_1, _MAX_PATH); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("L")) { + debugger->now_going = false; + if(num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + uint32 start_addr = my_hexatoi(arg_1) & data_addr_mask, end_addr = my_hexatoi(arg_2) & data_addr_mask; + FILEIO* fio = new FILEIO(); + if(fio->Fopen(debugger->file_path, FILEIO_READ_BINARY)) { + for(uint32 addr = start_addr; addr <= end_addr; addr++) { + int data = fio->Fgetc(); + if(data == EOF) { + break; + } + cpu->debug_write_data8(addr & data_addr_mask, data); + } + fio->Fclose(); + } else { + my_printf( _T("can't open %s\n"), debugger->file_path); + } + delete fio; + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("W")) { + debugger->now_going = false; + if(num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + uint32 start_addr = my_hexatoi(arg_1) & data_addr_mask, end_addr = my_hexatoi(arg_2) & data_addr_mask; + FILEIO* fio = new FILEIO(); + if(fio->Fopen(debugger->file_path, FILEIO_WRITE_BINARY)) { + for(uint32 addr = start_addr; addr <= end_addr; addr++) { + fio->Fputc(cpu->debug_read_data8(addr & data_addr_mask)); + } + fio->Fclose(); + } else { + my_printf( _T("can't open %s\n"), debugger->file_path); + } + delete fio; + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8( "BP") || cmd == QString::fromUtf8("RBP") || cmd == QString::fromUtf8("WBP")) { + debugger->now_going = false; + break_point_t *bp = get_break_point(debugger, cmd.toUtf8().data()); + if(num == 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + uint32 addr = my_hexatoi(arg_1); + bool found = false; + for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) { + if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == prog_addr_mask)) { + bp->table[i].addr = addr; + bp->table[i].mask = prog_addr_mask; + bp->table[i].status = 1; + found = true; + } + } + if(!found) { + my_printf( _T("too many break points\n")); + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("IBP") || cmd == QString::fromUtf8("OBP")) { + debugger->now_going = false; + break_point_t *bp = get_break_point(debugger, cmd.toUtf8().data()); + if(num == 2 || num == 3) { + char *arg_1 = s_params.value(1).toUtf8().data(); + uint32 addr = my_hexatoi(arg_1), mask = 0xff; + if(num == 3) { + char *arg_2 = s_params.value(2).toUtf8().data(); + mask = my_hexatoi(arg_2); + } + bool found = false; + for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) { + if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == mask)) { + bp->table[i].addr = addr; + bp->table[i].mask = mask; + bp->table[i].status = 1; + found = true; + } + } + if(!found) { + my_printf( _T("too many break points\n")); + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("BC") || cmd == QString::fromUtf8("RBC") || cmd == QString::fromUtf8("WBC") || cmd == QString::fromUtf8("IBC") || cmd == QString::fromUtf8("OBC")) { + debugger->now_going = false; + char *arg_1 = s_params.value(1).toUtf8().data(); + break_point_t *bp = get_break_point(debugger, cmd.toUtf8().data()); + if(num == 2 && strcasecmp(arg_1, _T("ALL"))) { + memset(bp->table, 0, sizeof(bp->table)); + } else if(num >= 2) { + char *arg_n; + for(int i = 1; i < num; i++) { + arg_n = s_params.value(i).toUtf8().data(); + if(arg_n == NULL) break; + int index = my_hexatoi(arg_n); + if(!(index >= 1 && index <= MAX_BREAK_POINTS)) { + my_printf( _T("invalid index %x\n"), index); + } else { + bp->table[index - 1].addr = bp->table[index - 1].mask = 0; + bp->table[index - 1].status = 0; + } + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("BD") || cmd == QString::fromUtf8("RBD") || cmd == QString::fromUtf8("WBD") || cmd == QString::fromUtf8("IBD") || cmd == QString::fromUtf8("OBD") || + cmd == QString::fromUtf8("BE") || cmd == QString::fromUtf8("RBE") || cmd == QString::fromUtf8("WBE") || cmd == QString::fromUtf8("IBE") || cmd == QString::fromUtf8("OBE")) { + debugger->now_going = false; + break_point_t *bp = get_break_point(debugger, cmd.toUtf8().data()); + QString m1 = cmd.mid(1, 1); + QString m2 = cmd.mid(2, 1); + + bool enabled = (m1 == QString::fromUtf8("E") || m1 == QString::fromUtf8("e") || + m2 == QString::fromUtf8("E") || m2 == QString::fromUtf8("e")); + char *arg_1 = s_params.value(1).toUtf8().data(); + if(num == 2 && strcasecmp(arg_1, _T("ALL"))) { + for(int i = 0; i < MAX_BREAK_POINTS; i++) { + if(bp->table[i].status != 0) { + bp->table[i].status = enabled ? 1 : -1; + } + } + } else if(num >= 2) { + for(int i = 1; i < num; i++) { + char *arg_n = s_params.value(i).toUtf8().data(); + if(arg_n == NULL) break; + int index = my_hexatoi(arg_n); + if(!(index >= 1 && index <= MAX_BREAK_POINTS)) { + my_printf( _T("invalid index %x\n"), index); + } else if(bp->table[index - 1].status == 0) { + my_printf( _T("break point %x is null\n"), index); + } else { + bp->table[index - 1].status = enabled ? 1 : -1; + } + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("BL") || cmd == QString::fromUtf8("RBL") || cmd == QString::fromUtf8("WBL")) { + debugger->now_going = false; + if(num == 1) { + break_point_t *bp = get_break_point(debugger, cmd.toUtf8().data()); + for(int i = 0; i < MAX_BREAK_POINTS; i++) { + if(bp->table[i].status) { + my_printf( _T("%d %c %08X\n"), i + 1, bp->table[i].status == 1 ? _T('e') : _T('d'), bp->table[i].addr); + } + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("IBL") || cmd == QString::fromUtf8("OBL")) { + if(num == 1) { + break_point_t *bp = get_break_point(debugger, cmd.toUtf8().data()); + for(int i = 0; i < MAX_BREAK_POINTS; i++) { + if(bp->table[i].status) { + my_printf( _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); + } + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("G")) { + if(num == 1 || num == 2) { + if(num >= 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + debugger->store_break_points(); + debugger->bp.table[0].addr = my_hexatoi(arg_1) & prog_addr_mask; + debugger->bp.table[0].mask = prog_addr_mask; + debugger->bp.table[0].status = 1; + } + debugger->now_going = true; + debugger->now_suspended = false; + trace_steps = -1; + pausing = true; + emit sig_start_trap(); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("T")) { + if(num == 1 || num == 2) { + int steps = 1; + if(num >= 2) { + char *arg_1 = s_params.value(1).toUtf8().data(); + steps = my_hexatoi(arg_1); + } + if(steps >= 1) trace_steps = steps; + debugger->now_going = false; + debugger->now_suspended = false; + emit sig_start_trap(); + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(cmd == QString::fromUtf8("Q")) { + debugger->now_going = false; + p->running = false; + p->request_terminate = true; + this->request_terminate = true; + emit quit_debugger_thread(); + return -1; + } else if(cmd == QString::fromUtf8(">")) { + if(num >= 2) { + if(logfile != NULL) { + if(logfile->IsOpened()) { + logfile->Fclose(); + } + delete logfile; + logfile = NULL; + } + logfile = new FILEIO(); + logfile->Fopen(s_params.value(1).toUtf8().data(), FILEIO_WRITE_ASCII); + my_printf(_T("Log Opened %s .\n"), s_params.value(1).toUtf8().data()); + } else { + if(logfile != NULL) { + if(logfile->IsOpened()) { + logfile->Fclose(); + } + delete logfile; + logfile = NULL; + my_printf(_T("LOG closed.\n")); + } else { + my_printf(_T("invalid parameter number\n")); + } + } + } else if(cmd == QString::fromUtf8("!")) { + char *arg_1 = s_params.value(1).toUtf8().data(); + char *arg_2 = s_params.value(2).toUtf8().data(); + debugger->now_going = false; + if(num == 1) { + my_printf( _T("invalid parameter number\n")); + } else if(strcasecmp(arg_1, _T("RESET"))) { + if(num == 2) { + p->vm->reset(); + } else if(num == 3) { + if(strcasecmp(arg_2, _T("ALL"))) { + p->vm->reset(); + } if(strcasecmp(arg_2, _T("CPU"))) { + cpu->reset(); + } else { + my_printf( _T("unknown device %s\n"), arg_2); + } + } else { + my_printf( _T("invalid parameter number\n")); + } + } else if(strcasecmp(arg_1, _T("KEY"))) { + if(num == 3 || num == 4) { + int code = my_hexatoi(arg_1) & 0xff, msec = 100; + if(num == 4) { + char *arg_3 = s_params.value(3).toUtf8().data(); + msec = my_hexatoi(arg_3); + } +#ifdef SUPPORT_VARIABLE_TIMING + //p->emu->key_buffer()[code] = (int)fmax(p->vm->frame_rate() * (double)msec / 1000.0 + 0.5, 1.0); +#else + //p->emu->key_buffer()[code] = (int)fmax(FRAMES_PER_SEC * (double)msec / 1000.0 + 0.5, 1.0); +#endif +#ifdef NOTIFY_KEY_DOWN + p->vm->key_down(code, false); +#endif + } else { + my_printf( _T("invalid parameter number\n")); + } + } else { + my_printf( _T("unknown command ! %s\n"), arg_1); + } + } else if(cmd == QString::fromUtf8("?")) { + debugger->now_going = false; + my_printf( _T("D [] - dump memory\n")); + my_printf( _T("E[{B,W,D}]
- edit memory (byte,word,dword)\n")); + my_printf( _T("EA
\"\" - edit memory (ascii)\n")); + my_printf( _T("I[{B,W,D}] - input port (byte,word,dword)\n")); + my_printf( _T("O[{B,W,D}] - output port (byte,word,dword)\n")); + my_printf( _T("R - show register(s)\n")); + my_printf( _T("R - edit register\n")); + my_printf( _T("S - search\n")); + my_printf( _T("U [] - unassemble\n")); + my_printf( _T("UW [] [] filename - unassemble to file\n")); + + my_printf( _T("H - hexadd\n")); + my_printf( _T("N - name\n")); + my_printf( _T("L - load file\n")); + my_printf( _T("W - write file\n")); + + my_printf( _T("BP
- set breakpoint\n")); + my_printf( _T("{R,W}BP
- set breakpoint (break at memory access)\n")); + my_printf( _T("{I,O}BP [] - set breakpoint (break at i/o access)\n")); + my_printf( _T("[{R,W,I,O}]B{C,D,E} {all,} - clear/disable/enable breakpoint(s)\n")); + my_printf( _T("[{R,W,I,O}]BL - list breakpoint(s)\n")); + + my_printf( _T("G - go (press return key to break)\n")); + my_printf( _T("G
- go and break at address\n")); + my_printf( _T("T [] - trace\n")); + my_printf( _T("Q - quit\n")); + + my_printf( _T("! reset [cpu] - reset\n")); + my_printf( _T("! key [] - press key\n")); + + my_printf( _T(" - hexa, decimal(%%d), ascii('a')\n")); + } else { + my_printf( _T("unknown command %s\n"), cmd.toUtf8().data()); + } + } + p->running = false; + emit sig_text_clear(); + + return 0; +} + +void CSP_DebuggerThread::getRegisterInfo() +{ + _TCHAR buffer[2048]; + uint32 p_pc = cpu->get_pc(); + + memset(buffer, 0x00, sizeof(buffer)); + + cpu->debug_regs_info(buffer, 2048); + my_printf(_T("CPU Domain #%d\n%s\n"), cpu_index, buffer); + + + my_printf(_T("breaked at %08X\n"), p_pc); + + memset(buffer, 0x00, sizeof(buffer)); + cpu->debug_dasm(p_pc, buffer, 2048); + my_printf(_T("%s\nnext\t%08X\n"), buffer, cpu->get_next_pc()); +} + +void CSP_DebuggerThread::quit_debugger() +{ + debugger->now_going = false; + d_params->running = false; + d_params->request_terminate = true; + this->request_terminate = true; + //this->wait(1000); + emit quit_debugger_thread(); + //debugger_main(QString::fromUtf8("Q")); +} + +void CSP_DebuggerThread::do_string_input(QString s) +{ + if(pausing) { + pausing = false; + getRegisterInfo(); + return; + } + debugger_main(s); +} + +void CSP_DebuggerThread::run() +{ + QString str = QString::fromUtf8(_T("Debugger CPU #")) + QString::number(cpu_index); + emit sig_set_title(str); + + pausing = false; + d_params->running = true; + d_params->request_terminate = false; + this->request_terminate = false; + dasm_addr = cpu->get_next_pc(); + this->getRegisterInfo(); + debugger->now_going = false; + debugger->now_debugging = true; + + while(!this->request_terminate) { + this->msleep(10); + } + //emit quit_debugger_thread(); + this->quit(); +} + +CSP_DebuggerThread::CSP_DebuggerThread(QObject *parent, debugger_thread_t *th) : QThread(parent) +{ + logfile = NULL; + d_params = th; + cpu = d_params->vm->get_cpu(d_params->cpu_index); + cpu_index = d_params->cpu_index; + debugger = (DEBUGGER *)cpu->get_debugger(); + + trap_timer = new QTimer(this); + trap_timer->setInterval(3); + trap_timer->setSingleShot(false); + prev_command.clear(); + dump_addr = 0; + dasm_addr = 0; + pausing = false; + + trace_steps = 0; + connect(this, SIGNAL(sig_start_trap()), trap_timer, SLOT(start())); + connect(this, SIGNAL(sig_end_trap()), this, SLOT(display_break_point())); + connect(trap_timer, SIGNAL(timeout()), this, SLOT(check_trap())); + connect(this, SIGNAL(started()), this, SLOT(run())); +} + +CSP_DebuggerThread::~CSP_DebuggerThread() +{ + if(logfile != NULL) { + if(logfile->IsOpened()) { + logfile->Fclose(); + } + delete logfile; + logfile = NULL; + } + trap_timer->stop(); + delete trap_timer; +} + +void EMU::initialize_debugger() +{ + now_debugging = false; +} + diff --git a/source/src/qt/debugger/qt_debugger.cpp b/source/src/qt/debugger/qt_debugger.cpp index 184afbddd..b78b33721 100644 --- a/source/src/qt/debugger/qt_debugger.cpp +++ b/source/src/qt/debugger/qt_debugger.cpp @@ -22,7 +22,8 @@ #include "../../vm/vm.h" #include "../../fileio.h" #include "qt_debugger.h" -#include "osd.h" +//#include +//#include #ifdef USE_DEBUGGER @@ -39,9 +40,24 @@ void CSP_Debugger::cmd_clear() text->moveCursor(QTextCursor::End); } + +void CSP_Debugger::doExit2(void) +{ + emit sig_close_debugger(); +} + void CSP_Debugger::doExit(void) { - //p_emu->close_debugger(); + DEVICE *cpu = debugger_thread_param.vm->get_cpu(debugger_thread_param.cpu_index); + DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger(); + debugger_thread_param.request_terminate = true; + + try { + debugger->now_debugging = debugger->now_going = debugger->now_suspended = false; + } catch(...) { + } + // release console + debugger_thread_param.running = false; emit sig_finished(); } @@ -52,32 +68,47 @@ void CSP_Debugger::stop_polling() void CSP_Debugger::call_debugger(void) { - emit sig_call_debugger(text_command->text()); + //emit sig_call_debugger(text_command->text()); + main_thread->call_debugger(text_command->text()); } void CSP_Debugger::run(void) { + main_thread = new CSP_DebuggerThread(NULL, &debugger_thread_param); + main_thread->setObjectName(QString::fromUtf8("Debugger")); + main_thread->moveToThread(main_thread); + //main_thread = new CSP_DebuggerThread(this, &debugger_thread_param); + connect(text_command, SIGNAL(editingFinished()), this, SLOT(call_debugger())); - connect(this, SIGNAL(sig_call_debugger(QString)), p_osd, SLOT(do_write_inputdata(QString)), Qt::DirectConnection); + connect(this, SIGNAL(sig_call_debugger(QString)), main_thread, SLOT(call_debugger(QString))); + + connect(main_thread, SIGNAL(sig_text_clear()), this, SLOT(cmd_clear())); + connect(main_thread, SIGNAL(sig_put_string(QString)), this, SLOT(put_string(QString))); + + connect(main_thread, SIGNAL(finished()), this, SLOT(doExit())); + connect(main_thread, SIGNAL(quit_debugger_thread()), this, SLOT(doExit())); - connect(p_osd, SIGNAL(sig_debugger_finished()), this, SLOT(doExit())); - connect(this, SIGNAL(sig_finished()), p_osd, SLOT(do_close_debugger_thread())); - connect(this, SIGNAL(destroyed()), this, SLOT(doExit())); - connect(parent_object, SIGNAL(quit_debugger_thread()), this, SLOT(close())); connect(this, SIGNAL(sig_finished()), this, SLOT(close())); + connect(this, SIGNAL(destroyed()), this, SLOT(doExit())); + connect(this, SIGNAL(sig_close_debugger()), main_thread, SLOT(quit_debugger())); + //connect(parent_object, SIGNAL(quit_debugger_thread()), this, SLOT(doExit2())); + connect(parent_object, SIGNAL(quit_debugger_thread()), this, SLOT(close())); + + connect(this, SIGNAL(sig_start_debugger()), main_thread, SLOT(start())); + main_thread->start(); //emit sig_start_debugger(); } void CSP_Debugger::closeEvent(QCloseEvent *event) { + main_thread->terminate(); doExit(); } -CSP_Debugger::CSP_Debugger(QWidget *parent, OSD *osd) : QWidget(parent, Qt::Window) +CSP_Debugger::CSP_Debugger(QWidget *parent) : QWidget(parent, Qt::Window) { widget = this; - p_osd = osd; parent_object = parent; text = new QTextEdit(this); @@ -91,6 +122,7 @@ CSP_Debugger::CSP_Debugger(QWidget *parent, OSD *osd) : QWidget(parent, Qt::Wind text_command->setReadOnly(false); text_command->setEnabled(true); text_command->clear(); + //connect(text_command, SIGNAL(editingFinished()), this, SLOT(call_debugger())); VBoxWindow = new QVBoxLayout; diff --git a/source/src/qt/debugger/qt_debugger.h b/source/src/qt/debugger/qt_debugger.h index cb168bf3b..fbd7af0b8 100644 --- a/source/src/qt/debugger/qt_debugger.h +++ b/source/src/qt/debugger/qt_debugger.h @@ -27,9 +27,55 @@ #include "../../vm/debugger.h" #include "../../vm/vm.h" #include "../../fileio.h" -#include "osd.h" #define MAX_COMMAND_LEN 64 + +class CSP_DebuggerThread : public QThread +{ + Q_OBJECT + +protected: + debugger_thread_t *d_params; + DEBUGGER *debugger; + DEVICE *cpu; + uint32 cpu_index; + bool pausing; + + FILEIO *logfile; + QTimer *trap_timer; + QString prev_command; + uint32 dump_addr; + uint32 dasm_addr; + int trace_steps; + bool request_terminate; + + break_point_t *get_break_point(DEBUGGER *debugger, _TCHAR *command); + uint32 my_hexatoi(_TCHAR *str); + void my_putch(_TCHAR c); + void my_printf(const _TCHAR *format, ...); + void getRegisterInfo(); + void display_break_status(void); + void display_pc(void); + +public: + CSP_DebuggerThread(QObject *parent, debugger_thread_t *th); + ~CSP_DebuggerThread(); +public slots: + void run(); + virtual int debugger_main(QString command); + void call_debugger(QString); + void check_trap(); + void display_break_point(); + void quit_debugger(); + void do_string_input(QString s); +signals: + int sig_start_trap(); + int sig_end_trap(); + int sig_text_clear(); + int sig_put_string(QString); + int quit_debugger_thread(); + void sig_set_title(QString); +}; class CSP_Debugger : public QWidget { @@ -40,17 +86,20 @@ class CSP_Debugger : public QWidget QTextEdit *text; QLineEdit *text_command; QVBoxLayout *VBoxWindow; - OSD *p_osd; + CSP_DebuggerThread *main_thread; protected: //QFont font;// = QApplication::font(); //QMainWindow *debug_window; public: - CSP_Debugger(QWidget *parent, OSD *osd); + CSP_Debugger(QWidget *parent); ~CSP_Debugger(); + debugger_thread_t debugger_thread_param; void closeEvent(QCloseEvent *event); + public slots: void doExit(void); + void doExit2(void); void stop_polling(); void put_string(QString); void cmd_clear(); diff --git a/source/src/qt/osd.cpp b/source/src/qt/osd.cpp index 712238a7c..696b94ee0 100644 --- a/source/src/qt/osd.cpp +++ b/source/src/qt/osd.cpp @@ -52,6 +52,9 @@ void OSD::set_draw_thread(DrawThreadClass *handler) connect(this, SIGNAL(sig_save_screen(const char *)), glv, SLOT(do_save_frame_screen(const char *))); connect(this, SIGNAL(sig_close_window()), parent_thread, SLOT(doExit())); connect(this, SIGNAL(sig_resize_vm_screen(QImage *, int, int)), glv, SLOT(do_set_texture_size(QImage *, int, int))); + connect(this, SIGNAL(sig_console_input_string(QString)), parent_thread, SLOT(do_call_debugger_command(QString))); + connect(parent_thread, SIGNAL(sig_debugger_input(QString)), this, SLOT(do_set_input_string(QString))); + connect(parent_thread, SIGNAL(sig_quit_debugger()), this, SLOT(do_close_debugger_thread())); } void OSD::initialize(int rate, int samples) @@ -69,7 +72,7 @@ void OSD::initialize(int rate, int samples) memset(app_path, 0x00, sizeof(app_path)); strncpy(app_path, tmp_path.toUtf8().constData(), _MAX_PATH); - osd_console_input = NULL; + memset(console_string, 0x00, sizeof(console_string)); osd_console_opened = false; //CoInitialize(NULL); initialize_input(); @@ -165,3 +168,30 @@ void OSD::create_date_file_name(_TCHAR *name, int length, const _TCHAR *extensio snprintf(name, length, _T("%s"), tmps.toLocal8Bit().constData()); } +void OSD::lock_vm(void) +{ + if(parent_thread != NULL) { + if(!parent_thread->now_debugging()) VMSemaphore->acquire(1); + } else { + VMSemaphore->acquire(1); + } +} + +void OSD::unlock_vm(void) +{ + if(parent_thread != NULL) { + if(!parent_thread->now_debugging()) VMSemaphore->release(1); + } else { + VMSemaphore->release(1); + } +} + +void OSD::force_unlock_vm(void) +{ + if(parent_thread == NULL) { + while(VMSemaphore->available() < 1) VMSemaphore->release(1); + return; + } + if(parent_thread->now_debugging()) return; + while(VMSemaphore->available() < 1) VMSemaphore->release(1); +} diff --git a/source/src/qt/osd.h b/source/src/qt/osd.h index 1ac3aa621..75587a2dc 100644 --- a/source/src/qt/osd.h +++ b/source/src/qt/osd.h @@ -167,7 +167,7 @@ protected: // console FILE *hStdIn, *hStdOut; - FIFO *osd_console_input; + char console_string[128]; bool osd_console_opened; // input void initialize_input(); @@ -574,20 +574,18 @@ public: void set_parent_thread(EmuThreadClass *parent); EmuThreadClass *get_parent_handler(); void set_draw_thread(DrawThreadClass *handler); - void lock_vm(void){ - VMSemaphore->acquire(1); - } - void unlock_vm(void){ - VMSemaphore->release(1); - } - void force_unlock_vm(void){ - while(VMSemaphore->available() < 1) VMSemaphore->release(1); - } + _TCHAR *console_input_string(void); + void clear_console_input_string(void); + void lock_vm(void); + void unlock_vm(void); + void force_unlock_vm(void); + public slots: #ifdef USE_AUTO_KEY void set_auto_key_string(QByteArray); #endif void do_write_inputdata(QString s); + void do_set_input_string(QString s); void do_close_debugger_console(); void do_close_debugger_thread(); @@ -597,6 +595,7 @@ signals: int sig_close_window(void); int sig_resize_vm_screen(QImage *, int, int); int sig_put_string_debugger(QString); + int sig_console_input_string(QString); int sig_debugger_finished(); }; QT_END_NAMESPACE diff --git a/source/src/qt/osd_console.cpp b/source/src/qt/osd_console.cpp index 1a896aa93..02ec1ed0b 100644 --- a/source/src/qt/osd_console.cpp +++ b/source/src/qt/osd_console.cpp @@ -22,29 +22,37 @@ extern EMU *emu; void OSD::do_write_inputdata(QString s) { int i; - QByteArray p = s.toUtf8(); - //printf("%s\n", p.constData()); - //lock_vm(); - for(i = 0; i < p.length(); i++){ - osd_console_input->write(p.at(i)); - printf("%c", p.at(i)); - } - //unlock_vm(); + emit sig_console_input_string(s); } -void OSD::open_console(_TCHAR* title) +void OSD::do_set_input_string(QString s) +{ + memset(console_string, 0x00, sizeof(console_string)); + strncpy(console_string, s.toLocal8Bit().constData(), sizeof(console_string) - 1); +} + +_TCHAR *OSD::console_input_string(void) +{ + if(strlen(console_string) <= 0) return NULL; + return console_string; +} + +void OSD::clear_console_input_string(void) { + memset(console_string, 0x00, sizeof(console_string)); +} - if(osd_console_opened || (osd_console_input != NULL)) return; +void OSD::open_console(_TCHAR* title) +{ + if(osd_console_opened) return; + memset(console_string, 0x00, sizeof(console_string)); osd_console_opened = true; - osd_console_input = new FIFO(65536); + } void OSD::close_console() { - osd_console_input->release(); - delete osd_console_input; - osd_console_input = NULL; + memset(console_string, 0x00, sizeof(console_string)); osd_console_opened = false; } @@ -73,13 +81,7 @@ void OSD::write_console(_TCHAR* buffer, unsigned int length) int OSD::read_console_input(_TCHAR* buffer) { int i; - int count; - //lock_vm(); - count = osd_console_input->count(); - for(i = 0; i < count; i++) { - buffer[i] = (_TCHAR)osd_console_input->read(); - } - //unlock_vm(); + int count = 0; return count; } @@ -91,6 +93,9 @@ void OSD::do_close_debugger_console() void OSD::do_close_debugger_thread() { #if defined(USE_DEBUGGER) - emu->close_debugger(); + //if(emu->debugger_thread_param.request_terminate == true) { + emit sig_debugger_finished(); + //} + //emu->close_debugger(); #endif } -- 2.11.0