diff --git a/docs/debugger.html b/docs/debugger.html index 4f1d506cc..10c43e512 100644 --- a/docs/debugger.html +++ b/docs/debugger.html @@ -388,8 +388,8 @@ in detail in the User's Guide.
The debugger tracks changes to the CPU registers and RAM by displaying -changed locations or registers with a red background after each step, +
The debugger tracks changes to the CPU, TIA and RIOT registers and RAM by +displaying changed locations or registers with a red background after each step, trace, scanline, or frame advance. This sounds simple, and it is, but it's also amazingly useful.
diff --git a/src/debugger/TIADebug.cxx b/src/debugger/TIADebug.cxx index b2e1ad755..2ed0cc518 100644 --- a/src/debugger/TIADebug.cxx +++ b/src/debugger/TIADebug.cxx @@ -60,6 +60,24 @@ const DebuggerState& TIADebug::getState() myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::BL]); myState.fixedCols.push_back(TIA::FixedColor::HBLANK_WHITE); + // Collisions + myState.cx.clear(); + myState.cx.push_back(collP0_PF()); + myState.cx.push_back(collP0_BL()); + myState.cx.push_back(collM1_P0()); + myState.cx.push_back(collM0_P0()); + myState.cx.push_back(collP0_P1()); + myState.cx.push_back(collP1_PF()); + myState.cx.push_back(collP1_BL()); + myState.cx.push_back(collM1_P1()); + myState.cx.push_back(collM0_P1()); + myState.cx.push_back(collM0_PF()); + myState.cx.push_back(collM0_BL()); + myState.cx.push_back(collM0_M1()); + myState.cx.push_back(collM1_PF()); + myState.cx.push_back(collM1_BL()); + myState.cx.push_back(collBL_PF()); + // Player 0 & 1 and Ball graphics registers myState.gr.clear(); myState.gr.push_back(myTIA.myPlayer0.getGRPNew()); @@ -69,6 +87,18 @@ const DebuggerState& TIADebug::getState() myState.gr.push_back(myTIA.myBall.getENABLNew()); myState.gr.push_back(myTIA.myBall.getENABLOld()); + // Player 0 & 1, Missile 0 & 1 and Ball graphics status registers + myState.ref.clear(); + myState.ref.push_back(refP0()); + myState.ref.push_back(refP1()); + myState.vdel.clear(); + myState.vdel.push_back(vdelP0()); + myState.vdel.push_back(vdelP1()); + myState.vdel.push_back(vdelBL()); + myState.res.clear(); + myState.res.push_back(resMP0()); + myState.res.push_back(resMP1()); + // Position registers myState.pos.clear(); myState.pos.push_back(posP0()); @@ -90,6 +120,9 @@ const DebuggerState& TIADebug::getState() myState.pf.push_back(pf0()); myState.pf.push_back(pf1()); myState.pf.push_back(pf2()); + myState.pf.push_back(refPF()); + myState.pf.push_back(scorePF()); + myState.pf.push_back(priorityPF()); // Size registers myState.size.clear(); @@ -131,6 +164,24 @@ void TIADebug::saveOldState() myOldState.coluRegs.push_back(coluPF()); myOldState.coluRegs.push_back(coluBK()); + // Collisions + myOldState.cx.clear(); + myOldState.cx.push_back(collP0_PF()); + myOldState.cx.push_back(collP0_BL()); + myOldState.cx.push_back(collM1_P0()); + myOldState.cx.push_back(collM0_P0()); + myOldState.cx.push_back(collP0_P1()); + myOldState.cx.push_back(collP1_PF()); + myOldState.cx.push_back(collP1_BL()); + myOldState.cx.push_back(collM1_P1()); + myOldState.cx.push_back(collM0_P1()); + myOldState.cx.push_back(collM0_PF()); + myOldState.cx.push_back(collM0_BL()); + myOldState.cx.push_back(collM0_M1()); + myOldState.cx.push_back(collM1_PF()); + myOldState.cx.push_back(collM1_BL()); + myOldState.cx.push_back(collBL_PF()); + // Player 0 & 1 graphics registers myOldState.gr.clear(); myOldState.gr.push_back(myTIA.myPlayer0.getGRPNew()); @@ -140,6 +191,18 @@ void TIADebug::saveOldState() myOldState.gr.push_back(myTIA.myBall.getENABLNew()); myOldState.gr.push_back(myTIA.myBall.getENABLOld()); + // Player 0 & 1, Missile 0 & 1 and Ball graphics status registers + myOldState.ref.clear(); + myOldState.ref.push_back(refP0()); + myOldState.ref.push_back(refP1()); + myOldState.vdel.clear(); + myOldState.vdel.push_back(vdelP0()); + myOldState.vdel.push_back(vdelP1()); + myOldState.vdel.push_back(vdelBL()); + myOldState.res.clear(); + myOldState.res.push_back(resMP0()); + myOldState.res.push_back(resMP1()); + // Position registers myOldState.pos.clear(); myOldState.pos.push_back(posP0()); @@ -161,6 +224,9 @@ void TIADebug::saveOldState() myOldState.pf.push_back(pf0()); myOldState.pf.push_back(pf1()); myOldState.pf.push_back(pf2()); + myOldState.pf.push_back(refPF()); + myOldState.pf.push_back(scorePF()); + myOldState.pf.push_back(priorityPF()); // Size registers myOldState.size.clear(); diff --git a/src/debugger/TIADebug.hxx b/src/debugger/TIADebug.hxx index 55fe764d0..6b1d4f6bb 100644 --- a/src/debugger/TIADebug.hxx +++ b/src/debugger/TIADebug.hxx @@ -39,7 +39,11 @@ class TiaState : public DebuggerState public: IntArray coluRegs; IntArray fixedCols; + BoolArray cx; IntArray gr; + BoolArray ref; + BoolArray vdel; + BoolArray res; IntArray pos; IntArray hm; IntArray pf; diff --git a/src/debugger/gui/TiaWidget.cxx b/src/debugger/gui/TiaWidget.cxx index a0dc84676..7a7bb1832 100644 --- a/src/debugger/gui/TiaWidget.cxx +++ b/src/debugger/gui/TiaWidget.cxx @@ -915,21 +915,21 @@ void TiaWidget::loadConfig() //////////////////////////// // Collision register bits //////////////////////////// - myCollision[kP0_PFID]->setState(tia.collP0_PF()); - myCollision[kP0_BLID]->setState(tia.collP0_BL()); - myCollision[kP0_M1ID]->setState(tia.collM1_P0()); - myCollision[kP0_M0ID]->setState(tia.collM0_P0()); - myCollision[kP0_P1ID]->setState(tia.collP0_P1()); - myCollision[kP1_PFID]->setState(tia.collP1_PF()); - myCollision[kP1_BLID]->setState(tia.collP1_BL()); - myCollision[kP1_M1ID]->setState(tia.collM1_P1()); - myCollision[kP1_M0ID]->setState(tia.collM0_P1()); - myCollision[kM0_PFID]->setState(tia.collM0_PF()); - myCollision[kM0_BLID]->setState(tia.collM0_BL()); - myCollision[kM0_M1ID]->setState(tia.collM0_M1()); - myCollision[kM1_PFID]->setState(tia.collM1_PF()); - myCollision[kM1_BLID]->setState(tia.collM1_BL()); - myCollision[kBL_PFID]->setState(tia.collBL_PF()); + myCollision[kP0_PFID]->setState(tia.collP0_PF(), state.cx[0] != oldstate.cx[0]); + myCollision[kP0_BLID]->setState(tia.collP0_BL(), state.cx[1] != oldstate.cx[1]); + myCollision[kP0_M1ID]->setState(tia.collM1_P0(), state.cx[2] != oldstate.cx[2]); + myCollision[kP0_M0ID]->setState(tia.collM0_P0(), state.cx[3] != oldstate.cx[3]); + myCollision[kP0_P1ID]->setState(tia.collP0_P1(), state.cx[4] != oldstate.cx[4]); + myCollision[kP1_PFID]->setState(tia.collP1_PF(), state.cx[5] != oldstate.cx[5]); + myCollision[kP1_BLID]->setState(tia.collP1_BL(), state.cx[6] != oldstate.cx[6]); + myCollision[kP1_M1ID]->setState(tia.collM1_P1(), state.cx[7] != oldstate.cx[7]); + myCollision[kP1_M0ID]->setState(tia.collM0_P1(), state.cx[8] != oldstate.cx[8]); + myCollision[kM0_PFID]->setState(tia.collM0_PF(), state.cx[9] != oldstate.cx[9]); + myCollision[kM0_BLID]->setState(tia.collM0_BL(), state.cx[10] != oldstate.cx[10]); + myCollision[kM0_M1ID]->setState(tia.collM0_M1(), state.cx[11] != oldstate.cx[11]); + myCollision[kM1_PFID]->setState(tia.collM1_PF(), state.cx[12] != oldstate.cx[12]); + myCollision[kM1_BLID]->setState(tia.collM1_BL(), state.cx[13] != oldstate.cx[13]); + myCollision[kBL_PFID]->setState(tia.collBL_PF(), state.cx[14] != oldstate.cx[14]); //////////////////////////// // P0 register info @@ -957,8 +957,8 @@ void TiaWidget::loadConfig() myHMP0->setList(0, state.hm[P0], state.hm[P0] != oldstate.hm[P0]); // refP0 & vdelP0 - myRefP0->setState(tia.refP0()); - myDelP0->setState(tia.vdelP0()); + myRefP0->setState(tia.refP0(), state.ref[P0] != oldstate.ref[P0]); + myDelP0->setState(tia.vdelP0(), state.vdel[P0] != oldstate.vdel[P0]); // NUSIZ0 (player portion) bool nusiz0changed = state.size[P0] != oldstate.size[P0]; @@ -991,8 +991,8 @@ void TiaWidget::loadConfig() myHMP1->setList(0, state.hm[P1], state.hm[P1] != oldstate.hm[P1]); // refP1 & vdelP1 - myRefP1->setState(tia.refP1()); - myDelP1->setState(tia.vdelP1()); + myRefP1->setState(tia.refP1(), state.ref[P1] != oldstate.ref[P1]); + myDelP1->setState(tia.vdelP1(), state.vdel[P1] != oldstate.vdel[P1]); // NUSIZ1 (player portion) bool nusiz1changed = state.size[P1] != oldstate.size[P1]; @@ -1004,7 +1004,7 @@ void TiaWidget::loadConfig() //////////////////////////// // enaM0 myEnaM0->setColor(state.coluRegs[0]); - myEnaM0->setIntState(tia.enaM0() ? 1: 0, false); + myEnaM0->setIntState(tia.enaM0() ? 1 : 0, false); // posM0 myPosM0->setList(0, state.pos[M0], state.pos[M0] != oldstate.pos[M0]); @@ -1016,14 +1016,14 @@ void TiaWidget::loadConfig() myNusizM0->setList(0, state.size[M0], state.size[M0] != oldstate.size[M0]); // resMP0 - myResMP0->setState(tia.resMP0()); + myResMP0->setState(tia.resMP0(), state.res[P0] != oldstate.res[P0]); //////////////////////////// // M1 register info //////////////////////////// // enaM1 myEnaM1->setColor(state.coluRegs[1]); - myEnaM1->setIntState(tia.enaM1() ? 1: 0, false); + myEnaM1->setIntState(tia.enaM1() ? 1 : 0, false); // posM1 myPosM1->setList(0, state.pos[M1], state.pos[M1] != oldstate.pos[M1]); @@ -1035,7 +1035,7 @@ void TiaWidget::loadConfig() myNusizM1->setList(0, state.size[M1], state.size[M1] != oldstate.size[M1]); // resMP1 - myResMP1->setState(tia.resMP1()); + myResMP1->setState(tia.resMP1(),state.res[P1] != oldstate.res[P1]); //////////////////////////// // BL register info @@ -1066,7 +1066,7 @@ void TiaWidget::loadConfig() mySizeBL->setList(0, state.size[BL], state.size[BL] != oldstate.size[BL]); // vdelBL - myDelBL->setState(tia.vdelBL()); + myDelBL->setState(tia.vdelBL(), state.vdel[2] != oldstate.vdel[2]); //////////////////////////// // PF register info @@ -1084,13 +1084,13 @@ void TiaWidget::loadConfig() myPF[2]->setIntState(state.pf[2], true); // reverse bit order // Reflect - myRefPF->setState(tia.refPF()); + myRefPF->setState(tia.refPF(), state.pf[3] != oldstate.pf[3]); // Score - myScorePF->setState(tia.scorePF()); + myScorePF->setState(tia.scorePF(), state.pf[4] != oldstate.pf[4]); // Priority - myPriorityPF->setState(tia.priorityPF()); + myPriorityPF->setState(tia.priorityPF(), state.pf[5] != oldstate.pf[5]); myDelayQueueWidget->loadConfig(); } diff --git a/src/debugger/gui/TogglePixelWidget.cxx b/src/debugger/gui/TogglePixelWidget.cxx index 5f310ea91..abd9e7e40 100644 --- a/src/debugger/gui/TogglePixelWidget.cxx +++ b/src/debugger/gui/TogglePixelWidget.cxx @@ -40,11 +40,25 @@ TogglePixelWidget::TogglePixelWidget(GuiObject* boss, const GUI::Font& font, // Changed state isn't used, but we still need to fill it while(int(_changedList.size()) < rows * cols) _changedList.push_back(false); + // prepare _stateList for change tracking + while(int(_stateList.size()) < rows * cols) + _stateList.push_back(false); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TogglePixelWidget::setState(const BoolArray& state) { + // track changes automatically + for(int row = 0; row < _rows; row++) + { + for(int col = 0; col < _cols; col++) + { + int pos = row * _cols + col; + + _changedList[pos] = _stateList[pos] != state[pos]; + } + } + _stateList.clear(); _stateList = state; @@ -133,6 +147,8 @@ void TogglePixelWidget::drawWidget(bool hilite) // Either draw the pixel in given color, or erase (show background) s.fillRect(x - 3, y - 1, _colWidth-1, _rowHeight-1, _stateList[pos] ? _pixelColor : _backgroundColor); + if (_changedList[pos]) + s.frameRect(x - 3, y - 1, _colWidth - 1, _rowHeight - 1, kDbgChangedColor); } }