Merge pull request #437 from Kingcom/DebugMode

Replace OnCpuStepped signal
This commit is contained in:
Tony Wasserka 2015-01-11 21:28:18 +01:00
commit f1080de47d
9 changed files with 60 additions and 15 deletions

View File

@ -40,18 +40,35 @@ void EmuThread::SetFilename(std::string filename)
void EmuThread::run() void EmuThread::run()
{ {
stop_run = false; stop_run = false;
// holds whether the cpu was running during the last iteration,
// so that the DebugModeLeft signal can be emitted before the
// next execution step
bool was_active = false;
while (!stop_run) while (!stop_run)
{ {
if (cpu_running) if (cpu_running)
{ {
if (!was_active)
emit DebugModeLeft();
Core::RunLoop(); Core::RunLoop();
was_active = cpu_running || exec_cpu_step;
if (!was_active)
emit DebugModeEntered();
} }
else if (exec_cpu_step) else if (exec_cpu_step)
{ {
if (!was_active)
emit DebugModeLeft();
exec_cpu_step = false; exec_cpu_step = false;
Core::SingleStep(); Core::SingleStep();
emit CPUStepped(); emit DebugModeEntered();
yieldCurrentThread(); yieldCurrentThread();
was_active = false;
} }
} }
render_window->moveContext(); render_window->moveContext();

View File

@ -81,12 +81,18 @@ private:
signals: signals:
/** /**
* Emitted when CPU when we've finished processing a single Gekko instruction * Emitted when the CPU has halted execution
* *
* @warning This will only be emitted when the CPU is not running (SetCpuRunning(false))
* @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns) * @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
*/ */
void CPUStepped(); void DebugModeEntered();
/**
* Emitted right before the CPU continues execution
*
* @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
*/
void DebugModeLeft();
}; };
class GRenderWindow : public QWidget, public EmuWindow class GRenderWindow : public QWidget, public EmuWindow

View File

@ -25,7 +25,7 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)
ui.treeView->setModel(callstack_model); ui.treeView->setModel(callstack_model);
} }
void CallstackWidget::OnCPUStepped() void CallstackWidget::OnDebugModeEntered()
{ {
ARM_Disasm* disasm = new ARM_Disasm(); ARM_Disasm* disasm = new ARM_Disasm();
ARM_Interface* app_core = Core::g_app_core; ARM_Interface* app_core = Core::g_app_core;
@ -71,3 +71,8 @@ void CallstackWidget::OnCPUStepped()
} }
} }
} }
void CallstackWidget::OnDebugModeLeft()
{
}

View File

@ -15,7 +15,8 @@ public:
CallstackWidget(QWidget* parent = 0); CallstackWidget(QWidget* parent = 0);
public slots: public slots:
void OnCPUStepped(); void OnDebugModeEntered();
void OnDebugModeLeft();
private: private:
Ui::CallStack ui; Ui::CallStack ui;

View File

@ -235,7 +235,7 @@ void DisassemblerWidget::OnToggleStartStop()
emu_thread.SetCpuRunning(!emu_thread.IsCpuRunning()); emu_thread.SetCpuRunning(!emu_thread.IsCpuRunning());
} }
void DisassemblerWidget::OnCPUStepped() void DisassemblerWidget::OnDebugModeEntered()
{ {
ARMword next_instr = Core::g_app_core->GetPC(); ARMword next_instr = Core::g_app_core->GetPC();
@ -252,6 +252,11 @@ void DisassemblerWidget::OnCPUStepped()
disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
} }
void DisassemblerWidget::OnDebugModeLeft()
{
}
int DisassemblerWidget::SelectedRow() int DisassemblerWidget::SelectedRow()
{ {
QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex(); QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex();

View File

@ -61,7 +61,8 @@ public slots:
void OnPause(); void OnPause();
void OnToggleStartStop(); void OnToggleStartStop();
void OnCPUStepped(); void OnDebugModeEntered();
void OnDebugModeLeft();
private: private:
// returns -1 if no row is selected // returns -1 if no row is selected

View File

@ -41,7 +41,7 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent)
CSPR->addChild(new QTreeWidgetItem(QStringList("N"))); CSPR->addChild(new QTreeWidgetItem(QStringList("N")));
} }
void RegistersWidget::OnCPUStepped() void RegistersWidget::OnDebugModeEntered()
{ {
ARM_Interface* app_core = Core::g_app_core; ARM_Interface* app_core = Core::g_app_core;
@ -65,3 +65,8 @@ void RegistersWidget::OnCPUStepped()
CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero
CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than
} }
void RegistersWidget::OnDebugModeLeft()
{
}

View File

@ -17,7 +17,8 @@ public:
RegistersWidget(QWidget* parent = NULL); RegistersWidget(QWidget* parent = NULL);
public slots: public slots:
void OnCPUStepped(); void OnDebugModeEntered();
void OnDebugModeLeft();
private: private:
Ui::ARMRegisters cpu_regs_ui; Ui::ARMRegisters cpu_regs_ui;

View File

@ -124,9 +124,13 @@ GMainWindow::GMainWindow()
connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog())); connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog()));
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues
connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), disasmWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); connect(&render_window->GetEmuThread(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), registersWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); connect(&render_window->GetEmuThread(), SIGNAL(DebugModeEntered()), registersWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
connect(&render_window->GetEmuThread(), SIGNAL(CPUStepped()), callstackWidget, SLOT(OnCPUStepped()), Qt::BlockingQueuedConnection); connect(&render_window->GetEmuThread(), SIGNAL(DebugModeEntered()), callstackWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
connect(&render_window->GetEmuThread(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection);
connect(&render_window->GetEmuThread(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection);
connect(&render_window->GetEmuThread(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection);
// Setup hotkeys // Setup hotkeys
RegisterHotkey("Main Window", "Load File", QKeySequence::Open); RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
@ -167,8 +171,8 @@ void GMainWindow::BootGame(std::string filename)
} }
disasmWidget->Init(); disasmWidget->Init();
registersWidget->OnCPUStepped(); registersWidget->OnDebugModeEntered();
callstackWidget->OnCPUStepped(); callstackWidget->OnDebugModeEntered();
render_window->GetEmuThread().SetFilename(filename); render_window->GetEmuThread().SetFilename(filename);
render_window->GetEmuThread().start(); render_window->GetEmuThread().start();