mirror of https://github.com/stella-emu/stella.git
Improve TV mode detection logic:
* Skip the first view frames * Change the algorithm to be more eager to accept mode changes until the mode has settled for at least five frames * If in doubt, assign odd frames to NTSC
This commit is contained in:
parent
b9e2fc9022
commit
a35f378d87
|
@ -17,20 +17,24 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
// #define TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
|
|
||||||
#include "FrameManager.hxx"
|
#include "FrameManager.hxx"
|
||||||
|
|
||||||
enum Metrics: uInt32 {
|
enum Metrics: uInt32 {
|
||||||
vblankNTSC = 40,
|
vblankNTSC = 40,
|
||||||
vblankPAL = 48,
|
vblankPAL = 48,
|
||||||
kernelNTSC = 192,
|
kernelNTSC = 192,
|
||||||
kernelPAL = 228,
|
kernelPAL = 228,
|
||||||
overscanNTSC = 30,
|
overscanNTSC = 30,
|
||||||
overscanPAL = 36,
|
overscanPAL = 36,
|
||||||
vsync = 3,
|
vsync = 3,
|
||||||
visibleOverscan = 20,
|
visibleOverscan = 20,
|
||||||
maxUnderscan = 10,
|
maxUnderscan = 10,
|
||||||
maxFramesWithoutVsync = 50,
|
maxFramesWithoutVsync = 50,
|
||||||
tvModeDetectionTolerance = 20
|
tvModeDetectionTolerance = 20,
|
||||||
|
modeDetectionInitialFrameskip = 5,
|
||||||
|
framesForModeConfirmation = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr uInt32
|
static constexpr uInt32
|
||||||
|
@ -65,6 +69,9 @@ void FrameManager::reset()
|
||||||
myWaitForVsync = true;
|
myWaitForVsync = true;
|
||||||
myVsync = false;
|
myVsync = false;
|
||||||
myVblank = false;
|
myVblank = false;
|
||||||
|
myTotalFrames = 0;
|
||||||
|
myFramesInMode = 0;
|
||||||
|
myModeConfirmed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -146,7 +153,10 @@ void FrameManager::setVsync(bool vsync)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::frame:
|
case State::frame:
|
||||||
if (myVsync) finalizeFrame(State::waitForVsyncEnd);
|
if (myVsync) {
|
||||||
|
myCurrentFrameTotalLines++;
|
||||||
|
finalizeFrame(State::waitForVsyncEnd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -237,25 +247,50 @@ void FrameManager::setState(FrameManager::State state)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::finalizeFrame(FrameManager::State state)
|
void FrameManager::finalizeFrame(FrameManager::State state)
|
||||||
{
|
{
|
||||||
const uInt32
|
|
||||||
deltaNTSC = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesNTSC)),
|
|
||||||
deltaPAL = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesPAL));
|
|
||||||
|
|
||||||
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance) {
|
|
||||||
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myOnFrameComplete) {
|
if (myOnFrameComplete) {
|
||||||
myOnFrameComplete();
|
myOnFrameComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameFinalLines << " total)" << "\n").flush();
|
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameTotalLines << " total)" << "\n").flush();
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
|
|
||||||
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
|
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
|
||||||
myCurrentFrameTotalLines = 0;
|
myCurrentFrameTotalLines = 0;
|
||||||
setState(state);
|
setState(state);
|
||||||
|
|
||||||
|
myTotalFrames++;
|
||||||
|
|
||||||
|
if (myTotalFrames <= Metrics::modeDetectionInitialFrameskip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TvMode oldMode = myMode;
|
||||||
|
|
||||||
|
const uInt32
|
||||||
|
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
|
||||||
|
deltaPAL = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesPAL));
|
||||||
|
|
||||||
|
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
|
||||||
|
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
|
||||||
|
else if (!myModeConfirmed) {
|
||||||
|
if (
|
||||||
|
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
||||||
|
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
||||||
|
(myCurrentFrameFinalLines % 2)
|
||||||
|
)
|
||||||
|
setTvMode(TvMode::ntsc);
|
||||||
|
else
|
||||||
|
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldMode == myMode)
|
||||||
|
myFramesInMode++;
|
||||||
|
else
|
||||||
|
myFramesInMode = 0;
|
||||||
|
|
||||||
|
if (myFramesInMode > Metrics::framesForModeConfirmation)
|
||||||
|
myModeConfirmed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -97,6 +97,10 @@ class FrameManager : public Serializable
|
||||||
uInt32 myCurrentFrameTotalLines;
|
uInt32 myCurrentFrameTotalLines;
|
||||||
uInt32 myCurrentFrameFinalLines;
|
uInt32 myCurrentFrameFinalLines;
|
||||||
|
|
||||||
|
uInt32 myTotalFrames;
|
||||||
|
uInt32 myFramesInMode;
|
||||||
|
bool myModeConfirmed;
|
||||||
|
|
||||||
bool myVsync;
|
bool myVsync;
|
||||||
bool myVblank;
|
bool myVblank;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue