mirror of https://github.com/stella-emu/stella.git
Merge remote-tracking branch 'origin/master' into feature/full-on-sqlite
This commit is contained in:
commit
f496f8b74a
|
@ -41,7 +41,7 @@
|
||||||
* Fixed autofire bug for trackball controllers.
|
* Fixed autofire bug for trackball controllers.
|
||||||
|
|
||||||
* Fixed bug in TV autodetection in filenames; a filename containing
|
* 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
|
* Fixed Stelladaptor/2600'daptor devices sometimes not being assigned
|
||||||
correct default mappings.
|
correct default mappings.
|
||||||
|
|
|
@ -947,7 +947,7 @@ clearsavestateifs - Clear all savestate points
|
||||||
deltrap - Delete trap <xx>
|
deltrap - Delete trap <xx>
|
||||||
delwatch - Delete watch <xx>
|
delwatch - Delete watch <xx>
|
||||||
disasm - Disassemble address xx [yy lines] (default=PC)
|
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]
|
exec - Execute script file <xx> [prefix]
|
||||||
exitrom - Exit emulator, return to ROM launcher
|
exitrom - Exit emulator, return to ROM launcher
|
||||||
frame - Advance emulation by <xx> frames (default=1)
|
frame - Advance emulation by <xx> frames (default=1)
|
||||||
|
@ -989,12 +989,12 @@ clearsavestateifs - Clear all savestate points
|
||||||
runto - Run until string xx in disassembly
|
runto - Run until string xx in disassembly
|
||||||
runtopc - Run until PC is set to value xx
|
runtopc - Run until PC is set to value xx
|
||||||
s - Set Stack Pointer to value xx
|
s - Set Stack Pointer to value xx
|
||||||
save - Save breaks, watches, traps and functions to file xx (use ? for file dialog)
|
save - Save breaks, watches, traps and functions to file <xx or ?>
|
||||||
saveaccess - Save access counters to CSV file (use ? for file dialog)
|
saveaccess - Save access counters to CSV file [?]
|
||||||
saveconfig - Save DiStella config file (with default name)
|
saveconfig - Save DiStella config file (with default name)
|
||||||
savedis - Save DiStella disassembly (use ? for file dialog)
|
savedis - Save DiStella disassembly to file [?]
|
||||||
saverom - Save (possibly patched) ROM (use ? for file dialog)
|
saverom - Save (possibly patched) ROM to file [?]
|
||||||
saveses - Save console session (use ? for file dialog)
|
saveses - Save console session to file [?]
|
||||||
savesnap - Save current TIA image to PNG file
|
savesnap - Save current TIA image to PNG file
|
||||||
saveallstates - Save all emulator states
|
saveallstates - Save all emulator states
|
||||||
savestate - Save emulator state xx (valid args 0-9)
|
savestate - Save emulator state xx (valid args 0-9)
|
||||||
|
|
|
@ -3239,19 +3239,21 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><pre>-dis.resolve <1|0></pre></td>
|
<td><pre>-dis.resolve <1|0></pre></td>
|
||||||
<td>Try to differentiate between code vs. data sections in the
|
<td>Try to differentiate between tentative code vs. data sections in the
|
||||||
disassembler. See the <b>Debugger - <a href="debugger.html#DisassemblySettings">ROM Disassembly Settings</b></a> for more information.</td>
|
disassembler via static code analysis. See the <b>Debugger -
|
||||||
|
<a href="debugger.html#DisassemblySettings">ROM Disassembly Settings</b></a> for more information.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><pre>-dis.gfxformat <2|16></pre></td>
|
<td><pre>-dis.gfxformat <2|16></pre></td>
|
||||||
<td>Set the base to use for displaying GFX sections in the disassembler.
|
<td>Switch between displaying/editing GFX and PGFX sections in either
|
||||||
|
binary or hexidecimal in the disassembler.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><pre>-dis.showaddr <1|0></pre></td>
|
<td><pre>-dis.showaddr <1|0></pre></td>
|
||||||
<td>Show/hide opcode addresses in the disassembler.</td>
|
<td>Show/hide program counter addresses as labels in the disassembler.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -26,10 +26,9 @@ class Cheat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Cheat(OSystem& osystem, const string& name, const string& code)
|
Cheat(OSystem& osystem, const string& name, const string& code)
|
||||||
: myOSystem(osystem),
|
: myOSystem{osystem},
|
||||||
myName(name == "" ? code : name),
|
myName{name == "" ? code : name},
|
||||||
myCode(code)
|
myCode{code} { }
|
||||||
{ }
|
|
||||||
virtual ~Cheat() = default;
|
virtual ~Cheat() = default;
|
||||||
|
|
||||||
bool enabled() const { return myEnabled; }
|
bool enabled() const { return myEnabled; }
|
||||||
|
|
|
@ -32,7 +32,6 @@ namespace Common {
|
||||||
*/
|
*/
|
||||||
struct Point
|
struct Point
|
||||||
{
|
{
|
||||||
// FIXME : make this uInt32
|
|
||||||
Int32 x{0}; //!< The horizontal part of the point
|
Int32 x{0}; //!< The horizontal part of the point
|
||||||
Int32 y{0}; //!< The vertical part of the point
|
Int32 y{0}; //!< The vertical part of the point
|
||||||
|
|
||||||
|
|
|
@ -170,10 +170,10 @@ namespace BSPF
|
||||||
return (val < lower) ? upper : (val > upper) ? lower : val;
|
return (val < lower) ? upper : (val > upper) ? lower : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test whether the vector contains the given value
|
// Test whether a container contains the given value
|
||||||
template<typename T>
|
template<typename Container>
|
||||||
bool contains(const std::vector<T>& v, const T& elem) {
|
bool contains(const Container& c, typename Container::const_reference elem) {
|
||||||
return !(v.empty() || std::find(v.begin(), v.end(), elem) == v.end());
|
return std::find(c.cbegin(), c.cend(), elem) != c.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert string to given case
|
// Convert string to given case
|
||||||
|
|
|
@ -236,13 +236,13 @@ class CartDebug : public DebuggerSystem
|
||||||
/**
|
/**
|
||||||
Save disassembly and ROM file
|
Save disassembly and ROM file
|
||||||
*/
|
*/
|
||||||
string saveDisassembly(string path);
|
string saveDisassembly(string path = EmptyString);
|
||||||
string saveRom(string path);
|
string saveRom(string path = EmptyString);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Save access counters file
|
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)
|
Show Distella directives (both set by the user and determined by Distella)
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "RomWidget.hxx"
|
#include "RomWidget.hxx"
|
||||||
#include "ProgressDialog.hxx"
|
#include "ProgressDialog.hxx"
|
||||||
#include "BrowserDialog.hxx"
|
#include "BrowserDialog.hxx"
|
||||||
|
#include "FrameBuffer.hxx"
|
||||||
#include "TimerManager.hxx"
|
#include "TimerManager.hxx"
|
||||||
#include "Vec.hxx"
|
#include "Vec.hxx"
|
||||||
|
|
||||||
|
@ -699,6 +700,21 @@ string DebuggerParser::saveScriptFile(string file)
|
||||||
return "saved " + node.getShortPath() + " OK";
|
return "saved " + node.getShortPath() + " OK";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void DebuggerParser::saveDump(const FilesystemNode& node, const stringstream& out,
|
||||||
|
ostringstream& result)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
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)
|
void DebuggerParser::executeDirective(Device::AccessType type)
|
||||||
{
|
{
|
||||||
|
@ -1126,7 +1142,7 @@ void DebuggerParser::executeDump()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Error checking
|
// Error checking
|
||||||
if( argCount == 0 || argCount > 3)
|
if(argCount == 0 || argCount > 4)
|
||||||
{
|
{
|
||||||
outputCommandError("wrong number of arguments", myCommand);
|
outputCommandError("wrong number of arguments", myCommand);
|
||||||
return;
|
return;
|
||||||
|
@ -1143,32 +1159,33 @@ void DebuggerParser::executeDump()
|
||||||
dump(commandResult, args[0], args[1]);
|
dump(commandResult, args[0], args[1]);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ostringstream file;
|
if((args[2] & 0x07) == 0)
|
||||||
file << debugger.myOSystem.userDir() << cartName() << "_dbg_";
|
|
||||||
if(execDepth > 0)
|
|
||||||
{
|
{
|
||||||
file << execPrefix;
|
commandResult << red("dump flags must be 1..7");
|
||||||
}
|
|
||||||
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);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if((args[2] & 0x07) != 0)
|
if(argCount == 4 && argStrings[3] != "?")
|
||||||
commandResult << "dumped ";
|
{
|
||||||
|
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 ";
|
||||||
|
|
||||||
|
stringstream out;
|
||||||
if((args[2] & 0x01) != 0)
|
if((args[2] & 0x01) != 0)
|
||||||
{
|
{
|
||||||
// dump memory
|
// dump memory
|
||||||
dump(ofs, args[0], args[1]);
|
dump(out, args[0], args[1]);
|
||||||
commandResult << "bytes from $" << hex << args[0] << " to $" << hex << args[1];
|
commandResult << "bytes from $" << hex << args[0] << " to $" << hex << args[1];
|
||||||
if((args[2] & 0x06) != 0)
|
if((args[2] & 0x06) != 0)
|
||||||
commandResult << ", ";
|
commandResult << ", ";
|
||||||
|
@ -1177,8 +1194,8 @@ void DebuggerParser::executeDump()
|
||||||
{
|
{
|
||||||
// dump CPU state
|
// dump CPU state
|
||||||
CpuDebug& cpu = debugger.cpuDebug();
|
CpuDebug& cpu = debugger.cpuDebug();
|
||||||
ofs << " <PC>PC SP A X Y - - N V B D I Z C -\n";
|
out << " <PC>PC SP A X Y - - N V B D I Z C -\n";
|
||||||
ofs << "XC: "
|
out << "XC: "
|
||||||
<< Base::toString(cpu.pc() & 0xff) << " " // PC lsb
|
<< Base::toString(cpu.pc() & 0xff) << " " // PC lsb
|
||||||
<< Base::toString(cpu.pc() >> 8) << " " // PC msb
|
<< Base::toString(cpu.pc() >> 8) << " " // PC msb
|
||||||
<< Base::toString(cpu.sp()) << " " // SP
|
<< Base::toString(cpu.sp()) << " " // SP
|
||||||
|
@ -1203,8 +1220,8 @@ void DebuggerParser::executeDump()
|
||||||
if((args[2] & 0x04) != 0)
|
if((args[2] & 0x04) != 0)
|
||||||
{
|
{
|
||||||
// dump SWCHx/INPTx state
|
// dump SWCHx/INPTx state
|
||||||
ofs << " SWA - SWB - IT - - - I0 I1 I2 I3 I4 I5 - -\n";
|
out << " SWA - SWB - IT - - - I0 I1 I2 I3 I4 I5 - -\n";
|
||||||
ofs << "XS: "
|
out << "XS: "
|
||||||
<< Base::toString(debugger.peek(0x280)) << " " // SWCHA
|
<< Base::toString(debugger.peek(0x280)) << " " // SWCHA
|
||||||
<< Base::toString(0) << " " // unused
|
<< Base::toString(0) << " " // unused
|
||||||
<< Base::toString(debugger.peek(0x282)) << " " // SWCHB
|
<< Base::toString(debugger.peek(0x282)) << " " // SWCHB
|
||||||
|
@ -1224,8 +1241,37 @@ void DebuggerParser::executeDump()
|
||||||
<< endl;
|
<< endl;
|
||||||
commandResult << "switches and fire buttons";
|
commandResult << "switches and fire buttons";
|
||||||
}
|
}
|
||||||
if((args[2] & 0x07) != 0)
|
|
||||||
commandResult << " to file " << node.getShortPath();
|
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;
|
||||||
|
BrowserDialog::show(dlg, "Save Dump as", path.str(),
|
||||||
|
BrowserDialog::Mode::FileSave,
|
||||||
|
[this, dlg, outStr, resultStr]
|
||||||
|
(bool OK, const FilesystemNode& node)
|
||||||
|
{
|
||||||
|
if(OK)
|
||||||
|
{
|
||||||
|
stringstream localOut(outStr);
|
||||||
|
ostringstream localResult(resultStr, std::ios_base::app);
|
||||||
|
|
||||||
|
saveDump(node, localOut, localResult);
|
||||||
|
dlg->prompt().print(localResult.str() + '\n');
|
||||||
|
}
|
||||||
|
dlg->prompt().printPrompt();
|
||||||
|
});
|
||||||
|
// avoid printing a new prompt
|
||||||
|
commandResult.str("_NO_PROMPT");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
saveDump(FilesystemNode(path.str()), out, commandResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1846,9 +1892,19 @@ void DebuggerParser::executeSave()
|
||||||
{
|
{
|
||||||
if(argCount && argStrings[0] == "?")
|
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, dlg](bool OK, const FilesystemNode& node)
|
||||||
|
{
|
||||||
|
if(OK)
|
||||||
|
dlg->prompt().print(saveScriptFile(node.getPath()) + '\n');
|
||||||
|
dlg->prompt().printPrompt();
|
||||||
|
});
|
||||||
// avoid printing a new prompt
|
// avoid printing a new prompt
|
||||||
commandResult << "_EXIT_DEBUGGER";
|
commandResult.str("_NO_PROMPT");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
commandResult << saveScriptFile(argStrings[0]);
|
commandResult << saveScriptFile(argStrings[0]);
|
||||||
|
@ -1860,12 +1916,22 @@ void DebuggerParser::executeSaveAccess()
|
||||||
{
|
{
|
||||||
if(argCount && argStrings[0] == "?")
|
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, dlg](bool OK, const FilesystemNode& node)
|
||||||
|
{
|
||||||
|
if(OK)
|
||||||
|
dlg->prompt().print(debugger.cartDebug().saveAccessFile(node.getPath()) + '\n');
|
||||||
|
dlg->prompt().printPrompt();
|
||||||
|
});
|
||||||
// avoid printing a new prompt
|
// avoid printing a new prompt
|
||||||
commandResult << "_EXIT_DEBUGGER";
|
commandResult.str("_NO_PROMPT");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
commandResult << debugger.cartDebug().saveAccessFile(argCount ? argStrings[0] : EmptyString);
|
commandResult << debugger.cartDebug().saveAccessFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1881,12 +1947,22 @@ void DebuggerParser::executeSavedisassembly()
|
||||||
{
|
{
|
||||||
if(argCount && argStrings[0] == "?")
|
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, dlg](bool OK, const FilesystemNode& node)
|
||||||
|
{
|
||||||
|
if(OK)
|
||||||
|
dlg->prompt().print(debugger.cartDebug().saveDisassembly(node.getPath()) + '\n');
|
||||||
|
dlg->prompt().printPrompt();
|
||||||
|
});
|
||||||
// avoid printing a new prompt
|
// avoid printing a new prompt
|
||||||
commandResult << "_EXIT_DEBUGGER";
|
commandResult.str("_NO_PROMPT");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
commandResult << debugger.cartDebug().saveDisassembly(argCount ? argStrings[0] : EmptyString);
|
commandResult << debugger.cartDebug().saveDisassembly();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1895,12 +1971,22 @@ void DebuggerParser::executeSaverom()
|
||||||
{
|
{
|
||||||
if(argCount && argStrings[0] == "?")
|
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, dlg](bool OK, const FilesystemNode& node)
|
||||||
|
{
|
||||||
|
if(OK)
|
||||||
|
dlg->prompt().print(debugger.cartDebug().saveRom(node.getPath()) + '\n');
|
||||||
|
dlg->prompt().printPrompt();
|
||||||
|
});
|
||||||
// avoid printing a new prompt
|
// avoid printing a new prompt
|
||||||
commandResult << "_EXIT_DEBUGGER";
|
commandResult.str("_NO_PROMPT");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
commandResult << debugger.cartDebug().saveRom(argCount ? argStrings[0] : EmptyString);
|
commandResult << debugger.cartDebug().saveRom();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1913,22 +1999,30 @@ void DebuggerParser::executeSaveses()
|
||||||
|
|
||||||
if(argCount && argStrings[0] == "?")
|
if(argCount && argStrings[0] == "?")
|
||||||
{
|
{
|
||||||
debugger.myDialog->showBrowser(DebuggerDialog::svSession, filename.str());
|
DebuggerDialog* dlg = debugger.myDialog;
|
||||||
commandResult << "_EXIT_DEBUGGER";
|
|
||||||
|
BrowserDialog::show(dlg, "Save Session as",
|
||||||
|
dlg->instance().userDir().getPath() + filename.str(),
|
||||||
|
BrowserDialog::Mode::FileSave,
|
||||||
|
[this, dlg](bool OK, const FilesystemNode& node)
|
||||||
|
{
|
||||||
|
if(OK)
|
||||||
|
dlg->prompt().print(debugger.prompt().saveBuffer(node) + '\n');
|
||||||
|
dlg->prompt().printPrompt();
|
||||||
|
});
|
||||||
|
// avoid printing a new prompt
|
||||||
|
commandResult.str("_NO_PROMPT");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ostringstream path;
|
ostringstream path;
|
||||||
|
|
||||||
if(argCount)
|
if(argCount)
|
||||||
path << argStrings[0];
|
path << argStrings[0];
|
||||||
else
|
else
|
||||||
path << debugger.myOSystem.userDir() << filename.str();
|
path << debugger.myOSystem.userDir() << filename.str();
|
||||||
FilesystemNode file(path.str());
|
|
||||||
|
|
||||||
if(debugger.prompt().saveBuffer(file))
|
commandResult << debugger.prompt().saveBuffer(FilesystemNode(path.str()));
|
||||||
commandResult << "saved " + file.getShortPath() + " OK";
|
|
||||||
else
|
|
||||||
commandResult << "unable to save session";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2667,15 +2761,16 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
|
||||||
|
|
||||||
{
|
{
|
||||||
"dump",
|
"dump",
|
||||||
"Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs]",
|
"Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs] [?]",
|
||||||
"Example:\n"
|
"Example:\n"
|
||||||
" dump f000 - dumps 128 bytes from f000\n"
|
" dump f000 - dumps 128 bytes from f000\n"
|
||||||
" dump f000 f0ff - dumps all bytes from f000 to f0ff\n"
|
" dump f000 f0ff - dumps all bytes from f000 to f0ff\n"
|
||||||
" dump f000 f0ff 7 - 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,
|
true,
|
||||||
false,
|
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)
|
std::mem_fn(&DebuggerParser::executeDump)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3095,7 +3190,7 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
|
||||||
|
|
||||||
{
|
{
|
||||||
"save",
|
"save",
|
||||||
"Save breaks, watches, traps and functions to file xx",
|
"Save breaks, watches, traps and functions to file <xx or ?>",
|
||||||
"Example: save commands.script, save ?\n"
|
"Example: save commands.script, save ?\n"
|
||||||
"NOTE: saves to user dir by default",
|
"NOTE: saves to user dir by default",
|
||||||
true,
|
true,
|
||||||
|
@ -3106,12 +3201,12 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
|
||||||
|
|
||||||
{
|
{
|
||||||
"saveaccess",
|
"saveaccess",
|
||||||
"Save the access counters to CSV file",
|
"Save the access counters to CSV file [?]",
|
||||||
"Example: saveaccess, saveaccess ?\n"
|
"Example: saveaccess, saveaccess ?\n"
|
||||||
"NOTE: saves to user dir by default",
|
"NOTE: saves to user dir by default",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
|
{ Parameters::ARG_LABEL, Parameters::ARG_END_ARGS },
|
||||||
std::mem_fn(&DebuggerParser::executeSaveAccess)
|
std::mem_fn(&DebuggerParser::executeSaveAccess)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3127,34 +3222,34 @@ std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
|
||||||
|
|
||||||
{
|
{
|
||||||
"savedis",
|
"savedis",
|
||||||
"Save Distella disassembly",
|
"Save Distella disassembly to file [?]",
|
||||||
"Example: savedis, savedis ?\n"
|
"Example: savedis, savedis ?\n"
|
||||||
"NOTE: saves to user dir by default",
|
"NOTE: saves to user dir by default",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
|
{ Parameters::ARG_LABEL, Parameters::ARG_END_ARGS },
|
||||||
std::mem_fn(&DebuggerParser::executeSavedisassembly)
|
std::mem_fn(&DebuggerParser::executeSavedisassembly)
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"saverom",
|
"saverom",
|
||||||
"Save (possibly patched) ROM",
|
"Save (possibly patched) ROM to file [?]",
|
||||||
"Example: saverom, saverom ?\n"
|
"Example: saverom, saverom ?\n"
|
||||||
"NOTE: saves to user dir by default",
|
"NOTE: saves to user dir by default",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
|
{ Parameters::ARG_LABEL, Parameters::ARG_END_ARGS },
|
||||||
std::mem_fn(&DebuggerParser::executeSaverom)
|
std::mem_fn(&DebuggerParser::executeSaverom)
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"saveses",
|
"saveses",
|
||||||
"Save console session",
|
"Save console session to file [?]",
|
||||||
"Example: saveses, saveses ?\n"
|
"Example: saveses, saveses ?\n"
|
||||||
"NOTE: saves to user dir by default",
|
"NOTE: saves to user dir by default",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
{ Parameters::ARG_FILE, Parameters::ARG_END_ARGS },
|
{ Parameters::ARG_LABEL, Parameters::ARG_END_ARGS },
|
||||||
std::mem_fn(&DebuggerParser::executeSaveses)
|
std::mem_fn(&DebuggerParser::executeSaveses)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ class DebuggerParser
|
||||||
bool validateArgs(int cmd);
|
bool validateArgs(int cmd);
|
||||||
string eval();
|
string eval();
|
||||||
string saveScriptFile(string file);
|
string saveScriptFile(string file);
|
||||||
|
void saveDump(const FilesystemNode& node, const stringstream& out,
|
||||||
|
ostringstream& result);
|
||||||
const string& cartName() const;
|
const string& cartName() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -400,66 +400,6 @@ void DebuggerDialog::createFont()
|
||||||
tooltip().setFont(*myNFont);
|
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)
|
void DebuggerDialog::showFatalMessage(const string& msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,13 +55,6 @@ class DebuggerDialog : public Dialog
|
||||||
kMediumFontMinW = 1160, kMediumFontMinH = 770,
|
kMediumFontMinW = 1160, kMediumFontMinH = 770,
|
||||||
kLargeFontMinW = 1160, kLargeFontMinH = 870
|
kLargeFontMinW = 1160, kLargeFontMinH = 870
|
||||||
};
|
};
|
||||||
enum BrowserType {
|
|
||||||
svAccess, // saveaccess
|
|
||||||
svDis, // savedis
|
|
||||||
svRom, // saverom
|
|
||||||
svScript, // save
|
|
||||||
svSession // saveses
|
|
||||||
};
|
|
||||||
|
|
||||||
DebuggerDialog(OSystem& osystem, DialogContainer& parent,
|
DebuggerDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
int x, int y, int w, int h);
|
int x, int y, int w, int h);
|
||||||
|
@ -82,7 +75,6 @@ class DebuggerDialog : public Dialog
|
||||||
|
|
||||||
void showFatalMessage(const string& msg);
|
void showFatalMessage(const string& msg);
|
||||||
void saveConfig() override;
|
void saveConfig() override;
|
||||||
void showBrowser(BrowserType type, const string& defaultName);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setPosition() override { positionAt(0); }
|
void setPosition() override { positionAt(0); }
|
||||||
|
@ -127,9 +119,6 @@ class DebuggerDialog : public Dialog
|
||||||
kDDOptionsCmd = 'DDop'
|
kDDOptionsCmd = 'DDop'
|
||||||
};
|
};
|
||||||
|
|
||||||
void runCommand(const FilesystemNode& node,
|
|
||||||
const string& command = EmptyString);
|
|
||||||
|
|
||||||
TabWidget *myTab{nullptr}, *myRomTab{nullptr};
|
TabWidget *myTab{nullptr}, *myRomTab{nullptr};
|
||||||
|
|
||||||
PromptWidget* myPrompt{nullptr};
|
PromptWidget* myPrompt{nullptr};
|
||||||
|
|
|
@ -191,6 +191,8 @@ bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
_exitedEarly = true;
|
_exitedEarly = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if(result == "_NO_PROMPT")
|
||||||
|
return true;
|
||||||
else if(result != "")
|
else if(result != "")
|
||||||
print(result + "\n");
|
print(result + "\n");
|
||||||
}
|
}
|
||||||
|
@ -968,7 +970,7 @@ void PromptWidget::scrollToCurrent()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool PromptWidget::saveBuffer(const FilesystemNode& file)
|
string PromptWidget::saveBuffer(const FilesystemNode& file)
|
||||||
{
|
{
|
||||||
stringstream out;
|
stringstream out;
|
||||||
for(int start = 0; start < _promptStartPos; start += _lineWidth)
|
for(int start = 0; start < _promptStartPos; start += _lineWidth)
|
||||||
|
@ -988,8 +990,13 @@ bool PromptWidget::saveBuffer(const FilesystemNode& file)
|
||||||
out << endl;
|
out << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
try { return file.write(out) > 0; }
|
try {
|
||||||
catch(...) { return false; }
|
if(file.write(out) > 0)
|
||||||
|
return "saved " + file.getShortPath() + " OK";
|
||||||
|
}
|
||||||
|
catch(...) { }
|
||||||
|
|
||||||
|
return "unable to save session";
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -46,7 +46,7 @@ class PromptWidget : public Widget, public CommandSender
|
||||||
ATTRIBUTE_FMT_PRINTF int vprintf(const char* format, va_list argptr);
|
ATTRIBUTE_FMT_PRINTF int vprintf(const char* format, va_list argptr);
|
||||||
void print(const string& str);
|
void print(const string& str);
|
||||||
void printPrompt();
|
void printPrompt();
|
||||||
bool saveBuffer(const FilesystemNode& file);
|
string saveBuffer(const FilesystemNode& file);
|
||||||
|
|
||||||
// Clear screen and erase all history
|
// Clear screen and erase all history
|
||||||
void clearScreen();
|
void clearScreen();
|
||||||
|
|
|
@ -58,19 +58,24 @@ RomListSettings::RomListSettings(GuiObject* boss, const GUI::Font& font)
|
||||||
// Settings for Distella
|
// Settings for Distella
|
||||||
xpos += 4; ypos += buttonHeight + 8;
|
xpos += 4; ypos += buttonHeight + 8;
|
||||||
myShowTentative = new CheckboxWidget(this, font, xpos, ypos,
|
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);
|
wid.push_back(myShowTentative);
|
||||||
ypos += buttonHeight + 4;
|
ypos += buttonHeight + 4;
|
||||||
myShowAddresses = new CheckboxWidget(this, font, xpos, ypos,
|
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);
|
wid.push_back(myShowAddresses);
|
||||||
ypos += buttonHeight + 4;
|
ypos += buttonHeight + 4;
|
||||||
myShowGFXBinary = new CheckboxWidget(this, font, xpos, ypos,
|
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);
|
wid.push_back(myShowGFXBinary);
|
||||||
ypos += buttonHeight + 4;
|
ypos += buttonHeight + 4;
|
||||||
myUseRelocation = new CheckboxWidget(this, font, xpos, ypos,
|
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);
|
wid.push_back(myUseRelocation);
|
||||||
|
|
||||||
// Set real dimensions
|
// Set real dimensions
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "FSNode.hxx"
|
#include "FSNode.hxx"
|
||||||
#include "GuiObject.hxx"
|
#include "GuiObject.hxx"
|
||||||
#include "OSystem.hxx"
|
#include "OSystem.hxx"
|
||||||
|
#include "FrameBuffer.hxx"
|
||||||
#include "EditTextWidget.hxx"
|
#include "EditTextWidget.hxx"
|
||||||
#include "FileListWidget.hxx"
|
#include "FileListWidget.hxx"
|
||||||
#include "Widget.hxx"
|
#include "Widget.hxx"
|
||||||
|
@ -131,6 +132,17 @@ void BrowserDialog::show(GuiObject* parent, const GUI::Font& font,
|
||||||
ourBrowser->show(startpath, mode, command, namefilter);
|
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,
|
void BrowserDialog::show(const string& startpath,
|
||||||
BrowserDialog::Mode mode,
|
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
|
// Send a signal to the calling class that a selection has been made
|
||||||
if(_mode != Mode::Directories)
|
if(_mode != Mode::Directories)
|
||||||
{
|
{
|
||||||
// TODO: check if affected by '-baseDir'and 'basedirinapp' params
|
|
||||||
bool savePath = _savePathBox->getState();
|
bool savePath = _savePathBox->getState();
|
||||||
|
|
||||||
instance().settings().setValue("saveuserdir", savePath);
|
instance().settings().setValue("saveuserdir", savePath);
|
||||||
|
|
|
@ -69,6 +69,23 @@ class BrowserDialog : public Dialog
|
||||||
const FilesystemNode::NameFilter& namefilter = {
|
const FilesystemNode::NameFilter& namefilter = {
|
||||||
[](const FilesystemNode&) { return true; }});
|
[](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:
|
private:
|
||||||
/** Place the browser window onscreen, using the given attributes */
|
/** Place the browser window onscreen, using the given attributes */
|
||||||
void show(const string& startpath,
|
void show(const string& startpath,
|
||||||
|
|
|
@ -316,8 +316,7 @@ bool Widget::isWidgetInChain(Widget* w, Widget* find)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool Widget::isWidgetInChain(const WidgetArray& list, Widget* find)
|
bool Widget::isWidgetInChain(const WidgetArray& list, Widget* find)
|
||||||
{
|
{
|
||||||
return std::any_of(list.cbegin(), list.cend(),
|
return BSPF::contains(list, find);
|
||||||
[&](Widget* w) { return w == find; });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
Loading…
Reference in New Issue