mirror of https://github.com/bsnes-emu/bsnes.git
Update to v073r07 release.
byuu says: I give up for now. This WIP doesn't really improve uPD any, but it does have major fixes to the debugger. Debugger is still Linux-only for want of a HexEditor widget, but the Linux one is now usable. Before it'd trace and search for breakpoint at sub-1fps. Fixed it to not break out of core for simple things and it'll run at near-fullspeed for BPs, half-speed for tracing to file (lots of I/O.)
This commit is contained in:
parent
73113da41e
commit
92da6bde26
|
@ -7,11 +7,21 @@ namespace SNES {
|
|||
#include "serialization.cpp"
|
||||
|
||||
void uPDcore::exec() {
|
||||
//static uint16 lastpc = 0xffff;
|
||||
//if(lastpc != regs.pc) {
|
||||
// print("A:", hex<4>((uint16)regs.a), " B:", hex<4>((uint16)regs.b), " DR:", hex<4>(regs.dr), " SR:", hex<4>(regs.sr), " FA:", hex<2>(regs.flaga), " FB:", hex<2>(regs.flagb), "\n");
|
||||
// print(disassemble(lastpc = regs.pc), "\n");
|
||||
//}
|
||||
#if 0
|
||||
static uint16 lastpc = 0xffff;
|
||||
if(lastpc != regs.pc) {
|
||||
print(
|
||||
"A:", hex<4>((uint16)regs.a), " B:", hex<4>((uint16)regs.b),
|
||||
" DR:", hex<4>(regs.dr), " SR:", hex<4>(regs.sr),
|
||||
" FA:", hex<2>(regs.flaga), " FB:", hex<2>(regs.flagb),
|
||||
" RP:", hex<4>(regs.rp), " DP:", hex<4>(regs.dp), " SO:", hex<4>(regs.so), "\n",
|
||||
"K: ", hex<4>((uint16)regs.k), " L:", hex<4>((uint16)regs.l),
|
||||
" M:", hex<4>((uint16)regs.m), " N:", hex<4>((uint16)regs.n),
|
||||
" TR:", hex<4>(regs.tr), " TRB:", hex<4>(regs.trb), " [DP15]:", hex<4>(dataRAM[0x15]), "\n"
|
||||
);
|
||||
print(disassemble(lastpc = regs.pc), "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
uint24 opcode = programROM[regs.pc];
|
||||
regs.pc = regs.pc + 1;
|
||||
|
@ -163,9 +173,6 @@ void uPDcore::exec_jp(uint24 opcode) {
|
|||
uint16 jps = (regs.pc & 0x3800) | (na << 0);
|
||||
uint16 jpl = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
|
||||
|
||||
bool lj = false;
|
||||
ljmp:
|
||||
|
||||
switch(brch) {
|
||||
case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA
|
||||
case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA
|
||||
|
@ -209,24 +216,14 @@ void uPDcore::exec_jp(uint24 opcode) {
|
|||
case 0x140: stack_push(); regs.pc = jps; return; //CALL
|
||||
}
|
||||
|
||||
if(brch == 0x000) {
|
||||
regs.pc = regs.so;
|
||||
return;
|
||||
switch(brch) {
|
||||
case 0x000: regs.pc = regs.so; return;
|
||||
|
||||
case 0x081: if(regs.flaga.c == 1) regs.pc = jpl; return;
|
||||
|
||||
case 0x0bf: if(regs.sr.rqm == 1) regs.pc = jpl; return;
|
||||
}
|
||||
|
||||
if(lj == false) {
|
||||
lj = true;
|
||||
brch &= ~1;
|
||||
jps = jpl;
|
||||
goto ljmp;
|
||||
}
|
||||
|
||||
/*switch(brch) {
|
||||
case 0x081: if(regs.flaga.c == 0) regs.pc = jpl; return; //LJNCA
|
||||
|
||||
case 0x0bf: if(regs.sr.rqm == 1) regs.pc = jpl; return; //LJRQM
|
||||
}*/
|
||||
|
||||
print(hex<4>(regs.pc - 1), ": unknown jump ", hex<3>(brch), "\n");
|
||||
|
||||
/*bool r = false;
|
||||
|
|
|
@ -8,13 +8,11 @@ void CPUDebugger::op_step() {
|
|||
opcode_pc = regs.pc;
|
||||
|
||||
opcode_edge = true;
|
||||
if(debugger.step_cpu) {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||
if(step_event && step_event() == true) {
|
||||
debugger.break_event = Debugger::BreakEvent::CPUStep;
|
||||
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
||||
} else {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||
}
|
||||
if(step_event) step_event();
|
||||
opcode_edge = false;
|
||||
|
||||
CPU::op_step();
|
||||
|
|
|
@ -2,7 +2,7 @@ class CPUDebugger : public CPU, public ChipDebugger {
|
|||
public:
|
||||
bool property(unsigned id, string &name, string &value);
|
||||
|
||||
function<void ()> step_event;
|
||||
function<bool ()> step_event;
|
||||
|
||||
enum Usage {
|
||||
UsageRead = 0x80,
|
||||
|
|
|
@ -103,9 +103,6 @@ Debugger::Debugger() {
|
|||
breakpoint[n].counter = 0;
|
||||
}
|
||||
breakpoint_hit = 0;
|
||||
|
||||
step_cpu = false;
|
||||
step_smp = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,9 +19,6 @@ public:
|
|||
unsigned breakpoint_hit;
|
||||
void breakpoint_test(Breakpoint::Source source, Breakpoint::Mode mode, unsigned addr, uint8 data);
|
||||
|
||||
bool step_cpu;
|
||||
bool step_smp;
|
||||
|
||||
enum class MemorySource : unsigned { CPUBus, APUBus, APURAM, VRAM, OAM, CGRAM };
|
||||
uint8 read(MemorySource, unsigned addr);
|
||||
void write(MemorySource, unsigned addr, uint8 data);
|
||||
|
|
|
@ -7,13 +7,11 @@ void SMPDebugger::op_step() {
|
|||
opcode_pc = regs.pc;
|
||||
|
||||
opcode_edge = true;
|
||||
if(debugger.step_smp) {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||
if(step_event && step_event() == true) {
|
||||
debugger.break_event = Debugger::BreakEvent::SMPStep;
|
||||
scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
|
||||
} else {
|
||||
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
|
||||
}
|
||||
if(step_event) step_event();
|
||||
opcode_edge = false;
|
||||
|
||||
SMP::op_step();
|
||||
|
|
|
@ -2,7 +2,7 @@ class SMPDebugger : public SMP, public ChipDebugger {
|
|||
public:
|
||||
bool property(unsigned id, string &name, string &value);
|
||||
|
||||
function<void ()> step_event;
|
||||
function<bool ()> step_event;
|
||||
|
||||
enum Usage {
|
||||
UsageRead = 0x80,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "073.06";
|
||||
static const char Version[] = "073.07";
|
||||
static const unsigned SerializerVersion = 16;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,12 +33,13 @@ void Console::create() {
|
|||
};
|
||||
}
|
||||
|
||||
void Console::write(const string &text) {
|
||||
if(traceToConsole.checked()) {
|
||||
void Console::write(const string &text, bool echo) {
|
||||
if(traceToConsole.checked() || echo) {
|
||||
if(buffer != "") buffer.append("\n");
|
||||
buffer.append(text);
|
||||
output.setText(buffer);
|
||||
output.setCursorPosition(~0);
|
||||
OS::run();
|
||||
}
|
||||
if(traceToFile.checked() && logfile.open()) {
|
||||
logfile.print(string(text, "\n"));
|
||||
|
@ -55,20 +56,21 @@ void Console::tracerEnable(bool state) {
|
|||
}
|
||||
|
||||
void Console::eventBreakpoint() {
|
||||
if(traceToConsole.checked() == false) return;
|
||||
|
||||
unsigned n = SNES::debugger.breakpoint_hit;
|
||||
write({ "Breakpoint ", n + 1, " hit." });
|
||||
write({ "Breakpoint ", n + 1, " hit." }, true);
|
||||
|
||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::CPUBus) {
|
||||
eventTraceCPU();
|
||||
cpuDebugger.refreshDisassembly();
|
||||
} else if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::APURAM) {
|
||||
eventTraceSMP();
|
||||
smpDebugger.refreshDisassembly();
|
||||
}
|
||||
}
|
||||
|
||||
void Console::eventTraceCPU() {
|
||||
if(traceCPU.checked() == false) return;
|
||||
if(traceToConsole.checked() == false && traceToFile.checked() == false) return;
|
||||
|
||||
char text[256];
|
||||
SNES::cpu.disassemble_opcode(text, SNES::cpu.regs.pc);
|
||||
|
@ -77,6 +79,7 @@ void Console::eventTraceCPU() {
|
|||
|
||||
void Console::eventTraceSMP() {
|
||||
if(traceSMP.checked() == false) return;
|
||||
if(traceToConsole.checked() == false && traceToFile.checked() == false) return;
|
||||
|
||||
char text[256];
|
||||
SNES::smp.disassemble_opcode(text, SNES::smp.regs.pc);
|
||||
|
|
|
@ -10,7 +10,7 @@ struct Console : TopLevelWindow {
|
|||
file logfile;
|
||||
|
||||
void create();
|
||||
void write(const string &text);
|
||||
void write(const string &text, bool echo = false);
|
||||
void tracerEnable(bool state);
|
||||
void eventBreakpoint();
|
||||
void eventTraceCPU();
|
||||
|
|
|
@ -29,7 +29,7 @@ void CPUDebugger::create() {
|
|||
}
|
||||
|
||||
void CPUDebugger::synchronize() {
|
||||
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked());
|
||||
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked() && breakpointEditor.runToBreakpoint.checked() == false);
|
||||
stepOver.setEnabled(stepInto.enabled() && SNES::cpu.opcode_edge);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,13 +85,10 @@ void Debugger::setVisible(bool visible) {
|
|||
|
||||
void Debugger::enable(bool state) {
|
||||
enableDebugger.setChecked(state);
|
||||
SNES::debugger.step_cpu = state;
|
||||
SNES::debugger.step_smp = state;
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void Debugger::run() {
|
||||
synchronize();
|
||||
|
||||
if(enableDebugger.checked() == false) {
|
||||
SNES::system.run();
|
||||
return;
|
||||
|
@ -109,30 +106,41 @@ void Debugger::run() {
|
|||
debugMode = DebugMode::None;
|
||||
console.eventBreakpoint();
|
||||
breakpointEditor.eventBreakpoint();
|
||||
synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::CPUStep) {
|
||||
if(debugMode == DebugMode::StepIntoCPU) {
|
||||
debugMode = DebugMode::None;
|
||||
cpuDebugger.eventStepInto();
|
||||
}
|
||||
console.eventTraceCPU();
|
||||
}
|
||||
|
||||
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::SMPStep) {
|
||||
if(debugMode == DebugMode::StepIntoSMP) {
|
||||
debugMode = DebugMode::None;
|
||||
smpDebugger.eventStepInto();
|
||||
}
|
||||
console.eventTraceSMP();
|
||||
}
|
||||
|
||||
SNES::debugger.break_event = SNES::Debugger::BreakEvent::None;
|
||||
}
|
||||
|
||||
bool Debugger::step_cpu() {
|
||||
if(enableDebugger.checked() == false) return false;
|
||||
console.eventTraceCPU();
|
||||
if(debugMode == DebugMode::StepIntoCPU) {
|
||||
debugMode = DebugMode::None;
|
||||
cpuDebugger.eventStepInto();
|
||||
synchronize();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Debugger::step_smp() {
|
||||
if(enableDebugger.checked() == false) return false;
|
||||
console.eventTraceSMP();
|
||||
if(debugMode == DebugMode::StepIntoSMP) {
|
||||
debugMode = DebugMode::None;
|
||||
smpDebugger.eventStepInto();
|
||||
synchronize();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Debugger::Debugger() {
|
||||
debugMode = DebugMode::None;
|
||||
SNES::cpu.step_event = { &Debugger::step_cpu, this };
|
||||
SNES::smp.step_event = { &Debugger::step_smp, this };
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,8 @@ struct Debugger : TopLevelWindow {
|
|||
void setVisible(bool visible = true);
|
||||
void enable(bool state);
|
||||
void run();
|
||||
bool step_cpu();
|
||||
bool step_smp();
|
||||
|
||||
Debugger();
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ void SMPDebugger::create() {
|
|||
}
|
||||
|
||||
void SMPDebugger::synchronize() {
|
||||
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked());
|
||||
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked() && breakpointEditor.runToBreakpoint.checked() == false);
|
||||
stepOver.setEnabled(stepInto.enabled() && SNES::smp.opcode_edge);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ void BreakpointEditor::create() {
|
|||
} else {
|
||||
debugger.debugMode = Debugger::DebugMode::None;
|
||||
}
|
||||
debugger.synchronize();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue