diff --git a/stella/Debugger.txt b/stella/Debugger.txt index 7386fbbeb..d8358b841 100644 --- a/stella/Debugger.txt +++ b/stella/Debugger.txt @@ -35,6 +35,8 @@ What the debugger can do: and switch banks. There's still more to be done here though. - Patching ROM in-place. Currently there's no way to save the patched ROM though. +- Registers/memory that get changed by the CPU during debugging are + highlighted when they're displayed Planned features for Stella 2.0 release: - Better TIA state display, with register names and GUI buttons for @@ -446,6 +448,8 @@ z - Toggle Zero Flag The 'Restart' button restarts the whole procedure (ie, clear the input and listboxes, and allows another search. + (TODO: need a way to name and save/load the cheats) + - TIA tab (TODO) - ROM tab (TODO) diff --git a/stella/src/debugger/Debugger.cxx b/stella/src/debugger/Debugger.cxx index 0d822c3cc..182e20ae8 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.48 2005-07-03 00:53:58 stephena Exp $ +// $Id: Debugger.cxx,v 1.49 2005-07-03 01:36:39 urchlay Exp $ //============================================================================ #include "bspf.hxx" @@ -123,6 +123,7 @@ void Debugger::setConsole(Console* console) // base class and entirely eliminate MediaSource class?? delete myTIAdebug; myTIAdebug = new TIADebug((TIA*)&myConsole->mediaSource()); + myTIAdebug->setDebugger(this); // Create a new 6502 debugger for this console delete myDebugger; @@ -396,14 +397,6 @@ const string Debugger::dumpRAM(uInt8 start, uInt8 len) return result; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const string booleanWithLabel(string label, bool value) { - if(value) - return label + ":On"; - else - return label + ":Off"; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const string Debugger::dumpTIA() { @@ -419,16 +412,9 @@ const string Debugger::dumpTIA() if(j == 0x07) result += "- "; } - result += "\nscanline "; - //result += valueToString( myConsole->mediaSource().scanlines() ); - result += valueToString( myTIAdebug->scanlines() ); result += "\n"; - - result += booleanWithLabel("VSYNC", myTIAdebug->vsync()); - result += "\n"; - - result += myTIAdebug->spriteState(); + result += myTIAdebug->state(); return result; } diff --git a/stella/src/debugger/TIADebug.cxx b/stella/src/debugger/TIADebug.cxx index bf6e30aa6..2f72f8764 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.4 2005-06-29 13:11:03 stephena Exp $ +// $Id: TIADebug.cxx,v 1.5 2005-07-03 01:36:39 urchlay Exp $ //============================================================================ #include "TIADebug.hxx" @@ -22,11 +22,24 @@ TIADebug::TIADebug(TIA *tia) { myTIA = tia; + + nusizStrings[0] = "size=8, copies=1"; + nusizStrings[1] = "size=8, copies=2, spacing=8"; + nusizStrings[2] = "size=8, copies=2, spacing=18"; + nusizStrings[3] = "size=8, copies=3, spacing=8"; + nusizStrings[4] = "size=8, copies=2, spacing=38"; + nusizStrings[5] = "size=10, copies=1"; + nusizStrings[6] = "size=8, copies=3, spacing=18"; + nusizStrings[7] = "size=20, copies=1"; } TIADebug::~TIADebug() { } +void TIADebug::setDebugger(Debugger *d) { + myDebugger = d; +} + int TIADebug::frameCount() { return myTIA->myFrameCounter; } @@ -39,33 +52,114 @@ bool TIADebug::vsync() { return (myTIA->myVSYNC & 2) == 2; } +bool TIADebug::vblank() { + return (myTIA->myVBLANK & 2) == 2; +} + void TIADebug::updateTIA() { // not working the way I expected: // myTIA->updateFrame(myTIA->mySystem->cycles() * 3); } -string TIADebug::spriteState() { +string TIADebug::colorSwatch(uInt8 c) { + string ret; + + ret += char((c >> 1) | 0x80); + ret += "\177 "; + ret += "\177\003 "; + + return ret; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const string booleanWithLabel(string label, bool value) { + if(value) + return label + ":On"; + else + return label + ":Off"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string TIADebug::state() { string ret; // TODO: prettier printing (table?) - // TODO: NUSIZ - // TODO: missiles, ball, PF - // TODO: collisions + // TODO: joysticks, pots, switches // TODO: audio + // TIA::myCOLUxx are stored 4 copies to each int, we need only 1 + uInt8 COLUP0 = myTIA->myCOLUP0 & 0xff; + uInt8 COLUP1 = myTIA->myCOLUP1 & 0xff; + uInt8 COLUPF = myTIA->myCOLUPF & 0xff; + uInt8 COLUBK = myTIA->myCOLUBK & 0xff; + + // TIA::myPF holds all 3 PFx regs, we shall extract + int PF = myTIA->myPF; + uInt8 PF0 = PF & 0x0f; + uInt8 PF1 = (PF >> 4) & 0xff; + uInt8 PF2 = (PF >> 12) & 0xff; + + // Hope Brad never changes this: + uInt16 coll = myTIA->myCollision; + + // calculate sizes + uInt8 ballSize = 1 << (myTIA->myCTRLPF & 0x18); + uInt8 m0Size = 1 << (myTIA->myNUSIZ0 & 0x18); + uInt8 m1Size = 1 << (myTIA->myNUSIZ1 & 0x18); + + // easier to use a table for these: + string p0Size = nusizStrings[myTIA->myNUSIZ0 & 0x07]; + string p1Size = nusizStrings[myTIA->myNUSIZ1 & 0x07]; + + // build up output, then return it. + ret += "scanline "; + + ret += myDebugger->valueToString(myTIA->scanlines()); + ret += " "; + + ret += booleanWithLabel("VSYNC", vsync()); + ret += " "; + + ret += booleanWithLabel("VBLANK", vblank()); + ret += "\n"; + + ret += "COLUP0: "; + ret += myDebugger->valueToString(COLUP0); + ret += "/"; + ret += colorSwatch(COLUP0); + + ret += "COLUP1: "; + ret += myDebugger->valueToString(COLUP1); + ret += "/"; + ret += colorSwatch(COLUP1); + + ret += "COLUPF: "; + ret += myDebugger->valueToString(COLUPF); + ret += "/"; + ret += colorSwatch(COLUPF); + + ret += "COLUBK: "; + ret += myDebugger->valueToString(COLUBK); + ret += "/"; + ret += colorSwatch(COLUBK); + + ret += "\n"; + ret += "P0: data="; + // TODO: ret += myDebugger->invIfChanged(myTIA->myGRP0, oldGRP0); ret += Debugger::to_bin_8(myTIA->myGRP0); ret += "/"; ret += Debugger::to_hex_8(myTIA->myGRP0); ret += ", "; + ret += p0Size; + ret += ", "; if(!myTIA->myREFP0) ret += "not "; ret += "reflected, pos="; ret += Debugger::to_hex_8(myTIA->myPOSP0); - ret += ", color="; - ret += Debugger::to_hex_8(myTIA->myCOLUP0 & 0xff); ret += ", "; if(!myTIA->myVDELP0) ret += "not "; - ret += " delayed"; + ret += "delayed, HMP0="; + ret += Debugger::to_hex_8(myTIA->myHMP0); ret += "\n"; ret += "P1: data="; @@ -73,15 +167,92 @@ string TIADebug::spriteState() { ret += "/"; ret += Debugger::to_hex_8(myTIA->myGRP1); ret += ", "; + ret += p1Size; + ret += ", "; if(!myTIA->myREFP1) ret += "not "; ret += "reflected, pos="; ret += Debugger::to_hex_8(myTIA->myPOSP1); - ret += ", color="; - ret += Debugger::to_hex_8(myTIA->myCOLUP1 & 0xff); ret += ", "; if(!myTIA->myVDELP1) ret += "not "; - ret += "delayed"; + ret += "delayed, HMP1="; + ret += Debugger::to_hex_8(myTIA->myHMP1); ret += "\n"; + ret += "M0: "; + ret += (myTIA->myENAM0 ? " enabled" : "disabled"); + ret += ", pos="; + ret += Debugger::to_hex_8(myTIA->myPOSM0); + ret += ", size="; + ret += Debugger::to_hex_8(m0Size); + ret += ", "; + if(!myTIA->myRESMP0) ret += "not "; + ret += "reset, HMM0="; + ret += Debugger::to_hex_8(myTIA->myHMM0); + ret += "\n"; + + ret += "M1: "; + ret += (myTIA->myENAM1 ? " enabled" : "disabled"); + ret += ", pos="; + ret += Debugger::to_hex_8(myTIA->myPOSM1); + ret += ", size="; + ret += Debugger::to_hex_8(m1Size); + ret += ", "; + if(!myTIA->myRESMP1) ret += "not "; + ret += "reset, HMM1="; + ret += Debugger::to_hex_8(myTIA->myHMM1); + ret += "\n"; + + ret += "BL: "; + ret += (myTIA->myENABL ? " enabled" : "disabled"); + ret += ", pos="; + ret += Debugger::to_hex_8(myTIA->myPOSBL); + ret += ", size="; + ret += Debugger::to_hex_8(ballSize); + ret += ", "; + if(!myTIA->myVDELBL) ret += "not "; + ret += "delayed, HMBL="; + ret += Debugger::to_hex_8(myTIA->myHMBL); + ret += "\n"; + + ret += "PF0: "; + ret += Debugger::to_bin_8(PF0); + ret += "/"; + ret += Debugger::to_hex_8(PF0); + ret += ", PF1: "; + ret += Debugger::to_bin_8(PF1); + ret += "/"; + ret += Debugger::to_hex_8(PF1); + ret += ", PF2: "; + ret += Debugger::to_bin_8(PF2); + ret += "/"; + ret += Debugger::to_hex_8(PF2); + ret += "\n (pf "; + if(! (myTIA->myCTRLPF & 0x01) ) ret += "not "; + ret += "reflected, "; + if(! (myTIA->myCTRLPF & 0x02) ) ret += "not "; + ret += "score, "; + if(! (myTIA->myCTRLPF & 0x04) ) ret += "not "; + ret += "priority)"; + ret += "\n"; + + ret += "Collisions: "; + if(coll && 0x0001) ret += "M0-P1 "; + if(coll && 0x0002) ret += "M0-P0 "; + if(coll && 0x0004) ret += "M1-P0 "; + if(coll && 0x0008) ret += "M1-P1 "; + if(coll && 0x0010) ret += "P0-PF "; + if(coll && 0x0020) ret += "P0-BL "; + if(coll && 0x0040) ret += "P1-PF "; + ret += "\n "; + if(coll && 0x0080) ret += "P1-BL "; + if(coll && 0x0100) ret += "M0-PF "; + if(coll && 0x0200) ret += "M0-BL "; + if(coll && 0x0400) ret += "M1-PF "; + if(coll && 0x0800) ret += "M1-BL "; + if(coll && 0x1000) ret += "BL-PF "; + if(coll && 0x2000) ret += "P0-P1 "; + if(coll && 0x4000) ret += "M0-M1 "; + + // note: last "ret +=" line should not contain \n, caller will add. return ret; } diff --git a/stella/src/debugger/TIADebug.hxx b/stella/src/debugger/TIADebug.hxx index 475e990c3..8c5e26233 100644 --- a/stella/src/debugger/TIADebug.hxx +++ b/stella/src/debugger/TIADebug.hxx @@ -13,27 +13,36 @@ // 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.4 2005-06-29 13:11:03 stephena Exp $ +// $Id: TIADebug.hxx,v 1.5 2005-07-03 01:36:39 urchlay Exp $ //============================================================================ #ifndef TIADEBUG_HXX #define TIADEBUG_HXX #include "TIA.hxx" +#include "Debugger.hxx" class TIADebug { public: TIADebug(TIA *tia); ~TIADebug(); + void setDebugger(Debugger *d); + int scanlines(); int frameCount(); bool vsync(); + bool vblank(); void updateTIA(); - string spriteState(); + string state(); private: TIA *myTIA; + Debugger *myDebugger; + + string colorSwatch(uInt8 c); + + string nusizStrings[8]; }; diff --git a/stella/src/emucore/Console.cxx b/stella/src/emucore/Console.cxx index 8d78d6890..8a8dfea0a 100644 --- a/stella/src/emucore/Console.cxx +++ b/stella/src/emucore/Console.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: Console.cxx,v 1.64 2005-07-02 17:15:41 urchlay Exp $ +// $Id: Console.cxx,v 1.65 2005-07-03 01:36:40 urchlay Exp $ //============================================================================ #include @@ -349,9 +349,28 @@ void Console::setPalette() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/* Original frying research and code by Fred Quimby. + I've tried the following variations on this code: + - Both OR and Exclusive OR instead of AND. This generally crashes the game + without ever giving us realistic "fried" effects. + - Loop only over the RIOT RAM. This still gave us frying-like effects, but + it seemed harder to duplicate most effects. I have no idea why, but + munging the TIA regs seems to have some effect (I'd think it wouldn't). + + Fred says he also tried mangling the PC and registers, but usually it'd just + crash the game (e.g. black screen, no way out of it). + + It's definitely easier to get some effects (e.g. 255 lives in Battlezone) + with this code than it is on a real console. My guess is that most "good" + frying effects come from a RIOT location getting cleared to 0. Fred's + code is more likely to accomplish this than frying a real console is... + + Until someone comes up with a more accurate way to emulate frying, I'm + leaving this as Fred posted it. -- B. +*/ void Console::fry() { - for (int ZPmem=0; ZPmem<255; ZPmem += rand() % 4) + for (int ZPmem=0; ZPmem<0x100; ZPmem += rand() % 4) mySystem->poke(ZPmem, mySystem->peek(ZPmem) & (uInt8)rand() % 256); } diff --git a/stella/src/gui/PromptWidget.cxx b/stella/src/gui/PromptWidget.cxx index 2d8062b73..fcaa28bfe 100644 --- a/stella/src/gui/PromptWidget.cxx +++ b/stella/src/gui/PromptWidget.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: PromptWidget.cxx,v 1.23 2005-07-02 15:36:44 stephena Exp $ +// $Id: PromptWidget.cxx,v 1.24 2005-07-03 01:36:40 urchlay Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -746,7 +746,7 @@ void PromptWidget::putcharIntern(int c) textColor = (OverlayColor) ((c & 0x7f) << 1); } else if(c < ' ') { // More colors (the regular GUI ones) - textColor = (OverlayColor) (c); + textColor = (OverlayColor) (c + 0x100); } else if(c == 0x7f) { // toggle inverse video (DEL char) _inverse = !_inverse; @@ -826,14 +826,14 @@ bool PromptWidget::saveBuffer(string& filename) for(int start=0; start<_promptStartPos; start+=_lineWidth) { int end = start+_lineWidth-1; - // look for first non-space char from end of line - while(_buffer[end] == ' ' && end >= start) + // look for first non-space, printing char from end of line + while( char(_buffer[end] & 0xff) <= ' ' && end >= start) end--; - // spit out the line minus its trailing spaces. + // spit out the line minus its trailing junk. // Strip off any color/inverse bits for(int j=start; j<=end; j++) - out << (_buffer[j] & 0xff); + out << char(_buffer[j] & 0xff); // add a \n out << endl;