mirror of https://github.com/bsnes-emu/bsnes.git
Update to v070r07 release.
byuu says: I'm happy enough with the debugger now. Not 100% up to par with the old one, but it also does some new things the old one didn't. - step into / step over are disabled unless they can be done safely - this means step over is usually grayed unless you hit step into first, due to bsnes not being opcode-based (you can't skip an opcode that is half-executed) - you can now trace console output to disk - stepping the CPU will print stepped SMP opcodes if the checkbox for it is on and vice versa - button added to clear the console log
This commit is contained in:
parent
7e8958b102
commit
26643a43de
|
@ -7,14 +7,16 @@ void CPUDebugger::op_step() {
|
||||||
usage[regs.pc] |= UsageExec | (regs.p.m << 1) | (regs.p.x << 0);
|
usage[regs.pc] |= UsageExec | (regs.p.m << 1) | (regs.p.x << 0);
|
||||||
opcode_pc = regs.pc;
|
opcode_pc = regs.pc;
|
||||||
|
|
||||||
|
opcode_edge = true;
|
||||||
if(debugger.step_cpu) {
|
if(debugger.step_cpu) {
|
||||||
debugger.break_event = Debugger::BreakEvent::CPUStep;
|
debugger.break_event = Debugger::BreakEvent::CPUStep;
|
||||||
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
||||||
} else {
|
} else {
|
||||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(step_event) step_event();
|
if(step_event) step_event();
|
||||||
|
opcode_edge = false;
|
||||||
|
|
||||||
CPU::op_step();
|
CPU::op_step();
|
||||||
synchronize_smp();
|
synchronize_smp();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +38,7 @@ void CPUDebugger::op_write(uint32 addr, uint8 data) {
|
||||||
CPUDebugger::CPUDebugger() {
|
CPUDebugger::CPUDebugger() {
|
||||||
usage = new uint8[1 << 24]();
|
usage = new uint8[1 << 24]();
|
||||||
opcode_pc = 0x8000;
|
opcode_pc = 0x8000;
|
||||||
|
opcode_edge = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPUDebugger::~CPUDebugger() {
|
CPUDebugger::~CPUDebugger() {
|
||||||
|
|
|
@ -12,7 +12,8 @@ public:
|
||||||
UsageFlagX = 0x01,
|
UsageFlagX = 0x01,
|
||||||
};
|
};
|
||||||
uint8 *usage;
|
uint8 *usage;
|
||||||
uint32 opcode_pc; //points to the current opcode, used to backtrace on read/write breakpoints
|
uint32 opcode_pc;
|
||||||
|
bool opcode_edge;
|
||||||
|
|
||||||
void op_step();
|
void op_step();
|
||||||
uint8 op_read(uint32 addr);
|
uint8 op_read(uint32 addr);
|
||||||
|
|
|
@ -7,14 +7,16 @@ void CPUDebugger::op_step() {
|
||||||
usage[regs.pc] |= UsageExec | (regs.p.m << 1) | (regs.p.x << 0);
|
usage[regs.pc] |= UsageExec | (regs.p.m << 1) | (regs.p.x << 0);
|
||||||
opcode_pc = regs.pc;
|
opcode_pc = regs.pc;
|
||||||
|
|
||||||
|
opcode_edge = true;
|
||||||
if(debugger.step_cpu) {
|
if(debugger.step_cpu) {
|
||||||
debugger.break_event = Debugger::BreakEvent::CPUStep;
|
debugger.break_event = Debugger::BreakEvent::CPUStep;
|
||||||
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
||||||
} else {
|
} else {
|
||||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(step_event) step_event();
|
if(step_event) step_event();
|
||||||
|
opcode_edge = false;
|
||||||
|
|
||||||
CPU::op_step();
|
CPU::op_step();
|
||||||
synchronize_smp();
|
synchronize_smp();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +38,7 @@ void CPUDebugger::op_write(uint32 addr, uint8 data) {
|
||||||
CPUDebugger::CPUDebugger() {
|
CPUDebugger::CPUDebugger() {
|
||||||
usage = new uint8[1 << 24]();
|
usage = new uint8[1 << 24]();
|
||||||
opcode_pc = 0x8000;
|
opcode_pc = 0x8000;
|
||||||
|
opcode_edge = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPUDebugger::~CPUDebugger() {
|
CPUDebugger::~CPUDebugger() {
|
||||||
|
|
|
@ -12,7 +12,8 @@ public:
|
||||||
UsageFlagX = 0x01,
|
UsageFlagX = 0x01,
|
||||||
};
|
};
|
||||||
uint8 *usage;
|
uint8 *usage;
|
||||||
uint32 opcode_pc; //points to the current opcode, used to backtrace on read/write breakpoints
|
uint24 opcode_pc; //points to the current opcode, used to backtrace on read/write breakpoints
|
||||||
|
bool opcode_edge; //true right before an opcode execues, used to skip over opcodes
|
||||||
|
|
||||||
void op_step();
|
void op_step();
|
||||||
uint8 op_read(uint32 addr);
|
uint8 op_read(uint32 addr);
|
||||||
|
|
|
@ -6,14 +6,16 @@ void SMPDebugger::op_step() {
|
||||||
usage[regs.pc] |= UsageExec;
|
usage[regs.pc] |= UsageExec;
|
||||||
opcode_pc = regs.pc;
|
opcode_pc = regs.pc;
|
||||||
|
|
||||||
|
opcode_edge = true;
|
||||||
if(debugger.step_smp) {
|
if(debugger.step_smp) {
|
||||||
debugger.break_event = Debugger::BreakEvent::SMPStep;
|
debugger.break_event = Debugger::BreakEvent::SMPStep;
|
||||||
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
||||||
} else {
|
} else {
|
||||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(step_event) step_event();
|
if(step_event) step_event();
|
||||||
|
opcode_edge = false;
|
||||||
|
|
||||||
SMP::op_step();
|
SMP::op_step();
|
||||||
synchronize_cpu();
|
synchronize_cpu();
|
||||||
}
|
}
|
||||||
|
@ -35,6 +37,7 @@ void SMPDebugger::op_write(uint16 addr, uint8 data) {
|
||||||
SMPDebugger::SMPDebugger() {
|
SMPDebugger::SMPDebugger() {
|
||||||
usage = new uint8[1 << 16]();
|
usage = new uint8[1 << 16]();
|
||||||
opcode_pc = 0xffc0;
|
opcode_pc = 0xffc0;
|
||||||
|
opcode_edge = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMPDebugger::~SMPDebugger() {
|
SMPDebugger::~SMPDebugger() {
|
||||||
|
|
|
@ -11,6 +11,7 @@ public:
|
||||||
};
|
};
|
||||||
uint8 *usage;
|
uint8 *usage;
|
||||||
uint16 opcode_pc;
|
uint16 opcode_pc;
|
||||||
|
bool opcode_edge;
|
||||||
|
|
||||||
void op_step();
|
void op_step();
|
||||||
uint8 op_read(uint16 addr);
|
uint8 op_read(uint16 addr);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "072.06";
|
static const char Version[] = "072.07";
|
||||||
static const unsigned SerializerVersion = 14;
|
static const unsigned SerializerVersion = 14;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,28 +11,54 @@ void Console::create() {
|
||||||
|
|
||||||
traceToConsole.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace to console"); y += Style::CheckBoxHeight;
|
traceToConsole.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace to console"); y += Style::CheckBoxHeight;
|
||||||
traceToConsole.setChecked(true);
|
traceToConsole.setChecked(true);
|
||||||
traceToDisk.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace to disk"); y += Style::CheckBoxHeight;
|
traceToFile.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace to file"); y += Style::CheckBoxHeight;
|
||||||
traceToDisk.setEnabled(false);
|
|
||||||
traceCPU.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace S-CPU"); y += Style::CheckBoxHeight;
|
traceCPU.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace S-CPU"); y += Style::CheckBoxHeight;
|
||||||
traceCPU.setChecked(true);
|
traceCPU.setChecked(true);
|
||||||
traceSMP.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace S-SMP"); y += Style::CheckBoxHeight;
|
traceSMP.create(*this, x, y, 120, Style::CheckBoxHeight, "Trace S-SMP"); y += Style::CheckBoxHeight;
|
||||||
|
|
||||||
setGeometry(0, 0, 775, 338);
|
clearConsole.create(*this, x, 338 - Style::ButtonHeight - 5, 120, Style::ButtonHeight, "Clear console");
|
||||||
|
|
||||||
|
setGeometry(0, 0, 710, 338);
|
||||||
|
|
||||||
onClose = []() {
|
onClose = []() {
|
||||||
debugger.showConsole.setChecked(false);
|
debugger.showConsole.setChecked(false);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
traceToFile.onTick = []() { console.tracerEnable(console.traceToFile.checked()); };
|
||||||
|
|
||||||
|
clearConsole.onTick = []() {
|
||||||
|
console.buffer = "";
|
||||||
|
console.output.setText(console.buffer);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::write(const string &text) {
|
||||||
|
if(traceToConsole.checked()) {
|
||||||
|
if(buffer != "") buffer.append("\n");
|
||||||
|
buffer.append(text);
|
||||||
|
output.setText(buffer);
|
||||||
|
output.setCursorPosition(~0);
|
||||||
|
}
|
||||||
|
if(traceToFile.checked() && logfile.open()) {
|
||||||
|
logfile.print(string(text, "\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Console::tracerEnable(bool state) {
|
||||||
|
if(state == true) {
|
||||||
|
string filename = { cartridge.baseName, ".log" };
|
||||||
|
logfile.open(filename, file::mode::write);
|
||||||
|
} else {
|
||||||
|
logfile.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::eventBreakpoint() {
|
void Console::eventBreakpoint() {
|
||||||
if(traceToConsole.checked() == false) return;
|
if(traceToConsole.checked() == false) return;
|
||||||
|
|
||||||
unsigned n = SNES::debugger.breakpoint_hit;
|
unsigned n = SNES::debugger.breakpoint_hit;
|
||||||
string text = { "Breakpoint ", n + 1, " hit." };
|
write({ "Breakpoint ", n + 1, " hit." });
|
||||||
buffer.append(string(buffer == "" ? "" : "\n", text));
|
|
||||||
output.setText(buffer);
|
|
||||||
output.setCursorPosition(~0);
|
|
||||||
|
|
||||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::CPUBus) {
|
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::CPUBus) {
|
||||||
eventTraceCPU();
|
eventTraceCPU();
|
||||||
|
@ -43,22 +69,16 @@ void Console::eventBreakpoint() {
|
||||||
|
|
||||||
void Console::eventTraceCPU() {
|
void Console::eventTraceCPU() {
|
||||||
if(traceCPU.checked() == false) return;
|
if(traceCPU.checked() == false) return;
|
||||||
if(traceToConsole.checked() == false) return;
|
|
||||||
|
|
||||||
char text[256];
|
char text[256];
|
||||||
SNES::cpu.disassemble_opcode(text, SNES::cpu.regs.pc);
|
SNES::cpu.disassemble_opcode(text, SNES::cpu.regs.pc);
|
||||||
buffer.append(string(buffer == "" ? "" : "\n", text));
|
write(text);
|
||||||
output.setText(buffer);
|
|
||||||
output.setCursorPosition(~0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::eventTraceSMP() {
|
void Console::eventTraceSMP() {
|
||||||
if(traceSMP.checked() == false) return;
|
if(traceSMP.checked() == false) return;
|
||||||
if(traceToConsole.checked() == false) return;
|
|
||||||
|
|
||||||
char text[256];
|
char text[256];
|
||||||
SNES::smp.disassemble_opcode(text, SNES::smp.regs.pc);
|
SNES::smp.disassemble_opcode(text, SNES::smp.regs.pc);
|
||||||
buffer.append(string(buffer == "" ? "" : "\n", text));
|
write(text);
|
||||||
output.setText(buffer);
|
|
||||||
output.setCursorPosition(~0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
struct Console : TopLevelWindow {
|
struct Console : TopLevelWindow {
|
||||||
EditBox output;
|
EditBox output;
|
||||||
CheckBox traceToConsole;
|
CheckBox traceToConsole;
|
||||||
CheckBox traceToDisk;
|
CheckBox traceToFile;
|
||||||
CheckBox traceCPU;
|
CheckBox traceCPU;
|
||||||
CheckBox traceSMP;
|
CheckBox traceSMP;
|
||||||
|
Button clearConsole;
|
||||||
|
|
||||||
string buffer;
|
string buffer;
|
||||||
|
file logfile;
|
||||||
|
|
||||||
void create();
|
void create();
|
||||||
|
void write(const string &text);
|
||||||
|
void tracerEnable(bool state);
|
||||||
void eventBreakpoint();
|
void eventBreakpoint();
|
||||||
void eventTraceCPU();
|
void eventTraceCPU();
|
||||||
void eventTraceSMP();
|
void eventTraceSMP();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
CPUdebugger cpuDebugger;
|
CPUDebugger cpuDebugger;
|
||||||
|
|
||||||
void CPUdebugger::create() {
|
void CPUDebugger::create() {
|
||||||
Window::create(0, 0, 256, 256, "CPU Debugger");
|
Window::create(0, 0, 256, 256, "CPU Debugger");
|
||||||
application.addWindow(this, "Debugger.CPUdebugger", "192,192");
|
application.addWindow(this, "Debugger.CPUdebugger", "192,192");
|
||||||
|
|
||||||
|
@ -22,14 +22,18 @@ void CPUdebugger::create() {
|
||||||
};
|
};
|
||||||
|
|
||||||
stepInto.onTick = []() {
|
stepInto.onTick = []() {
|
||||||
SNES::debugger.step_cpu = true;
|
|
||||||
debugger.debugMode = Debugger::DebugMode::StepIntoCPU;
|
debugger.debugMode = Debugger::DebugMode::StepIntoCPU;
|
||||||
};
|
};
|
||||||
|
|
||||||
stepOver.onTick = { &CPUdebugger::eventStepOver, this };
|
stepOver.onTick = { &CPUDebugger::eventStepOver, this };
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPUdebugger::refreshDisassembly() {
|
void CPUDebugger::synchronize() {
|
||||||
|
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked());
|
||||||
|
stepOver.setEnabled(stepInto.enabled() && SNES::cpu.opcode_edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPUDebugger::refreshDisassembly() {
|
||||||
unsigned addr = SNES::cpu.regs.pc;
|
unsigned addr = SNES::cpu.regs.pc;
|
||||||
uint8_t *usage = SNES::cpu.usage;
|
uint8_t *usage = SNES::cpu.usage;
|
||||||
|
|
||||||
|
@ -86,18 +90,18 @@ void CPUdebugger::refreshDisassembly() {
|
||||||
output.setText(buffer);
|
output.setText(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPUdebugger::eventStepInto() {
|
void CPUDebugger::eventStepInto() {
|
||||||
SNES::debugger.step_cpu = false;
|
|
||||||
refreshDisassembly();
|
refreshDisassembly();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPUdebugger::eventStepOver() {
|
void CPUDebugger::eventStepOver() {
|
||||||
uint8_t opcode = read(SNES::cpu.regs.pc);
|
uint8_t opcode = read(SNES::cpu.regs.pc);
|
||||||
unsigned length = SNESCPU::getOpcodeLength(SNES::cpu.regs.p.m, SNES::cpu.regs.p.x, opcode);
|
unsigned length = SNESCPU::getOpcodeLength(SNES::cpu.regs.p.m, SNES::cpu.regs.p.x, opcode);
|
||||||
SNES::cpu.regs.pc += length;
|
SNES::cpu.regs.pc += length;
|
||||||
refreshDisassembly();
|
refreshDisassembly();
|
||||||
|
console.eventTraceCPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CPUdebugger::read(unsigned addr) {
|
uint8_t CPUDebugger::read(unsigned addr) {
|
||||||
return SNES::debugger.read(SNES::Debugger::MemorySource::CPUBus, addr);
|
return SNES::debugger.read(SNES::Debugger::MemorySource::CPUBus, addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
struct CPUdebugger : TopLevelWindow {
|
struct CPUDebugger : TopLevelWindow {
|
||||||
EditBox output;
|
EditBox output;
|
||||||
Button stepInto;
|
Button stepInto;
|
||||||
Button stepOver;
|
Button stepOver;
|
||||||
Button proceed;
|
Button proceed;
|
||||||
|
|
||||||
void create();
|
void create();
|
||||||
|
void synchronize();
|
||||||
void refreshDisassembly();
|
void refreshDisassembly();
|
||||||
void eventStepInto();
|
void eventStepInto();
|
||||||
void eventStepOver();
|
void eventStepOver();
|
||||||
|
@ -12,4 +13,4 @@ struct CPUdebugger : TopLevelWindow {
|
||||||
uint8_t read(unsigned addr);
|
uint8_t read(unsigned addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CPUdebugger cpuDebugger;
|
extern CPUDebugger cpuDebugger;
|
||||||
|
|
|
@ -65,6 +65,13 @@ void Debugger::create() {
|
||||||
debugger.enable(false);
|
debugger.enable(false);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debugger::synchronize() {
|
||||||
|
cpuDebugger.synchronize();
|
||||||
|
smpDebugger.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::setVisible(bool visible) {
|
void Debugger::setVisible(bool visible) {
|
||||||
|
@ -78,9 +85,13 @@ void Debugger::setVisible(bool visible) {
|
||||||
|
|
||||||
void Debugger::enable(bool state) {
|
void Debugger::enable(bool state) {
|
||||||
enableDebugger.setChecked(state);
|
enableDebugger.setChecked(state);
|
||||||
|
SNES::debugger.step_cpu = state;
|
||||||
|
SNES::debugger.step_smp = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debugger::run() {
|
void Debugger::run() {
|
||||||
|
synchronize();
|
||||||
|
|
||||||
if(enableDebugger.checked() == false) {
|
if(enableDebugger.checked() == false) {
|
||||||
SNES::system.run();
|
SNES::system.run();
|
||||||
return;
|
return;
|
||||||
|
@ -101,20 +112,20 @@ void Debugger::run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(debugMode == DebugMode::StepIntoCPU) {
|
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::CPUStep) {
|
||||||
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::CPUStep) {
|
if(debugMode == DebugMode::StepIntoCPU) {
|
||||||
debugMode = DebugMode::None;
|
debugMode = DebugMode::None;
|
||||||
console.eventTraceCPU();
|
|
||||||
cpuDebugger.eventStepInto();
|
cpuDebugger.eventStepInto();
|
||||||
}
|
}
|
||||||
|
console.eventTraceCPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(debugMode == DebugMode::StepIntoSMP) {
|
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::SMPStep) {
|
||||||
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::SMPStep) {
|
if(debugMode == DebugMode::StepIntoSMP) {
|
||||||
debugMode = DebugMode::None;
|
debugMode = DebugMode::None;
|
||||||
console.eventTraceSMP();
|
|
||||||
smpDebugger.eventStepInto();
|
smpDebugger.eventStepInto();
|
||||||
}
|
}
|
||||||
|
console.eventTraceSMP();
|
||||||
}
|
}
|
||||||
|
|
||||||
SNES::debugger.break_event = SNES::Debugger::BreakEvent::None;
|
SNES::debugger.break_event = SNES::Debugger::BreakEvent::None;
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct Debugger : TopLevelWindow {
|
||||||
CheckBox showMemoryEditor;
|
CheckBox showMemoryEditor;
|
||||||
|
|
||||||
void create();
|
void create();
|
||||||
|
void synchronize();
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void enable(bool state);
|
void enable(bool state);
|
||||||
void run();
|
void run();
|
||||||
|
|
|
@ -22,13 +22,17 @@ void SMPDebugger::create() {
|
||||||
};
|
};
|
||||||
|
|
||||||
stepInto.onTick = []() {
|
stepInto.onTick = []() {
|
||||||
SNES::debugger.step_smp = true;
|
|
||||||
debugger.debugMode = Debugger::DebugMode::StepIntoSMP;
|
debugger.debugMode = Debugger::DebugMode::StepIntoSMP;
|
||||||
};
|
};
|
||||||
|
|
||||||
stepOver.onTick = { &SMPDebugger::eventStepOver, this };
|
stepOver.onTick = { &SMPDebugger::eventStepOver, this };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMPDebugger::synchronize() {
|
||||||
|
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked());
|
||||||
|
stepOver.setEnabled(stepInto.enabled() && SNES::smp.opcode_edge);
|
||||||
|
}
|
||||||
|
|
||||||
void SMPDebugger::refreshDisassembly() {
|
void SMPDebugger::refreshDisassembly() {
|
||||||
uint16_t addr = SNES::smp.regs.pc;
|
uint16_t addr = SNES::smp.regs.pc;
|
||||||
uint8_t *usage = SNES::smp.usage;
|
uint8_t *usage = SNES::smp.usage;
|
||||||
|
@ -86,7 +90,6 @@ void SMPDebugger::refreshDisassembly() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMPDebugger::eventStepInto() {
|
void SMPDebugger::eventStepInto() {
|
||||||
SNES::debugger.step_smp = false;
|
|
||||||
refreshDisassembly();
|
refreshDisassembly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +98,7 @@ void SMPDebugger::eventStepOver() {
|
||||||
unsigned length = SNESSMP::getOpcodeLength(opcode);
|
unsigned length = SNESSMP::getOpcodeLength(opcode);
|
||||||
SNES::smp.regs.pc += length;
|
SNES::smp.regs.pc += length;
|
||||||
refreshDisassembly();
|
refreshDisassembly();
|
||||||
|
console.eventTraceSMP();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t SMPDebugger::read(uint16_t addr) {
|
uint8_t SMPDebugger::read(uint16_t addr) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ struct SMPDebugger : TopLevelWindow {
|
||||||
Button proceed;
|
Button proceed;
|
||||||
|
|
||||||
void create();
|
void create();
|
||||||
|
void synchronize();
|
||||||
void refreshDisassembly();
|
void refreshDisassembly();
|
||||||
void eventStepInto();
|
void eventStepInto();
|
||||||
void eventStepOver();
|
void eventStepOver();
|
||||||
|
|
|
@ -6,7 +6,7 @@ void BreakpointEditor::create() {
|
||||||
|
|
||||||
unsigned x = 5, y = 5;
|
unsigned x = 5, y = 5;
|
||||||
|
|
||||||
runToBreakpoint.create(*this, x, y, 295, Style::CheckBoxHeight, "Run To Breakpoint");
|
runToBreakpoint.create(*this, x, y, 295, Style::CheckBoxHeight, "Run to breakpoint");
|
||||||
y += Style::CheckBoxHeight + 5;
|
y += Style::CheckBoxHeight + 5;
|
||||||
|
|
||||||
for(unsigned n = 0; n < Breakpoints; n++) {
|
for(unsigned n = 0; n < Breakpoints; n++) {
|
||||||
|
|
Loading…
Reference in New Issue