From 1a8971e6d1fa2de9e603fa7df772363a418b760b Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Wed, 13 Jul 2022 10:34:15 +0200 Subject: [PATCH 1/2] added optional autodetection of PAL-60 & NTSC-50 --- docs/graphics/options_video_palettes.png | Bin 9315 -> 9802 bytes docs/index.html | 22 ++- src/emucore/Console.cxx | 43 +++++- src/emucore/Settings.cxx | 6 + src/emucore/tia/FrameLayout.hxx | 6 +- src/emucore/tia/TIA.cxx | 22 ++- src/emucore/tia/TIA.hxx | 7 +- .../frame-manager/AbstractFrameManager.hxx | 5 + .../tia/frame-manager/FrameLayoutDetector.cxx | 133 +++++++++++++++++- .../tia/frame-manager/FrameLayoutDetector.hxx | 26 +++- .../tia/frame-manager/JitterEmulation.cxx | 8 +- src/gui/GameInfoDialog.cxx | 8 +- src/gui/VideoAudioDialog.cxx | 23 ++- src/gui/VideoAudioDialog.hxx | 2 + 14 files changed, 275 insertions(+), 36 deletions(-) diff --git a/docs/graphics/options_video_palettes.png b/docs/graphics/options_video_palettes.png index 2a6f66be875da565378f7b874601bdf5c7df0200..9c231eb9283c7aa5ac7789e026e2ba4aa25b4071 100644 GIT binary patch literal 9802 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%0AYykjYsycBQg3a0Y*o7 zWw={bV%W&S9hzZ+GO~^oS?{4-Gq-eS3iS@h-yQ ztCK?cM)}94d$man%&zHN=QlyqhmNCtPH;b5J;vbiS>nYc+JjL=wxf4pa3!V-W#+Rx z*&YGcCZMS2NY`W84CVuxWk=&#zLu6u`oF5H$=DD-vy?`Uu(oHw`m5xYoq$W~-$?N$ z+Rl+3D3bu8lwW?F$ifG2^G@KBa12b2cVa1sYBEp3xxBIO?T_a zx4HfUD|+?}lOk29Y~?3l<+qtmrwGWZxt5D_Cu=QS?)7~{m`Utc=Uo$cBVHbKk$GiR zoUB?=y2xHU7rI9iX%MUcHs7%jgbbD_Mp05G>NJ9HKTZtC#DwRAg^PgkXrO zQ67mVGu!dT)-K#rtHwa;p65yf?S%jXOqXqI;eFhY;&FxO#JF1RwcG8(Q3YT&f4tlKPzU?%SXOtIZYqB^h zTXG!UYeacqI@8E>`p)){gxT6Ml*l2rk$phseU8M?3#aT?kz-S8J6NT~S_1N1T6(hu zf!uQCRVnbYLv&d$E^HGRV*j&58OSUcWt}HiGHzr*=}e#i6Hk+juy$cw>u(pR`t+w| zN<``MmIe4X+#4;Ln*|#7kfDU}k^*%15*x=8F~qICv~ckKHHkFC1=of3s5I+tOtFB( zUlpPJRmE^&%ep)-o*kt1k-x*!E|#*(*$2#Bj^G}Ik)g_tbU)vi zv~zmX$8Bs4-;08${Cg_DG8KDF{2oKh$tL2*w6QP((5*}7qbnfvfY;B7E3cnxltLCt z@4J5zuC9KaBQGecV(s$|CENEBqd9f$_E<{_rl}x4zQ>|%Z;xc}O_Eny(Q!&$IS;+N zY0;F6(A{I>{iVWIdvNzI@OT0ABGe3Mtg{J6VIHZy7w0@i~f;h zVq3;FI`-u>>`n6*lxiA>uF7+G1QMdD5F0C^n2EFn$JZZ)wG9cJ;+O5s^qW)Ek87^U z^2v6WLa63NzDb|{bjwxfgmUEtQjcbj%t0h_4)y4BHKIiJpsZ^idHz9U9MU0A>B@Cc z>STs%iBMs0UhfYAu=}ps0eVH`=+8bKALDJd&APW|7RM(D+1!P$TID>llh5!1Hmuy?=OZ4eiFwPV)F{bY#v9=Rk~W~ wxsid!>90y^<(~-FJ`~hEmFknlEikjptpkdbD_Vj7I05ONH#nE8@#nq&0-Tq4hyVZp diff --git a/docs/index.html b/docs/index.html index 67ad5604f..53a393266 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2608,6 +2608,16 @@ Adjust gamma of current palette (range -1.0 to 1.0). + +
-detectpal60 <1|0>
+ Enable autodetection of PAL-60 based on colors used.. + + + +
-detectntsc50 <1|0>
+ Enable autodetection of NTSC-50 based on colors used.. + +
-speed <number>
Control the emulation speed (as a percentage, 10 - 1000). @@ -3642,15 +3652,17 @@ - - - - + + + + +
ItemBrief descriptionFor more information,
see Command Line
PalettePalette used for emulation mode-palette
NTSC/PAL phaseAdjust phase shift of 'Custom' NTSC or PAL (depends on game) palette. -pal.phase_ntsc, -pal.phase_pal
RAdjust red scale and shift of 'Custom' palette-pal.red_scale, -pal.red_shift
GAdjust green scale and shift of 'Custom' palette-pal.green_scale, -pal.green_shift
BAdjust blue scale and shift of 'Custom' palette-pal.blue_scale, -pal.blue_shift
NTSC/PAL phaseAdjust phase shift of 'Custom' NTSC or PAL (depends on game) palette.-pal.phase_ntsc
-pal.phase_pal
RAdjust red scale and shift of 'Custom' palette-pal.red_scale
-pal.red_shift
GAdjust green scale and shift of 'Custom' palette-pal.green_scale
-pal.green_shift
BAdjust blue scale and shift of 'Custom' palette-pal.blue_scale
-pal.blue_shift
HueAdjust hue of currently selected palette-pal.hue
SaturationAdjust saturation of currently selected palette-pal.saturation
ContrastAdjust contrast of currently selected palette-pal.contrast
BrightnessAdjust brightness of currently selected palette-pal.brightness
GammaAdjust gamma of currently selected palette-pal.gamma
AutodetectionEnable autodetection of PAL-60/NTSC-50 based on colors used.
+ Note: The detection is not very reliable and therefore uses very conservative parameters to avoid false positives.
-detectpal60
-detectntsc50
@@ -3666,7 +3678,7 @@ - + diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index edb160d1e..6dcfbb238 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index d6e31cd31..2613eb512 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -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 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" diff --git a/src/emucore/tia/FrameLayout.hxx b/src/emucore/tia/FrameLayout.hxx index affbf7da1..6c6dabba4 100644 --- a/src/emucore/tia/FrameLayout.hxx +++ b/src/emucore/tia/FrameLayout.hxx @@ -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 diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 4c61e197f..5b94814a0 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 3c80163a4..77714b132 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -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. */ diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx index a69b5118c..2422e57ea 100644 --- a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx +++ b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx @@ -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. diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx index 6861ff8bb..5bce1774c 100644 --- a/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx +++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.cxx @@ -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 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 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 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()) { diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx index da72a0cf9..a9b40752f 100644 --- a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx +++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx @@ -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 myColorCount{0}; + private: FrameLayoutDetector(const FrameLayoutDetector&) = delete; diff --git a/src/emucore/tia/frame-manager/JitterEmulation.cxx b/src/emucore/tia/frame-manager/JitterEmulation.cxx index b151cb7e7..b31a20852 100644 --- a/src/emucore/tia/frame-manager/JitterEmulation.cxx +++ b/src/emucore/tia/frame-manager/JitterEmulation.cxx @@ -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; diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index e9192c223..eb83b563c 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -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; diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx index 971011d87..9b0fe23f1 100644 --- a/src/gui/VideoAudioDialog.cxx +++ b/src/gui/VideoAudioDialog.cxx @@ -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; } diff --git a/src/gui/VideoAudioDialog.hxx b/src/gui/VideoAudioDialog.hxx index 098658145..7370e21fd 100644 --- a/src/gui/VideoAudioDialog.hxx +++ b/src/gui/VideoAudioDialog.hxx @@ -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}; From 5ad9c0e5ce206faa7b5185ac952bc2529633e110 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Wed, 13 Jul 2022 11:32:27 -0230 Subject: [PATCH 2/2] Fix minor compile warnings. --- src/common/main.cxx | 9 +++++++++ src/emucore/ProfilingRunner.cxx | 3 +++ src/emucore/tia/frame-manager/AbstractFrameManager.hxx | 2 +- src/emucore/tia/frame-manager/FrameLayoutDetector.hxx | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/common/main.cxx b/src/common/main.cxx index 1354801f7..b2ebb5e58 100644 --- a/src/common/main.cxx +++ b/src/common/main.cxx @@ -74,6 +74,15 @@ void checkForCustomBaseDir(Settings::Options& options); */ bool isProfilingRun(int ac, char* av[]); +/** + In Windows, attach console to allow command line output (e.g. for -help). + This is needed since by default Windows doesn't set up stdout/stderr + correctly. +*/ +void attachConsole(); +void freeConsole(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void parseCommandLine(int ac, char* av[], Settings::Options& globalOpts, Settings::Options& localOpts) diff --git a/src/emucore/ProfilingRunner.cxx b/src/emucore/ProfilingRunner.cxx index 95c43ba99..b64b80845 100644 --- a/src/emucore/ProfilingRunner.cxx +++ b/src/emucore/ProfilingRunner.cxx @@ -157,6 +157,9 @@ bool ProfilingRunner::runOne(const ProfilingRun& run) cout << "PAL"; consoleTiming = ConsoleTiming::pal; break; + + default: // TODO: add other layouts here + break; } (cout << endl).flush(); diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx index 2422e57ea..bcaef4589 100644 --- a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx +++ b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx @@ -72,7 +72,7 @@ class AbstractFrameManager : public Serializable /** * Called when a pixel is rendered. */ - virtual void pixelColor(uInt8 color) {}; + virtual void pixelColor(uInt8 color) {} /** * Should the TIA render its frame? This is buffered in a flag for diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx index a9b40752f..bdb8ad391 100644 --- a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx +++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx @@ -46,7 +46,7 @@ class FrameLayoutDetector: public AbstractFrameManager /** * Simulate some input to pass a potential title screen. */ - void FrameLayoutDetector::simulateInput(M6532& riot, EventHandler& eventHandler, bool pressed) const; + void simulateInput(M6532& riot, EventHandler& eventHandler, bool pressed) const; protected:
ItemBrief descriptionFor more information,
see Command Line
TV modeDisable TV effects, or select TV preset-tv.filter
Adjustable slidersSet specific attribute in 'Custom' TV mode-tv.sharpness, -tv.resolution, etc.
Adjustable slidersSet specific attribute in 'Custom' TV mode-tv.sharpness
-tv.resolution, etc.
Phosphor for all ROMsEnable phosphor mode for all ROMs-tv.phosphor
Blend (phosphor)Blend level to use in phosphor mode for all ROMs (needs to be manually adjusted for your particular hardware)-tv.phosblend