mirror of https://github.com/stella-emu/stella.git
enhanced jitter (resolves #316)
This commit is contained in:
parent
eb6d854599
commit
3beb5599e2
|
@ -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.
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 8.7 KiB |
|
@ -1982,6 +1982,18 @@
|
|||
<td>Cmd + J</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>Decrease</i> TV jitter sensitivity</td>
|
||||
<td>Shift-Control-Alt + J</td>
|
||||
<td>Shift-Control-Cmd + J</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>Increase</i> TV jitter sensitivity</td>
|
||||
<td>Control-Alt + J</td>
|
||||
<td>Control-Cmd + J</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><i>Decrease</i> TV jitter roll time</td>
|
||||
<td>Shift-Control + J</td>
|
||||
|
@ -3812,10 +3824,13 @@
|
|||
<td><pre>-<plr.|dev.>tv.jitter <1|0></pre></td>
|
||||
<td>Enable TV jitter/roll effect, when there are too many or too few scanlines
|
||||
per frame.</td>
|
||||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>tv.jitter_sense <1 - 10></pre></td>
|
||||
<td>When TV jitter/roll effect is enabled, determines the sensitivy to varying frame timings.</td>
|
||||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>tv.jitter_recovery <1 - 20></pre></td>
|
||||
<td>When TV jitter/roll effect is enabled, determines how long to delay recovery
|
||||
time (recovery spread over multiple frames).</td>
|
||||
<td>When TV jitter/roll effect is enabled, determines the recovery time for screen rolling
|
||||
(recovery spread over multiple frames).</td>
|
||||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>colorloss <1|0></pre></td>
|
||||
<td>Enable/disable the PAL color-loss effect.</td>
|
||||
|
@ -4677,6 +4692,7 @@
|
|||
<table border="1" cellpadding="4">
|
||||
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">Command Line</a></th></tr>
|
||||
<tr><td>Jitter/roll effect</td><td>Emulate screen roll with inconsistent scanline count</td><td>-plr.tv.jitter<br/>-dev.tv.jitter</td></tr>
|
||||
<tr><td>(Jitter/roll) Sensitivity</td><td>Determines sensitivity for screen rolling</td><td><span style="white-space:nowrap">-plr.tv.jitter_sense<br/>-dev.tv.jitter_sense</span></td></tr>
|
||||
<tr><td>(Jitter/roll) Recovery</td><td>Determines recovery time for screen rolling</td><td><span style="white-space:nowrap">-plr.tv.jitter_recovery<br/>-dev.tv.jitter_recovery</span></td></tr>
|
||||
<tr><td>PAL color-loss</td><td>Use PAL color-loss effect</td><td>-plr.colorloss<br/>-dev.colorloss</td></tr>
|
||||
<tr><td>Debug colors</td><td>Use fixed debug colors</td><td>-plr.debugcolors<br/>-dev.debugcolors</td></tr>
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -55,6 +55,7 @@ class DevSettingsHandler
|
|||
std::array<string, numSets> myRandomizeCPU;
|
||||
std::array<bool, numSets> myColorLoss;
|
||||
std::array<bool, numSets> myTVJitter;
|
||||
std::array<int, numSets> myTVJitterSense;
|
||||
std::array<int, numSets> myTVJitterRec;
|
||||
std::array<bool, numSets> myDebugColors;
|
||||
std::array<bool, numSets> myUndrivenPins;
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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<Int32>(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<Int32>(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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
;
|
||||
|
||||
|
|
|
@ -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)}},
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -39,7 +39,7 @@ void FrameLayoutDetector::onReset()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameLayoutDetector::onSetVsync()
|
||||
void FrameLayoutDetector::onSetVsync(uInt64)
|
||||
{
|
||||
if (myVsync)
|
||||
setState(State::waitForVsyncEnd);
|
||||
|
|
|
@ -44,7 +44,7 @@ class FrameLayoutDetector: public AbstractFrameManager
|
|||
/**
|
||||
* Hook into vsync changes.
|
||||
*/
|
||||
void onSetVsync() override;
|
||||
void onSetVsync(uInt64) override;
|
||||
|
||||
/**
|
||||
* Hook into reset.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Int32>(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<float>(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<Int32>(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<Int32>(round(scanlineCount * (1 - static_cast<float>(vsyncCycles) / myVsyncCycles)),
|
||||
myJitterLines),
|
||||
myJitterRecovery + 1); // Roll at least one scanline
|
||||
|
||||
myJitter -= jitter;
|
||||
// Limit jitter to -myYstart..scanlineCount
|
||||
if(myJitter < -myYStart)
|
||||
myJitter += 262;
|
||||
}
|
||||
else myStabilizationCounter = 0;
|
||||
if(!vsyncLinesStable)
|
||||
{
|
||||
#ifdef VSYNC_LINE_JITTER
|
||||
myJitter += minLines > maxLastLines ? myVsyncLines : -myVsyncLines;
|
||||
#else
|
||||
myJitter += vsyncCycles > myLastFrameVsyncCycles ? myVsyncLines : -myVsyncLines;
|
||||
#endif
|
||||
}
|
||||
myJitter = std::max(myJitter, -myYStart);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
else myDestabilizationCounter = 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<uInt32>(abs(scanlineDifference)) < Metrics::minDeltaForJitter) return;
|
||||
|
||||
Int32 jitter = std::min<Int32>(scanlineDifference, Metrics::maxJitter);
|
||||
jitter = std::max<Int32>(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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -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<PopUpWidget*, DEBUG_COLORS> 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();
|
||||
|
|
Loading…
Reference in New Issue