mirror of https://github.com/stella-emu/stella.git
conditional savestates in debugger added
This commit is contained in:
parent
b098f29e9d
commit
01d3a29f66
|
@ -65,6 +65,7 @@ class Debugger : public DialogContainer
|
|||
// directly, and not touch the instance variables
|
||||
friend class DebuggerParser;
|
||||
friend class EventHandler;
|
||||
friend class M6502;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -652,6 +652,10 @@ string DebuggerParser::saveScriptFile(string file)
|
|||
for(const auto& cond : conds)
|
||||
out << "breakif {" << cond << "}" << endl;
|
||||
|
||||
conds = debugger.m6502().getCondSaveStateNames();
|
||||
for(const auto& cond : conds)
|
||||
out << "savestateif {" << cond << "}" << endl;
|
||||
|
||||
StringList names = debugger.m6502().getCondTrapNames();
|
||||
for(uInt32 i = 0; i < myTraps.size(); ++i)
|
||||
{
|
||||
|
@ -807,6 +811,14 @@ void DebuggerParser::executeClearconfig()
|
|||
commandResult << debugger.cartDebug().clearConfig();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "clearbreaks"
|
||||
void DebuggerParser::executeClearsavestateifs()
|
||||
{
|
||||
debugger.m6502().clearCondSaveStates();
|
||||
commandResult << "all savestate points cleared";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "cleartraps"
|
||||
void DebuggerParser::executeCleartraps()
|
||||
|
@ -932,6 +944,16 @@ void DebuggerParser::executeDelfunction()
|
|||
commandResult << "function " << argStrings[0] << " built-in or not found";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "delsavestateif"
|
||||
void DebuggerParser::executeDelsavestateif()
|
||||
{
|
||||
if(debugger.m6502().delCondSaveState(args[0]))
|
||||
commandResult << "removed savestateif " << Base::toString(args[0]);
|
||||
else
|
||||
commandResult << red("no such savestateif");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "deltrap"
|
||||
void DebuggerParser::executeDeltrap()
|
||||
|
@ -1212,6 +1234,31 @@ void DebuggerParser::executeListfunctions()
|
|||
commandResult << "no user-defined functions";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "listsavestateifs"
|
||||
void DebuggerParser::executeListsavestateifs()
|
||||
{
|
||||
ostringstream buf;
|
||||
int count = 0;
|
||||
|
||||
StringList conds = debugger.m6502().getCondSaveStateNames();
|
||||
if(conds.size() > 0)
|
||||
{
|
||||
if(count)
|
||||
commandResult << endl;
|
||||
commandResult << "savestateif:" << endl;
|
||||
for(uInt32 i = 0; i < conds.size(); i++)
|
||||
{
|
||||
commandResult << Base::toString(i) << ": " << conds[i];
|
||||
if(i != (conds.size() - 1)) commandResult << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if(commandResult.str() == "")
|
||||
commandResult << "no savestateifs defined";
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "listtraps"
|
||||
void DebuggerParser::executeListtraps()
|
||||
|
@ -1542,6 +1589,21 @@ void DebuggerParser::executeSavestate()
|
|||
commandResult << red("invalid slot (must be 0-9)");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "savestateif"
|
||||
void DebuggerParser::executeSavestateif()
|
||||
{
|
||||
int res = YaccParser::parse(argStrings[0].c_str());
|
||||
if(res == 0)
|
||||
{
|
||||
uInt32 ret = debugger.m6502().addCondSaveState(
|
||||
YaccParser::getResult(), argStrings[0]);
|
||||
commandResult << "Added savestateif " << Base::toString(ret);
|
||||
}
|
||||
else
|
||||
commandResult << red("invalid expression");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "scanline"
|
||||
void DebuggerParser::executeScanline()
|
||||
|
@ -1981,6 +2043,16 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
|||
std::mem_fn(&DebuggerParser::executeClearbreaks)
|
||||
},
|
||||
|
||||
{
|
||||
"clearsavestateifs",
|
||||
"Clear all savestate points",
|
||||
"Example: clearsavestateifss (no parameters)",
|
||||
false,
|
||||
true,
|
||||
{ kARG_END_ARGS },
|
||||
std::mem_fn(&DebuggerParser::executeClearsavestateifs)
|
||||
},
|
||||
|
||||
{
|
||||
"clearconfig",
|
||||
"Clear Distella config directives [bank xx]",
|
||||
|
@ -2101,6 +2173,16 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
|||
std::mem_fn(&DebuggerParser::executeDelfunction)
|
||||
},
|
||||
|
||||
{
|
||||
"delsavestateif",
|
||||
"Delete conditional savestate point <xx>",
|
||||
"Example: delsavestateif 0",
|
||||
true,
|
||||
false,
|
||||
{ kARG_WORD, kARG_END_ARGS },
|
||||
std::mem_fn(&DebuggerParser::executeDelsavestateif)
|
||||
},
|
||||
|
||||
{
|
||||
"deltrap",
|
||||
"Delete trap <xx>",
|
||||
|
@ -2245,6 +2327,16 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
|||
std::mem_fn(&DebuggerParser::executeListfunctions)
|
||||
},
|
||||
|
||||
{
|
||||
"listsavestateifs",
|
||||
"List savestate points",
|
||||
"Example: listsavestateifs (no parameters)",
|
||||
false,
|
||||
false,
|
||||
{ kARG_END_ARGS },
|
||||
std::mem_fn(&DebuggerParser::executeListsavestateifs)
|
||||
},
|
||||
|
||||
{
|
||||
"listtraps",
|
||||
"List traps",
|
||||
|
@ -2502,6 +2594,16 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
|||
std::mem_fn(&DebuggerParser::executeSavestate)
|
||||
},
|
||||
|
||||
{
|
||||
"savestateif",
|
||||
"Create savestate on <condition>",
|
||||
"Condition can include multiple items, see documentation\nExample: savestateif pc==f000",
|
||||
true,
|
||||
false,
|
||||
{ kARG_WORD, kARG_END_ARGS },
|
||||
std::mem_fn(&DebuggerParser::executeSavestateif)
|
||||
},
|
||||
|
||||
{
|
||||
"scanline",
|
||||
"Advance emulation by <xx> scanlines (default=1)",
|
||||
|
|
|
@ -66,7 +66,7 @@ class DebuggerParser
|
|||
string saveScriptFile(string file);
|
||||
|
||||
private:
|
||||
enum { kNumCommands = 77 };
|
||||
enum { kNumCommands = 81 };
|
||||
|
||||
// Constants for argument processing
|
||||
enum {
|
||||
|
@ -142,6 +142,7 @@ class DebuggerParser
|
|||
void executeCheat();
|
||||
void executeClearbreaks();
|
||||
void executeClearconfig();
|
||||
void executeClearsavestateifs();
|
||||
void executeCleartraps();
|
||||
void executeClearwatches();
|
||||
void executeCls();
|
||||
|
@ -153,6 +154,7 @@ class DebuggerParser
|
|||
void executeDefine();
|
||||
void executeDelbreakif();
|
||||
void executeDelfunction();
|
||||
void executeDelsavestateif();
|
||||
void executeDeltrap();
|
||||
void executeDelwatch();
|
||||
void executeDisasm();
|
||||
|
@ -167,6 +169,7 @@ class DebuggerParser
|
|||
void executeListbreaks();
|
||||
void executeListconfig();
|
||||
void executeListfunctions();
|
||||
void executeListsavestateifs();
|
||||
void executeListtraps();
|
||||
void executeLoadconfig();
|
||||
void executeLoadstate();
|
||||
|
@ -192,6 +195,7 @@ class DebuggerParser
|
|||
void executeSaveses();
|
||||
void executeSavesnap();
|
||||
void executeSavestate();
|
||||
void executeSavestateif();
|
||||
void executeScanline();
|
||||
void executeStep();
|
||||
void executeTia();
|
||||
|
|
|
@ -219,10 +219,16 @@ bool M6502::execute(uInt32 number)
|
|||
int cond = evalCondBreaks();
|
||||
if(cond > -1)
|
||||
{
|
||||
string buf = "CBP: " + myBreakCondNames[cond];
|
||||
string buf = "CBP: " + myCondBreakNames[cond];
|
||||
if(myDebugger && myDebugger->start(buf))
|
||||
return true;
|
||||
}
|
||||
|
||||
cond = evalCondSaveStates();
|
||||
if(cond > -1)
|
||||
{
|
||||
myDebugger->saveOldState("conditional savestate");
|
||||
}
|
||||
#endif // DEBUGGER_SUPPORT
|
||||
|
||||
uInt16 operandAddress = 0, intermediateAddress = 0;
|
||||
|
@ -424,18 +430,18 @@ void M6502::attach(Debugger& debugger)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 M6502::addCondBreak(Expression* e, const string& name)
|
||||
{
|
||||
myBreakConds.emplace_back(e);
|
||||
myBreakCondNames.push_back(name);
|
||||
return uInt32(myBreakConds.size() - 1);
|
||||
myCondBreaks.emplace_back(e);
|
||||
myCondBreakNames.push_back(name);
|
||||
return uInt32(myCondBreaks.size() - 1);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6502::delCondBreak(uInt32 brk)
|
||||
bool M6502::delCondBreak(uInt32 idx)
|
||||
{
|
||||
if(brk < myBreakConds.size())
|
||||
if(idx < myCondBreaks.size())
|
||||
{
|
||||
Vec::removeAt(myBreakConds, brk);
|
||||
Vec::removeAt(myBreakCondNames, brk);
|
||||
Vec::removeAt(myCondBreaks, idx);
|
||||
Vec::removeAt(myCondBreakNames, idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -444,14 +450,47 @@ bool M6502::delCondBreak(uInt32 brk)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6502::clearCondBreaks()
|
||||
{
|
||||
myBreakConds.clear();
|
||||
myBreakCondNames.clear();
|
||||
myCondBreaks.clear();
|
||||
myCondBreakNames.clear();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const StringList& M6502::getCondBreakNames() const
|
||||
{
|
||||
return myBreakCondNames;
|
||||
return myCondBreakNames;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 M6502::addCondSaveState(Expression* e, const string& name)
|
||||
{
|
||||
myCondSaveStates.emplace_back(e);
|
||||
myCondSaveStateNames.push_back(name);
|
||||
return uInt32(myCondSaveStates.size() - 1);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool M6502::delCondSaveState(uInt32 idx)
|
||||
{
|
||||
if(idx < myCondSaveStates.size())
|
||||
{
|
||||
Vec::removeAt(myCondSaveStates, idx);
|
||||
Vec::removeAt(myCondSaveStateNames, idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6502::clearCondSaveStates()
|
||||
{
|
||||
myCondSaveStates.clear();
|
||||
myCondSaveStateNames.clear();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const StringList& M6502::getCondSaveStateNames() const
|
||||
{
|
||||
return myCondSaveStateNames;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -222,19 +222,21 @@ class M6502 : public Serializable
|
|||
void attach(Debugger& debugger);
|
||||
|
||||
PackedBitArray& breakPoints() { return myBreakPoints; }
|
||||
//PackedBitArray& readTraps() { return myReadTraps; }
|
||||
//PackedBitArray& writeTraps() { return myWriteTraps; }
|
||||
//PackedBitArray& readTrapIfs() { return myReadTrapIfs; }
|
||||
//PackedBitArray& writeTrapIfs() { return myWriteTrapIfs; }
|
||||
TrapArray& readTraps() { return myReadTraps; }
|
||||
TrapArray& writeTraps() { return myWriteTraps; }
|
||||
|
||||
// methods for 'breakif' handling
|
||||
uInt32 addCondBreak(Expression* e, const string& name);
|
||||
bool delCondBreak(uInt32 brk);
|
||||
bool delCondBreak(uInt32 idx);
|
||||
void clearCondBreaks();
|
||||
const StringList& getCondBreakNames() const;
|
||||
|
||||
// methods for 'savestateif' handling
|
||||
uInt32 addCondSaveState(Expression* e, const string& name);
|
||||
bool delCondSaveState(uInt32 idx);
|
||||
void clearCondSaveStates();
|
||||
const StringList& getCondSaveStateNames() const;
|
||||
|
||||
// methods for 'trapif' handling
|
||||
uInt32 addCondTrap(Expression* e, const string& name);
|
||||
bool delCondTrap(uInt32 brk);
|
||||
|
@ -380,14 +382,29 @@ class M6502 : public Serializable
|
|||
bool myHaltRequested;
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
enum CondAction
|
||||
{
|
||||
breakAction,
|
||||
saveStateAction
|
||||
};
|
||||
|
||||
Int32 evalCondBreaks() {
|
||||
for(uInt32 i = 0; i < myBreakConds.size(); i++)
|
||||
if(myBreakConds[i]->evaluate())
|
||||
for(uInt32 i = 0; i < myCondBreaks.size(); i++)
|
||||
if(myCondBreaks[i]->evaluate())
|
||||
return i;
|
||||
|
||||
return -1; // no break hit
|
||||
}
|
||||
|
||||
Int32 evalCondSaveStates()
|
||||
{
|
||||
for(uInt32 i = 0; i < myCondSaveStates.size(); i++)
|
||||
if(myCondSaveStates[i]->evaluate())
|
||||
return i;
|
||||
|
||||
return -1; // no save state point hit
|
||||
}
|
||||
|
||||
Int32 evalCondTraps()
|
||||
{
|
||||
for(uInt32 i = 0; i < myTrapConds.size(); i++)
|
||||
|
@ -413,10 +430,13 @@ class M6502 : public Serializable
|
|||
};
|
||||
HitTrapInfo myHitTrapInfo;
|
||||
|
||||
vector<unique_ptr<Expression>> myBreakConds;
|
||||
StringList myBreakCondNames;
|
||||
vector<unique_ptr<Expression>> myCondBreaks;
|
||||
StringList myCondBreakNames;
|
||||
vector<unique_ptr<Expression>> myCondSaveStates;
|
||||
StringList myCondSaveStateNames;
|
||||
vector<unique_ptr<Expression>> myTrapConds;
|
||||
StringList myTrapCondNames;
|
||||
|
||||
#endif // DEBUGGER_SUPPORT
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue