mirror of https://github.com/stella-emu/stella.git
trapifs implemented (and fixed mirrors)
wrong port display for swapped ports fixed error due wrong argument number now with example display label display in status line added
This commit is contained in:
parent
07d2797c62
commit
3fddc03ff6
|
@ -603,6 +603,15 @@ bool Debugger::addFunction(const string& name, const string& definition,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool Debugger::isBuiltinFunction(const string& name)
|
||||||
|
{
|
||||||
|
for(int i = 0; builtin_functions[i][0] != 0; ++i)
|
||||||
|
if(name == builtin_functions[i][0])
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool Debugger::delFunction(const string& name)
|
bool Debugger::delFunction(const string& name)
|
||||||
{
|
{
|
||||||
|
@ -611,8 +620,7 @@ bool Debugger::delFunction(const string& name)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We never want to delete built-in functions
|
// We never want to delete built-in functions
|
||||||
for(int i = 0; builtin_functions[i][0] != 0; ++i)
|
if (isBuiltinFunction(name))
|
||||||
if(name == builtin_functions[i][0])
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myFunctions.erase(name);
|
myFunctions.erase(name);
|
||||||
|
|
|
@ -99,6 +99,7 @@ class Debugger : public DialogContainer
|
||||||
|
|
||||||
bool addFunction(const string& name, const string& def,
|
bool addFunction(const string& name, const string& def,
|
||||||
Expression* exp, bool builtin = false);
|
Expression* exp, bool builtin = false);
|
||||||
|
bool isBuiltinFunction(const string& name);
|
||||||
bool delFunction(const string& name);
|
bool delFunction(const string& name);
|
||||||
const Expression& getFunction(const string& name) const;
|
const Expression& getFunction(const string& name) const;
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,10 @@ string DebuggerParser::run(const string& command)
|
||||||
if(BSPF::equalsIgnoreCase(verb, commands[i].cmdString))
|
if(BSPF::equalsIgnoreCase(verb, commands[i].cmdString))
|
||||||
{
|
{
|
||||||
if(validateArgs(i))
|
if(validateArgs(i))
|
||||||
|
{
|
||||||
|
myCommand = i;
|
||||||
commands[i].executor(this);
|
commands[i].executor(this);
|
||||||
|
}
|
||||||
|
|
||||||
if(commands[i].refreshRequired)
|
if(commands[i].refreshRequired)
|
||||||
debugger.myBaseDialog->loadConfig();
|
debugger.myBaseDialog->loadConfig();
|
||||||
|
@ -151,6 +154,16 @@ string DebuggerParser::exec(const FilesystemNode& file)
|
||||||
return red("script file \'" + file.getShortPath() + "\' not found");
|
return red("script file \'" + file.getShortPath() + "\' not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void DebuggerParser::outputCommandError(const string& errorMsg, int command)
|
||||||
|
{
|
||||||
|
string example = commands[command].extendedDesc.substr(commands[command].extendedDesc.find("Example:"));
|
||||||
|
|
||||||
|
commandResult << red(errorMsg);
|
||||||
|
if(!example.empty())
|
||||||
|
commandResult << endl << example;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// Completion-related stuff:
|
// Completion-related stuff:
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -396,7 +409,8 @@ bool DebuggerParser::validateArgs(int cmd)
|
||||||
{
|
{
|
||||||
if(required)
|
if(required)
|
||||||
{
|
{
|
||||||
commandResult.str(red("missing required argument(s)"));
|
commandResult.str();
|
||||||
|
outputCommandError("missing required argument(s)", cmd);
|
||||||
return false; // needed args. didn't get 'em.
|
return false; // needed args. didn't get 'em.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -492,12 +506,14 @@ cerr << "curCount = " << curCount << endl
|
||||||
|
|
||||||
if(curCount < argRequiredCount)
|
if(curCount < argRequiredCount)
|
||||||
{
|
{
|
||||||
commandResult.str(red("missing required argument(s)"));
|
commandResult.str();
|
||||||
|
outputCommandError("missing required argument(s)", cmd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if(argCount > curCount)
|
else if(argCount > curCount)
|
||||||
{
|
{
|
||||||
commandResult.str(red("too many arguments"));
|
commandResult.str();
|
||||||
|
outputCommandError("too many arguments", cmd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,6 +558,39 @@ string DebuggerParser::eval()
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void DebuggerParser::listTraps(bool listCond)
|
||||||
|
{
|
||||||
|
StringList names = debugger.cpuDebug().m6502().getCondTrapNames();
|
||||||
|
|
||||||
|
commandResult << (listCond ? "trapifs:" : "traps:") << endl;
|
||||||
|
for(uInt32 i = 0; i < names.size(); i++)
|
||||||
|
{
|
||||||
|
bool hasCond = names[i] != "";
|
||||||
|
if(hasCond == listCond)
|
||||||
|
{
|
||||||
|
commandResult << Base::toString(i) << ": ";
|
||||||
|
if(myTraps[i]->read && myTraps[i]->write)
|
||||||
|
commandResult << "read|write";
|
||||||
|
else if(myTraps[i]->read)
|
||||||
|
commandResult << "read ";
|
||||||
|
else if(myTraps[i]->write)
|
||||||
|
commandResult << " write";
|
||||||
|
else
|
||||||
|
commandResult << "none";
|
||||||
|
|
||||||
|
if(hasCond)
|
||||||
|
commandResult << " " << names[i];
|
||||||
|
commandResult << " " << debugger.cartDebug().getLabel(myTraps[i]->begin, true, 4);
|
||||||
|
if(myTraps[i]->begin != myTraps[i]->end)
|
||||||
|
commandResult << " " << debugger.cartDebug().getLabel(myTraps[i]->end, true, 4);
|
||||||
|
commandResult << trapStatus(*myTraps[i]);
|
||||||
|
commandResult << " + mirrors";
|
||||||
|
if(i != (names.size() - 1)) commandResult << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string DebuggerParser::trapStatus(const Trap& trap)
|
string DebuggerParser::trapStatus(const Trap& trap)
|
||||||
{
|
{
|
||||||
|
@ -585,33 +634,41 @@ string DebuggerParser::saveScriptFile(string file)
|
||||||
|
|
||||||
FunctionDefMap funcs = debugger.getFunctionDefMap();
|
FunctionDefMap funcs = debugger.getFunctionDefMap();
|
||||||
for(const auto& f: funcs)
|
for(const auto& f: funcs)
|
||||||
out << "function " << f.first << " { " << f.second << " }" << endl;
|
if (!debugger.isBuiltinFunction(f.first))
|
||||||
|
out << "function " << f.first << " {" << f.second << "}" << endl;
|
||||||
|
|
||||||
for(const auto& w: myWatches)
|
for(const auto& w: myWatches)
|
||||||
out << "watch " << w << endl;
|
out << "watch " << w << endl;
|
||||||
|
|
||||||
for(uInt32 i = 0; i < 0x10000; ++i)
|
for(uInt32 i = 0; i < 0x10000; ++i)
|
||||||
if(debugger.breakPoint(i))
|
if(debugger.breakPoint(i))
|
||||||
out << "break #" << i << endl;
|
out << "break " << Base::toString(i) << endl;
|
||||||
|
|
||||||
// TODO: new trapif
|
|
||||||
for(uInt32 i = 0; i < 0x10000; ++i)
|
|
||||||
{
|
|
||||||
bool r = debugger.readTrap(i);
|
|
||||||
bool w = debugger.writeTrap(i);
|
|
||||||
|
|
||||||
if(r && w)
|
|
||||||
out << "trap #" << i << endl;
|
|
||||||
else if(r)
|
|
||||||
out << "trapread #" << i << endl;
|
|
||||||
else if(w)
|
|
||||||
out << "trapwrite #" << i << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringList conds = debugger.cpuDebug().m6502().getCondBreakNames();
|
StringList conds = debugger.cpuDebug().m6502().getCondBreakNames();
|
||||||
for(const auto& cond: conds)
|
for(const auto& cond : conds)
|
||||||
out << "breakif {" << cond << "}" << endl;
|
out << "breakif {" << cond << "}" << endl;
|
||||||
|
|
||||||
|
StringList names = debugger.cpuDebug().m6502().getCondTrapNames();
|
||||||
|
for(uInt32 i = 0; i < myTraps.size(); ++i)
|
||||||
|
{
|
||||||
|
bool read = myTraps[i]->read;
|
||||||
|
bool write = myTraps[i]->write;
|
||||||
|
bool hasCond = names[i] != "";
|
||||||
|
|
||||||
|
if(read && write)
|
||||||
|
out << "trap";
|
||||||
|
else if(read)
|
||||||
|
out << "trapread";
|
||||||
|
else if(write)
|
||||||
|
out << "trapwrite";
|
||||||
|
if(hasCond)
|
||||||
|
out << "if {" << names[i] << "}";
|
||||||
|
out << " " << Base::toString(myTraps[i]->begin);
|
||||||
|
if(myTraps[i]->begin != myTraps[i]->end)
|
||||||
|
out << " " << Base::toString(myTraps[i]->end);
|
||||||
|
out << endl;
|
||||||
|
}
|
||||||
|
|
||||||
return "saved " + node.getShortPath() + " OK";
|
return "saved " + node.getShortPath() + " OK";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +767,7 @@ void DebuggerParser::executeCheat()
|
||||||
#ifdef CHEATCODE_SUPPORT
|
#ifdef CHEATCODE_SUPPORT
|
||||||
if(argCount == 0)
|
if(argCount == 0)
|
||||||
{
|
{
|
||||||
commandResult << red("Missing cheat code");
|
outputCommandError("missing cheat code", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,7 +777,7 @@ void DebuggerParser::executeCheat()
|
||||||
if(debugger.myOSystem.cheat().add("DBG", cheat))
|
if(debugger.myOSystem.cheat().add("DBG", cheat))
|
||||||
commandResult << "Cheat code " << cheat << " enabled" << endl;
|
commandResult << "Cheat code " << cheat << " enabled" << endl;
|
||||||
else
|
else
|
||||||
commandResult << red("Invalid cheat code ") << cheat << endl;
|
commandResult << red("invalid cheat code ") << cheat << endl;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
commandResult << red("Cheat support not enabled\n");
|
commandResult << red("Cheat support not enabled\n");
|
||||||
|
@ -778,12 +835,12 @@ void DebuggerParser::executeCode()
|
||||||
{
|
{
|
||||||
if(argCount != 2)
|
if(argCount != 2)
|
||||||
{
|
{
|
||||||
commandResult << red("Specify start and end of range only");
|
outputCommandError("specify start and end of range only", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(args[1] < args[0])
|
else if(args[1] < args[0])
|
||||||
{
|
{
|
||||||
commandResult << red("Start address must be <= end address");
|
commandResult << red("start address must be <= end address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,12 +876,12 @@ void DebuggerParser::executeData()
|
||||||
{
|
{
|
||||||
if(argCount != 2)
|
if(argCount != 2)
|
||||||
{
|
{
|
||||||
commandResult << red("Specify start and end of range only");
|
outputCommandError("specify start and end of range only", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(args[1] < args[0])
|
else if(args[1] < args[0])
|
||||||
{
|
{
|
||||||
commandResult << red("Start address must be <= end address");
|
commandResult << red("start address must be <= end address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,7 +971,7 @@ void DebuggerParser::executeDisasm()
|
||||||
start = args[0];
|
start = args[0];
|
||||||
lines = args[1];
|
lines = args[1];
|
||||||
} else {
|
} else {
|
||||||
commandResult << "wrong number of arguments";
|
outputCommandError("wrong number of arguments", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,7 +1001,7 @@ void DebuggerParser::executeDump()
|
||||||
// Error checking
|
// Error checking
|
||||||
if(argCount > 1 && args[1] < args[0])
|
if(argCount > 1 && args[1] < args[0])
|
||||||
{
|
{
|
||||||
commandResult << red("Start address must be <= end address");
|
commandResult << red("start address must be <= end address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,7 +1011,7 @@ void DebuggerParser::executeDump()
|
||||||
dump(args[0], args[1]);
|
dump(args[0], args[1]);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
commandResult << "wrong number of arguments";
|
outputCommandError("wrong number of arguments", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1015,12 +1072,12 @@ void DebuggerParser::executeGfx()
|
||||||
{
|
{
|
||||||
if(argCount != 2)
|
if(argCount != 2)
|
||||||
{
|
{
|
||||||
commandResult << red("Specify start and end of range only");
|
outputCommandError("specify start and end of range only", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(args[1] < args[0])
|
else if(args[1] < args[0])
|
||||||
{
|
{
|
||||||
commandResult << red("Start address must be <= end address");
|
commandResult << red("start address must be <= end address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1100,23 +1157,18 @@ void DebuggerParser::executeListbreaks()
|
||||||
if(debugger.breakPoints().isSet(i))
|
if(debugger.breakPoints().isSet(i))
|
||||||
{
|
{
|
||||||
buf << debugger.cartDebug().getLabel(i, true, 4) << " ";
|
buf << debugger.cartDebug().getLabel(i, true, 4) << " ";
|
||||||
if(! (++count % 8) ) buf << "\n";
|
if(! (++count % 8) ) buf << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if(count)
|
if(count)
|
||||||
return ret;
|
commandResult << "breaks:" << endl << buf.str();
|
||||||
else
|
|
||||||
return "no breakpoints set";
|
|
||||||
*/
|
|
||||||
if(count)
|
|
||||||
commandResult << "breaks:\n" << buf.str();
|
|
||||||
|
|
||||||
StringList conds = debugger.cpuDebug().m6502().getCondBreakNames();
|
StringList conds = debugger.cpuDebug().m6502().getCondBreakNames();
|
||||||
if(conds.size() > 0)
|
if(conds.size() > 0)
|
||||||
{
|
{
|
||||||
commandResult << "\nbreakifs:\n";
|
if(count)
|
||||||
|
commandResult << endl;
|
||||||
|
commandResult << "breakifs:" << endl;
|
||||||
for(uInt32 i = 0; i < conds.size(); i++)
|
for(uInt32 i = 0; i < conds.size(); i++)
|
||||||
{
|
{
|
||||||
commandResult << Base::toString(i) << ": " << conds[i];
|
commandResult << Base::toString(i) << ": " << conds[i];
|
||||||
|
@ -1164,30 +1216,20 @@ void DebuggerParser::executeListtraps()
|
||||||
commandResult << "Internal error! Different trap sizes.";
|
commandResult << "Internal error! Different trap sizes.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (names.size() > 0)
|
if (names.size() > 0)
|
||||||
{
|
{
|
||||||
|
bool trapFound = false, trapifFound = false;
|
||||||
for(uInt32 i = 0; i < names.size(); i++)
|
for(uInt32 i = 0; i < names.size(); i++)
|
||||||
{
|
if(names[i] == "")
|
||||||
commandResult << Base::toString(i) << ": ";
|
trapFound = true;
|
||||||
|
|
||||||
if(myTraps[i]->read && myTraps[i]->write)
|
|
||||||
commandResult << "read|write";
|
|
||||||
else if(myTraps[i]->read)
|
|
||||||
commandResult << "read ";
|
|
||||||
else if(myTraps[i]->write)
|
|
||||||
commandResult << " write";
|
|
||||||
else
|
else
|
||||||
commandResult << "none";
|
trapifFound = true;
|
||||||
|
|
||||||
commandResult << " " << names[i];
|
if(trapFound)
|
||||||
commandResult << " " << Base::toString(myTraps[i]->begin);
|
listTraps(false);
|
||||||
if (myTraps[i]->begin != myTraps[i]->end)
|
if(trapifFound)
|
||||||
commandResult << " " << Base::toString(myTraps[i]->end);
|
listTraps(true);
|
||||||
commandResult << trapStatus(*myTraps[i]);
|
|
||||||
commandResult << " + mirrors";
|
|
||||||
if(i != (names.size() - 1)) commandResult << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
commandResult << "no traps set";
|
commandResult << "no traps set";
|
||||||
|
@ -1240,12 +1282,12 @@ void DebuggerParser::executePGfx()
|
||||||
{
|
{
|
||||||
if(argCount != 2)
|
if(argCount != 2)
|
||||||
{
|
{
|
||||||
commandResult << red("Specify start and end of range only");
|
outputCommandError("specify start and end of range only", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(args[1] < args[0])
|
else if(args[1] < args[0])
|
||||||
{
|
{
|
||||||
commandResult << red("Start address must be <= end address");
|
commandResult << red("start address must be <= end address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1332,12 +1374,12 @@ void DebuggerParser::executeRow()
|
||||||
{
|
{
|
||||||
if(argCount != 2)
|
if(argCount != 2)
|
||||||
{
|
{
|
||||||
commandResult << red("Specify start and end of range only");
|
outputCommandError("specify start and end of range only", myCommand);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(args[1] < args[0])
|
else if(args[1] < args[0])
|
||||||
{
|
{
|
||||||
commandResult << red("Start address must be <= end address");
|
commandResult << red("start address must be <= end address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1575,69 +1617,68 @@ void DebuggerParser::executeTrapwriteif()
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// Wrapper function for trap(if)s
|
// Wrapper function for trap(if)s
|
||||||
void DebuggerParser::executeTraps(bool read, bool write, string command, bool hasCond)
|
void DebuggerParser::executeTraps(bool read, bool write, const string& command, bool hasCond)
|
||||||
{
|
{
|
||||||
if(hasCond)
|
|
||||||
{
|
|
||||||
if(argCount < 1 || argCount > 3)
|
|
||||||
{
|
|
||||||
commandResult << red("Command takes one to three arguments");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(argCount > 2)
|
|
||||||
{
|
|
||||||
commandResult << red("Command takes one or two arguments");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ofs = hasCond ? 1 : 0;
|
int ofs = hasCond ? 1 : 0;
|
||||||
uInt32 begin = args[ofs];
|
uInt32 begin = args[ofs];
|
||||||
uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : begin;
|
uInt32 end = argCount == 2 + ofs ? args[1 + ofs] : begin;
|
||||||
// mirrors
|
|
||||||
uInt32 beginRead = debugger.getBaseAddress(begin, true);
|
|
||||||
uInt32 endRead = debugger.getBaseAddress(end, true);
|
|
||||||
uInt32 beginWrite = debugger.getBaseAddress(begin, false);
|
|
||||||
uInt32 endWrite = debugger.getBaseAddress(end, false);
|
|
||||||
|
|
||||||
if(begin > 0xFFFF || end > 0xFFFF || begin > end)
|
if(argCount < 1 + ofs)
|
||||||
{
|
{
|
||||||
commandResult << red("One or more addresses are invalid");
|
outputCommandError("missing required argument(s)", myCommand);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(argCount > 2 + ofs)
|
||||||
|
{
|
||||||
|
outputCommandError("too many arguments", myCommand);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(begin > 0xFFFF || end > 0xFFFF)
|
||||||
|
{
|
||||||
|
commandResult << red("invalid word argument(s) (must be 0-$ffff)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(begin > end)
|
||||||
|
{
|
||||||
|
commandResult << red("start address must be <= end address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// base addresses of mirrors
|
||||||
|
uInt32 beginRead = debugger.getBaseAddress(begin, true);
|
||||||
|
uInt32 endRead = debugger.getBaseAddress(end, true);
|
||||||
|
uInt32 beginWrite = debugger.getBaseAddress(begin, false);
|
||||||
|
uInt32 endWrite = debugger.getBaseAddress(end, false);
|
||||||
|
stringstream conditionBuf;
|
||||||
|
|
||||||
// parenthesize provided and address range condition(s) (begin)
|
// parenthesize provided and address range condition(s) (begin)
|
||||||
stringstream parserBuf, displayBuf;
|
|
||||||
if(hasCond)
|
if(hasCond)
|
||||||
parserBuf << "(" << argStrings[0] << ")&&(";
|
conditionBuf << "(" << argStrings[0] << ")&&(";
|
||||||
|
|
||||||
// add address range condition(s) to provided condition
|
// add address range condition(s) to provided condition
|
||||||
if(read)
|
if(read)
|
||||||
{
|
{
|
||||||
if(beginRead != endRead)
|
if(beginRead != endRead)
|
||||||
parserBuf << "__lastread>=" << Base::toString(beginRead) << "&&__lastread<=" << Base::toString(endRead);
|
conditionBuf << "__lastread>=" << Base::toString(beginRead) << "&&__lastread<=" << Base::toString(endRead);
|
||||||
else
|
else
|
||||||
parserBuf << "__lastread==" << Base::toString(beginRead);
|
conditionBuf << "__lastread==" << Base::toString(beginRead);
|
||||||
}
|
}
|
||||||
if(read && write)
|
if(read && write)
|
||||||
parserBuf << "||";
|
conditionBuf << "||";
|
||||||
if(write)
|
if(write)
|
||||||
{
|
{
|
||||||
if(beginWrite != endWrite)
|
if(beginWrite != endWrite)
|
||||||
parserBuf << "__lastwrite>=" << Base::toString(beginWrite) << "&&__lastwrite<=" << Base::toString(endWrite);
|
conditionBuf << "__lastwrite>=" << Base::toString(beginWrite) << "&&__lastwrite<=" << Base::toString(endWrite);
|
||||||
else
|
else
|
||||||
parserBuf << "__lastwrite==" << Base::toString(beginWrite);
|
conditionBuf << "__lastwrite==" << Base::toString(beginWrite);
|
||||||
}
|
}
|
||||||
// parenthesize provided condition (end)
|
// parenthesize provided condition (end)
|
||||||
if(hasCond)
|
if(hasCond)
|
||||||
parserBuf << ")";
|
conditionBuf << ")";
|
||||||
|
|
||||||
const string parserCondition = parserBuf.str();
|
const string condition = conditionBuf.str();
|
||||||
|
|
||||||
int res = YaccParser::parse(parserCondition.c_str());
|
int res = YaccParser::parse(condition.c_str());
|
||||||
if(res == 0)
|
if(res == 0)
|
||||||
{
|
{
|
||||||
// duplicates will remove each other
|
// duplicates will remove each other
|
||||||
|
@ -1646,7 +1687,7 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha
|
||||||
{
|
{
|
||||||
if(myTraps[i]->begin == begin && myTraps[i]->end == end &&
|
if(myTraps[i]->begin == begin && myTraps[i]->end == end &&
|
||||||
myTraps[i]->read == read && myTraps[i]->write == write &&
|
myTraps[i]->read == read && myTraps[i]->write == write &&
|
||||||
myTraps[i]->condition == parserCondition)
|
myTraps[i]->condition == condition)
|
||||||
{
|
{
|
||||||
if(debugger.cpuDebug().m6502().delCondTrap(i))
|
if(debugger.cpuDebug().m6502().delCondTrap(i))
|
||||||
{
|
{
|
||||||
|
@ -1663,11 +1704,11 @@ void DebuggerParser::executeTraps(bool read, bool write, string command, bool ha
|
||||||
if(add)
|
if(add)
|
||||||
{
|
{
|
||||||
uInt32 ret = debugger.cpuDebug().m6502().addCondTrap(
|
uInt32 ret = debugger.cpuDebug().m6502().addCondTrap(
|
||||||
YaccParser::getResult(), hasCond ? argStrings[0] : " ");
|
YaccParser::getResult(), hasCond ? argStrings[0] : "");
|
||||||
commandResult << "Added trap " << Base::toString(ret);
|
commandResult << "Added trap " << Base::toString(ret);
|
||||||
|
|
||||||
// @sa666666: please check this:
|
// @sa666666: please check this:
|
||||||
myTraps.emplace_back(new Trap{ read, write, begin, end, parserCondition });
|
myTraps.emplace_back(new Trap{ read, write, begin, end, condition });
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uInt32 addr = begin; addr <= end; ++addr)
|
for(uInt32 addr = begin; addr <= end; ++addr)
|
||||||
|
@ -2482,7 +2523,7 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
||||||
"trapif",
|
"trapif",
|
||||||
"On <condition> trap R/W access to address(es) xx [yy]",
|
"On <condition> trap R/W access to address(es) xx [yy]",
|
||||||
"Set a conditional R/W trap on the given address(es) and all mirrors\nCondition can include multiple items.\n"
|
"Set a conditional R/W trap on the given address(es) and all mirrors\nCondition can include multiple items.\n"
|
||||||
"Example: trapif _scan>100 GRP0, trapif _bank==1 f000 f100",
|
"Example: trapif _scan>#100 GRP0, trapif _bank==1 f000 f100",
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
{ kARG_WORD, kARG_MULTI_BYTE },
|
{ kARG_WORD, kARG_MULTI_BYTE },
|
||||||
|
@ -2504,7 +2545,7 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
||||||
"trapreadif",
|
"trapreadif",
|
||||||
"On <condition> trap read access to address(es) xx [yy]",
|
"On <condition> trap read access to address(es) xx [yy]",
|
||||||
"Set a conditional read trap on the given address(es) and all mirrors\nCondition can include multiple items.\n"
|
"Set a conditional read trap on the given address(es) and all mirrors\nCondition can include multiple items.\n"
|
||||||
"Example: trapreadif _scan>100 GRP0, trapreadif _bank==1 f000 f100",
|
"Example: trapreadif _scan>#100 GRP0, trapreadif _bank==1 f000 f100",
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
{ kARG_WORD, kARG_MULTI_BYTE },
|
{ kARG_WORD, kARG_MULTI_BYTE },
|
||||||
|
@ -2526,7 +2567,7 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
||||||
"trapwriteif",
|
"trapwriteif",
|
||||||
"On <condition> trap write access to address(es) xx [yy]",
|
"On <condition> trap write access to address(es) xx [yy]",
|
||||||
"Set a conditional write trap on the given address(es) and all mirrors\nCondition can include multiple items.\n"
|
"Set a conditional write trap on the given address(es) and all mirrors\nCondition can include multiple items.\n"
|
||||||
"Example: trapwriteif _scan>100 GRP0, trapwriteif _bank==1 f000 f100",
|
"Example: trapwriteif _scan>#100 GRP0, trapwriteif _bank==1 f000 f100",
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
{ kARG_WORD, kARG_MULTI_BYTE },
|
{ kARG_WORD, kARG_MULTI_BYTE },
|
||||||
|
|
|
@ -118,20 +118,23 @@ class DebuggerParser
|
||||||
// The results of the currently running command
|
// The results of the currently running command
|
||||||
ostringstream commandResult;
|
ostringstream commandResult;
|
||||||
|
|
||||||
|
// currently execute command id
|
||||||
|
int myCommand;
|
||||||
// Arguments in 'int' and 'string' format for the currently running command
|
// Arguments in 'int' and 'string' format for the currently running command
|
||||||
IntArray args;
|
IntArray args;
|
||||||
StringList argStrings;
|
StringList argStrings;
|
||||||
uInt32 argCount;
|
uInt32 argCount;
|
||||||
|
|
||||||
StringList myWatches;
|
StringList myWatches;
|
||||||
|
|
||||||
|
|
||||||
// Keep track of traps (read and/or write)
|
// Keep track of traps (read and/or write)
|
||||||
vector<unique_ptr<Trap>> myTraps;
|
vector<unique_ptr<Trap>> myTraps;
|
||||||
/*std::set<uInt32> myTraps;
|
void listTraps(bool listCond);
|
||||||
std::vector<uInt32> myTrapIfs;*/
|
|
||||||
string trapStatus(const Trap& trap);
|
string trapStatus(const Trap& trap);
|
||||||
|
|
||||||
|
// output the error with the example provided for the command
|
||||||
|
void outputCommandError(const string& errorMsg, int command);
|
||||||
|
|
||||||
// List of available command methods
|
// List of available command methods
|
||||||
void executeA();
|
void executeA();
|
||||||
void executeBase();
|
void executeBase();
|
||||||
|
@ -165,7 +168,7 @@ class DebuggerParser
|
||||||
void executeJump();
|
void executeJump();
|
||||||
void executeListbreaks();
|
void executeListbreaks();
|
||||||
void executeListconfig();
|
void executeListconfig();
|
||||||
void executeListfunctions();
|
void executeListfunctions();
|
||||||
void executeListtraps();
|
void executeListtraps();
|
||||||
void executeLoadconfig();
|
void executeLoadconfig();
|
||||||
void executeLoadstate();
|
void executeLoadstate();
|
||||||
|
@ -201,7 +204,7 @@ class DebuggerParser
|
||||||
void executeTrapreadif();
|
void executeTrapreadif();
|
||||||
void executeTrapwrite();
|
void executeTrapwrite();
|
||||||
void executeTrapwriteif();
|
void executeTrapwriteif();
|
||||||
void executeTraps(bool read, bool write, string command, bool cond = false);
|
void executeTraps(bool read, bool write, const string& command, bool cond = false);
|
||||||
void executeTrapRW(uInt32 addr, bool read, bool write, bool add = true); // not exposed by debugger
|
void executeTrapRW(uInt32 addr, bool read, bool write, bool add = true); // not exposed by debugger
|
||||||
void executeType();
|
void executeType();
|
||||||
void executeUHex();
|
void executeUHex();
|
||||||
|
|
|
@ -85,7 +85,7 @@ class AtariVox : public SaveKey
|
||||||
*/
|
*/
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
string about() const override { return Controller::about() + myAboutString; }
|
string about(bool swappedPorts) const override { return Controller::about(swappedPorts) + myAboutString; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clockDataIn(bool value);
|
void clockDataIn(bool value);
|
||||||
|
|
|
@ -199,8 +199,9 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
// Finally, add remaining info about the console
|
// Finally, add remaining info about the console
|
||||||
myConsoleInfo.CartName = myProperties.get(Cartridge_Name);
|
myConsoleInfo.CartName = myProperties.get(Cartridge_Name);
|
||||||
myConsoleInfo.CartMD5 = myProperties.get(Cartridge_MD5);
|
myConsoleInfo.CartMD5 = myProperties.get(Cartridge_MD5);
|
||||||
myConsoleInfo.Control0 = myLeftControl->about();
|
bool swappedPorts = properties().get(Console_SwapPorts) == "YES";
|
||||||
myConsoleInfo.Control1 = myRightControl->about();
|
myConsoleInfo.Control0 = myLeftControl->about(swappedPorts);
|
||||||
|
myConsoleInfo.Control1 = myRightControl->about(swappedPorts);
|
||||||
myConsoleInfo.BankSwitch = myCart->about();
|
myConsoleInfo.BankSwitch = myCart->about();
|
||||||
|
|
||||||
myCart->setRomName(myConsoleInfo.CartName);
|
myCart->setRomName(myConsoleInfo.CartName);
|
||||||
|
|
|
@ -208,8 +208,10 @@ class Controller : public Serializable
|
||||||
/**
|
/**
|
||||||
Returns more detailed information about this controller.
|
Returns more detailed information about this controller.
|
||||||
*/
|
*/
|
||||||
virtual string about() const
|
virtual string about(bool swappedPorts) const
|
||||||
{ return name() + " in " + (myJack == Left ? "left port" : "right port"); }
|
{
|
||||||
|
return name() + " in " + (myJack == Left ^ swappedPorts ? "left port" : "right port");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The following two functions are used by the debugger to set
|
The following two functions are used by the debugger to set
|
||||||
|
|
|
@ -116,8 +116,10 @@ void RomInfoWidget::parseProperties()
|
||||||
myRomInfo.push_back("Model: " + myProperties.get(Cartridge_ModelNo));
|
myRomInfo.push_back("Model: " + myProperties.get(Cartridge_ModelNo));
|
||||||
myRomInfo.push_back("Rarity: " + myProperties.get(Cartridge_Rarity));
|
myRomInfo.push_back("Rarity: " + myProperties.get(Cartridge_Rarity));
|
||||||
myRomInfo.push_back("Note: " + myProperties.get(Cartridge_Note));
|
myRomInfo.push_back("Note: " + myProperties.get(Cartridge_Note));
|
||||||
myRomInfo.push_back("Controllers: " + myProperties.get(Controller_Left) +
|
bool swappedPorts = myProperties.get(Console_SwapPorts) == "YES";
|
||||||
" (left), " + myProperties.get(Controller_Right) + " (right)");
|
myRomInfo.push_back("Controllers: " + (!swappedPorts
|
||||||
|
? myProperties.get(Controller_Left) + " (left), " + myProperties.get(Controller_Right) + " (right)"
|
||||||
|
: myProperties.get(Controller_Right) + " (left), " + myProperties.get(Controller_Left) + " (right)"));
|
||||||
#if 0
|
#if 0
|
||||||
myRomInfo.push_back("YStart/Height: " + myProperties.get(Display_YStart) +
|
myRomInfo.push_back("YStart/Height: " + myProperties.get(Display_YStart) +
|
||||||
" " + myProperties.get(Display_Height));
|
" " + myProperties.get(Display_Height));
|
||||||
|
|
Loading…
Reference in New Issue