From f92d2fc6df249d7ec18717919755919fd2f304a0 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 13 Aug 2024 14:54:03 +0200 Subject: [PATCH] enhanced UI and settings for TIA glitch "short late HMOVEs" --- src/common/DevSettingsHandler.cxx | 9 ++++++++ src/common/DevSettingsHandler.hxx | 3 +++ src/emucore/Settings.cxx | 12 ++++++++-- src/emucore/tia/Ball.cxx | 7 ++++++ src/emucore/tia/Ball.hxx | 5 +++- src/emucore/tia/Missile.cxx | 7 ++++++ src/emucore/tia/Missile.hxx | 4 +++- src/emucore/tia/Player.cxx | 7 ++++++ src/emucore/tia/Player.hxx | 4 +++- src/emucore/tia/TIA.cxx | 26 +++++++++++++++++++++ src/emucore/tia/TIA.hxx | 21 +++++++++++++++++ src/gui/DeveloperDialog.cxx | 38 ++++++++++++++++++++++++++++--- src/gui/DeveloperDialog.hxx | 8 +++++++ 13 files changed, 143 insertions(+), 8 deletions(-) diff --git a/src/common/DevSettingsHandler.cxx b/src/common/DevSettingsHandler.cxx index c457c16d8..4b569385e 100644 --- a/src/common/DevSettingsHandler.cxx +++ b/src/common/DevSettingsHandler.cxx @@ -70,6 +70,9 @@ void DevSettingsHandler::loadSettings(SettingsSet set) myPlInvPhase[set] = devSettings ? settings.getBool("dev.tia.plinvphase") : false; myMsInvPhase[set] = devSettings ? settings.getBool("dev.tia.msinvphase") : false; myBlInvPhase[set] = devSettings ? settings.getBool("dev.tia.blinvphase") : false; + myPlLateHMove[set] = devSettings ? settings.getBool("dev.tia.pllatehmove") : false; + myMsLateHMove[set] = devSettings ? settings.getBool("dev.tia.mslatehmove") : false; + myBlLateHMove[set] = devSettings ? settings.getBool("dev.tia.bllatehmove") : false; myPFBits[set] = devSettings ? settings.getBool("dev.tia.delaypfbits") : false; myPFColor[set] = devSettings ? settings.getBool("dev.tia.delaypfcolor") : false; myPFScore[set] = devSettings ? settings.getBool("dev.tia.pfscoreglitch") : false; @@ -141,6 +144,9 @@ void DevSettingsHandler::saveSettings(SettingsSet set) settings.setValue("dev.tia.plinvphase", myPlInvPhase[set]); settings.setValue("dev.tia.msinvphase", myMsInvPhase[set]); settings.setValue("dev.tia.blinvphase", myBlInvPhase[set]); + settings.setValue("dev.tia.pllatehmove", myPlLateHMove[set]); + settings.setValue("dev.tia.mslatehmove", myMsLateHMove[set]); + settings.setValue("dev.tia.bllatehmove", myBlLateHMove[set]); settings.setValue("dev.tia.delaypfbits", myPFBits[set]); settings.setValue("dev.tia.delaypfcolor", myPFColor[set]); settings.setValue("dev.tia.pfscoreglitch", myPFScore[set]); @@ -197,6 +203,9 @@ void DevSettingsHandler::applySettings(SettingsSet set) myOSystem.console().tia().setPlInvertedPhaseClock(myPlInvPhase[set]); myOSystem.console().tia().setMsInvertedPhaseClock(myMsInvPhase[set]); myOSystem.console().tia().setBlInvertedPhaseClock(myBlInvPhase[set]); + myOSystem.console().tia().setPlShortLateHMove(myPlLateHMove[set]); + myOSystem.console().tia().setMsShortLateHMove(myMsLateHMove[set]); + myOSystem.console().tia().setBlShortLateHMove(myBlLateHMove[set]); myOSystem.console().tia().setPFBitsDelay(myPFBits[set]); myOSystem.console().tia().setPFColorDelay(myPFColor[set]); myOSystem.console().tia().setPFScoreGlitch(myPFScore[set]); diff --git a/src/common/DevSettingsHandler.hxx b/src/common/DevSettingsHandler.hxx index b2c304d3d..802809dde 100644 --- a/src/common/DevSettingsHandler.hxx +++ b/src/common/DevSettingsHandler.hxx @@ -73,6 +73,9 @@ class DevSettingsHandler std::array myPlInvPhase; std::array myMsInvPhase; std::array myBlInvPhase; + std::array myPlLateHMove; + std::array myMsLateHMove; + std::array myBlLateHMove; std::array myPFBits; std::array myPFColor; std::array myPFScore; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 8dd3c12eb..6df1bfe52 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -297,6 +297,9 @@ Settings::Settings() setPermanent("dev.tia.plinvphase", "true"); setPermanent("dev.tia.msinvphase", "true"); setPermanent("dev.tia.blinvphase", "true"); + setPermanent("dev.tia.pllatehmove", "true"); + setPermanent("dev.tia.mslatehmove", "true"); + setPermanent("dev.tia.bllatehmove", "true"); setPermanent("dev.tia.delaypfbits", "true"); setPermanent("dev.tia.delaypfcolor", "true"); setPermanent("dev.tia.pfscoreglitch", "true"); @@ -312,7 +315,7 @@ Settings::Settings() setPermanent("dev.extaccess", "true"); // Thumb ARM emulation options setPermanent("dev.thumb.trapfatal", "true"); - setPermanent("dev.arm.mips", CartridgeELF::MIPS_DEF); + setPermanent("dev.arm.mips", CartridgeELF::MIPS_DEF); #ifdef DEBUGGER_SUPPORT setPermanent("dev.thumb.inccycles", "true"); setPermanent("dev.thumb.cyclefactor", "1.05"); @@ -811,11 +814,16 @@ void Settings::usage() << " koolaidman|\n" << " cosmicark|pesco|\n" << " quickstep|matchie|\n" - << " indy500|heman|>\n" + << " indy500|heman|\n" + << " flashmenu>\n" << " -dev.tia.plinvphase <1|0> Enable inverted HMOVE clock phase for players\n" << " -dev.tia.msinvphase <1|0> Enable inverted HMOVE clock phase for\n" << " missiles\n" << " -dev.tia.blinvphase <1|0> Enable inverted HMOVE clock phase for ball\n" + << " -dev.tia.pllatehmove <1|0> Enable short late HMOVE for players\n" + << " -dev.tia.mslatehmove <1|0> Enable short late HMOVE for\n" + << " missiles\n" + << " -dev.tia.bllatehmove <1|0> Enable short late HMOVE for ball\n" << " -dev.tia.delaypfbits <1|0> Enable extra delay cycle for PF bits access\n" << " -dev.tia.delaypfcolor <1|0> Enable extra delay cycle for PF color\n" << " -dev.tia.pfscoreglitch <1|0> Enable PF score mode color glitch\n" diff --git a/src/emucore/tia/Ball.cxx b/src/emucore/tia/Ball.cxx index 242f103bd..d9e3a5af4 100644 --- a/src/emucore/tia/Ball.cxx +++ b/src/emucore/tia/Ball.cxx @@ -45,6 +45,7 @@ void Ball::reset() myRenderCounter = 0; myInvertedPhaseClock = false; myUseInvertedPhaseClock = false; + myUseShortLateHMove = false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -153,6 +154,12 @@ void Ball::setInvertedPhaseClock(bool enable) myUseInvertedPhaseClock = enable; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Ball::setShortLateHMove(bool enable) +{ + myUseShortLateHMove = enable; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Ball::startMovement() { diff --git a/src/emucore/tia/Ball.hxx b/src/emucore/tia/Ball.hxx index 5bfe8bb9c..df468566c 100644 --- a/src/emucore/tia/Ball.hxx +++ b/src/emucore/tia/Ball.hxx @@ -108,6 +108,7 @@ class Ball : public Serializable Aid Man bug on some Jr. models. */ void setInvertedPhaseClock(bool enable); + void setShortLateHMove(bool enable); /** Start movement --- this is triggered by strobing HMOVE. @@ -323,6 +324,8 @@ class Ball : public Serializable */ bool myUseInvertedPhaseClock{false}; + bool myUseShortLateHMove{false}; + /** TIA instance. Required for flushing the line cache and requesting collision updates. */ @@ -350,7 +353,7 @@ void Ball::movementTick(uInt32 clock, uInt32 hclock, bool hblank) // Stop movement once the number of clocks according to HMBL is reached if (clock == myHmmClocks) isMoving = false; - else if (hclock != 0) + else if (!myUseShortLateHMove || hclock != 0) { // Process the tick if we are in hblank. Otherwise, the tick is either masked // by an ordinary tick or merges two consecutive ticks into a single tick (inverted diff --git a/src/emucore/tia/Missile.cxx b/src/emucore/tia/Missile.cxx index 4e1c9371d..8ed8ddda9 100644 --- a/src/emucore/tia/Missile.cxx +++ b/src/emucore/tia/Missile.cxx @@ -46,6 +46,7 @@ void Missile::reset() collision = myCollisionMaskDisabled; myInvertedPhaseClock = false; myUseInvertedPhaseClock = false; + myUseShortLateHMove = false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -199,6 +200,12 @@ void Missile::setInvertedPhaseClock(bool enable) myUseInvertedPhaseClock = enable; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Missile::setShortLateHMove(bool enable) +{ + myUseShortLateHMove = enable; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Missile::updateEnabled() { diff --git a/src/emucore/tia/Missile.hxx b/src/emucore/tia/Missile.hxx index aa54055a1..04f6fe4f6 100644 --- a/src/emucore/tia/Missile.hxx +++ b/src/emucore/tia/Missile.hxx @@ -60,6 +60,7 @@ class Missile : public Serializable void applyColorLoss(); void setInvertedPhaseClock(bool enable); + void setShortLateHMove(bool enable); void toggleCollisions(bool enabled); @@ -127,6 +128,7 @@ class Missile : public Serializable bool myInvertedPhaseClock{false}; bool myUseInvertedPhaseClock{false}; + bool myUseShortLateHMove{false}; TIA *myTIA{nullptr}; @@ -149,7 +151,7 @@ void Missile::movementTick(uInt8 clock, uInt8 hclock, bool hblank) // Stop movement once the number of clocks according to HMMx is reached if(clock == myHmmClocks) isMoving = false; - else if (hclock != 0) + else if (!myUseShortLateHMove || hclock != 0) { // Process the tick if we are in hblank. Otherwise, the tick is either masked // by an ordinary tick or merges two consecutive ticks into a single tick (inverted diff --git a/src/emucore/tia/Player.cxx b/src/emucore/tia/Player.cxx index 0925f25ee..5698d0c38 100644 --- a/src/emucore/tia/Player.cxx +++ b/src/emucore/tia/Player.cxx @@ -47,6 +47,7 @@ void Player::reset() myDividerChangeCounter = -1; myInvertedPhaseClock = false; myUseInvertedPhaseClock = false; + myUseShortLateHMove = false; myPattern = 0; setDivider(1); @@ -260,6 +261,12 @@ void Player::setInvertedPhaseClock(bool enable) myUseInvertedPhaseClock = enable; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Player::setShortLateHMove(bool enable) +{ + myUseShortLateHMove = enable; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Player::startMovement() { diff --git a/src/emucore/tia/Player.hxx b/src/emucore/tia/Player.hxx index 289d22c1d..823d627eb 100644 --- a/src/emucore/tia/Player.hxx +++ b/src/emucore/tia/Player.hxx @@ -60,6 +60,7 @@ class Player : public Serializable void applyColorLoss(); void setInvertedPhaseClock(bool enable); + void setShortLateHMove(bool enable); void startMovement(); @@ -143,6 +144,7 @@ class Player : public Serializable bool myIsDelaying{false}; bool myInvertedPhaseClock{false}; bool myUseInvertedPhaseClock{false}; + bool myUseShortLateHMove{false}; TIA* myTIA{nullptr}; @@ -165,7 +167,7 @@ void Player::movementTick(uInt32 clock, uInt32 hclock, bool hblank) // Stop movement once the number of clocks according to HMPx is reached if (clock == myHmmClocks) isMoving = false; - else if (hclock != 0) + else if (!myUseShortLateHMove || hclock != 0) { // Process the tick if we are in hblank. Otherwise, the tick is either masked // by an ordinary tick or merges two consecutive ticks into a single tick (inverted diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 658f53e69..98ed5ffa3 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -978,6 +978,11 @@ void TIA::applyDeveloperSettings() ? mySettings.getBool("dev.tia.msinvphase") : BSPF::equalsIgnoreCase("cosmicark", mySettings.getString("dev.tia.type"))); setBlInvertedPhaseClock(custom ? mySettings.getBool("dev.tia.blinvphase") : false); + setPlShortLateHMove(custom + ? mySettings.getBool("dev.tia.pllatehmove") + : BSPF::equalsIgnoreCase("flashmenu", mySettings.getString("dev.tia.type"))); + setMsShortLateHMove(custom ? mySettings.getBool("dev.tia.mslatehmove") : false); + setBlShortLateHMove(custom ? mySettings.getBool("dev.tia.bllatehmove") : false); setPFBitsDelay(custom ? mySettings.getBool("dev.tia.delaypfbits") : BSPF::equalsIgnoreCase("pesco", mySettings.getString("dev.tia.type"))); @@ -1900,6 +1905,27 @@ void TIA::setBlInvertedPhaseClock(bool enable) myBall.setInvertedPhaseClock(enable); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIA::setPlShortLateHMove(bool enable) +{ + myPlayer0.setShortLateHMove(enable); + myPlayer1.setShortLateHMove(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIA::setMsShortLateHMove(bool enable) +{ + myMissile0.setShortLateHMove(enable); + myMissile1.setShortLateHMove(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIA::setBlShortLateHMove(bool enable) +{ + myBall.setShortLateHMove(enable); +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIA::delayedWrite(uInt8 address, uInt8 value) { diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index bd7873b46..75f47cf79 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -523,6 +523,27 @@ class TIA : public Device */ void setBlInvertedPhaseClock(bool enable); + /** + Enables/disables short late HMOVE for players. + + @param enable Whether to enable short late HMOVE for players + */ + void setPlShortLateHMove(bool enable); + + /** + Enables/disables short late HMOVE for missiles. + + @param enable Whether to enable short late HMOVE for missiles + */ + void setMsShortLateHMove(bool enable); + + /** + Enables/disables short late HMOVE for ball. + + @param enable Whether to enable short late HMOVE for ball + */ + void setBlShortLateHMove(bool enable); + /** This method should be called to update the TIA with a new scanline. */ diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 282a62726..a049f25ce 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -229,8 +229,8 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font) myArmSpeedWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 1, ypos - 1, fontWidth * 10, lineHeight, "Limit ARM speed (*) ", 0, kArmSpeedChanged, fontWidth * 9, " MIPS"); - myArmSpeedWidget->setMinValue(CartridgeELF::MIPS_MIN); - myArmSpeedWidget->setMaxValue(CartridgeELF::MIPS_MAX); + myArmSpeedWidget->setMinValue(CartridgeELF::MIPS_MIN); + myArmSpeedWidget->setMaxValue(CartridgeELF::MIPS_MAX); myArmSpeedWidget->setTickmarkIntervals((CartridgeELF::MIPS_MAX - CartridgeELF::MIPS_MIN) / 50); myArmSpeedWidget->setStepValue(2); myArmSpeedWidget->setToolTip("Limit emulation speed to simulate ARM CPU used for ELF."); @@ -238,7 +238,7 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font) ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER; lwidth = infofont.getStringWidth("(*) Change requires a reload for ELF ROMs"); - new StaticTextWidget(myTab, infofont, HBORDER, ypos, lwidth, infofont.getFontHeight(), + new StaticTextWidget(myTab, infofont, HBORDER, ypos, lwidth, infofont.getFontHeight(), "(*) Change requires a reload for ELF ROMs"); // Add items for tab 0 @@ -286,6 +286,7 @@ void DeveloperDialog::addTiaTab(const GUI::Font& font) VarList::push_back(items, "Glitched Matchie line", "matchie"); VarList::push_back(items, "Glitched Indy 500 menu", "indy500"); VarList::push_back(items, "Glitched He-Man title", "heman"); + VarList::push_back(items, "Shifted flashcart menu", "flashmenu"); VarList::push_back(items, "Custom", "custom"); myTIATypeWidget = new PopUpWidget(myTab, font, HBORDER + INDENT, ypos - 1, pwidth, lineHeight, items, "Chip type ", 0, kTIAType); @@ -314,6 +315,24 @@ void DeveloperDialog::addTiaTab(const GUI::Font& font) wid.push_back(myBlInvPhaseWidget); ypos += lineHeight + VGAP * 1; + myLateHMoveLabel = new StaticTextWidget(myTab, font, HBORDER + INDENT * 2, ypos + 1, + "Short late HMOVEs for"); + myLateHMoveLabel->setToolTip("Objects react different to late HMOVEs"); + wid.push_back(myLateHMoveLabel); + ypos += lineHeight + VGAP * 1; + + myPlLateHMoveWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 3, ypos + 1, "Players"); + wid.push_back(myPlLateHMoveWidget); + + myMsLateHMoveWidget = new CheckboxWidget(myTab, font, myPlLateHMoveWidget->getRight() + fontWidth() * 2.5, + ypos + 1, "Missiles"); + wid.push_back(myMsLateHMoveWidget); + + myBlLateHMoveWidget = new CheckboxWidget(myTab, font, myMsLateHMoveWidget->getRight() + fontWidth() * 2.5, + ypos + 1, "Ball"); + wid.push_back(myBlLateHMoveWidget); + ypos += lineHeight + VGAP * 1; + myPlayfieldLabel = new StaticTextWidget(myTab, font, HBORDER + INDENT * 2, ypos + 1, "Delayed playfield"); myPlayfieldLabel->setToolTip("Playfield reacts one color clock slower to updates."); @@ -758,6 +777,9 @@ void DeveloperDialog::getWidgetStates(SettingsSet set) myPlInvPhase[set] = myPlInvPhaseWidget->getState(); myMsInvPhase[set] = myMsInvPhaseWidget->getState(); myBlInvPhase[set] = myBlInvPhaseWidget->getState(); + myPlLateHMove[set] = myPlLateHMoveWidget->getState(); + myMsLateHMove[set] = myMsLateHMoveWidget->getState(); + myBlLateHMove[set] = myBlLateHMoveWidget->getState(); myPFBits[set] = myPFBitsWidget->getState(); myPFColor[set] = myPFColorWidget->getState(); myPFScore[set] = myPFScoreWidget->getState(); @@ -1183,6 +1205,10 @@ void DeveloperDialog::handleTia() myPlInvPhaseWidget->setEnabled(enable); myMsInvPhaseWidget->setEnabled(enable); myBlInvPhaseWidget->setEnabled(enable); + myLateHMoveLabel->setEnabled(enable); + myPlLateHMoveWidget->setEnabled(enable); + myMsLateHMoveWidget->setEnabled(enable); + myBlLateHMoveWidget->setEnabled(enable); myPlayfieldLabel->setEnabled(enable); myBackgroundLabel->setEnabled(enable); myPFBitsWidget->setEnabled(enable); @@ -1200,6 +1226,9 @@ void DeveloperDialog::handleTia() myPlInvPhaseWidget->setState(myPlInvPhase[set]); myMsInvPhaseWidget->setState(myMsInvPhase[set]); myBlInvPhaseWidget->setState(myBlInvPhase[set]); + myPlLateHMoveWidget->setState(myPlLateHMove[set]); + myMsLateHMoveWidget->setState(myMsLateHMove[set]); + myBlLateHMoveWidget->setState(myBlLateHMove[set]); myPFBitsWidget->setState(myPFBits[set]); myPFColorWidget->setState(myPFColor[set]); myPFScoreWidget->setState(myPFScore[set]); @@ -1212,6 +1241,9 @@ void DeveloperDialog::handleTia() myPlInvPhaseWidget->setState(BSPF::equalsIgnoreCase("koolaidman", myTIATypeWidget->getSelectedTag().toString())); myMsInvPhaseWidget->setState(BSPF::equalsIgnoreCase("cosmicark", myTIATypeWidget->getSelectedTag().toString())); myBlInvPhaseWidget->setState(false); + myPlLateHMoveWidget->setState(BSPF::equalsIgnoreCase("flashmenu", myTIATypeWidget->getSelectedTag().toString())); + myMsLateHMoveWidget->setState(false); + myBlLateHMoveWidget->setState(false); myPFBitsWidget->setState(BSPF::equalsIgnoreCase("pesco", myTIATypeWidget->getSelectedTag().toString())); myPFColorWidget->setState(BSPF::equalsIgnoreCase("quickstep", myTIATypeWidget->getSelectedTag().toString())); myPFScoreWidget->setState(BSPF::equalsIgnoreCase("matchie", myTIATypeWidget->getSelectedTag().toString())); diff --git a/src/gui/DeveloperDialog.hxx b/src/gui/DeveloperDialog.hxx index 1a4c83489..41418e901 100644 --- a/src/gui/DeveloperDialog.hxx +++ b/src/gui/DeveloperDialog.hxx @@ -108,14 +108,22 @@ class DeveloperDialog : public Dialog, DevSettingsHandler // TIA widgets RadioButtonGroup* mySettingsGroupTia{nullptr}; PopUpWidget* myTIATypeWidget{nullptr}; + StaticTextWidget* myInvPhaseLabel{nullptr}; CheckboxWidget* myPlInvPhaseWidget{nullptr}; CheckboxWidget* myMsInvPhaseWidget{nullptr}; CheckboxWidget* myBlInvPhaseWidget{nullptr}; + + StaticTextWidget* myLateHMoveLabel{nullptr}; + CheckboxWidget* myPlLateHMoveWidget{nullptr}; + CheckboxWidget* myMsLateHMoveWidget{nullptr}; + CheckboxWidget* myBlLateHMoveWidget{nullptr}; + StaticTextWidget* myPlayfieldLabel{nullptr}; CheckboxWidget* myPFBitsWidget{nullptr}; CheckboxWidget* myPFColorWidget{nullptr}; CheckboxWidget* myPFScoreWidget{nullptr}; + StaticTextWidget* myBackgroundLabel{nullptr}; CheckboxWidget* myBKColorWidget{nullptr}; StaticTextWidget* mySwapLabel{nullptr};