From a5f76a530f3ef1f993941ef92615df5c522e0c28 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 27 Dec 2020 21:34:36 -0330 Subject: [PATCH 1/7] Clarified point in changelog. --- Changes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes.txt b/Changes.txt index 976e17aec..2a5f2dd6d 100644 --- a/Changes.txt +++ b/Changes.txt @@ -41,7 +41,7 @@ * Fixed autofire bug for trackball controllers. * Fixed bug in TV autodetection in filenames; a filename containing - 'PAL' would sometimes misdetect as a PAL ROM. + 'PAL' inside a word would sometimes misdetect as a PAL ROM. * Fixed Stelladaptor/2600'daptor devices sometimes not being assigned correct default mappings. From 024b228fdca04f0c2f24ed87e49b2701a9485dfc Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 27 Dec 2020 21:52:13 -0330 Subject: [PATCH 2/7] Missed a few brace-initializations. --- src/cheat/Cheat.hxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cheat/Cheat.hxx b/src/cheat/Cheat.hxx index 4979fca51..bde8b007a 100644 --- a/src/cheat/Cheat.hxx +++ b/src/cheat/Cheat.hxx @@ -26,10 +26,9 @@ class Cheat { public: Cheat(OSystem& osystem, const string& name, const string& code) - : myOSystem(osystem), - myName(name == "" ? code : name), - myCode(code) - { } + : myOSystem{osystem}, + myName{name == "" ? code : name}, + myCode{code} { } virtual ~Cheat() = default; bool enabled() const { return myEnabled; } From 9a32eff61f7cb45d769734dd4968c91769ccd4fe Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 27 Dec 2020 22:38:09 -0330 Subject: [PATCH 3/7] Add generic 'contains' method, and remove incorrect FIXME. --- src/common/Rect.hxx | 1 - src/common/bspf.hxx | 8 ++++---- src/gui/Widget.cxx | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/common/Rect.hxx b/src/common/Rect.hxx index 869cc5e75..708de9d86 100644 --- a/src/common/Rect.hxx +++ b/src/common/Rect.hxx @@ -32,7 +32,6 @@ namespace Common { */ struct Point { - // FIXME : make this uInt32 Int32 x{0}; //!< The horizontal part of the point Int32 y{0}; //!< The vertical part of the point diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index 44d649869..5abe26dd3 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -170,10 +170,10 @@ namespace BSPF return (val < lower) ? upper : (val > upper) ? lower : val; } - // Test whether the vector contains the given value - template - bool contains(const std::vector& v, const T& elem) { - return !(v.empty() || std::find(v.begin(), v.end(), elem) == v.end()); + // Test whether a container contains the given value + template + bool contains(const Container& c, typename Container::const_reference elem) { + return std::find(c.cbegin(), c.cend(), elem) != c.end(); } // Convert string to given case diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index d568c14cb..98120cae4 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -316,8 +316,7 @@ bool Widget::isWidgetInChain(Widget* w, Widget* find) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Widget::isWidgetInChain(const WidgetArray& list, Widget* find) { - return std::any_of(list.cbegin(), list.cend(), - [&](Widget* w) { return w == find; }); + return BSPF::contains(list, find); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 967434aad6bf4942955ae36f1925b283a08d5cf6 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 28 Dec 2020 12:37:49 +0100 Subject: [PATCH 4/7] inlined browser dialogs in debugger parser added optional browser dialog to "dump" command (somewhat ugly!) --- docs/debugger.html | 12 +- src/debugger/CartDebug.hxx | 6 +- src/debugger/DebuggerParser.cxx | 216 ++++++++++++++++++++-------- src/debugger/DebuggerParser.hxx | 2 + src/debugger/gui/DebuggerDialog.cxx | 60 -------- src/debugger/gui/DebuggerDialog.hxx | 11 -- src/debugger/gui/PromptWidget.cxx | 11 +- src/debugger/gui/PromptWidget.hxx | 2 +- src/gui/BrowserDialog.cxx | 13 +- src/gui/BrowserDialog.hxx | 17 +++ 10 files changed, 208 insertions(+), 142 deletions(-) diff --git a/docs/debugger.html b/docs/debugger.html index 6e9432fc6..38e24467b 100644 --- a/docs/debugger.html +++ b/docs/debugger.html @@ -947,7 +947,7 @@ clearsavestateifs - Clear all savestate points deltrap - Delete trap <xx> delwatch - Delete watch <xx> disasm - Disassemble address xx [yy lines] (default=PC) - dump - Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs] + dump - Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs] [?] exec - Execute script file <xx> [prefix] exitrom - Exit emulator, return to ROM launcher frame - Advance emulation by <xx> frames (default=1) @@ -989,12 +989,12 @@ clearsavestateifs - Clear all savestate points runto - Run until string xx in disassembly runtopc - Run until PC is set to value xx s - Set Stack Pointer to value xx - save - Save breaks, watches, traps and functions to file xx (use ? for file dialog) - saveaccess - Save access counters to CSV file (use ? for file dialog) + save - Save breaks, watches, traps and functions to file + saveaccess - Save access counters to CSV file [?] saveconfig - Save DiStella config file (with default name) - savedis - Save DiStella disassembly (use ? for file dialog) - saverom - Save (possibly patched) ROM (use ? for file dialog) - saveses - Save console session (use ? for file dialog) + savedis - Save DiStella disassembly to file [?] + saverom - Save (possibly patched) ROM to file [?] + saveses - Save console session to file [?] savesnap - Save current TIA image to PNG file saveallstates - Save all emulator states savestate - Save emulator state xx (valid args 0-9) diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 174478e71..e9797c91e 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -236,13 +236,13 @@ class CartDebug : public DebuggerSystem /** Save disassembly and ROM file */ - string saveDisassembly(string path); - string saveRom(string path); + string saveDisassembly(string path = EmptyString); + string saveRom(string path = EmptyString); /** Save access counters file */ - string saveAccessFile(string path); + string saveAccessFile(string path = EmptyString); /** Show Distella directives (both set by the user and determined by Distella) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 0d35b5e30..3723f82eb 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -36,6 +36,7 @@ #include "RomWidget.hxx" #include "ProgressDialog.hxx" #include "BrowserDialog.hxx" +#include "FrameBuffer.hxx" #include "TimerManager.hxx" #include "Vec.hxx" @@ -699,6 +700,21 @@ string DebuggerParser::saveScriptFile(string file) return "saved " + node.getShortPath() + " OK"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DebuggerParser::saveDump(const FilesystemNode& node, const ostringstream& out, + ostringstream& result) +{ + // cout << "dump " << args[0] << "-" << args[1] << " to " << path.str() << endl; + std::ofstream ofs(node.getPath(), std::ofstream::out); + + if(!ofs.is_open()) + result.str(red("Unable to append dump to file " + node.getShortPath())); + else + { + ofs << out.str(); + result << " to file " << node.getShortPath(); + } +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerParser::executeDirective(Device::AccessType type) { @@ -1126,7 +1142,7 @@ void DebuggerParser::executeDump() }; // Error checking - if( argCount == 0 || argCount > 3) + if(argCount == 0 || argCount > 4) { outputCommandError("wrong number of arguments", myCommand); return; @@ -1143,32 +1159,33 @@ void DebuggerParser::executeDump() dump(commandResult, args[0], args[1]); else { - ostringstream file; - file << debugger.myOSystem.userDir() << cartName() << "_dbg_"; - if(execDepth > 0) + if((args[2] & 0x07) == 0) { - file << execPrefix; - } - else - { - file << std::hex << std::setw(8) << std::setfill('0') - << uInt32(TimerManager::getTicks() / 1000); - } - file << ".dump"; - FilesystemNode node(file.str()); - // cout << "dump " << args[0] << "-" << args[1] << " to " << file.str() << endl; - std::ofstream ofs(node.getPath(), std::ofstream::out | std::ofstream::app); - if(!ofs.is_open()) - { - outputCommandError("Unable to append dump to file " + node.getShortPath(), myCommand); + commandResult << red("dump flags must be 1..7"); return; } - if((args[2] & 0x07) != 0) - commandResult << "dumped "; + if(argCount == 4 && argStrings[3] != "?") + { + commandResult << red("browser dialog parameter must be '?'"); + return; + } + + ostringstream path; + path << debugger.myOSystem.userDir() << cartName() << "_dbg_"; + if(execDepth > 0) + path << execPrefix; + else + path << std::hex << std::setw(8) << std::setfill('0') + << uInt32(TimerManager::getTicks() / 1000); + path << ".dump"; + + commandResult << "dumped "; + + ostringstream out; if((args[2] & 0x01) != 0) { // dump memory - dump(ofs, args[0], args[1]); + dump(out, args[0], args[1]); commandResult << "bytes from $" << hex << args[0] << " to $" << hex << args[1]; if((args[2] & 0x06) != 0) commandResult << ", "; @@ -1177,8 +1194,8 @@ void DebuggerParser::executeDump() { // dump CPU state CpuDebug& cpu = debugger.cpuDebug(); - ofs << " PC SP A X Y - - N V B D I Z C -\n"; - ofs << "XC: " + out << " PC SP A X Y - - N V B D I Z C -\n"; + out << "XC: " << Base::toString(cpu.pc() & 0xff) << " " // PC lsb << Base::toString(cpu.pc() >> 8) << " " // PC msb << Base::toString(cpu.sp()) << " " // SP @@ -1203,8 +1220,8 @@ void DebuggerParser::executeDump() if((args[2] & 0x04) != 0) { // dump SWCHx/INPTx state - ofs << " SWA - SWB - IT - - - I0 I1 I2 I3 I4 I5 - -\n"; - ofs << "XS: " + out << " SWA - SWB - IT - - - I0 I1 I2 I3 I4 I5 - -\n"; + out << "XS: " << Base::toString(debugger.peek(0x280)) << " " // SWCHA << Base::toString(0) << " " // unused << Base::toString(debugger.peek(0x282)) << " " // SWCHB @@ -1224,8 +1241,34 @@ void DebuggerParser::executeDump() << endl; commandResult << "switches and fire buttons"; } - if((args[2] & 0x07) != 0) - commandResult << " to file " << node.getShortPath(); + + if(argCount == 4) + { + string outStr = out.str(); // ugly, why can't we transfer directly? + string resultStr = commandResult.str(); // same + BrowserDialog::show(debugger.myDialog, "Save Dump as", path.str(), + BrowserDialog::Mode::FileSave, + [this, outStr, resultStr](bool OK, const FilesystemNode& node) + { + DebuggerDialog* dlg = debugger.myDialog; + + if(OK) + { + ostringstream out, result; + + out << outStr; // ...and ugly back + result << resultStr; + + saveDump(node, out, result); + dlg->prompt().print(result.str() + '\n'); + } + dlg->prompt().printPrompt(); + }); + // avoid printing a new prompt + commandResult.str("_EXIT_DEBUGGER"); + } + else + saveDump(FilesystemNode(path.str()), out, commandResult); } } @@ -1846,9 +1889,21 @@ void DebuggerParser::executeSave() { if(argCount && argStrings[0] == "?") { - debugger.myDialog->showBrowser(DebuggerDialog::svScript, cartName() + ".script"); + DebuggerDialog* dlg = debugger.myDialog; + + BrowserDialog::show(dlg, "Save Workbench as", + dlg->instance().userDir().getPath() + cartName() + ".script", + BrowserDialog::Mode::FileSave, + [this](bool OK, const FilesystemNode& node) + { + DebuggerDialog* dlg = debugger.myDialog; + + if(OK) + dlg->prompt().print(saveScriptFile(node.getPath()) + '\n'); + dlg->prompt().printPrompt(); + }); // avoid printing a new prompt - commandResult << "_EXIT_DEBUGGER"; + commandResult.str("_EXIT_DEBUGGER"); } else commandResult << saveScriptFile(argStrings[0]); @@ -1860,12 +1915,24 @@ void DebuggerParser::executeSaveAccess() { if(argCount && argStrings[0] == "?") { - debugger.myDialog->showBrowser(DebuggerDialog::svAccess, cartName() + ".csv"); + DebuggerDialog* dlg = debugger.myDialog; + + BrowserDialog::show(dlg, "Save Access Counters as", + dlg->instance().userDir().getPath() + cartName() + ".csv", + BrowserDialog::Mode::FileSave, + [this](bool OK, const FilesystemNode& node) + { + DebuggerDialog* dlg = debugger.myDialog; + + if(OK) + dlg->prompt().print(debugger.cartDebug().saveAccessFile(node.getPath()) + '\n'); + dlg->prompt().printPrompt(); + }); // avoid printing a new prompt - commandResult << "_EXIT_DEBUGGER"; + commandResult.str("_EXIT_DEBUGGER"); } else - commandResult << debugger.cartDebug().saveAccessFile(argCount ? argStrings[0] : EmptyString); + commandResult << debugger.cartDebug().saveAccessFile(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1881,12 +1948,24 @@ void DebuggerParser::executeSavedisassembly() { if(argCount && argStrings[0] == "?") { - debugger.myDialog->showBrowser(DebuggerDialog::svDis, cartName() + ".asm"); + DebuggerDialog* dlg = debugger.myDialog; + + BrowserDialog::show(dlg, "Save Disassembly as", + dlg->instance().userDir().getPath() + cartName() + ".asm", + BrowserDialog::Mode::FileSave, + [this](bool OK, const FilesystemNode& node) + { + DebuggerDialog* dlg = debugger.myDialog; + + if(OK) + dlg->prompt().print(debugger.cartDebug().saveDisassembly(node.getPath()) + '\n'); + dlg->prompt().printPrompt(); + }); // avoid printing a new prompt - commandResult << "_EXIT_DEBUGGER"; + commandResult.str("_EXIT_DEBUGGER"); } else - commandResult << debugger.cartDebug().saveDisassembly(argCount ? argStrings[0] : EmptyString); + commandResult << debugger.cartDebug().saveDisassembly(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1895,12 +1974,24 @@ void DebuggerParser::executeSaverom() { if(argCount && argStrings[0] == "?") { - debugger.myDialog->showBrowser(DebuggerDialog::svRom, cartName() + ".a26"); + DebuggerDialog* dlg = debugger.myDialog; + + BrowserDialog::show(dlg, "Save ROM as", + dlg->instance().userDir().getPath() + cartName() + ".a26", + BrowserDialog::Mode::FileSave, + [this](bool OK, const FilesystemNode& node) + { + DebuggerDialog* dlg = debugger.myDialog; + + if(OK) + dlg->prompt().print(debugger.cartDebug().saveRom(node.getPath()) + '\n'); + dlg->prompt().printPrompt(); + }); // avoid printing a new prompt - commandResult << "_EXIT_DEBUGGER"; + commandResult.str("_EXIT_DEBUGGER"); } else - commandResult << debugger.cartDebug().saveRom(argCount ? argStrings[0] : EmptyString); + commandResult << debugger.cartDebug().saveRom(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1913,22 +2004,32 @@ void DebuggerParser::executeSaveses() if(argCount && argStrings[0] == "?") { - debugger.myDialog->showBrowser(DebuggerDialog::svSession, filename.str()); - commandResult << "_EXIT_DEBUGGER"; + DebuggerDialog* dlg = debugger.myDialog; + + BrowserDialog::show(dlg, "Save Session as", + dlg->instance().userDir().getPath() + filename.str(), + BrowserDialog::Mode::FileSave, + [this](bool OK, const FilesystemNode& node) + { + DebuggerDialog* dlg = debugger.myDialog; + + if(OK) + dlg->prompt().print(debugger.prompt().saveBuffer(node) + '\n'); + dlg->prompt().printPrompt(); + }); + // avoid printing a new prompt + commandResult.str("_EXIT_DEBUGGER"); } else { ostringstream path; + if(argCount) path << argStrings[0]; else path << debugger.myOSystem.userDir() << filename.str(); - FilesystemNode file(path.str()); - if(debugger.prompt().saveBuffer(file)) - commandResult << "saved " + file.getShortPath() + " OK"; - else - commandResult << "unable to save session"; + commandResult << debugger.prompt().saveBuffer(FilesystemNode(path.str())); } } @@ -2667,15 +2768,16 @@ std::array DebuggerParser::commands = { { { "dump", - "Dump data at address [to yy] [1: memory; 2: CPU state; 4: input regs]", + "Dump data at address [to yy] [1: memory; 2: CPU state; 4: input regs] [?]", "Example:\n" " dump f000 - dumps 128 bytes from f000\n" " dump f000 f0ff - dumps all bytes from f000 to f0ff\n" " dump f000 f0ff 7 - dumps all bytes from f000 to f0ff,\n" - " CPU state and input registers into a file in user dir", + " CPU state and input registers into a file in user dir,\n" + " dump f000 f0ff 7 ? - same, but with a browser dialog\n", true, false, - { Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE }, + { Parameters::ARG_WORD, Parameters::ARG_WORD, Parameters::ARG_BYTE, Parameters::ARG_LABEL }, std::mem_fn(&DebuggerParser::executeDump) }, @@ -3095,7 +3197,7 @@ std::array DebuggerParser::commands = { { { "save", - "Save breaks, watches, traps and functions to file xx", + "Save breaks, watches, traps and functions to file ", "Example: save commands.script, save ?\n" "NOTE: saves to user dir by default", true, @@ -3106,12 +3208,12 @@ std::array DebuggerParser::commands = { { { "saveaccess", - "Save the access counters to CSV file", + "Save the access counters to CSV file [?]", "Example: saveaccess, saveaccess ?\n" "NOTE: saves to user dir by default", false, false, - { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, + { Parameters::ARG_LABEL, Parameters::ARG_END_ARGS }, std::mem_fn(&DebuggerParser::executeSaveAccess) }, @@ -3127,34 +3229,34 @@ std::array DebuggerParser::commands = { { { "savedis", - "Save Distella disassembly", + "Save Distella disassembly to file [?]", "Example: savedis, savedis ?\n" "NOTE: saves to user dir by default", false, false, - { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, + { Parameters::ARG_LABEL, Parameters::ARG_END_ARGS }, std::mem_fn(&DebuggerParser::executeSavedisassembly) }, { "saverom", - "Save (possibly patched) ROM", + "Save (possibly patched) ROM to file [?]", "Example: saverom, saverom ?\n" "NOTE: saves to user dir by default", false, false, - { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, + { Parameters::ARG_LABEL, Parameters::ARG_END_ARGS }, std::mem_fn(&DebuggerParser::executeSaverom) }, { "saveses", - "Save console session", + "Save console session to file [?]", "Example: saveses, saveses ?\n" "NOTE: saves to user dir by default", false, false, - { Parameters::ARG_FILE, Parameters::ARG_END_ARGS }, + { Parameters::ARG_LABEL, Parameters::ARG_END_ARGS }, std::mem_fn(&DebuggerParser::executeSaveses) }, diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index afdda5f36..687e96cee 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -65,6 +65,8 @@ class DebuggerParser bool validateArgs(int cmd); string eval(); string saveScriptFile(string file); + void saveDump(const FilesystemNode& node, const ostringstream& out, + ostringstream& result); const string& cartName() const; private: diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index f7a8987f0..fee627c3a 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -400,66 +400,6 @@ void DebuggerDialog::createFont() tooltip().setFont(*myNFont); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DebuggerDialog::showBrowser(BrowserType type, const string& defaultName) -{ - string title, command; - - switch(type) - { - case BrowserType::svAccess: - title = "Access Counters"; - command = "saveaccess"; - break; - - case BrowserType::svDis: - title = "Disassembly"; - command = "savedis"; - break; - - case BrowserType::svRom: - title = "ROM"; - command = "saverom"; - break; - - case BrowserType::svScript: - title = "Workbench"; - command = "save"; - break; - - case BrowserType::svSession: - title = "Session"; - command = "saveses"; - break; - - default: - break; - } - - if(command != EmptyString) - { - BrowserDialog::show(this, instance().frameBuffer().font(), "Save " + title + " as", - instance().userDir().getPath() + defaultName, - BrowserDialog::Mode::FileSave, - [this, command](bool OK, const FilesystemNode& node) { - if(OK) runCommand(node, command); - else runCommand(node); - }); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DebuggerDialog::runCommand(const FilesystemNode& node, const string& command) -{ - if(command != EmptyString) - { - string result = instance().debugger().parser().run(command + " {" + - node.getPath() + "}"); - prompt().print(result + '\n'); - } - prompt().printPrompt(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerDialog::showFatalMessage(const string& msg) { diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index 2552f78c1..b5dc49583 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -55,13 +55,6 @@ class DebuggerDialog : public Dialog kMediumFontMinW = 1160, kMediumFontMinH = 770, kLargeFontMinW = 1160, kLargeFontMinH = 870 }; - enum BrowserType { - svAccess, // saveaccess - svDis, // savedis - svRom, // saverom - svScript, // save - svSession // saveses - }; DebuggerDialog(OSystem& osystem, DialogContainer& parent, int x, int y, int w, int h); @@ -82,7 +75,6 @@ class DebuggerDialog : public Dialog void showFatalMessage(const string& msg); void saveConfig() override; - void showBrowser(BrowserType type, const string& defaultName); private: void setPosition() override { positionAt(0); } @@ -127,9 +119,6 @@ class DebuggerDialog : public Dialog kDDOptionsCmd = 'DDop' }; - void runCommand(const FilesystemNode& node, - const string& command = EmptyString); - TabWidget *myTab{nullptr}, *myRomTab{nullptr}; PromptWidget* myPrompt{nullptr}; diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx index 1ed5b2350..52360f3af 100644 --- a/src/debugger/gui/PromptWidget.cxx +++ b/src/debugger/gui/PromptWidget.cxx @@ -968,7 +968,7 @@ void PromptWidget::scrollToCurrent() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool PromptWidget::saveBuffer(const FilesystemNode& file) +string PromptWidget::saveBuffer(const FilesystemNode& file) { stringstream out; for(int start = 0; start < _promptStartPos; start += _lineWidth) @@ -988,8 +988,13 @@ bool PromptWidget::saveBuffer(const FilesystemNode& file) out << endl; } - try { return file.write(out) > 0; } - catch(...) { return false; } + try { + if(file.write(out) > 0) + return "saved " + file.getShortPath() + " OK"; + } + catch(...) { } + + return "unable to save session"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/PromptWidget.hxx b/src/debugger/gui/PromptWidget.hxx index c1719fa1a..e61e4d598 100644 --- a/src/debugger/gui/PromptWidget.hxx +++ b/src/debugger/gui/PromptWidget.hxx @@ -46,7 +46,7 @@ class PromptWidget : public Widget, public CommandSender ATTRIBUTE_FMT_PRINTF int vprintf(const char* format, va_list argptr); void print(const string& str); void printPrompt(); - bool saveBuffer(const FilesystemNode& file); + string saveBuffer(const FilesystemNode& file); // Clear screen and erase all history void clearScreen(); diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index 5506c4bc3..a93fe5a3b 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -20,6 +20,7 @@ #include "FSNode.hxx" #include "GuiObject.hxx" #include "OSystem.hxx" +#include "FrameBuffer.hxx" #include "EditTextWidget.hxx" #include "FileListWidget.hxx" #include "Widget.hxx" @@ -131,6 +132,17 @@ void BrowserDialog::show(GuiObject* parent, const GUI::Font& font, ourBrowser->show(startpath, mode, command, namefilter); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void BrowserDialog::show(GuiObject* parent, + const string& title, const string& startpath, + BrowserDialog::Mode mode, + const Command& command, + const FilesystemNode::NameFilter& namefilter) +{ + show(parent, parent->instance().frameBuffer().font(), title, startpath, + mode, command, namefilter); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void BrowserDialog::show(const string& startpath, BrowserDialog::Mode mode, @@ -247,7 +259,6 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd, // Send a signal to the calling class that a selection has been made if(_mode != Mode::Directories) { - // TODO: check if affected by '-baseDir'and 'basedirinapp' params bool savePath = _savePathBox->getState(); instance().settings().setValue("saveuserdir", savePath); diff --git a/src/gui/BrowserDialog.hxx b/src/gui/BrowserDialog.hxx index c8c32759c..466c43242 100644 --- a/src/gui/BrowserDialog.hxx +++ b/src/gui/BrowserDialog.hxx @@ -69,6 +69,23 @@ class BrowserDialog : public Dialog const FilesystemNode::NameFilter& namefilter = { [](const FilesystemNode&) { return true; }}); + /** + Place the browser window onscreen, using the given attributes. + + @param parent The parent object of the browser (cannot be nullptr) + @param title The title of the browser window + @param startpath The initial path to select in the browser + @param mode The functionality to use (load/save/display) + @param command The command to run when 'OK' or 'Cancel' is clicked + @param namefilter Filter files/directories in browser display + */ + static void show(GuiObject* parent, + const string& title, const string& startpath, + BrowserDialog::Mode mode, + const Command& command, + const FilesystemNode::NameFilter& namefilter = { + [](const FilesystemNode&) { return true; } }); + private: /** Place the browser window onscreen, using the given attributes */ void show(const string& startpath, From 395366b0772f42885ecee935b35dad74e4f1eeb8 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 28 Dec 2020 17:16:49 +0100 Subject: [PATCH 5/7] fixed duplicate prompt when stepping, tracing etc. after browser dialog a few minor improvements --- src/debugger/DebuggerParser.cxx | 47 ++++++++++++------------------- src/debugger/gui/PromptWidget.cxx | 2 ++ 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 3723f82eb..3f7d346fa 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1244,20 +1244,19 @@ void DebuggerParser::executeDump() if(argCount == 4) { - string outStr = out.str(); // ugly, why can't we transfer directly? - string resultStr = commandResult.str(); // same - BrowserDialog::show(debugger.myDialog, "Save Dump as", path.str(), + DebuggerDialog* dlg = debugger.myDialog; + const string outStr = out.str(); // ugly, why can't we capture directly? + const string resultStr = commandResult.str(); // same + BrowserDialog::show(dlg, "Save Dump as", path.str(), BrowserDialog::Mode::FileSave, - [this, outStr, resultStr](bool OK, const FilesystemNode& node) + [=](bool OK, const FilesystemNode& node) { - DebuggerDialog* dlg = debugger.myDialog; - if(OK) { ostringstream out, result; - out << outStr; // ...and ugly back - result << resultStr; + out.str(outStr); // ...and ugly back + result.str(resultStr); saveDump(node, out, result); dlg->prompt().print(result.str() + '\n'); @@ -1265,7 +1264,7 @@ void DebuggerParser::executeDump() dlg->prompt().printPrompt(); }); // avoid printing a new prompt - commandResult.str("_EXIT_DEBUGGER"); + commandResult.str("_NO_PROMPT"); } else saveDump(FilesystemNode(path.str()), out, commandResult); @@ -1894,16 +1893,14 @@ void DebuggerParser::executeSave() BrowserDialog::show(dlg, "Save Workbench as", dlg->instance().userDir().getPath() + cartName() + ".script", BrowserDialog::Mode::FileSave, - [this](bool OK, const FilesystemNode& node) + [=](bool OK, const FilesystemNode& node) { - DebuggerDialog* dlg = debugger.myDialog; - if(OK) dlg->prompt().print(saveScriptFile(node.getPath()) + '\n'); dlg->prompt().printPrompt(); }); // avoid printing a new prompt - commandResult.str("_EXIT_DEBUGGER"); + commandResult.str("_NO_PROMPT"); } else commandResult << saveScriptFile(argStrings[0]); @@ -1920,16 +1917,14 @@ void DebuggerParser::executeSaveAccess() BrowserDialog::show(dlg, "Save Access Counters as", dlg->instance().userDir().getPath() + cartName() + ".csv", BrowserDialog::Mode::FileSave, - [this](bool OK, const FilesystemNode& node) + [=](bool OK, const FilesystemNode& node) { - DebuggerDialog* dlg = debugger.myDialog; - if(OK) dlg->prompt().print(debugger.cartDebug().saveAccessFile(node.getPath()) + '\n'); dlg->prompt().printPrompt(); }); // avoid printing a new prompt - commandResult.str("_EXIT_DEBUGGER"); + commandResult.str("_NO_PROMPT"); } else commandResult << debugger.cartDebug().saveAccessFile(); @@ -1953,16 +1948,14 @@ void DebuggerParser::executeSavedisassembly() BrowserDialog::show(dlg, "Save Disassembly as", dlg->instance().userDir().getPath() + cartName() + ".asm", BrowserDialog::Mode::FileSave, - [this](bool OK, const FilesystemNode& node) + [=](bool OK, const FilesystemNode& node) { - DebuggerDialog* dlg = debugger.myDialog; - if(OK) dlg->prompt().print(debugger.cartDebug().saveDisassembly(node.getPath()) + '\n'); dlg->prompt().printPrompt(); }); // avoid printing a new prompt - commandResult.str("_EXIT_DEBUGGER"); + commandResult.str("_NO_PROMPT"); } else commandResult << debugger.cartDebug().saveDisassembly(); @@ -1979,16 +1972,14 @@ void DebuggerParser::executeSaverom() BrowserDialog::show(dlg, "Save ROM as", dlg->instance().userDir().getPath() + cartName() + ".a26", BrowserDialog::Mode::FileSave, - [this](bool OK, const FilesystemNode& node) + [=](bool OK, const FilesystemNode& node) { - DebuggerDialog* dlg = debugger.myDialog; - if(OK) dlg->prompt().print(debugger.cartDebug().saveRom(node.getPath()) + '\n'); dlg->prompt().printPrompt(); }); // avoid printing a new prompt - commandResult.str("_EXIT_DEBUGGER"); + commandResult.str("_NO_PROMPT"); } else commandResult << debugger.cartDebug().saveRom(); @@ -2009,16 +2000,14 @@ void DebuggerParser::executeSaveses() BrowserDialog::show(dlg, "Save Session as", dlg->instance().userDir().getPath() + filename.str(), BrowserDialog::Mode::FileSave, - [this](bool OK, const FilesystemNode& node) + [=](bool OK, const FilesystemNode& node) { - DebuggerDialog* dlg = debugger.myDialog; - if(OK) dlg->prompt().print(debugger.prompt().saveBuffer(node) + '\n'); dlg->prompt().printPrompt(); }); // avoid printing a new prompt - commandResult.str("_EXIT_DEBUGGER"); + commandResult.str("_NO_PROMPT"); } else { diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx index 52360f3af..584fd1d56 100644 --- a/src/debugger/gui/PromptWidget.cxx +++ b/src/debugger/gui/PromptWidget.cxx @@ -191,6 +191,8 @@ bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod) _exitedEarly = true; return true; } + else if(result == "_NO_PROMPT") + return true; else if(result != "") print(result + "\n"); } From b5c1d4f2e6e9a36ae199b7e45a6d40574629f8be Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Mon, 28 Dec 2020 16:19:52 -0330 Subject: [PATCH 6/7] Fix issues with passing streams into lambda, and data not being transferred sometimes. Documented weirdness of this; perhaps a future version of C++ will allow it. Write data through 'node' object rather than raw ofstream, like other code in the class. --- src/debugger/DebuggerParser.cxx | 50 ++++++++++++++++++--------------- src/debugger/DebuggerParser.hxx | 2 +- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 3f7d346fa..a783b5db8 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -701,20 +701,20 @@ string DebuggerParser::saveScriptFile(string file) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DebuggerParser::saveDump(const FilesystemNode& node, const ostringstream& out, +void DebuggerParser::saveDump(const FilesystemNode& node, const stringstream& out, ostringstream& result) { - // cout << "dump " << args[0] << "-" << args[1] << " to " << path.str() << endl; - std::ofstream ofs(node.getPath(), std::ofstream::out); - - if(!ofs.is_open()) - result.str(red("Unable to append dump to file " + node.getShortPath())); - else + try { - ofs << out.str(); + node.write(out); result << " to file " << node.getShortPath(); } + catch(...) + { + result.str(red("Unable to append dump to file " + node.getShortPath())); + } } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerParser::executeDirective(Device::AccessType type) { @@ -1181,7 +1181,7 @@ void DebuggerParser::executeDump() commandResult << "dumped "; - ostringstream out; + stringstream out; if((args[2] & 0x01) != 0) { // dump memory @@ -1244,22 +1244,26 @@ void DebuggerParser::executeDump() if(argCount == 4) { + // FIXME: C++ doesn't currently allow capture of stringstreams + // So we pass a copy of its contents, then re-create the + // stream inside the lambda + // Maybe this will change in a future version + const string outStr = out.str(); + const string resultStr = commandResult.str(); + DebuggerDialog* dlg = debugger.myDialog; - const string outStr = out.str(); // ugly, why can't we capture directly? - const string resultStr = commandResult.str(); // same BrowserDialog::show(dlg, "Save Dump as", path.str(), BrowserDialog::Mode::FileSave, - [=](bool OK, const FilesystemNode& node) + [this, dlg, outStr, resultStr] + (bool OK, const FilesystemNode& node) { if(OK) { - ostringstream out, result; + stringstream localOut(outStr); + ostringstream localResult(resultStr, std::ios_base::app); - out.str(outStr); // ...and ugly back - result.str(resultStr); - - saveDump(node, out, result); - dlg->prompt().print(result.str() + '\n'); + saveDump(node, localOut, localResult); + dlg->prompt().print(localResult.str() + '\n'); } dlg->prompt().printPrompt(); }); @@ -1893,7 +1897,7 @@ void DebuggerParser::executeSave() BrowserDialog::show(dlg, "Save Workbench as", dlg->instance().userDir().getPath() + cartName() + ".script", BrowserDialog::Mode::FileSave, - [=](bool OK, const FilesystemNode& node) + [this, dlg](bool OK, const FilesystemNode& node) { if(OK) dlg->prompt().print(saveScriptFile(node.getPath()) + '\n'); @@ -1917,7 +1921,7 @@ void DebuggerParser::executeSaveAccess() BrowserDialog::show(dlg, "Save Access Counters as", dlg->instance().userDir().getPath() + cartName() + ".csv", BrowserDialog::Mode::FileSave, - [=](bool OK, const FilesystemNode& node) + [this, dlg](bool OK, const FilesystemNode& node) { if(OK) dlg->prompt().print(debugger.cartDebug().saveAccessFile(node.getPath()) + '\n'); @@ -1948,7 +1952,7 @@ void DebuggerParser::executeSavedisassembly() BrowserDialog::show(dlg, "Save Disassembly as", dlg->instance().userDir().getPath() + cartName() + ".asm", BrowserDialog::Mode::FileSave, - [=](bool OK, const FilesystemNode& node) + [this, dlg](bool OK, const FilesystemNode& node) { if(OK) dlg->prompt().print(debugger.cartDebug().saveDisassembly(node.getPath()) + '\n'); @@ -1972,7 +1976,7 @@ void DebuggerParser::executeSaverom() BrowserDialog::show(dlg, "Save ROM as", dlg->instance().userDir().getPath() + cartName() + ".a26", BrowserDialog::Mode::FileSave, - [=](bool OK, const FilesystemNode& node) + [this, dlg](bool OK, const FilesystemNode& node) { if(OK) dlg->prompt().print(debugger.cartDebug().saveRom(node.getPath()) + '\n'); @@ -2000,7 +2004,7 @@ void DebuggerParser::executeSaveses() BrowserDialog::show(dlg, "Save Session as", dlg->instance().userDir().getPath() + filename.str(), BrowserDialog::Mode::FileSave, - [=](bool OK, const FilesystemNode& node) + [this, dlg](bool OK, const FilesystemNode& node) { if(OK) dlg->prompt().print(debugger.prompt().saveBuffer(node) + '\n'); diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 687e96cee..1f66f06e3 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -65,7 +65,7 @@ class DebuggerParser bool validateArgs(int cmd); string eval(); string saveScriptFile(string file); - void saveDump(const FilesystemNode& node, const ostringstream& out, + void saveDump(const FilesystemNode& node, const stringstream& out, ostringstream& result); const string& cartName() const; From 5770ec4daa22b963d9985caffa938837fb4bc189 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Wed, 30 Dec 2020 18:16:14 +0100 Subject: [PATCH 7/7] minor debugger doc updates --- docs/index.html | 10 ++++++---- src/debugger/gui/RomListSettings.cxx | 13 +++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/index.html b/docs/index.html index ab72c53a3..db7957c7c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3239,19 +3239,21 @@
-dis.resolve <1|0>
- Try to differentiate between code vs. data sections in the - disassembler. See the Debugger - ROM Disassembly Settings for more information. + Try to differentiate between tentative code vs. data sections in the + disassembler via static code analysis. See the Debugger - + ROM Disassembly Settings for more information.
-dis.gfxformat <2|16>
- Set the base to use for displaying GFX sections in the disassembler. + Switch between displaying/editing GFX and PGFX sections in either + binary or hexidecimal in the disassembler.
-dis.showaddr <1|0>
- Show/hide opcode addresses in the disassembler. + Show/hide program counter addresses as labels in the disassembler. diff --git a/src/debugger/gui/RomListSettings.cxx b/src/debugger/gui/RomListSettings.cxx index 93b555631..0029638c5 100644 --- a/src/debugger/gui/RomListSettings.cxx +++ b/src/debugger/gui/RomListSettings.cxx @@ -58,19 +58,24 @@ RomListSettings::RomListSettings(GuiObject* boss, const GUI::Font& font) // Settings for Distella xpos += 4; ypos += buttonHeight + 8; myShowTentative = new CheckboxWidget(this, font, xpos, ypos, - "Show tentative code", RomListWidget::kTentativeCodeCmd); + "Show tentative code", RomListWidget::kTentativeCodeCmd); + myShowTentative->setToolTip("Check to differentiate between tentative code\n" + "vs. data sections via static code analysis."); wid.push_back(myShowTentative); ypos += buttonHeight + 4; myShowAddresses = new CheckboxWidget(this, font, xpos, ypos, - "Show PC addresses", RomListWidget::kPCAddressesCmd); + "Show PC addresses", RomListWidget::kPCAddressesCmd); + myShowAddresses->setToolTip("Check to show program counter addresses as labels."); wid.push_back(myShowAddresses); ypos += buttonHeight + 4; myShowGFXBinary = new CheckboxWidget(this, font, xpos, ypos, - "Show GFX as binary", RomListWidget::kGfxAsBinaryCmd); + "Show GFX as binary", RomListWidget::kGfxAsBinaryCmd); + myShowGFXBinary->setToolTip("Check to allow editing GFX sections in binary format."); wid.push_back(myShowGFXBinary); ypos += buttonHeight + 4; myUseRelocation = new CheckboxWidget(this, font, xpos, ypos, - "Use address relocation", RomListWidget::kAddrRelocationCmd); + "Use address relocation", RomListWidget::kAddrRelocationCmd); + myUseRelocation->setToolTip("Check to relocate calls out of address range."); wid.push_back(myUseRelocation); // Set real dimensions