diff --git a/Changes.txt b/Changes.txt
index 9f6bc410d..732d82330 100644
--- a/Changes.txt
+++ b/Changes.txt
@@ -45,6 +45,8 @@
* Added another oddball TIA glitch option for score mode color.
+ * Enhanced TV jitter emulation (TODO: doc).
+
* Enhanced support for CDFJ+ bankswitching type.
* Added 0FA0 bankswitching for Fotomania ROMs.
diff --git a/docs/graphics/options_developer_video.png b/docs/graphics/options_developer_video.png
index 02b2549ed..441f30c60 100644
Binary files a/docs/graphics/options_developer_video.png and b/docs/graphics/options_developer_video.png differ
diff --git a/docs/index.html b/docs/index.html
index b40a78e5a..e9d527f93 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1982,6 +1982,18 @@
Cmd + J |
+
+ Decrease TV jitter sensitivity |
+ Shift-Control-Alt + J |
+ Shift-Control-Cmd + J |
+
+
+
+ Increase TV jitter sensitivity |
+ Control-Alt + J |
+ Control-Cmd + J |
+
+
Decrease TV jitter roll time |
Shift-Control + J |
@@ -3812,10 +3824,13 @@
-<plr.|dev.>tv.jitter <1|0> |
Enable TV jitter/roll effect, when there are too many or too few scanlines
per frame. |
+
+ -<plr.|dev.>tv.jitter_sense <1 - 10> |
+ When TV jitter/roll effect is enabled, determines the sensitivy to varying frame timings. |
-<plr.|dev.>tv.jitter_recovery <1 - 20> |
- When TV jitter/roll effect is enabled, determines how long to delay recovery
- time (recovery spread over multiple frames). |
+ When TV jitter/roll effect is enabled, determines the recovery time for screen rolling
+ (recovery spread over multiple frames). |
-<plr.|dev.>colorloss <1|0> |
Enable/disable the PAL color-loss effect. |
@@ -4677,6 +4692,7 @@
Item | Brief description | For more information, see Command Line |
Jitter/roll effect | Emulate screen roll with inconsistent scanline count | -plr.tv.jitter -dev.tv.jitter |
+ (Jitter/roll) Sensitivity | Determines sensitivity for screen rolling | -plr.tv.jitter_sense -dev.tv.jitter_sense |
(Jitter/roll) Recovery | Determines recovery time for screen rolling | -plr.tv.jitter_recovery -dev.tv.jitter_recovery |
PAL color-loss | Use PAL color-loss effect | -plr.colorloss -dev.colorloss |
Debug colors | Use fixed debug colors | -plr.debugcolors -dev.debugcolors |
diff --git a/src/common/DevSettingsHandler.cxx b/src/common/DevSettingsHandler.cxx
index 2b90144f3..bd70cfef3 100644
--- a/src/common/DevSettingsHandler.cxx
+++ b/src/common/DevSettingsHandler.cxx
@@ -78,6 +78,7 @@ void DevSettingsHandler::loadSettings(SettingsSet set)
myColorLoss[set] = settings.getBool(prefix + "colorloss");
// Jitter
myTVJitter[set] = settings.getBool(prefix + "tv.jitter");
+ myTVJitterSense[set] = settings.getInt(prefix + "tv.jitter_sense");
myTVJitterRec[set] = settings.getInt(prefix + "tv.jitter_recovery");
// States
@@ -148,6 +149,7 @@ void DevSettingsHandler::saveSettings(SettingsSet set)
settings.setValue(prefix + "colorloss", myColorLoss[set]);
// Jitter
settings.setValue(prefix + "tv.jitter", myTVJitter[set]);
+ settings.setValue(prefix + "tv.jitter_sense", myTVJitterSense[set]);
settings.setValue(prefix + "tv.jitter_recovery", myTVJitterRec[set]);
// States
@@ -200,6 +202,7 @@ void DevSettingsHandler::applySettings(SettingsSet set)
{
// TV Jitter
myOSystem.console().tia().toggleJitter(myTVJitter[set] ? 1 : 0);
+ myOSystem.console().tia().setJitterSensitivity(myTVJitterSense[set]);
myOSystem.console().tia().setJitterRecoveryFactor(myTVJitterRec[set]);
// PAL color loss
myOSystem.console().enableColorLoss(myColorLoss[set]);
diff --git a/src/common/DevSettingsHandler.hxx b/src/common/DevSettingsHandler.hxx
index 25145b6c9..8b602aea0 100644
--- a/src/common/DevSettingsHandler.hxx
+++ b/src/common/DevSettingsHandler.hxx
@@ -55,6 +55,7 @@ class DevSettingsHandler
std::array myRandomizeCPU;
std::array myColorLoss;
std::array myTVJitter;
+ std::array myTVJitterSense;
std::array myTVJitterRec;
std::array myDebugColors;
std::array myUndrivenPins;
diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx
index a1ed83659..5c6f37d6b 100644
--- a/src/common/PKeyboardHandler.cxx
+++ b/src/common/PKeyboardHandler.cxx
@@ -700,8 +700,10 @@ PhysicalKeyboardHandler::DefaultCommonMapping = {
{ Event::DecreaseSpeed, KBDK_S, KBDM_SHIFT | KBDM_CTRL },
{ Event::IncreaseSpeed, KBDK_S, KBDM_CTRL },
{ Event::ToggleTurbo, KBDK_T, KBDM_CTRL },
- { Event::JitterDecrease, KBDK_J, KBDM_SHIFT | KBDM_CTRL },
- { Event::JitterIncrease, KBDK_J, KBDM_CTRL },
+ { Event::JitterSenseDecrease, KBDK_J, KBDM_SHIFT | MOD3 | KBDM_CTRL },
+ { Event::JitterSenseIncrease, KBDK_J, MOD3 | KBDM_CTRL },
+ { Event::JitterRecDecrease, KBDK_J, KBDM_SHIFT | KBDM_CTRL },
+ { Event::JitterRecIncrease, KBDK_J, KBDM_CTRL },
{ Event::ToggleDeveloperSet, KBDK_D, MOD3 },
{ Event::ToggleJitter, KBDK_J, MOD3 },
{ Event::ToggleFrameStats, KBDK_L, MOD3 },
diff --git a/src/common/jsonDefinitions.hxx b/src/common/jsonDefinitions.hxx
index 0d0f9a7ce..ee82567fc 100644
--- a/src/common/jsonDefinitions.hxx
+++ b/src/common/jsonDefinitions.hxx
@@ -361,8 +361,10 @@ NLOHMANN_JSON_SERIALIZE_ENUM(Event::Type, {
{Event::TogglePhosphor, "TogglePhosphor"},
{Event::ToggleDeveloperSet, "ToggleDeveloperSet"},
{Event::ToggleInter, "ToggleInter"},
- {Event::JitterDecrease, "JitterDecrease"},
- {Event::JitterIncrease, "JitterIncrease"},
+ {Event::JitterSenseDecrease, "JitterSenseDecrease"},
+ {Event::JitterSenseIncrease, "JitterSenseIncrease"},
+ {Event::JitterRecDecrease, "JitterRecDecrease"},
+ {Event::JitterRecIncrease, "JitterRecIncrease"},
{Event::ToggleJitter, "ToggleJitter"},
{Event::VolumeDecrease, "VolumeDecrease"},
{Event::VolumeIncrease, "VolumeIncrease"},
diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx
index 8d3801023..4d98ab731 100644
--- a/src/emucore/Console.cxx
+++ b/src/emucore/Console.cxx
@@ -1253,7 +1253,40 @@ void Console::toggleJitter(bool toggle) const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::changeJitter(int direction) const
+void Console::changeJitterSense(int direction) const
+{
+ const string prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
+ int sensitivity = myOSystem.settings().getInt(prefix + "tv.jitter_sense");
+ const bool enabled = direction ? sensitivity + direction > 0 : myTIA->toggleJitter(3);
+
+ // if disabled, enable before first before increasing recovery
+ if(!myTIA->toggleJitter(3))
+ direction = 0;
+
+ sensitivity = BSPF::clamp(static_cast(sensitivity + direction),
+ JitterEmulation::MIN_SENSITIVITY, JitterEmulation::MAX_SENSITIVITY);
+ myOSystem.settings().setValue(prefix + "tv.jitter", enabled);
+
+ if(enabled)
+ {
+ ostringstream val;
+
+ myTIA->toggleJitter(1);
+ myTIA->setJitterSensitivity(sensitivity);
+ myOSystem.settings().setValue(prefix + "tv.jitter_sense", sensitivity);
+ val << sensitivity;
+ myOSystem.frameBuffer().showGaugeMessage("TV jitter sensitivity", val.str(), sensitivity,
+ 0, JitterEmulation::MAX_SENSITIVITY);
+ }
+ else
+ {
+ myTIA->toggleJitter(0);
+ myOSystem.frameBuffer().showTextMessage("TV scanline jitter disabled");
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void Console::changeJitterRecovery(int direction) const
{
const string prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
int recovery = myOSystem.settings().getInt(prefix + "tv.jitter_recovery");
@@ -1263,7 +1296,8 @@ void Console::changeJitter(int direction) const
if(!myTIA->toggleJitter(3))
direction = 0;
- recovery = BSPF::clamp(recovery + direction, 1, 20);
+ recovery = BSPF::clamp(static_cast(recovery + direction),
+ JitterEmulation::MIN_RECOVERY, JitterEmulation::MAX_RECOVERY);
myOSystem.settings().setValue(prefix + "tv.jitter", enabled);
if(enabled)
@@ -1274,7 +1308,8 @@ void Console::changeJitter(int direction) const
myTIA->setJitterRecoveryFactor(recovery);
myOSystem.settings().setValue(prefix + "tv.jitter_recovery", recovery);
val << recovery;
- myOSystem.frameBuffer().showGaugeMessage("TV jitter roll", val.str(), recovery, 0, 20);
+ myOSystem.frameBuffer().showGaugeMessage("TV jitter roll", val.str(), recovery,
+ 0, JitterEmulation::MAX_RECOVERY);
}
else
{
diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx
index 169ba2beb..128316672 100644
--- a/src/emucore/Console.hxx
+++ b/src/emucore/Console.hxx
@@ -357,10 +357,15 @@ class Console : public Serializable, public ConsoleIO
*/
void toggleJitter(bool toggle = true) const;
+ /**
+ Changes the TIA 'scanline jitter' sensitivity.
+ */
+ void changeJitterSense(int direction = +1) const;
+
/**
Changes the TIA 'scanline jitter' revcovery rate.
*/
- void changeJitter(int direction = +1) const;
+ void changeJitterRecovery(int direction = +1) const;
/**
* Update vcenter
diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx
index 0a3fffbe4..db6ae19d9 100644
--- a/src/emucore/Event.hxx
+++ b/src/emucore/Event.hxx
@@ -116,7 +116,8 @@ class Event
ScanlinesDecrease, ScanlinesIncrease,
PreviousScanlineMask, NextScanlineMask,
PhosphorDecrease, PhosphorIncrease, TogglePhosphor, ToggleInter,
- ToggleDeveloperSet, JitterDecrease, JitterIncrease, ToggleJitter,
+ ToggleDeveloperSet, JitterRecDecrease, JitterRecIncrease,
+ JitterSenseDecrease, JitterSenseIncrease, ToggleJitter,
VolumeDecrease, VolumeIncrease, SoundToggle,
diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx
index e51163466..7ad4b6813 100644
--- a/src/emucore/EventHandler.cxx
+++ b/src/emucore/EventHandler.cxx
@@ -976,23 +976,39 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if(pressed && !repeated)
{
myOSystem.console().toggleJitter();
- myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER);
+ myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER_SENSE);
}
return;
- case Event::JitterDecrease:
+ case Event::JitterSenseDecrease:
if(pressed)
{
- myOSystem.console().changeJitter(-1);
- myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER);
+ myOSystem.console().changeJitterSense(-1);
+ myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER_SENSE);
}
return;
- case Event::JitterIncrease:
+ case Event::JitterSenseIncrease:
if(pressed)
{
- myOSystem.console().changeJitter(+1);
- myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER);
+ myOSystem.console().changeJitterSense(+1);
+ myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER_SENSE);
+ }
+ return;
+
+ case Event::JitterRecDecrease:
+ if(pressed)
+ {
+ myOSystem.console().changeJitterRecovery(-1);
+ myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER_REC);
+ }
+ return;
+
+ case Event::JitterRecIncrease:
+ if(pressed)
+ {
+ myOSystem.console().changeJitterRecovery(+1);
+ myGlobalKeyHandler->setSetting(GlobalKeyHandler::Setting::JITTER_REC);
}
return;
@@ -3041,8 +3057,10 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
{ Event::ToggleFixedColors, "Toggle TIA 'Fixed Debug Colors' mode", "" },
{ Event::ToggleColorLoss, "Toggle PAL color-loss effect", "" },
{ Event::ToggleJitter, "Toggle TV scanline 'Jitter' effect", "" },
- { Event::JitterDecrease, "Decrease TV 'Jitter' roll", "" },
- { Event::JitterIncrease, "Increase TV 'Jitter' roll", "" },
+ { Event::JitterSenseDecrease, "Decrease TV 'Jitter' sensitivity", "" },
+ { Event::JitterSenseIncrease, "Increase TV 'Jitter' sensitivity", "" },
+ { Event::JitterRecDecrease, "Decrease TV 'Jitter' roll", "" },
+ { Event::JitterRecIncrease, "Increase TV 'Jitter' roll", "" },
// Combo
{ Event::Combo1, "Combo 1", "" },
@@ -3230,5 +3248,6 @@ const Event::EventSet EventHandler::DebugEvents = {
Event::ToggleBLCollision, Event::ToggleBLBit, Event::TogglePFCollision, Event::TogglePFBit,
Event::ToggleCollisions, Event::ToggleBits, Event::ToggleFixedColors,
Event::ToggleColorLoss,
- Event::ToggleJitter, Event::JitterDecrease,Event::JitterIncrease,
+ Event::ToggleJitter, Event::JitterSenseDecrease,Event::JitterSenseIncrease,
+ Event::JitterRecDecrease,Event::JitterRecIncrease,
};
diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx
index 2182e08e2..d85afa969 100644
--- a/src/emucore/EventHandler.hxx
+++ b/src/emucore/EventHandler.hxx
@@ -524,7 +524,7 @@ class EventHandler
#else
REFRESH_SIZE = 0,
#endif
- EMUL_ACTIONLIST_SIZE = 230 + PNG_SIZE + COMBO_SIZE + REFRESH_SIZE,
+ EMUL_ACTIONLIST_SIZE = 232 + PNG_SIZE + COMBO_SIZE + REFRESH_SIZE,
MENU_ACTIONLIST_SIZE = 19
;
diff --git a/src/emucore/GlobalKeyHandler.cxx b/src/emucore/GlobalKeyHandler.cxx
index 381b63f70..bf640b920 100644
--- a/src/emucore/GlobalKeyHandler.cxx
+++ b/src/emucore/GlobalKeyHandler.cxx
@@ -436,7 +436,8 @@ GlobalKeyHandler::SettingData GlobalKeyHandler::getSettingData(const Setting set
{Setting::ALL_CX, {false, std::bind(&Console::toggleCollisions, &myOSystem.console(), _1)}}, // debug, not persisted
{Setting::FIXED_COL, {false, std::bind(&Console::toggleFixedColors, &myOSystem.console(), _1)}}, // debug, not persisted
{Setting::COLOR_LOSS, {false, std::bind(&Console::toggleColorLoss, &myOSystem.console(), _1)}},
- {Setting::JITTER, {true, std::bind(&Console::changeJitter, &myOSystem.console(), _1)}},
+ {Setting::JITTER_SENSE, {true, std::bind(&Console::changeJitterSense, &myOSystem.console(), _1)}},
+ {Setting::JITTER_REC, {true, std::bind(&Console::changeJitterRecovery, &myOSystem.console(), _1)}},
// *** Following functions are not used when cycling settings, but for "direct only" hotkeys ***
{Setting::STATE, {true, std::bind(&StateManager::changeState, &myOSystem.state(), _1)}}, // temporary, not persisted
{Setting::PALETTE_ATTRIBUTE, {true, std::bind(&PaletteHandler::changeCurrentAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1)}},
diff --git a/src/emucore/GlobalKeyHandler.hxx b/src/emucore/GlobalKeyHandler.hxx
index 60cc6ab13..69615e17f 100644
--- a/src/emucore/GlobalKeyHandler.hxx
+++ b/src/emucore/GlobalKeyHandler.hxx
@@ -118,7 +118,8 @@ class GlobalKeyHandler
ALL_CX,
FIXED_COL,
COLOR_LOSS,
- JITTER,
+ JITTER_SENSE,
+ JITTER_REC,
// *** Only used via direct hotkeys ***
STATE,
PALETTE_ATTRIBUTE,
@@ -131,7 +132,7 @@ class GlobalKeyHandler
START_INPUT_ADJ = DIGITAL_DEADZONE,
END_INPUT_ADJ = MOUSE_RANGE,
START_DEBUG_ADJ = DEVELOPER,
- END_DEBUG_ADJ = JITTER,
+ END_DEBUG_ADJ = JITTER_REC,
};
public:
diff --git a/src/emucore/MindLink.cxx b/src/emucore/MindLink.cxx
index e7464eb63..02ec5a79f 100644
--- a/src/emucore/MindLink.cxx
+++ b/src/emucore/MindLink.cxx
@@ -43,9 +43,9 @@ void MindLink::update()
myEvent.get(Event::MouseButtonRightValue))
myMindlinkPos = myMindlinkPos | TRIGGER_VALUE; // starts game, calibration and reverse
-#ifdef DEBUG_BUILD
- cerr << std::hex << myMindlinkPos << endl;
-#endif
+//#ifdef DEBUG_BUILD
+// cerr << std::hex << myMindlinkPos << endl;
+//#endif
myMindlinkShift = 1; // start transfer with least significant bit
nextMindlinkBit();
diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx
index cb641c16b..91a56822f 100644
--- a/src/emucore/Settings.cxx
+++ b/src/emucore/Settings.cxx
@@ -25,6 +25,7 @@
#include "PaletteHandler.hxx"
#include "Joystick.hxx"
#include "Paddles.hxx"
+#include "JitterEmulation.hxx"
#ifdef DEBUGGER_SUPPORT
#include "DebuggerDialog.hxx"
@@ -225,7 +226,8 @@ Settings::Settings()
setPermanent("plr.tiarandom", "false");
setPermanent("plr.colorloss", "false");
setPermanent("plr.tv.jitter", "true");
- setPermanent("plr.tv.jitter_recovery", "10");
+ setPermanent("plr.tv.jitter_sense", JitterEmulation::PLR_SENSITIVITY);
+ setPermanent("plr.tv.jitter_recovery", JitterEmulation::PLR_RECOVERY);
setPermanent("plr.debugcolors", "false");
setPermanent("plr.console", "2600"); // 7800
setPermanent("plr.timemachine", true);
@@ -245,7 +247,8 @@ Settings::Settings()
setPermanent("dev.tiarandom", "true");
setPermanent("dev.colorloss", "true");
setPermanent("dev.tv.jitter", "true");
- setPermanent("dev.tv.jitter_recovery", "2");
+ setPermanent("dev.tv.jitter_sense", JitterEmulation::DEV_SENSITIVITY);
+ setPermanent("dev.tv.jitter_recovery", JitterEmulation::DEV_RECOVERY);
setPermanent("dev.debugcolors", "false");
setPermanent("dev.tiadriven", "true");
setPermanent("dev.console", "2600"); // 7800
@@ -336,8 +339,13 @@ void Settings::validate()
i = getInt("tv.filter");
if(i < 0 || i > 5) setValue("tv.filter", "0");
+ i = getInt("dev.tv.jitter_sense");
+ if(i < JitterEmulation::MIN_SENSITIVITY || i > JitterEmulation::MAX_SENSITIVITY)
+ setValue("dev.tv.jitter_sense", JitterEmulation::DEV_SENSITIVITY);
+
i = getInt("dev.tv.jitter_recovery");
- if(i < 1 || i > 20) setValue("dev.tv.jitter_recovery", "2");
+ if(i < JitterEmulation::MIN_RECOVERY || i > JitterEmulation::MAX_RECOVERY)
+ setValue("dev.tv.jitter_recovery", JitterEmulation::DEV_RECOVERY);
int size = getInt("dev.tm.size");
if(size < 20 || size > 1000)
@@ -355,8 +363,12 @@ void Settings::validate()
i = getInt("dev.tm.horizon");
if(i < 0 || i > 6) setValue("dev.tm.horizon", 1);*/
+ i = getInt("plr.tv.jitter_sense");
+ if(i < JitterEmulation::MIN_SENSITIVITY || i > JitterEmulation::MAX_SENSITIVITY)
+ setValue("plr.tv.jitter_sense", JitterEmulation::PLR_SENSITIVITY);
+
i = getInt("plr.tv.jitter_recovery");
- if(i < 1 || i > 20) setValue("plr.tv.jitter_recovery", "10");
+ if(i < 1 || i > 20) setValue("plr.tv.jitter_recovery", JitterEmulation::PLR_RECOVERY);
size = getInt("plr.tm.size");
if(size < 20 || size > 1000)
@@ -713,6 +725,7 @@ void Settings::usage() const
<< " -plr.debugcolors <1|0> Enable debug colors\n"
<< " -plr.colorloss <1|0> Enable PAL color-loss effect\n"
<< " -plr.tv.jitter <1|0> Enable TV jitter effect\n"
+ << " -plr.tv.jitter_sense <1-10> Set TV jitter effect sensitivity\n"
<< " -plr.tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
<< " -plr.extaccess <1|0> Enable messages for external access\n"
<< endl
@@ -729,8 +742,9 @@ void Settings::usage() const
<< " -dev.debugcolors <1|0> Enable debug colors\n"
<< " -dev.colorloss <1|0> Enable PAL color-loss effect\n"
<< " -dev.tv.jitter <1|0> Enable TV jitter effect\n"
+ << " -dev.tv.jitter_sense <1-10> Set TV jitter effect sensitivity\n"
<< " -dev.tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
- << " -dev.tiadriven <1|0> Drive unused TIA pins randomly on a\n"
+ << " -dev.tiadriven <1|0> Drive unqused TIA pins randomly on a\n"
<< " read/peek\n"
#ifdef DEBUGGER_SUPPORT
<< " -dev.rwportbreak <1|0> Debugger breaks on reads from write ports\n"
diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx
index 4d73e85ee..4c61e197f 100644
--- a/src/emucore/tia/TIA.cxx
+++ b/src/emucore/tia/TIA.cxx
@@ -104,7 +104,8 @@ void TIA::setFrameManager(AbstractFrameManager* frameManager)
);
myFrameManager->enableJitter(myEnableJitter);
- myFrameManager->setJitterFactor(myJitterFactor);
+ myFrameManager->setJitterSensitivity(myJitterSensitivity);
+ myFrameManager->setJitterRecovery(myJitterRecovery);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -544,7 +545,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
break;
case VSYNC:
- myFrameManager->setVsync(value & 0x02);
+ myFrameManager->setVsync(value & 0x02, mySystem->cycles());
myShadowRegisters[address] = value;
break;
@@ -985,7 +986,8 @@ void TIA::applyDeveloperSettings()
myTIAPinsDriven = devSettings ? mySettings.getBool("dev.tiadriven") : false;
myEnableJitter = mySettings.getBool(devSettings ? "dev.tv.jitter" : "plr.tv.jitter");
- myJitterFactor = mySettings.getInt(devSettings ? "dev.tv.jitter_recovery" : "plr.tv.jitter_recovery");
+ myJitterSensitivity = mySettings.getInt(devSettings ? "dev.tv.jitter_sense" : "plr.tv.jitter_sense");
+ myJitterRecovery = mySettings.getInt(devSettings ? "dev.tv.jitter_recovery" : "plr.tv.jitter_recovery");
if(myFrameManager)
enableColorLoss(mySettings.getBool(devSettings ? "dev.colorloss" : "plr.colorloss"));
@@ -1281,12 +1283,20 @@ bool TIA::toggleJitter(uInt8 mode)
return myEnableJitter;
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void TIA::setJitterSensitivity(Int32 sensitivity)
+{
+ myJitterSensitivity = sensitivity;
+
+ if (myFrameManager) myFrameManager->setJitterSensitivity(sensitivity);
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::setJitterRecoveryFactor(Int32 factor)
{
- myJitterFactor = factor;
+ myJitterRecovery = factor;
- if (myFrameManager) myFrameManager->setJitterFactor(myJitterFactor);
+ if (myFrameManager) myFrameManager->setJitterRecovery(myJitterRecovery);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx
index 3959ea62f..3c80163a4 100644
--- a/src/emucore/tia/TIA.hxx
+++ b/src/emucore/tia/TIA.hxx
@@ -441,6 +441,7 @@ class TIA : public Device
@return Whether the mode was enabled or disabled
*/
bool toggleJitter(uInt8 mode = 2);
+ void setJitterSensitivity(Int32 sensitivity);
void setJitterRecoveryFactor(Int32 factor);
/**
@@ -977,7 +978,8 @@ class TIA : public Device
* The frame manager can change during our lifetime, so we buffer those two.
*/
bool myEnableJitter{false};
- uInt8 myJitterFactor{0};
+ uInt8 myJitterSensitivity{0};
+ uInt8 myJitterRecovery{0};
static constexpr uInt16
TIA_SIZE = 0x40, TIA_MASK = TIA_SIZE - 1,
diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.cxx b/src/emucore/tia/frame-manager/AbstractFrameManager.cxx
index 0067a6a40..92dacfb55 100644
--- a/src/emucore/tia/frame-manager/AbstractFrameManager.cxx
+++ b/src/emucore/tia/frame-manager/AbstractFrameManager.cxx
@@ -72,13 +72,13 @@ void AbstractFrameManager::setVblank(bool vblank)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AbstractFrameManager::setVsync(bool vsync)
+void AbstractFrameManager::setVsync(bool vsync, uInt64 cycles)
{
if (vsync == myVsync) return;
myVsync = vsync;
- onSetVsync();
+ onSetVsync(cycles);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx
index 5327257f5..a69b5118c 100644
--- a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx
+++ b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx
@@ -67,7 +67,7 @@ class AbstractFrameManager : public Serializable
/**
* Called by TIA on VSYNC writes.
*/
- void setVsync(bool vsync);
+ void setVsync(bool vsync, uInt64 cycles);
/**
* Should the TIA render its frame? This is buffered in a flag for
@@ -123,10 +123,15 @@ class AbstractFrameManager : public Serializable
// required. All of these are irrelevant if nothing is displayed (during
// autodetect).
+ /**
+ * The jitter sensitivity determines jitter simulation sensitivity to unstable video signals.
+ */
+ virtual void setJitterSensitivity(uInt8 sensitivity) {}
+
/**
* The jitter factor determines the time jitter simulation takes to recover.
*/
- virtual void setJitterFactor(uInt8 factor) {}
+ virtual void setJitterRecovery(uInt8 factor) {}
/**
* Is jitter simulation enabled?
@@ -207,7 +212,7 @@ class AbstractFrameManager : public Serializable
/**
* Called if vsync changes.
*/
- virtual void onSetVsync() {}
+ virtual void onSetVsync(uInt64 cycles) {}
/**
* Called if the next line is signalled, after the internal bookkeeping has
diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx
index ac01f0702..6861ff8bb 100644
--- a/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx
+++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx
@@ -39,7 +39,7 @@ void FrameLayoutDetector::onReset()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void FrameLayoutDetector::onSetVsync()
+void FrameLayoutDetector::onSetVsync(uInt64)
{
if (myVsync)
setState(State::waitForVsyncEnd);
diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx
index 0d5c52a28..da72a0cf9 100644
--- a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx
+++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx
@@ -44,7 +44,7 @@ class FrameLayoutDetector: public AbstractFrameManager
/**
* Hook into vsync changes.
*/
- void onSetVsync() override;
+ void onSetVsync(uInt64) override;
/**
* Hook into reset.
diff --git a/src/emucore/tia/frame-manager/FrameManager.cxx b/src/emucore/tia/frame-manager/FrameManager.cxx
index 9eb86427a..0ab4369cc 100644
--- a/src/emucore/tia/frame-manager/FrameManager.cxx
+++ b/src/emucore/tia/frame-manager/FrameManager.cxx
@@ -114,10 +114,16 @@ void FrameManager::setAdjustVSize(Int32 adjustVSize)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void FrameManager::onSetVsync()
+void FrameManager::onSetVsync(uInt64 cycles)
{
- if (myState == State::waitForVsyncEnd) setState(State::waitForFrameStart);
- else setState(State::waitForVsyncEnd);
+ if (myState == State::waitForVsyncEnd) {
+ myVsyncEnd = cycles;
+ setState(State::waitForFrameStart);
+ }
+ else {
+ myVsyncStart = cycles;
+ setState(State::waitForVsyncEnd);
+ }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -133,7 +139,7 @@ void FrameManager::setState(FrameManager::State state)
notifyFrameComplete();
if (myTotalFrames > Metrics::initialGarbageFrames)
- myJitterEmulation.frameComplete(myCurrentFrameFinalLines);
+ myJitterEmulation.frameComplete(myCurrentFrameFinalLines, myVsyncEnd - myVsyncStart);
notifyFrameStart();
diff --git a/src/emucore/tia/frame-manager/FrameManager.hxx b/src/emucore/tia/frame-manager/FrameManager.hxx
index f5b8eae4d..7ec51c903 100644
--- a/src/emucore/tia/frame-manager/FrameManager.hxx
+++ b/src/emucore/tia/frame-manager/FrameManager.hxx
@@ -47,8 +47,9 @@ class FrameManager: public AbstractFrameManager {
FrameManager();
public:
+ void setJitterSensitivity(uInt8 sensitivity) override { myJitterEmulation.setSensitivity(sensitivity); }
- void setJitterFactor(uInt8 factor) override { myJitterEmulation.setJitterFactor(factor); }
+ void setJitterRecovery(uInt8 factor) override { myJitterEmulation.setRecovery(factor); }
bool jitterEnabled() const override { return myJitterEnabled; }
@@ -78,7 +79,7 @@ class FrameManager: public AbstractFrameManager {
void setLayout(FrameLayout mode) override { layout(mode); }
- void onSetVsync() override;
+ void onSetVsync(uInt64 cycles) override;
void onNextLine() override;
@@ -122,6 +123,8 @@ class FrameManager: public AbstractFrameManager {
Int32 myMaxVcenter{0};
Int32 myVSizeAdjust{0};
+ uInt64 myVsyncStart{0};
+ uInt64 myVsyncEnd{0};
bool myJitterEnabled{false};
JitterEmulation myJitterEmulation;
diff --git a/src/emucore/tia/frame-manager/JitterEmulation.cxx b/src/emucore/tia/frame-manager/JitterEmulation.cxx
index c9e08aa28..905dbe0c9 100644
--- a/src/emucore/tia/frame-manager/JitterEmulation.cxx
+++ b/src/emucore/tia/frame-manager/JitterEmulation.cxx
@@ -26,52 +26,103 @@ JitterEmulation::JitterEmulation()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JitterEmulation::reset()
{
- myLastFrameScanlines = 0;
- myStableFrameFinalLines = -1;
- myStableFrames = 0;
- myStabilizationCounter = 0;
- myDestabilizationCounter = 0;
- myJitter = 0;
+ setSensitivity(mySensitivity);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void JitterEmulation::frameComplete(uInt32 scanlineCount)
+void JitterEmulation::setSensitivity(Int32 sensitivity)
{
- if (static_cast(scanlineCount) != myStableFrameFinalLines) {
- if (myDestabilizationCounter++ > Metrics::framesUntilDestabilization) myStableFrameFinalLines = -1;
+ myLastFrameScanlines = myLastFrameVsyncCycles = myUnstableCount = myJitter = 0;
+ mySensitivity = BSPF::clamp(sensitivity, MIN_SENSITIVITY, MAX_SENSITIVITY);
- if (scanlineCount == myLastFrameScanlines) {
+ const float factor = pow(static_cast(mySensitivity - MIN_SENSITIVITY) / (MAX_SENSITIVITY - MIN_SENSITIVITY), 1.5);
- if (++myStabilizationCounter >= Metrics::framesForStableHeight) {
- if (myStableFrameFinalLines > 0) updateJitter(scanlineCount - myStableFrameFinalLines);
+ myScanlineDelta = round(MAX_SCANLINE_DELTA - (MAX_SCANLINE_DELTA - MIN_SCANLINE_DELTA) * factor);
+ myVsyncCycles = round(MIN_VSYNC_CYCLES + (MAX_VSYNC_CYCLES - MIN_VSYNC_CYCLES) * factor);
+ myVsyncDelta1 = round(MAX_VSYNC_DELTA_1 - (MAX_VSYNC_DELTA_1 - MIN_VSYNC_DELTA_1) * factor);
+#ifdef VSYNC_LINE_JITTER
+ myVsyncDelta2 = round(MIN_VSYNC_DELTA_2 + (MAX_VSYNC_DELTA_2 - MIN_VSYNC_DELTA_2) * factor);
+#endif
+ myUnstableFrames = round(MAX_UNSTABLE_FRAMES - (MAX_UNSTABLE_FRAMES - MIN_UNSTABLE_FRAMES) * factor);
+ myJitterLines = round(MIN_JITTER_LINES + (MAX_JITTER_LINES - MIN_JITTER_LINES) * factor);
+ myVsyncLines = round(MIN_VSYNC_LINES + (MAX_VSYNC_LINES - MIN_VSYNC_LINES) * factor);
+}
- myStableFrameFinalLines = scanlineCount;
- myDestabilizationCounter = 0;
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void JitterEmulation::frameComplete(Int32 scanlineCount, Int32 vsyncCycles)
+{
+#ifdef DEBUG_BUILD
+ const int vsyncLines = round((vsyncCycles - 2) / 76.0);
+ cerr << "TV jitter " << myJitter << " - " << scanlineCount << ", " << vsyncCycles << ", " << vsyncLines << endl;
+#endif
+
+ // Check if current frame size is stable compared to previous frame
+ const bool scanlinesStable = scanlineCount == myLastFrameScanlines;
+ const bool vsyncCyclesStable = vsyncCycles >= myVsyncCycles;
+ // Handle inconsistency of vsync cycles and around half lines
+#ifdef VSYNC_LINE_JITTER
+ const Int32 minLines = round((vsyncCycles - 2 - myVsyncDelta2) / 76.0);
+ const Int32 maxLines = round((vsyncCycles - 2 + myVsyncDelta2) / 76.0);
+ const Int32 minLastLines = round((myLastFrameVsyncCycles - 2 - myVsyncDelta2) / 76.0);
+ const Int32 maxLastLines = round((myLastFrameVsyncCycles - 2 + myVsyncDelta2) / 76.0);
+ const bool vsyncLinesStable = abs(vsyncCycles - myLastFrameVsyncCycles) < myVsyncDelta1
+ && minLines == maxLastLines && maxLines == minLastLines;
+#else
+ const bool vsyncLinesStable = abs(vsyncCycles - myLastFrameVsyncCycles) < myVsyncDelta1;
+#endif
+
+ if(!scanlinesStable || !vsyncCyclesStable || !vsyncLinesStable)
+ {
+ if(++myUnstableCount >= myUnstableFrames)
+ {
+ if(!scanlinesStable)
+ {
+ const Int32 scanlineDifference = scanlineCount - myLastFrameScanlines;
+
+ if(abs(scanlineDifference) < myScanlineDelta
+ && abs(myJitter) < static_cast(myRandom.next() % myJitterLines))
+ {
+ // Repeated invalid frames cause randomly repeated jitter
+ myJitter = std::max(std::min(scanlineDifference, myJitterLines), -myYStart);
+ }
}
+ if(!vsyncCyclesStable)
+ {
+ // If VSYNC length is too low, the frame rolls permanently down, speed depending on missing cycles
+ const Int32 jitter = std::max(
+ std::min(round(scanlineCount * (1 - static_cast(vsyncCycles) / myVsyncCycles)),
+ myJitterLines),
+ myJitterRecovery + 1); // Roll at least one scanline
+ myJitter -= jitter;
+ // Limit jitter to -myYstart..scanlineCount
+ if(myJitter < -myYStart)
+ myJitter += 262;
+ }
+ if(!vsyncLinesStable)
+ {
+#ifdef VSYNC_LINE_JITTER
+ myJitter += minLines > maxLastLines ? myVsyncLines : -myVsyncLines;
+#else
+ myJitter += vsyncCycles > myLastFrameVsyncCycles ? myVsyncLines : -myVsyncLines;
+#endif
+ }
+ myJitter = std::max(myJitter, -myYStart);
}
- else myStabilizationCounter = 0;
}
- else myDestabilizationCounter = 0;
+ else
+ {
+ myUnstableCount = 0;
+
+ // Only recover during stable frames
+ if(myJitter > 0)
+ myJitter = std::max(myJitter - myJitterRecovery, 0);
+ else if(myJitter < 0)
+ myJitter = std::min(myJitter + myJitterRecovery, 0);
+ }
myLastFrameScanlines = scanlineCount;
-
- if (myJitter > 0) myJitter = std::max(myJitter - myJitterFactor, 0);
- if (myJitter < 0) myJitter = std::min(myJitter + myJitterFactor, 0);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void JitterEmulation::updateJitter(Int32 scanlineDifference)
-{
- if (static_cast(abs(scanlineDifference)) < Metrics::minDeltaForJitter) return;
-
- Int32 jitter = std::min(scanlineDifference, Metrics::maxJitter);
- jitter = std::max(jitter, -myYStart);
-
- if (jitter > 0) jitter += myJitterFactor;
- if (jitter < 0) jitter -= myJitterFactor;
-
- if (abs(jitter) > abs(myJitter)) myJitter = jitter;
+ myLastFrameVsyncCycles = vsyncCycles;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -79,14 +130,13 @@ bool JitterEmulation::save(Serializer& out) const
{
try
{
- out.putInt(myLastFrameScanlines);
- out.putInt(myStableFrameFinalLines);
- out.putInt(myStableFrames);
- out.putInt(myStabilizationCounter);
- out.putInt(myDestabilizationCounter);
- out.putInt(myJitter);
- out.putInt(myJitterFactor);
+ out.putInt(mySensitivity);
+ out.putInt(myJitterRecovery);
out.putInt(myYStart);
+ out.putInt(myLastFrameScanlines);
+ out.putInt(myLastFrameVsyncCycles);
+ out.putInt(myUnstableCount);
+ out.putInt(myJitter);
}
catch(...)
{
@@ -103,14 +153,13 @@ bool JitterEmulation::load(Serializer& in)
{
try
{
- myLastFrameScanlines = in.getInt();
- myStableFrameFinalLines = in.getInt();
- myStableFrames = in.getInt();
- myStabilizationCounter = in.getInt();
- myDestabilizationCounter = in.getInt();
- myJitter = in.getInt();
- myJitterFactor = in.getInt();
+ mySensitivity = in.getInt();
+ myJitterRecovery = in.getInt();
myYStart = in.getInt();
+ myLastFrameScanlines = in.getInt();
+ myLastFrameVsyncCycles = in.getInt();
+ myUnstableCount = in.getInt();
+ myJitter = in.getInt();
}
catch (...)
{
@@ -118,6 +167,7 @@ bool JitterEmulation::load(Serializer& in)
return false;
}
+ setSensitivity(mySensitivity);
return true;
}
diff --git a/src/emucore/tia/frame-manager/JitterEmulation.hxx b/src/emucore/tia/frame-manager/JitterEmulation.hxx
index ebdee2559..0c6aa06b8 100644
--- a/src/emucore/tia/frame-manager/JitterEmulation.hxx
+++ b/src/emucore/tia/frame-manager/JitterEmulation.hxx
@@ -18,27 +18,38 @@
#ifndef TIA_JITTER_EMULATION
#define TIA_JITTER_EMULATION
+//#define VSYNC_LINE_JITTER // makes e.g. Alien jitter, but not on my TV (TJ)
+
#include "bspf.hxx"
#include "Serializable.hxx"
+#include "Random.hxx"
-class JitterEmulation: public Serializable
+class JitterEmulation : public Serializable
{
public:
-
JitterEmulation();
public:
+ // sensitivity:
+ static constexpr Int32 MIN_SENSITIVITY = 1;
+ static constexpr Int32 MAX_SENSITIVITY = 10;
+ static constexpr Int32 PLR_SENSITIVITY = 3;
+ static constexpr Int32 DEV_SENSITIVITY = 8;
+ // roll speed:
+ static constexpr Int32 MIN_RECOVERY = 1;
+ static constexpr Int32 MAX_RECOVERY = 20;
+ static constexpr Int32 PLR_RECOVERY = 10;
+ static constexpr Int32 DEV_RECOVERY = 2;
+ public:
void reset();
+ void setSensitivity(Int32 sensitivity);
+ void setRecovery(Int32 recoveryFactor) { myJitterRecovery = recoveryFactor; }
+ void setYStart(Int32 ystart) { myYStart = ystart; }
- void frameComplete(uInt32 scanlineCount);
-
- void setJitterFactor(Int32 factor) { myJitterFactor = factor; }
-
+ void frameComplete(Int32 scanlineCount, Int32 vsyncCycles);
Int32 jitter() const { return myJitter; }
- void setYStart(uInt32 ystart) { myYStart = ystart; }
-
/**
* Save state.
*/
@@ -50,36 +61,48 @@ class JitterEmulation: public Serializable
bool load(Serializer& in) override;
private:
-
- void updateJitter(Int32 scanlineDifference);
+ // varying scanlines:
+ static constexpr Int32 MIN_SCANLINE_DELTA = 1; // was: 3
+ static constexpr Int32 MAX_SCANLINE_DELTA = 5;
+ // varying VSYNC timing:
+ static constexpr Int32 MIN_VSYNC_CYCLES = 76 * 3 / 4;
+ static constexpr Int32 MAX_VSYNC_CYCLES = 76 * 3;
+ static constexpr Int32 MIN_VSYNC_DELTA_1 = 1;
+ static constexpr Int32 MAX_VSYNC_DELTA_1 = 76 / 3;
+#ifdef VSYNC_LINE_JITTER
+ static constexpr Int32 MIN_VSYNC_DELTA_2 = 1;
+ static constexpr Int32 MAX_VSYNC_DELTA_2 = 10;
+#endif
+ // threshold for jitter:
+ static constexpr Int32 MIN_UNSTABLE_FRAMES = 1; // was: 10
+ static constexpr Int32 MAX_UNSTABLE_FRAMES = 10;
+ // resulting jitter:
+ static constexpr Int32 MIN_JITTER_LINES = 1; // was: 50
+ static constexpr Int32 MAX_JITTER_LINES = 200;
+ static constexpr Int32 MIN_VSYNC_LINES = 1;
+ static constexpr Int32 MAX_VSYNC_LINES = 5;
private:
+ Random myRandom;
- uInt32 myLastFrameScanlines{0};
-
- Int32 myStableFrameFinalLines{-1};
-
- uInt32 myStableFrames{0};
-
- uInt32 myStabilizationCounter{0};
-
- uInt32 myDestabilizationCounter{0};
-
+ Int32 myLastFrameScanlines{0};
+ Int32 myLastFrameVsyncCycles{0};
+ Int32 myUnstableCount{0};
Int32 myJitter{0};
-
- Int32 myJitterFactor{0};
-
- uInt32 myYStart{0};
-
- enum Metrics: uInt32 {
- framesForStableHeight = 2,
- framesUntilDestabilization = 10,
- minDeltaForJitter = 3,
- maxJitter = 50
- };
+ Int32 myJitterRecovery{0};
+ Int32 myYStart{0};
+ Int32 mySensitivity{MIN_SENSITIVITY};
+ Int32 myScanlineDelta{MAX_SCANLINE_DELTA};
+ Int32 myVsyncCycles{MIN_VSYNC_CYCLES};
+ Int32 myVsyncDelta1{MAX_VSYNC_DELTA_1};
+#ifdef VSYNC_LINE_JITTER
+ Int32 myVsyncDelta2{MIN_VSYNC_DELTA_2};
+#endif
+ Int32 myUnstableFrames{MAX_UNSTABLE_FRAMES};
+ Int32 myJitterLines{MIN_JITTER_LINES};
+ Int32 myVsyncLines{MIN_VSYNC_LINES};
private:
-
JitterEmulation(const JitterEmulation&) = delete;
JitterEmulation(JitterEmulation&&) = delete;
JitterEmulation& operator=(const JitterEmulation&) = delete;
diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx
index fd22e69d9..3e1d5e975 100644
--- a/src/gui/DeveloperDialog.cxx
+++ b/src/gui/DeveloperDialog.cxx
@@ -33,6 +33,7 @@
#include "Font.hxx"
#include "Console.hxx"
#include "TIA.hxx"
+#include "JitterEmulation.hxx"
#include "OSystem.hxx"
#include "EventHandler.hxx"
#include "StateManager.hxx"
@@ -372,21 +373,33 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font)
// TV jitter effect
myTVJitterWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
"Jitter/roll effect", kTVJitter);
+ ypos += lineHeight + VGAP;
+
myTVJitterWidget->setToolTip("Enable to emulate TV loss of sync.", Event::ToggleJitter);
wid.push_back(myTVJitterWidget);
+
+ myTVJitterSenseWidget = new SliderWidget(myTab, font,
+ myTVJitterWidget->getLeft() + CheckboxWidget::prefixSize(font), ypos - 1,
+ fontWidth * 9, lineHeight,
+ "Sensitivity ", 0, 0, fontWidth * 2);
+ myTVJitterSenseWidget->setMinValue(JitterEmulation::MIN_SENSITIVITY);
+ myTVJitterSenseWidget->setMaxValue(JitterEmulation::MAX_SENSITIVITY);
+ myTVJitterSenseWidget->setTickmarkIntervals(3);
+ myTVJitterSenseWidget->setToolTip("Define sensitivity to unstable frames.",
+ Event::JitterSenseDecrease, Event::JitterSenseIncrease);
+ wid.push_back(myTVJitterSenseWidget);
+
myTVJitterRecWidget = new SliderWidget(myTab, font,
- myTVJitterWidget->getRight() + fontWidth * 3, ypos - 1,
- "Recovery ", 0, kTVJitterChanged);
- myTVJitterRecWidget->setMinValue(1); myTVJitterRecWidget->setMaxValue(20);
+ myTVJitterSenseWidget->getRight() + fontWidth * 2, ypos - 1,
+ fontWidth * 9, lineHeight,
+ "Recovery ", 0, 0, fontWidth * 2);
+ myTVJitterRecWidget->setMinValue(JitterEmulation::MIN_RECOVERY);
+ myTVJitterRecWidget->setMaxValue(JitterEmulation::MAX_RECOVERY);
myTVJitterRecWidget->setTickmarkIntervals(5);
myTVJitterRecWidget->setToolTip("Define speed of sync recovery.",
- Event::JitterDecrease, Event::JitterIncrease);
+ Event::JitterRecDecrease, Event::JitterRecIncrease);
wid.push_back(myTVJitterRecWidget);
- myTVJitterRecLabelWidget = new StaticTextWidget(myTab, font,
- myTVJitterRecWidget->getRight() + 4,
- myTVJitterRecWidget->getTop() + 2,
- 5 * fontWidth, fontHeight);
- ypos += lineHeight + VGAP;
+ ypos += lineHeight + VGAP * 2;
myColorLossWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
"PAL color-loss");
@@ -728,6 +741,7 @@ void DeveloperDialog::getWidgetStates(SettingsSet set)
myColorLoss[set] = myColorLossWidget->getState();
// Jitter
myTVJitter[set] = myTVJitterWidget->getState();
+ myTVJitterSense[set] = myTVJitterSenseWidget->getValue();
myTVJitterRec[set] = myTVJitterRecWidget->getValue();
// States
@@ -777,9 +791,10 @@ void DeveloperDialog::setWidgetStates(SettingsSet set)
myColorLossWidget->setState(myColorLoss[set]);
// Jitter
myTVJitterWidget->setState(myTVJitter[set]);
+ myTVJitterSenseWidget->setValue(myTVJitterSense[set]);
myTVJitterRecWidget->setValue(myTVJitterRec[set]);
- handleTVJitterChange(myTVJitterWidget->getState());
+ handleTVJitterChange();
// States
myTimeMachineWidget->setState(myTimeMachine[set]);
@@ -931,6 +946,9 @@ void DeveloperDialog::setDefaults()
case 2: // Video
// Jitter
myTVJitter[set] = true;
+ myTVJitterSense[set] = devSettings
+ ? JitterEmulation::DEV_SENSITIVITY
+ : JitterEmulation::PLR_SENSITIVITY;
myTVJitterRec[set] = devSettings ? 2 : 10;
// PAL color-loss effect
myColorLoss[set] = devSettings ? true : false;
@@ -997,11 +1015,7 @@ void DeveloperDialog::handleCommand(CommandSender* sender, int cmd, int data, in
break;
case kTVJitter:
- handleTVJitterChange(myTVJitterWidget->getState());
- break;
-
- case kTVJitterChanged:
- myTVJitterRecLabelWidget->setValue(myTVJitterRecWidget->getValue());
+ handleTVJitterChange();
break;
case kTimeMachine:
@@ -1101,10 +1115,12 @@ void DeveloperDialog::handleSettings(bool devSettings)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void DeveloperDialog::handleTVJitterChange(bool enable)
+void DeveloperDialog::handleTVJitterChange()
{
+ bool enable = myTVJitterWidget->getState();
+
+ myTVJitterSenseWidget->setEnabled(enable);
myTVJitterRecWidget->setEnabled(enable);
- myTVJitterRecLabelWidget->setEnabled(enable);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/gui/DeveloperDialog.hxx b/src/gui/DeveloperDialog.hxx
index c94b2e473..2e900ef9c 100644
--- a/src/gui/DeveloperDialog.hxx
+++ b/src/gui/DeveloperDialog.hxx
@@ -60,7 +60,6 @@ class DeveloperDialog : public Dialog, DevSettingsHandler
kConsole = 'DVco',
kTIAType = 'DVtt',
kTVJitter = 'DVjt',
- kTVJitterChanged = 'DVjr',
kTimeMachine = 'DTtm',
kSizeChanged = 'DTsz',
kUncompressedChanged = 'DTuc',
@@ -125,6 +124,7 @@ class DeveloperDialog : public Dialog, DevSettingsHandler
CheckboxWidget* myTVJitterWidget{nullptr};
SliderWidget* myTVJitterRecWidget{nullptr};
StaticTextWidget* myTVJitterRecLabelWidget{nullptr};
+ SliderWidget* myTVJitterSenseWidget{nullptr};
CheckboxWidget* myColorLossWidget{nullptr};
CheckboxWidget* myDebugColorsWidget{nullptr};
std::array myDbgColour{nullptr};
@@ -160,7 +160,7 @@ class DeveloperDialog : public Dialog, DevSettingsHandler
void setWidgetStates(SettingsSet set);
void handleSettings(bool devSettings);
- void handleTVJitterChange(bool enable);
+ void handleTVJitterChange();
void handleConsole();
void handleTia();