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:
Tim Allen 2011-01-10 23:21:57 +11:00
parent 73113da41e
commit 92da6bde26
15 changed files with 70 additions and 69 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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,

View File

@ -103,9 +103,6 @@ Debugger::Debugger() {
breakpoint[n].counter = 0;
}
breakpoint_hit = 0;
step_cpu = false;
step_smp = false;
}
#endif

View File

@ -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);

View File

@ -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();

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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();

View File

@ -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);
}

View File

@ -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

View File

@ -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();
};

View File

@ -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);
}

View File

@ -28,6 +28,7 @@ void BreakpointEditor::create() {
} else {
debugger.debugMode = Debugger::DebugMode::None;
}
debugger.synchronize();
};
}