diff options
| author | 2014-04-03 21:24:07 -0400 | |
|---|---|---|
| committer | 2014-04-03 21:25:40 -0400 | |
| commit | 1c7120b3aab46e7470ad8dccaa047fdbeb9b7ff5 (patch) | |
| tree | a79e840c63f98e1d8eac8a7f9a889e142d01b685 /src | |
| parent | Add Core::GetState() for debugger (diff) | |
| download | yuzu-1c7120b3aab46e7470ad8dccaa047fdbeb9b7ff5.tar.gz yuzu-1c7120b3aab46e7470ad8dccaa047fdbeb9b7ff5.tar.xz yuzu-1c7120b3aab46e7470ad8dccaa047fdbeb9b7ff5.zip | |
More Qt changes for debugger
Diffstat (limited to 'src')
| -rw-r--r-- | src/citra_qt/src/bootmanager.cpp | 64 | ||||
| -rw-r--r-- | src/citra_qt/src/bootmanager.hxx | 8 | ||||
| -rw-r--r-- | src/citra_qt/src/cpu_regs.cpp | 86 | ||||
| -rw-r--r-- | src/citra_qt/src/disasm.cpp | 126 | ||||
| -rw-r--r-- | src/citra_qt/src/disasm.hxx | 6 | ||||
| -rw-r--r-- | src/citra_qt/src/main.cpp | 51 | ||||
| -rw-r--r-- | src/citra_qt/src/main.hxx | 4 | ||||
| -rw-r--r-- | src/citra_qt/src/main.ui | 21 | ||||
| -rw-r--r-- | src/citra_qt/src/ui_main.h | 11 |
9 files changed, 190 insertions, 187 deletions
diff --git a/src/citra_qt/src/bootmanager.cpp b/src/citra_qt/src/bootmanager.cpp index cda618778..56356ae35 100644 --- a/src/citra_qt/src/bootmanager.cpp +++ b/src/citra_qt/src/bootmanager.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #define APP_TITLE APP_NAME " " APP_VERSION | 14 | #define APP_TITLE APP_NAME " " APP_VERSION |
| 15 | #define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" | 15 | #define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" |
| 16 | 16 | ||
| 17 | EmuThread::EmuThread(GRenderWindow* render_window) : exec_cpu_step(false), cpu_running(true), render_window(render_window) | 17 | EmuThread::EmuThread(GRenderWindow* render_window) : exec_cpu_step(false), cpu_running(false), render_window(render_window) |
| 18 | { | 18 | { |
| 19 | } | 19 | } |
| 20 | 20 | ||
| @@ -25,61 +25,23 @@ void EmuThread::SetFilename(const char* filename) | |||
| 25 | 25 | ||
| 26 | void EmuThread::run() | 26 | void EmuThread::run() |
| 27 | { | 27 | { |
| 28 | //u32 tight_loop; | ||
| 29 | |||
| 30 | NOTICE_LOG(MASTER_LOG, APP_NAME " starting...\n"); | ||
| 31 | |||
| 32 | if (Core::Init(/*render_window*/)) { | ||
| 33 | ERROR_LOG(MASTER_LOG, "core initialization failed, exiting..."); | ||
| 34 | Core::Stop(); | ||
| 35 | exit(1); | ||
| 36 | } | ||
| 37 | |||
| 38 | // Load a game or die... | ||
| 39 | std::string boot_filename = filename; | ||
| 40 | std::string error_str; | ||
| 41 | bool res = Loader::LoadFile(boot_filename, &error_str); | ||
| 42 | |||
| 43 | if (!res) { | ||
| 44 | ERROR_LOG(BOOT, "Failed to load ROM: %s", error_str.c_str()); | ||
| 45 | } | ||
| 46 | |||
| 47 | Core::Start(); //autoboot for now | 28 | Core::Start(); //autoboot for now |
| 48 | 29 | ||
| 49 | for (int tight_loop = 0; tight_loop < 10000; ++tight_loop) { | 30 | while (true) |
| 50 | Core::SingleStep(); | 31 | { |
| 51 | } | 32 | for (int tight_loop = 0; tight_loop < 10000; ++tight_loop) |
| 52 | /* | 33 | { |
| 53 | while(core::SYS_DIE != core::g_state) | 34 | if (cpu_running || exec_cpu_step) |
| 54 | { | 35 | { |
| 55 | if (core::SYS_RUNNING == core::g_state) | 36 | if (exec_cpu_step) |
| 56 | { | 37 | exec_cpu_step = false; |
| 57 | if(!cpu->is_on) | 38 | |
| 58 | { | 39 | Core::SingleStep(); |
| 59 | cpu->Start(); // Initialize and start CPU. | 40 | emit CPUStepped(); |
| 60 | } | ||
| 61 | else | ||
| 62 | { | ||
| 63 | for(tight_loop = 0; tight_loop < 10000; ++tight_loop) | ||
| 64 | { | ||
| 65 | if (!cpu_running) | ||
| 66 | { | ||
| 67 | emit CPUStepped(); | ||
| 68 | exec_cpu_step = false; | ||
| 69 | cpu->step = true; | ||
| 70 | while (!exec_cpu_step && !cpu_running && core::SYS_DIE != core::g_state); | ||
| 71 | } | ||
| 72 | cpu->execStep(); | ||
| 73 | cpu->step = false; | ||
| 74 | } | ||
| 75 | } | 41 | } |
| 76 | } | ||
| 77 | else if (core::SYS_HALTED == core::g_state) | ||
| 78 | { | ||
| 79 | core::Stop(); | ||
| 80 | } | 42 | } |
| 81 | } | 43 | } |
| 82 | */ | 44 | |
| 83 | Core::Stop(); | 45 | Core::Stop(); |
| 84 | } | 46 | } |
| 85 | 47 | ||
diff --git a/src/citra_qt/src/bootmanager.hxx b/src/citra_qt/src/bootmanager.hxx index 943945961..b3aa1cf30 100644 --- a/src/citra_qt/src/bootmanager.hxx +++ b/src/citra_qt/src/bootmanager.hxx | |||
| @@ -40,6 +40,14 @@ public: | |||
| 40 | */ | 40 | */ |
| 41 | void SetCpuRunning(bool running) { cpu_running = running; } | 41 | void SetCpuRunning(bool running) { cpu_running = running; } |
| 42 | 42 | ||
| 43 | /** | ||
| 44 | * Allow the CPU to continue processing instructions without interruption | ||
| 45 | * | ||
| 46 | * @note This function is thread-safe | ||
| 47 | */ | ||
| 48 | bool IsCpuRunning() { return cpu_running; } | ||
| 49 | |||
| 50 | |||
| 43 | public slots: | 51 | public slots: |
| 44 | /** | 52 | /** |
| 45 | * Stop emulation and wait for the thread to finish. | 53 | * Stop emulation and wait for the thread to finish. |
diff --git a/src/citra_qt/src/cpu_regs.cpp b/src/citra_qt/src/cpu_regs.cpp index 5d240b4bc..ba0e8d702 100644 --- a/src/citra_qt/src/cpu_regs.cpp +++ b/src/citra_qt/src/cpu_regs.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include "cpu_regs.hxx" | 1 | #include "cpu_regs.hxx" |
| 2 | 2 | ||
| 3 | //#include "powerpc/cpu_core_regs.h" | 3 | #include "core.h" |
| 4 | #include "arm/armdefs.h" | ||
| 4 | 5 | ||
| 5 | GARM11RegsView::GARM11RegsView(QWidget* parent) : QDockWidget(parent) | 6 | GARM11RegsView::GARM11RegsView(QWidget* parent) : QDockWidget(parent) |
| 6 | { | 7 | { |
| @@ -8,57 +9,54 @@ GARM11RegsView::GARM11RegsView(QWidget* parent) : QDockWidget(parent) | |||
| 8 | 9 | ||
| 9 | tree = cpu_regs_ui.treeWidget; | 10 | tree = cpu_regs_ui.treeWidget; |
| 10 | tree->addTopLevelItem(registers = new QTreeWidgetItem(QStringList("Registers"))); | 11 | tree->addTopLevelItem(registers = new QTreeWidgetItem(QStringList("Registers"))); |
| 11 | tree->addTopLevelItem(CSPR = new QTreeWidgetItem(QStringList("CSPR"))); | 12 | tree->addTopLevelItem(CSPR = new QTreeWidgetItem(QStringList("CSPR"))); |
| 12 | 13 | ||
| 13 | //const Qt::ItemFlags child_flags = Qt::ItemIsEditable | Qt::ItemIsEnabled; | 14 | registers->setExpanded(true); |
| 14 | //registers->setFlags(child_flags); | 15 | CSPR->setExpanded(true); |
| 15 | //CSPR->setFlags(child_flags); | ||
| 16 | 16 | ||
| 17 | for (int i = 0; i < 16; ++i) | 17 | for (int i = 0; i < 16; ++i) |
| 18 | { | 18 | { |
| 19 | QTreeWidgetItem* child = new QTreeWidgetItem(QStringList(QString("R[%1]").arg(i, 2, 10, QLatin1Char('0')))); | 19 | QTreeWidgetItem* child = new QTreeWidgetItem(QStringList(QString("R[%1]").arg(i, 2, 10, QLatin1Char('0')))); |
| 20 | //child->setFlags(child_flags); | ||
| 21 | registers->addChild(child); | 20 | registers->addChild(child); |
| 22 | } | 21 | } |
| 23 | 22 | ||
| 24 | CSPR->addChild(new QTreeWidgetItem(QStringList("M"))); | 23 | CSPR->addChild(new QTreeWidgetItem(QStringList("M"))); |
| 25 | CSPR->addChild(new QTreeWidgetItem(QStringList("T"))); | 24 | CSPR->addChild(new QTreeWidgetItem(QStringList("T"))); |
| 26 | CSPR->addChild(new QTreeWidgetItem(QStringList("F"))); | 25 | CSPR->addChild(new QTreeWidgetItem(QStringList("F"))); |
| 27 | CSPR->addChild(new QTreeWidgetItem(QStringList("I"))); | 26 | CSPR->addChild(new QTreeWidgetItem(QStringList("I"))); |
| 28 | CSPR->addChild(new QTreeWidgetItem(QStringList("A"))); | 27 | CSPR->addChild(new QTreeWidgetItem(QStringList("A"))); |
| 29 | CSPR->addChild(new QTreeWidgetItem(QStringList("E"))); | 28 | CSPR->addChild(new QTreeWidgetItem(QStringList("E"))); |
| 30 | CSPR->addChild(new QTreeWidgetItem(QStringList("IT"))); | 29 | CSPR->addChild(new QTreeWidgetItem(QStringList("IT"))); |
| 31 | CSPR->addChild(new QTreeWidgetItem(QStringList("GE"))); | 30 | CSPR->addChild(new QTreeWidgetItem(QStringList("GE"))); |
| 32 | CSPR->addChild(new QTreeWidgetItem(QStringList("DNM"))); | 31 | CSPR->addChild(new QTreeWidgetItem(QStringList("DNM"))); |
| 33 | CSPR->addChild(new QTreeWidgetItem(QStringList("J"))); | 32 | CSPR->addChild(new QTreeWidgetItem(QStringList("J"))); |
| 34 | CSPR->addChild(new QTreeWidgetItem(QStringList("Q"))); | 33 | CSPR->addChild(new QTreeWidgetItem(QStringList("Q"))); |
| 35 | CSPR->addChild(new QTreeWidgetItem(QStringList("V"))); | 34 | CSPR->addChild(new QTreeWidgetItem(QStringList("V"))); |
| 36 | CSPR->addChild(new QTreeWidgetItem(QStringList("C"))); | 35 | CSPR->addChild(new QTreeWidgetItem(QStringList("C"))); |
| 37 | CSPR->addChild(new QTreeWidgetItem(QStringList("Z"))); | 36 | CSPR->addChild(new QTreeWidgetItem(QStringList("Z"))); |
| 38 | CSPR->addChild(new QTreeWidgetItem(QStringList("N"))); | 37 | CSPR->addChild(new QTreeWidgetItem(QStringList("N"))); |
| 39 | } | 38 | } |
| 40 | 39 | ||
| 41 | void GARM11RegsView::OnCPUStepped() | 40 | void GARM11RegsView::OnCPUStepped() |
| 42 | { | 41 | { |
| 43 | //TODO (Vail) replace values | 42 | ARMul_State* state = Core::GetState(); |
| 44 | int value = 0; | 43 | for (int i = 0; i < 16; ++i) |
| 45 | for (int i = 0; i < 16; ++i) | 44 | registers->child(i)->setText(1, QString("0x%1").arg(state->Reg[i], 8, 16, QLatin1Char('0'))); |
| 46 | registers->child(i)->setText(1, QString("0x%1").arg(i, 8, 16, QLatin1Char('0'))); | 45 | |
| 47 | 46 | CSPR->setText(1, QString("0x%1").arg(state->Cpsr, 8, 16, QLatin1Char('0'))); | |
| 48 | CSPR->child(0)->setText(1, QString("%1").arg(value)); | 47 | CSPR->child(0)->setText(1, QString("b%1").arg(state->Cpsr & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode |
| 49 | CSPR->child(1)->setText(1, QString("%1").arg(value)); | 48 | CSPR->child(1)->setText(1, QString("%1").arg((state->Cpsr >> 5) & 0x1)); // T - State |
| 50 | CSPR->child(2)->setText(1, QString("%1").arg(value)); | 49 | CSPR->child(2)->setText(1, QString("%1").arg((state->Cpsr >> 6) & 0x1)); // F - FIQ disable |
| 51 | CSPR->child(3)->setText(1, QString("%1").arg(value)); | 50 | CSPR->child(3)->setText(1, QString("%1").arg((state->Cpsr >> 7) & 0x1)); // I - IRQ disable |
| 52 | CSPR->child(4)->setText(1, QString("%1").arg(value)); | 51 | CSPR->child(4)->setText(1, QString("%1").arg((state->Cpsr >> 8) & 0x1)); // A - Imprecise abort |
| 53 | CSPR->child(5)->setText(1, QString("%1").arg(value)); | 52 | CSPR->child(5)->setText(1, QString("%1").arg((state->Cpsr >> 9) & 0x1)); // E - Data endianess |
| 54 | CSPR->child(6)->setText(1, QString("%1").arg(value)); | 53 | CSPR->child(6)->setText(1, QString("%1").arg((state->Cpsr >> 10) & 0x3F)); // IT - If-Then state (DNM) |
| 55 | CSPR->child(7)->setText(1, QString("%1").arg(value)); | 54 | CSPR->child(7)->setText(1, QString("%1").arg((state->Cpsr >> 16) & 0xF)); // GE - Greater-than-or-Equal |
| 56 | CSPR->child(8)->setText(1, QString("%1").arg(value)); | 55 | CSPR->child(8)->setText(1, QString("%1").arg((state->Cpsr >> 20) & 0xF)); // DNM - Do not modify |
| 57 | CSPR->child(9)->setText(1, QString("%1").arg(value)); | 56 | CSPR->child(9)->setText(1, QString("%1").arg((state->Cpsr >> 24) & 0x1)); // J - Java state |
| 58 | CSPR->child(10)->setText(1, QString("%1").arg(value)); | 57 | CSPR->child(10)->setText(1, QString("%1").arg((state->Cpsr >> 27) & 0x1)); // Q - Sticky overflow |
| 59 | CSPR->child(11)->setText(1, QString("%1").arg(value)); | 58 | CSPR->child(11)->setText(1, QString("%1").arg((state->Cpsr >> 28) & 0x1)); // V - Overflow |
| 60 | CSPR->child(12)->setText(1, QString("%1").arg(value)); | 59 | CSPR->child(12)->setText(1, QString("%1").arg((state->Cpsr >> 29) & 0x1)); // C - Carry/Borrow/Extend |
| 61 | CSPR->child(13)->setText(1, QString("%1").arg(value)); | 60 | CSPR->child(13)->setText(1, QString("%1").arg((state->Cpsr >> 30) & 0x1)); // Z - Zero |
| 62 | CSPR->child(14)->setText(1, QString("%1").arg(value)); | 61 | CSPR->child(14)->setText(1, QString("%1").arg((state->Cpsr >> 31) & 0x1)); // N - Negative/Less than |
| 63 | CSPR->child(15)->setText(1, QString("%1").arg(value)); | ||
| 64 | } | 62 | } |
diff --git a/src/citra_qt/src/disasm.cpp b/src/citra_qt/src/disasm.cpp index 6e4087b23..2d1c61a72 100644 --- a/src/citra_qt/src/disasm.cpp +++ b/src/citra_qt/src/disasm.cpp | |||
| @@ -8,12 +8,11 @@ | |||
| 8 | #include "common.h" | 8 | #include "common.h" |
| 9 | #include "mem_map.h" | 9 | #include "mem_map.h" |
| 10 | 10 | ||
| 11 | #include "core.h" | ||
| 11 | #include "break_points.h" | 12 | #include "break_points.h" |
| 12 | //#include "powerpc/cpu_core_regs.h" | 13 | #include "arm/armdefs.h" |
| 13 | #include "arm/disassembler/arm_disasm.h" | 14 | #include "arm/disassembler/arm_disasm.h" |
| 14 | 15 | ||
| 15 | //#include "powerpc/interpreter/cpu_int.h" | ||
| 16 | |||
| 17 | GDisAsmView::GDisAsmView(QWidget* parent, EmuThread& emu_thread) : QDockWidget(parent), base_addr(0), emu_thread(emu_thread) | 16 | GDisAsmView::GDisAsmView(QWidget* parent, EmuThread& emu_thread) : QDockWidget(parent), base_addr(0), emu_thread(emu_thread) |
| 18 | { | 17 | { |
| 19 | disasm_ui.setupUi(this); | 18 | disasm_ui.setupUi(this); |
| @@ -21,50 +20,83 @@ GDisAsmView::GDisAsmView(QWidget* parent, EmuThread& emu_thread) : QDockWidget(p | |||
| 21 | breakpoints = new BreakPoints(); | 20 | breakpoints = new BreakPoints(); |
| 22 | 21 | ||
| 23 | model = new QStandardItemModel(this); | 22 | model = new QStandardItemModel(this); |
| 24 | model->setColumnCount(3); | 23 | model->setColumnCount(2); |
| 25 | disasm_ui.treeView->setModel(model); | 24 | disasm_ui.treeView->setModel(model); |
| 26 | 25 | ||
| 26 | RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); | ||
| 27 | RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut); | 27 | RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut); |
| 28 | RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut); | 28 | RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut); |
| 29 | // RegisterHotkey("Disassembler", "Pause", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); | ||
| 30 | RegisterHotkey("Disassembler", "Continue", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut); | ||
| 31 | RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), Qt::ApplicationShortcut); | 29 | RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), Qt::ApplicationShortcut); |
| 32 | 30 | ||
| 33 | connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), this, SLOT(OnSetBreakpoint())); | 31 | connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), this, SLOT(OnSetBreakpoint())); |
| 34 | connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep())); | 32 | connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep())); |
| 35 | connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause())); | 33 | connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause())); |
| 36 | connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue())); | 34 | connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue())); |
| 35 | |||
| 36 | connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, SLOT(OnToggleStartStop())); | ||
| 37 | connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep())); | 37 | connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep())); |
| 38 | connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, SLOT(OnStepInto())); | 38 | connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, SLOT(OnStepInto())); |
| 39 | // connect(GetHotkey("Disassembler", "Pause", this), SIGNAL(activated()), this, SLOT(OnPause())); | ||
| 40 | connect(GetHotkey("Disassembler", "Continue", this), SIGNAL(activated()), this, SLOT(OnContinue())); | ||
| 41 | connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), this, SLOT(OnSetBreakpoint())); | 39 | connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), this, SLOT(OnSetBreakpoint())); |
| 42 | } | 40 | } |
| 43 | 41 | ||
| 42 | void GDisAsmView::Init() | ||
| 43 | { | ||
| 44 | ARMul_State* state = Core::GetState(); | ||
| 45 | Arm* disasm = new Arm(); | ||
| 46 | |||
| 47 | base_addr = state->pc; | ||
| 48 | unsigned int curInstAddr = base_addr; | ||
| 49 | char result[255]; | ||
| 50 | |||
| 51 | for (int i = 0; i < 10000; i++) // fixed for now | ||
| 52 | { | ||
| 53 | disasm->disasm(curInstAddr, Memory::Read32(curInstAddr), result); | ||
| 54 | model->setItem(i, 0, new QStandardItem(QString("0x%1").arg((uint)(curInstAddr), 8, 16, QLatin1Char('0')))); | ||
| 55 | model->setItem(i, 1, new QStandardItem(QString(result))); | ||
| 56 | curInstAddr += 4; | ||
| 57 | } | ||
| 58 | disasm_ui.treeView->resizeColumnToContents(0); | ||
| 59 | disasm_ui.treeView->resizeColumnToContents(1); | ||
| 60 | |||
| 61 | QModelIndex model_index = model->index(0, 0); | ||
| 62 | disasm_ui.treeView->scrollTo(model_index); | ||
| 63 | disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); | ||
| 64 | } | ||
| 65 | |||
| 44 | void GDisAsmView::OnSetBreakpoint() | 66 | void GDisAsmView::OnSetBreakpoint() |
| 45 | { | 67 | { |
| 46 | if (SelectedRow() == -1) | 68 | int selected_row = SelectedRow(); |
| 69 | |||
| 70 | if (selected_row == -1) | ||
| 47 | return; | 71 | return; |
| 48 | 72 | ||
| 49 | u32 address = base_addr + 4 * SelectedRow(); | 73 | u32 address = base_addr + (selected_row * 4); |
| 50 | if (breakpoints->IsAddressBreakPoint(address)) | 74 | if (breakpoints->IsAddressBreakPoint(address)) |
| 51 | { | 75 | { |
| 52 | breakpoints->Remove(address); | 76 | breakpoints->Remove(address); |
| 53 | model->item(SelectedRow(), 0)->setBackground(QBrush()); | 77 | model->item(selected_row, 0)->setBackground(QBrush()); |
| 54 | model->item(SelectedRow(), 1)->setBackground(QBrush()); | 78 | model->item(selected_row, 1)->setBackground(QBrush()); |
| 55 | model->item(SelectedRow(), 2)->setBackground(QBrush()); | ||
| 56 | } | 79 | } |
| 57 | else | 80 | else |
| 58 | { | 81 | { |
| 59 | breakpoints->Add(address); | 82 | breakpoints->Add(address); |
| 60 | model->item(SelectedRow(), 0)->setBackground(Qt::red); | 83 | model->item(selected_row, 0)->setBackground(QBrush(QColor(0xFF, 0x99, 0x99))); |
| 61 | model->item(SelectedRow(), 1)->setBackground(Qt::red); | 84 | model->item(selected_row, 1)->setBackground(QBrush(QColor(0xFF, 0x99, 0x99))); |
| 62 | model->item(SelectedRow(), 2)->setBackground(Qt::red); | ||
| 63 | } | 85 | } |
| 64 | } | 86 | } |
| 65 | 87 | ||
| 88 | void GDisAsmView::OnContinue() | ||
| 89 | { | ||
| 90 | emu_thread.SetCpuRunning(true); | ||
| 91 | } | ||
| 92 | |||
| 66 | void GDisAsmView::OnStep() | 93 | void GDisAsmView::OnStep() |
| 67 | { | 94 | { |
| 95 | OnStepInto(); // change later | ||
| 96 | } | ||
| 97 | |||
| 98 | void GDisAsmView::OnStepInto() | ||
| 99 | { | ||
| 68 | emu_thread.SetCpuRunning(false); | 100 | emu_thread.SetCpuRunning(false); |
| 69 | emu_thread.ExecStep(); | 101 | emu_thread.ExecStep(); |
| 70 | } | 102 | } |
| @@ -74,64 +106,24 @@ void GDisAsmView::OnPause() | |||
| 74 | emu_thread.SetCpuRunning(false); | 106 | emu_thread.SetCpuRunning(false); |
| 75 | } | 107 | } |
| 76 | 108 | ||
| 77 | void GDisAsmView::OnContinue() | 109 | void GDisAsmView::OnToggleStartStop() |
| 78 | { | 110 | { |
| 79 | emu_thread.SetCpuRunning(true); | 111 | emu_thread.SetCpuRunning(!emu_thread.IsCpuRunning()); |
| 80 | } | 112 | } |
| 81 | 113 | ||
| 82 | void GDisAsmView::OnCPUStepped() | 114 | void GDisAsmView::OnCPUStepped() |
| 83 | { | 115 | { |
| 84 | /* | 116 | ARMword next_instr = Core::GetState()->pc; |
| 85 | base_addr = ireg.PC - 52; | ||
| 86 | unsigned int curInstAddr = base_addr; | ||
| 87 | int counter = 0; | ||
| 88 | QModelIndex cur_instr_index; | ||
| 89 | model->setRowCount(100); | ||
| 90 | while(true) | ||
| 91 | { | ||
| 92 | u32 opcode = *(u32*)(&Mem_RAM[curInstAddr & RAM_MASK]); | ||
| 93 | |||
| 94 | char out1[64]; | ||
| 95 | char out2[128]; | ||
| 96 | u32 out3 = 0; | ||
| 97 | memset(out1, 0, sizeof(out1)); | ||
| 98 | memset(out2, 0, sizeof(out2)); | ||
| 99 | |||
| 100 | // NOTE: out3 (nextInstAddr) seems to be bugged, better don't use it... | ||
| 101 | DisassembleGekko(out1, out2, opcode, curInstAddr, &out3); | ||
| 102 | model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg((uint)curInstAddr, 8, 16, QLatin1Char('0')))); | ||
| 103 | model->setItem(counter, 1, new QStandardItem(QString(out1))); | ||
| 104 | model->setItem(counter, 2, new QStandardItem(QString(out2))); | ||
| 105 | |||
| 106 | if (ireg.PC == curInstAddr) | ||
| 107 | { | ||
| 108 | model->item(counter, 0)->setBackground(Qt::yellow); | ||
| 109 | model->item(counter, 1)->setBackground(Qt::yellow); | ||
| 110 | model->item(counter, 2)->setBackground(Qt::yellow); | ||
| 111 | cur_instr_index = model->index(counter, 0); | ||
| 112 | } | ||
| 113 | else if (Debugger::IsBreakpoint(curInstAddr)) | ||
| 114 | { | ||
| 115 | model->item(counter, 0)->setBackground(Qt::red); | ||
| 116 | model->item(counter, 1)->setBackground(Qt::red); | ||
| 117 | model->item(counter, 2)->setBackground(Qt::red); | ||
| 118 | } | ||
| 119 | else | ||
| 120 | { | ||
| 121 | model->item(counter, 0)->setBackground(QBrush()); | ||
| 122 | model->item(counter, 1)->setBackground(QBrush()); | ||
| 123 | model->item(counter, 2)->setBackground(QBrush()); | ||
| 124 | } | ||
| 125 | curInstAddr += 4; | ||
| 126 | 117 | ||
| 127 | ++counter; | 118 | if (breakpoints->IsAddressBreakPoint(next_instr)) |
| 128 | if (counter >= 100) break; | 119 | { |
| 120 | emu_thread.SetCpuRunning(false); | ||
| 129 | } | 121 | } |
| 130 | disasm_ui.treeView->resizeColumnToContents(0); | 122 | |
| 131 | disasm_ui.treeView->resizeColumnToContents(1); | 123 | unsigned int index = (next_instr - base_addr) / 4; |
| 132 | disasm_ui.treeView->resizeColumnToContents(2); | 124 | QModelIndex model_index = model->index(index, 0); |
| 133 | disasm_ui.treeView->scrollTo(cur_instr_index); // QAbstractItemView::PositionAtCenter? | 125 | disasm_ui.treeView->scrollTo(model_index); |
| 134 | */ | 126 | disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); |
| 135 | } | 127 | } |
| 136 | 128 | ||
| 137 | int GDisAsmView::SelectedRow() | 129 | int GDisAsmView::SelectedRow() |
diff --git a/src/citra_qt/src/disasm.hxx b/src/citra_qt/src/disasm.hxx index 648107114..0e4a0fc3d 100644 --- a/src/citra_qt/src/disasm.hxx +++ b/src/citra_qt/src/disasm.hxx | |||
| @@ -15,11 +15,15 @@ class GDisAsmView : public QDockWidget | |||
| 15 | public: | 15 | public: |
| 16 | GDisAsmView(QWidget* parent, EmuThread& emu_thread); | 16 | GDisAsmView(QWidget* parent, EmuThread& emu_thread); |
| 17 | 17 | ||
| 18 | void Init(); | ||
| 19 | |||
| 18 | public slots: | 20 | public slots: |
| 19 | void OnSetBreakpoint(); | 21 | void OnSetBreakpoint(); |
| 22 | void OnContinue(); | ||
| 20 | void OnStep(); | 23 | void OnStep(); |
| 24 | void OnStepInto(); | ||
| 21 | void OnPause(); | 25 | void OnPause(); |
| 22 | void OnContinue(); | 26 | void OnToggleStartStop(); |
| 23 | 27 | ||
| 24 | void OnCPUStepped(); | 28 | void OnCPUStepped(); |
| 25 | 29 | ||
diff --git a/src/citra_qt/src/main.cpp b/src/citra_qt/src/main.cpp index 02893809b..d7104eb02 100644 --- a/src/citra_qt/src/main.cpp +++ b/src/citra_qt/src/main.cpp | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include "callstack.hxx" | 19 | #include "callstack.hxx" |
| 20 | #include "ramview.hxx" | 20 | #include "ramview.hxx" |
| 21 | 21 | ||
| 22 | #include "system.h" | ||
| 23 | #include "loader.h" | ||
| 22 | #include "core.h" | 24 | #include "core.h" |
| 23 | #include "version.h" | 25 | #include "version.h" |
| 24 | 26 | ||
| @@ -31,11 +33,11 @@ GMainWindow::GMainWindow() | |||
| 31 | render_window = new GRenderWindow; | 33 | render_window = new GRenderWindow; |
| 32 | render_window->hide(); | 34 | render_window->hide(); |
| 33 | 35 | ||
| 34 | GDisAsmView* disasm = new GDisAsmView(this, render_window->GetEmuThread()); | 36 | disasm = new GDisAsmView(this, render_window->GetEmuThread()); |
| 35 | addDockWidget(Qt::BottomDockWidgetArea, disasm); | 37 | addDockWidget(Qt::BottomDockWidgetArea, disasm); |
| 36 | disasm->hide(); | 38 | disasm->hide(); |
| 37 | 39 | ||
| 38 | GARM11RegsView* arm_regs = new GARM11RegsView(this); | 40 | arm_regs = new GARM11RegsView(this); |
| 39 | addDockWidget(Qt::RightDockWidgetArea, arm_regs); | 41 | addDockWidget(Qt::RightDockWidgetArea, arm_regs); |
| 40 | arm_regs->hide(); | 42 | arm_regs->hide(); |
| 41 | 43 | ||
| @@ -75,8 +77,6 @@ GMainWindow::GMainWindow() | |||
| 75 | // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues | 77 | // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues |
| 76 | connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), disasm, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); | 78 | connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), disasm, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); |
| 77 | connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), arm_regs, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); | 79 | connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), arm_regs, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); |
| 78 | //connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), ram_edit, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); | ||
| 79 | //connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), callstack, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); | ||
| 80 | 80 | ||
| 81 | // Setup hotkeys | 81 | // Setup hotkeys |
| 82 | RegisterHotkey("Main Window", "Load Image", QKeySequence::Open); | 82 | RegisterHotkey("Main Window", "Load Image", QKeySequence::Open); |
| @@ -87,6 +87,8 @@ GMainWindow::GMainWindow() | |||
| 87 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); | 87 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); |
| 88 | 88 | ||
| 89 | show(); | 89 | show(); |
| 90 | |||
| 91 | System::Init(render_window); | ||
| 90 | } | 92 | } |
| 91 | 93 | ||
| 92 | GMainWindow::~GMainWindow() | 94 | GMainWindow::~GMainWindow() |
| @@ -100,6 +102,27 @@ void GMainWindow::BootGame(const char* filename) | |||
| 100 | { | 102 | { |
| 101 | render_window->DoneCurrent(); // make sure EmuThread can access GL context | 103 | render_window->DoneCurrent(); // make sure EmuThread can access GL context |
| 102 | render_window->GetEmuThread().SetFilename(filename); | 104 | render_window->GetEmuThread().SetFilename(filename); |
| 105 | |||
| 106 | NOTICE_LOG(MASTER_LOG, "citra starting...\n"); | ||
| 107 | |||
| 108 | if (Core::Init(/*render_window*/)) { | ||
| 109 | ERROR_LOG(MASTER_LOG, "core initialization failed, exiting..."); | ||
| 110 | Core::Stop(); | ||
| 111 | exit(1); | ||
| 112 | } | ||
| 113 | |||
| 114 | // Load a game or die... | ||
| 115 | std::string boot_filename = filename; | ||
| 116 | std::string error_str; | ||
| 117 | bool res = Loader::LoadFile(boot_filename, &error_str); | ||
| 118 | |||
| 119 | if (!res) { | ||
| 120 | ERROR_LOG(BOOT, "Failed to load ROM: %s", error_str.c_str()); | ||
| 121 | } | ||
| 122 | |||
| 123 | disasm->Init(); | ||
| 124 | arm_regs->OnCPUStepped(); | ||
| 125 | |||
| 103 | render_window->GetEmuThread().start(); | 126 | render_window->GetEmuThread().start(); |
| 104 | 127 | ||
| 105 | SetupEmuWindowMode(); | 128 | SetupEmuWindowMode(); |
| @@ -115,14 +138,30 @@ void GMainWindow::OnMenuLoadELF() | |||
| 115 | 138 | ||
| 116 | void GMainWindow::OnStartGame() | 139 | void GMainWindow::OnStartGame() |
| 117 | { | 140 | { |
| 141 | render_window->show(); | ||
| 142 | render_window->GetEmuThread().SetCpuRunning(true); | ||
| 143 | |||
| 144 | ui.action_Start->setEnabled(false); | ||
| 145 | ui.action_Pause->setEnabled(true); | ||
| 146 | ui.action_Stop->setEnabled(true); | ||
| 118 | } | 147 | } |
| 119 | 148 | ||
| 120 | void GMainWindow::OnPauseGame() | 149 | void GMainWindow::OnPauseGame() |
| 121 | { | 150 | { |
| 151 | render_window->GetEmuThread().SetCpuRunning(false); | ||
| 152 | |||
| 153 | ui.action_Start->setEnabled(true); | ||
| 154 | ui.action_Pause->setEnabled(false); | ||
| 155 | ui.action_Stop->setEnabled(true); | ||
| 122 | } | 156 | } |
| 123 | 157 | ||
| 124 | void GMainWindow::OnStopGame() | 158 | void GMainWindow::OnStopGame() |
| 125 | { | 159 | { |
| 160 | render_window->GetEmuThread().SetCpuRunning(false); | ||
| 161 | |||
| 162 | ui.action_Start->setEnabled(true); | ||
| 163 | ui.action_Pause->setEnabled(false); | ||
| 164 | ui.action_Stop->setEnabled(false); | ||
| 126 | } | 165 | } |
| 127 | 166 | ||
| 128 | void GMainWindow::OnOpenHotkeysDialog() | 167 | void GMainWindow::OnOpenHotkeysDialog() |
| @@ -134,8 +173,8 @@ void GMainWindow::OnOpenHotkeysDialog() | |||
| 134 | 173 | ||
| 135 | void GMainWindow::SetupEmuWindowMode() | 174 | void GMainWindow::SetupEmuWindowMode() |
| 136 | { | 175 | { |
| 137 | if (!render_window->GetEmuThread().isRunning()) | 176 | //if (!render_window->GetEmuThread().isRunning()) |
| 138 | return; | 177 | // return; |
| 139 | 178 | ||
| 140 | bool enable = ui.action_Single_Window_Mode->isChecked(); | 179 | bool enable = ui.action_Single_Window_Mode->isChecked(); |
| 141 | if (enable && render_window->parent() == NULL) // switch to single window mode | 180 | if (enable && render_window->parent() == NULL) // switch to single window mode |
diff --git a/src/citra_qt/src/main.hxx b/src/citra_qt/src/main.hxx index 81ee3860f..34bd2c3a4 100644 --- a/src/citra_qt/src/main.hxx +++ b/src/citra_qt/src/main.hxx | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | class GImageInfo; | 8 | class GImageInfo; |
| 9 | class GRenderWindow; | 9 | class GRenderWindow; |
| 10 | class GDisAsmView; | ||
| 11 | class GARM11RegsView; | ||
| 10 | 12 | ||
| 11 | class GMainWindow : public QMainWindow | 13 | class GMainWindow : public QMainWindow |
| 12 | { | 14 | { |
| @@ -42,6 +44,8 @@ private: | |||
| 42 | Ui::MainWindow ui; | 44 | Ui::MainWindow ui; |
| 43 | 45 | ||
| 44 | GRenderWindow* render_window; | 46 | GRenderWindow* render_window; |
| 47 | GDisAsmView* disasm; | ||
| 48 | GARM11RegsView* arm_regs; | ||
| 45 | }; | 49 | }; |
| 46 | 50 | ||
| 47 | #endif // _CITRA_QT_MAIN_HXX_ | 51 | #endif // _CITRA_QT_MAIN_HXX_ |
diff --git a/src/citra_qt/src/main.ui b/src/citra_qt/src/main.ui index 83d1e1f0c..bc895d89c 100644 --- a/src/citra_qt/src/main.ui +++ b/src/citra_qt/src/main.ui | |||
| @@ -87,14 +87,6 @@ | |||
| 87 | <string>&Start</string> | 87 | <string>&Start</string> |
| 88 | </property> | 88 | </property> |
| 89 | </action> | 89 | </action> |
| 90 | <action name="action_Stop"> | ||
| 91 | <property name="enabled"> | ||
| 92 | <bool>false</bool> | ||
| 93 | </property> | ||
| 94 | <property name="text"> | ||
| 95 | <string>&Stop</string> | ||
| 96 | </property> | ||
| 97 | </action> | ||
| 98 | <action name="action_Pause"> | 90 | <action name="action_Pause"> |
| 99 | <property name="enabled"> | 91 | <property name="enabled"> |
| 100 | <bool>false</bool> | 92 | <bool>false</bool> |
| @@ -102,11 +94,16 @@ | |||
| 102 | <property name="text"> | 94 | <property name="text"> |
| 103 | <string>&Pause</string> | 95 | <string>&Pause</string> |
| 104 | </property> | 96 | </property> |
| 105 | <property name="visible"> | ||
| 106 | <bool>false</bool> | ||
| 107 | </property> | ||
| 108 | </action> | 97 | </action> |
| 109 | <action name="action_About"> | 98 | <action name="action_Stop"> |
| 99 | <property name="enabled"> | ||
| 100 | <bool>false</bool> | ||
| 101 | </property> | ||
| 102 | <property name="text"> | ||
| 103 | <string>&Stop</string> | ||
| 104 | </property> | ||
| 105 | </action> | ||
| 106 | <action name="action_About"> | ||
| 110 | <property name="text"> | 107 | <property name="text"> |
| 111 | <string>About Citra</string> | 108 | <string>About Citra</string> |
| 112 | </property> | 109 | </property> |
diff --git a/src/citra_qt/src/ui_main.h b/src/citra_qt/src/ui_main.h index 693fa70bd..d349a5c6a 100644 --- a/src/citra_qt/src/ui_main.h +++ b/src/citra_qt/src/ui_main.h | |||
| @@ -29,8 +29,8 @@ public: | |||
| 29 | QAction *action_load_elf; | 29 | QAction *action_load_elf; |
| 30 | QAction *action_Exit; | 30 | QAction *action_Exit; |
| 31 | QAction *action_Start; | 31 | QAction *action_Start; |
| 32 | QAction *action_Stop; | ||
| 33 | QAction *action_Pause; | 32 | QAction *action_Pause; |
| 33 | QAction *action_Stop; | ||
| 34 | QAction *action_About; | 34 | QAction *action_About; |
| 35 | QAction *action_Single_Window_Mode; | 35 | QAction *action_Single_Window_Mode; |
| 36 | QAction *action_Hotkeys; | 36 | QAction *action_Hotkeys; |
| @@ -60,13 +60,12 @@ public: | |||
| 60 | action_Exit->setObjectName(QString::fromUtf8("action_Exit")); | 60 | action_Exit->setObjectName(QString::fromUtf8("action_Exit")); |
| 61 | action_Start = new QAction(MainWindow); | 61 | action_Start = new QAction(MainWindow); |
| 62 | action_Start->setObjectName(QString::fromUtf8("action_Start")); | 62 | action_Start->setObjectName(QString::fromUtf8("action_Start")); |
| 63 | action_Stop = new QAction(MainWindow); | ||
| 64 | action_Stop->setObjectName(QString::fromUtf8("action_Stop")); | ||
| 65 | action_Stop->setEnabled(false); | ||
| 66 | action_Pause = new QAction(MainWindow); | 63 | action_Pause = new QAction(MainWindow); |
| 67 | action_Pause->setObjectName(QString::fromUtf8("action_Pause")); | 64 | action_Pause->setObjectName(QString::fromUtf8("action_Pause")); |
| 68 | action_Pause->setEnabled(false); | 65 | action_Pause->setEnabled(false); |
| 69 | action_Pause->setVisible(false); | 66 | action_Stop = new QAction(MainWindow); |
| 67 | action_Stop->setObjectName(QString::fromUtf8("action_Stop")); | ||
| 68 | action_Stop->setEnabled(false); | ||
| 70 | action_About = new QAction(MainWindow); | 69 | action_About = new QAction(MainWindow); |
| 71 | action_About->setObjectName(QString::fromUtf8("action_About")); | 70 | action_About->setObjectName(QString::fromUtf8("action_About")); |
| 72 | action_Single_Window_Mode = new QAction(MainWindow); | 71 | action_Single_Window_Mode = new QAction(MainWindow); |
| @@ -126,8 +125,8 @@ public: | |||
| 126 | action_load_elf->setText(QApplication::translate("MainWindow", "Load ELF ...", 0, QApplication::UnicodeUTF8)); | 125 | action_load_elf->setText(QApplication::translate("MainWindow", "Load ELF ...", 0, QApplication::UnicodeUTF8)); |
| 127 | action_Exit->setText(QApplication::translate("MainWindow", "E&xit", 0, QApplication::UnicodeUTF8)); | 126 | action_Exit->setText(QApplication::translate("MainWindow", "E&xit", 0, QApplication::UnicodeUTF8)); |
| 128 | action_Start->setText(QApplication::translate("MainWindow", "&Start", 0, QApplication::UnicodeUTF8)); | 127 | action_Start->setText(QApplication::translate("MainWindow", "&Start", 0, QApplication::UnicodeUTF8)); |
| 129 | action_Stop->setText(QApplication::translate("MainWindow", "&Stop", 0, QApplication::UnicodeUTF8)); | ||
| 130 | action_Pause->setText(QApplication::translate("MainWindow", "&Pause", 0, QApplication::UnicodeUTF8)); | 128 | action_Pause->setText(QApplication::translate("MainWindow", "&Pause", 0, QApplication::UnicodeUTF8)); |
| 129 | action_Stop->setText(QApplication::translate("MainWindow", "&Stop", 0, QApplication::UnicodeUTF8)); | ||
| 131 | action_About->setText(QApplication::translate("MainWindow", "About Citra", 0, QApplication::UnicodeUTF8)); | 130 | action_About->setText(QApplication::translate("MainWindow", "About Citra", 0, QApplication::UnicodeUTF8)); |
| 132 | action_Single_Window_Mode->setText(QApplication::translate("MainWindow", "Single Window Mode", 0, QApplication::UnicodeUTF8)); | 131 | action_Single_Window_Mode->setText(QApplication::translate("MainWindow", "Single Window Mode", 0, QApplication::UnicodeUTF8)); |
| 133 | action_Hotkeys->setText(QApplication::translate("MainWindow", "Configure &Hotkeys ...", 0, QApplication::UnicodeUTF8)); | 132 | action_Hotkeys->setText(QApplication::translate("MainWindow", "Configure &Hotkeys ...", 0, QApplication::UnicodeUTF8)); |