From 5b207618c880c11b673491b0834baf49ddab9b58 Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Mon, 13 Nov 2017 20:39:53 +0100 Subject: [PATCH 1/9] Add debugger commands to manipulate controller state. --- src/debugger/DebuggerParser.cxx | 210 ++++++++++++++++++++++++++++++++ src/debugger/DebuggerParser.hxx | 12 +- 2 files changed, 221 insertions(+), 1 deletion(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 357132e7f..8751f14af 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1161,6 +1161,116 @@ void DebuggerParser::executeHelp() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy0up" +void DebuggerParser::executeJoy0Up() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Left); + if(argCount == 0) + controller.set(Controller::One, !controller.read(Controller::One)); + else if(argCount == 1) + controller.set(Controller::One, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy0down" +void DebuggerParser::executeJoy0Down() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Left); + if(argCount == 0) + controller.set(Controller::Two, !controller.read(Controller::Two)); + else if(argCount == 1) + controller.set(Controller::Two, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy0left" +void DebuggerParser::executeJoy0Left() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Left); + if(argCount == 0) + controller.set(Controller::Three, !controller.read(Controller::Three)); + else if(argCount == 1) + controller.set(Controller::Three, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy0right" +void DebuggerParser::executeJoy0Right() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Left); + if(argCount == 0) + controller.set(Controller::Four, !controller.read(Controller::Four)); + else if(argCount == 1) + controller.set(Controller::Four, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy0fire" +void DebuggerParser::executeJoy0Fire() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Left); + if(argCount == 0) + controller.set(Controller::Six, !controller.read(Controller::Six)); + else if(argCount == 1) + controller.set(Controller::Six, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy1up" +void DebuggerParser::executeJoy1Up() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Right); + if(argCount == 0) + controller.set(Controller::One, !controller.read(Controller::One)); + else if(argCount == 1) + controller.set(Controller::One, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy1down" +void DebuggerParser::executeJoy1Down() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Right); + if(argCount == 0) + controller.set(Controller::Two, !controller.read(Controller::Two)); + else if(argCount == 1) + controller.set(Controller::Two, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy1left" +void DebuggerParser::executeJoy1Left() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Right); + if(argCount == 0) + controller.set(Controller::Three, !controller.read(Controller::Three)); + else if(argCount == 1) + controller.set(Controller::Three, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy1right" +void DebuggerParser::executeJoy1Right() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Right); + if(argCount == 0) + controller.set(Controller::Four, !controller.read(Controller::Four)); + else if(argCount == 1) + controller.set(Controller::Four, args[0] != 0); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "joy1fire" +void DebuggerParser::executeJoy1Fire() +{ + Controller& controller = debugger.riotDebug().controller(Controller::Right); + if(argCount == 0) + controller.set(Controller::Six, !controller.read(Controller::Six)); + else if(argCount == 1) + controller.set(Controller::Six, args[0] != 0); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "jump" void DebuggerParser::executeJump() @@ -2305,6 +2415,106 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { std::mem_fn(&DebuggerParser::executeHelp) }, + { + "joy0up", + "Set joystick 0 up direction to value (0 or 1), or toggle (no arg)", + "Example: joy0up 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy0Up) + }, + + { + "joy0down", + "Set joystick 0 down direction to value (0 or 1), or toggle (no arg)", + "Example: joy0down 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy0Down) + }, + + { + "joy0left", + "Set joystick 0 left direction to value (0 or 1), or toggle (no arg)", + "Example: joy0left 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy0Left) + }, + + { + "joy0right", + "Set joystick 0 right direction to value (0 or 1), or toggle (no arg)", + "Example: joy0left 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy0Right) + }, + + { + "joy0fire", + "Set joystick 0 fire button to value (0 or 1), or toggle (no arg)", + "Example: joy0fire 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy0Fire) + }, + + { + "joy1up", + "Set joystick 1 up direction to value (0 or 1), or toggle (no arg)", + "Example: joy1up 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy1Up) + }, + + { + "joy1down", + "Set joystick 1 down direction to value (0 or 1), or toggle (no arg)", + "Example: joy1down 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy1Down) + }, + + { + "joy1left", + "Set joystick 1 left direction to value (0 or 1), or toggle (no arg)", + "Example: joy1left 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy1Left) + }, + + { + "joy1right", + "Set joystick 1 right direction to value (0 or 1), or toggle (no arg)", + "Example: joy1left 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy1Right) + }, + + { + "joy1fire", + "Set joystick 1 fire button to value (0 or 1), or toggle (no arg)", + "Example: joy1fire 0", + false, + true, + { kARG_BOOL, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeJoy1Fire) + }, + { "jump", "Scroll disassembly to address xx", diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index b804ace65..3f1706b9d 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -66,7 +66,7 @@ class DebuggerParser string saveScriptFile(string file); private: - enum { kNumCommands = 81 }; + enum { kNumCommands = 91 }; // Constants for argument processing enum { @@ -165,6 +165,16 @@ class DebuggerParser void executeFunction(); void executeGfx(); void executeHelp(); + void executeJoy0Up(); + void executeJoy0Down(); + void executeJoy0Left(); + void executeJoy0Right(); + void executeJoy0Fire(); + void executeJoy1Up(); + void executeJoy1Down(); + void executeJoy1Left(); + void executeJoy1Right(); + void executeJoy1Fire(); void executeJump(); void executeListbreaks(); void executeListconfig(); From ff4603d81f7dec9f84b70e821e4f27c3137a6df5 Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Mon, 13 Nov 2017 22:02:46 +0100 Subject: [PATCH 2/9] Bugfix: redraw TiaOutputWidget on savesnap when executing in a script. --- src/debugger/DebuggerParser.cxx | 7 +++++-- src/debugger/DebuggerParser.hxx | 2 ++ src/debugger/gui/TiaOutputWidget.cxx | 9 +++++++-- src/debugger/gui/TiaOutputWidget.hxx | 3 ++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 8751f14af..f8401d0b9 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -58,7 +58,8 @@ using std::right; DebuggerParser::DebuggerParser(Debugger& d, Settings& s) : debugger(d), settings(s), - argCount(0) + argCount(0), + execDepth(0) { } @@ -1064,7 +1065,9 @@ void DebuggerParser::executeExec() file += ".script"; FilesystemNode node(debugger.myOSystem.defaultSaveDir() + file); + execDepth++; commandResult << exec(node); + execDepth--; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1695,7 +1698,7 @@ void DebuggerParser::executeSaveses() // "savesnap" void DebuggerParser::executeSavesnap() { - debugger.tiaOutput().saveSnapshot(); + debugger.tiaOutput().saveSnapshot(execDepth); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 3f1706b9d..ce3ca7599 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -123,6 +123,8 @@ class DebuggerParser StringList argStrings; uInt32 argCount; + uInt32 execDepth; + StringList myWatches; // Keep track of traps (read and/or write) diff --git a/src/debugger/gui/TiaOutputWidget.cxx b/src/debugger/gui/TiaOutputWidget.cxx index d2e73e851..60fd21652 100644 --- a/src/debugger/gui/TiaOutputWidget.cxx +++ b/src/debugger/gui/TiaOutputWidget.cxx @@ -58,8 +58,11 @@ void TiaOutputWidget::loadConfig() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TiaOutputWidget::saveSnapshot() +void TiaOutputWidget::saveSnapshot(int execDepth) { + if (execDepth > 0) { + drawWidget(false); + } int number = int(instance().getTicks() / 1000); ostringstream sspath; sspath << instance().snapshotSaveDir() @@ -80,7 +83,9 @@ void TiaOutputWidget::saveSnapshot() { message = e.what(); } - instance().frameBuffer().showMessage(message); + if (execDepth == 0) { + instance().frameBuffer().showMessage(message); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/TiaOutputWidget.hxx b/src/debugger/gui/TiaOutputWidget.hxx index 5be537e91..0b755c329 100644 --- a/src/debugger/gui/TiaOutputWidget.hxx +++ b/src/debugger/gui/TiaOutputWidget.hxx @@ -36,7 +36,8 @@ class TiaOutputWidget : public Widget, public CommandSender void loadConfig() override; void setZoomWidget(TiaZoomWidget* w) { myZoom = w; } - void saveSnapshot(); + void saveSnapshot() { saveSnapshot(0); }; + void saveSnapshot(int execDepth); // Eventually, these methods will enable access to the onscreen TIA image // For example, clicking an area may cause an action From 2f787fbb91173b395224ea5cfa62cf07fa244589 Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Mon, 13 Nov 2017 22:21:14 +0100 Subject: [PATCH 3/9] Exec command: search script first in current directory. --- src/debugger/DebuggerParser.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index f8401d0b9..d914a6c24 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1064,7 +1064,10 @@ void DebuggerParser::executeExec() if(file.find_last_of('.') == string::npos) file += ".script"; - FilesystemNode node(debugger.myOSystem.defaultSaveDir() + file); + FilesystemNode node(file); + if (!node.exists()) { + node = FilesystemNode(debugger.myOSystem.defaultSaveDir() + file); + } execDepth++; commandResult << exec(node); execDepth--; From e6b5d792b72c3c6f7c758529176408870d3b0e0f Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Mon, 13 Nov 2017 22:23:38 +0100 Subject: [PATCH 4/9] Reset command: also reset controller state. --- src/debugger/DebuggerParser.cxx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index d914a6c24..5a8990933 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1500,6 +1500,16 @@ void DebuggerParser::executeReset() { debugger.reset(); debugger.rom().invalidate(); + debugger.riotDebug().controller(Controller::Left).set(Controller::One, true); + debugger.riotDebug().controller(Controller::Left).set(Controller::Two, true); + debugger.riotDebug().controller(Controller::Left).set(Controller::Three, true); + debugger.riotDebug().controller(Controller::Left).set(Controller::Four, true); + debugger.riotDebug().controller(Controller::Left).set(Controller::Six, true); + debugger.riotDebug().controller(Controller::Right).set(Controller::One, true); + debugger.riotDebug().controller(Controller::Right).set(Controller::Two, true); + debugger.riotDebug().controller(Controller::Right).set(Controller::Three, true); + debugger.riotDebug().controller(Controller::Right).set(Controller::Four, true); + debugger.riotDebug().controller(Controller::Right).set(Controller::Six, true); commandResult << "reset system"; } From 7010400235a68de5fd1c5180479ae993e535e24d Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Mon, 13 Nov 2017 22:27:38 +0100 Subject: [PATCH 5/9] Add new debugger command 'stepwhile'. This command steps through the code instruction-by-instruction (just like the 'step' command) while the argument evaluates to true. This is a (pretty slow) workaround for breakpoints and the 'run' command which seems broken from debugging scripts. --- src/debugger/DebuggerParser.cxx | 27 +++++++++++++++++++++++++++ src/debugger/DebuggerParser.hxx | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 5a8990933..61f08b884 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1766,6 +1766,23 @@ void DebuggerParser::executeStep() << "executed " << dec << debugger.step() << " cycles"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "stepwhile" +void DebuggerParser::executeStepwhile() +{ + int res = YaccParser::parse(argStrings[0].c_str()); + if(res != 0) { + commandResult << red("invalid expression"); + return; + } + Expression* expr = YaccParser::getResult(); + int ncycles = 0; + do { + ncycles += debugger.step(); + } while (expr->evaluate()); + commandResult << "executed " << ncycles << " cycles"; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "tia" void DebuggerParser::executeTia() @@ -2868,6 +2885,16 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { std::mem_fn(&DebuggerParser::executeStep) }, + { + "stepwhile", + "Single step CPU while is true", + "Example: stepwhile pc!=$f2a9", + true, + true, + { kARG_WORD, kARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeStepwhile) + }, + { "tia", "Show TIA state", diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index ce3ca7599..6a1faf580 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -66,7 +66,7 @@ class DebuggerParser string saveScriptFile(string file); private: - enum { kNumCommands = 91 }; + enum { kNumCommands = 92 }; // Constants for argument processing enum { @@ -210,6 +210,7 @@ class DebuggerParser void executeSavestateif(); void executeScanline(); void executeStep(); + void executeStepwhile(); void executeTia(); void executeTrace(); void executeTrap(); From 0ecb4f5ae7d46fa2be2307018ecac0b8a453bd18 Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Tue, 14 Nov 2017 23:22:54 +0100 Subject: [PATCH 6/9] Add an 'exec'-prefix to snapshot name when saving from a script. Allow the user to specify an additional 'prefix' string in the exec command that will be prepended the ticks-part of the snapshot name when saving a snapshot from script. --- src/debugger/DebuggerParser.cxx | 19 ++++++++++++++----- src/debugger/DebuggerParser.hxx | 1 + src/debugger/gui/TiaOutputWidget.cxx | 10 +++++++--- src/debugger/gui/TiaOutputWidget.hxx | 4 ++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 61f08b884..1c68c4c38 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -59,7 +59,8 @@ DebuggerParser::DebuggerParser(Debugger& d, Settings& s) : debugger(d), settings(s), argCount(0), - execDepth(0) + execDepth(0), + execPrefix("") { } @@ -1063,11 +1064,19 @@ void DebuggerParser::executeExec() string file = argStrings[0]; if(file.find_last_of('.') == string::npos) file += ".script"; - FilesystemNode node(file); if (!node.exists()) { node = FilesystemNode(debugger.myOSystem.defaultSaveDir() + file); } + + if (argCount == 2) { + execPrefix = argStrings[1]; + } + else { + ostringstream prefix; + prefix << std::hex << std::setw(8) << std::setfill('0') << (debugger.myOSystem.getTicks()/1000 & 0xffffffff); + execPrefix = prefix.str(); + } execDepth++; commandResult << exec(node); execDepth--; @@ -1711,7 +1720,7 @@ void DebuggerParser::executeSaveses() // "savesnap" void DebuggerParser::executeSavesnap() { - debugger.tiaOutput().saveSnapshot(execDepth); + debugger.tiaOutput().saveSnapshot(execDepth, execPrefix); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2389,11 +2398,11 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { { "exec", - "Execute script file ", + "Execute script file [prefix]", "Example: exec script.dat, exec auto.txt", true, true, - { kARG_FILE, kARG_END_ARGS }, + { kARG_FILE, kARG_LABEL, kARG_MULTI_BYTE }, std::mem_fn(&DebuggerParser::executeExec) }, diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 6a1faf580..69926e544 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -124,6 +124,7 @@ class DebuggerParser uInt32 argCount; uInt32 execDepth; + string execPrefix; StringList myWatches; diff --git a/src/debugger/gui/TiaOutputWidget.cxx b/src/debugger/gui/TiaOutputWidget.cxx index 60fd21652..210988242 100644 --- a/src/debugger/gui/TiaOutputWidget.cxx +++ b/src/debugger/gui/TiaOutputWidget.cxx @@ -58,7 +58,7 @@ void TiaOutputWidget::loadConfig() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TiaOutputWidget::saveSnapshot(int execDepth) +void TiaOutputWidget::saveSnapshot(int execDepth, const string& execPrefix) { if (execDepth > 0) { drawWidget(false); @@ -66,8 +66,12 @@ void TiaOutputWidget::saveSnapshot(int execDepth) int number = int(instance().getTicks() / 1000); ostringstream sspath; sspath << instance().snapshotSaveDir() - << instance().console().properties().get(Cartridge_Name) - << "_dbg_" << std::hex << std::setw(8) << std::setfill('0') << number << ".png"; + << instance().console().properties().get(Cartridge_Name); + sspath << "_dbg_"; + if (execDepth > 0 && !execPrefix.empty()) { + sspath << execPrefix << "_"; + } + sspath << std::hex << std::setw(8) << std::setfill('0') << (number/1000 & 0xffffffff) << ".png"; const uInt32 width = instance().console().tia().width(), height = instance().console().tia().height(); diff --git a/src/debugger/gui/TiaOutputWidget.hxx b/src/debugger/gui/TiaOutputWidget.hxx index 0b755c329..59a3c1843 100644 --- a/src/debugger/gui/TiaOutputWidget.hxx +++ b/src/debugger/gui/TiaOutputWidget.hxx @@ -36,8 +36,8 @@ class TiaOutputWidget : public Widget, public CommandSender void loadConfig() override; void setZoomWidget(TiaZoomWidget* w) { myZoom = w; } - void saveSnapshot() { saveSnapshot(0); }; - void saveSnapshot(int execDepth); + void saveSnapshot() { saveSnapshot(0, ""); }; + void saveSnapshot(int execDepth, const string& execPrefix); // Eventually, these methods will enable access to the onscreen TIA image // For example, clicking an area may cause an action From ed3b61fdb10829246abb7970b4a9e94dffbe491b Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Tue, 14 Nov 2017 23:33:06 +0100 Subject: [PATCH 7/9] Improve 'dump' command. Add third parameter to indicate that the dump should be appended to a file instead of printed on screen. Also, allow to dump CPU state and input registers. The third argument is a flags value (0x01: dump memory, 0x02: dump CPU state, 0x04: dump input registers). --- src/debugger/DebuggerParser.cxx | 86 +++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 10 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 1c68c4c38..c7e567acd 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1022,23 +1022,28 @@ void DebuggerParser::executeDisasm() // "dump" void DebuggerParser::executeDump() { - auto dump = [&](int start, int end) + auto dump = [&](ostream& os, int start, int end) { for(int i = start; i <= end; i += 16) { // Print label every 16 bytes - commandResult << Base::toString(i) << ": "; + os << Base::toString(i) << ": "; for(int j = i; j < i+16 && j <= end; ++j) { - commandResult << Base::toString(debugger.peek(j)) << " "; - if(j == i+7 && j != end) commandResult << "- "; + os << Base::toString(debugger.peek(j)) << " "; + if(j == i+7 && j != end) os << "- "; } - commandResult << endl; + os << endl; } }; // Error checking + if( argCount == 0 || argCount > 3) + { + outputCommandError("wrong number of arguments", myCommand); + return; + } if(argCount > 1 && args[1] < args[0]) { commandResult << red("start address must be <= end address"); @@ -1046,14 +1051,75 @@ void DebuggerParser::executeDump() } if(argCount == 1) - dump(args[0], args[0] + 127); - else if(argCount == 2) - dump(args[0], args[1]); - else + dump(commandResult, args[0], args[0] + 127); + else if(argCount == 2 || args[2] == 0) + dump(commandResult, args[0], args[1]); + else { + ostringstream file; + file << debugger.myOSystem.snapshotSaveDir() << debugger.myOSystem.console().properties().get(Cartridge_Name) << "_dbg_"; + if (execDepth > 0) { + file << execPrefix; + } + else { + file << std::hex << std::setw(8) << std::setfill('0') << (debugger.myOSystem.getTicks()/1000 & 0xffffffff); + } + file << ".dump"; + FilesystemNode node(file.str()); + // cout << "dump " << args[0] << "-" << args[1] << " to " << file.str() << endl; + ofstream ofs(node.getPath(), ofstream::out | ofstream::app); + if(!ofs.is_open()) { - outputCommandError("wrong number of arguments", myCommand); + outputCommandError("Unable to append dump to file " + node.getShortPath(), myCommand); return; } + if ((args[2] & 0x01) != 0) { + // dump memory + dump(ofs, args[0], args[1]); +} + if ((args[2] & 0x02) != 0) { + // dump CPU state + CpuDebug& cpu = debugger.cpuDebug(); + ofs << "XC: " + << Base::toString(cpu.pc()&0xff) << " " // PC lsb + << Base::toString(cpu.pc()>>8) << " " // PC msb + << Base::toString(cpu.sp()) << " " // SP + << Base::toString(cpu.a()) << " " // A + << Base::toString(cpu.x()) << " " // X + << Base::toString(cpu.y()) << " " // Y + << Base::toString(0) << " " // unused + << Base::toString(0) << " - " // unused + << Base::toString(cpu.n()) << " " // N (flag) + << Base::toString(cpu.v()) << " " // V (flag) + << Base::toString(cpu.b()) << " " // B (flag) + << Base::toString(cpu.d()) << " " // D (flag) + << Base::toString(cpu.i()) << " " // I (flag) + << Base::toString(cpu.z()) << " " // Z (flag) + << Base::toString(cpu.c()) << " " // C (flag) + << Base::toString(0) << " " // unused + << endl; + } + if ((args[2] & 0x04) != 0) { + // dump SWCHx/INPTx state + ofs << "XS: " + << Base::toString(debugger.peek(0x280)) << " " // SWCHA + << Base::toString(0) << " " // unused + << Base::toString(debugger.peek(0x282)) << " " // SWCHB + << Base::toString(0) << " " // unused + << Base::toString(0) << " " // unused + << Base::toString(0) << " " // unused + << Base::toString(0) << " " // unused + << Base::toString(0) << " - " // unused + << Base::toString(0) << " " // unused + << Base::toString(0) << " " // unused + << Base::toString(0) << " " // unused + << Base::toString(0) << " " // unused + << Base::toString(debugger.peek(TIARegister::INPT4)) << " " + << Base::toString(debugger.peek(TIARegister::INPT5)) << " " + << Base::toString(0) << " " // unused + << Base::toString(0) << " " // unused + << endl; + } +} } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From bfd12d7ddcb03698b3f14e60ae5bdefce3a1d27c Mon Sep 17 00:00:00 2001 From: Markus Uhr Date: Wed, 15 Nov 2017 00:23:50 +0100 Subject: [PATCH 8/9] Fix tick suffix in snapshot file name. --- src/debugger/gui/TiaOutputWidget.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/debugger/gui/TiaOutputWidget.cxx b/src/debugger/gui/TiaOutputWidget.cxx index 210988242..9664b3f01 100644 --- a/src/debugger/gui/TiaOutputWidget.cxx +++ b/src/debugger/gui/TiaOutputWidget.cxx @@ -63,7 +63,6 @@ void TiaOutputWidget::saveSnapshot(int execDepth, const string& execPrefix) if (execDepth > 0) { drawWidget(false); } - int number = int(instance().getTicks() / 1000); ostringstream sspath; sspath << instance().snapshotSaveDir() << instance().console().properties().get(Cartridge_Name); @@ -71,7 +70,7 @@ void TiaOutputWidget::saveSnapshot(int execDepth, const string& execPrefix) if (execDepth > 0 && !execPrefix.empty()) { sspath << execPrefix << "_"; } - sspath << std::hex << std::setw(8) << std::setfill('0') << (number/1000 & 0xffffffff) << ".png"; + sspath << std::hex << std::setw(8) << std::setfill('0') << (instance().getTicks()/1000 & 0xffffffff) << ".png"; const uInt32 width = instance().console().tia().width(), height = instance().console().tia().height(); From 9ada07a7330f8cb64c1842c337a7adeb946b9334 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Fri, 24 Nov 2017 13:24:19 -0330 Subject: [PATCH 9/9] Minor fixups for last commits. --- src/debugger/DebuggerParser.cxx | 4 ++-- src/debugger/gui/TiaOutputWidget.cxx | 4 ++-- src/debugger/gui/TiaOutputWidget.hxx | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index c7e567acd..4068d12ad 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1061,7 +1061,7 @@ void DebuggerParser::executeDump() file << execPrefix; } else { - file << std::hex << std::setw(8) << std::setfill('0') << (debugger.myOSystem.getTicks()/1000 & 0xffffffff); + file << std::hex << std::setw(8) << std::setfill('0') << uInt32(debugger.myOSystem.getTicks()/1000); } file << ".dump"; FilesystemNode node(file.str()); @@ -1140,7 +1140,7 @@ void DebuggerParser::executeExec() } else { ostringstream prefix; - prefix << std::hex << std::setw(8) << std::setfill('0') << (debugger.myOSystem.getTicks()/1000 & 0xffffffff); + prefix << std::hex << std::setw(8) << std::setfill('0') << uInt32(debugger.myOSystem.getTicks()/1000); execPrefix = prefix.str(); } execDepth++; diff --git a/src/debugger/gui/TiaOutputWidget.cxx b/src/debugger/gui/TiaOutputWidget.cxx index 9664b3f01..ddbf48d29 100644 --- a/src/debugger/gui/TiaOutputWidget.cxx +++ b/src/debugger/gui/TiaOutputWidget.cxx @@ -70,14 +70,14 @@ void TiaOutputWidget::saveSnapshot(int execDepth, const string& execPrefix) if (execDepth > 0 && !execPrefix.empty()) { sspath << execPrefix << "_"; } - sspath << std::hex << std::setw(8) << std::setfill('0') << (instance().getTicks()/1000 & 0xffffffff) << ".png"; + sspath << std::hex << std::setw(8) << std::setfill('0') << uInt32(instance().getTicks()/1000) << ".png"; const uInt32 width = instance().console().tia().width(), height = instance().console().tia().height(); FBSurface& s = dialog().surface(); GUI::Rect rect(_x, _y, _x + width*2, _y + height); - string message = "snapshot saved"; + string message = "Snapshot saved"; try { instance().png().saveImage(sspath.str(), s, rect); diff --git a/src/debugger/gui/TiaOutputWidget.hxx b/src/debugger/gui/TiaOutputWidget.hxx index 59a3c1843..b62fc123e 100644 --- a/src/debugger/gui/TiaOutputWidget.hxx +++ b/src/debugger/gui/TiaOutputWidget.hxx @@ -36,8 +36,7 @@ class TiaOutputWidget : public Widget, public CommandSender void loadConfig() override; void setZoomWidget(TiaZoomWidget* w) { myZoom = w; } - void saveSnapshot() { saveSnapshot(0, ""); }; - void saveSnapshot(int execDepth, const string& execPrefix); + void saveSnapshot(int execDepth = 0, const string& execPrefix = ""); // Eventually, these methods will enable access to the onscreen TIA image // For example, clicking an area may cause an action