mirror of https://github.com/stella-emu/stella.git
Documentation, minor simplificationsDocumentation, minor simplifications.
This commit is contained in:
parent
4f31166e11
commit
12afce8c0d
|
@ -18,6 +18,9 @@
|
||||||
#include "FrameLayoutDetector.hxx"
|
#include "FrameLayoutDetector.hxx"
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Misc. numeric constants used in the algorithm.
|
||||||
|
*/
|
||||||
enum Metrics: uInt32 {
|
enum Metrics: uInt32 {
|
||||||
frameLinesNTSC = 262,
|
frameLinesNTSC = 262,
|
||||||
frameLinesPAL = 312,
|
frameLinesPAL = 312,
|
||||||
|
@ -28,6 +31,7 @@ enum Metrics: uInt32 {
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameLayout FrameLayoutDetector::detectedLayout() const{
|
FrameLayout FrameLayoutDetector::detectedLayout() const{
|
||||||
|
// We choose the mode that was detected for the majority of frames.
|
||||||
return myPalFrames > myNtscFrames ? FrameLayout::pal : FrameLayout::ntsc;
|
return myPalFrames > myNtscFrames ? FrameLayout::pal : FrameLayout::ntsc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +59,8 @@ void FrameLayoutDetector::onNextLine()
|
||||||
|
|
||||||
switch (myState) {
|
switch (myState) {
|
||||||
case State::waitForVsyncStart:
|
case State::waitForVsyncStart:
|
||||||
|
// We start counting the number of "lines spent while waiting for vsync start" from
|
||||||
|
// the "ideal" frame size (corrected by the three scanlines spent in vsync).
|
||||||
if (myCurrentFrameTotalLines > frameLines - 3 || myTotalFrames == 0)
|
if (myCurrentFrameTotalLines > frameLines - 3 || myTotalFrames == 0)
|
||||||
myLinesWaitingForVsync++;
|
myLinesWaitingForVsync++;
|
||||||
|
|
||||||
|
@ -78,15 +84,13 @@ void FrameLayoutDetector::setState(State state)
|
||||||
if (state == myState) return;
|
if (state == myState) return;
|
||||||
|
|
||||||
myState = state;
|
myState = state;
|
||||||
|
myLinesWaitingForVsync = 0;
|
||||||
|
|
||||||
switch (myState) {
|
switch (myState) {
|
||||||
case State::waitForVsyncEnd:
|
case State::waitForVsyncEnd:
|
||||||
myLinesWaitingForVsync = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::waitForVsyncStart:
|
case State::waitForVsyncStart:
|
||||||
myLinesWaitingForVsync = 0;
|
|
||||||
|
|
||||||
finalizeFrame();
|
finalizeFrame();
|
||||||
notifyFrameStart();
|
notifyFrameStart();
|
||||||
break;
|
break;
|
||||||
|
@ -103,19 +107,25 @@ void FrameLayoutDetector::finalizeFrame()
|
||||||
|
|
||||||
if (myTotalFrames <= Metrics::initialGarbageFrames) return;
|
if (myTotalFrames <= Metrics::initialGarbageFrames) return;
|
||||||
|
|
||||||
|
// Calculate the delta between scanline count and the sweet spot for the respective
|
||||||
|
// frame layouts
|
||||||
const uInt32
|
const uInt32
|
||||||
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
|
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
|
||||||
deltaPAL = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesPAL));
|
deltaPAL = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesPAL));
|
||||||
|
|
||||||
|
// Does the scanline count fall into one of our tolerance windows? -> use it
|
||||||
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
|
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
|
||||||
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
||||||
else if (
|
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)
|
||||||
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
||||||
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
||||||
(myCurrentFrameFinalLines % 2)
|
(myCurrentFrameFinalLines % 2)
|
||||||
)
|
)
|
||||||
layout(FrameLayout::ntsc);
|
layout(FrameLayout::ntsc);
|
||||||
else
|
else
|
||||||
|
// Take the nearest layout if all else fails
|
||||||
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
||||||
|
|
||||||
switch (layout()) {
|
switch (layout()) {
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
#include "AbstractFrameManager.hxx"
|
#include "AbstractFrameManager.hxx"
|
||||||
#include "FrameLayout.hxx"
|
#include "FrameLayout.hxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This frame manager performs frame layout autodetection. It counts the scanlines
|
||||||
|
* in each frame and assigns guesses the frame layout from this.
|
||||||
|
*/
|
||||||
class FrameLayoutDetector: public AbstractFrameManager {
|
class FrameLayoutDetector: public AbstractFrameManager {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -28,36 +32,70 @@ class FrameLayoutDetector: public AbstractFrameManager {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the detected frame layout.
|
||||||
|
*/
|
||||||
FrameLayout detectedLayout() const;
|
FrameLayout detectedLayout() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into vsync changes.
|
||||||
|
*/
|
||||||
void onSetVsync() override;
|
void onSetVsync() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into reset.
|
||||||
|
*/
|
||||||
void onReset() override;
|
void onReset() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into line changes.
|
||||||
|
*/
|
||||||
void onNextLine() override;
|
void onNextLine() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This frame manager only tracks frame boundaries, so we have only two states.
|
||||||
|
*/
|
||||||
enum State {
|
enum State {
|
||||||
|
// Wait for VSYNC to be enabled.
|
||||||
waitForVsyncStart,
|
waitForVsyncStart,
|
||||||
|
|
||||||
|
// Wait for VSYNC to be disabled.
|
||||||
waitForVsyncEnd
|
waitForVsyncEnd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change state and change internal state accordingly.
|
||||||
|
*/
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize the current frame and guess frame layout from the scanline count.
|
||||||
|
*/
|
||||||
void finalizeFrame();
|
void finalizeFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current state.
|
||||||
|
*/
|
||||||
State myState;
|
State myState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of frames detected as the respective frame layout.
|
||||||
|
*/
|
||||||
uInt32 myNtscFrames, myPalFrames;
|
uInt32 myNtscFrames, myPalFrames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We count the number of scanlines we spend waiting for vsync to be
|
||||||
|
* toggled. If a threshold is exceeded, we force the transition.
|
||||||
|
*/
|
||||||
uInt32 myLinesWaitingForVsync;
|
uInt32 myLinesWaitingForVsync;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue