mirror of https://github.com/stella-emu/stella.git
Merge branch 'refactoring/frame_manager'
This commit is contained in:
commit
2c96258890
|
@ -8,3 +8,4 @@ project.xcworkspace/
|
||||||
xcuserdata/
|
xcuserdata/
|
||||||
build/
|
build/
|
||||||
src/macosx/M6502.ins
|
src/macosx/M6502.ins
|
||||||
|
*.dSYM
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"${workspaceRoot}/src/gui",
|
"${workspaceRoot}/src/gui",
|
||||||
"${workspaceRoot}/src/emucore",
|
"${workspaceRoot}/src/emucore",
|
||||||
"${workspaceRoot}/src/emucore/tia",
|
"${workspaceRoot}/src/emucore/tia",
|
||||||
|
"${workspaceRoot}/src/emucore/tia/frame-manager",
|
||||||
"${workspaceRoot}/src/unix",
|
"${workspaceRoot}/src/unix",
|
||||||
"${workspaceRoot}/src/debugger",
|
"${workspaceRoot}/src/debugger",
|
||||||
"${workspaceRoot}/src/debugger/gui",
|
"${workspaceRoot}/src/debugger/gui",
|
||||||
|
|
|
@ -12,5 +12,9 @@
|
||||||
"editor.trimAutoWhitespace": true,
|
"editor.trimAutoWhitespace": true,
|
||||||
"editor.useTabStops": false,
|
"editor.useTabStops": false,
|
||||||
"C_Cpp.intelliSenseEngine": "Default",
|
"C_Cpp.intelliSenseEngine": "Default",
|
||||||
"files.insertFinalNewline": true
|
"files.insertFinalNewline": true,
|
||||||
|
"files.associations": {
|
||||||
|
"locale": "cpp",
|
||||||
|
"string": "cpp"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1
Makefile
1
Makefile
|
@ -98,6 +98,7 @@ MODULES := $(MODULES)
|
||||||
MODULES += \
|
MODULES += \
|
||||||
src/emucore \
|
src/emucore \
|
||||||
src/emucore/tia \
|
src/emucore/tia \
|
||||||
|
src/emucore/tia/frame-manager \
|
||||||
src/gui \
|
src/gui \
|
||||||
src/common \
|
src/common \
|
||||||
src/common/tv_filters
|
src/common/tv_filters
|
||||||
|
|
|
@ -691,6 +691,7 @@ SRC="src"
|
||||||
CORE="$SRC/emucore"
|
CORE="$SRC/emucore"
|
||||||
COMMON="$SRC/common"
|
COMMON="$SRC/common"
|
||||||
TIA="$SRC/emucore/tia"
|
TIA="$SRC/emucore/tia"
|
||||||
|
TIA_FRAME_MANAGER="$SRC/emucore/tia/frame-manager"
|
||||||
TV="$SRC/common/tv_filters"
|
TV="$SRC/common/tv_filters"
|
||||||
GUI="$SRC/gui"
|
GUI="$SRC/gui"
|
||||||
DBG="$SRC/debugger"
|
DBG="$SRC/debugger"
|
||||||
|
@ -700,7 +701,7 @@ CHEAT="$SRC/cheat"
|
||||||
LIBPNG="$SRC/libpng"
|
LIBPNG="$SRC/libpng"
|
||||||
ZLIB="$SRC/zlib"
|
ZLIB="$SRC/zlib"
|
||||||
|
|
||||||
INCLUDES="-I$CORE -I$COMMON -I$TV -I$GUI -I$TIA"
|
INCLUDES="-I$CORE -I$COMMON -I$TV -I$GUI -I$TIA -I$TIA_FRAME_MANAGER"
|
||||||
|
|
||||||
INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
|
INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
|
||||||
if test "$_build_static" = yes ; then
|
if test "$_build_static" = yes ; then
|
||||||
|
|
|
@ -48,7 +48,7 @@ const DebuggerState& TIADebug::getState()
|
||||||
myState.coluRegs.push_back(coluBK());
|
myState.coluRegs.push_back(coluBK());
|
||||||
|
|
||||||
// Debug Colors
|
// Debug Colors
|
||||||
int mode = myTIA.myFrameManager.layout() == FrameLayout::ntsc ? 0 : 1;
|
int mode = myTIA.frameLayout() == FrameLayout::ntsc ? 0 : 1;
|
||||||
myState.fixedCols.clear();
|
myState.fixedCols.clear();
|
||||||
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P0]);
|
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P0]);
|
||||||
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P1]);
|
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P1]);
|
||||||
|
@ -721,7 +721,7 @@ int TIADebug::scanlines() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int TIADebug::scanlinesLastFrame() const
|
int TIADebug::scanlinesLastFrame() const
|
||||||
{
|
{
|
||||||
return myTIA.myFrameManager.scanlinesLastFrame();
|
return myTIA.scanlinesLastFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -807,7 +807,7 @@ string TIADebug::debugColors() const
|
||||||
{
|
{
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
|
|
||||||
int mode = myTIA.myFrameManager.layout() == FrameLayout::ntsc ? 0 : 1;
|
int mode = myTIA.frameLayout() == FrameLayout::ntsc ? 0 : 1;
|
||||||
buf << " Red " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P0])
|
buf << " Red " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P0])
|
||||||
<< " Player 0\n"
|
<< " Player 0\n"
|
||||||
<< " Orange " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M0])
|
<< " Orange " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M0])
|
||||||
|
|
|
@ -55,8 +55,11 @@
|
||||||
#include "CommandMenu.hxx"
|
#include "CommandMenu.hxx"
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "Version.hxx"
|
#include "Version.hxx"
|
||||||
#include "FrameManager.hxx"
|
#include "TIAConstants.hxx"
|
||||||
#include "FrameLayout.hxx"
|
#include "FrameLayout.hxx"
|
||||||
|
#include "frame-manager/FrameManager.hxx"
|
||||||
|
#include "frame-manager/FrameLayoutDetector.hxx"
|
||||||
|
#include "frame-manager/YStartDetector.hxx"
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "Debugger.hxx"
|
#include "Debugger.hxx"
|
||||||
|
@ -77,7 +80,8 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
myCart(std::move(cart)),
|
myCart(std::move(cart)),
|
||||||
myDisplayFormat(""), // Unknown TV format @ start
|
myDisplayFormat(""), // Unknown TV format @ start
|
||||||
myFramerate(0.0), // Unknown framerate @ start
|
myFramerate(0.0), // Unknown framerate @ start
|
||||||
myCurrentFormat(0), // Unknown format @ start
|
myCurrentFormat(0), // Unknown format @ start,
|
||||||
|
myAutodetectedYstart(0),
|
||||||
myUserPaletteDefined(false),
|
myUserPaletteDefined(false),
|
||||||
myConsoleTiming(ConsoleTiming::ntsc)
|
myConsoleTiming(ConsoleTiming::ntsc)
|
||||||
{
|
{
|
||||||
|
@ -88,8 +92,11 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
my6502 = make_unique<M6502>(myOSystem.settings());
|
my6502 = make_unique<M6502>(myOSystem.settings());
|
||||||
myRiot = make_unique<M6532>(*this, myOSystem.settings());
|
myRiot = make_unique<M6532>(*this, myOSystem.settings());
|
||||||
myTIA = make_unique<TIA>(*this, myOSystem.sound(), myOSystem.settings());
|
myTIA = make_unique<TIA>(*this, myOSystem.sound(), myOSystem.settings());
|
||||||
|
myFrameManager = make_unique<FrameManager>();
|
||||||
mySwitches = make_unique<Switches>(myEvent, myProperties);
|
mySwitches = make_unique<Switches>(myEvent, myProperties);
|
||||||
|
|
||||||
|
myTIA->setFrameManager(myFrameManager.get());
|
||||||
|
|
||||||
// Construct the system and components
|
// Construct the system and components
|
||||||
mySystem = make_unique<System>(osystem, *my6502, *myRiot, *myTIA, *myCart);
|
mySystem = make_unique<System>(osystem, *my6502, *myRiot, *myTIA, *myCart);
|
||||||
|
|
||||||
|
@ -114,36 +121,19 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
|
|
||||||
if(myDisplayFormat == "AUTO" || myOSystem.settings().getBool("rominfo"))
|
if(myDisplayFormat == "AUTO" || myOSystem.settings().getBool("rominfo"))
|
||||||
{
|
{
|
||||||
// Run the TIA, looking for PAL scanline patterns
|
autodetectFrameLayout();
|
||||||
// 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);
|
|
||||||
|
|
||||||
uInt8 initialGarbageFrames = FrameManager::initialGarbageFrames();
|
|
||||||
uInt8 linesPAL = 0;
|
|
||||||
uInt8 linesNTSC = 0;
|
|
||||||
|
|
||||||
mySystem->reset(true); // autodetect in reset enabled
|
|
||||||
myTIA->autodetectLayout(true);
|
|
||||||
for(int i = 0; i < 60; ++i) {
|
|
||||||
if (i > initialGarbageFrames)
|
|
||||||
myTIA->frameLayout() == FrameLayout::pal ? linesPAL++ : linesNTSC++;
|
|
||||||
|
|
||||||
myTIA->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
myDisplayFormat = linesPAL > linesNTSC ? "PAL" : "NTSC";
|
|
||||||
if(myProperties.get(Display_Format) == "AUTO")
|
if(myProperties.get(Display_Format) == "AUTO")
|
||||||
{
|
{
|
||||||
autodetected = "*";
|
autodetected = "*";
|
||||||
myCurrentFormat = 0;
|
myCurrentFormat = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't forget to reset the SC progress bars again
|
|
||||||
myOSystem.settings().setValue("fastscbios", fastscbios);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atoi(myProperties.get(Display_YStart).c_str()) == 0) {
|
||||||
|
autodetectYStart();
|
||||||
|
}
|
||||||
|
|
||||||
myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected;
|
myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected;
|
||||||
|
|
||||||
// Set up the correct properties used when toggling format
|
// Set up the correct properties used when toggling format
|
||||||
|
@ -218,6 +208,54 @@ Console::~Console()
|
||||||
myRightControl->close();
|
myRightControl->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Console::autodetectFrameLayout()
|
||||||
|
{
|
||||||
|
// Run the TIA, looking for PAL scanline patterns
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
FrameLayoutDetector frameLayoutDetector;
|
||||||
|
myTIA->setFrameManager(&frameLayoutDetector);
|
||||||
|
mySystem->reset(true);
|
||||||
|
|
||||||
|
for(int i = 0; i < 60; ++i) myTIA->update();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Console::autodetectYStart()
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
YStartDetector ystartDetector;
|
||||||
|
ystartDetector.setLayout(myDisplayFormat == "PAL" ? FrameLayout::pal : FrameLayout::ntsc);
|
||||||
|
myTIA->setFrameManager(&ystartDetector);
|
||||||
|
mySystem->reset();
|
||||||
|
|
||||||
|
for (int i = 0; i < 80; i++) myTIA->update();
|
||||||
|
|
||||||
|
myTIA->setFrameManager(myFrameManager.get());
|
||||||
|
|
||||||
|
myAutodetectedYstart = ystartDetector.detectedYStart();
|
||||||
|
|
||||||
|
// Don't forget to reset the SC progress bars again
|
||||||
|
myOSystem.settings().setValue("fastscbios", fastscbios);
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool Console::save(Serializer& out) const
|
bool Console::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
|
@ -570,7 +608,7 @@ void Console::changeYStart(int direction)
|
||||||
|
|
||||||
if(direction == +1) // increase YStart
|
if(direction == +1) // increase YStart
|
||||||
{
|
{
|
||||||
if(ystart >= FrameManager::maxYStart)
|
if(ystart >= TIAConstants::maxYStart)
|
||||||
{
|
{
|
||||||
myOSystem.frameBuffer().showMessage("YStart at maximum");
|
myOSystem.frameBuffer().showMessage("YStart at maximum");
|
||||||
return;
|
return;
|
||||||
|
@ -579,11 +617,17 @@ void Console::changeYStart(int direction)
|
||||||
}
|
}
|
||||||
else if(direction == -1) // decrease YStart
|
else if(direction == -1) // decrease YStart
|
||||||
{
|
{
|
||||||
if(ystart == FrameManager::minYStart-1)
|
if (ystart == TIAConstants::minYStart && myAutodetectedYstart == 0) {
|
||||||
|
myOSystem.frameBuffer().showMessage("Autodetected YStart not available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ystart == TIAConstants::minYStart-1 && myAutodetectedYstart > 0)
|
||||||
{
|
{
|
||||||
myOSystem.frameBuffer().showMessage("YStart at minimum");
|
myOSystem.frameBuffer().showMessage("YStart at minimum");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ystart--;
|
ystart--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -591,16 +635,16 @@ void Console::changeYStart(int direction)
|
||||||
|
|
||||||
ostringstream val;
|
ostringstream val;
|
||||||
val << ystart;
|
val << ystart;
|
||||||
if(ystart == FrameManager::minYStart-1)
|
if(ystart == TIAConstants::minYStart-1)
|
||||||
myOSystem.frameBuffer().showMessage("YStart autodetected");
|
myOSystem.frameBuffer().showMessage("YStart autodetected");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(myTIA->ystartIsAuto(ystart))
|
if(myAutodetectedYstart > 0 && myAutodetectedYstart == ystart)
|
||||||
{
|
{
|
||||||
// We've reached the auto-detect value, so reset
|
// We've reached the auto-detect value, so reset
|
||||||
myOSystem.frameBuffer().showMessage("YStart " + val.str() + " (Auto)");
|
myOSystem.frameBuffer().showMessage("YStart " + val.str() + " (Auto)");
|
||||||
val.str("");
|
val.str("");
|
||||||
val << FrameManager::minYStart-1;
|
val << TIAConstants::minYStart-1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
myOSystem.frameBuffer().showMessage("YStart " + val.str());
|
myOSystem.frameBuffer().showMessage("YStart " + val.str());
|
||||||
|
@ -620,7 +664,7 @@ void Console::changeHeight(int direction)
|
||||||
if(direction == +1) // increase Height
|
if(direction == +1) // increase Height
|
||||||
{
|
{
|
||||||
height++;
|
height++;
|
||||||
if(height > FrameManager::maxViewableHeight || height > dheight)
|
if(height > TIAConstants::maxViewableHeight || height > dheight)
|
||||||
{
|
{
|
||||||
myOSystem.frameBuffer().showMessage("Height at maximum");
|
myOSystem.frameBuffer().showMessage("Height at maximum");
|
||||||
return;
|
return;
|
||||||
|
@ -629,7 +673,7 @@ void Console::changeHeight(int direction)
|
||||||
else if(direction == -1) // decrease Height
|
else if(direction == -1) // decrease Height
|
||||||
{
|
{
|
||||||
height--;
|
height--;
|
||||||
if(height < FrameManager::minViewableHeight) height = 0;
|
if(height < TIAConstants::minViewableHeight) height = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
@ -649,12 +693,10 @@ void Console::setTIAProperties()
|
||||||
{
|
{
|
||||||
uInt32 ystart = atoi(myProperties.get(Display_YStart).c_str());
|
uInt32 ystart = atoi(myProperties.get(Display_YStart).c_str());
|
||||||
if(ystart != 0)
|
if(ystart != 0)
|
||||||
ystart = BSPF::clamp(ystart, FrameManager::minYStart, FrameManager::maxYStart);
|
ystart = BSPF::clamp(ystart, TIAConstants::minYStart, TIAConstants::maxYStart);
|
||||||
uInt32 height = atoi(myProperties.get(Display_Height).c_str());
|
uInt32 height = atoi(myProperties.get(Display_Height).c_str());
|
||||||
if(height != 0)
|
if(height != 0)
|
||||||
height = BSPF::clamp(height, FrameManager::minViewableHeight, FrameManager::maxViewableHeight);
|
height = BSPF::clamp(height, TIAConstants::minViewableHeight, TIAConstants::maxViewableHeight);
|
||||||
|
|
||||||
myTIA->autodetectLayout(false);
|
|
||||||
|
|
||||||
if(myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" ||
|
if(myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" ||
|
||||||
myDisplayFormat == "SECAM60")
|
myDisplayFormat == "SECAM60")
|
||||||
|
@ -676,7 +718,7 @@ void Console::setTIAProperties()
|
||||||
myTIA->setLayout(FrameLayout::pal);
|
myTIA->setLayout(FrameLayout::pal);
|
||||||
}
|
}
|
||||||
|
|
||||||
myTIA->setYStart(ystart);
|
myTIA->setYStart(ystart != 0 ? ystart : myAutodetectedYstart);
|
||||||
myTIA->setHeight(height);
|
myTIA->setHeight(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ class Debugger;
|
||||||
#include "FrameBuffer.hxx"
|
#include "FrameBuffer.hxx"
|
||||||
#include "Serializable.hxx"
|
#include "Serializable.hxx"
|
||||||
#include "NTSCFilter.hxx"
|
#include "NTSCFilter.hxx"
|
||||||
|
#include "frame-manager/AbstractFrameManager.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Contains detailed info about a console.
|
Contains detailed info about a console.
|
||||||
|
@ -304,6 +305,16 @@ class Console : public Serializable
|
||||||
void toggleJitter() const;
|
void toggleJitter() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Dry-run the emulation and detect the frame layout (PAL / NTSC).
|
||||||
|
*/
|
||||||
|
void autodetectFrameLayout();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dryrun the emulation and detect ystart (the first visible scanline).
|
||||||
|
*/
|
||||||
|
void autodetectYStart();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets various properties of the TIA (YStart, Height, etc) based on
|
Sets various properties of the TIA (YStart, Height, etc) based on
|
||||||
the current display format.
|
the current display format.
|
||||||
|
@ -366,6 +377,9 @@ class Console : public Serializable
|
||||||
// Pointer to the TIA object
|
// Pointer to the TIA object
|
||||||
unique_ptr<TIA> myTIA;
|
unique_ptr<TIA> myTIA;
|
||||||
|
|
||||||
|
// The frame manager instance that is used during emulation.
|
||||||
|
unique_ptr<AbstractFrameManager> myFrameManager;
|
||||||
|
|
||||||
// Pointer to the Cartridge (the debugger needs it)
|
// Pointer to the Cartridge (the debugger needs it)
|
||||||
unique_ptr<Cartridge> myCart;
|
unique_ptr<Cartridge> myCart;
|
||||||
|
|
||||||
|
@ -387,6 +401,9 @@ class Console : public Serializable
|
||||||
// Display format currently in use
|
// Display format currently in use
|
||||||
uInt32 myCurrentFormat;
|
uInt32 myCurrentFormat;
|
||||||
|
|
||||||
|
// Autodetected ystart.
|
||||||
|
uInt32 myAutodetectedYstart;
|
||||||
|
|
||||||
// Indicates whether an external palette was found and
|
// Indicates whether an external palette was found and
|
||||||
// successfully loaded
|
// successfully loaded
|
||||||
bool myUserPaletteDefined;
|
bool myUserPaletteDefined;
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace GUI {
|
||||||
#include "Variant.hxx"
|
#include "Variant.hxx"
|
||||||
#include "FBSurface.hxx"
|
#include "FBSurface.hxx"
|
||||||
#include "TIASurface.hxx"
|
#include "TIASurface.hxx"
|
||||||
#include "FrameManager.hxx"
|
#include "TIAConstants.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
// Return values for initialization of framebuffer window
|
// Return values for initialization of framebuffer window
|
||||||
|
@ -132,7 +132,7 @@ class FrameBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
kTIAMinW = 320u, kTIAMinH = FrameManager::minViewableHeight,
|
kTIAMinW = 320u, kTIAMinH = TIAConstants::minViewableHeight,
|
||||||
kFBMinW = 640u, kFBMinH = 480u
|
kFBMinW = 640u, kFBMinH = 480u
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ class VideoMode;
|
||||||
#include "Rect.hxx"
|
#include "Rect.hxx"
|
||||||
#include "NTSCFilter.hxx"
|
#include "NTSCFilter.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
#include "TIAConstants.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class is basically a wrapper around all things related to rendering
|
This class is basically a wrapper around all things related to rendering
|
||||||
|
@ -173,9 +174,9 @@ class TIASurface
|
||||||
};
|
};
|
||||||
Filter myFilter;
|
Filter myFilter;
|
||||||
|
|
||||||
enum TIAConstants {
|
enum {
|
||||||
kTIAW = 160,
|
kTIAW = 160,
|
||||||
kTIAH = FrameManager::frameBufferHeight,
|
kTIAH = TIAConstants::frameBufferHeight,
|
||||||
kScanH = kTIAH*2
|
kScanH = kTIAH*2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,488 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
// #define TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "FrameManager.hxx"
|
|
||||||
|
|
||||||
enum Metrics: uInt32 {
|
|
||||||
vblankNTSC = 37,
|
|
||||||
vblankPAL = 45,
|
|
||||||
kernelNTSC = 192,
|
|
||||||
kernelPAL = 228,
|
|
||||||
overscanNTSC = 30,
|
|
||||||
overscanPAL = 36,
|
|
||||||
vsync = 3,
|
|
||||||
maxLinesVsync = 32,
|
|
||||||
maxLinesVsyncDuringAutodetect = 100,
|
|
||||||
visibleOverscan = 20,
|
|
||||||
tvModeDetectionTolerance = 20,
|
|
||||||
initialGarbageFrames = 10,
|
|
||||||
framesForModeConfirmation = 5,
|
|
||||||
minStableFrames = 10,
|
|
||||||
maxStabilizationFrames = 20,
|
|
||||||
minDeltaForJitter = 3,
|
|
||||||
framesForStableHeight = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr uInt32
|
|
||||||
frameLinesNTSC = Metrics::vsync + Metrics::vblankNTSC + Metrics::kernelNTSC + Metrics::overscanNTSC,
|
|
||||||
frameLinesPAL = Metrics::vsync + Metrics::vblankPAL + Metrics::kernelPAL + Metrics::overscanPAL;
|
|
||||||
|
|
||||||
inline static uInt32 vsyncLimit(bool autodetect) {
|
|
||||||
return autodetect ? maxLinesVsyncDuringAutodetect : maxLinesVsync;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt8 FrameManager::initialGarbageFrames()
|
|
||||||
{
|
|
||||||
return Metrics::initialGarbageFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
FrameManager::FrameManager()
|
|
||||||
: myLayout(FrameLayout::pal),
|
|
||||||
myAutodetectLayout(true),
|
|
||||||
myHeight(0),
|
|
||||||
myFixedHeight(0),
|
|
||||||
myJitterEnabled(false)
|
|
||||||
{
|
|
||||||
updateLayout(FrameLayout::ntsc);
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setHandlers(
|
|
||||||
FrameManager::callback frameStartCallback,
|
|
||||||
FrameManager::callback frameCompleteCallback,
|
|
||||||
FrameManager::callback renderingStartCallback
|
|
||||||
)
|
|
||||||
{
|
|
||||||
myOnFrameStart = frameStartCallback;
|
|
||||||
myOnFrameComplete = frameCompleteCallback;
|
|
||||||
myOnRenderingStart = renderingStartCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::reset()
|
|
||||||
{
|
|
||||||
myVblankManager.reset();
|
|
||||||
|
|
||||||
myState = State::waitForVsyncStart;
|
|
||||||
myCurrentFrameTotalLines = myCurrentFrameFinalLines = 0;
|
|
||||||
myFrameRate = 60.0;
|
|
||||||
myLineInState = 0;
|
|
||||||
myVsync = false;
|
|
||||||
myTotalFrames = 0;
|
|
||||||
myFramesInMode = 0;
|
|
||||||
myModeConfirmed = false;
|
|
||||||
myVsyncLines = 0;
|
|
||||||
myY = 0;
|
|
||||||
myFramePending = false;
|
|
||||||
myStabilizationFrames = 0;
|
|
||||||
myStableFrames = 0;
|
|
||||||
myHasStabilized = false;
|
|
||||||
|
|
||||||
myStableFrameLines = -1;
|
|
||||||
myStableFrameHeightCountdown = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::nextLine()
|
|
||||||
{
|
|
||||||
State previousState = myState;
|
|
||||||
|
|
||||||
myCurrentFrameTotalLines++;
|
|
||||||
myLineInState++;
|
|
||||||
|
|
||||||
switch (myState)
|
|
||||||
{
|
|
||||||
case State::waitForVsyncStart:
|
|
||||||
if ((myCurrentFrameTotalLines > myFrameLines - 3) || myTotalFrames == 0)
|
|
||||||
myVsyncLines++;
|
|
||||||
|
|
||||||
if (myVsyncLines > vsyncLimit(myAutodetectLayout)) setState(State::waitForFrameStart);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::waitForVsyncEnd:
|
|
||||||
if (++myVsyncLines > vsyncLimit(myAutodetectLayout))
|
|
||||||
setState(State::waitForFrameStart);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::waitForFrameStart:
|
|
||||||
if (myVblankManager.nextLine(myTotalFrames <= Metrics::initialGarbageFrames))
|
|
||||||
setState(State::frame);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::frame:
|
|
||||||
if (myLineInState >= myHeight)
|
|
||||||
{
|
|
||||||
myLastY = ystart() + myY; // Last line drawn in this frame
|
|
||||||
setState(State::waitForVsyncStart);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// default:
|
|
||||||
// throw runtime_error("frame manager: invalid state");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myState == State::frame && previousState == State::frame) myY++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 FrameManager::missingScanlines() const
|
|
||||||
{
|
|
||||||
if (myLastY == ystart() + myY)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return myHeight - myY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setVsync(bool vsync)
|
|
||||||
{
|
|
||||||
if (vsync == myVsync) return;
|
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
(cout << "vsync " << myVsync << " -> " << vsync << ": state " << int(myState) << " @ " << myLineInState << "\n").flush();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
myVsync = vsync;
|
|
||||||
|
|
||||||
switch (myState)
|
|
||||||
{
|
|
||||||
case State::waitForVsyncStart:
|
|
||||||
case State::waitForFrameStart:
|
|
||||||
if (myVsync) setState(State::waitForVsyncEnd);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::waitForVsyncEnd:
|
|
||||||
if (!myVsync) setState(State::waitForFrameStart);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::frame:
|
|
||||||
if (myVsync) setState(State::waitForVsyncEnd);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// default:
|
|
||||||
// throw runtime_error("frame manager: invalid state");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setState(FrameManager::State state)
|
|
||||||
{
|
|
||||||
if (myState == state) return;
|
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
(cout << "state change " << myState << " -> " << state << " @ " << myLineInState << "\n").flush();
|
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
|
|
||||||
myState = state;
|
|
||||||
myLineInState = 0;
|
|
||||||
|
|
||||||
switch (myState) {
|
|
||||||
case State::waitForFrameStart:
|
|
||||||
if (!myHasStabilized) {
|
|
||||||
myHasStabilized =
|
|
||||||
myStableFrames >= Metrics::minStableFrames ||
|
|
||||||
myStabilizationFrames >= Metrics::maxStabilizationFrames;
|
|
||||||
|
|
||||||
myStabilizationFrames++;
|
|
||||||
|
|
||||||
if (myVblankManager.isStable())
|
|
||||||
myStableFrames++;
|
|
||||||
else
|
|
||||||
myStableFrames = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myFramePending) finalizeFrame();
|
|
||||||
if (myOnFrameStart) myOnFrameStart();
|
|
||||||
|
|
||||||
myVblankManager.start();
|
|
||||||
myFramePending = true;
|
|
||||||
|
|
||||||
myVsyncLines = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::frame:
|
|
||||||
if (myOnRenderingStart) myOnRenderingStart();
|
|
||||||
myVsyncLines = 0;
|
|
||||||
myY = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::finalizeFrame()
|
|
||||||
{
|
|
||||||
if (myCurrentFrameTotalLines != uInt32(myStableFrameLines)) {
|
|
||||||
if (myCurrentFrameTotalLines == myCurrentFrameFinalLines) {
|
|
||||||
|
|
||||||
if (++myStableFrameHeightCountdown >= Metrics::framesForStableHeight) {
|
|
||||||
if (myStableFrameLines >= 0) {
|
|
||||||
handleJitter(myCurrentFrameTotalLines - myStableFrameLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
myStableFrameLines = myCurrentFrameTotalLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else myStableFrameHeightCountdown = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
myPreviousFrameFinalLines = myCurrentFrameFinalLines;
|
|
||||||
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
|
|
||||||
myCurrentFrameTotalLines = 0;
|
|
||||||
myTotalFrames++;
|
|
||||||
|
|
||||||
if (myOnFrameComplete) myOnFrameComplete();
|
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameFinalLines << " total)" << "\n").flush();
|
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
|
|
||||||
if (myAutodetectLayout) updateAutodetectedLayout();
|
|
||||||
|
|
||||||
myFrameRate = (myLayout == FrameLayout::pal ? 15600.0 : 15720.0) /
|
|
||||||
myCurrentFrameFinalLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::handleJitter(Int32 scanlineDifference)
|
|
||||||
{
|
|
||||||
if (
|
|
||||||
uInt32(abs(scanlineDifference)) < Metrics::minDeltaForJitter ||
|
|
||||||
!myJitterEnabled ||
|
|
||||||
myTotalFrames < Metrics::initialGarbageFrames
|
|
||||||
) return;
|
|
||||||
|
|
||||||
myVblankManager.setJitter(scanlineDifference);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::updateAutodetectedLayout()
|
|
||||||
{
|
|
||||||
if (myTotalFrames <= Metrics::initialGarbageFrames) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FrameLayout oldLayout = myLayout;
|
|
||||||
|
|
||||||
const uInt32
|
|
||||||
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
|
|
||||||
deltaPAL = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesPAL));
|
|
||||||
|
|
||||||
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
|
|
||||||
updateLayout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
|
||||||
else if (!myModeConfirmed) {
|
|
||||||
if (
|
|
||||||
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
|
||||||
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
|
||||||
(myCurrentFrameFinalLines % 2)
|
|
||||||
)
|
|
||||||
updateLayout(FrameLayout::ntsc);
|
|
||||||
else
|
|
||||||
updateLayout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldLayout == myLayout)
|
|
||||||
myFramesInMode++;
|
|
||||||
else
|
|
||||||
myFramesInMode = 0;
|
|
||||||
|
|
||||||
if (myFramesInMode > Metrics::framesForModeConfirmation)
|
|
||||||
myModeConfirmed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::updateLayout(FrameLayout layout)
|
|
||||||
{
|
|
||||||
if (layout == myLayout) return;
|
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
(cout << "TV mode switched to " << int(layout) << "\n").flush();
|
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
|
|
||||||
myLayout = layout;
|
|
||||||
|
|
||||||
switch (myLayout)
|
|
||||||
{
|
|
||||||
case FrameLayout::ntsc:
|
|
||||||
myVblankLines = Metrics::vblankNTSC;
|
|
||||||
myKernelLines = Metrics::kernelNTSC;
|
|
||||||
myOverscanLines = Metrics::overscanNTSC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FrameLayout::pal:
|
|
||||||
myVblankLines = Metrics::vblankPAL;
|
|
||||||
myKernelLines = Metrics::kernelPAL;
|
|
||||||
myOverscanLines = Metrics::overscanPAL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// default:
|
|
||||||
// throw runtime_error("frame manager: invalid TV mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
myFrameLines = Metrics::vsync + myVblankLines + myKernelLines + myOverscanLines;
|
|
||||||
if (myFixedHeight == 0)
|
|
||||||
myHeight = myKernelLines + Metrics::visibleOverscan;
|
|
||||||
|
|
||||||
myVblankManager.setVblankLines(myVblankLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setVblank(bool vblank)
|
|
||||||
{
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
(cout << "vblank change " << myVblankManager.vblank() << " -> " << vblank << "@" << myLineInState << "\n").flush();
|
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
|
||||||
|
|
||||||
if (myState == State::waitForFrameStart) {
|
|
||||||
if (myVblankManager.setVblankDuringVblank(vblank, myTotalFrames <= Metrics::initialGarbageFrames)) {
|
|
||||||
setState(State::frame);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
myVblankManager.setVblank(vblank);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setFixedHeight(uInt32 height)
|
|
||||||
{
|
|
||||||
myFixedHeight = height;
|
|
||||||
myHeight = myFixedHeight > 0 ? myFixedHeight : (myKernelLines + Metrics::visibleOverscan);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::enableJitter(bool enabled)
|
|
||||||
{
|
|
||||||
myJitterEnabled = enabled;
|
|
||||||
|
|
||||||
if (!enabled) myVblankManager.setJitter(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FrameManager::save(Serializer& out) const
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out.putString(name());
|
|
||||||
|
|
||||||
if (!myVblankManager.save(out)) return false;
|
|
||||||
|
|
||||||
out.putInt(uInt32(myLayout));
|
|
||||||
out.putBool(myAutodetectLayout);
|
|
||||||
out.putInt(uInt32(myState));
|
|
||||||
out.putInt(myLineInState);
|
|
||||||
out.putInt(myCurrentFrameTotalLines);
|
|
||||||
out.putInt(myCurrentFrameFinalLines);
|
|
||||||
out.putInt(myPreviousFrameFinalLines);
|
|
||||||
out.putInt(myVsyncLines);
|
|
||||||
out.putDouble(myFrameRate);
|
|
||||||
out.putInt(myY); out.putInt(myLastY);
|
|
||||||
out.putBool(myFramePending);
|
|
||||||
|
|
||||||
out.putInt(myTotalFrames);
|
|
||||||
out.putInt(myFramesInMode);
|
|
||||||
out.putBool(myModeConfirmed);
|
|
||||||
|
|
||||||
out.putInt(myStableFrames);
|
|
||||||
out.putInt(myStabilizationFrames);
|
|
||||||
out.putBool(myHasStabilized);
|
|
||||||
|
|
||||||
out.putBool(myVsync);
|
|
||||||
|
|
||||||
out.putInt(myVblankLines);
|
|
||||||
out.putInt(myKernelLines);
|
|
||||||
out.putInt(myOverscanLines);
|
|
||||||
out.putInt(myFrameLines);
|
|
||||||
out.putInt(myHeight);
|
|
||||||
out.putInt(myFixedHeight);
|
|
||||||
|
|
||||||
out.putBool(myJitterEnabled);
|
|
||||||
|
|
||||||
out.putInt(myStableFrameLines);
|
|
||||||
out.putInt(myStableFrameHeightCountdown);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_FrameManager::save" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FrameManager::load(Serializer& in)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(in.getString() != name())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!myVblankManager.load(in)) return false;
|
|
||||||
|
|
||||||
myLayout = FrameLayout(in.getInt());
|
|
||||||
myAutodetectLayout = in.getBool();
|
|
||||||
myState = State(in.getInt());
|
|
||||||
myLineInState = in.getInt();
|
|
||||||
myCurrentFrameTotalLines = in.getInt();
|
|
||||||
myCurrentFrameFinalLines = in.getInt();
|
|
||||||
myPreviousFrameFinalLines = in.getInt();
|
|
||||||
myVsyncLines = in.getInt();
|
|
||||||
myFrameRate = float(in.getDouble());
|
|
||||||
myY = in.getInt(); myLastY = in.getInt();
|
|
||||||
myFramePending = in.getBool();
|
|
||||||
|
|
||||||
myTotalFrames = in.getInt();
|
|
||||||
myFramesInMode = in.getInt();
|
|
||||||
myModeConfirmed = in.getBool();
|
|
||||||
|
|
||||||
myStableFrames = in.getInt();
|
|
||||||
myStabilizationFrames = in.getInt();
|
|
||||||
myHasStabilized = in.getBool();
|
|
||||||
|
|
||||||
myVsync = in.getBool();
|
|
||||||
|
|
||||||
myVblankLines = in.getInt();
|
|
||||||
myKernelLines = in.getInt();
|
|
||||||
myOverscanLines = in.getInt();
|
|
||||||
myFrameLines = in.getInt();
|
|
||||||
myHeight = in.getInt();
|
|
||||||
myFixedHeight = in.getInt();
|
|
||||||
|
|
||||||
myJitterEnabled = in.getBool();
|
|
||||||
|
|
||||||
myStableFrameLines = in.getInt();
|
|
||||||
myStableFrameHeightCountdown = in.getInt();
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_FrameManager::load" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,188 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#ifndef TIA_FRAME_MANAGER
|
|
||||||
#define TIA_FRAME_MANAGER
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "VblankManager.hxx"
|
|
||||||
#include "Serializable.hxx"
|
|
||||||
#include "FrameLayout.hxx"
|
|
||||||
#include "bspf.hxx"
|
|
||||||
|
|
||||||
class FrameManager : public Serializable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
using callback = std::function<void()>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FrameManager();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static uInt8 initialGarbageFrames();
|
|
||||||
|
|
||||||
void setHandlers(
|
|
||||||
callback frameStartCallback,
|
|
||||||
callback frameCompletionCallback,
|
|
||||||
callback renderingStartCallback
|
|
||||||
);
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void nextLine();
|
|
||||||
|
|
||||||
void setVblank(bool vblank);
|
|
||||||
|
|
||||||
void setVsync(bool vsync);
|
|
||||||
|
|
||||||
bool isRendering() const { return myState == State::frame && myHasStabilized; }
|
|
||||||
|
|
||||||
FrameLayout layout() const { return myLayout; }
|
|
||||||
|
|
||||||
bool vblank() const { return myVblankManager.vblank(); }
|
|
||||||
|
|
||||||
bool vsync() const { return myVsync; }
|
|
||||||
|
|
||||||
uInt32 height() const { return myHeight; }
|
|
||||||
|
|
||||||
void setFixedHeight(uInt32 height);
|
|
||||||
|
|
||||||
uInt32 getY() const { return myY; }
|
|
||||||
|
|
||||||
uInt32 scanlines() const { return myCurrentFrameTotalLines; }
|
|
||||||
|
|
||||||
uInt32 scanlinesLastFrame() const { return myCurrentFrameFinalLines; }
|
|
||||||
|
|
||||||
uInt32 missingScanlines() const;
|
|
||||||
|
|
||||||
bool scanlineCountTransitioned() const {
|
|
||||||
return (myPreviousFrameFinalLines & 0x1) != (myCurrentFrameFinalLines & 0x1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uInt32 frameCount() const { return myTotalFrames; }
|
|
||||||
|
|
||||||
float frameRate() const { return myFrameRate; }
|
|
||||||
|
|
||||||
void setYstart(uInt32 ystart) { myVblankManager.setYstart(ystart); }
|
|
||||||
|
|
||||||
uInt32 ystart() const { return myVblankManager.ystart(); }
|
|
||||||
bool ystartIsAuto(uInt32 line) const { return myVblankManager.ystartIsAuto(line); }
|
|
||||||
|
|
||||||
void autodetectLayout(bool toggle) { myAutodetectLayout = toggle; }
|
|
||||||
|
|
||||||
void setLayout(FrameLayout mode) { if (!myAutodetectLayout) updateLayout(mode); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Serializable methods (see that class for more information).
|
|
||||||
*/
|
|
||||||
bool save(Serializer& out) const override;
|
|
||||||
bool load(Serializer& in) override;
|
|
||||||
string name() const override { return "TIA_FrameManager"; }
|
|
||||||
|
|
||||||
void setJitterFactor(uInt8 factor) { myVblankManager.setJitterFactor(factor); }
|
|
||||||
bool jitterEnabled() const { return myJitterEnabled; }
|
|
||||||
void enableJitter(bool enabled);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr uInt32 frameBufferHeight = 320;
|
|
||||||
static constexpr uInt32 minYStart = 1, maxYStart = 64;
|
|
||||||
static constexpr uInt32 minViewableHeight = 210, maxViewableHeight = 256;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
enum State {
|
|
||||||
waitForVsyncStart,
|
|
||||||
waitForVsyncEnd,
|
|
||||||
waitForFrameStart,
|
|
||||||
frame
|
|
||||||
};
|
|
||||||
|
|
||||||
enum VblankMode {
|
|
||||||
locked,
|
|
||||||
floating,
|
|
||||||
final,
|
|
||||||
fixed
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void updateLayout(FrameLayout mode);
|
|
||||||
|
|
||||||
void updateAutodetectedLayout();
|
|
||||||
|
|
||||||
void setState(State state);
|
|
||||||
|
|
||||||
void finalizeFrame();
|
|
||||||
|
|
||||||
void nextLineInVsync();
|
|
||||||
|
|
||||||
void handleJitter(Int32 scanlineDifference);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
callback myOnFrameStart;
|
|
||||||
callback myOnFrameComplete;
|
|
||||||
callback myOnRenderingStart;
|
|
||||||
|
|
||||||
VblankManager myVblankManager;
|
|
||||||
|
|
||||||
FrameLayout myLayout;
|
|
||||||
bool myAutodetectLayout;
|
|
||||||
State myState;
|
|
||||||
uInt32 myLineInState;
|
|
||||||
uInt32 myCurrentFrameTotalLines;
|
|
||||||
uInt32 myCurrentFrameFinalLines;
|
|
||||||
uInt32 myPreviousFrameFinalLines;
|
|
||||||
uInt32 myVsyncLines;
|
|
||||||
float myFrameRate;
|
|
||||||
uInt32 myY, myLastY;
|
|
||||||
bool myFramePending;
|
|
||||||
|
|
||||||
uInt32 myTotalFrames;
|
|
||||||
uInt32 myFramesInMode;
|
|
||||||
bool myModeConfirmed;
|
|
||||||
|
|
||||||
uInt32 myStableFrames;
|
|
||||||
uInt32 myStabilizationFrames;
|
|
||||||
bool myHasStabilized;
|
|
||||||
|
|
||||||
bool myVsync;
|
|
||||||
|
|
||||||
uInt32 myVblankLines;
|
|
||||||
uInt32 myKernelLines;
|
|
||||||
uInt32 myOverscanLines;
|
|
||||||
uInt32 myFrameLines;
|
|
||||||
uInt32 myHeight;
|
|
||||||
uInt32 myFixedHeight;
|
|
||||||
|
|
||||||
bool myJitterEnabled;
|
|
||||||
|
|
||||||
Int32 myStableFrameLines;
|
|
||||||
uInt8 myStableFrameHeightCountdown;
|
|
||||||
|
|
||||||
private:
|
|
||||||
FrameManager(const FrameManager&) = delete;
|
|
||||||
FrameManager(FrameManager&&) = delete;
|
|
||||||
FrameManager& operator=(const FrameManager&) = delete;
|
|
||||||
FrameManager& operator=(FrameManager&&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // TIA_FRAME_MANAGER
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "Control.hxx"
|
#include "Control.hxx"
|
||||||
#include "Paddles.hxx"
|
#include "Paddles.hxx"
|
||||||
#include "DelayQueueIteratorImpl.hxx"
|
#include "DelayQueueIteratorImpl.hxx"
|
||||||
|
#include "TIAConstants.hxx"
|
||||||
|
#include "frame-manager/FrameManager.hxx"
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartDebug.hxx"
|
#include "CartDebug.hxx"
|
||||||
|
@ -67,6 +69,7 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
: myConsole(console),
|
: myConsole(console),
|
||||||
mySound(sound),
|
mySound(sound),
|
||||||
mySettings(settings),
|
mySettings(settings),
|
||||||
|
myFrameManager(nullptr),
|
||||||
myPlayfield(~CollisionMask::playfield & 0x7FFF),
|
myPlayfield(~CollisionMask::playfield & 0x7FFF),
|
||||||
myMissile0(~CollisionMask::missile0 & 0x7FFF),
|
myMissile0(~CollisionMask::missile0 & 0x7FFF),
|
||||||
myMissile1(~CollisionMask::missile1 & 0x7FFF),
|
myMissile1(~CollisionMask::missile1 & 0x7FFF),
|
||||||
|
@ -76,18 +79,6 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
mySpriteEnabledBits(0xFF),
|
mySpriteEnabledBits(0xFF),
|
||||||
myCollisionsEnabledBits(0xFF)
|
myCollisionsEnabledBits(0xFF)
|
||||||
{
|
{
|
||||||
myFrameManager.setHandlers(
|
|
||||||
[this] () {
|
|
||||||
onFrameStart();
|
|
||||||
},
|
|
||||||
[this] () {
|
|
||||||
onFrameComplete();
|
|
||||||
},
|
|
||||||
[this] () {
|
|
||||||
onRenderingStart();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
myTIAPinsDriven = mySettings.getBool("tiadriven");
|
myTIAPinsDriven = mySettings.getBool("tiadriven");
|
||||||
|
|
||||||
myBackground.setTIA(this);
|
myBackground.setTIA(this);
|
||||||
|
@ -98,12 +89,42 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
myMissile1.setTIA(this);
|
myMissile1.setTIA(this);
|
||||||
myBall.setTIA(this);
|
myBall.setTIA(this);
|
||||||
|
|
||||||
myFrameManager.enableJitter(mySettings.getBool("tv.jitter"));
|
myEnableJitter = mySettings.getBool("tv.jitter");
|
||||||
myFrameManager.setJitterFactor(mySettings.getInt("tv.jitter_recovery"));
|
myJitterFactor = mySettings.getInt("tv.jitter_recovery");
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void TIA::setFrameManager(AbstractFrameManager *frameManager)
|
||||||
|
{
|
||||||
|
clearFrameManager();
|
||||||
|
|
||||||
|
myFrameManager = frameManager;
|
||||||
|
|
||||||
|
myFrameManager->setHandlers(
|
||||||
|
[this] () {
|
||||||
|
onFrameStart();
|
||||||
|
},
|
||||||
|
[this] () {
|
||||||
|
onFrameComplete();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
myFrameManager->enableJitter(myEnableJitter);
|
||||||
|
myFrameManager->setJitterFactor(myJitterFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void TIA::clearFrameManager()
|
||||||
|
{
|
||||||
|
if (!myFrameManager) return;
|
||||||
|
|
||||||
|
myFrameManager->clearHandlers();
|
||||||
|
|
||||||
|
myFrameManager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::reset()
|
void TIA::reset()
|
||||||
{
|
{
|
||||||
|
@ -143,7 +164,8 @@ void TIA::reset()
|
||||||
|
|
||||||
mySound.reset();
|
mySound.reset();
|
||||||
myDelayQueue.reset();
|
myDelayQueue.reset();
|
||||||
myFrameManager.reset();
|
|
||||||
|
if (myFrameManager) myFrameManager->reset();
|
||||||
|
|
||||||
myCyclesAtFrameStart = 0;
|
myCyclesAtFrameStart = 0;
|
||||||
|
|
||||||
|
@ -161,7 +183,7 @@ void TIA::reset()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::frameReset()
|
void TIA::frameReset()
|
||||||
{
|
{
|
||||||
memset(myFramebuffer, 0, 160 * FrameManager::frameBufferHeight);
|
memset(myFramebuffer, 0, 160 * TIAConstants::frameBufferHeight);
|
||||||
myAutoFrameEnabled = mySettings.getInt("framerate") <= 0;
|
myAutoFrameEnabled = mySettings.getInt("framerate") <= 0;
|
||||||
enableColorLoss(mySettings.getBool("colorloss"));
|
enableColorLoss(mySettings.getBool("colorloss"));
|
||||||
}
|
}
|
||||||
|
@ -205,7 +227,7 @@ bool TIA::save(Serializer& out) const
|
||||||
if(!mySound.save(out)) return false;
|
if(!mySound.save(out)) return false;
|
||||||
|
|
||||||
if(!myDelayQueue.save(out)) return false;
|
if(!myDelayQueue.save(out)) return false;
|
||||||
if(!myFrameManager.save(out)) return false;
|
if(!myFrameManager->save(out)) return false;
|
||||||
|
|
||||||
if(!myBackground.save(out)) return false;
|
if(!myBackground.save(out)) return false;
|
||||||
if(!myPlayfield.save(out)) return false;
|
if(!myPlayfield.save(out)) return false;
|
||||||
|
@ -276,7 +298,7 @@ bool TIA::load(Serializer& in)
|
||||||
if(!mySound.load(in)) return false;
|
if(!mySound.load(in)) return false;
|
||||||
|
|
||||||
if(!myDelayQueue.load(in)) return false;
|
if(!myDelayQueue.load(in)) return false;
|
||||||
if(!myFrameManager.load(in)) return false;
|
if(!myFrameManager->load(in)) return false;
|
||||||
|
|
||||||
if(!myBackground.load(in)) return false;
|
if(!myBackground.load(in)) return false;
|
||||||
if(!myPlayfield.load(in)) return false;
|
if(!myPlayfield.load(in)) return false;
|
||||||
|
@ -481,7 +503,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VSYNC:
|
case VSYNC:
|
||||||
myFrameManager.setVsync(value & 0x02);
|
myFrameManager->setVsync(value & 0x02);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -752,7 +774,7 @@ bool TIA::saveDisplay(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putByteArray(myFramebuffer, 160*FrameManager::frameBufferHeight);
|
out.putByteArray(myFramebuffer, 160*TIAConstants::frameBufferHeight);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -769,7 +791,7 @@ bool TIA::loadDisplay(Serializer& in)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Reset frame buffer pointer and data
|
// Reset frame buffer pointer and data
|
||||||
in.getByteArray(myFramebuffer, 160*FrameManager::frameBufferHeight);
|
in.getByteArray(myFramebuffer, 160*TIAConstants::frameBufferHeight);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -795,7 +817,7 @@ bool TIA::enableColorLoss(bool enabled)
|
||||||
if(enabled)
|
if(enabled)
|
||||||
{
|
{
|
||||||
myColorLossEnabled = true;
|
myColorLossEnabled = true;
|
||||||
myColorLossActive = myFrameManager.scanlinesLastFrame() & 0x1;
|
myColorLossActive = myFrameManager->scanlinesLastFrame() & 0x1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -819,7 +841,7 @@ bool TIA::electronBeamPos(uInt32& x, uInt32& y) const
|
||||||
uInt8 clocks = clocksThisLine();
|
uInt8 clocks = clocksThisLine();
|
||||||
|
|
||||||
x = (clocks < 68) ? 0 : clocks - 68;
|
x = (clocks < 68) ? 0 : clocks - 68;
|
||||||
y = myFrameManager.getY();
|
y = myFrameManager->getY();
|
||||||
|
|
||||||
return isRendering();
|
return isRendering();
|
||||||
}
|
}
|
||||||
|
@ -905,7 +927,11 @@ bool TIA::toggleCollisions()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool TIA::enableFixedColors(bool enable)
|
bool TIA::enableFixedColors(bool enable)
|
||||||
{
|
{
|
||||||
int layout = myFrameManager.layout() == FrameLayout::pal ? 1 : 0;
|
// This will be called during reset at a point where no frame manager
|
||||||
|
// instance is available, so we guard aginst this here.
|
||||||
|
int layout = 0;
|
||||||
|
if (myFrameManager) layout = myFrameManager->layout() == FrameLayout::pal ? 1 : 0;
|
||||||
|
|
||||||
myMissile0.setDebugColor(myFixedColorPalette[layout][FixedObject::M0]);
|
myMissile0.setDebugColor(myFixedColorPalette[layout][FixedObject::M0]);
|
||||||
myMissile1.setDebugColor(myFixedColorPalette[layout][FixedObject::M1]);
|
myMissile1.setDebugColor(myFixedColorPalette[layout][FixedObject::M1]);
|
||||||
myPlayer0.setDebugColor(myFixedColorPalette[layout][FixedObject::P0]);
|
myPlayer0.setDebugColor(myFixedColorPalette[layout][FixedObject::P0]);
|
||||||
|
@ -990,22 +1016,32 @@ bool TIA::toggleJitter(uInt8 mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0:
|
case 0:
|
||||||
myFrameManager.enableJitter(false);
|
myEnableJitter = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
myFrameManager.enableJitter(true);
|
myEnableJitter = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
myFrameManager.enableJitter(!myFrameManager.jitterEnabled());
|
myEnableJitter = !myEnableJitter;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw runtime_error("invalid argument for toggleJitter");
|
throw runtime_error("invalid argument for toggleJitter");
|
||||||
}
|
}
|
||||||
|
|
||||||
return myFrameManager.jitterEnabled();
|
if (myFrameManager) myFrameManager->enableJitter(myEnableJitter);
|
||||||
|
|
||||||
|
return myEnableJitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void TIA::setJitterRecoveryFactor(Int32 factor)
|
||||||
|
{
|
||||||
|
myJitterFactor = factor;
|
||||||
|
|
||||||
|
if (myFrameManager) myFrameManager->setJitterFactor(myJitterFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1080,9 +1116,9 @@ void TIA::onFrameStart()
|
||||||
{
|
{
|
||||||
// Only activate it when necessary, since changing colours in
|
// Only activate it when necessary, since changing colours in
|
||||||
// the graphical object forces the TIA cached line to be flushed
|
// the graphical object forces the TIA cached line to be flushed
|
||||||
if (myFrameManager.scanlineCountTransitioned())
|
if (myFrameManager->scanlineCountTransitioned())
|
||||||
{
|
{
|
||||||
myColorLossActive = myFrameManager.scanlinesLastFrame() & 0x1;
|
myColorLossActive = myFrameManager->scanlinesLastFrame() & 0x1;
|
||||||
|
|
||||||
myMissile0.applyColorLoss();
|
myMissile0.applyColorLoss();
|
||||||
myMissile1.applyColorLoss();
|
myMissile1.applyColorLoss();
|
||||||
|
@ -1095,12 +1131,6 @@ void TIA::onFrameStart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void TIA::onRenderingStart()
|
|
||||||
{
|
|
||||||
myXAtRenderingStart = myHctr > 68 ? myHctr - 68 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::onFrameComplete()
|
void TIA::onFrameComplete()
|
||||||
{
|
{
|
||||||
|
@ -1111,13 +1141,13 @@ void TIA::onFrameComplete()
|
||||||
memset(myFramebuffer, 0, myXAtRenderingStart);
|
memset(myFramebuffer, 0, myXAtRenderingStart);
|
||||||
|
|
||||||
// Blank out any extra lines not drawn this frame
|
// Blank out any extra lines not drawn this frame
|
||||||
const uInt32 missingScanlines = myFrameManager.missingScanlines();
|
const Int32 missingScanlines = myFrameManager->missingScanlines();
|
||||||
if (missingScanlines > 0)
|
if (missingScanlines > 0)
|
||||||
memset(myFramebuffer + 160 * myFrameManager.getY(), 0, missingScanlines * 160);
|
memset(myFramebuffer + 160 * myFrameManager->getY(), 0, missingScanlines * 160);
|
||||||
|
|
||||||
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
|
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
|
||||||
if(myAutoFrameEnabled)
|
if(myAutoFrameEnabled)
|
||||||
myConsole.setFramerate(myFrameManager.frameRate());
|
myConsole.setFramerate(myFrameManager->frameRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1147,7 +1177,7 @@ void TIA::cycle(uInt32 colorClocks)
|
||||||
else
|
else
|
||||||
tickHframe();
|
tickHframe();
|
||||||
|
|
||||||
if (myCollisionUpdateRequired && !myFrameManager.vblank()) updateCollision();
|
if (myCollisionUpdateRequired && !myFrameManager->vblank()) updateCollision();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++myHctr >= 228)
|
if (++myHctr >= 228)
|
||||||
|
@ -1201,7 +1231,7 @@ void TIA::tickHblank()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::tickHframe()
|
void TIA::tickHframe()
|
||||||
{
|
{
|
||||||
const uInt32 y = myFrameManager.getY();
|
const uInt32 y = myFrameManager->getY();
|
||||||
const uInt32 x = myHctr - 68 - myHctrDelta;
|
const uInt32 x = myHctr - 68 - myHctrDelta;
|
||||||
|
|
||||||
myCollisionUpdateRequired = true;
|
myCollisionUpdateRequired = true;
|
||||||
|
@ -1213,7 +1243,7 @@ void TIA::tickHframe()
|
||||||
myPlayer1.tick();
|
myPlayer1.tick();
|
||||||
myBall.tick();
|
myBall.tick();
|
||||||
|
|
||||||
if (myFrameManager.isRendering())
|
if (myFrameManager->isRendering())
|
||||||
renderPixel(x, y);
|
renderPixel(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1223,8 +1253,8 @@ void TIA::applyRsync()
|
||||||
const uInt32 x = myHctr > 68 ? myHctr - 68 : 0;
|
const uInt32 x = myHctr > 68 ? myHctr - 68 : 0;
|
||||||
|
|
||||||
myHctrDelta = 225 - myHctr;
|
myHctrDelta = 225 - myHctr;
|
||||||
if (myFrameManager.isRendering())
|
if (myFrameManager->isRendering())
|
||||||
memset(myFramebuffer + myFrameManager.getY() * 160 + x, 0, 160 - x);
|
memset(myFramebuffer + myFrameManager->getY() * 160 + x, 0, 160 - x);
|
||||||
|
|
||||||
myHctr = 225;
|
myHctr = 225;
|
||||||
}
|
}
|
||||||
|
@ -1243,9 +1273,9 @@ void TIA::nextLine()
|
||||||
myHstate = HState::blank;
|
myHstate = HState::blank;
|
||||||
myHctrDelta = 0;
|
myHctrDelta = 0;
|
||||||
|
|
||||||
myFrameManager.nextLine();
|
myFrameManager->nextLine();
|
||||||
|
|
||||||
if (myFrameManager.isRendering() && myFrameManager.getY() == 0) flushLineCache();
|
if (myFrameManager->isRendering() && myFrameManager->getY() == 0) flushLineCache();
|
||||||
|
|
||||||
mySystem->m6502().clearHaltRequest();
|
mySystem->m6502().clearHaltRequest();
|
||||||
}
|
}
|
||||||
|
@ -1253,9 +1283,9 @@ void TIA::nextLine()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::cloneLastLine()
|
void TIA::cloneLastLine()
|
||||||
{
|
{
|
||||||
const auto y = myFrameManager.getY();
|
const auto y = myFrameManager->getY();
|
||||||
|
|
||||||
if (!myFrameManager.isRendering() || y == 0) return;
|
if (!myFrameManager->isRendering() || y == 0) return;
|
||||||
|
|
||||||
uInt8* buffer = myFramebuffer;
|
uInt8* buffer = myFramebuffer;
|
||||||
|
|
||||||
|
@ -1282,7 +1312,7 @@ void TIA::renderPixel(uInt32 x, uInt32 y)
|
||||||
|
|
||||||
uInt8 color = 0;
|
uInt8 color = 0;
|
||||||
|
|
||||||
if (!myFrameManager.vblank())
|
if (!myFrameManager->vblank())
|
||||||
{
|
{
|
||||||
switch (myPriority)
|
switch (myPriority)
|
||||||
{
|
{
|
||||||
|
@ -1355,8 +1385,8 @@ void TIA::flushLineCache()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::clearHmoveComb()
|
void TIA::clearHmoveComb()
|
||||||
{
|
{
|
||||||
if (myFrameManager.isRendering() && myHstate == HState::blank)
|
if (myFrameManager->isRendering() && myHstate == HState::blank)
|
||||||
memset(myFramebuffer + myFrameManager.getY() * 160, myColorHBlank, 8);
|
memset(myFramebuffer + myFrameManager->getY() * 160, myColorHBlank, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1369,7 +1399,7 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||||
{
|
{
|
||||||
case VBLANK:
|
case VBLANK:
|
||||||
flushLineCache();
|
flushLineCache();
|
||||||
myFrameManager.setVblank(value & 0x02);
|
myFrameManager->setVblank(value & 0x02);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMOVE:
|
case HMOVE:
|
||||||
|
|
|
@ -25,9 +25,10 @@
|
||||||
#include "Device.hxx"
|
#include "Device.hxx"
|
||||||
#include "Serializer.hxx"
|
#include "Serializer.hxx"
|
||||||
#include "TIATypes.hxx"
|
#include "TIATypes.hxx"
|
||||||
|
#include "TIAConstants.hxx"
|
||||||
#include "DelayQueue.hxx"
|
#include "DelayQueue.hxx"
|
||||||
#include "DelayQueueIterator.hxx"
|
#include "DelayQueueIterator.hxx"
|
||||||
#include "FrameManager.hxx"
|
#include "frame-manager/AbstractFrameManager.hxx"
|
||||||
#include "FrameLayout.hxx"
|
#include "FrameLayout.hxx"
|
||||||
#include "Background.hxx"
|
#include "Background.hxx"
|
||||||
#include "Playfield.hxx"
|
#include "Playfield.hxx"
|
||||||
|
@ -100,9 +101,20 @@ class TIA : public Device
|
||||||
@param settings The settings object for this TIA device
|
@param settings The settings object for this TIA device
|
||||||
*/
|
*/
|
||||||
TIA(Console& console, Sound& sound, Settings& settings);
|
TIA(Console& console, Sound& sound, Settings& settings);
|
||||||
|
|
||||||
virtual ~TIA() = default;
|
virtual ~TIA() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Configure the frame manager.
|
||||||
|
*/
|
||||||
|
void setFrameManager(AbstractFrameManager *frameManager);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the configured frame manager and deteach the lifecycle callbacks.
|
||||||
|
*/
|
||||||
|
void clearFrameManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reset device to its power-on state.
|
Reset device to its power-on state.
|
||||||
*/
|
*/
|
||||||
|
@ -192,21 +204,19 @@ class TIA : public Device
|
||||||
Answers dimensional info about the framebuffer.
|
Answers dimensional info about the framebuffer.
|
||||||
*/
|
*/
|
||||||
uInt32 width() const { return 160; }
|
uInt32 width() const { return 160; }
|
||||||
uInt32 height() const { return myFrameManager.height(); }
|
uInt32 height() const { return myFrameManager->height(); }
|
||||||
uInt32 ystart() const { return myFrameManager.ystart(); }
|
uInt32 ystart() const { return myFrameManager->ystart(); }
|
||||||
bool ystartIsAuto(uInt32 line) const { return myFrameManager.ystartIsAuto(line); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Changes the current Height/YStart properties.
|
Changes the current Height/YStart properties.
|
||||||
Note that calls to these method(s) must be eventually followed by
|
Note that calls to these method(s) must be eventually followed by
|
||||||
::frameReset() for the changes to take effect.
|
::frameReset() for the changes to take effect.
|
||||||
*/
|
*/
|
||||||
void setHeight(uInt32 height) { myFrameManager.setFixedHeight(height); }
|
void setHeight(uInt32 height) { myFrameManager->setFixedHeight(height); }
|
||||||
void setYStart(uInt32 ystart) { myFrameManager.setYstart(ystart); }
|
void setYStart(uInt32 ystart) { myFrameManager->setYstart(ystart); }
|
||||||
|
|
||||||
void autodetectLayout(bool toggle) { myFrameManager.autodetectLayout(toggle); }
|
void setLayout(FrameLayout layout) { myFrameManager->setLayout(layout); }
|
||||||
void setLayout(FrameLayout layout) { myFrameManager.setLayout(layout); }
|
FrameLayout frameLayout() const { return myFrameManager->layout(); }
|
||||||
FrameLayout frameLayout() const { return myFrameManager.layout(); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the timing of the console currently in use.
|
Answers the timing of the console currently in use.
|
||||||
|
@ -249,7 +259,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@return The total number of scanlines generated
|
@return The total number of scanlines generated
|
||||||
*/
|
*/
|
||||||
uInt32 scanlines() const { return myFrameManager.scanlines(); }
|
uInt32 scanlines() const { return myFrameManager->scanlines(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the total number of scanlines the TIA generated in the
|
Answers the total number of scanlines the TIA generated in the
|
||||||
|
@ -257,7 +267,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@return The total number of scanlines generated in the last frame.
|
@return The total number of scanlines generated in the last frame.
|
||||||
*/
|
*/
|
||||||
uInt32 scanlinesLastFrame() const { return myFrameManager.scanlinesLastFrame(); }
|
uInt32 scanlinesLastFrame() const { return myFrameManager->scanlinesLastFrame(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the total system cycles from the start of the emulation.
|
Answers the total system cycles from the start of the emulation.
|
||||||
|
@ -267,7 +277,7 @@ class TIA : public Device
|
||||||
/**
|
/**
|
||||||
Answers the frame count from the start of the emulation.
|
Answers the frame count from the start of the emulation.
|
||||||
*/
|
*/
|
||||||
uInt32 frameCount() const { return myFrameManager.frameCount(); }
|
uInt32 frameCount() const { return myFrameManager->frameCount(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the system cycles from the start of the current frame.
|
Answers the system cycles from the start of the current frame.
|
||||||
|
@ -282,7 +292,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@return If the frame is in rendering mode
|
@return If the frame is in rendering mode
|
||||||
*/
|
*/
|
||||||
bool isRendering() const { return myFrameManager.isRendering(); }
|
bool isRendering() const { return myFrameManager->isRendering(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the current position of the virtual 'electron beam' used
|
Answers the current position of the virtual 'electron beam' used
|
||||||
|
@ -359,7 +369,7 @@ class TIA : public Device
|
||||||
@return Whether the mode was enabled or disabled
|
@return Whether the mode was enabled or disabled
|
||||||
*/
|
*/
|
||||||
bool toggleJitter(uInt8 mode = 2);
|
bool toggleJitter(uInt8 mode = 2);
|
||||||
void setJitterRecoveryFactor(Int32 factor) { myFrameManager.setJitterFactor(factor); }
|
void setJitterRecoveryFactor(Int32 factor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method should be called to update the TIA with a new scanline.
|
This method should be called to update the TIA with a new scanline.
|
||||||
|
@ -451,12 +461,6 @@ class TIA : public Device
|
||||||
*/
|
*/
|
||||||
void onFrameStart();
|
void onFrameStart();
|
||||||
|
|
||||||
/**
|
|
||||||
* This callback is invoked by FrameManager when the visible range of the
|
|
||||||
* current frame starts.
|
|
||||||
*/
|
|
||||||
void onRenderingStart();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This callback is invoked by FrameManager when the current frame completes.
|
* This callback is invoked by FrameManager when the current frame completes.
|
||||||
*/
|
*/
|
||||||
|
@ -598,7 +602,7 @@ class TIA : public Device
|
||||||
* The frame manager is responsible for detecting frame boundaries and the visible
|
* The frame manager is responsible for detecting frame boundaries and the visible
|
||||||
* region of each frame.
|
* region of each frame.
|
||||||
*/
|
*/
|
||||||
FrameManager myFrameManager;
|
AbstractFrameManager *myFrameManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The various TIA objects.
|
* The various TIA objects.
|
||||||
|
@ -622,10 +626,8 @@ class TIA : public Device
|
||||||
LatchedInput myInput0;
|
LatchedInput myInput0;
|
||||||
LatchedInput myInput1;
|
LatchedInput myInput1;
|
||||||
|
|
||||||
/**
|
// Pointer to the internal color-index-based frame buffer
|
||||||
* Pointer to the internal color-index-based frame buffer
|
uInt8 myFramebuffer[160 * TIAConstants::frameBufferHeight];
|
||||||
*/
|
|
||||||
uInt8 myFramebuffer[160 * FrameManager::frameBufferHeight];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting this to true injects random values into undefined reads.
|
* Setting this to true injects random values into undefined reads.
|
||||||
|
@ -738,10 +740,17 @@ class TIA : public Device
|
||||||
bool myColorLossActive;
|
bool myColorLossActive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* System cycles at the end of the previous frame / beginning of next frame
|
* System cycles at the end of the previous frame / beginning of next frame.
|
||||||
*/
|
*/
|
||||||
uInt64 myCyclesAtFrameStart;
|
uInt64 myCyclesAtFrameStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frame manager can change during our lifetime, so we buffer those two.
|
||||||
|
*/
|
||||||
|
bool myEnableJitter;
|
||||||
|
uInt8 myJitterFactor;
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
// The arrays containing information about every byte of TIA
|
// The arrays containing information about every byte of TIA
|
||||||
// indicating whether and how (RW) it is used.
|
// indicating whether and how (RW) it is used.
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef TIA_CONSTANTS_HXX
|
||||||
|
#define TIA_CONSTANTS_HXX
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
namespace TIAConstants {
|
||||||
|
|
||||||
|
constexpr uInt32 frameBufferHeight = 320;
|
||||||
|
constexpr uInt32 minYStart = 1, maxYStart = 64;
|
||||||
|
constexpr uInt32 minViewableHeight = 210, maxViewableHeight = 256;
|
||||||
|
constexpr uInt32 initialGarbageFrames = 10;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TIA_CONSTANTS_HXX
|
|
@ -1,306 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
// #define TIA_VBLANK_MANAGER_DEBUG_LOG
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "VblankManager.hxx"
|
|
||||||
|
|
||||||
enum Metrics: uInt32 {
|
|
||||||
maxUnderscan = 10,
|
|
||||||
maxVblankViolations = 2,
|
|
||||||
minStableVblankFrames = 1,
|
|
||||||
framesUntilFinal = 30,
|
|
||||||
maxJitter = 50
|
|
||||||
};
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
VblankManager::VblankManager()
|
|
||||||
: myVblankLines(0),
|
|
||||||
myYstart(0),
|
|
||||||
myMode(VblankMode::floating),
|
|
||||||
myJitter(0),
|
|
||||||
myJitterFactor(2)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void VblankManager::reset()
|
|
||||||
{
|
|
||||||
myVblank = false;
|
|
||||||
myCurrentLine = 0;
|
|
||||||
myVblankViolations = 0;
|
|
||||||
myStableVblankFrames = 0;
|
|
||||||
myVblankViolated = false;
|
|
||||||
myLastVblankLines = 0;
|
|
||||||
myIsRunning = false;
|
|
||||||
myJitter = 0;
|
|
||||||
|
|
||||||
if (myMode != VblankMode::fixed) setVblankMode(VblankMode::floating);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void VblankManager::setJitter(Int32 jitter) {
|
|
||||||
jitter = std::min<Int32>(jitter, Metrics::maxJitter);
|
|
||||||
|
|
||||||
if (myMode == VblankMode::final) jitter = std::max<Int32>(jitter, -myLastVblankLines);
|
|
||||||
if (myMode == VblankMode::fixed) jitter = std::max<Int32>(jitter, -myYstart);
|
|
||||||
|
|
||||||
if (jitter > 0) jitter += myJitterFactor;
|
|
||||||
if (jitter < 0) jitter -= myJitterFactor;
|
|
||||||
|
|
||||||
if (abs(jitter) > abs(myJitter)) myJitter = jitter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void VblankManager::start()
|
|
||||||
{
|
|
||||||
myCurrentLine = 0;
|
|
||||||
myIsRunning = true;
|
|
||||||
myVblankViolated = false;
|
|
||||||
|
|
||||||
if (myJitter > 0) myJitter = std::max(myJitter - myJitterFactor, 0);
|
|
||||||
if (myJitter < 0) myJitter = std::min(myJitter + myJitterFactor, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool VblankManager::nextLine(bool isGarbageFrame)
|
|
||||||
{
|
|
||||||
if (!myIsRunning) return false;
|
|
||||||
|
|
||||||
// Make sure that we do the transition check **before** incrementing the line
|
|
||||||
// counter. This ensures that, if the transition is caused by VBLANK off during
|
|
||||||
// the line, this will continue to trigger the transition in 'locked' mode. Otherwise,
|
|
||||||
// the transition would be triggered by the line change **before** the VBLANK
|
|
||||||
// and thus detected as a suprious violation. Sigh, this stuff is complicated,
|
|
||||||
// isn't it?
|
|
||||||
const bool transition = shouldTransition(isGarbageFrame);
|
|
||||||
if (transition) myIsRunning = false;
|
|
||||||
|
|
||||||
myCurrentLine++;
|
|
||||||
|
|
||||||
return transition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void VblankManager::setYstart(uInt32 ystart)
|
|
||||||
{
|
|
||||||
if (ystart == myYstart) return;
|
|
||||||
|
|
||||||
myYstart = ystart;
|
|
||||||
|
|
||||||
setVblankMode(ystart ? VblankMode::fixed : VblankMode::floating);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool VblankManager::setVblankDuringVblank(bool vblank, bool isGarbageFrame)
|
|
||||||
{
|
|
||||||
const bool oldVblank = myVblank;
|
|
||||||
|
|
||||||
myVblank = vblank;
|
|
||||||
if (!myIsRunning || vblank || oldVblank == myVblank) return false;
|
|
||||||
|
|
||||||
const bool transition = shouldTransition(isGarbageFrame);
|
|
||||||
if (transition) myIsRunning = false;
|
|
||||||
|
|
||||||
return transition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool VblankManager::shouldTransition(bool isGarbageFrame)
|
|
||||||
{
|
|
||||||
// Are we free to transition as per vblank cycle?
|
|
||||||
bool shouldTransition = myCurrentLine + 1 >= (myVblank ? myVblankLines : myVblankLines - Metrics::maxUnderscan);
|
|
||||||
|
|
||||||
// Do we **actually** transition? This depends on what mode we are in.
|
|
||||||
bool transition = false;
|
|
||||||
|
|
||||||
switch (myMode) {
|
|
||||||
// Floating mode: we still are looking for a stable frame start
|
|
||||||
case VblankMode::floating:
|
|
||||||
|
|
||||||
// Are we free to transition?
|
|
||||||
if (shouldTransition) {
|
|
||||||
// Is this same scanline in which the transition ocurred last frame?
|
|
||||||
if (!isGarbageFrame && myCurrentLine == myLastVblankLines)
|
|
||||||
// Yes? -> Increase the number of stable frames
|
|
||||||
myStableVblankFrames++;
|
|
||||||
else
|
|
||||||
// No? -> Frame start shifted again, set the number of consecutive stable frames to zero
|
|
||||||
myStableVblankFrames = 0;
|
|
||||||
|
|
||||||
// Save the transition point for checking on it next frame
|
|
||||||
myLastVblankLines = myCurrentLine;
|
|
||||||
|
|
||||||
#ifdef TIA_VBLANK_MANAGER_DEBUG_LOG
|
|
||||||
(cout << "leaving vblank in floating mode, should transition: " << shouldTransition << "\n").flush();
|
|
||||||
#endif
|
|
||||||
// In floating mode, we transition whenever we can.
|
|
||||||
transition = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transition to locked mode if we saw enough stable frames in a row.
|
|
||||||
if (myStableVblankFrames >= Metrics::minStableVblankFrames) {
|
|
||||||
setVblankMode(VblankMode::locked);
|
|
||||||
myVblankViolations = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Locked mode: always transition at the same point, but check whether this is actually the
|
|
||||||
// detected transition point and revert state if applicable
|
|
||||||
case VblankMode::locked:
|
|
||||||
|
|
||||||
// Have we reached the transition point?
|
|
||||||
if (myCurrentLine == myLastVblankLines) {
|
|
||||||
|
|
||||||
// Are we free to transition per the algorithm and didn't we observe an violation before?
|
|
||||||
// (aka did the algorithm tell us to transition before reaching the actual line)
|
|
||||||
if (shouldTransition && !myVblankViolated)
|
|
||||||
// Reset the number of irregular frames (if any)
|
|
||||||
myVblankViolations = 0;
|
|
||||||
else {
|
|
||||||
// Record a violation if it wasn't recorded before
|
|
||||||
if (!myVblankViolated) myVblankViolations++;
|
|
||||||
myVblankViolated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TIA_VBLANK_MANAGER_DEBUG_LOG
|
|
||||||
(cout << "leaving vblank in locked mode, should transition: " << shouldTransition << "\n").flush();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// transition
|
|
||||||
transition = true;
|
|
||||||
// The algorithm tells us to transition although we haven't reached the trip line before
|
|
||||||
} else if (shouldTransition) {
|
|
||||||
// Record a violation if it wasn't recorded before
|
|
||||||
if (!myVblankViolated) myVblankViolations++;
|
|
||||||
myVblankViolated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Freeze frame start if the detected value seems to be sufficiently stable
|
|
||||||
if (transition && ++myFramesInLockedMode > Metrics::framesUntilFinal) {
|
|
||||||
setVblankMode(VblankMode::final);
|
|
||||||
// Revert to floating mode if there were too many irregular frames in a row
|
|
||||||
} else if (myVblankViolations > Metrics::maxVblankViolations) {
|
|
||||||
setVblankMode(VblankMode::floating);
|
|
||||||
myStableVblankFrames = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Fixed mode: use external ystart value
|
|
||||||
case VblankMode::fixed:
|
|
||||||
transition = Int32(myCurrentLine) >=
|
|
||||||
std::max<Int32>(myYstart + std::min<Int32>(myJitter, Metrics::maxJitter), 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Final mode: use detected ystart value
|
|
||||||
case VblankMode::final:
|
|
||||||
transition = Int32(myCurrentLine) >=
|
|
||||||
std::max<Int32>(myLastVblankLines + std::min<Int32>(myJitter, Metrics::maxJitter), 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return transition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void VblankManager::setVblankMode(VblankMode mode)
|
|
||||||
{
|
|
||||||
if (myMode == mode) return;
|
|
||||||
|
|
||||||
myMode = mode;
|
|
||||||
|
|
||||||
switch (myMode) {
|
|
||||||
case VblankMode::locked:
|
|
||||||
myFramesInLockedMode = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool VblankManager::save(Serializer& out) const
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out.putString(name());
|
|
||||||
|
|
||||||
out.putInt(myVblankLines);
|
|
||||||
out.putInt(myYstart);
|
|
||||||
out.putBool(myVblank);
|
|
||||||
out.putInt(myCurrentLine);
|
|
||||||
|
|
||||||
out.putInt(int(myMode));
|
|
||||||
out.putInt(myLastVblankLines);
|
|
||||||
out.putByte(myVblankViolations);
|
|
||||||
out.putByte(myStableVblankFrames);
|
|
||||||
out.putBool(myVblankViolated);
|
|
||||||
out.putByte(myFramesInLockedMode);
|
|
||||||
|
|
||||||
out.putInt(myJitter);
|
|
||||||
out.putByte(myJitterFactor);
|
|
||||||
|
|
||||||
out.putBool(myIsRunning);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_VblankManager::save" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool VblankManager::load(Serializer& in)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(in.getString() != name())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
myVblankLines = in.getInt();
|
|
||||||
myYstart = in.getInt();
|
|
||||||
myVblank = in.getBool();
|
|
||||||
myCurrentLine = in.getInt();
|
|
||||||
|
|
||||||
myMode = VblankMode(in.getInt());
|
|
||||||
myLastVblankLines = in.getInt();
|
|
||||||
myVblankViolations = in.getByte();
|
|
||||||
myStableVblankFrames = in.getByte();
|
|
||||||
myVblankViolated = in.getBool();
|
|
||||||
myFramesInLockedMode = in.getByte();
|
|
||||||
|
|
||||||
myJitter = in.getInt();
|
|
||||||
myJitterFactor = in.getByte();
|
|
||||||
|
|
||||||
myIsRunning = in.getBool();
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_VblankManager::load" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// SSSS tt lll lll
|
|
||||||
// SS SS tt ll ll
|
|
||||||
// SS tttttt eeee ll ll aaaa
|
|
||||||
// SSSS tt ee ee ll ll aa
|
|
||||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
||||||
// SS SS tt ee ll ll aa aa
|
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
|
||||||
//
|
|
||||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
|
||||||
// and the Stella Team
|
|
||||||
//
|
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#ifndef TIA_VBLANK_MANAGER
|
|
||||||
#define TIA_VBLANK_MANAGER
|
|
||||||
|
|
||||||
#include "Serializable.hxx"
|
|
||||||
|
|
||||||
class VblankManager : public Serializable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
VblankManager();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void start();
|
|
||||||
|
|
||||||
bool nextLine(bool isGarbageFrame);
|
|
||||||
|
|
||||||
void setVblankLines(uInt32 lines) { myVblankLines = lines; }
|
|
||||||
|
|
||||||
void setYstart(uInt32 ystart);
|
|
||||||
|
|
||||||
uInt32 ystart() const { return myYstart == 0 ? myLastVblankLines : myYstart; }
|
|
||||||
bool ystartIsAuto(uInt32 line) const { return myLastVblankLines == line; }
|
|
||||||
|
|
||||||
void setVblank(bool vblank) { myVblank = vblank; }
|
|
||||||
|
|
||||||
bool setVblankDuringVblank(bool vblank, bool isGarbageFrame);
|
|
||||||
|
|
||||||
bool vblank() const { return myVblank; }
|
|
||||||
|
|
||||||
uInt32 currentLine() const { return myCurrentLine; }
|
|
||||||
|
|
||||||
void setJitter(Int32 jitter);
|
|
||||||
void setJitterFactor(uInt8 jitterFactor) { myJitterFactor = jitterFactor; }
|
|
||||||
|
|
||||||
bool isStable() const { return myMode != VblankMode::floating; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Serializable methods (see that class for more information).
|
|
||||||
*/
|
|
||||||
bool save(Serializer& out) const override;
|
|
||||||
bool load(Serializer& in) override;
|
|
||||||
string name() const override { return "TIA_VblankManager"; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
enum VblankMode {
|
|
||||||
locked,
|
|
||||||
floating,
|
|
||||||
final,
|
|
||||||
fixed
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool shouldTransition(bool isGarbageFrame);
|
|
||||||
|
|
||||||
void setVblankMode(VblankMode mode);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
uInt32 myVblankLines;
|
|
||||||
uInt32 myYstart;
|
|
||||||
bool myVblank;
|
|
||||||
uInt32 myCurrentLine;
|
|
||||||
|
|
||||||
VblankMode myMode;
|
|
||||||
uInt32 myLastVblankLines;
|
|
||||||
uInt8 myVblankViolations;
|
|
||||||
uInt8 myStableVblankFrames;
|
|
||||||
bool myVblankViolated;
|
|
||||||
uInt8 myFramesInLockedMode;
|
|
||||||
|
|
||||||
Int32 myJitter;
|
|
||||||
uInt8 myJitterFactor;
|
|
||||||
|
|
||||||
bool myIsRunning;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
VblankManager(const VblankManager&) = delete;
|
|
||||||
VblankManager(VblankManager&&) = delete;
|
|
||||||
VblankManager& operator=(const VblankManager&) = delete;
|
|
||||||
VblankManager& operator=(VblankManager&&) = delete;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // TIA_VBLANK_MANAGER
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include "AbstractFrameManager.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
AbstractFrameManager::AbstractFrameManager() :
|
||||||
|
myLayout(FrameLayout::pal),
|
||||||
|
myOnFrameStart(nullptr),
|
||||||
|
myOnFrameComplete(nullptr)
|
||||||
|
{
|
||||||
|
layout(FrameLayout::ntsc);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::reset()
|
||||||
|
{
|
||||||
|
myIsRendering = false;
|
||||||
|
myVsync = false;
|
||||||
|
myVblank = false;
|
||||||
|
myCurrentFrameTotalLines = 0;
|
||||||
|
myCurrentFrameFinalLines = 0;
|
||||||
|
myPreviousFrameFinalLines = 0;
|
||||||
|
myTotalFrames = 0;
|
||||||
|
myFrameRate = 0;
|
||||||
|
myFrameRate = 60.0;
|
||||||
|
|
||||||
|
onReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::nextLine()
|
||||||
|
{
|
||||||
|
myCurrentFrameTotalLines++;
|
||||||
|
|
||||||
|
onNextLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::setHandlers(
|
||||||
|
callback frameStartCallback,
|
||||||
|
callback frameCompletionCallback
|
||||||
|
) {
|
||||||
|
myOnFrameStart = frameStartCallback;
|
||||||
|
myOnFrameComplete = frameCompletionCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::clearHandlers()
|
||||||
|
{
|
||||||
|
myOnFrameStart = myOnFrameComplete = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::setVblank(bool vblank)
|
||||||
|
{
|
||||||
|
if (vblank == myVblank) return;
|
||||||
|
|
||||||
|
myVblank = vblank;
|
||||||
|
|
||||||
|
onSetVblank();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::setVsync(bool vsync)
|
||||||
|
{
|
||||||
|
if (vsync == myVsync) return;
|
||||||
|
|
||||||
|
myVsync = vsync;
|
||||||
|
|
||||||
|
onSetVsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::notifyFrameStart()
|
||||||
|
{
|
||||||
|
if (myOnFrameStart) myOnFrameStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::notifyFrameComplete()
|
||||||
|
{
|
||||||
|
myPreviousFrameFinalLines = myCurrentFrameFinalLines;
|
||||||
|
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
|
||||||
|
myCurrentFrameTotalLines = 0;
|
||||||
|
myTotalFrames++;
|
||||||
|
|
||||||
|
if (myOnFrameComplete) myOnFrameComplete();
|
||||||
|
|
||||||
|
myFrameRate = (layout() == FrameLayout::pal ? 15600.0 : 15720.0) /
|
||||||
|
myCurrentFrameFinalLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::layout(FrameLayout layout)
|
||||||
|
{
|
||||||
|
if (layout == myLayout) return;
|
||||||
|
|
||||||
|
myLayout = layout;
|
||||||
|
|
||||||
|
onLayoutChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool AbstractFrameManager::save(Serializer& out) const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
out.putString(name());
|
||||||
|
|
||||||
|
out.putBool(myIsRendering);
|
||||||
|
out.putBool(myVsync);
|
||||||
|
out.putBool(myVblank);
|
||||||
|
out.putInt(myCurrentFrameFinalLines);
|
||||||
|
out.putInt(myPreviousFrameFinalLines);
|
||||||
|
out.putInt(myTotalFrames);
|
||||||
|
out.putInt(uInt32(myLayout));
|
||||||
|
out.putDouble(myFrameRate);
|
||||||
|
|
||||||
|
return onSave(out);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: AbstractFrameManager::save" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool AbstractFrameManager::load(Serializer& in)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (in.getString() != name()) return false;
|
||||||
|
|
||||||
|
myIsRendering = in.getBool();
|
||||||
|
myVsync = in.getBool();
|
||||||
|
myVblank = in.getBool();
|
||||||
|
myCurrentFrameFinalLines = in.getInt();
|
||||||
|
myPreviousFrameFinalLines = in.getInt();
|
||||||
|
myTotalFrames = in.getInt();
|
||||||
|
myLayout = FrameLayout(in.getInt());
|
||||||
|
myFrameRate = float(in.getDouble());
|
||||||
|
|
||||||
|
return onLoad(in);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: AbstractFrameManager::load" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,321 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef TIA_ABSTRACT_FRAME_MANAGER
|
||||||
|
#define TIA_ABSTRACT_FRAME_MANAGER
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "Serializable.hxx"
|
||||||
|
#include "FrameLayout.hxx"
|
||||||
|
|
||||||
|
class AbstractFrameManager : public Serializable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
using callback = std::function<void()>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AbstractFrameManager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the various handler callbacks.
|
||||||
|
*/
|
||||||
|
void setHandlers(
|
||||||
|
callback frameStartCallback,
|
||||||
|
callback frameCompletionCallback
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the configured handler callbacks.
|
||||||
|
*/
|
||||||
|
void clearHandlers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset.
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by TIA to notify the start of the next scanline.
|
||||||
|
*/
|
||||||
|
void nextLine();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by TIA on VBLANK writes.
|
||||||
|
*/
|
||||||
|
void setVblank(bool vblank);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by TIA on VSYNC writes.
|
||||||
|
*/
|
||||||
|
void setVsync(bool vsync);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the TIA render its frame? This is buffered in a flag for
|
||||||
|
* performance reasons; descendants must update the flag.
|
||||||
|
*/
|
||||||
|
bool isRendering() const { return myIsRendering; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is vsync on?
|
||||||
|
*/
|
||||||
|
bool vsync() const { return myVsync; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is vblank on?
|
||||||
|
*/
|
||||||
|
bool vblank() const { return myVblank; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of scanlines in the last finished frame.
|
||||||
|
*/
|
||||||
|
uInt32 scanlinesLastFrame() const { return myCurrentFrameFinalLines; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Did the number of scanlines switch between even / odd (used for color loss
|
||||||
|
* emulation).
|
||||||
|
*
|
||||||
|
* TODO: Crappy name, find something better.
|
||||||
|
*/
|
||||||
|
bool scanlineCountTransitioned() const {
|
||||||
|
return (myPreviousFrameFinalLines & 0x1) != (myCurrentFrameFinalLines & 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of frames. 32 bit should be good for > 2 years :)
|
||||||
|
*/
|
||||||
|
uInt32 frameCount() const { return myTotalFrames; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configured (our autodetected) frame layout (PAL / NTSC).
|
||||||
|
*/
|
||||||
|
FrameLayout layout() const { return myLayout; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current frame rate. This is calculated dynamically from the number of
|
||||||
|
* scanlines in the last frames and used to control sleep time in the
|
||||||
|
* dispatch loop.
|
||||||
|
*/
|
||||||
|
float frameRate() const { return myFrameRate; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save state.
|
||||||
|
*/
|
||||||
|
bool save(Serializer& out) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore state.
|
||||||
|
*/
|
||||||
|
bool load(Serializer& in) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// The following methods are implement as noops and should be overriden as
|
||||||
|
// required. All of these are irrelevant if nothing is displayed (during
|
||||||
|
// autodetect).
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The jitter factor determines the time jitter simulation takes to recover.
|
||||||
|
*/
|
||||||
|
virtual void setJitterFactor(uInt8 factor) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is jitter simulation enabled?
|
||||||
|
*/
|
||||||
|
virtual bool jitterEnabled() const { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable jitter simulation
|
||||||
|
*/
|
||||||
|
virtual void enableJitter(bool enabled) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scanline difference between the last two frames. Used in the TIA to
|
||||||
|
* clear any scanlines that were not repainted.
|
||||||
|
*/
|
||||||
|
virtual Int32 missingScanlines() const { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frame height.
|
||||||
|
*/
|
||||||
|
virtual uInt32 height() const { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure a fixed frame height (the default is determined by the frame
|
||||||
|
* layout).
|
||||||
|
*/
|
||||||
|
virtual void setFixedHeight(uInt32 height) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current y coordinate (valid only during rendering).
|
||||||
|
*/
|
||||||
|
virtual uInt32 getY() const { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current number of scanlines in the current frame (including invisible
|
||||||
|
* lines).
|
||||||
|
*/
|
||||||
|
virtual uInt32 scanlines() const { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the ystart value.
|
||||||
|
*/
|
||||||
|
virtual void setYstart(uInt32 ystart) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configured ystart value.
|
||||||
|
*/
|
||||||
|
virtual uInt32 ystart() const { return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the frame layout. This may be a noop (on the autodetection manager).
|
||||||
|
*/
|
||||||
|
virtual void setLayout(FrameLayout mode) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// The following are template methods that can be implemented to hook into
|
||||||
|
// the frame logic.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if vblank changes.
|
||||||
|
*/
|
||||||
|
virtual void onSetVblank() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if vsync changes.
|
||||||
|
*/
|
||||||
|
virtual void onSetVsync() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if the next line is signalled, after the internal bookkeeping has
|
||||||
|
* been updated.
|
||||||
|
*/
|
||||||
|
virtual void onNextLine() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on reset (after the base class has reset).
|
||||||
|
*/
|
||||||
|
virtual void onReset() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after a frame layout change.
|
||||||
|
*/
|
||||||
|
virtual void onLayoutChange() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called during state save (after the base class has serialized its state).
|
||||||
|
*/
|
||||||
|
virtual bool onSave(Serializer& out) const { throw runtime_error("cannot be serialized"); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called during state restore (after the base class has restored its state).
|
||||||
|
*/
|
||||||
|
virtual bool onLoad(Serializer& in) { throw runtime_error("cannot be serialized"); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This needs to be overriden if state serialization is implemented
|
||||||
|
* (unnecesary in autodetect managers).
|
||||||
|
*/
|
||||||
|
string name() const override { throw runtime_error("state serialization is not implemented!"); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// These need to be called in order to drive the frame lifecycle of the
|
||||||
|
// emulation.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal frame start.
|
||||||
|
*/
|
||||||
|
void notifyFrameStart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal frame stop.
|
||||||
|
*/
|
||||||
|
void notifyFrameComplete();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The internal setter to update the frame layout.
|
||||||
|
*/
|
||||||
|
void layout(FrameLayout layout);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rendering flag.
|
||||||
|
*/
|
||||||
|
bool myIsRendering;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vsync flag.
|
||||||
|
*/
|
||||||
|
bool myVsync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vblank flag.
|
||||||
|
*/
|
||||||
|
bool myVblank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current scanline count in the current frame.
|
||||||
|
*/
|
||||||
|
uInt32 myCurrentFrameTotalLines;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total number of scanlines in the last complete frame.
|
||||||
|
*/
|
||||||
|
uInt32 myCurrentFrameFinalLines;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total number of scanlines in the second last complete frame.
|
||||||
|
*/
|
||||||
|
uInt32 myPreviousFrameFinalLines;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total frame count.
|
||||||
|
*/
|
||||||
|
uInt32 myTotalFrames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frame rate (see above.)
|
||||||
|
*/
|
||||||
|
float myFrameRate;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current frame layout.
|
||||||
|
*/
|
||||||
|
FrameLayout myLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The various lifecycle callbacks.
|
||||||
|
*/
|
||||||
|
callback myOnFrameStart;
|
||||||
|
callback myOnFrameComplete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
AbstractFrameManager(const AbstractFrameManager&) = delete;
|
||||||
|
AbstractFrameManager(AbstractFrameManager&&) = delete;
|
||||||
|
AbstractFrameManager& operator=(const AbstractFrameManager&);
|
||||||
|
AbstractFrameManager& operator=(AbstractFrameManager&&);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIA_ABSTRACT_FRAME_MANAGER
|
|
@ -0,0 +1,143 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include "FrameLayoutDetector.hxx"
|
||||||
|
#include "TIAConstants.hxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Misc. numeric constants used in the algorithm.
|
||||||
|
*/
|
||||||
|
enum Metrics: uInt32 {
|
||||||
|
frameLinesNTSC = 262,
|
||||||
|
frameLinesPAL = 312,
|
||||||
|
waitForVsync = 100,
|
||||||
|
tvModeDetectionTolerance = 20,
|
||||||
|
initialGarbageFrames = TIAConstants::initialGarbageFrames
|
||||||
|
};
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
FrameLayout FrameLayoutDetector::detectedLayout() const{
|
||||||
|
// We choose the mode that was detected for the majority of frames.
|
||||||
|
return myPalFrames > myNtscFrames ? FrameLayout::pal : FrameLayout::ntsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameLayoutDetector::onReset()
|
||||||
|
{
|
||||||
|
myState = State::waitForVsyncStart;
|
||||||
|
myNtscFrames = myPalFrames = 0;
|
||||||
|
myLinesWaitingForVsyncToStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameLayoutDetector::onSetVsync()
|
||||||
|
{
|
||||||
|
if (myVsync)
|
||||||
|
setState(State::waitForVsyncEnd);
|
||||||
|
else
|
||||||
|
setState(State::waitForVsyncStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameLayoutDetector::onNextLine()
|
||||||
|
{
|
||||||
|
const uInt32 frameLines = layout() == FrameLayout::ntsc ? Metrics::frameLinesNTSC : Metrics::frameLinesPAL;
|
||||||
|
|
||||||
|
switch (myState) {
|
||||||
|
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)
|
||||||
|
myLinesWaitingForVsyncToStart++;
|
||||||
|
|
||||||
|
if (myLinesWaitingForVsyncToStart > Metrics::waitForVsync) setState(State::waitForVsyncEnd);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::waitForVsyncEnd:
|
||||||
|
if (++myLinesWaitingForVsyncToStart > Metrics::waitForVsync) setState(State::waitForVsyncStart);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("cannot happen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameLayoutDetector::setState(State state)
|
||||||
|
{
|
||||||
|
if (state == myState) return;
|
||||||
|
|
||||||
|
myState = state;
|
||||||
|
myLinesWaitingForVsyncToStart = 0;
|
||||||
|
|
||||||
|
switch (myState) {
|
||||||
|
case State::waitForVsyncEnd:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::waitForVsyncStart:
|
||||||
|
finalizeFrame();
|
||||||
|
notifyFrameStart();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new runtime_error("cannot happen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameLayoutDetector::finalizeFrame()
|
||||||
|
{
|
||||||
|
notifyFrameComplete();
|
||||||
|
|
||||||
|
if (myTotalFrames <= Metrics::initialGarbageFrames) return;
|
||||||
|
|
||||||
|
// Calculate the delta between scanline count and the sweet spot for the respective
|
||||||
|
// frame layouts
|
||||||
|
const uInt32
|
||||||
|
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
||||||
|
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
||||||
|
(myCurrentFrameFinalLines % 2)
|
||||||
|
)
|
||||||
|
layout(FrameLayout::ntsc);
|
||||||
|
else
|
||||||
|
// Take the nearest layout if all else fails
|
||||||
|
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
||||||
|
|
||||||
|
switch (layout()) {
|
||||||
|
case FrameLayout::ntsc:
|
||||||
|
myNtscFrames++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FrameLayout::pal:
|
||||||
|
myPalFrames++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("cannot happen");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef TIA_FRAME_LAYOUT_DETECTOR
|
||||||
|
#define TIA_FRAME_LAYOUT_DETECTOR
|
||||||
|
|
||||||
|
#include "AbstractFrameManager.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 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
FrameLayoutDetector() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the detected frame layout.
|
||||||
|
*/
|
||||||
|
FrameLayout detectedLayout() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into vsync changes.
|
||||||
|
*/
|
||||||
|
void onSetVsync() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into reset.
|
||||||
|
*/
|
||||||
|
void onReset() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook into line changes.
|
||||||
|
*/
|
||||||
|
void onNextLine() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This frame manager only tracks frame boundaries, so we have only two states.
|
||||||
|
*/
|
||||||
|
enum State {
|
||||||
|
// Wait for VSYNC to be enabled.
|
||||||
|
waitForVsyncStart,
|
||||||
|
|
||||||
|
// Wait for VSYNC to be disabled.
|
||||||
|
waitForVsyncEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change state and change internal state accordingly.
|
||||||
|
*/
|
||||||
|
void setState(State state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize the current frame and guess frame layout from the scanline count.
|
||||||
|
*/
|
||||||
|
void finalizeFrame();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current state.
|
||||||
|
*/
|
||||||
|
State myState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of frames detected as the respective frame layout.
|
||||||
|
*/
|
||||||
|
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 myLinesWaitingForVsyncToStart;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
FrameLayoutDetector(const FrameLayoutDetector&) = delete;
|
||||||
|
FrameLayoutDetector(FrameLayoutDetector&&) = delete;
|
||||||
|
FrameLayoutDetector& operator=(const FrameLayoutDetector&) = delete;
|
||||||
|
FrameLayoutDetector& operator=(FrameLayoutDetector&&) = delete;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIA_FRAME_LAYOUT_DETECTOR
|
|
@ -0,0 +1,253 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
// #define TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "FrameManager.hxx"
|
||||||
|
|
||||||
|
enum Metrics: uInt32 {
|
||||||
|
vblankNTSC = 37,
|
||||||
|
vblankPAL = 45,
|
||||||
|
kernelNTSC = 192,
|
||||||
|
kernelPAL = 228,
|
||||||
|
overscanNTSC = 30,
|
||||||
|
overscanPAL = 36,
|
||||||
|
vsync = 3,
|
||||||
|
maxLinesVsync = 32,
|
||||||
|
visibleOverscan = 20,
|
||||||
|
tvModeDetectionTolerance = 20,
|
||||||
|
initialGarbageFrames = TIAConstants::initialGarbageFrames,
|
||||||
|
minStableFrames = 10,
|
||||||
|
maxStabilizationFrames = 20,
|
||||||
|
minDeltaForJitter = 3,
|
||||||
|
framesForStableHeight = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
FrameManager::FrameManager() :
|
||||||
|
myHeight(0),
|
||||||
|
myYStart(0)
|
||||||
|
{
|
||||||
|
onLayoutChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::onReset()
|
||||||
|
{
|
||||||
|
myState = State::waitForVsyncStart;
|
||||||
|
myLineInState = 0;
|
||||||
|
myTotalFrames = 0;
|
||||||
|
myVsyncLines = 0;
|
||||||
|
myY = 0;
|
||||||
|
|
||||||
|
myStableFrameLines = -1;
|
||||||
|
myStableFrameHeightCountdown = 0;
|
||||||
|
|
||||||
|
myJitterEmulation.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::onNextLine()
|
||||||
|
{
|
||||||
|
Int32 jitter;
|
||||||
|
|
||||||
|
State previousState = myState;
|
||||||
|
myLineInState++;
|
||||||
|
|
||||||
|
switch (myState)
|
||||||
|
{
|
||||||
|
case State::waitForVsyncStart:
|
||||||
|
if ((myCurrentFrameTotalLines > myFrameLines - 3) || myTotalFrames == 0)
|
||||||
|
myVsyncLines++;
|
||||||
|
|
||||||
|
if (myVsyncLines > Metrics::maxLinesVsync) setState(State::waitForFrameStart);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::waitForVsyncEnd:
|
||||||
|
if (++myVsyncLines > Metrics::maxLinesVsync)
|
||||||
|
setState(State::waitForFrameStart);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::waitForFrameStart:
|
||||||
|
jitter =
|
||||||
|
(myJitterEnabled && myTotalFrames > Metrics::initialGarbageFrames) ? myJitterEmulation.jitter() : 0;
|
||||||
|
|
||||||
|
if (myLineInState >= (myYStart + jitter)) setState(State::frame);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::frame:
|
||||||
|
if (myLineInState >= myHeight)
|
||||||
|
{
|
||||||
|
myLastY = ystart() + myY; // Last line drawn in this frame
|
||||||
|
setState(State::waitForVsyncStart);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("frame manager: invalid state");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myState == State::frame && previousState == State::frame) myY++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Int32 FrameManager::missingScanlines() const
|
||||||
|
{
|
||||||
|
if (myLastY == myYStart + myY)
|
||||||
|
return 0;
|
||||||
|
else {
|
||||||
|
return myHeight - myY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::setYstart(uInt32 ystart)
|
||||||
|
{
|
||||||
|
myYStart = ystart;
|
||||||
|
myJitterEmulation.setYStart(ystart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::onSetVsync()
|
||||||
|
{
|
||||||
|
if (myState == State::waitForVsyncEnd) setState(State::waitForFrameStart);
|
||||||
|
else setState(State::waitForVsyncEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::setState(FrameManager::State state)
|
||||||
|
{
|
||||||
|
if (myState == state) return;
|
||||||
|
|
||||||
|
myState = state;
|
||||||
|
myLineInState = 0;
|
||||||
|
|
||||||
|
switch (myState) {
|
||||||
|
case State::waitForFrameStart:
|
||||||
|
notifyFrameComplete();
|
||||||
|
myJitterEmulation.frameComplete(myCurrentFrameFinalLines);
|
||||||
|
notifyFrameStart();
|
||||||
|
|
||||||
|
myVsyncLines = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::frame:
|
||||||
|
myVsyncLines = 0;
|
||||||
|
myY = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateIsRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// TODO: kill this with fire once frame manager refactoring is complete
|
||||||
|
void FrameManager::onLayoutChange()
|
||||||
|
{
|
||||||
|
switch (layout())
|
||||||
|
{
|
||||||
|
case FrameLayout::ntsc:
|
||||||
|
myVblankLines = Metrics::vblankNTSC;
|
||||||
|
myKernelLines = Metrics::kernelNTSC;
|
||||||
|
myOverscanLines = Metrics::overscanNTSC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FrameLayout::pal:
|
||||||
|
myVblankLines = Metrics::vblankPAL;
|
||||||
|
myKernelLines = Metrics::kernelPAL;
|
||||||
|
myOverscanLines = Metrics::overscanPAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("frame manager: invalid TV mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
myFrameLines = Metrics::vsync + myVblankLines + myKernelLines + myOverscanLines;
|
||||||
|
if (myFixedHeight == 0)
|
||||||
|
myHeight = myKernelLines + Metrics::visibleOverscan;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::setFixedHeight(uInt32 height)
|
||||||
|
{
|
||||||
|
myFixedHeight = height;
|
||||||
|
myHeight = myFixedHeight > 0 ? myFixedHeight : (myKernelLines + Metrics::visibleOverscan);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::updateIsRendering() {
|
||||||
|
myIsRendering = myState == State::frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool FrameManager::onSave(Serializer& out) const
|
||||||
|
{
|
||||||
|
if (!myJitterEmulation.save(out)) return false;
|
||||||
|
|
||||||
|
out.putInt(uInt32(myState));
|
||||||
|
out.putInt(myLineInState);
|
||||||
|
out.putInt(myVsyncLines);
|
||||||
|
out.putInt(myY);
|
||||||
|
out.putInt(myLastY);
|
||||||
|
|
||||||
|
out.putInt(myVblankLines);
|
||||||
|
out.putInt(myKernelLines);
|
||||||
|
out.putInt(myOverscanLines);
|
||||||
|
out.putInt(myFrameLines);
|
||||||
|
out.putInt(myHeight);
|
||||||
|
out.putInt(myFixedHeight);
|
||||||
|
|
||||||
|
out.putBool(myJitterEnabled);
|
||||||
|
|
||||||
|
out.putInt(myStableFrameLines);
|
||||||
|
out.putInt(myStableFrameHeightCountdown);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool FrameManager::onLoad(Serializer& in)
|
||||||
|
{
|
||||||
|
if (!myJitterEmulation.load(in)) return false;
|
||||||
|
|
||||||
|
myState = State(in.getInt());
|
||||||
|
myLineInState = in.getInt();
|
||||||
|
myVsyncLines = in.getInt();
|
||||||
|
myY = in.getInt();
|
||||||
|
myLastY = in.getInt();
|
||||||
|
|
||||||
|
myVblankLines = in.getInt();
|
||||||
|
myKernelLines = in.getInt();
|
||||||
|
myOverscanLines = in.getInt();
|
||||||
|
myFrameLines = in.getInt();
|
||||||
|
myHeight = in.getInt();
|
||||||
|
myFixedHeight = in.getInt();
|
||||||
|
|
||||||
|
myJitterEnabled = in.getBool();
|
||||||
|
|
||||||
|
myStableFrameLines = in.getInt();
|
||||||
|
myStableFrameHeightCountdown = in.getInt();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef TIA_FRAME_MANAGER
|
||||||
|
#define TIA_FRAME_MANAGER
|
||||||
|
|
||||||
|
#include "AbstractFrameManager.hxx"
|
||||||
|
#include "TIAConstants.hxx"
|
||||||
|
#include "bspf.hxx"
|
||||||
|
#include "JitterEmulation.hxx"
|
||||||
|
|
||||||
|
class FrameManager: public AbstractFrameManager {
|
||||||
|
public:
|
||||||
|
|
||||||
|
FrameManager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void setJitterFactor(uInt8 factor) override { myJitterEmulation.setJitterFactor(factor); }
|
||||||
|
|
||||||
|
bool jitterEnabled() const override { return myJitterEnabled; }
|
||||||
|
|
||||||
|
void enableJitter(bool enabled) override { myJitterEnabled = enabled; }
|
||||||
|
|
||||||
|
uInt32 height() const override { return myHeight; }
|
||||||
|
|
||||||
|
void setFixedHeight(uInt32 height) override;
|
||||||
|
|
||||||
|
uInt32 getY() const override { return myY; }
|
||||||
|
|
||||||
|
uInt32 scanlines() const override { return myCurrentFrameTotalLines; }
|
||||||
|
|
||||||
|
Int32 missingScanlines() const override;
|
||||||
|
|
||||||
|
void setYstart(uInt32 ystart) override;
|
||||||
|
|
||||||
|
uInt32 ystart() const override { return myYStart; }
|
||||||
|
|
||||||
|
void setLayout(FrameLayout mode) override { layout(mode); }
|
||||||
|
|
||||||
|
void onSetVsync() override;
|
||||||
|
|
||||||
|
void onNextLine() override;
|
||||||
|
|
||||||
|
void onReset() override;
|
||||||
|
|
||||||
|
void onLayoutChange() override;
|
||||||
|
|
||||||
|
bool onSave(Serializer& out) const override;
|
||||||
|
|
||||||
|
bool onLoad(Serializer& in) override;
|
||||||
|
|
||||||
|
string name() const override { return "TIA_FrameManager"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
waitForVsyncStart,
|
||||||
|
waitForVsyncEnd,
|
||||||
|
waitForFrameStart,
|
||||||
|
frame
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void updateAutodetectedLayout();
|
||||||
|
|
||||||
|
void setState(State state);
|
||||||
|
|
||||||
|
void updateIsRendering();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
State myState;
|
||||||
|
uInt32 myLineInState;
|
||||||
|
uInt32 myVsyncLines;
|
||||||
|
uInt32 myY, myLastY;
|
||||||
|
|
||||||
|
uInt32 myVblankLines;
|
||||||
|
uInt32 myKernelLines;
|
||||||
|
uInt32 myOverscanLines;
|
||||||
|
uInt32 myFrameLines;
|
||||||
|
uInt32 myHeight;
|
||||||
|
uInt32 myFixedHeight;
|
||||||
|
uInt32 myYStart;
|
||||||
|
|
||||||
|
bool myJitterEnabled;
|
||||||
|
|
||||||
|
Int32 myStableFrameLines;
|
||||||
|
uInt8 myStableFrameHeightCountdown;
|
||||||
|
|
||||||
|
JitterEmulation myJitterEmulation;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
FrameManager(const FrameManager&) = delete;
|
||||||
|
FrameManager(FrameManager&&) = delete;
|
||||||
|
FrameManager& operator=(const FrameManager&) = delete;
|
||||||
|
FrameManager& operator=(FrameManager&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIA_FRAME_MANAGER
|
|
@ -0,0 +1,123 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include "JitterEmulation.hxx"
|
||||||
|
|
||||||
|
enum Metrics: uInt32 {
|
||||||
|
framesForStableHeight = 2,
|
||||||
|
minDeltaForJitter = 3,
|
||||||
|
maxJitter = 50
|
||||||
|
};
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
JitterEmulation::JitterEmulation() :
|
||||||
|
myYStart(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void JitterEmulation::reset()
|
||||||
|
{
|
||||||
|
myLastFrameScanlines = 0;
|
||||||
|
myStableFrameFinalLines = 0;
|
||||||
|
myStableFrames = 0;
|
||||||
|
myStabilizationCounter = 0;
|
||||||
|
myJitter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void JitterEmulation::frameComplete(uInt32 scanlineCount)
|
||||||
|
{
|
||||||
|
if (scanlineCount != myStableFrameFinalLines) {
|
||||||
|
if (scanlineCount == myLastFrameScanlines) {
|
||||||
|
|
||||||
|
if (++myStabilizationCounter >= Metrics::framesForStableHeight) {
|
||||||
|
if (myStableFrameFinalLines > 0) updateJitter(scanlineCount - myStableFrameFinalLines);
|
||||||
|
|
||||||
|
myStableFrameFinalLines = scanlineCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else myStabilizationCounter = 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 (uInt32(abs(scanlineDifference)) < Metrics::minDeltaForJitter) return;
|
||||||
|
|
||||||
|
Int32 jitter = std::min<Int32>(jitter, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool JitterEmulation::save(Serializer& out) const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
out.putString(name());
|
||||||
|
|
||||||
|
out.putInt(myLastFrameScanlines);
|
||||||
|
out.putInt(myStableFrameFinalLines);
|
||||||
|
out.putInt(myStableFrames);
|
||||||
|
out.putInt(myStabilizationCounter);
|
||||||
|
out.putInt(myJitter);
|
||||||
|
out.putInt(myJitterFactor);
|
||||||
|
out.putInt(myYStart);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: JitterEmulation::save" << std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool JitterEmulation::load(Serializer& in)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (in.getString() != name()) return false;
|
||||||
|
|
||||||
|
myLastFrameScanlines = in.getInt();
|
||||||
|
myStableFrameFinalLines = in.getInt();
|
||||||
|
myStableFrames = in.getInt();
|
||||||
|
myStabilizationCounter = in.getInt();
|
||||||
|
myJitter = in.getInt();
|
||||||
|
myJitterFactor = in.getInt();
|
||||||
|
myYStart = in.getInt();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: JitterEmulation::load" << std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef TIA_JITTER_EMULATION
|
||||||
|
#define TIA_JITTER_EMULATION
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
#include "Serializable.hxx"
|
||||||
|
|
||||||
|
class JitterEmulation: public Serializable {
|
||||||
|
public:
|
||||||
|
|
||||||
|
JitterEmulation();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void frameComplete(uInt32 scanlineCount);
|
||||||
|
|
||||||
|
void setJitterFactor(Int32 factor) { myJitterFactor = factor; }
|
||||||
|
|
||||||
|
Int32 jitter() const { return myJitter; }
|
||||||
|
|
||||||
|
void setYStart(uInt32 ystart) { myYStart = ystart; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save state.
|
||||||
|
*/
|
||||||
|
bool save(Serializer& out) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore state.
|
||||||
|
*/
|
||||||
|
bool load(Serializer& in) override;
|
||||||
|
|
||||||
|
string name() const override { return "JitterEmulation"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void updateJitter(Int32 scanlineDifference);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uInt32 myLastFrameScanlines;
|
||||||
|
|
||||||
|
uInt32 myStableFrameFinalLines;
|
||||||
|
|
||||||
|
uInt32 myStableFrames;
|
||||||
|
|
||||||
|
uInt32 myStabilizationCounter;
|
||||||
|
|
||||||
|
Int32 myJitter;
|
||||||
|
|
||||||
|
Int32 myJitterFactor;
|
||||||
|
|
||||||
|
uInt32 myYStart;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
JitterEmulation(const JitterEmulation&) = delete;
|
||||||
|
JitterEmulation(JitterEmulation&&) = delete;
|
||||||
|
JitterEmulation& operator=(const JitterEmulation&) = delete;
|
||||||
|
JitterEmulation& operator=(JitterEmulation&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIA_JITTER_EMULATION
|
|
@ -0,0 +1,14 @@
|
||||||
|
MODULE := src/emucore/tia/frame-manager
|
||||||
|
|
||||||
|
MODULE_OBJS := \
|
||||||
|
src/emucore/tia/frame-manager/FrameManager.o \
|
||||||
|
src/emucore/tia/frame-manager/AbstractFrameManager.o \
|
||||||
|
src/emucore/tia/frame-manager/FrameLayoutDetector.o \
|
||||||
|
src/emucore/tia/frame-manager/YStartDetector.o \
|
||||||
|
src/emucore/tia/frame-manager/JitterEmulation.o
|
||||||
|
|
||||||
|
MODULE_DIRS += \
|
||||||
|
src/emucore/tia/frame-manager
|
||||||
|
|
||||||
|
# Include common rules
|
||||||
|
include $(srcdir)/common.rules
|
|
@ -2,7 +2,6 @@ MODULE := src/emucore/tia
|
||||||
|
|
||||||
MODULE_OBJS := \
|
MODULE_OBJS := \
|
||||||
src/emucore/tia/TIA.o \
|
src/emucore/tia/TIA.o \
|
||||||
src/emucore/tia/FrameManager.o \
|
|
||||||
src/emucore/tia/Playfield.o \
|
src/emucore/tia/Playfield.o \
|
||||||
src/emucore/tia/DrawCounterDecodes.o \
|
src/emucore/tia/DrawCounterDecodes.o \
|
||||||
src/emucore/tia/Missile.o \
|
src/emucore/tia/Missile.o \
|
||||||
|
@ -10,8 +9,7 @@ MODULE_OBJS := \
|
||||||
src/emucore/tia/Ball.o \
|
src/emucore/tia/Ball.o \
|
||||||
src/emucore/tia/Background.o \
|
src/emucore/tia/Background.o \
|
||||||
src/emucore/tia/LatchedInput.o \
|
src/emucore/tia/LatchedInput.o \
|
||||||
src/emucore/tia/PaddleReader.o \
|
src/emucore/tia/PaddleReader.o
|
||||||
src/emucore/tia/VblankManager.o
|
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
src/emucore/tia
|
src/emucore/tia
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "Props.hxx"
|
#include "Props.hxx"
|
||||||
#include "PropsSet.hxx"
|
#include "PropsSet.hxx"
|
||||||
#include "TabWidget.hxx"
|
#include "TabWidget.hxx"
|
||||||
#include "FrameManager.hxx"
|
#include "TIAConstants.hxx"
|
||||||
#include "Widget.hxx"
|
#include "Widget.hxx"
|
||||||
|
|
||||||
#include "GameInfoDialog.hxx"
|
#include "GameInfoDialog.hxx"
|
||||||
|
@ -310,8 +310,8 @@ GameInfoDialog::GameInfoDialog(
|
||||||
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "YStart ", kTextAlignLeft);
|
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "YStart ", kTextAlignLeft);
|
||||||
myYStart = new SliderWidget(myTab, font, t->getRight(), ypos, 8*fontWidth, lineHeight,
|
myYStart = new SliderWidget(myTab, font, t->getRight(), ypos, 8*fontWidth, lineHeight,
|
||||||
"", 0, kYStartChanged);
|
"", 0, kYStartChanged);
|
||||||
myYStart->setMinValue(FrameManager::minYStart-1);
|
myYStart->setMinValue(TIAConstants::minYStart-1);
|
||||||
myYStart->setMaxValue(FrameManager::maxYStart);
|
myYStart->setMaxValue(TIAConstants::maxYStart);
|
||||||
wid.push_back(myYStart);
|
wid.push_back(myYStart);
|
||||||
myYStartLabel = new StaticTextWidget(myTab, font, myYStart->getRight() + 4,
|
myYStartLabel = new StaticTextWidget(myTab, font, myYStart->getRight() + 4,
|
||||||
ypos+1, 5*fontWidth, fontHeight, "", kTextAlignLeft);
|
ypos+1, 5*fontWidth, fontHeight, "", kTextAlignLeft);
|
||||||
|
@ -321,8 +321,8 @@ GameInfoDialog::GameInfoDialog(
|
||||||
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "Height ", kTextAlignLeft);
|
t = new StaticTextWidget(myTab, font, hSpace, ypos+1, "Height ", kTextAlignLeft);
|
||||||
myHeight = new SliderWidget(myTab, font, t->getRight(), ypos, 8*fontWidth, lineHeight,
|
myHeight = new SliderWidget(myTab, font, t->getRight(), ypos, 8*fontWidth, lineHeight,
|
||||||
"", 0, kHeightChanged);
|
"", 0, kHeightChanged);
|
||||||
myHeight->setMinValue(FrameManager::minViewableHeight-1);
|
myHeight->setMinValue(TIAConstants::minViewableHeight-1);
|
||||||
myHeight->setMaxValue(FrameManager::maxViewableHeight);
|
myHeight->setMaxValue(TIAConstants::maxViewableHeight);
|
||||||
wid.push_back(myHeight);
|
wid.push_back(myHeight);
|
||||||
myHeightLabel = new StaticTextWidget(myTab, font, myHeight->getRight() + 4,
|
myHeightLabel = new StaticTextWidget(myTab, font, myHeight->getRight() + 4,
|
||||||
ypos+1, 5*fontWidth, fontHeight, "", kTextAlignLeft);
|
ypos+1, 5*fontWidth, fontHeight, "", kTextAlignLeft);
|
||||||
|
@ -647,14 +647,14 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
case kYStartChanged:
|
case kYStartChanged:
|
||||||
if(myYStart->getValue() == FrameManager::minYStart-1)
|
if(myYStart->getValue() == TIAConstants::minYStart-1)
|
||||||
myYStartLabel->setLabel("Auto");
|
myYStartLabel->setLabel("Auto");
|
||||||
else
|
else
|
||||||
myYStartLabel->setValue(myYStart->getValue());
|
myYStartLabel->setValue(myYStart->getValue());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kHeightChanged:
|
case kHeightChanged:
|
||||||
if(myHeight->getValue() == FrameManager::minViewableHeight-1)
|
if(myHeight->getValue() == TIAConstants::minViewableHeight-1)
|
||||||
myHeightLabel->setLabel("Auto");
|
myHeightLabel->setLabel("Auto");
|
||||||
else
|
else
|
||||||
myHeightLabel->setValue(myHeight->getValue());
|
myHeightLabel->setValue(myHeight->getValue());
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "OSystem.hxx"
|
#include "OSystem.hxx"
|
||||||
#include "Settings.hxx"
|
#include "Settings.hxx"
|
||||||
#include "Widget.hxx"
|
#include "Widget.hxx"
|
||||||
|
#include "TIAConstants.hxx"
|
||||||
|
|
||||||
#include "RomInfoWidget.hxx"
|
#include "RomInfoWidget.hxx"
|
||||||
|
|
||||||
|
@ -28,8 +29,8 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
: Widget(boss, font, x, y, w, h),
|
: Widget(boss, font, x, y, w, h),
|
||||||
mySurfaceIsValid(false),
|
mySurfaceIsValid(false),
|
||||||
myHaveProperties(false),
|
myHaveProperties(false),
|
||||||
myAvail(w > 400 ? GUI::Size(640, FrameManager::maxViewableHeight*2) :
|
myAvail(w > 400 ? GUI::Size(640, TIAConstants::maxViewableHeight*2) :
|
||||||
GUI::Size(320, FrameManager::maxViewableHeight))
|
GUI::Size(320, TIAConstants::maxViewableHeight))
|
||||||
{
|
{
|
||||||
_flags = WIDGET_ENABLED;
|
_flags = WIDGET_ENABLED;
|
||||||
_bgcolor = _bgcolorhi = kWidColor;
|
_bgcolor = _bgcolorhi = kWidColor;
|
||||||
|
@ -76,7 +77,7 @@ void RomInfoWidget::parseProperties()
|
||||||
// only draw certain parts of it
|
// only draw certain parts of it
|
||||||
if(mySurface == nullptr)
|
if(mySurface == nullptr)
|
||||||
{
|
{
|
||||||
mySurface = instance().frameBuffer().allocateSurface(320*2, FrameManager::maxViewableHeight*2);
|
mySurface = instance().frameBuffer().allocateSurface(320*2, TIAConstants::maxViewableHeight*2);
|
||||||
mySurface->attributes().smoothing = true;
|
mySurface->attributes().smoothing = true;
|
||||||
mySurface->applyAttributes();
|
mySurface->applyAttributes();
|
||||||
|
|
||||||
|
|
|
@ -366,8 +366,6 @@
|
||||||
DC6C726313CDEA0A008A5975 /* LoggerDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC6C726113CDEA0A008A5975 /* LoggerDialog.hxx */; };
|
DC6C726313CDEA0A008A5975 /* LoggerDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC6C726113CDEA0A008A5975 /* LoggerDialog.hxx */; };
|
||||||
DC6D39871A3CE65000171E71 /* CartWDWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC6D39851A3CE65000171E71 /* CartWDWidget.cxx */; };
|
DC6D39871A3CE65000171E71 /* CartWDWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC6D39851A3CE65000171E71 /* CartWDWidget.cxx */; };
|
||||||
DC6D39881A3CE65000171E71 /* CartWDWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC6D39861A3CE65000171E71 /* CartWDWidget.hxx */; };
|
DC6D39881A3CE65000171E71 /* CartWDWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC6D39861A3CE65000171E71 /* CartWDWidget.hxx */; };
|
||||||
DC72B2221E356F4F009056D0 /* VblankManager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC72B2201E356F4F009056D0 /* VblankManager.cxx */; };
|
|
||||||
DC72B2231E356F4F009056D0 /* VblankManager.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC72B2211E356F4F009056D0 /* VblankManager.hxx */; };
|
|
||||||
DC73BD851915E5B1003FAFAD /* FBSurfaceSDL2.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD831915E5B1003FAFAD /* FBSurfaceSDL2.cxx */; };
|
DC73BD851915E5B1003FAFAD /* FBSurfaceSDL2.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD831915E5B1003FAFAD /* FBSurfaceSDL2.cxx */; };
|
||||||
DC73BD861915E5B1003FAFAD /* FBSurfaceSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC73BD841915E5B1003FAFAD /* FBSurfaceSDL2.hxx */; };
|
DC73BD861915E5B1003FAFAD /* FBSurfaceSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC73BD841915E5B1003FAFAD /* FBSurfaceSDL2.hxx */; };
|
||||||
DC73BD891915E5E3003FAFAD /* FBSurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD871915E5E3003FAFAD /* FBSurface.cxx */; };
|
DC73BD891915E5E3003FAFAD /* FBSurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD871915E5E3003FAFAD /* FBSurface.cxx */; };
|
||||||
|
@ -563,8 +561,6 @@
|
||||||
DCF3A6EE1DFC75E3008A8AF3 /* DelayQueueMember.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCF3A6D41DFC75E3008A8AF3 /* DelayQueueMember.hxx */; };
|
DCF3A6EE1DFC75E3008A8AF3 /* DelayQueueMember.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCF3A6D41DFC75E3008A8AF3 /* DelayQueueMember.hxx */; };
|
||||||
DCF3A6EF1DFC75E3008A8AF3 /* DrawCounterDecodes.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCF3A6D51DFC75E3008A8AF3 /* DrawCounterDecodes.cxx */; };
|
DCF3A6EF1DFC75E3008A8AF3 /* DrawCounterDecodes.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCF3A6D51DFC75E3008A8AF3 /* DrawCounterDecodes.cxx */; };
|
||||||
DCF3A6F01DFC75E3008A8AF3 /* DrawCounterDecodes.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCF3A6D61DFC75E3008A8AF3 /* DrawCounterDecodes.hxx */; };
|
DCF3A6F01DFC75E3008A8AF3 /* DrawCounterDecodes.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCF3A6D61DFC75E3008A8AF3 /* DrawCounterDecodes.hxx */; };
|
||||||
DCF3A6F11DFC75E3008A8AF3 /* FrameManager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCF3A6D71DFC75E3008A8AF3 /* FrameManager.cxx */; };
|
|
||||||
DCF3A6F21DFC75E3008A8AF3 /* FrameManager.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCF3A6D81DFC75E3008A8AF3 /* FrameManager.hxx */; };
|
|
||||||
DCF3A6F31DFC75E3008A8AF3 /* LatchedInput.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCF3A6D91DFC75E3008A8AF3 /* LatchedInput.cxx */; };
|
DCF3A6F31DFC75E3008A8AF3 /* LatchedInput.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCF3A6D91DFC75E3008A8AF3 /* LatchedInput.cxx */; };
|
||||||
DCF3A6F41DFC75E3008A8AF3 /* LatchedInput.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCF3A6DA1DFC75E3008A8AF3 /* LatchedInput.hxx */; };
|
DCF3A6F41DFC75E3008A8AF3 /* LatchedInput.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCF3A6DA1DFC75E3008A8AF3 /* LatchedInput.hxx */; };
|
||||||
DCF3A6F51DFC75E3008A8AF3 /* Missile.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCF3A6DB1DFC75E3008A8AF3 /* Missile.cxx */; };
|
DCF3A6F51DFC75E3008A8AF3 /* Missile.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCF3A6DB1DFC75E3008A8AF3 /* Missile.cxx */; };
|
||||||
|
@ -594,6 +590,16 @@
|
||||||
DCFF14CE18B0260300A20364 /* EventHandlerSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCFF14CC18B0260300A20364 /* EventHandlerSDL2.hxx */; };
|
DCFF14CE18B0260300A20364 /* EventHandlerSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCFF14CC18B0260300A20364 /* EventHandlerSDL2.hxx */; };
|
||||||
DCFFE59D12100E1400DFA000 /* ComboDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCFFE59B12100E1400DFA000 /* ComboDialog.cxx */; };
|
DCFFE59D12100E1400DFA000 /* ComboDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCFFE59B12100E1400DFA000 /* ComboDialog.cxx */; };
|
||||||
DCFFE59E12100E1400DFA000 /* ComboDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCFFE59C12100E1400DFA000 /* ComboDialog.hxx */; };
|
DCFFE59E12100E1400DFA000 /* ComboDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCFFE59C12100E1400DFA000 /* ComboDialog.hxx */; };
|
||||||
|
E0306E0C1F93E916003DDD52 /* YStartDetector.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0306E061F93E915003DDD52 /* YStartDetector.cxx */; };
|
||||||
|
E0306E0D1F93E916003DDD52 /* FrameLayoutDetector.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0306E071F93E915003DDD52 /* FrameLayoutDetector.hxx */; };
|
||||||
|
E0306E0E1F93E916003DDD52 /* YStartDetector.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0306E081F93E915003DDD52 /* YStartDetector.hxx */; };
|
||||||
|
E0306E0F1F93E916003DDD52 /* JitterEmulation.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0306E091F93E915003DDD52 /* JitterEmulation.cxx */; };
|
||||||
|
E0306E101F93E916003DDD52 /* FrameLayoutDetector.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0306E0A1F93E916003DDD52 /* FrameLayoutDetector.cxx */; };
|
||||||
|
E0306E111F93E916003DDD52 /* JitterEmulation.hxx in Headers */ = {isa = PBXBuildFile; fileRef = E0306E0B1F93E916003DDD52 /* JitterEmulation.hxx */; };
|
||||||
|
E0406FB61F81A85400A82AE0 /* AbstractFrameManager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0DFDD781F81A358000F3505 /* AbstractFrameManager.cxx */; };
|
||||||
|
E0406FB71F81A85400A82AE0 /* AbstractFrameManager.hxx in Sources */ = {isa = PBXBuildFile; fileRef = E0DFDD791F81A358000F3505 /* AbstractFrameManager.hxx */; };
|
||||||
|
E0406FB81F81A85400A82AE0 /* FrameManager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = E0DFDD7B1F81A358000F3505 /* FrameManager.cxx */; };
|
||||||
|
E0406FB91F81A85400A82AE0 /* FrameManager.hxx in Sources */ = {isa = PBXBuildFile; fileRef = E0DFDD7C1F81A358000F3505 /* FrameManager.hxx */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXBuildRule section */
|
/* Begin PBXBuildRule section */
|
||||||
|
@ -604,6 +610,7 @@
|
||||||
isEditable = 1;
|
isEditable = 1;
|
||||||
outputFiles = (
|
outputFiles = (
|
||||||
);
|
);
|
||||||
|
script = "";
|
||||||
};
|
};
|
||||||
DC5EE7DF14F7C32D001C628C /* PBXBuildRule */ = {
|
DC5EE7DF14F7C32D001C628C /* PBXBuildRule */ = {
|
||||||
isa = PBXBuildRule;
|
isa = PBXBuildRule;
|
||||||
|
@ -612,6 +619,7 @@
|
||||||
isEditable = 1;
|
isEditable = 1;
|
||||||
outputFiles = (
|
outputFiles = (
|
||||||
);
|
);
|
||||||
|
script = "";
|
||||||
};
|
};
|
||||||
DC5EE7E014F7C32D001C628C /* PBXBuildRule */ = {
|
DC5EE7E014F7C32D001C628C /* PBXBuildRule */ = {
|
||||||
isa = PBXBuildRule;
|
isa = PBXBuildRule;
|
||||||
|
@ -620,6 +628,7 @@
|
||||||
isEditable = 1;
|
isEditable = 1;
|
||||||
outputFiles = (
|
outputFiles = (
|
||||||
);
|
);
|
||||||
|
script = "";
|
||||||
};
|
};
|
||||||
/* End PBXBuildRule section */
|
/* End PBXBuildRule section */
|
||||||
|
|
||||||
|
@ -1004,8 +1013,6 @@
|
||||||
DC6C726113CDEA0A008A5975 /* LoggerDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LoggerDialog.hxx; sourceTree = "<group>"; };
|
DC6C726113CDEA0A008A5975 /* LoggerDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LoggerDialog.hxx; sourceTree = "<group>"; };
|
||||||
DC6D39851A3CE65000171E71 /* CartWDWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartWDWidget.cxx; sourceTree = "<group>"; };
|
DC6D39851A3CE65000171E71 /* CartWDWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartWDWidget.cxx; sourceTree = "<group>"; };
|
||||||
DC6D39861A3CE65000171E71 /* CartWDWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartWDWidget.hxx; sourceTree = "<group>"; };
|
DC6D39861A3CE65000171E71 /* CartWDWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartWDWidget.hxx; sourceTree = "<group>"; };
|
||||||
DC72B2201E356F4F009056D0 /* VblankManager.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VblankManager.cxx; sourceTree = "<group>"; };
|
|
||||||
DC72B2211E356F4F009056D0 /* VblankManager.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VblankManager.hxx; sourceTree = "<group>"; };
|
|
||||||
DC73BD831915E5B1003FAFAD /* FBSurfaceSDL2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurfaceSDL2.cxx; sourceTree = "<group>"; };
|
DC73BD831915E5B1003FAFAD /* FBSurfaceSDL2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurfaceSDL2.cxx; sourceTree = "<group>"; };
|
||||||
DC73BD841915E5B1003FAFAD /* FBSurfaceSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FBSurfaceSDL2.hxx; sourceTree = "<group>"; };
|
DC73BD841915E5B1003FAFAD /* FBSurfaceSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FBSurfaceSDL2.hxx; sourceTree = "<group>"; };
|
||||||
DC73BD871915E5E3003FAFAD /* FBSurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurface.cxx; sourceTree = "<group>"; };
|
DC73BD871915E5E3003FAFAD /* FBSurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurface.cxx; sourceTree = "<group>"; };
|
||||||
|
@ -1203,8 +1210,6 @@
|
||||||
DCF3A6D41DFC75E3008A8AF3 /* DelayQueueMember.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DelayQueueMember.hxx; sourceTree = "<group>"; };
|
DCF3A6D41DFC75E3008A8AF3 /* DelayQueueMember.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DelayQueueMember.hxx; sourceTree = "<group>"; };
|
||||||
DCF3A6D51DFC75E3008A8AF3 /* DrawCounterDecodes.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawCounterDecodes.cxx; sourceTree = "<group>"; };
|
DCF3A6D51DFC75E3008A8AF3 /* DrawCounterDecodes.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawCounterDecodes.cxx; sourceTree = "<group>"; };
|
||||||
DCF3A6D61DFC75E3008A8AF3 /* DrawCounterDecodes.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DrawCounterDecodes.hxx; sourceTree = "<group>"; };
|
DCF3A6D61DFC75E3008A8AF3 /* DrawCounterDecodes.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DrawCounterDecodes.hxx; sourceTree = "<group>"; };
|
||||||
DCF3A6D71DFC75E3008A8AF3 /* FrameManager.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameManager.cxx; sourceTree = "<group>"; };
|
|
||||||
DCF3A6D81DFC75E3008A8AF3 /* FrameManager.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FrameManager.hxx; sourceTree = "<group>"; };
|
|
||||||
DCF3A6D91DFC75E3008A8AF3 /* LatchedInput.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LatchedInput.cxx; sourceTree = "<group>"; };
|
DCF3A6D91DFC75E3008A8AF3 /* LatchedInput.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LatchedInput.cxx; sourceTree = "<group>"; };
|
||||||
DCF3A6DA1DFC75E3008A8AF3 /* LatchedInput.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LatchedInput.hxx; sourceTree = "<group>"; };
|
DCF3A6DA1DFC75E3008A8AF3 /* LatchedInput.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LatchedInput.hxx; sourceTree = "<group>"; };
|
||||||
DCF3A6DB1DFC75E3008A8AF3 /* Missile.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Missile.cxx; sourceTree = "<group>"; };
|
DCF3A6DB1DFC75E3008A8AF3 /* Missile.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Missile.cxx; sourceTree = "<group>"; };
|
||||||
|
@ -1234,6 +1239,16 @@
|
||||||
DCFF14CC18B0260300A20364 /* EventHandlerSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EventHandlerSDL2.hxx; sourceTree = "<group>"; };
|
DCFF14CC18B0260300A20364 /* EventHandlerSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EventHandlerSDL2.hxx; sourceTree = "<group>"; };
|
||||||
DCFFE59B12100E1400DFA000 /* ComboDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComboDialog.cxx; sourceTree = "<group>"; };
|
DCFFE59B12100E1400DFA000 /* ComboDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComboDialog.cxx; sourceTree = "<group>"; };
|
||||||
DCFFE59C12100E1400DFA000 /* ComboDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ComboDialog.hxx; sourceTree = "<group>"; };
|
DCFFE59C12100E1400DFA000 /* ComboDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ComboDialog.hxx; sourceTree = "<group>"; };
|
||||||
|
E0306E061F93E915003DDD52 /* YStartDetector.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YStartDetector.cxx; sourceTree = "<group>"; };
|
||||||
|
E0306E071F93E915003DDD52 /* FrameLayoutDetector.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FrameLayoutDetector.hxx; sourceTree = "<group>"; };
|
||||||
|
E0306E081F93E915003DDD52 /* YStartDetector.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = YStartDetector.hxx; sourceTree = "<group>"; };
|
||||||
|
E0306E091F93E915003DDD52 /* JitterEmulation.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JitterEmulation.cxx; sourceTree = "<group>"; };
|
||||||
|
E0306E0A1F93E916003DDD52 /* FrameLayoutDetector.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLayoutDetector.cxx; sourceTree = "<group>"; };
|
||||||
|
E0306E0B1F93E916003DDD52 /* JitterEmulation.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = JitterEmulation.hxx; sourceTree = "<group>"; };
|
||||||
|
E0DFDD781F81A358000F3505 /* AbstractFrameManager.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractFrameManager.cxx; sourceTree = "<group>"; };
|
||||||
|
E0DFDD791F81A358000F3505 /* AbstractFrameManager.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AbstractFrameManager.hxx; sourceTree = "<group>"; };
|
||||||
|
E0DFDD7B1F81A358000F3505 /* FrameManager.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FrameManager.cxx; sourceTree = "<group>"; };
|
||||||
|
E0DFDD7C1F81A358000F3505 /* FrameManager.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = FrameManager.hxx; sourceTree = "<group>"; };
|
||||||
F5A47A9D01A0482F01D3D55B /* SDLMain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDLMain.h; sourceTree = SOURCE_ROOT; };
|
F5A47A9D01A0482F01D3D55B /* SDLMain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDLMain.h; sourceTree = SOURCE_ROOT; };
|
||||||
F5A47A9E01A0483001D3D55B /* SDLMain.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = SDLMain.m; sourceTree = SOURCE_ROOT; };
|
F5A47A9E01A0483001D3D55B /* SDLMain.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = SDLMain.m; sourceTree = SOURCE_ROOT; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
@ -1975,6 +1990,7 @@
|
||||||
DCE903E31DF5DCD10080A7F3 /* tia */ = {
|
DCE903E31DF5DCD10080A7F3 /* tia */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E0DFDD731F81A358000F3505 /* frame-manager */,
|
||||||
DCF3A6CD1DFC75E3008A8AF3 /* Background.cxx */,
|
DCF3A6CD1DFC75E3008A8AF3 /* Background.cxx */,
|
||||||
DCF3A6CE1DFC75E3008A8AF3 /* Background.hxx */,
|
DCF3A6CE1DFC75E3008A8AF3 /* Background.hxx */,
|
||||||
DCF3A6CF1DFC75E3008A8AF3 /* Ball.cxx */,
|
DCF3A6CF1DFC75E3008A8AF3 /* Ball.cxx */,
|
||||||
|
@ -1986,8 +2002,6 @@
|
||||||
DCF3A6D51DFC75E3008A8AF3 /* DrawCounterDecodes.cxx */,
|
DCF3A6D51DFC75E3008A8AF3 /* DrawCounterDecodes.cxx */,
|
||||||
DCF3A6D61DFC75E3008A8AF3 /* DrawCounterDecodes.hxx */,
|
DCF3A6D61DFC75E3008A8AF3 /* DrawCounterDecodes.hxx */,
|
||||||
DCE8B1861E7E03B300189864 /* FrameLayout.hxx */,
|
DCE8B1861E7E03B300189864 /* FrameLayout.hxx */,
|
||||||
DCF3A6D71DFC75E3008A8AF3 /* FrameManager.cxx */,
|
|
||||||
DCF3A6D81DFC75E3008A8AF3 /* FrameManager.hxx */,
|
|
||||||
DCF3A6D91DFC75E3008A8AF3 /* LatchedInput.cxx */,
|
DCF3A6D91DFC75E3008A8AF3 /* LatchedInput.cxx */,
|
||||||
DCF3A6DA1DFC75E3008A8AF3 /* LatchedInput.hxx */,
|
DCF3A6DA1DFC75E3008A8AF3 /* LatchedInput.hxx */,
|
||||||
DCF3A6DB1DFC75E3008A8AF3 /* Missile.cxx */,
|
DCF3A6DB1DFC75E3008A8AF3 /* Missile.cxx */,
|
||||||
|
@ -2000,12 +2014,27 @@
|
||||||
DCF3A6E31DFC75E3008A8AF3 /* Playfield.hxx */,
|
DCF3A6E31DFC75E3008A8AF3 /* Playfield.hxx */,
|
||||||
DCF3A6E41DFC75E3008A8AF3 /* TIA.cxx */,
|
DCF3A6E41DFC75E3008A8AF3 /* TIA.cxx */,
|
||||||
DCF3A6E51DFC75E3008A8AF3 /* TIA.hxx */,
|
DCF3A6E51DFC75E3008A8AF3 /* TIA.hxx */,
|
||||||
DC72B2201E356F4F009056D0 /* VblankManager.cxx */,
|
|
||||||
DC72B2211E356F4F009056D0 /* VblankManager.hxx */,
|
|
||||||
);
|
);
|
||||||
path = tia;
|
path = tia;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E0DFDD731F81A358000F3505 /* frame-manager */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E0306E0A1F93E916003DDD52 /* FrameLayoutDetector.cxx */,
|
||||||
|
E0306E071F93E915003DDD52 /* FrameLayoutDetector.hxx */,
|
||||||
|
E0306E091F93E915003DDD52 /* JitterEmulation.cxx */,
|
||||||
|
E0306E0B1F93E916003DDD52 /* JitterEmulation.hxx */,
|
||||||
|
E0306E061F93E915003DDD52 /* YStartDetector.cxx */,
|
||||||
|
E0306E081F93E915003DDD52 /* YStartDetector.hxx */,
|
||||||
|
E0DFDD781F81A358000F3505 /* AbstractFrameManager.cxx */,
|
||||||
|
E0DFDD791F81A358000F3505 /* AbstractFrameManager.hxx */,
|
||||||
|
E0DFDD7B1F81A358000F3505 /* FrameManager.cxx */,
|
||||||
|
E0DFDD7C1F81A358000F3505 /* FrameManager.hxx */,
|
||||||
|
);
|
||||||
|
path = "frame-manager";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXHeadersBuildPhase section */
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
|
@ -2104,7 +2133,6 @@
|
||||||
2D91742309BA90380026E9FF /* DebuggerParser.hxx in Headers */,
|
2D91742309BA90380026E9FF /* DebuggerParser.hxx in Headers */,
|
||||||
2D91742409BA90380026E9FF /* EditableWidget.hxx in Headers */,
|
2D91742409BA90380026E9FF /* EditableWidget.hxx in Headers */,
|
||||||
DC3EE86F1E2C0E6D00905161 /* zutil.h in Headers */,
|
DC3EE86F1E2C0E6D00905161 /* zutil.h in Headers */,
|
||||||
DCF3A6F21DFC75E3008A8AF3 /* FrameManager.hxx in Headers */,
|
|
||||||
2D91742509BA90380026E9FF /* EditTextWidget.hxx in Headers */,
|
2D91742509BA90380026E9FF /* EditTextWidget.hxx in Headers */,
|
||||||
DCB87E581A104C1E00BF2A3B /* MediaFactory.hxx in Headers */,
|
DCB87E581A104C1E00BF2A3B /* MediaFactory.hxx in Headers */,
|
||||||
2D91742809BA90380026E9FF /* PackedBitArray.hxx in Headers */,
|
2D91742809BA90380026E9FF /* PackedBitArray.hxx in Headers */,
|
||||||
|
@ -2126,6 +2154,7 @@
|
||||||
2D91745209BA90380026E9FF /* CommandDialog.hxx in Headers */,
|
2D91745209BA90380026E9FF /* CommandDialog.hxx in Headers */,
|
||||||
2D91745309BA90380026E9FF /* CommandMenu.hxx in Headers */,
|
2D91745309BA90380026E9FF /* CommandMenu.hxx in Headers */,
|
||||||
DCB2ECAE1F0AECA3009738A6 /* BSType.hxx in Headers */,
|
DCB2ECAE1F0AECA3009738A6 /* BSType.hxx in Headers */,
|
||||||
|
E0306E111F93E916003DDD52 /* JitterEmulation.hxx in Headers */,
|
||||||
2D91745509BA90380026E9FF /* CpuWidget.hxx in Headers */,
|
2D91745509BA90380026E9FF /* CpuWidget.hxx in Headers */,
|
||||||
2D91745609BA90380026E9FF /* DataGridOpsWidget.hxx in Headers */,
|
2D91745609BA90380026E9FF /* DataGridOpsWidget.hxx in Headers */,
|
||||||
2D91745709BA90380026E9FF /* DataGridWidget.hxx in Headers */,
|
2D91745709BA90380026E9FF /* DataGridWidget.hxx in Headers */,
|
||||||
|
@ -2161,6 +2190,7 @@
|
||||||
DC47455D09C34BFA00EDDA3A /* CheetahCheat.hxx in Headers */,
|
DC47455D09C34BFA00EDDA3A /* CheetahCheat.hxx in Headers */,
|
||||||
DC47455F09C34BFA00EDDA3A /* RamCheat.hxx in Headers */,
|
DC47455F09C34BFA00EDDA3A /* RamCheat.hxx in Headers */,
|
||||||
DCD56D390B247D920092F9F8 /* Cart4A50.hxx in Headers */,
|
DCD56D390B247D920092F9F8 /* Cart4A50.hxx in Headers */,
|
||||||
|
E0306E0D1F93E916003DDD52 /* FrameLayoutDetector.hxx in Headers */,
|
||||||
DC8078DB0B4BD5F3005E9305 /* DebuggerExpressions.hxx in Headers */,
|
DC8078DB0B4BD5F3005E9305 /* DebuggerExpressions.hxx in Headers */,
|
||||||
DC8078EB0B4BD697005E9305 /* UIDialog.hxx in Headers */,
|
DC8078EB0B4BD697005E9305 /* UIDialog.hxx in Headers */,
|
||||||
DCEECE570B5E5E540021D754 /* Cart0840.hxx in Headers */,
|
DCEECE570B5E5E540021D754 /* Cart0840.hxx in Headers */,
|
||||||
|
@ -2199,7 +2229,6 @@
|
||||||
DCF7B0DE10A762FC007A2870 /* CartF0.hxx in Headers */,
|
DCF7B0DE10A762FC007A2870 /* CartF0.hxx in Headers */,
|
||||||
DCF7B0E010A762FC007A2870 /* CartFA.hxx in Headers */,
|
DCF7B0E010A762FC007A2870 /* CartFA.hxx in Headers */,
|
||||||
DCC527D110B9DA19005E1287 /* Device.hxx in Headers */,
|
DCC527D110B9DA19005E1287 /* Device.hxx in Headers */,
|
||||||
DC72B2231E356F4F009056D0 /* VblankManager.hxx in Headers */,
|
|
||||||
DCC527D310B9DA19005E1287 /* M6502.hxx in Headers */,
|
DCC527D310B9DA19005E1287 /* M6502.hxx in Headers */,
|
||||||
DC3EE8661E2C0E6D00905161 /* inflate.h in Headers */,
|
DC3EE8661E2C0E6D00905161 /* inflate.h in Headers */,
|
||||||
DCC527D510B9DA19005E1287 /* NullDev.hxx in Headers */,
|
DCC527D510B9DA19005E1287 /* NullDev.hxx in Headers */,
|
||||||
|
@ -2309,6 +2338,7 @@
|
||||||
DCAACB13188D636F00A4D282 /* CartBFWidget.hxx in Headers */,
|
DCAACB13188D636F00A4D282 /* CartBFWidget.hxx in Headers */,
|
||||||
DCAACB15188D636F00A4D282 /* CartDFSCWidget.hxx in Headers */,
|
DCAACB15188D636F00A4D282 /* CartDFSCWidget.hxx in Headers */,
|
||||||
DC44019F1F1A5D01008C08F6 /* ColorWidget.hxx in Headers */,
|
DC44019F1F1A5D01008C08F6 /* ColorWidget.hxx in Headers */,
|
||||||
|
E0306E0E1F93E916003DDD52 /* YStartDetector.hxx in Headers */,
|
||||||
DC96162D1F817830008A2206 /* AmigaMouseWidget.hxx in Headers */,
|
DC96162D1F817830008A2206 /* AmigaMouseWidget.hxx in Headers */,
|
||||||
DCAACB17188D636F00A4D282 /* CartDFWidget.hxx in Headers */,
|
DCAACB17188D636F00A4D282 /* CartDFWidget.hxx in Headers */,
|
||||||
DCF3A6FF1DFC75E3008A8AF3 /* TIA.hxx in Headers */,
|
DCF3A6FF1DFC75E3008A8AF3 /* TIA.hxx in Headers */,
|
||||||
|
@ -2416,6 +2446,10 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
E0406FB61F81A85400A82AE0 /* AbstractFrameManager.cxx in Sources */,
|
||||||
|
E0406FB71F81A85400A82AE0 /* AbstractFrameManager.hxx in Sources */,
|
||||||
|
E0406FB81F81A85400A82AE0 /* FrameManager.cxx in Sources */,
|
||||||
|
E0406FB91F81A85400A82AE0 /* FrameManager.hxx in Sources */,
|
||||||
2D91747409BA90380026E9FF /* SDLMain.m in Sources */,
|
2D91747409BA90380026E9FF /* SDLMain.m in Sources */,
|
||||||
2D91747509BA90380026E9FF /* Booster.cxx in Sources */,
|
2D91747509BA90380026E9FF /* Booster.cxx in Sources */,
|
||||||
DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */,
|
DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */,
|
||||||
|
@ -2441,6 +2475,7 @@
|
||||||
2D91748909BA90380026E9FF /* Console.cxx in Sources */,
|
2D91748909BA90380026E9FF /* Console.cxx in Sources */,
|
||||||
2D91748A09BA90380026E9FF /* Control.cxx in Sources */,
|
2D91748A09BA90380026E9FF /* Control.cxx in Sources */,
|
||||||
2D91748C09BA90380026E9FF /* Driving.cxx in Sources */,
|
2D91748C09BA90380026E9FF /* Driving.cxx in Sources */,
|
||||||
|
E0306E101F93E916003DDD52 /* FrameLayoutDetector.cxx in Sources */,
|
||||||
2D91748E09BA90380026E9FF /* Joystick.cxx in Sources */,
|
2D91748E09BA90380026E9FF /* Joystick.cxx in Sources */,
|
||||||
2D91748F09BA90380026E9FF /* Keyboard.cxx in Sources */,
|
2D91748F09BA90380026E9FF /* Keyboard.cxx in Sources */,
|
||||||
2D91749009BA90380026E9FF /* M6532.cxx in Sources */,
|
2D91749009BA90380026E9FF /* M6532.cxx in Sources */,
|
||||||
|
@ -2584,7 +2619,6 @@
|
||||||
DCAD60A81152F8BD00BC4184 /* CartDPCPlus.cxx in Sources */,
|
DCAD60A81152F8BD00BC4184 /* CartDPCPlus.cxx in Sources */,
|
||||||
DCD6FC7011C281ED005DA767 /* png.c in Sources */,
|
DCD6FC7011C281ED005DA767 /* png.c in Sources */,
|
||||||
DCD6FC7311C281ED005DA767 /* pngerror.c in Sources */,
|
DCD6FC7311C281ED005DA767 /* pngerror.c in Sources */,
|
||||||
DCF3A6F11DFC75E3008A8AF3 /* FrameManager.cxx in Sources */,
|
|
||||||
DCF3A6E71DFC75E3008A8AF3 /* Background.cxx in Sources */,
|
DCF3A6E71DFC75E3008A8AF3 /* Background.cxx in Sources */,
|
||||||
DCD6FC7411C281ED005DA767 /* pngget.c in Sources */,
|
DCD6FC7411C281ED005DA767 /* pngget.c in Sources */,
|
||||||
DCD6FC7511C281ED005DA767 /* pngmem.c in Sources */,
|
DCD6FC7511C281ED005DA767 /* pngmem.c in Sources */,
|
||||||
|
@ -2595,6 +2629,7 @@
|
||||||
DCD6FC7A11C281ED005DA767 /* pngrtran.c in Sources */,
|
DCD6FC7A11C281ED005DA767 /* pngrtran.c in Sources */,
|
||||||
DC3EE85C1E2C0E6D00905161 /* gzclose.c in Sources */,
|
DC3EE85C1E2C0E6D00905161 /* gzclose.c in Sources */,
|
||||||
DCD6FC7B11C281ED005DA767 /* pngrutil.c in Sources */,
|
DCD6FC7B11C281ED005DA767 /* pngrutil.c in Sources */,
|
||||||
|
E0306E0F1F93E916003DDD52 /* JitterEmulation.cxx in Sources */,
|
||||||
DCD6FC7C11C281ED005DA767 /* pngset.c in Sources */,
|
DCD6FC7C11C281ED005DA767 /* pngset.c in Sources */,
|
||||||
DCD6FC7E11C281ED005DA767 /* pngtrans.c in Sources */,
|
DCD6FC7E11C281ED005DA767 /* pngtrans.c in Sources */,
|
||||||
DCD6FC7F11C281ED005DA767 /* pngwio.c in Sources */,
|
DCD6FC7F11C281ED005DA767 /* pngwio.c in Sources */,
|
||||||
|
@ -2625,6 +2660,7 @@
|
||||||
DCF3A6F31DFC75E3008A8AF3 /* LatchedInput.cxx in Sources */,
|
DCF3A6F31DFC75E3008A8AF3 /* LatchedInput.cxx in Sources */,
|
||||||
DC67270B1556F4860023653B /* CartCTY.cxx in Sources */,
|
DC67270B1556F4860023653B /* CartCTY.cxx in Sources */,
|
||||||
DCE395F016CB0B5F008DB1E5 /* FSNodeZIP.cxx in Sources */,
|
DCE395F016CB0B5F008DB1E5 /* FSNodeZIP.cxx in Sources */,
|
||||||
|
E0306E0C1F93E916003DDD52 /* YStartDetector.cxx in Sources */,
|
||||||
DCE395F216CB0B5F008DB1E5 /* ZipHandler.cxx in Sources */,
|
DCE395F216CB0B5F008DB1E5 /* ZipHandler.cxx in Sources */,
|
||||||
DCAAE5D31715887B0080BB82 /* Cart2KWidget.cxx in Sources */,
|
DCAAE5D31715887B0080BB82 /* Cart2KWidget.cxx in Sources */,
|
||||||
DCAAE5D51715887B0080BB82 /* Cart3FWidget.cxx in Sources */,
|
DCAAE5D51715887B0080BB82 /* Cart3FWidget.cxx in Sources */,
|
||||||
|
@ -2644,7 +2680,6 @@
|
||||||
DCAAE5E81715887B0080BB82 /* CartF6SCWidget.cxx in Sources */,
|
DCAAE5E81715887B0080BB82 /* CartF6SCWidget.cxx in Sources */,
|
||||||
DCAAE5EA1715887B0080BB82 /* CartF6Widget.cxx in Sources */,
|
DCAAE5EA1715887B0080BB82 /* CartF6Widget.cxx in Sources */,
|
||||||
DCAAE5EC1715887B0080BB82 /* CartF8SCWidget.cxx in Sources */,
|
DCAAE5EC1715887B0080BB82 /* CartF8SCWidget.cxx in Sources */,
|
||||||
DC72B2221E356F4F009056D0 /* VblankManager.cxx in Sources */,
|
|
||||||
DCAAE5EE1715887B0080BB82 /* CartF8Widget.cxx in Sources */,
|
DCAAE5EE1715887B0080BB82 /* CartF8Widget.cxx in Sources */,
|
||||||
DCAAE5F01715887B0080BB82 /* CartFAWidget.cxx in Sources */,
|
DCAAE5F01715887B0080BB82 /* CartFAWidget.cxx in Sources */,
|
||||||
DCAAE5F21715887B0080BB82 /* CartUAWidget.cxx in Sources */,
|
DCAAE5F21715887B0080BB82 /* CartUAWidget.cxx in Sources */,
|
||||||
|
@ -2736,6 +2771,7 @@
|
||||||
../emucore,
|
../emucore,
|
||||||
../gui,
|
../gui,
|
||||||
../yacc,
|
../yacc,
|
||||||
|
../emucore/tia,
|
||||||
.,
|
.,
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = "Info-Stella.plist";
|
INFOPLIST_FILE = "Info-Stella.plist";
|
||||||
|
@ -2788,6 +2824,7 @@
|
||||||
../emucore,
|
../emucore,
|
||||||
../gui,
|
../gui,
|
||||||
../yacc,
|
../yacc,
|
||||||
|
../emucore/tia,
|
||||||
.,
|
.,
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = "Info-Stella.plist";
|
INFOPLIST_FILE = "Info-Stella.plist";
|
||||||
|
|
Loading…
Reference in New Issue