mirror of https://github.com/stella-emu/stella.git
make breakpoints consider banks (fixes #512)
This commit is contained in:
parent
0215cda991
commit
c3f379b45d
|
@ -282,7 +282,7 @@ int main(int ac, char* av[])
|
||||||
{
|
{
|
||||||
Debugger& dbg = theOSystem->debugger();
|
Debugger& dbg = theOSystem->debugger();
|
||||||
uInt16 bp = uInt16(dbg.stringToValue(localOpts["break"].toString()));
|
uInt16 bp = uInt16(dbg.stringToValue(localOpts["break"].toString()));
|
||||||
dbg.setBreakPoint(bp, true);
|
dbg.setBreakPoint(bp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,13 +49,14 @@
|
||||||
|
|
||||||
#include "RomWidget.hxx"
|
#include "RomWidget.hxx"
|
||||||
#include "Expression.hxx"
|
#include "Expression.hxx"
|
||||||
#include "PackedBitArray.hxx"
|
|
||||||
#include "YaccParser.hxx"
|
#include "YaccParser.hxx"
|
||||||
|
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "Debugger.hxx"
|
#include "Debugger.hxx"
|
||||||
#include "DispatchResult.hxx"
|
#include "DispatchResult.hxx"
|
||||||
|
|
||||||
|
using Common::Base;
|
||||||
|
|
||||||
Debugger* Debugger::myStaticDebugger = nullptr;
|
Debugger* Debugger::myStaticDebugger = nullptr;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -190,18 +191,6 @@ string Debugger::autoExec(StringList* history)
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
PackedBitArray& Debugger::breakPoints() const
|
|
||||||
{
|
|
||||||
return mySystem.m6502().breakPoints();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
PackedBitArray& Debugger::breakPointFlags() const
|
|
||||||
{
|
|
||||||
return mySystem.m6502().breakPointFlags();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
TrapArray& Debugger::readTraps() const
|
TrapArray& Debugger::readTraps() const
|
||||||
{
|
{
|
||||||
|
@ -336,12 +325,11 @@ int Debugger::trace()
|
||||||
int targetPC = myCpuDebug->pc() + 3; // return address
|
int targetPC = myCpuDebug->pc() + 3; // return address
|
||||||
|
|
||||||
// set temporary breakpoint at target PC (if not existing already)
|
// set temporary breakpoint at target PC (if not existing already)
|
||||||
breakPoints().initialize();
|
Int8 bank = myCartDebug->getBank();
|
||||||
if(!breakPoints().isSet(targetPC))
|
if(checkBreakPoint(targetPC, bank) == NOT_FOUND)
|
||||||
{
|
{
|
||||||
breakPoints().set(targetPC);
|
// add temporary breakpoint and remove later
|
||||||
breakPointFlags().initialize();
|
setBreakPoint(targetPC, bank, true, true);
|
||||||
breakPointFlags().set(targetPC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unlockSystem();
|
unlockSystem();
|
||||||
|
@ -357,26 +345,59 @@ int Debugger::trace()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Debugger::toggleBreakPoint(uInt16 bp)
|
bool Debugger::setBreakPoint(uInt16 addr, Int8 bank, bool set, bool oneShot)
|
||||||
{
|
{
|
||||||
breakPoints().initialize();
|
Int32 id = checkBreakPoint(addr, bank);
|
||||||
breakPoints().toggle(bp);
|
|
||||||
breakPointFlags().initialize();
|
if(set)
|
||||||
|
{
|
||||||
|
if(id != NOT_FOUND)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mySystem.m6502().addCondBreak(YaccParser::getResult(), getCondition(addr, bank), oneShot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(id == NOT_FOUND)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m6502().delCondBreak(id);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Debugger::setBreakPoint(uInt16 bp, bool set)
|
Int32 Debugger::checkBreakPoint(uInt16 addr, Int8 bank)
|
||||||
{
|
{
|
||||||
breakPoints().initialize();
|
string condition = getCondition(addr, bank);
|
||||||
if(set) breakPoints().set(bp);
|
|
||||||
else breakPoints().clear(bp);
|
for(uInt32 i = 0; i < m6502().getCondBreakNames().size(); ++i)
|
||||||
breakPointFlags().initialize();
|
if(condition == m6502().getCondBreakNames()[i])
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool Debugger::breakPoint(uInt16 bp)
|
string Debugger::getCondition(uInt16 addr, Int8 bank)
|
||||||
{
|
{
|
||||||
return breakPoints().isSet(bp);
|
stringstream condition;
|
||||||
|
|
||||||
|
condition << "(pc == " << Base::HEX4 << addr << ")";
|
||||||
|
if(bank != ANY_BANK && myCartDebug->bankCount() > 1)
|
||||||
|
condition << " && (_bank == #" << int(bank) << ")";
|
||||||
|
|
||||||
|
YaccParser::parse(condition.str());
|
||||||
|
|
||||||
|
return condition.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool Debugger::toggleBreakPoint(uInt16 addr, Int8 bank)
|
||||||
|
{
|
||||||
|
setBreakPoint(addr, bank, checkBreakPoint(addr, bank) == NOT_FOUND);
|
||||||
|
|
||||||
|
return checkBreakPoint(addr, bank) != NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -604,12 +625,6 @@ uInt16 Debugger::unwindStates(const uInt16 numStates, string& message)
|
||||||
return windStates(numStates, true, message);
|
return windStates(numStates, true, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Debugger::clearAllBreakPoints()
|
|
||||||
{
|
|
||||||
breakPoints().clearAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Debugger::clearAllTraps()
|
void Debugger::clearAllTraps()
|
||||||
{
|
{
|
||||||
|
@ -688,7 +703,6 @@ void Debugger::setQuitState()
|
||||||
// execute one instruction on quit. If we're
|
// execute one instruction on quit. If we're
|
||||||
// sitting at a breakpoint/trap, this will get us past it.
|
// sitting at a breakpoint/trap, this will get us past it.
|
||||||
// Somehow this feels like a hack to me, but I don't know why
|
// Somehow this feels like a hack to me, but I don't know why
|
||||||
// if(breakPoints().isSet(myCpuDebug->pc()))
|
|
||||||
mySystem.m6502().execute(1);
|
mySystem.m6502().execute(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ class TiaZoomWidget;
|
||||||
class EditTextWidget;
|
class EditTextWidget;
|
||||||
class RomWidget;
|
class RomWidget;
|
||||||
class Expression;
|
class Expression;
|
||||||
class PackedBitArray;
|
|
||||||
class TrapArray;
|
class TrapArray;
|
||||||
class PromptWidget;
|
class PromptWidget;
|
||||||
class ButtonWidget;
|
class ButtonWidget;
|
||||||
|
@ -74,6 +73,9 @@ class Debugger : public DialogContainer
|
||||||
Debugger(OSystem& osystem, Console& console);
|
Debugger(OSystem& osystem, Console& console);
|
||||||
virtual ~Debugger();
|
virtual ~Debugger();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const Int8 ANY_BANK = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Initialize the debugger dialog container.
|
Initialize the debugger dialog container.
|
||||||
|
@ -149,11 +151,24 @@ class Debugger : public DialogContainer
|
||||||
RomWidget& rom() const { return myDialog->rom(); }
|
RomWidget& rom() const { return myDialog->rom(); }
|
||||||
TiaOutputWidget& tiaOutput() const { return myDialog->tiaOutput(); }
|
TiaOutputWidget& tiaOutput() const { return myDialog->tiaOutput(); }
|
||||||
|
|
||||||
PackedBitArray& breakPoints() const;
|
|
||||||
PackedBitArray& breakPointFlags() const;
|
|
||||||
TrapArray& readTraps() const;
|
TrapArray& readTraps() const;
|
||||||
TrapArray& writeTraps() const;
|
TrapArray& writeTraps() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets or clears a breakpoint.
|
||||||
|
|
||||||
|
Returns true if successfully set or cleared
|
||||||
|
*/
|
||||||
|
bool setBreakPoint(uInt16 addr, Int8 bank = ANY_BANK,
|
||||||
|
bool set = true, bool oneShot = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Checks for a breakpoint.
|
||||||
|
|
||||||
|
Returns -1 if not existing, else the Id
|
||||||
|
*/
|
||||||
|
Int32 checkBreakPoint(uInt16 addr, Int8 bank);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Run the debugger command and return the result.
|
Run the debugger command and return the result.
|
||||||
*/
|
*/
|
||||||
|
@ -224,7 +239,6 @@ class Debugger : public DialogContainer
|
||||||
int getAccessFlags(uInt16 addr) const;
|
int getAccessFlags(uInt16 addr) const;
|
||||||
void setAccessFlags(uInt16 addr, uInt8 flags);
|
void setAccessFlags(uInt16 addr, uInt8 flags);
|
||||||
|
|
||||||
void setBreakPoint(uInt16 bp, bool set);
|
|
||||||
uInt32 getBaseAddress(uInt32 addr, bool read);
|
uInt32 getBaseAddress(uInt32 addr, bool read);
|
||||||
|
|
||||||
bool patchROM(uInt16 addr, uInt8 value);
|
bool patchROM(uInt16 addr, uInt8 value);
|
||||||
|
@ -250,6 +264,8 @@ class Debugger : public DialogContainer
|
||||||
*/
|
*/
|
||||||
Dialog* baseDialog() override { return myDialog; }
|
Dialog* baseDialog() override { return myDialog; }
|
||||||
|
|
||||||
|
static const Int32 NOT_FOUND = -1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Save state of each debugger subsystem and, by default, mark all
|
Save state of each debugger subsystem and, by default, mark all
|
||||||
|
@ -279,9 +295,9 @@ class Debugger : public DialogContainer
|
||||||
uInt16 rewindStates(const uInt16 numStates, string& message);
|
uInt16 rewindStates(const uInt16 numStates, string& message);
|
||||||
uInt16 unwindStates(const uInt16 numStates, string& message);
|
uInt16 unwindStates(const uInt16 numStates, string& message);
|
||||||
|
|
||||||
void toggleBreakPoint(uInt16 bp);
|
bool toggleBreakPoint(uInt16 addr, Int8 bank);
|
||||||
|
string getCondition(uInt16 addr, Int8 bank);
|
||||||
|
|
||||||
bool breakPoint(uInt16 bp);
|
|
||||||
void addReadTrap(uInt16 t);
|
void addReadTrap(uInt16 t);
|
||||||
void addWriteTrap(uInt16 t);
|
void addWriteTrap(uInt16 t);
|
||||||
void addTrap(uInt16 t);
|
void addTrap(uInt16 t);
|
||||||
|
@ -296,7 +312,6 @@ class Debugger : public DialogContainer
|
||||||
string setRAM(IntArray& args);
|
string setRAM(IntArray& args);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void clearAllBreakPoints();
|
|
||||||
|
|
||||||
void saveState(int state);
|
void saveState(int state);
|
||||||
void saveAllStates();
|
void saveAllStates();
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "PromptWidget.hxx"
|
#include "PromptWidget.hxx"
|
||||||
#include "RomWidget.hxx"
|
#include "RomWidget.hxx"
|
||||||
#include "ProgressDialog.hxx"
|
#include "ProgressDialog.hxx"
|
||||||
#include "PackedBitArray.hxx"
|
|
||||||
#include "TimerManager.hxx"
|
#include "TimerManager.hxx"
|
||||||
#include "Vec.hxx"
|
#include "Vec.hxx"
|
||||||
|
|
||||||
|
@ -648,10 +647,6 @@ string DebuggerParser::saveScriptFile(string file)
|
||||||
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)
|
|
||||||
if(debugger.breakPoint(i))
|
|
||||||
out << "break " << Base::toString(i) << endl;
|
|
||||||
|
|
||||||
StringList conds = debugger.m6502().getCondBreakNames();
|
StringList conds = debugger.m6502().getCondBreakNames();
|
||||||
for(const auto& cond : conds)
|
for(const auto& cond : conds)
|
||||||
out << "breakif {" << cond << "}" << endl;
|
out << "breakif {" << cond << "}" << endl;
|
||||||
|
@ -730,20 +725,35 @@ void DebuggerParser::executeBase()
|
||||||
// "break"
|
// "break"
|
||||||
void DebuggerParser::executeBreak()
|
void DebuggerParser::executeBreak()
|
||||||
{
|
{
|
||||||
uInt16 bp;
|
uInt16 addr;
|
||||||
|
Int8 bank;
|
||||||
|
|
||||||
if(argCount == 0)
|
if(argCount == 0)
|
||||||
bp = debugger.cpuDebug().pc();
|
addr = debugger.cpuDebug().pc();
|
||||||
else
|
else
|
||||||
bp = args[0];
|
addr = args[0];
|
||||||
debugger.toggleBreakPoint(bp);
|
|
||||||
|
if(argCount < 2)
|
||||||
|
bank = debugger.cartDebug().getBank();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bank = args[1];
|
||||||
|
if(bank >= debugger.cartDebug().bankCount())
|
||||||
|
{
|
||||||
|
commandResult << red("invalid bank");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool set = debugger.toggleBreakPoint(addr, bank);
|
||||||
debugger.rom().invalidate();
|
debugger.rom().invalidate();
|
||||||
|
|
||||||
if(debugger.breakPoint(bp))
|
if(set)
|
||||||
commandResult << "set";
|
commandResult << "set";
|
||||||
else
|
else
|
||||||
commandResult << "cleared";
|
commandResult << "cleared";
|
||||||
|
|
||||||
commandResult << " breakpoint at " << Base::toString(bp);
|
commandResult << " breakpoint at " << Base::toString(addr) << " in bank " << int(bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -764,7 +774,7 @@ void DebuggerParser::executeBreakif()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uInt32 ret = debugger.m6502().addCondBreak(
|
uInt32 ret = debugger.m6502().addCondBreak(
|
||||||
YaccParser::getResult(), argStrings[0] );
|
YaccParser::getResult(), argStrings[0]);
|
||||||
commandResult << "added breakif " << Base::toString(ret);
|
commandResult << "added breakif " << Base::toString(ret);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -810,7 +820,6 @@ void DebuggerParser::executeCheat()
|
||||||
// "clearbreaks"
|
// "clearbreaks"
|
||||||
void DebuggerParser::executeClearbreaks()
|
void DebuggerParser::executeClearbreaks()
|
||||||
{
|
{
|
||||||
debugger.clearAllBreakPoints();
|
|
||||||
debugger.m6502().clearCondBreaks();
|
debugger.m6502().clearCondBreaks();
|
||||||
commandResult << "all breakpoints cleared";
|
commandResult << "all breakpoints cleared";
|
||||||
}
|
}
|
||||||
|
@ -1403,21 +1412,9 @@ void DebuggerParser::executeJump()
|
||||||
// "listbreaks"
|
// "listbreaks"
|
||||||
void DebuggerParser::executeListbreaks()
|
void DebuggerParser::executeListbreaks()
|
||||||
{
|
{
|
||||||
ostringstream buf;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for(uInt32 i = 0; i <= 0xffff; ++i)
|
|
||||||
{
|
|
||||||
if(debugger.breakPoints().isSet(i))
|
|
||||||
{
|
|
||||||
buf << debugger.cartDebug().getLabel(i, true, 4) << " ";
|
|
||||||
if(! (++count % 8) ) buf << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(count)
|
|
||||||
commandResult << "breaks:" << endl << buf.str();
|
|
||||||
|
|
||||||
StringList conds = debugger.m6502().getCondBreakNames();
|
StringList conds = debugger.m6502().getCondBreakNames();
|
||||||
|
|
||||||
if(conds.size() > 0)
|
if(conds.size() > 0)
|
||||||
{
|
{
|
||||||
if(count)
|
if(count)
|
||||||
|
@ -2256,12 +2253,12 @@ DebuggerParser::Command DebuggerParser::commands[NumCommands] = {
|
||||||
|
|
||||||
{
|
{
|
||||||
"break",
|
"break",
|
||||||
"Set/clear breakpoint at <address>",
|
"Set/clear breakpoint at <address> and <bank>",
|
||||||
"Command is a toggle, default is current PC\nValid address is 0 - ffff\n"
|
"Command is a toggle, default is current PC and bank\nValid address is 0 - ffff\n"
|
||||||
"Example: break, break f000",
|
"Example: break, break f000, break f000 0",
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
{ Parameters::ARG_WORD, Parameters::ARG_END_ARGS },
|
{ Parameters::ARG_WORD, Parameters::ARG_BYTE, Parameters::ARG_END_ARGS },
|
||||||
std::mem_fn(&DebuggerParser::executeBreak)
|
std::mem_fn(&DebuggerParser::executeBreak)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#ifndef PACKED_BIT_ARRAY_HXX
|
|
||||||
#define PACKED_BIT_ARRAY_HXX
|
|
||||||
|
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
#include "bspf.hxx"
|
|
||||||
|
|
||||||
class PackedBitArray
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PackedBitArray() : myInitialized(false) { }
|
|
||||||
|
|
||||||
bool isSet(uInt16 bit) const { return myBits[bit]; }
|
|
||||||
bool isClear(uInt16 bit) const { return !myBits[bit]; }
|
|
||||||
|
|
||||||
void set(uInt16 bit) { myBits[bit] = true; }
|
|
||||||
void clear(uInt16 bit) { myBits[bit] = false; }
|
|
||||||
void toggle(uInt16 bit) { myBits.flip(bit); }
|
|
||||||
|
|
||||||
void initialize() { myInitialized = true; }
|
|
||||||
void clearAll() { myInitialized = false; myBits.reset(); }
|
|
||||||
|
|
||||||
bool isInitialized() const { return myInitialized; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// The actual bits
|
|
||||||
std::bitset<0x10000> myBits;
|
|
||||||
|
|
||||||
// Indicates whether we should treat this bitset as initialized
|
|
||||||
bool myInitialized;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Following constructors and assignment operators not supported
|
|
||||||
PackedBitArray(const PackedBitArray&) = delete;
|
|
||||||
PackedBitArray(PackedBitArray&&) = delete;
|
|
||||||
PackedBitArray& operator=(const PackedBitArray&) = delete;
|
|
||||||
PackedBitArray& operator=(PackedBitArray&&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Debugger.hxx"
|
#include "Debugger.hxx"
|
||||||
#include "DiStella.hxx"
|
#include "DiStella.hxx"
|
||||||
#include "PackedBitArray.hxx"
|
|
||||||
#include "Widget.hxx"
|
#include "Widget.hxx"
|
||||||
#include "StellaKeys.hxx"
|
#include "StellaKeys.hxx"
|
||||||
#include "FBSurface.hxx"
|
#include "FBSurface.hxx"
|
||||||
|
@ -40,8 +39,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
_editMode(false),
|
_editMode(false),
|
||||||
_currentKeyDown(KBDK_UNKNOWN),
|
_currentKeyDown(KBDK_UNKNOWN),
|
||||||
_base(Common::Base::F_DEFAULT),
|
_base(Common::Base::F_DEFAULT),
|
||||||
myDisasm(nullptr),
|
myDisasm(nullptr)//,
|
||||||
myBPState(nullptr)
|
|
||||||
{
|
{
|
||||||
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
|
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
|
||||||
_bgcolor = kWidColor;
|
_bgcolor = kWidColor;
|
||||||
|
@ -122,11 +120,9 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void RomListWidget::setList(const CartDebug::Disassembly& disasm,
|
void RomListWidget::setList(const CartDebug::Disassembly& disasm)
|
||||||
const PackedBitArray& state)
|
|
||||||
{
|
{
|
||||||
myDisasm = &disasm;
|
myDisasm = &disasm;
|
||||||
myBPState = &state;
|
|
||||||
|
|
||||||
// Enable all checkboxes
|
// Enable all checkboxes
|
||||||
for(int i = 0; i < _rows; ++i)
|
for(int i = 0; i < _rows; ++i)
|
||||||
|
@ -496,7 +492,9 @@ void RomListWidget::drawWidget(bool hilite)
|
||||||
ColorId bytesColor = textColor;
|
ColorId bytesColor = textColor;
|
||||||
|
|
||||||
// Draw checkboxes for correct lines (takes scrolling into account)
|
// Draw checkboxes for correct lines (takes scrolling into account)
|
||||||
myCheckList[i]->setState(myBPState->isSet(dlist[pos].address));
|
myCheckList[i]->setState(instance().debugger().
|
||||||
|
checkBreakPoint(dlist[pos].address, instance().debugger().cartDebug().getBank()) != Debugger::NOT_FOUND);
|
||||||
|
|
||||||
myCheckList[i]->setDirty();
|
myCheckList[i]->setDirty();
|
||||||
myCheckList[i]->draw();
|
myCheckList[i]->draw();
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#define ROM_LIST_WIDGET_HXX
|
#define ROM_LIST_WIDGET_HXX
|
||||||
|
|
||||||
class ScrollBarWidget;
|
class ScrollBarWidget;
|
||||||
class PackedBitArray;
|
|
||||||
class CheckListWidget;
|
class CheckListWidget;
|
||||||
class RomListSettings;
|
class RomListSettings;
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ class RomListWidget : public EditableWidget
|
||||||
int x, int y, int w, int h);
|
int x, int y, int w, int h);
|
||||||
virtual ~RomListWidget() = default;
|
virtual ~RomListWidget() = default;
|
||||||
|
|
||||||
void setList(const CartDebug::Disassembly& disasm, const PackedBitArray& state);
|
void setList(const CartDebug::Disassembly& disasm);
|
||||||
|
|
||||||
int getSelected() const { return _selectedItem; }
|
int getSelected() const { return _selectedItem; }
|
||||||
int getHighlighted() const { return _highlightedItem; }
|
int getHighlighted() const { return _highlightedItem; }
|
||||||
|
@ -102,7 +101,6 @@ class RomListWidget : public EditableWidget
|
||||||
Common::Base::Format _base; // base used during editing
|
Common::Base::Format _base; // base used during editing
|
||||||
|
|
||||||
const CartDebug::Disassembly* myDisasm;
|
const CartDebug::Disassembly* myDisasm;
|
||||||
const PackedBitArray* myBPState;
|
|
||||||
vector<CheckboxWidget*> myCheckList;
|
vector<CheckboxWidget*> myCheckList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -72,7 +72,7 @@ void RomWidget::loadConfig()
|
||||||
myListIsDirty |= cart.disassemble(myListIsDirty);
|
myListIsDirty |= cart.disassemble(myListIsDirty);
|
||||||
if(myListIsDirty)
|
if(myListIsDirty)
|
||||||
{
|
{
|
||||||
myRomList->setList(cart.disassembly(), dbg.breakPoints());
|
myRomList->setList(cart.disassembly());
|
||||||
myListIsDirty = false;
|
myListIsDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,8 @@ void RomWidget::setBreak(int disasm_line, bool state)
|
||||||
if(disasm_line >= int(list.size())) return;
|
if(disasm_line >= int(list.size())) return;
|
||||||
|
|
||||||
if(list[disasm_line].address != 0 && list[disasm_line].bytes != "")
|
if(list[disasm_line].address != 0 && list[disasm_line].bytes != "")
|
||||||
instance().debugger().setBreakPoint(list[disasm_line].address, state);
|
instance().debugger().setBreakPoint(list[disasm_line].address,
|
||||||
|
instance().debugger().cartDebug().getBank(), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "Debugger.hxx"
|
#include "Debugger.hxx"
|
||||||
#include "Expression.hxx"
|
#include "Expression.hxx"
|
||||||
#include "CartDebug.hxx"
|
#include "CartDebug.hxx"
|
||||||
#include "PackedBitArray.hxx"
|
|
||||||
#include "Base.hxx"
|
#include "Base.hxx"
|
||||||
|
|
||||||
// Flags for disassembly types
|
// Flags for disassembly types
|
||||||
|
@ -280,24 +279,18 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(myBreakPoints.isInitialized() && myBreakPoints.isSet(PC)) {
|
|
||||||
myLastBreakCycle = mySystem->cycles();
|
|
||||||
// disable a one-shot breakpoint
|
|
||||||
if(myBreakPoints.isInitialized() && myBreakPointFlags.isSet(PC))
|
|
||||||
{
|
|
||||||
myBreakPoints.clear(PC);
|
|
||||||
myBreakPointFlags.clear(PC);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result.setDebugger(currentCycles, "BP: ", PC);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cond = evalCondBreaks();
|
int cond = evalCondBreaks();
|
||||||
if(cond > -1)
|
if(cond > -1)
|
||||||
{
|
{
|
||||||
ostringstream msg;
|
ostringstream msg;
|
||||||
msg << "CBP[" << Common::Base::HEX2 << cond << "]: " << myCondBreakNames[cond];
|
|
||||||
|
// one shot break (trace)?
|
||||||
|
if(myCondBreakFlags[cond])
|
||||||
|
{
|
||||||
|
delCondBreak(cond);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg << "BP[" << Common::Base::HEX2 << cond << "]: " << myCondBreakNames[cond];
|
||||||
|
|
||||||
myLastBreakCycle = mySystem->cycles();
|
myLastBreakCycle = mySystem->cycles();
|
||||||
result.setDebugger(currentCycles, msg.str());
|
result.setDebugger(currentCycles, msg.str());
|
||||||
|
@ -543,10 +536,11 @@ void M6502::attach(Debugger& debugger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 M6502::addCondBreak(Expression* e, const string& name)
|
uInt32 M6502::addCondBreak(Expression* e, const string& name, bool oneShot)
|
||||||
{
|
{
|
||||||
myCondBreaks.emplace_back(e);
|
myCondBreaks.emplace_back(e);
|
||||||
myCondBreakNames.push_back(name);
|
myCondBreakNames.push_back(name);
|
||||||
|
myCondBreakFlags.push_back(oneShot);
|
||||||
|
|
||||||
updateStepStateByInstruction();
|
updateStepStateByInstruction();
|
||||||
|
|
||||||
|
@ -560,6 +554,7 @@ bool M6502::delCondBreak(uInt32 idx)
|
||||||
{
|
{
|
||||||
Vec::removeAt(myCondBreaks, idx);
|
Vec::removeAt(myCondBreaks, idx);
|
||||||
Vec::removeAt(myCondBreakNames, idx);
|
Vec::removeAt(myCondBreakNames, idx);
|
||||||
|
Vec::removeAt(myCondBreakFlags, idx);
|
||||||
|
|
||||||
updateStepStateByInstruction();
|
updateStepStateByInstruction();
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ class DispatchResult;
|
||||||
class CpuDebug;
|
class CpuDebug;
|
||||||
|
|
||||||
#include "Expression.hxx"
|
#include "Expression.hxx"
|
||||||
#include "PackedBitArray.hxx"
|
|
||||||
#include "TrapArray.hxx"
|
#include "TrapArray.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -212,14 +211,11 @@ class M6502 : public Serializable
|
||||||
// Attach the specified debugger.
|
// Attach the specified debugger.
|
||||||
void attach(Debugger& debugger);
|
void attach(Debugger& debugger);
|
||||||
|
|
||||||
PackedBitArray& breakPoints() { return myBreakPoints; }
|
|
||||||
// flags used for one-shot breakpoints
|
|
||||||
PackedBitArray& breakPointFlags() { return myBreakPointFlags; }
|
|
||||||
TrapArray& readTraps() { return myReadTraps; }
|
TrapArray& readTraps() { return myReadTraps; }
|
||||||
TrapArray& writeTraps() { return myWriteTraps; }
|
TrapArray& writeTraps() { return myWriteTraps; }
|
||||||
|
|
||||||
// methods for 'breakif' handling
|
// methods for 'breakif' handling
|
||||||
uInt32 addCondBreak(Expression* e, const string& name);
|
uInt32 addCondBreak(Expression* e, const string& name, bool oneShot = false);
|
||||||
bool delCondBreak(uInt32 idx);
|
bool delCondBreak(uInt32 idx);
|
||||||
void clearCondBreaks();
|
void clearCondBreaks();
|
||||||
const StringList& getCondBreakNames() const;
|
const StringList& getCondBreakNames() const;
|
||||||
|
@ -399,7 +395,7 @@ class M6502 : public Serializable
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
Int32 evalCondBreaks() {
|
Int32 evalCondBreaks() {
|
||||||
for(uInt32 i = 0; i < myCondBreaks.size(); i++)
|
for(Int32 i = Int32(myCondBreaks.size()) - 1; i >= 0; --i)
|
||||||
if(myCondBreaks[i]->evaluate())
|
if(myCondBreaks[i]->evaluate())
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
|
@ -408,7 +404,7 @@ class M6502 : public Serializable
|
||||||
|
|
||||||
Int32 evalCondSaveStates()
|
Int32 evalCondSaveStates()
|
||||||
{
|
{
|
||||||
for(uInt32 i = 0; i < myCondSaveStates.size(); i++)
|
for(Int32 i = Int32(myCondSaveStates.size()) - 1; i >= 0; --i)
|
||||||
if(myCondSaveStates[i]->evaluate())
|
if(myCondSaveStates[i]->evaluate())
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
|
@ -417,7 +413,7 @@ class M6502 : public Serializable
|
||||||
|
|
||||||
Int32 evalCondTraps()
|
Int32 evalCondTraps()
|
||||||
{
|
{
|
||||||
for(uInt32 i = 0; i < myTrapConds.size(); i++)
|
for(Int32 i = Int32(myTrapConds.size()) - 1; i >= 0; --i)
|
||||||
if(myTrapConds[i]->evaluate())
|
if(myTrapConds[i]->evaluate())
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
|
@ -428,8 +424,6 @@ class M6502 : public Serializable
|
||||||
Debugger* myDebugger;
|
Debugger* myDebugger;
|
||||||
|
|
||||||
// Addresses for which the specified action should occur
|
// Addresses for which the specified action should occur
|
||||||
PackedBitArray myBreakPoints;
|
|
||||||
PackedBitArray myBreakPointFlags;
|
|
||||||
TrapArray myReadTraps, myWriteTraps;
|
TrapArray myReadTraps, myWriteTraps;
|
||||||
|
|
||||||
// Did we just now hit a trap?
|
// Did we just now hit a trap?
|
||||||
|
@ -443,6 +437,7 @@ class M6502 : public Serializable
|
||||||
|
|
||||||
vector<unique_ptr<Expression>> myCondBreaks;
|
vector<unique_ptr<Expression>> myCondBreaks;
|
||||||
StringList myCondBreakNames;
|
StringList myCondBreakNames;
|
||||||
|
BoolArray myCondBreakFlags;
|
||||||
vector<unique_ptr<Expression>> myCondSaveStates;
|
vector<unique_ptr<Expression>> myCondSaveStates;
|
||||||
StringList myCondSaveStateNames;
|
StringList myCondSaveStateNames;
|
||||||
vector<unique_ptr<Expression>> myTrapConds;
|
vector<unique_ptr<Expression>> myTrapConds;
|
||||||
|
|
|
@ -1324,7 +1324,6 @@
|
||||||
<ClInclude Include="..\debugger\DebuggerSystem.hxx" />
|
<ClInclude Include="..\debugger\DebuggerSystem.hxx" />
|
||||||
<ClInclude Include="..\debugger\DiStella.hxx" />
|
<ClInclude Include="..\debugger\DiStella.hxx" />
|
||||||
<ClInclude Include="..\debugger\Expression.hxx" />
|
<ClInclude Include="..\debugger\Expression.hxx" />
|
||||||
<ClInclude Include="..\debugger\PackedBitArray.hxx" />
|
|
||||||
<ClInclude Include="..\debugger\gui\PromptWidget.hxx" />
|
<ClInclude Include="..\debugger\gui\PromptWidget.hxx" />
|
||||||
<ClInclude Include="..\debugger\gui\RamWidget.hxx" />
|
<ClInclude Include="..\debugger\gui\RamWidget.hxx" />
|
||||||
<ClInclude Include="..\debugger\RiotDebug.hxx" />
|
<ClInclude Include="..\debugger\RiotDebug.hxx" />
|
||||||
|
|
|
@ -1226,9 +1226,6 @@
|
||||||
<ClInclude Include="..\debugger\Expression.hxx">
|
<ClInclude Include="..\debugger\Expression.hxx">
|
||||||
<Filter>Header Files\debugger</Filter>
|
<Filter>Header Files\debugger</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\debugger\PackedBitArray.hxx">
|
|
||||||
<Filter>Header Files\debugger</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\debugger\gui\PromptWidget.hxx">
|
<ClInclude Include="..\debugger\gui\PromptWidget.hxx">
|
||||||
<Filter>Header Files\debugger</Filter>
|
<Filter>Header Files\debugger</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
Loading…
Reference in New Issue