From 735144457db8c47721a189970a83a5ae4be12b3c Mon Sep 17 00:00:00 2001 From: stephena Date: Sat, 19 Apr 2008 21:11:52 +0000 Subject: [PATCH] Added RiotDebug class, which for now only duplicates the previous functionality of the Debugger::riotState() method. It will become more useful when I add a RIOT tab to the debugger. Also, added change tracking infrastructure. Fixed long-standing bug with viewing the contents of TIM{1, 8, 64, 1024}T registers. Apparently, the output generated by the 'riot' debugger command showed either INTIM or TIMINT for those registers, and not the actual value written to those registers. Added INTIM, TIMINT, and TIMCLKS to the riot output, which show the current values of the timer, the timer interrupt, and the number of 'timer clocks' resulting from writing to a timer register. Cleaned up some of the debugger API, removing pointers and using references instead. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1479 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/common/Array.hxx | 4 +- stella/src/debugger/CpuDebug.cxx | 166 +++++++----- stella/src/debugger/CpuDebug.hxx | 49 ++-- stella/src/debugger/Debugger.cxx | 227 +---------------- stella/src/debugger/Debugger.hxx | 69 +++-- stella/src/debugger/DebuggerParser.cxx | 11 +- stella/src/debugger/DebuggerSystem.hxx | 14 +- stella/src/debugger/RamDebug.cxx | 57 ++++- stella/src/debugger/RamDebug.hxx | 11 +- stella/src/debugger/RiotDebug.cxx | 281 +++++++++++++++++++++ stella/src/debugger/RiotDebug.hxx | 82 ++++++ stella/src/debugger/TIADebug.cxx | 334 +++++++++++++------------ stella/src/debugger/TIADebug.hxx | 35 +-- stella/src/debugger/gui/TiaWidget.cxx | 17 +- stella/src/debugger/module.mk | 1 + stella/src/emucore/M6532.cxx | 32 ++- stella/src/emucore/M6532.hxx | 20 +- 17 files changed, 852 insertions(+), 558 deletions(-) create mode 100644 stella/src/debugger/RiotDebug.cxx create mode 100644 stella/src/debugger/RiotDebug.hxx diff --git a/stella/src/common/Array.hxx b/stella/src/common/Array.hxx index d6fbd5fa3..ce9c84519 100644 --- a/stella/src/common/Array.hxx +++ b/stella/src/common/Array.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Array.hxx,v 1.5 2008-02-06 13:45:19 stephena Exp $ +// $Id: Array.hxx,v 1.6 2008-04-19 21:11:52 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -22,7 +22,7 @@ #ifndef ARRAY_HXX #define ARRAY_HXX -#include +#include #include "bspf.hxx" diff --git a/stella/src/debugger/CpuDebug.cxx b/stella/src/debugger/CpuDebug.cxx index 2eb10455b..edb59a1dd 100644 --- a/stella/src/debugger/CpuDebug.cxx +++ b/stella/src/debugger/CpuDebug.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: CpuDebug.cxx,v 1.10 2008-04-02 01:54:31 stephena Exp $ +// $Id: CpuDebug.cxx,v 1.11 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #include @@ -21,34 +21,27 @@ #include "Array.hxx" #include "EquateList.hxx" #include "M6502.hxx" +#include "TIADebug.hxx" #include "CpuDebug.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CpuDebug::CpuDebug(Debugger* dbg, Console* console) - : DebuggerSystem(dbg, console), - mySystem(&(console->system())) +CpuDebug::CpuDebug(Debugger& dbg, Console& console) + : DebuggerSystem(dbg, console) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DebuggerState& CpuDebug::getState() +const DebuggerState& CpuDebug::getState() { - myState.PC = mySystem->m6502().PC; - myState.SP = mySystem->m6502().SP; - myState.PS = mySystem->m6502().PS(); - myState.A = mySystem->m6502().A; - myState.X = mySystem->m6502().X; - myState.Y = mySystem->m6502().Y; + myState.PC = mySystem.m6502().PC; + myState.SP = mySystem.m6502().SP; + myState.PS = mySystem.m6502().PS(); + myState.A = mySystem.m6502().A; + myState.X = mySystem.m6502().X; + myState.Y = mySystem.m6502().Y; - myState.PSbits.clear(); - for(int i = 0; i < 8; ++i) - { - if(myState.PS & (1<<(7-i))) - myState.PSbits.push_back(true); - else - myState.PSbits.push_back(false); - } + Debugger::set_bits(myState.PS, myState.PSbits); return myState; } @@ -56,21 +49,72 @@ DebuggerState& CpuDebug::getState() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::saveOldState() { - myOldState.PC = mySystem->m6502().PC; - myOldState.SP = mySystem->m6502().SP; - myOldState.PS = mySystem->m6502().PS(); - myOldState.A = mySystem->m6502().A; - myOldState.X = mySystem->m6502().X; - myOldState.Y = mySystem->m6502().Y; + myOldState.PC = mySystem.m6502().PC; + myOldState.SP = mySystem.m6502().SP; + myOldState.PS = mySystem.m6502().PS(); + myOldState.A = mySystem.m6502().A; + myOldState.X = mySystem.m6502().X; + myOldState.Y = mySystem.m6502().Y; - myOldState.PSbits.clear(); - for(int i = 0; i < 8; ++i) - { - if(myOldState.PS & (1<<(7-i))) - myOldState.PSbits.push_back(true); - else - myOldState.PSbits.push_back(false); - } + Debugger::set_bits(myOldState.PS, myOldState.PSbits); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CpuDebug::toString() +{ + // TODO - this doesn't seem to be used anywhere ?? + string result; + char buf[255]; + + const CpuState& state = (CpuState&) getState(); + const CpuState& oldstate = (CpuState&) getOldState(); + + result += "\nPC="; + result += myDebugger.invIfChanged(state.PC, oldstate.PC); + result += " A="; + result += myDebugger.invIfChanged(state.A, oldstate.A); + result += " X="; + result += myDebugger.invIfChanged(state.X, oldstate.X); + result += " Y="; + result += myDebugger.invIfChanged(state.Y, oldstate.Y); + result += " S="; + result += myDebugger.invIfChanged(state.SP, oldstate.SP); + result += " P="; + result += myDebugger.invIfChanged(state.PS, oldstate.PS); + result += "/"; + + // NV-BDIZC + buf[0] = n() ? 'N' : 'n'; + buf[1] = v() ? 'V' : 'v'; + buf[2] = '-'; + buf[3] = b() ? 'B' : 'b'; + buf[4] = d() ? 'D' : 'd'; + buf[5] = i() ? 'I' : 'i'; + buf[6] = z() ? 'Z' : 'z'; + buf[7] = c() ? 'C' : 'c'; + buf[8] = '\0'; + + result += buf; + result += "\n FrameCyc:"; + sprintf(buf, "%d", mySystem.cycles()); + result += buf; + result += " Frame:"; + sprintf(buf, "%d", myDebugger.tiaDebug().frameCount()); + result += buf; + result += " ScanLine:"; + sprintf(buf, "%d", myDebugger.tiaDebug().scanlines()); + result += buf; + result += " Clk/Pix/Cyc:"; + int clk = myDebugger.tiaDebug().clocksThisLine(); + sprintf(buf, "%d/%d/%d", clk, clk-68, clk/3); + result += buf; + result += " 6502Ins:"; + sprintf(buf, "%d", mySystem.m6502().totalInstructionCount()); + result += buf; + result += "\n "; + + result += myDebugger.disassemble(state.PC, 1); + return result; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -78,7 +122,7 @@ int CpuDebug::disassemble(int address, string& result, EquateList* equateList) { ostringstream buf; int count = 0; - int opcode = mySystem->peek(address); + int opcode = mySystem.peek(address); switch(M6502::ourAddressingModeTable[opcode]) { @@ -105,7 +149,7 @@ int CpuDebug::disassemble(int address, string& result, EquateList* equateList) case M6502::Immediate: buf << M6502::ourInstructionMnemonicTable[opcode] << " #$" - << hex << setw(2) << setfill('0') << (int) mySystem->peek(address + 1) << " ; " + << hex << setw(2) << setfill('0') << (int) mySystem.peek(address + 1) << " ; " << dec << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; @@ -125,42 +169,42 @@ int CpuDebug::disassemble(int address, string& result, EquateList* equateList) case M6502::IndirectX: buf << M6502::ourInstructionMnemonicTable[opcode] << " (" - << equateList->getFormatted(mySystem->peek(address + 1), 2) << ",x) ; " + << equateList->getFormatted(mySystem.peek(address + 1), 2) << ",x) ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::IndirectY: buf << M6502::ourInstructionMnemonicTable[opcode] << " (" - << equateList->getFormatted(mySystem->peek(address + 1), 2) << "),y ; " + << equateList->getFormatted(mySystem.peek(address + 1), 2) << "),y ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::Relative: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(address + 2 + ((Int16)(Int8)mySystem->peek(address + 1)), 4) + << equateList->getFormatted(address + 2 + ((Int16)(Int8)mySystem.peek(address + 1)), 4) << " ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::Zero: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(mySystem->peek(address + 1), 2) << " ; " + << equateList->getFormatted(mySystem.peek(address + 1), 2) << " ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::ZeroX: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(mySystem->peek(address + 1), 2) << ",x ; " + << equateList->getFormatted(mySystem.peek(address + 1), 2) << ",x ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::ZeroY: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(mySystem->peek(address + 1), 2) << ",y ; " + << equateList->getFormatted(mySystem.peek(address + 1), 2) << ",y ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; @@ -193,119 +237,119 @@ int CpuDebug::dPeek(int address) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setPC(int pc) { - mySystem->m6502().PC = pc; + mySystem.m6502().PC = pc; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setSP(int sp) { - mySystem->m6502().SP = sp; + mySystem.m6502().SP = sp; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setPS(int ps) { - mySystem->m6502().PS(ps); + mySystem.m6502().PS(ps); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setA(int a) { - mySystem->m6502().A = a; + mySystem.m6502().A = a; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setX(int x) { - mySystem->m6502().X = x; + mySystem.m6502().X = x; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setY(int y) { - mySystem->m6502().Y = y; + mySystem.m6502().Y = y; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setN(bool on) { - setPS( set_bit(mySystem->m6502().PS(), 7, on) ); + setPS( Debugger::set_bit(mySystem.m6502().PS(), 7, on) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setV(bool on) { - setPS( set_bit(mySystem->m6502().PS(), 6, on) ); + setPS( Debugger::set_bit(mySystem.m6502().PS(), 6, on) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setB(bool on) { - setPS( set_bit(mySystem->m6502().PS(), 4, on) ); + setPS( Debugger::set_bit(mySystem.m6502().PS(), 4, on) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setD(bool on) { - setPS( set_bit(mySystem->m6502().PS(), 3, on) ); + setPS( Debugger::set_bit(mySystem.m6502().PS(), 3, on) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setI(bool on) { - setPS( set_bit(mySystem->m6502().PS(), 2, on) ); + setPS( Debugger::set_bit(mySystem.m6502().PS(), 2, on) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setZ(bool on) { - setPS( set_bit(mySystem->m6502().PS(), 1, on) ); + setPS( Debugger::set_bit(mySystem.m6502().PS(), 1, on) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::setC(bool on) { - setPS( set_bit(mySystem->m6502().PS(), 0, on) ); + setPS( Debugger::set_bit(mySystem.m6502().PS(), 0, on) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::toggleN() { - setPS( mySystem->m6502().PS() ^ 0x80 ); + setPS( mySystem.m6502().PS() ^ 0x80 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::toggleV() { - setPS( mySystem->m6502().PS() ^ 0x40 ); + setPS( mySystem.m6502().PS() ^ 0x40 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::toggleB() { - setPS( mySystem->m6502().PS() ^ 0x10 ); + setPS( mySystem.m6502().PS() ^ 0x10 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::toggleD() { - setPS( mySystem->m6502().PS() ^ 0x08 ); + setPS( mySystem.m6502().PS() ^ 0x08 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::toggleI() { - setPS( mySystem->m6502().PS() ^ 0x04 ); + setPS( mySystem.m6502().PS() ^ 0x04 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::toggleZ() { - setPS( mySystem->m6502().PS() ^ 0x02 ); + setPS( mySystem.m6502().PS() ^ 0x02 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CpuDebug::toggleC() { - setPS( mySystem->m6502().PS() ^ 0x01 ); + setPS( mySystem.m6502().PS() ^ 0x01 ); } diff --git a/stella/src/debugger/CpuDebug.hxx b/stella/src/debugger/CpuDebug.hxx index bc672b1f7..6f840e3d4 100644 --- a/stella/src/debugger/CpuDebug.hxx +++ b/stella/src/debugger/CpuDebug.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: CpuDebug.hxx,v 1.12 2008-04-02 01:54:31 stephena Exp $ +// $Id: CpuDebug.hxx,v 1.13 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #ifndef CPU_DEBUG_HXX @@ -41,34 +41,35 @@ class CpuState : public DebuggerState class CpuDebug : public DebuggerSystem { public: - CpuDebug(Debugger* dbg, Console* console); + CpuDebug(Debugger& dbg, Console& console); - DebuggerState& getState(); - DebuggerState& getOldState() { return myOldState; } + const DebuggerState& getState(); + const DebuggerState& getOldState() { return myOldState; } void saveOldState(); + string toString(); // I know, we ain't supposed to do this... - M6502 &m6502() { return mySystem->m6502(); } + M6502 &m6502() { return mySystem.m6502(); } int disassemble(int address, string& result, EquateList* equateList); int dPeek(int address); int getBank(); - int pc() { return mySystem->m6502().PC; } - int sp() { return mySystem->m6502().SP; } - int a() { return mySystem->m6502().A; } - int x() { return mySystem->m6502().X; } - int y() { return mySystem->m6502().Y; } + int pc() { return mySystem.m6502().PC; } + int sp() { return mySystem.m6502().SP; } + int a() { return mySystem.m6502().A; } + int x() { return mySystem.m6502().X; } + int y() { return mySystem.m6502().Y; } // these return int, not boolean! - int n() { return mySystem->m6502().N; } - int v() { return mySystem->m6502().V; } - int b() { return mySystem->m6502().B; } - int d() { return mySystem->m6502().D; } - int i() { return mySystem->m6502().I; } - int z() { return !mySystem->m6502().notZ; } - int c() { return mySystem->m6502().C; } + int n() { return mySystem.m6502().N; } + int v() { return mySystem.m6502().V; } + int b() { return mySystem.m6502().B; } + int d() { return mySystem.m6502().D; } + int i() { return mySystem.m6502().I; } + int z() { return !mySystem.m6502().notZ; } + int c() { return mySystem.m6502().C; } void setPC(int pc); void setSP(int sp); @@ -94,24 +95,14 @@ class CpuDebug : public DebuggerSystem void toggleC(); private: - static unsigned char set_bit(unsigned char input, int bit, bool on) + static int dpeek(System& system, int address) { - if(on) - return input | (1 << bit); - else - return input & (~(1 << bit)); - } - - static int dpeek(System* system, int address) - { - return system->peek(address) | (system->peek(address + 1) << 8); + return system.peek(address) | (system.peek(address + 1) << 8); } private: CpuState myState; CpuState myOldState; - - System* mySystem; }; #endif diff --git a/stella/src/debugger/Debugger.cxx b/stella/src/debugger/Debugger.cxx index 41f42efda..f43c850e2 100644 --- a/stella/src/debugger/Debugger.cxx +++ b/stella/src/debugger/Debugger.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Debugger.cxx,v 1.122 2008-04-02 01:54:31 stephena Exp $ +// $Id: Debugger.cxx,v 1.123 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #include "bspf.hxx" @@ -38,6 +38,7 @@ #include "EquateList.hxx" #include "CpuDebug.hxx" #include "RamDebug.hxx" +#include "RiotDebug.hxx" #include "TIADebug.hxx" #include "TiaInfoWidget.hxx" @@ -95,6 +96,7 @@ Debugger::Debugger(OSystem* osystem) myParser(NULL), myCpuDebug(NULL), myRamDebug(NULL), + myRiotDebug(NULL), myTiaDebug(NULL), myTiaInfo(NULL), myTiaOutput(NULL), @@ -137,6 +139,7 @@ Debugger::~Debugger() delete myCpuDebug; delete myRamDebug; + delete myRiotDebug; delete myTiaDebug; delete myEquateList; @@ -183,13 +186,16 @@ void Debugger::setConsole(Console* console) // Create debugger subsystems delete myCpuDebug; - myCpuDebug = new CpuDebug(this, myConsole); + myCpuDebug = new CpuDebug(*this, *myConsole); delete myRamDebug; - myRamDebug = new RamDebug(this, myConsole); + myRamDebug = new RamDebug(*this, *myConsole); + + delete myRiotDebug; + myRiotDebug = new RiotDebug(*this, *myConsole); delete myTiaDebug; - myTiaDebug = new TIADebug(this, myConsole); + myTiaDebug = new TIADebug(*this, *myConsole); // Initialize equates and breakpoints to known state delete myEquateList; @@ -410,136 +416,6 @@ const string Debugger::invIfChanged(int reg, int oldReg) return ret; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const string Debugger::cpuState() -{ - string result; - char buf[255]; - - CpuState state = (CpuState&) myCpuDebug->getState(); - CpuState oldstate = (CpuState&) myCpuDebug->getOldState(); - - result += "\nPC="; - result += invIfChanged(state.PC, oldstate.PC); - result += " A="; - result += invIfChanged(state.A, oldstate.A); - result += " X="; - result += invIfChanged(state.X, oldstate.X); - result += " Y="; - result += invIfChanged(state.Y, oldstate.Y); - result += " S="; - result += invIfChanged(state.SP, oldstate.SP); - result += " P="; - result += invIfChanged(state.PS, oldstate.PS); - result += "/"; - formatFlags(state.PSbits, buf); - result += buf; - result += "\n FrameCyc:"; - sprintf(buf, "%d", mySystem->cycles()); - result += buf; - result += " Frame:"; - sprintf(buf, "%d", myTiaDebug->frameCount()); - result += buf; - result += " ScanLine:"; - sprintf(buf, "%d", myTiaDebug->scanlines()); - result += buf; - result += " Clk/Pix/Cyc:"; - int clk = myTiaDebug->clocksThisLine(); - sprintf(buf, "%d/%d/%d", clk, clk-68, clk/3); - result += buf; - result += " 6502Ins:"; - sprintf(buf, "%d", mySystem->m6502().totalInstructionCount()); - result += buf; - result += "\n "; - - result += disassemble(state.PC, 1); - return result; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* The timers, joysticks, and switches can be read via peeks, so - I didn't write a separate RIOTDebug class. */ -const string Debugger::riotState() -{ - string ret; - - // TODO: inverse video for changed regs. Core needs to track this. - // TODO: keyboard controllers? - - for(int i=0x280; i<0x284; i++) - { - ret += valueToString(i); - ret += "/"; - ret += equates().getFormatted(i, 2); - ret += "="; - ret += valueToString(mySystem->peek(i)); - ret += " "; - } - ret += "\n"; - - // These are squirrely: some symbol files will define these as - // 0x284-0x287. Doesn't actually matter, these registers repeat - // every 16 bytes. - ret += valueToString(0x294); - ret += "/TIM1T="; - ret += valueToString(mySystem->peek(0x294)); - ret += " "; - - ret += valueToString(0x295); - ret += "/TIM8T="; - ret += valueToString(mySystem->peek(0x295)); - ret += " "; - - ret += valueToString(0x296); - ret += "/TIM64T="; - ret += valueToString(mySystem->peek(0x296)); - ret += " "; - - ret += valueToString(0x297); - ret += "/TIM1024T="; - ret += valueToString(mySystem->peek(0x297)); - ret += "\n"; - - ret += "Left/P0diff: "; - ret += (mySystem->peek(0x282) & 0x40) ? "hard/A" : "easy/B"; - ret += " "; - - ret += "Right/P1diff: "; - ret += (mySystem->peek(0x282) & 0x80) ? "hard/A" : "easy/B"; - ret += "\n"; - - ret += "TVType: "; - ret += (mySystem->peek(0x282) & 0x8) ? "Color" : "B&W"; - ret += " Switches: "; - ret += (mySystem->peek(0x282) & 0x2) ? "-" : "+"; - ret += "select "; - ret += (mySystem->peek(0x282) & 0x1) ? "-" : "+"; - ret += "reset"; - ret += "\n"; - - // Yes, the fire buttons are in the TIA, but we might as well - // show them here for convenience. - ret += "Left/P0 stick: "; - ret += (mySystem->peek(0x280) & 0x80) ? "" : "right "; - ret += (mySystem->peek(0x280) & 0x40) ? "" : "left "; - ret += (mySystem->peek(0x280) & 0x20) ? "" : "down "; - ret += (mySystem->peek(0x280) & 0x10) ? "" : "up "; - ret += ((mySystem->peek(0x280) & 0xf0) == 0xf0) ? "(no directions) " : ""; - ret += (mySystem->peek(0x03c) & 0x80) ? "" : "(button) "; - ret += "\n"; - ret += "Right/P1 stick: "; - ret += (mySystem->peek(0x280) & 0x08) ? "" : "right "; - ret += (mySystem->peek(0x280) & 0x04) ? "" : "left "; - ret += (mySystem->peek(0x280) & 0x02) ? "" : "down "; - ret += (mySystem->peek(0x280) & 0x01) ? "" : "up "; - ret += ((mySystem->peek(0x280) & 0x0f) == 0x0f) ? "(no directions) " : ""; - ret += (mySystem->peek(0x03d) & 0x80) ? "" : "(button) "; - - //ret += "\n"; // caller will add - - return ret; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::reset() { @@ -547,21 +423,6 @@ void Debugger::reset() myCpuDebug->setPC(pc); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::formatFlags(BoolArray& b, char *out) -{ - // NV-BDIZC - out[0] = myCpuDebug->n() ? 'N' : 'n'; - out[1] = myCpuDebug->v() ? 'V' : 'v'; - out[2] = '-'; - out[3] = myCpuDebug->b() ? 'B' : 'b'; - out[4] = myCpuDebug->d() ? 'D' : 'd'; - out[5] = myCpuDebug->i() ? 'I' : 'i'; - out[6] = myCpuDebug->z() ? 'Z' : 'z'; - out[7] = myCpuDebug->c() ? 'C' : 'c'; - out[8] = '\0'; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* Element 0 of args is the address. The remaining elements are the data to poke, starting at the given address. @@ -584,73 +445,6 @@ const string Debugger::setRAM(IntArray& args) return ret; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* Warning: this method really is for dumping *RAM*, not ROM or I/O! */ -const string Debugger::dumpRAM() -{ - string result; - char buf[128]; - int bytesPerLine; - int start = kRamStart, len = kRamSize; - - switch(myParser->base()) - { - case kBASE_16: - case kBASE_10: - bytesPerLine = 0x10; - break; - - case kBASE_2: - bytesPerLine = 0x04; - break; - - case kBASE_DEFAULT: - default: - return DebuggerParser::red("invalid base, this is a BUG"); - } - - RamState state = (RamState&) myRamDebug->getState(); - RamState oldstate = (RamState&) myRamDebug->getOldState(); - for (uInt8 i = 0x00; i < len; i += bytesPerLine) - { - sprintf(buf, "%.2x: ", start+i); - result += buf; - - for (uInt8 j = 0; j < bytesPerLine; j++) - { - result += invIfChanged(state.ram[i+j], oldstate.ram[i+j]); - result += " "; - - if(j == 0x07) result += " "; - } - result += "\n"; - } - - return result; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const string Debugger::dumpTIA() -{ - string result; - char buf[128]; - - sprintf(buf, "%.2x: ", 0); - result += buf; - for (uInt8 j = 0; j < 0x010; j++) - { - sprintf(buf, "%.2x ", mySystem->peek(j)); - result += buf; - - if(j == 0x07) result += "- "; - } - - result += "\n"; - result += myTiaDebug->state(); - - return result; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::saveState(int state) { @@ -935,6 +729,7 @@ void Debugger::saveOldState() { myCpuDebug->saveOldState(); myRamDebug->saveOldState(); + myRiotDebug->saveOldState(); myTiaDebug->saveOldState(); } diff --git a/stella/src/debugger/Debugger.hxx b/stella/src/debugger/Debugger.hxx index 05a6f30ab..40e6cc2db 100644 --- a/stella/src/debugger/Debugger.hxx +++ b/stella/src/debugger/Debugger.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Debugger.hxx,v 1.92 2008-03-23 17:43:21 stephena Exp $ +// $Id: Debugger.hxx,v 1.93 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #ifndef DEBUGGER_HXX @@ -24,6 +24,7 @@ class Console; class System; class CpuDebug; class RamDebug; +class RiotDebug; class TIADebug; class TiaInfoWidget; class TiaOutputWidget; @@ -69,7 +70,7 @@ typedef uInt16 (Debugger::*DEBUGGER_WORD_METHOD)(); for all debugging operations in Stella (parser, 6502 debugger, etc). @author Stephen Anthony - @version $Id: Debugger.hxx,v 1.92 2008-03-23 17:43:21 stephena Exp $ + @version $Id: Debugger.hxx,v 1.93 2008-04-19 21:11:52 stephena Exp $ */ class Debugger : public DialogContainer { @@ -143,6 +144,11 @@ class Debugger : public DialogContainer */ RamDebug& ramDebug() const { return *myRamDebug; } + /** + The debugger subsystem responsible for all RIOT state + */ + RiotDebug& riotDebug() const { return *myRiotDebug; } + /** The debugger subsystem responsible for all TIA state */ @@ -163,17 +169,6 @@ class Debugger : public DialogContainer */ const string run(const string& command); - /** - Give the contents of the CPU registers and disassembly of - next instruction. - */ - const string cpuState(); - - /** - Get contents of RIOT switch & timer registers - */ - const string riotState(); - /** The current cycle count of the System. */ @@ -249,6 +244,41 @@ class Debugger : public DialogContainer else return -1; } + /* Convenience methods to get/set bit(s) in an 8-bit register */ + static uInt8 set_bit(uInt8 input, uInt8 bit, bool on) + { + if(on) + return input | (1 << bit); + else + return input & ~(1 << bit); + } + static void set_bits(uInt8 reg, BoolArray& bits) + { + bits.clear(); + for(int i = 0; i < 8; ++i) + { + if(reg & (1<<(7-i))) + bits.push_back(true); + else + bits.push_back(false); + } + } + static uInt8 get_bits(BoolArray& bits) + { + uInt8 result = 0x0; + for(int i = 0; i < 8; ++i) + { + if(bits[i]) + result |= (1<<(7-i)); + else + return result &= ~(1<<(7-i)); + } + return result; + } + + /* Invert given input if it differs from its previous value */ + const string invIfChanged(int reg, int oldReg); + /** This is used when we want the debugger from a class that can't receive the debugger object in any other way. @@ -322,21 +352,13 @@ class Debugger : public DialogContainer void reloadROM(); - /** - Return a formatted string containing the contents of the specified - device. - */ - const string dumpRAM(); - const string dumpTIA(); - - // set a bunch of RAM locations at once + // Set a bunch of RAM locations at once const string setRAM(IntArray& args); void reset(); void autoLoadSymbols(string file); void clearAllBreakPoints(); - void formatFlags(BoolArray& b, char *out); PromptWidget *prompt() { return myPrompt; } void addLabel(string label, int address); @@ -344,8 +366,6 @@ class Debugger : public DialogContainer void saveState(int state); void loadState(int state); - const string invIfChanged(int reg, int oldReg); - private: typedef multimap ListFile; typedef ListFile::const_iterator ListIter; @@ -356,6 +376,7 @@ class Debugger : public DialogContainer DebuggerParser* myParser; CpuDebug* myCpuDebug; RamDebug* myRamDebug; + RiotDebug* myRiotDebug; TIADebug* myTiaDebug; TiaInfoWidget* myTiaInfo; diff --git a/stella/src/debugger/DebuggerParser.cxx b/stella/src/debugger/DebuggerParser.cxx index 44094a9b8..119f0b2f0 100644 --- a/stella/src/debugger/DebuggerParser.cxx +++ b/stella/src/debugger/DebuggerParser.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: DebuggerParser.cxx,v 1.104 2008-04-02 21:22:16 stephena Exp $ +// $Id: DebuggerParser.cxx,v 1.105 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #include @@ -23,6 +23,9 @@ #include "Dialog.hxx" #include "Debugger.hxx" #include "CpuDebug.hxx" +#include "RamDebug.hxx" +#include "RiotDebug.hxx" +#include "TIADebug.hxx" #include "DebuggerParser.hxx" #include "YaccParser.hxx" #include "M6502.hxx" @@ -1093,7 +1096,7 @@ void DebuggerParser::executePrint() void DebuggerParser::executeRam() { if(argCount == 0) - commandResult = debugger->dumpRAM(); + commandResult = debugger->ramDebug().toString(); else commandResult = debugger->setRAM(args); } @@ -1110,7 +1113,7 @@ void DebuggerParser::executeReset() // "riot" void DebuggerParser::executeRiot() { - commandResult = debugger->riotState(); + commandResult = debugger->riotDebug().toString(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1257,7 +1260,7 @@ void DebuggerParser::executeStep() // "tia" void DebuggerParser::executeTia() { - commandResult = debugger->dumpTIA(); + commandResult = debugger->tiaDebug().toString(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/debugger/DebuggerSystem.hxx b/stella/src/debugger/DebuggerSystem.hxx index c9149366b..2521bf58c 100644 --- a/stella/src/debugger/DebuggerSystem.hxx +++ b/stella/src/debugger/DebuggerSystem.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: DebuggerSystem.hxx,v 1.6 2008-02-06 13:45:20 stephena Exp $ +// $Id: DebuggerSystem.hxx,v 1.7 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #ifndef DEBUGGER_SYSTEM_HXX @@ -42,16 +42,20 @@ class DebuggerState class DebuggerSystem { public: - DebuggerSystem(Debugger* dbg, Console* console) { myDebugger = dbg; } + DebuggerSystem(Debugger& dbg, Console& console) : + myDebugger(dbg), myConsole(console), mySystem(console.system()) { } virtual ~DebuggerSystem() { } - virtual DebuggerState& getState() = 0; - virtual DebuggerState& getOldState() = 0; + virtual const DebuggerState& getState() = 0; + virtual const DebuggerState& getOldState() = 0; virtual void saveOldState() = 0; + virtual string toString() = 0; protected: - Debugger* myDebugger; + Debugger& myDebugger; + Console& myConsole; + System& mySystem; }; #endif diff --git a/stella/src/debugger/RamDebug.cxx b/stella/src/debugger/RamDebug.cxx index 9a19fd0df..730305588 100644 --- a/stella/src/debugger/RamDebug.cxx +++ b/stella/src/debugger/RamDebug.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: RamDebug.cxx,v 1.7 2008-02-06 13:45:20 stephena Exp $ +// $Id: RamDebug.cxx,v 1.8 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #include "Array.hxx" @@ -21,14 +21,13 @@ #include "RamDebug.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -RamDebug::RamDebug(Debugger* dbg, Console* console) - : DebuggerSystem(dbg, console), - mySystem(&(console->system())) +RamDebug::RamDebug(Debugger& dbg, Console& console) + : DebuggerSystem(dbg, console) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DebuggerState& RamDebug::getState() +const DebuggerState& RamDebug::getState() { myState.ram.clear(); for(int i=0; i<0x80; i++) @@ -49,12 +48,56 @@ void RamDebug::saveOldState() int RamDebug::read(int offset) { offset &= 0x7f; // there are only 128 bytes - return mySystem->peek(offset + 0x80); + return mySystem.peek(offset + 0x80); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RamDebug::write(int offset, int value) { offset &= 0x7f; // there are only 128 bytes - mySystem->poke(offset + 0x80, value); + mySystem.poke(offset + 0x80, value); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RamDebug::toString() +{ + string result; + char buf[128]; + int bytesPerLine; + int start = kRamStart, len = kRamSize; + + switch(myDebugger.parser().base()) + { + case kBASE_16: + case kBASE_10: + bytesPerLine = 0x10; + break; + + case kBASE_2: + bytesPerLine = 0x04; + break; + + case kBASE_DEFAULT: + default: + return DebuggerParser::red("invalid base, this is a BUG"); + } + + const RamState& state = (RamState&) getState(); + const RamState& oldstate = (RamState&) getOldState(); + for (uInt8 i = 0x00; i < len; i += bytesPerLine) + { + sprintf(buf, "%.2x: ", start+i); + result += buf; + + for (uInt8 j = 0; j < bytesPerLine; j++) + { + result += myDebugger.invIfChanged(state.ram[i+j], oldstate.ram[i+j]); + result += " "; + + if(j == 0x07) result += " "; + } + result += "\n"; + } + + return result; } diff --git a/stella/src/debugger/RamDebug.hxx b/stella/src/debugger/RamDebug.hxx index 2106be49c..59b55f419 100644 --- a/stella/src/debugger/RamDebug.hxx +++ b/stella/src/debugger/RamDebug.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: RamDebug.hxx,v 1.6 2008-02-06 13:45:20 stephena Exp $ +// $Id: RamDebug.hxx,v 1.7 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #ifndef RAM_DEBUG_HXX @@ -33,12 +33,13 @@ class RamState : public DebuggerState class RamDebug : public DebuggerSystem { public: - RamDebug(Debugger* dbg, Console* console); + RamDebug(Debugger& dbg, Console& console); - DebuggerState& getState(); - DebuggerState& getOldState() { return myOldState; } + const DebuggerState& getState(); + const DebuggerState& getOldState() { return myOldState; } void saveOldState(); + string toString(); int read(int offset); void write(int offset, int value); @@ -46,8 +47,6 @@ class RamDebug : public DebuggerSystem private: RamState myState; RamState myOldState; - - System* mySystem; }; #endif diff --git a/stella/src/debugger/RiotDebug.cxx b/stella/src/debugger/RiotDebug.cxx new file mode 100644 index 000000000..13edf3b36 --- /dev/null +++ b/stella/src/debugger/RiotDebug.cxx @@ -0,0 +1,281 @@ +//============================================================================ +// +// 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-2008 by Bradford W. Mott and the Stella team +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: RiotDebug.cxx,v 1.1 2008-04-19 21:11:52 stephena Exp $ +//============================================================================ + +#include + +#include "System.hxx" +#include "Debugger.hxx" + +#include "RiotDebug.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +RiotDebug::RiotDebug(Debugger& dbg, Console& console) + : DebuggerSystem(dbg, console) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const DebuggerState& RiotDebug::getState() +{ + // Port A & B registers + myState.SWCHA = swcha(); + myState.SWCHB = swchb(); + myState.SWACNT = swacnt(); + myState.SWBCNT = swbcnt(); + Debugger::set_bits(swcha(), myState.swchaBits); + Debugger::set_bits(swchb(), myState.swchbBits); + Debugger::set_bits(swacnt(), myState.swacntBits); + Debugger::set_bits(swbcnt(), myState.swbcntBits); + + // Timer registers + myState.TIM1T = tim1T(); + myState.TIM8T = tim8T(); + myState.TIM64T = tim64T(); + myState.TIM1024T = tim1024T(); + myState.INTIM = intim(); + myState.TIMINT = timint(); + myState.TIMCLKS = timClocks(); + + return myState; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RiotDebug::saveOldState() +{ + // Port A & B registers + myOldState.SWCHA = swcha(); + myOldState.SWCHB = swchb(); + myOldState.SWACNT = swacnt(); + myOldState.SWBCNT = swbcnt(); + Debugger::set_bits(swcha(), myOldState.swchaBits); + Debugger::set_bits(swchb(), myOldState.swchbBits); + Debugger::set_bits(swacnt(), myOldState.swacntBits); + Debugger::set_bits(swbcnt(), myOldState.swbcntBits); + + // Timer registers + myOldState.TIM1T = tim1T(); + myOldState.TIM8T = tim8T(); + myOldState.TIM64T = tim64T(); + myOldState.TIM1024T = tim1024T(); + myOldState.INTIM = intim(); + myOldState.TIMINT = timint(); + myOldState.TIMCLKS = timClocks(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::swcha(int newVal) +{ + if(newVal > -1) + mySystem.poke(0x280, newVal); + + return mySystem.peek(0x280); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::swchb(int newVal) +{ +// TODO: directly access the Switches class to change this +// if(newVal > -1) +// mySystem.poke(0x282, newVal); + + return mySystem.peek(0x282); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::swacnt(int newVal) +{ + if(newVal > -1) + mySystem.poke(0x281, newVal); + + return mySystem.peek(0x281); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::swbcnt(int newVal) +{ + // This is read-only on a real system; it makes no sense to change it + return mySystem.peek(0x283); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::tim1T(int newVal) +{ + if(newVal > -1) + mySystem.poke(0x294, newVal); + + return mySystem.m6532().myOutTimer[0]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::tim8T(int newVal) +{ + if(newVal > -1) + mySystem.poke(0x295, newVal); + + return mySystem.m6532().myOutTimer[1]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::tim64T(int newVal) +{ + if(newVal > -1) + mySystem.poke(0x296, newVal); + + return mySystem.m6532().myOutTimer[2]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::tim1024T(int newVal) +{ + if(newVal > -1) + mySystem.poke(0x297, newVal); + + return mySystem.m6532().myOutTimer[3]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::intim() +{ + return mySystem.peek(0x284); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotDebug::timint() +{ + return mySystem.peek(0x285); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Int32 RiotDebug::timClocks() +{ + return mySystem.m6532().timerClocks(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotDebug::dirP0String() +{ + uInt8 reg = swcha(); + ostringstream buf; + buf << (reg & 0x80 ? "" : "right ") + << (reg & 0x40 ? "" : "left ") + << (reg & 0x20 ? "" : "left ") + << (reg & 0x10 ? "" : "left ") + << (reg & 0xf0 == 0xf0 ? "(no directions) " : ""); + return buf.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotDebug::dirP1String() +{ + uInt8 reg = swcha(); + ostringstream buf; + buf << (reg & 0x08 ? "" : "right ") + << (reg & 0x04 ? "" : "left ") + << (reg & 0x02 ? "" : "left ") + << (reg & 0x01 ? "" : "left ") + << (reg & 0x0f == 0x0f ? "(no directions) " : ""); + return buf.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotDebug::diffP0String() +{ + return (swchb() & 0x40) ? "hard/A" : "easy/B"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotDebug::diffP1String() +{ + return (swchb() & 0x80) ? "hard/A" : "easy/B"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotDebug::tvTypeString() +{ + return (swchb() & 0x8) ? "Color" : "B&W"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotDebug::switchesString() +{ + ostringstream buf; + buf << (swchb() & 0x2 ? "-" : "+") << "select " << + (swchb() & 0x1 ? "-" : "+") << "reset"; + return buf.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotDebug::toString() +{ + // TODO: keyboard controllers? + + const RiotState& state = (RiotState&) getState(); + const RiotState& oldstate = (RiotState&) getOldState(); + string ret; + + ret += myDebugger.valueToString(0x280) + "/" + + myDebugger.equates().getFormatted(0x280, 2) + "=" + + myDebugger.invIfChanged(state.SWCHA, oldstate.SWCHA) + " "; + ret += myDebugger.valueToString(0x281) + "/" + + myDebugger.equates().getFormatted(0x281, 2) + "=" + + myDebugger.invIfChanged(state.SWCHB, oldstate.SWCHB) + " "; + ret += myDebugger.valueToString(0x282) + "/" + + myDebugger.equates().getFormatted(0x282, 2) + "=" + + myDebugger.invIfChanged(state.SWACNT, oldstate.SWACNT) + " "; + ret += myDebugger.valueToString(0x283) + "/" + + myDebugger.equates().getFormatted(0x283, 2) + "=" + + myDebugger.invIfChanged(state.SWBCNT, oldstate.SWBCNT) + " "; + ret += "\n"; + + // These are squirrely: some symbol files will define these as + // 0x284-0x287. Doesn't actually matter, these registers repeat + // every 16 bytes. + ret += myDebugger.valueToString(0x294) + "/TIM1T=" + + myDebugger.invIfChanged(state.TIM1T, oldstate.TIM1T) + " "; + ret += myDebugger.valueToString(0x295) + "/TIM8T=" + + myDebugger.invIfChanged(state.TIM8T, oldstate.TIM8T) + " "; + ret += myDebugger.valueToString(0x296) + "/TIM64T=" + + myDebugger.invIfChanged(state.TIM64T, oldstate.TIM64T) + " "; + ret += myDebugger.valueToString(0x297) + "/TIM1024T=" + + myDebugger.invIfChanged(state.TIM1024T, oldstate.TIM1024T) + " "; + ret += "\n"; + + ret += myDebugger.valueToString(0x284) + "/INTIM=" + + myDebugger.invIfChanged(state.INTIM, oldstate.INTIM) + " "; + ret += myDebugger.valueToString(0x285) + "/TIMINT=" + + myDebugger.invIfChanged(state.TIMINT, oldstate.TIMINT) + " "; + ret += "Timer_Clocks=" + + myDebugger.invIfChanged(state.TIMCLKS, oldstate.TIMCLKS) + " "; + ret += "\n"; + + ret += "Left/P0diff: " + diffP0String() + " Right/P1diff: " + diffP0String(); + ret += "\n"; + + ret += "TVType: " + tvTypeString() + " Switches: " + switchesString(); + ret += "\n"; + + // Yes, the fire buttons are in the TIA, but we might as well + // show them here for convenience. + ret += "Left/P0 stick: " + dirP0String(); + ret += (mySystem.peek(0x03c) & 0x80) ? "" : "(button) "; + ret += "\n"; + ret += "Right/P1 stick: " + dirP1String(); + ret += (mySystem.peek(0x03d) & 0x80) ? "" : "(button) "; + + return ret; +} diff --git a/stella/src/debugger/RiotDebug.hxx b/stella/src/debugger/RiotDebug.hxx new file mode 100644 index 000000000..042c0e6ab --- /dev/null +++ b/stella/src/debugger/RiotDebug.hxx @@ -0,0 +1,82 @@ +//============================================================================ +// +// 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-2008 by Bradford W. Mott and the Stella team +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: RiotDebug.hxx,v 1.1 2008-04-19 21:11:52 stephena Exp $ +//============================================================================ + +#ifndef RIOT_DEBUG_HXX +#define RIOT_DEBUG_HXX + +class Debugger; +class RiotDebug; + +#include "Array.hxx" +#include "DebuggerSystem.hxx" + +class RiotState : public DebuggerState +{ + public: + uInt8 SWCHA, SWCHB, SWACNT, SWBCNT; + BoolArray swchaBits; + BoolArray swchbBits; + BoolArray swacntBits; + BoolArray swbcntBits; + + uInt8 TIM1T, TIM8T, TIM64T, TIM1024T, INTIM, TIMINT; + Int32 TIMCLKS; +}; + +class RiotDebug : public DebuggerSystem +{ + public: + RiotDebug(Debugger& dbg, Console& console); + + const DebuggerState& getState(); + const DebuggerState& getOldState() { return myOldState; } + + void saveOldState(); + string toString(); + + /* Port A and B registers */ + uInt8 swcha(int newVal = -1); + uInt8 swchb(int newVal = -1); + uInt8 swacnt(int newVal = -1); + uInt8 swbcnt(int newVal = -1); + + /* Timer registers & associated clock */ + uInt8 tim1T(int newVal = -1); + uInt8 tim8T(int newVal = -1); + uInt8 tim64T(int newVal = -1); + uInt8 tim1024T(int newVal = -1); + uInt8 intim(); + uInt8 timint(); + Int32 timClocks(); + + /* Port A description */ + string dirP0String(); + string dirP1String(); + + /* Port B description */ + string diffP0String(); + string diffP1String(); + string tvTypeString(); + string switchesString(); + + private: + RiotState myState; + RiotState myOldState; +}; + +#endif diff --git a/stella/src/debugger/TIADebug.cxx b/stella/src/debugger/TIADebug.cxx index 11ed57195..cacec82e1 100644 --- a/stella/src/debugger/TIADebug.cxx +++ b/stella/src/debugger/TIADebug.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: TIADebug.cxx,v 1.26 2008-02-06 13:45:20 stephena Exp $ +// $Id: TIADebug.cxx,v 1.27 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #include "System.hxx" @@ -22,10 +22,9 @@ #include "TIADebug.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TIADebug::TIADebug(Debugger* dbg, Console* console) +TIADebug::TIADebug(Debugger& dbg, Console& console) : DebuggerSystem(dbg, console), - mySystem(&console->system()), - myTIA((TIA*)&console->mediaSource()) + myTIA((TIA&)console.mediaSource()) { nusizStrings[0] = "size=8 copy=1"; nusizStrings[1] = "size=8 copy=2 spac=8"; @@ -38,11 +37,11 @@ TIADebug::TIADebug(Debugger* dbg, Console* console) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DebuggerState& TIADebug::getState() +const DebuggerState& TIADebug::getState() { myState.ram.clear(); for(int i = 0; i < 0x010; ++i) - myState.ram.push_back(myTIA->peek(i)); + myState.ram.push_back(myTIA.peek(i)); // Color registers myState.coluRegs.clear(); @@ -103,7 +102,7 @@ void TIADebug::saveOldState() { myOldState.ram.clear(); for(int i = 0; i < 0x010; ++i) - myOldState.ram.push_back(myTIA->peek(i)); + myOldState.ram.push_back(myTIA.peek(i)); // Color registers myOldState.coluRegs.clear(); @@ -157,7 +156,7 @@ void TIADebug::saveOldState() myOldState.aud.push_back(audV1()); } -/* the set methods now use mySystem->poke(). This will save us the +/* the set methods now use mySystem.poke(). This will save us the trouble of masking the values here, since TIA::poke() will do it for us. @@ -187,90 +186,90 @@ void TIADebug::saveOldState() bool TIADebug::vdelP0(int newVal) { if(newVal > -1) - mySystem->poke(VDELP0, ((bool)newVal)); + mySystem.poke(VDELP0, ((bool)newVal)); - return myTIA->myVDELP0; + return myTIA.myVDELP0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::vdelP1(int newVal) { if(newVal > -1) - mySystem->poke(VDELP1, ((bool)newVal)); + mySystem.poke(VDELP1, ((bool)newVal)); - return myTIA->myVDELP1; + return myTIA.myVDELP1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::vdelBL(int newVal) { if(newVal > -1) - mySystem->poke(VDELBL, ((bool)newVal)); + mySystem.poke(VDELBL, ((bool)newVal)); - return myTIA->myVDELBL; + return myTIA.myVDELBL; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::enaM0(int newVal) { if(newVal > -1) - mySystem->poke(ENAM0, ((bool)newVal) << 1); + mySystem.poke(ENAM0, ((bool)newVal) << 1); - return myTIA->myENAM0; + return myTIA.myENAM0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::enaM1(int newVal) { if(newVal > -1) - mySystem->poke(ENAM1, ((bool)newVal) << 1); + mySystem.poke(ENAM1, ((bool)newVal) << 1); - return myTIA->myENAM1; + return myTIA.myENAM1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::enaBL(int newVal) { if(newVal > -1) - mySystem->poke(ENABL, ((bool)newVal) << 1); + mySystem.poke(ENABL, ((bool)newVal) << 1); - return myTIA->myENABL; + return myTIA.myENABL; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::resMP0(int newVal) { if(newVal > -1) - mySystem->poke(RESMP0, ((bool)newVal) << 1); + mySystem.poke(RESMP0, ((bool)newVal) << 1); - return myTIA->myRESMP0; + return myTIA.myRESMP0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::resMP1(int newVal) { if(newVal > -1) - mySystem->poke(RESMP1, ((bool)newVal) << 1); + mySystem.poke(RESMP1, ((bool)newVal) << 1); - return myTIA->myRESMP1; + return myTIA.myRESMP1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::refP0(int newVal) { if(newVal > -1) - mySystem->poke(REFP0, ((bool)newVal) << 3); + mySystem.poke(REFP0, ((bool)newVal) << 3); - return myTIA->myREFP0; + return myTIA.myREFP0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::refP1(int newVal) { if(newVal > -1) - mySystem->poke(REFP1, ((bool)newVal) << 3); + mySystem.poke(REFP1, ((bool)newVal) << 3); - return myTIA->myREFP1; + return myTIA.myREFP1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -278,15 +277,15 @@ bool TIADebug::refPF(int newVal) { if(newVal > -1) { - int tmp = myTIA->myCTRLPF; + int tmp = myTIA.myCTRLPF; if(newVal) tmp |= 0x01; else tmp &= ~0x01; - mySystem->poke(CTRLPF, tmp); + mySystem.poke(CTRLPF, tmp); } - return myTIA->myCTRLPF & 0x01; + return myTIA.myCTRLPF & 0x01; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -294,15 +293,15 @@ bool TIADebug::scorePF(int newVal) { if(newVal > -1) { - int tmp = myTIA->myCTRLPF; + int tmp = myTIA.myCTRLPF; if(newVal) tmp |= 0x02; else tmp &= ~0x02; - mySystem->poke(CTRLPF, tmp); + mySystem.poke(CTRLPF, tmp); } - return myTIA->myCTRLPF & 0x02; + return myTIA.myCTRLPF & 0x02; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -310,15 +309,15 @@ bool TIADebug::priorityPF(int newVal) { if(newVal > -1) { - int tmp = myTIA->myCTRLPF; + int tmp = myTIA.myCTRLPF; if(newVal) tmp |= 0x04; else tmp &= ~0x04; - mySystem->poke(CTRLPF, tmp); + mySystem.poke(CTRLPF, tmp); } - return myTIA->myCTRLPF & 0x04; + return myTIA.myCTRLPF & 0x04; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -329,147 +328,147 @@ bool TIADebug::collision(int collID, int newVal) if(newVal > -1) { if(newVal) - myTIA->myCollision |= mask; + myTIA.myCollision |= mask; else - myTIA->myCollision &= ~mask; + myTIA.myCollision &= ~mask; } - return myTIA->myCollision & mask; + return myTIA.myCollision & mask; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::audC0(int newVal) { if(newVal > -1) - mySystem->poke(AUDC0, newVal); + mySystem.poke(AUDC0, newVal); - return myTIA->myAUDC0; + return myTIA.myAUDC0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::audC1(int newVal) { if(newVal > -1) - mySystem->poke(AUDC1, newVal); + mySystem.poke(AUDC1, newVal); - return myTIA->myAUDC1; + return myTIA.myAUDC1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::audV0(int newVal) { if(newVal > -1) - mySystem->poke(AUDV0, newVal); + mySystem.poke(AUDV0, newVal); - return myTIA->myAUDV0; + return myTIA.myAUDV0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::audV1(int newVal) { if(newVal > -1) - mySystem->poke(AUDV1, newVal); + mySystem.poke(AUDV1, newVal); - return myTIA->myAUDV1; + return myTIA.myAUDV1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::audF0(int newVal) { if(newVal > -1) - mySystem->poke(AUDF0, newVal); + mySystem.poke(AUDF0, newVal); - return myTIA->myAUDF0; + return myTIA.myAUDF0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::audF1(int newVal) { if(newVal > -1) - mySystem->poke(AUDF1, newVal); + mySystem.poke(AUDF1, newVal); - return myTIA->myAUDF1; + return myTIA.myAUDF1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::pf0(int newVal) { if(newVal > -1) - mySystem->poke(PF0, newVal << 4); + mySystem.poke(PF0, newVal << 4); - return myTIA->myPF & 0x0f; + return myTIA.myPF & 0x0f; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::pf1(int newVal) { if(newVal > -1) - mySystem->poke(PF1, newVal); + mySystem.poke(PF1, newVal); - return (myTIA->myPF & 0xff0) >> 4; + return (myTIA.myPF & 0xff0) >> 4; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::pf2(int newVal) { if(newVal > -1) - mySystem->poke(PF2, newVal); + mySystem.poke(PF2, newVal); - return (myTIA->myPF & 0xff000) >> 12; + return (myTIA.myPF & 0xff000) >> 12; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::coluP0(int newVal) { if(newVal > -1) - mySystem->poke(COLUP0, newVal); + mySystem.poke(COLUP0, newVal); - return myTIA->myCOLUP0 & 0xff; + return myTIA.myCOLUP0 & 0xff; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::coluP1(int newVal) { if(newVal > -1) - mySystem->poke(COLUP1, newVal); + mySystem.poke(COLUP1, newVal); - return myTIA->myCOLUP1 & 0xff; + return myTIA.myCOLUP1 & 0xff; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::coluPF(int newVal) { if(newVal > -1) - mySystem->poke(COLUPF, newVal); + mySystem.poke(COLUPF, newVal); - return myTIA->myCOLUPF & 0xff; + return myTIA.myCOLUPF & 0xff; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::coluBK(int newVal) { if(newVal > -1) - mySystem->poke(COLUBK, newVal); + mySystem.poke(COLUBK, newVal); - return myTIA->myCOLUBK & 0xff; + return myTIA.myCOLUBK & 0xff; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::nusiz0(int newVal) { if(newVal > -1) - mySystem->poke(NUSIZ0, newVal); + mySystem.poke(NUSIZ0, newVal); - return myTIA->myNUSIZ0; + return myTIA.myNUSIZ0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::nusiz1(int newVal) { if(newVal > -1) - mySystem->poke(NUSIZ1, newVal); + mySystem.poke(NUSIZ1, newVal); - return myTIA->myNUSIZ1; + return myTIA.myNUSIZ1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -477,12 +476,12 @@ uInt8 TIADebug::nusizP0(int newVal) { if(newVal > -1) { - uInt8 tmp = myTIA->myNUSIZ0 & ~0x07; + uInt8 tmp = myTIA.myNUSIZ0 & ~0x07; tmp |= (newVal & 0x07); - mySystem->poke(NUSIZ0, tmp); + mySystem.poke(NUSIZ0, tmp); } - return myTIA->myNUSIZ0 & 0x07; + return myTIA.myNUSIZ0 & 0x07; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -490,12 +489,12 @@ uInt8 TIADebug::nusizP1(int newVal) { if(newVal > -1) { - uInt8 tmp = myTIA->myNUSIZ1 & ~0x07; + uInt8 tmp = myTIA.myNUSIZ1 & ~0x07; tmp |= newVal & 0x07; - mySystem->poke(NUSIZ1, tmp); + mySystem.poke(NUSIZ1, tmp); } - return myTIA->myNUSIZ1 & 0x07; + return myTIA.myNUSIZ1 & 0x07; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -503,12 +502,12 @@ uInt8 TIADebug::nusizM0(int newVal) { if(newVal > -1) { - uInt8 tmp = myTIA->myNUSIZ0 & ~0x30; + uInt8 tmp = myTIA.myNUSIZ0 & ~0x30; tmp |= (newVal & 0x04) << 4; - mySystem->poke(NUSIZ0, tmp); + mySystem.poke(NUSIZ0, tmp); } - return (myTIA->myNUSIZ0 & 0x30) >> 4; + return (myTIA.myNUSIZ0 & 0x30) >> 4; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -516,46 +515,46 @@ uInt8 TIADebug::nusizM1(int newVal) { if(newVal > -1) { - uInt8 tmp = myTIA->myNUSIZ1 & ~0x30; + uInt8 tmp = myTIA.myNUSIZ1 & ~0x30; tmp |= (newVal & 0x04) << 4; - mySystem->poke(NUSIZ1, tmp); + mySystem.poke(NUSIZ1, tmp); } - return (myTIA->myNUSIZ1 & 0x30) >> 4; + return (myTIA.myNUSIZ1 & 0x30) >> 4; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::grP0(int newVal) { if(newVal > -1) - mySystem->poke(GRP0, newVal); + mySystem.poke(GRP0, newVal); - return myTIA->myGRP0; + return myTIA.myGRP0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::grP1(int newVal) { if(newVal > -1) - mySystem->poke(GRP1, newVal); + mySystem.poke(GRP1, newVal); - return myTIA->myGRP1; + return myTIA.myGRP1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::posP0(int newVal) { if(newVal > -1) - myTIA->myPOSP0 = newVal; - return myTIA->myPOSP0; + myTIA.myPOSP0 = newVal; + return myTIA.myPOSP0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::posP1(int newVal) { if(newVal > -1) - myTIA->myPOSP1 = newVal; - return myTIA->myPOSP1; + myTIA.myPOSP1 = newVal; + return myTIA.myPOSP1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -563,9 +562,9 @@ uInt8 TIADebug::posM0(int newVal) { /* FIXME if(newVal > -1) - mySystem->poke(???, newVal); + mySystem.poke(???, newVal); */ - return myTIA->myPOSM0; + return myTIA.myPOSM0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -573,9 +572,9 @@ uInt8 TIADebug::posM1(int newVal) { /* FIXME if(newVal > -1) - mySystem->poke(???, newVal); + mySystem.poke(???, newVal); */ - return myTIA->myPOSM1; + return myTIA.myPOSM1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -583,18 +582,18 @@ uInt8 TIADebug::posBL(int newVal) { /* FIXME if(newVal > -1) - mySystem->poke(???, newVal); + mySystem.poke(???, newVal); */ - return myTIA->myPOSBL; + return myTIA.myPOSBL; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::ctrlPF(int newVal) { if(newVal > -1) - mySystem->poke(CTRLPF, newVal); + mySystem.poke(CTRLPF, newVal); - return myTIA->myCTRLPF; + return myTIA.myCTRLPF; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -602,87 +601,87 @@ uInt8 TIADebug::sizeBL(int newVal) { if(newVal > -1) { - uInt8 tmp = myTIA->myCTRLPF & ~0x30; + uInt8 tmp = myTIA.myCTRLPF & ~0x30; tmp |= (newVal & 0x04) << 4; - mySystem->poke(CTRLPF, tmp); + mySystem.poke(CTRLPF, tmp); } - return (myTIA->myCTRLPF & 0x30) >> 4; + return (myTIA.myCTRLPF & 0x30) >> 4; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::hmP0(int newVal) { if(newVal > -1) - mySystem->poke(HMP0, newVal << 4); + mySystem.poke(HMP0, newVal << 4); - return myTIA->myHMP0; + return myTIA.myHMP0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::hmP1(int newVal) { if(newVal > -1) - mySystem->poke(HMP1, newVal << 4); + mySystem.poke(HMP1, newVal << 4); - return myTIA->myHMP1; + return myTIA.myHMP1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::hmM0(int newVal) { if(newVal > -1) - mySystem->poke(HMM0, newVal << 4); + mySystem.poke(HMM0, newVal << 4); - return myTIA->myHMM0; + return myTIA.myHMM0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::hmM1(int newVal) { if(newVal > -1) - mySystem->poke(HMM1, newVal << 4); + mySystem.poke(HMM1, newVal << 4); - return myTIA->myHMM1; + return myTIA.myHMM1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 TIADebug::hmBL(int newVal) { if(newVal > -1) - mySystem->poke(HMBL, newVal << 4); + mySystem.poke(HMBL, newVal << 4); - return myTIA->myHMBL; + return myTIA.myHMBL; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int TIADebug::frameCount() { - return myTIA->myFrameCounter; + return myTIA.myFrameCounter; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int TIADebug::scanlines() { - return myTIA->scanlines(); + return myTIA.scanlines(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int TIADebug::clocksThisLine() { - return myTIA->clocksThisLine(); + return myTIA.clocksThisLine(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::vsync() { - return (myTIA->myVSYNC & 2) == 2; + return (myTIA.myVSYNC & 2) == 2; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIADebug::vblank() { - return (myTIA->myVBLANK & 2) == 2; + return (myTIA.myVBLANK & 2) == 2; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -713,7 +712,7 @@ const string audFreq(uInt8 div) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const string booleanWithLabel(string label, bool value) +string TIADebug::booleanWithLabel(string label, bool value) { char buf[64]; string ret; @@ -733,20 +732,33 @@ const string booleanWithLabel(string label, bool value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string TIADebug::state() +string TIADebug::toString() { string ret; + char buf[128]; + + sprintf(buf, "%.2x: ", 0); + ret += buf; + for (uInt8 j = 0; j < 0x010; j++) + { + sprintf(buf, "%.2x ", mySystem.peek(j)); + ret += buf; + + if(j == 0x07) ret += "- "; + } + + ret += "\n"; // TODO: inverse video for changed regs. Core needs to track this. // TODO: strobes? WSYNC RSYNC RESP0/1 RESM0/1 RESBL HMOVE HMCLR CXCLR - TiaState state = (TiaState&) getState(); -// FIXME - change tracking TiaState oldstate = (TiaState&) getOldState(); + const TiaState& state = (TiaState&) getState(); +// const TiaState& oldstate = (TiaState&) getOldState(); // build up output, then return it. ret += "scanline "; - ret += myDebugger->valueToString(myTIA->scanlines()); + ret += myDebugger.valueToString(myTIA.scanlines()); ret += " "; ret += booleanWithLabel("vsync", vsync()); @@ -755,38 +767,38 @@ string TIADebug::state() ret += booleanWithLabel("vblank", vblank()); ret += "\n"; - ret += booleanWithLabel("inpt0", myTIA->peek(0x08) & 0x80); + ret += booleanWithLabel("inpt0", myTIA.peek(0x08) & 0x80); ret += " "; - ret += booleanWithLabel("inpt1", myTIA->peek(0x09) & 0x80); + ret += booleanWithLabel("inpt1", myTIA.peek(0x09) & 0x80); ret += " "; - ret += booleanWithLabel("inpt2", myTIA->peek(0x0a) & 0x80); + ret += booleanWithLabel("inpt2", myTIA.peek(0x0a) & 0x80); ret += " "; - ret += booleanWithLabel("inpt3", myTIA->peek(0x0b) & 0x80); + ret += booleanWithLabel("inpt3", myTIA.peek(0x0b) & 0x80); ret += " "; - ret += booleanWithLabel("inpt4", myTIA->peek(0x0c) & 0x80); + ret += booleanWithLabel("inpt4", myTIA.peek(0x0c) & 0x80); ret += " "; - ret += booleanWithLabel("inpt5", myTIA->peek(0x0d) & 0x80); + ret += booleanWithLabel("inpt5", myTIA.peek(0x0d) & 0x80); ret += " "; - ret += booleanWithLabel("dump_gnd_0123", myTIA->myDumpEnabled); + ret += booleanWithLabel("dump_gnd_0123", myTIA.myDumpEnabled); ret += "\n"; ret += "COLUP0: "; - ret += myDebugger->valueToString(state.coluRegs[0]); + ret += myDebugger.valueToString(state.coluRegs[0]); ret += "/"; ret += colorSwatch(state.coluRegs[0]); ret += "COLUP1: "; - ret += myDebugger->valueToString(state.coluRegs[1]); + ret += myDebugger.valueToString(state.coluRegs[1]); ret += "/"; ret += colorSwatch(state.coluRegs[1]); ret += "COLUPF: "; - ret += myDebugger->valueToString(state.coluRegs[2]); + ret += myDebugger.valueToString(state.coluRegs[2]); ret += "/"; ret += colorSwatch(state.coluRegs[2]); ret += "COLUBK: "; - ret += myDebugger->valueToString(state.coluRegs[3]); + ret += myDebugger.valueToString(state.coluRegs[3]); ret += "/"; ret += colorSwatch(state.coluRegs[3]); @@ -795,11 +807,11 @@ string TIADebug::state() ret += "P0: GR="; ret += Debugger::to_bin_8(state.gr[P0]); ret += "/"; - ret += myDebugger->valueToString(state.gr[P0]); + ret += myDebugger.valueToString(state.gr[P0]); ret += " pos="; - ret += myDebugger->valueToString(state.pos[P0]); + ret += myDebugger.valueToString(state.pos[P0]); ret += " HM="; - ret += myDebugger->valueToString(state.hm[P0]); + ret += myDebugger.valueToString(state.hm[P0]); ret += " "; ret += nusizP0String(); ret += " "; @@ -811,11 +823,11 @@ string TIADebug::state() ret += "P1: GR="; ret += Debugger::to_bin_8(state.gr[P1]); ret += "/"; - ret += myDebugger->valueToString(state.gr[P1]); + ret += myDebugger.valueToString(state.gr[P1]); ret += " pos="; - ret += myDebugger->valueToString(state.pos[P1]); + ret += myDebugger.valueToString(state.pos[P1]); ret += " HM="; - ret += myDebugger->valueToString(state.hm[P1]); + ret += myDebugger.valueToString(state.hm[P1]); ret += " "; ret += nusizP1String(); ret += " "; @@ -825,37 +837,37 @@ string TIADebug::state() ret += "\n"; ret += "M0: "; - ret += (myTIA->myENAM0 ? " ENABLED" : "disabled"); + ret += (myTIA.myENAM0 ? " ENABLED" : "disabled"); ret += " pos="; - ret += myDebugger->valueToString(state.pos[M0]); + ret += myDebugger.valueToString(state.pos[M0]); ret += " HM="; - ret += myDebugger->valueToString(state.hm[M0]); + ret += myDebugger.valueToString(state.hm[M0]); ret += " size="; - ret += myDebugger->valueToString(state.size[M0]); + ret += myDebugger.valueToString(state.size[M0]); ret += " "; ret += booleanWithLabel("reset", resMP0()); ret += "\n"; ret += "M1: "; - ret += (myTIA->myENAM1 ? " ENABLED" : "disabled"); + ret += (myTIA.myENAM1 ? " ENABLED" : "disabled"); ret += " pos="; - ret += myDebugger->valueToString(state.pos[M1]); + ret += myDebugger.valueToString(state.pos[M1]); ret += " HM="; - ret += myDebugger->valueToString(state.hm[M1]); + ret += myDebugger.valueToString(state.hm[M1]); ret += " size="; - ret += myDebugger->valueToString(state.size[M1]); + ret += myDebugger.valueToString(state.size[M1]); ret += " "; ret += booleanWithLabel("reset", resMP1()); ret += "\n"; ret += "BL: "; - ret += (myTIA->myENABL ? " ENABLED" : "disabled"); + ret += (myTIA.myENABL ? " ENABLED" : "disabled"); ret += " pos="; - ret += myDebugger->valueToString(state.pos[BL]); + ret += myDebugger.valueToString(state.pos[BL]); ret += " HM="; - ret += myDebugger->valueToString(state.hm[BL]); + ret += myDebugger.valueToString(state.hm[BL]); ret += " size="; - ret += myDebugger->valueToString(state.size[BL]); + ret += myDebugger.valueToString(state.size[BL]); ret += " "; ret += booleanWithLabel("delay", vdelBL()); ret += "\n"; @@ -863,15 +875,15 @@ string TIADebug::state() ret += "PF0: "; ret += Debugger::to_bin_8(state.pf[0]); ret += "/"; - ret += myDebugger->valueToString(state.pf[0]); + ret += myDebugger.valueToString(state.pf[0]); ret += " PF1: "; ret += Debugger::to_bin_8(state.pf[1]); ret += "/"; - ret += myDebugger->valueToString(state.pf[1]); + ret += myDebugger.valueToString(state.pf[1]); ret += " PF2: "; ret += Debugger::to_bin_8(state.pf[2]); ret += "/"; - ret += myDebugger->valueToString(state.pf[2]); + ret += myDebugger.valueToString(state.pf[2]); ret += "\n "; ret += booleanWithLabel("reflect", refPF()); ret += " "; @@ -900,31 +912,31 @@ string TIADebug::state() ret += "\n"; ret += "AUDF0: "; - ret += myDebugger->valueToString(myTIA->myAUDF0); + ret += myDebugger.valueToString(myTIA.myAUDF0); ret += "/"; - ret += audFreq(myTIA->myAUDF0); + ret += audFreq(myTIA.myAUDF0); ret += " "; ret += "AUDC0: "; - ret += myDebugger->valueToString(myTIA->myAUDC0); + ret += myDebugger.valueToString(myTIA.myAUDC0); ret += " "; ret += "AUDV0: "; - ret += myDebugger->valueToString(myTIA->myAUDV0); + ret += myDebugger.valueToString(myTIA.myAUDV0); ret += "\n"; ret += "AUDF1: "; - ret += myDebugger->valueToString(myTIA->myAUDF1); + ret += myDebugger.valueToString(myTIA.myAUDF1); ret += "/"; - ret += audFreq(myTIA->myAUDF1); + ret += audFreq(myTIA.myAUDF1); ret += " "; ret += "AUDC1: "; - ret += myDebugger->valueToString(myTIA->myAUDC1); + ret += myDebugger.valueToString(myTIA.myAUDC1); ret += " "; ret += "AUDV1: "; - ret += myDebugger->valueToString(myTIA->myAUDV1); + ret += myDebugger.valueToString(myTIA.myAUDV1); //ret += "\n"; // note: last "ret +=" line should not contain \n, caller will add. diff --git a/stella/src/debugger/TIADebug.hxx b/stella/src/debugger/TIADebug.hxx index 26199417c..6ca1aed2f 100644 --- a/stella/src/debugger/TIADebug.hxx +++ b/stella/src/debugger/TIADebug.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: TIADebug.hxx,v 1.22 2008-02-06 13:45:20 stephena Exp $ +// $Id: TIADebug.hxx,v 1.23 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #ifndef TIA_DEBUG_HXX @@ -102,12 +102,13 @@ class TiaState : public DebuggerState class TIADebug : public DebuggerSystem { public: - TIADebug(Debugger* dbg, Console* console); + TIADebug(Debugger& dbg, Console& console); - DebuggerState& getState(); - DebuggerState& getOldState() { return myOldState; } + const DebuggerState& getState(); + const DebuggerState& getOldState() { return myOldState; } void saveOldState(); + string toString(); /* TIA byte (or part of a byte) registers */ uInt8 nusiz0(int newVal = -1); @@ -187,16 +188,16 @@ class TIADebug : public DebuggerSystem bool collM0_M1(int newVal = -1) { return collision(14, newVal); } /* TIA strobe registers */ - void strobeWsync() { mySystem->poke(WSYNC, 0); } - void strobeRsync() { mySystem->poke(RSYNC, 0); } // not emulated! - void strobeResP0() { mySystem->poke(RESP0, 0); } - void strobeResP1() { mySystem->poke(RESP1, 0); } - void strobeResM0() { mySystem->poke(RESM0, 0); } - void strobeResM1() { mySystem->poke(RESM1, 0); } - void strobeResBL() { mySystem->poke(RESBL, 0); } - void strobeHmove() { mySystem->poke(HMOVE, 0); } - void strobeHmclr() { mySystem->poke(HMCLR, 0); } - void strobeCxclr() { mySystem->poke(CXCLR, 0); } + void strobeWsync() { mySystem.poke(WSYNC, 0); } + void strobeRsync() { mySystem.poke(RSYNC, 0); } // not emulated! + void strobeResP0() { mySystem.poke(RESP0, 0); } + void strobeResP1() { mySystem.poke(RESP1, 0); } + void strobeResM0() { mySystem.poke(RESM0, 0); } + void strobeResM1() { mySystem.poke(RESM1, 0); } + void strobeResBL() { mySystem.poke(RESBL, 0); } + void strobeHmove() { mySystem.poke(HMOVE, 0); } + void strobeHmclr() { mySystem.poke(HMCLR, 0); } + void strobeCxclr() { mySystem.poke(CXCLR, 0); } /* read-only internal TIA state */ int scanlines(); @@ -204,7 +205,6 @@ class TIADebug : public DebuggerSystem int clocksThisLine(); bool vsync(); bool vblank(); - string state(); private: /** Display a color patch for color at given index in the palette */ @@ -213,12 +213,13 @@ class TIADebug : public DebuggerSystem /** Get/set specific bits in the collision register (used by collXX_XX) */ bool collision(int collID, int newVal); + string booleanWithLabel(string label, bool value); + private: TiaState myState; TiaState myOldState; - System* mySystem; - TIA* myTIA; + TIA& myTIA; string nusizStrings[8]; }; diff --git a/stella/src/debugger/gui/TiaWidget.cxx b/stella/src/debugger/gui/TiaWidget.cxx index 110edeb6d..2e703bb43 100644 --- a/stella/src/debugger/gui/TiaWidget.cxx +++ b/stella/src/debugger/gui/TiaWidget.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: TiaWidget.cxx,v 1.10 2008-03-23 17:43:22 stephena Exp $ +// $Id: TiaWidget.cxx,v 1.11 2008-04-19 21:11:52 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -272,17 +272,6 @@ TiaWidget::TiaWidget(GuiObject* boss, const GUI::Font& font, "CxClr", kCxclrCmd); b->setTarget(this); - // Set the strings to be used in the grPx registers - // We only do this once because it's the state that changes, not the strings - const char* offstr[] = { "0", "0", "0", "0", "0", "0", "0", "0" }; - const char* onstr[] = { "1", "1", "1", "1", "1", "1", "1", "1" }; - StringList off, on; - for(int i = 0; i < 8; ++i) - { - off.push_back(offstr[i]); - on.push_back(onstr[i]); - } - //////////////////////////// // P0 register info //////////////////////////// @@ -931,8 +920,8 @@ void TiaWidget::fillGrid() Debugger& dbg = instance()->debugger(); TIADebug& tia = dbg.tiaDebug(); - TiaState state = (TiaState&) tia.getState(); - TiaState oldstate = (TiaState&) tia.getOldState(); + TiaState& state = (TiaState&) tia.getState(); + TiaState& oldstate = (TiaState&) tia.getOldState(); // TIA RAM alist.clear(); vlist.clear(); changed.clear(); diff --git a/stella/src/debugger/module.mk b/stella/src/debugger/module.mk index 0e7d73ef1..5a9e4868e 100644 --- a/stella/src/debugger/module.mk +++ b/stella/src/debugger/module.mk @@ -8,6 +8,7 @@ MODULE_OBJS := \ src/debugger/PackedBitArray.o \ src/debugger/CpuDebug.o \ src/debugger/RamDebug.o \ + src/debugger/RiotDebug.o \ src/debugger/TIADebug.o MODULE_DIRS += \ diff --git a/stella/src/emucore/M6532.cxx b/stella/src/emucore/M6532.cxx index 127f85562..2fb74c92a 100644 --- a/stella/src/emucore/M6532.cxx +++ b/stella/src/emucore/M6532.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: M6532.cxx,v 1.18 2008-04-17 13:39:14 stephena Exp $ +// $Id: M6532.cxx,v 1.19 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #include @@ -61,6 +61,9 @@ void M6532::reset() myOutA = 0x00; myDDRA = 0x00; myDDRB = 0x00; + + // Zero the timer registers + myOutTimer[0] = myOutTimer[1] = myOutTimer[2] = myOutTimer[3] = 0x0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -164,7 +167,7 @@ uInt8 M6532::peek(uInt16 addr) case 0x04: // Timer Output case 0x06: { - uInt32 timer = myTimer - (mySystem->cycles() - myCyclesWhenTimerSet); + uInt32 timer = timerClocks(); // See if the timer has expired yet? // Note that this constant comes from z26, and corresponds to @@ -184,9 +187,7 @@ uInt8 M6532::peek(uInt16 addr) case 0x05: // Interrupt Flag case 0x07: { - Int32 timer = myTimer - (mySystem->cycles() - myCyclesWhenTimerSet); - - if((timer >= 0) || myTimerReadAfterInterrupt) + if((timerClocks() >= 0) || myTimerReadAfterInterrupt) return 0x00; else return 0x80; @@ -273,29 +274,33 @@ void M6532::poke(uInt16 addr, uInt8 value) } else if((addr & 0x17) == 0x14) // Write timer divide by 1 { + myOutTimer[0] = value; myIntervalShift = 0; - myTimer = value << myIntervalShift; + myTimer = myOutTimer[0] << myIntervalShift; myCyclesWhenTimerSet = mySystem->cycles(); myTimerReadAfterInterrupt = false; } else if((addr & 0x17) == 0x15) // Write timer divide by 8 { + myOutTimer[1] = value; myIntervalShift = 3; - myTimer = value << myIntervalShift; + myTimer = myOutTimer[1] << myIntervalShift; myCyclesWhenTimerSet = mySystem->cycles(); myTimerReadAfterInterrupt = false; } else if((addr & 0x17) == 0x16) // Write timer divide by 64 { + myOutTimer[2] = value; myIntervalShift = 6; - myTimer = value << myIntervalShift; + myTimer = myOutTimer[2] << myIntervalShift; myCyclesWhenTimerSet = mySystem->cycles(); myTimerReadAfterInterrupt = false; } else if((addr & 0x17) == 0x17) // Write timer divide by 1024 { + myOutTimer[3] = value; myIntervalShift = 10; - myTimer = value << myIntervalShift; + myTimer = myOutTimer[3] << myIntervalShift; myCyclesWhenTimerSet = mySystem->cycles(); myTimerReadAfterInterrupt = false; } @@ -338,6 +343,10 @@ bool M6532::save(Serializer& out) const out.putByte((char)myOutA); out.putByte((char)myDDRA); out.putByte((char)myDDRB); + out.putByte((char)myOutTimer[0]); + out.putByte((char)myOutTimer[1]); + out.putByte((char)myOutTimer[2]); + out.putByte((char)myOutTimer[3]); } catch(char *msg) { @@ -376,6 +385,11 @@ bool M6532::load(Deserializer& in) myOutA = (uInt8) in.getByte(); myDDRA = (uInt8) in.getByte(); myDDRB = (uInt8) in.getByte(); + + myOutTimer[0] = (uInt8) in.getByte(); + myOutTimer[1] = (uInt8) in.getByte(); + myOutTimer[2] = (uInt8) in.getByte(); + myOutTimer[3] = (uInt8) in.getByte(); } catch(char *msg) { diff --git a/stella/src/emucore/M6532.hxx b/stella/src/emucore/M6532.hxx index 2dc0ad252..c86be5d73 100644 --- a/stella/src/emucore/M6532.hxx +++ b/stella/src/emucore/M6532.hxx @@ -13,28 +13,35 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: M6532.hxx,v 1.9 2008-04-17 13:39:14 stephena Exp $ +// $Id: M6532.hxx,v 1.10 2008-04-19 21:11:52 stephena Exp $ //============================================================================ #ifndef M6532_HXX #define M6532_HXX class Console; -class System; +class RiotDebug; class Serializer; class Deserializer; #include "bspf.hxx" #include "Device.hxx" +#include "System.hxx" /** RIOT @author Bradford W. Mott - @version $Id: M6532.hxx,v 1.9 2008-04-17 13:39:14 stephena Exp $ + @version $Id: M6532.hxx,v 1.10 2008-04-19 21:11:52 stephena Exp $ */ class M6532 : public Device { + public: + /** + The RIOT debugger class is a friend who needs special access + */ + friend class RiotDebug; + public: /** Create a new 6532 for the specified console @@ -119,6 +126,10 @@ class M6532 : public Device */ virtual void poke(uInt16 address, uInt8 value); + private: + inline Int32 timerClocks() + { return myTimer - (mySystem->cycles() - myCyclesWhenTimerSet); } + private: // Reference to the console const Console& myConsole; @@ -147,6 +158,9 @@ class M6532 : public Device // Data Direction Register for Port B uInt8 myDDRB; + // Last value written to the timer registers + uInt8 myOutTimer[4]; + private: // Copy constructor isn't supported by this class so make it private M6532(const M6532&);