diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 79f8abe7a..515d79a98 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -171,7 +171,7 @@ int CartDebug::readFromWritePort() // port address space AND the last access was actually a read (the latter // differentiates between reads that are normally part of a write cycle vs. // ones that are illegal) - if(mySystem.m6502().lastReadAddress() && + if(mySystem.m6502().lastRealReadAddress() && (mySystem.getPageAccessType(addr) & System::PA_WRITE) == System::PA_WRITE) return addr; else diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 3c178dd44..c9c0531ff 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -30,6 +30,7 @@ class CartDebugWidget; #include "Cart.hxx" #include "DebuggerSystem.hxx" #include "System.hxx" +#include "M6502.hxx" // Function type for CartDebug instance methods class CartDebug; @@ -127,6 +128,11 @@ class CartDebug : public DebuggerSystem // write port area. int readFromWritePort(); + // Return the address of the last CPU read + int lastReadAddress() { return mySystem.m6502().lastReadAddress(); } + // Return the address of the last CPU write + int lastWriteAddress() { return mySystem.m6502().lastWriteAddress(); } + // The following two methods are meant to be used together // First, a call is made to disassemble(), which updates the disassembly // list; it will figure out when an actual complete disassembly is diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index ec9e1d302..c73e002fc 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -85,7 +85,6 @@ static const char* const builtin_functions[][3] = { { "_diff0a", "*SWCHB & $40", "Left diff. set to A (hard)" }, { "_diff1b", "!(*SWCHB & $80)", "Right diff. set to B (easy)" }, { "_diff1a", "*SWCHB & $80", "Right diff. set to A (hard)" }, - // empty string marks end of list, do not remove { 0, 0, 0 } }; @@ -104,7 +103,10 @@ static const char* const pseudo_registers[][2] = { { "_rwport", "Address at which a read from a write port occurred" }, { "_scan", "Current scanline count" }, { "_vblank", "Whether vertical blank is enabled (1 or 0)" }, - { "_vsync", "Whether vertical sync is enabled (1 or 0)" }, + { "_vsync", "Whether vertical sync is enabled (1 or 0)" }, + // CPU address access functions: + { "_lastread", "last CPU read address" }, + { "_lastwrite", "last CPU write address" }, // empty string marks end of list, do not remove { 0, 0 } diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 5cebb73f7..719aafbef 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -1571,21 +1571,36 @@ void DebuggerParser::executeTraps(bool read, bool write, bool cond, string comma return; } - /*if(cond) - { - int res = YaccParser::parse(argStrings[0].c_str()); + uInt32 beg = args[ofs]; + uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; + + if(cond) + { + // create: (condition) && (_lastread >= f000 && _lastread <= f100) + // add address range condition(s) to provided condition + stringstream buf; + buf << "(" << argStrings[0] << ")&&("; + if(read) + buf << "_lastread>=" << Base::toString(beg) << "&&_lastread<=" << Base::toString(end); + if (read && write) + buf << "||"; + if (write) + buf << "_lastwrite>=" << Base::toString(beg) << "&&_lastwrite<=" << Base::toString(end); + buf << ")"; + string condition = buf.str(); + + //int res = YaccParser::parse(argStrings[0].c_str()); + int res = YaccParser::parse(condition.c_str()); if(res == 0) { uInt32 ret = debugger.cpuDebug().m6502().addCondTrap( - YaccParser::getResult(), argStrings[0]); - commandResult << "Added " << command << " " << Base::toString(ret) << ", "; + YaccParser::getResult(), condition); + commandResult << "Added " << command << " " << Base::toString(ret); } else commandResult << red("invalid expression"); - }*/ + } - uInt32 beg = args[ofs]; - uInt32 end = argCount == ofs + 2 ? args[ofs + 1] : beg; if(beg > 0xFFFF || end > 0xFFFF) { commandResult << red("One or more addresses are invalid") << endl; diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index ce9a08544..16ce43f35 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -459,10 +459,10 @@ const StringList& M6502::getCondBreakNames() const return myBreakCondNames; } -/*// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 M6502::addCondTrap(Expression* e, const string& name) { - //myTrapConds.emplace_back(e); + myTrapConds.emplace_back(e); myTrapCondNames.push_back(name); return uInt32(myTrapConds.size() - 1); } @@ -472,8 +472,7 @@ void M6502::delCondTrap(uInt32 brk) { if(brk < myTrapConds.size()) { - myTrapConds.erase(brk); - //Vec::removeAt(myTrapConds, brk); + Vec::removeAt(myTrapConds, brk); Vec::removeAt(myTrapCondNames, brk); } } @@ -489,5 +488,5 @@ void M6502::clearCondTraps() const StringList& M6502::getCondTrapNames() const { return myTrapCondNames; -}*/ +} #endif // DEBUGGER_SUPPORT diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index 7e21ea5c5..77c15423e 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -145,11 +145,25 @@ class M6502 : public Serializable @return The address of the last read */ - uInt16 lastReadAddress() const { + uInt16 lastRealReadAddress() const { return myLastPokeAddress ? (myLastPokeAddress != myLastPeekAddress ? myLastPeekAddress : 0) : myLastPeekAddress; - } + } + + /** + Return the last address that was part of a read/peek. + + @return The address of the last read + */ + uInt16 lastReadAddress() const { return myLastPeekAddress; } + + /** + Return the last address that was part of a write/poke. + + @return The address of the last write + */ + uInt16 lastWriteAddress() const { return myLastPokeAddress; } /** Return the source of the address that was used for a write/poke. @@ -215,16 +229,17 @@ class M6502 : public Serializable TrapArray& readTraps() { return myReadTraps; } TrapArray& writeTraps() { return myWriteTraps; } + // methods for 'breakif' handling uInt32 addCondBreak(Expression* e, const string& name); void delCondBreak(uInt32 brk); void clearCondBreaks(); const StringList& getCondBreakNames() const; - /*uInt32 addCondTrap(Expression* e, const string& name); + // methods for 'trapif' handling + uInt32 addCondTrap(Expression* e, const string& name); void delCondTrap(uInt32 brk); void clearCondTraps(); - const StringList& getCondTrapNames() const;*/ - + const StringList& getCondTrapNames() const; #endif // DEBUGGER_SUPPORT private: @@ -370,14 +385,14 @@ class M6502 : public Serializable return -1; // no break hit } - /*Int32 evalCondTraps() + Int32 evalCondTraps() { for(uInt32 i = 0; i < myTrapConds.size(); i++) if(myTrapConds[i]->evaluate()) return i; return -1; // no trapif hit - }*/ + } /// Pointer to the debugger for this processor or the null pointer Debugger* myDebugger; @@ -396,8 +411,8 @@ class M6502 : public Serializable vector> myBreakConds; StringList myBreakCondNames; - //std::map> myTrapConds; - //StringList myTrapCondNames; + vector> myTrapConds; + StringList myTrapCondNames; #endif // DEBUGGER_SUPPORT private: diff --git a/src/yacc/YaccParser.cxx b/src/yacc/YaccParser.cxx index 6a010b720..862970584 100644 --- a/src/yacc/YaccParser.cxx +++ b/src/yacc/YaccParser.cxx @@ -206,6 +206,10 @@ CartMethod getCartSpecial(char* ch) return &CartDebug::getBank; else if(BSPF::equalsIgnoreCase(ch, "_rwport")) return &CartDebug::readFromWritePort; + else if(BSPF::equalsIgnoreCase(ch, "_lastread")) + return &CartDebug::lastReadAddress; + else if(BSPF::equalsIgnoreCase(ch, "_lastwrite")) + return &CartDebug::lastWriteAddress; else return 0; }