added optional autodetection of PAL-60 & NTSC-50

This commit is contained in:
Thomas Jentzsch 2022-07-13 10:34:15 +02:00
parent a80798e281
commit 1a8971e6d1
14 changed files with 275 additions and 36 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -2608,6 +2608,16 @@
<td>Adjust gamma of current palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-detectpal60 &lt;1|0&gt;</pre></td>
<td>Enable autodetection of PAL-60 based on colors used..</td>
</tr>
<tr>
<td><pre>-detectntsc50 &lt;1|0&gt;</pre></td>
<td>Enable autodetection of NTSC-50 based on colors used..</td>
</tr>
<tr>
<td><pre>-speed &lt;number&gt;</pre></td>
<td>Control the emulation speed (as a percentage, 10 - 1000).</td>
@ -3642,15 +3652,17 @@
<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>Palette</td><td>Palette used for emulation mode</td><td>-palette</td></tr>
<tr><td>NTSC/PAL phase</td><td>Adjust phase shift of 'Custom' NTSC or PAL (depends on game) palette. </td><td>-pal.phase_ntsc, -pal.phase_pal</td></tr>
<tr><td>R</td><td>Adjust red scale and shift of 'Custom' palette</td><td>-pal.red_scale, -pal.red_shift</td></tr>
<tr><td>G</td><td>Adjust green scale and shift of 'Custom' palette</td><td>-pal.green_scale, -pal.green_shift</td></tr>
<tr><td>B</td><td>Adjust blue scale and shift of 'Custom' palette</td><td>-pal.blue_scale, -pal.blue_shift</td></tr>
<tr><td>NTSC/PAL phase</td><td>Adjust phase shift of 'Custom' NTSC or PAL (depends on game) palette.</td><td>-pal.phase_ntsc<br/>-pal.phase_pal</td></tr>
<tr><td>R</td><td>Adjust red scale and shift of 'Custom' palette</td><td>-pal.red_scale<br/>-pal.red_shift</td></tr>
<tr><td>G</td><td>Adjust green scale and shift of 'Custom' palette</td><td>-pal.green_scale<br/>-pal.green_shift</td></tr>
<tr><td>B</td><td>Adjust blue scale and shift of 'Custom' palette</td><td>-pal.blue_scale<br/>-pal.blue_shift</td></tr>
<tr><td>Hue</td><td>Adjust hue of currently selected palette</td><td>-pal.hue</td></tr>
<tr><td>Saturation</td><td>Adjust saturation of currently selected palette</td><td>-pal.saturation</td></tr>
<tr><td>Contrast</td><td>Adjust contrast of currently selected palette</td><td>-pal.contrast</td></tr>
<tr><td>Brightness</td><td>Adjust brightness of currently selected palette</td><td>-pal.brightness</td></tr>
<tr><td>Gamma</td><td>Adjust gamma of currently selected palette</td><td>-pal.gamma</td></tr>
<tr><td>Autodetection</td><td>Enable autodetection of PAL-60/NTSC-50 based on colors used.</br>
Note: The detection is not very reliable and therefore uses very conservative parameters to avoid false positives.</td><td>-detectpal60<br/>-detectntsc50</td></tr>
</table>
</td>
</tr>
@ -3666,7 +3678,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>TV mode</td><td>Disable TV effects, or select TV preset</td><td>-tv.filter</td></tr>
<tr><td>Adjustable sliders</td><td>Set specific attribute in 'Custom' TV mode</td><td>-tv.sharpness, -tv.resolution, etc.</td></tr>
<tr><td>Adjustable sliders</td><td>Set specific attribute in 'Custom' TV mode</td><td>-tv.sharpness<br/>-tv.resolution, etc.</td></tr>
<tr><td>Phosphor for all ROMs</td><td>Enable phosphor mode for all ROMs</td><td>-tv.phosphor</td></tr>
<tr><td>Blend (phosphor)</td><td>Blend level to use in phosphor mode for all ROMs
(needs to be manually adjusted for your particular hardware)</td><td>-tv.phosblend</td></tr>

View File

@ -280,25 +280,54 @@ void Console::autodetectFrameLayout(bool reset)
// We turn off the SuperCharger progress bars, otherwise the SC BIOS
// will take over 250 frames!
// The 'fastscbios' option must be changed before the system is reset
bool fastscbios = myOSystem.settings().getBool("fastscbios");
myOSystem.settings().setValue("fastscbios", true);
Settings& settings = myOSystem.settings();
bool fastscbios = settings.getBool("fastscbios");
settings.setValue("fastscbios", true);
FrameLayoutDetector frameLayoutDetector;
myTIA->setFrameManager(&frameLayoutDetector);
myTIA->setFrameManager(&frameLayoutDetector, true);
if (reset) {
mySystem->reset(true);
myRiot->update();
}
for(int i = 0; i < 60; ++i) myTIA->update();
// Sample colors, ratio is 1/5 title (if existing), 4/5 game screen.
for(int i = 0; i < 20; ++i)
myTIA->update();
frameLayoutDetector.simulateInput(*myRiot, myOSystem.eventHandler(), true);
myTIA->update();
frameLayoutDetector.simulateInput(*myRiot, myOSystem.eventHandler(), false);
for(int i = 0; i < 40; ++i)
myTIA->update();
switch(frameLayoutDetector.detectedLayout(
settings.getBool("detectpal60"), settings.getBool("detectntsc50"),
myProperties.get(PropType::Cart_Name)))
{
case FrameLayout::pal:
myDisplayFormat = "PAL";
break;
case FrameLayout::pal60:
myDisplayFormat = "PAL60";
break;
case FrameLayout::ntsc50:
myDisplayFormat = "NTSC50";
break;
default:
myDisplayFormat = "NTSC";
break;
}
myTIA->setFrameManager(myFrameManager.get());
myDisplayFormat = frameLayoutDetector.detectedLayout() == FrameLayout::pal ? "PAL" : "NTSC";
// Don't forget to reset the SC progress bars again
myOSystem.settings().setValue("fastscbios", fastscbios);
settings.setValue("fastscbios", fastscbios);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -92,6 +92,9 @@ Settings::Settings()
setPermanent("tv.fringing", "0.0");
setPermanent("tv.bleed", "0.0");
setPermanent("detectpal60", "false");
setPermanent("detectntsc50", "false");
// Sound options
setPermanent(AudioSettings::SETTING_ENABLED, AudioSettings::DEFAULT_ENABLED);
setPermanent(AudioSettings::SETTING_VOLUME, AudioSettings::DEFAULT_VOLUME);
@ -516,6 +519,9 @@ void Settings::usage() const
<< " -pal.brightness <-1.0 - 1.0> Adjust brightness of current palette\n"
<< " -pal.gamma <-1.0 - 1.0> Adjust gamma of current palette\n"
<< endl
<< " -detectpal60 <1|0> Enable PAL-60 autodetection\n"
<< " -detectntsc50 <1|0> Enable NTSC-50 autodetection\n"
<< endl
<< " -speed <number> Run emulation at the given speed\n"
<< " -turbo <1|0> Enable 'Turbo' mode for maximum emulation speed\n"
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"

View File

@ -19,8 +19,10 @@
#define FRAME_LAYOUT
enum class FrameLayout {
ntsc, // ROM display has NTSC timings (~60Hz, ~262 scanlines, etc)
pal // ROM display has PAL timings (~50Hz, ~312 scanlines, etc)
ntsc, // ROM display has NTSC timings (~60Hz, ~262 scanlines, etc)
pal, // ROM display has PAL timings (~50Hz, ~312 scanlines, etc)
pal60, // ROM display has NTSC timings (~60Hz, ~262 scanlines, etc), but uses PAL colors
ntsc50 // ROM display has PAL timings (~50Hz, ~312 scanlines, etc), but uses NTSC colors
};
#endif // FRAME_LAYOUT

View File

@ -88,11 +88,12 @@ TIA::TIA(ConsoleIO& console, const ConsoleTimingProvider& timingProvider,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::setFrameManager(AbstractFrameManager* frameManager)
void TIA::setFrameManager(AbstractFrameManager* frameManager, bool layoutDetector)
{
clearFrameManager();
myFrameManager = frameManager;
myIsLayoutDetector = layoutDetector;
myFrameManager->setHandlers(
[this] () {
@ -1559,12 +1560,21 @@ void TIA::nextLine()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::cloneLastLine()
{
const auto y = myFrameManager->getY();
if(myIsLayoutDetector)
{
// y is always 0 in FrameLayoutDetector
for(uInt32 i = 0 ; i < TIAConstants::H_PIXEL; ++i)
myFrameManager->pixelColor(myBackBuffer[i]);
}
else
{
const auto y = myFrameManager->getY();
if (!myFrameManager->isRendering() || y == 0) return;
if(!myFrameManager->isRendering() || y == 0) return;
std::copy_n(myBackBuffer.begin() + (y-1) * TIAConstants::H_PIXEL, TIAConstants::H_PIXEL,
myBackBuffer.begin() + y * TIAConstants::H_PIXEL);
std::copy_n(myBackBuffer.begin() + (y - 1) * TIAConstants::H_PIXEL, TIAConstants::H_PIXEL,
myBackBuffer.begin() + y * TIAConstants::H_PIXEL);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1642,6 +1652,8 @@ void TIA::renderPixel(uInt32 x, uInt32 y)
}
myBackBuffer[y * TIAConstants::H_PIXEL + x] = color;
if (myIsLayoutDetector)
myFrameManager->pixelColor(color);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -123,7 +123,7 @@ class TIA : public Device
/**
Configure the frame manager.
*/
void setFrameManager(AbstractFrameManager* frameManager);
void setFrameManager(AbstractFrameManager* frameManager, bool layoutDetector = false);
/**
Set the audio queue. This needs to be dynamic as the queue is created after
@ -794,6 +794,11 @@ class TIA : public Device
*/
AbstractFrameManager* myFrameManager{nullptr};
/**
* The frame manager type.
*/
bool myIsLayoutDetector{false};
/**
* The various TIA objects.
*/

View File

@ -69,6 +69,11 @@ class AbstractFrameManager : public Serializable
*/
void setVsync(bool vsync, uInt64 cycles);
/**
* Called when a pixel is rendered.
*/
virtual void pixelColor(uInt8 color) {};
/**
* Should the TIA render its frame? This is buffered in a flag for
* performance reasons; descendants must update the flag.

View File

@ -15,13 +15,122 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "EventHandler.hxx"
#include "Logger.hxx"
#include "M6532.hxx"
#include "FrameLayoutDetector.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameLayout FrameLayoutDetector::detectedLayout() const
void FrameLayoutDetector::simulateInput(M6532& riot, EventHandler& eventHandler, bool pressed) const
{
// We choose the mode that was detected for the majority of frames.
return myPalFrames > myNtscFrames ? FrameLayout::pal : FrameLayout::ntsc;
// Console
eventHandler.handleEvent(Event::ConsoleSelect, pressed);
eventHandler.handleEvent(Event::ConsoleReset, pressed);
// Various controller types
eventHandler.handleEvent(Event::LeftJoystickFire, pressed);
eventHandler.handleEvent(Event::RightJoystickFire, pressed);
// Required for Console::redetectFrameLayout
eventHandler.handleEvent(Event::LeftPaddleAFire, pressed);
eventHandler.handleEvent(Event::LeftPaddleBFire, pressed);
eventHandler.handleEvent(Event::RightPaddleAFire, pressed);
eventHandler.handleEvent(Event::RightPaddleBFire, pressed);
eventHandler.handleEvent(Event::LeftDrivingFire, pressed);
eventHandler.handleEvent(Event::RightDrivingFire, pressed);
riot.update();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameLayout FrameLayoutDetector::detectedLayout(bool detectPal60, bool detectNtsc50, const string& name) const
{
#if 0 // debug
cerr << endl << name << endl;
int i = 0;
for(auto count : myColorCount)
{
if(i % 8 == 0)
cerr << std::uppercase << std::setw(2) << std::hex << (i >> 3) << "x: ";
cerr << std::setw(6) << std::dec << count;
if(++i % 8 == 0)
cerr << endl;
else
cerr << ", ";
}
cerr << endl;
#endif
#if 0 // save sampled color values
std::ofstream file;
file.open("d:/Users/Thomas/Documents/Atari/Games/test/autodetect/colors.csv", std::ios::app);
if(file.is_open())
{
file << name;
for(auto count : myColorCount)
file << "; " << count;
file << "\n";
file.close();
}
#endif
// Multiply each hue's count with its NTSC and PAL stats and aggregate results
// If NTSC/PAL results differ significantly, overrule frame result
FrameLayout layout = myPalFrames > myNtscFrames ? FrameLayout::pal : FrameLayout::ntsc;
constexpr std::array<double, NUM_HUES> ntscColorFactor{
0.00000, 0.05683, 0.06220, 0.05505, 0.06162, 0.02874, 0.03532, 0.03716,
0.15568, 0.06471, 0.02886, 0.03224, 0.06903, 0.11478, 0.02632, 0.01675
}; // ignore black = 0x00!
constexpr std::array<double, NUM_HUES> palColorFactor{
0.00000, 0.00450, 0.09962, 0.07603, 0.06978, 0.13023, 0.09638, 0.02268,
0.02871, 0.04700, 0.02950, 0.11974, 0.03474, 0.08025, 0.00642, 0.00167
}; // ignore black = 0x00!
// Calculation weights and params (optimum based on sampled ROMs optimized for PAL-60)
constexpr double POWER_FACTOR = 0.17; // Level the color counts (large values become less relevant)
constexpr uInt32 SUM_DIV = 20; // Skip too small counts
constexpr uInt32 MIN_VALID = 3; // Minimum number of different hues with significant counts
constexpr double SUM_FACTOR = 2.0; // Minimum sum difference which triggers a layout change
double ntscSum{0}, palSum{0};
std::array<double, NUM_HUES> hueSum{0};
double totalHueSum = 0;
uInt32 validHues = 0;
// Aggregate hues
for(int hue = 0; hue < NUM_HUES; ++hue)
{
for(int lum = 0; lum < NUM_LUMS; ++lum)
if(hue || lum) // skip 0x00
hueSum[hue] += myColorCount[hue * NUM_LUMS + lum];
hueSum[hue] = std::pow(hueSum[hue], POWER_FACTOR);
totalHueSum += hueSum[hue];
}
// Calculate hue sums
for(int hue = 0; hue < NUM_HUES; ++hue)
{
if(hueSum[hue] > totalHueSum / SUM_DIV)
validHues++;
ntscSum += hueSum[hue] * ntscColorFactor[hue];
palSum += hueSum[hue] * palColorFactor[hue];
}
// Correct layout if enough valid hues and significant sum difference
// TODO: Use fractional scanline counts for intermediate values around 285 scanlines, e.g.
// Desert Falcon, Dumbo's Flying Circus, Dungeon, Firefox, Millipede, Popeye, RS Basketball, Star Trek, Stunt Cycle
if(validHues >= MIN_VALID)
{
if(detectPal60 && layout == FrameLayout::ntsc && ntscSum * SUM_FACTOR < palSum)
{
layout = FrameLayout::pal60;
Logger::debug("Changed layout from NTSC into PAL-60");
}
// Note: three false positives (Berzerk, Canyon Bomber, Jawbreaker) for NTSC-50 after
// optimizing for PAL-60
else if(detectNtsc50 && layout == FrameLayout::pal && palSum * SUM_FACTOR < ntscSum)
{
layout = FrameLayout::ntsc50;
Logger::debug("Changed layout from PAL into NTSC-50");
}
}
return layout;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -36,6 +145,8 @@ void FrameLayoutDetector::onReset()
myState = State::waitForVsyncStart;
myNtscFrames = myPalFrames = 0;
myLinesWaitingForVsyncToStart = 0;
myColorCount.fill(0);
myIsRendering = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -73,6 +184,16 @@ void FrameLayoutDetector::onNextLine()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameLayoutDetector::pixelColor(uInt8 color)
{
if(myTotalFrames > Metrics::initialGarbageFrames)
myColorCount[color >> 1]++;
// Ideas:
// - contrast to previous pixels (left/top)
// - ???
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameLayoutDetector::setState(State state)
{
@ -112,15 +233,15 @@ void FrameLayoutDetector::finalizeFrame()
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
else if (
// If scanline count is odd and lies between the PAL and NTSC windows we assume
// it is NTSC (it would cause color loss on PAL CRTs)
// If scanline count is odd and lies between the PAL and NTSC windows we assume
// it is NTSC (it would cause color loss on PAL CRTs)
(myCurrentFrameFinalLines < frameLinesPAL) &&
(myCurrentFrameFinalLines > frameLinesNTSC) &&
(myCurrentFrameFinalLines % 2)
)
layout(FrameLayout::ntsc);
else
// Take the nearest layout if all else fails
// Take the nearest layout if all else fails
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
switch (layout()) {

View File

@ -18,6 +18,9 @@
#ifndef TIA_FRAME_LAYOUT_DETECTOR
#define TIA_FRAME_LAYOUT_DETECTOR
class M6532;
class EventHandler;
#include "FrameLayout.hxx"
#include "AbstractFrameManager.hxx"
#include "TIAConstants.hxx"
@ -37,7 +40,13 @@ class FrameLayoutDetector: public AbstractFrameManager
/**
* Return the detected frame layout.
*/
FrameLayout detectedLayout() const;
FrameLayout detectedLayout(bool detectPal60 = false, bool detectNtsc50 = false,
const string& name = EmptyString) const;
/**
* Simulate some input to pass a potential title screen.
*/
void FrameLayoutDetector::simulateInput(M6532& riot, EventHandler& eventHandler, bool pressed) const;
protected:
@ -56,6 +65,11 @@ class FrameLayoutDetector: public AbstractFrameManager
*/
void onNextLine() override;
/**
* Called when a pixel is rendered.
*/
void pixelColor(uInt8 color) override;
private:
/**
@ -118,6 +132,16 @@ class FrameLayoutDetector: public AbstractFrameManager
*/
uInt32 myLinesWaitingForVsyncToStart{0};
/**
* We count the number of pixels for each colors used. These are
* evaluated against statistical color distributions and, if
* decisive, allow overruling the scanline results.
*/
static constexpr int NUM_HUES = 16;
static constexpr int NUM_LUMS = 8;
std::array<uInt64, NUM_HUES * NUM_LUMS> myColorCount{0};
private:
FrameLayoutDetector(const FrameLayoutDetector&) = delete;

View File

@ -56,10 +56,10 @@ void JitterEmulation::setSensitivity(Int32 sensitivity)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
//#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;

View File

@ -148,16 +148,16 @@ void GameInfoDialog::addEmulationTab()
VarList::push_back(items, "NTSC", "NTSC");
VarList::push_back(items, "PAL", "PAL");
VarList::push_back(items, "SECAM", "SECAM");
VarList::push_back(items, "NTSC50", "NTSC50");
VarList::push_back(items, "PAL60", "PAL60");
VarList::push_back(items, "SECAM60", "SECAM60");
VarList::push_back(items, "NTSC-50", "NTSC50");
VarList::push_back(items, "PAL-60", "PAL60");
VarList::push_back(items, "SECAM-60", "SECAM60");
myFormat = new PopUpWidget(myTab, _font, t->getRight(), ypos,
pwidth, lineHeight, items);
myFormat->setToolTip(Event::FormatDecrease, Event::FormatIncrease);
wid.push_back(myFormat);
myFormatDetected = new StaticTextWidget(myTab, ifont, myFormat->getRight() + fontWidth, ypos + 4,
"SECAM60 detected");
"SECAM-60 detected");
// Phosphor
ypos += lineHeight + VGAP;

View File

@ -65,7 +65,7 @@ VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions
setSize(44 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2,
_th + VGAP * 3 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3,
_th + VGAP * 5 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3,
max_w, max_h);
// The tab widget
@ -312,6 +312,17 @@ void VideoAudioDialog::addPaletteTab()
CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", kPaletteUpdated)
CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated)
ypos += VGAP;
StaticTextWidget* s = new StaticTextWidget(myTab, _font, xpos, ypos + 1, "Autodetection");
myDetectPal60 = new CheckboxWidget(myTab, _font, s->getRight() + fontWidth * 2, ypos + 1, "PAL-60");
myDetectPal60 ->setToolTip("Enable autodetection of PAL-60 based on colors used.");
wid.push_back(myDetectPal60 );
myDetectNtsc50 = new CheckboxWidget(myTab, _font, myDetectPal60->getRight() + fontWidth * 2, ypos + 1, "NTSC-50");
myDetectNtsc50 ->setToolTip("Enable autodetection of NTSC-50 based on colors used.");
wid.push_back(myDetectNtsc50 );
// The resulting palette
xpos = myPhaseShift->getRight() + fontWidth * 2;
addPalette(xpos, VBORDER, _w - 2 * 2 - HBORDER - xpos,
@ -644,6 +655,10 @@ void VideoAudioDialog::loadConfig()
handlePaletteChange();
colorPalette();
// Autodetection
myDetectPal60->setState(settings.getBool("detectpal60"));
myDetectNtsc50->setState(settings.getBool("detectntsc50"));
/////////////////////////////////////////////////////////////////////////////
// TV Effects tab
// TV Mode
@ -758,6 +773,10 @@ void VideoAudioDialog::saveConfig()
Logger::debug("Saving palette settings...");
instance().frameBuffer().tiaSurface().paletteHandler().saveConfig(settings);
// Autodetection
settings.setValue("detectpal60", myDetectPal60->getState());
settings.setValue("detectntsc50", myDetectNtsc50->getState());
/////////////////////////////////////////////////////////////////////////////
// TV Effects tab
// TV Mode
@ -893,6 +912,8 @@ void VideoAudioDialog::setDefaults()
myTVGamma->setValue(50);
handlePaletteChange();
handlePaletteUpdate();
myDetectPal60->setState(false);
myDetectNtsc50->setState(false);
break;
}

View File

@ -106,6 +106,8 @@ class VideoAudioDialog : public Dialog
// Palettes
PopUpWidget* myTIAPalette{nullptr};
CheckboxWidget* myDetectPal60{nullptr};
CheckboxWidget* myDetectNtsc50{nullptr};
SliderWidget* myPhaseShift{nullptr};
SliderWidget* myTVRedScale{nullptr};
SliderWidget* myTVRedShift{nullptr};