mirror of https://github.com/stella-emu/stella.git
Control-f now cycles between NTSC/PAL/SECAM/NTSC50/PAL60/SECAM60
display modes wrt both palette and display properties (# of scanlines, size of window, etc). This means you can now dynamically switch between these modes at runtime. Also added 'Shift-Control-f', which cycles through the modes in reverse order. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2527 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
b231dda2a9
commit
6353d118b7
|
@ -18,10 +18,19 @@
|
|||
scanlines; the output is now blanked as on a real TV. Special thanks
|
||||
to Omegamatrix of AtariAge for test ROMs in this area.
|
||||
|
||||
* Modified hotkey for "Change console palette" (Control-f) to also
|
||||
change the display properties of the TIA. This allows you to switch
|
||||
between NTSC/PAL/SECAM (and variants) modes dynamically. Related to
|
||||
this, added Shift-Control-f key to step backwards through the
|
||||
available modes.
|
||||
|
||||
* Fixed several bugs in DPC+ bankswitching scheme, including ability to
|
||||
load and save state files. As well, ROMs now work correctly after
|
||||
console format autodetection.
|
||||
|
||||
* Note: because of the TIA changes, the state file format has changed
|
||||
again, and old state files will not work with this release.
|
||||
|
||||
-Have fun!
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<br><br>
|
||||
<center><h2><b>A multi-platform Atari 2600 VCS emulator</b></h2></center>
|
||||
|
||||
<center><h4><b>Release 3.7</b></h4></center>
|
||||
<center><h4><b>Release 3.7.1</b></h4></center>
|
||||
<br><br>
|
||||
|
||||
<center><h2><b>User's Guide</b></h2></center>
|
||||
|
@ -1553,11 +1553,17 @@
|
|||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Toggle display palette (<i>NTSC/PAL/SECAM</i>)</td>
|
||||
<td>Toggle console type in increasing order (<i>NTSC/PAL/SECAM, etc)</i>)</td>
|
||||
<td>Control + f</td>
|
||||
<td>Control + f</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Toggle console type in decreasing order (<i>NTSC/PAL/SECAM, etc)</i>)</td>
|
||||
<td>Shift-Control + f</td>
|
||||
<td>Shift-Control + f</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Save current properties to a new properties file</td>
|
||||
<td>Control + s</td>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
#define STELLA_VERSION "3.8_svn"
|
||||
#define STELLA_VERSION "3.7.1_pre"
|
||||
#define STELLA_BUILD atoi("$Rev$" + 6)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,7 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
|
|||
myCMHandler(0),
|
||||
myDisplayFormat("NTSC"),
|
||||
myFramerate(60.0),
|
||||
myCurrentFormat(0),
|
||||
myUserPaletteDefined(false)
|
||||
{
|
||||
// Load user-defined palette for this ROM
|
||||
|
@ -118,24 +119,17 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
|
|||
// 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
|
||||
|
||||
// The algorithm used is as follows:
|
||||
// Run for 60 frames; if there's a frame that has more than 287
|
||||
// scanlines, count it as PAL
|
||||
// If at least 25 PAL frames are found, then the format is PAL, else NTSC
|
||||
bool fastscbios = myOSystem->settings().getBool("fastscbios");
|
||||
myOSystem->settings().setBool("fastscbios", true);
|
||||
mySystem->reset(true); // autodetect in reset enabled
|
||||
int palCount = 0;
|
||||
for(int i = 0; i < 60; ++i)
|
||||
{
|
||||
myTIA->update();
|
||||
if(myTIA->scanlines() >= 287)
|
||||
++palCount;
|
||||
}
|
||||
myDisplayFormat = (palCount >= 25) ? "PAL" : "NTSC";
|
||||
myDisplayFormat = myTIA->isPAL() ? "PAL" : "NTSC";
|
||||
if(myProperties.get(Display_Format) == "AUTO-DETECT")
|
||||
{
|
||||
autodetected = "*";
|
||||
myCurrentFormat = 0;
|
||||
}
|
||||
|
||||
// Don't forget to reset the SC progress bars again
|
||||
myOSystem->settings().setBool("fastscbios", fastscbios);
|
||||
|
@ -145,48 +139,15 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
|
|||
// Set up the correct properties used when toggling format
|
||||
// Note that this can be overridden if a format is forced
|
||||
// For example, if a PAL ROM is forced to be NTSC, it will use NTSC-like
|
||||
// properties (60Hz, 262 scanlines, etc) and cycle between NTSC-like modes
|
||||
// properties (60Hz, 262 scanlines, etc), but likely result in flicker
|
||||
// The TIA will self-adjust the framerate if necessary
|
||||
|
||||
// TODO - query these values directly from the TIA if value is 'AUTO'
|
||||
uInt32 ystart = atoi(myProperties.get(Display_YStart).c_str());
|
||||
if(ystart > 64) ystart = 64;
|
||||
uInt32 height = atoi(myProperties.get(Display_Height).c_str());
|
||||
if(height < 210) height = 210;
|
||||
else if(height > 256) height = 256;
|
||||
|
||||
if(myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" ||
|
||||
myDisplayFormat == "SECAM60")
|
||||
{
|
||||
// Assume we've got ~262 scanlines (NTSC-like format)
|
||||
myFramerate = 60.0;
|
||||
myConsoleInfo.InitialFrameRate = "60";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume we've got ~312 scanlines (PAL-like format)
|
||||
myFramerate = 50.0;
|
||||
myConsoleInfo.InitialFrameRate = "50";
|
||||
|
||||
// PAL ROMs normally need at least 250 lines
|
||||
height = BSPF_max(height, 250u);
|
||||
}
|
||||
|
||||
// Make sure these values fit within the bounds of the desktop
|
||||
// If not, attempt to center vertically
|
||||
if(height <= myOSystem->desktopHeight())
|
||||
{
|
||||
myTIA->setYStart(ystart);
|
||||
myTIA->setHeight(height);
|
||||
}
|
||||
else
|
||||
{
|
||||
ystart += height - myOSystem->desktopHeight();
|
||||
ystart = BSPF_min(ystart, 64u);
|
||||
height = myOSystem->desktopHeight();
|
||||
myTIA->setYStart(ystart);
|
||||
myTIA->setHeight(height);
|
||||
}
|
||||
setTIAProperties();
|
||||
if(myDisplayFormat == "NTSC") myCurrentFormat = 1;
|
||||
else if(myDisplayFormat == "PAL") myCurrentFormat = 2;
|
||||
else if(myDisplayFormat == "SECAM") myCurrentFormat = 3;
|
||||
else if(myDisplayFormat == "NTSC50") myCurrentFormat = 4;
|
||||
else if(myDisplayFormat == "PAL60") myCurrentFormat = 5;
|
||||
else if(myDisplayFormat == "SECAM60") myCurrentFormat = 6;
|
||||
|
||||
// Add the real controllers for this system
|
||||
// This must be done before the debugger is initialized
|
||||
|
@ -275,54 +236,56 @@ bool Console::load(Serializer& in)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::toggleFormat()
|
||||
void Console::toggleFormat(int direction)
|
||||
{
|
||||
string format, message;
|
||||
string saveformat, message;
|
||||
|
||||
if(myDisplayFormat.compare(0, 4, "NTSC") == 0)
|
||||
{
|
||||
if(myFramerate > 55.0)
|
||||
{
|
||||
format = "PAL60";
|
||||
message = "PAL palette (PAL60)";
|
||||
}
|
||||
else
|
||||
{
|
||||
format = "PAL";
|
||||
message = "PAL palette (PAL)";
|
||||
}
|
||||
}
|
||||
else if(myDisplayFormat.compare(0, 3, "PAL") == 0)
|
||||
{
|
||||
if(myFramerate > 55.0)
|
||||
{
|
||||
format = "SECAM";
|
||||
message = "SECAM palette (SECAM60)";
|
||||
}
|
||||
else
|
||||
{
|
||||
format = "SECAM";
|
||||
message = "SECAM palette (SECAM)";
|
||||
}
|
||||
}
|
||||
else if(myDisplayFormat.compare(0, 5, "SECAM") == 0)
|
||||
{
|
||||
if(myFramerate > 55.0)
|
||||
{
|
||||
format = "NTSC";
|
||||
message = "NTSC palette (NTSC)";
|
||||
}
|
||||
else
|
||||
{
|
||||
format = "NTSC50";
|
||||
message = "NTSC palette (NTSC50)";
|
||||
}
|
||||
}
|
||||
if(direction == 1)
|
||||
myCurrentFormat = (myCurrentFormat + 1) % 7;
|
||||
else if(direction == -1)
|
||||
myCurrentFormat = myCurrentFormat > 0 ? (myCurrentFormat - 1) : 6;
|
||||
|
||||
switch(myCurrentFormat)
|
||||
{
|
||||
case 0: // auto-detect
|
||||
myTIA->update();
|
||||
myDisplayFormat = myTIA->isPAL() ? "PAL" : "NTSC";
|
||||
message = "Auto-detect mode: " + myDisplayFormat;
|
||||
saveformat = "AUTO-DETECT";
|
||||
break;
|
||||
case 1:
|
||||
saveformat = myDisplayFormat = "NTSC";
|
||||
message = "NTSC mode";
|
||||
break;
|
||||
case 2:
|
||||
saveformat = myDisplayFormat = "PAL";
|
||||
message = "PAL mode";
|
||||
break;
|
||||
case 3:
|
||||
saveformat = myDisplayFormat = "SECAM";
|
||||
message = "SECAM mode";
|
||||
break;
|
||||
case 4:
|
||||
saveformat = myDisplayFormat = "NTSC50";
|
||||
message = "NTSC50 mode";
|
||||
break;
|
||||
case 5:
|
||||
saveformat = myDisplayFormat = "PAL60";
|
||||
message = "PAL60 mode";
|
||||
break;
|
||||
case 6:
|
||||
saveformat = myDisplayFormat = "SECAM60";
|
||||
message = "SECAM60 mode";
|
||||
break;
|
||||
}
|
||||
myProperties.set(Display_Format, saveformat);
|
||||
|
||||
myDisplayFormat = format;
|
||||
myProperties.set(Display_Format, myDisplayFormat);
|
||||
myOSystem->frameBuffer().showMessage(message);
|
||||
setPalette(myOSystem->settings().getString("palette"));
|
||||
setTIAProperties();
|
||||
myTIA->frameReset();
|
||||
initializeVideo(); // takes care of refreshing the screen
|
||||
|
||||
myOSystem->frameBuffer().showMessage(message);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -605,6 +568,50 @@ void Console::changeHeight(int direction)
|
|||
myProperties.set(Display_Height, val.str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::setTIAProperties()
|
||||
{
|
||||
// TODO - query these values directly from the TIA if value is 'AUTO'
|
||||
uInt32 ystart = atoi(myProperties.get(Display_YStart).c_str());
|
||||
if(ystart > 64) ystart = 64;
|
||||
uInt32 height = atoi(myProperties.get(Display_Height).c_str());
|
||||
if(height < 210) height = 210;
|
||||
else if(height > 256) height = 256;
|
||||
|
||||
if(myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" ||
|
||||
myDisplayFormat == "SECAM60")
|
||||
{
|
||||
// Assume we've got ~262 scanlines (NTSC-like format)
|
||||
myFramerate = 60.0;
|
||||
myConsoleInfo.InitialFrameRate = "60";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume we've got ~312 scanlines (PAL-like format)
|
||||
myFramerate = 50.0;
|
||||
myConsoleInfo.InitialFrameRate = "50";
|
||||
|
||||
// PAL ROMs normally need at least 250 lines
|
||||
height = BSPF_max(height, 250u);
|
||||
}
|
||||
|
||||
// Make sure these values fit within the bounds of the desktop
|
||||
// If not, attempt to center vertically
|
||||
if(height <= myOSystem->desktopHeight())
|
||||
{
|
||||
myTIA->setYStart(ystart);
|
||||
myTIA->setHeight(height);
|
||||
}
|
||||
else
|
||||
{
|
||||
ystart += height - myOSystem->desktopHeight();
|
||||
ystart = BSPF_min(ystart, 64u);
|
||||
height = myOSystem->desktopHeight();
|
||||
myTIA->setYStart(ystart);
|
||||
myTIA->setHeight(height);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::setControllers(const string& rommd5)
|
||||
{
|
||||
|
|
|
@ -182,8 +182,10 @@ class Console : public Serializable
|
|||
public:
|
||||
/**
|
||||
Toggle between NTSC/PAL/SECAM (and variants) display format.
|
||||
|
||||
@param direction +1 indicates increase, -1 indicates decrease.
|
||||
*/
|
||||
void toggleFormat();
|
||||
void toggleFormat(int direction = 1);
|
||||
|
||||
/**
|
||||
Toggle between the available palettes.
|
||||
|
@ -285,6 +287,12 @@ class Console : public Serializable
|
|||
void toggleFixedColors() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
Sets various properties of the TIA (YStart, Height, etc) based on
|
||||
the current display format.
|
||||
*/
|
||||
void setTIAProperties();
|
||||
|
||||
/**
|
||||
Adds the left and right controllers to the console.
|
||||
*/
|
||||
|
@ -350,6 +358,9 @@ class Console : public Serializable
|
|||
// The currently defined display framerate
|
||||
float myFramerate;
|
||||
|
||||
// Display format currently in use
|
||||
uInt32 myCurrentFormat;
|
||||
|
||||
// Indicates whether an external palette was found and
|
||||
// successfully loaded
|
||||
bool myUserPaletteDefined;
|
||||
|
|
|
@ -576,8 +576,8 @@ void EventHandler::poll(uInt64 time)
|
|||
toggleSAPortOrder();
|
||||
break;
|
||||
|
||||
case KBDK_f: // Ctrl-f toggles NTSC/PAL mode
|
||||
myOSystem->console().toggleFormat();
|
||||
case KBDK_f: // (Shift) Ctrl-f toggles NTSC/PAL/SECAM mode
|
||||
myOSystem->console().toggleFormat(mod & KMOD_SHIFT ? -1 : 1);
|
||||
break;
|
||||
|
||||
case KBDK_g: // Ctrl-g (un)grabs mouse
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "StateManager.hxx"
|
||||
|
||||
#define STATE_HEADER "03070000state"
|
||||
#define STATE_HEADER "03070100state"
|
||||
#define MOVIE_HEADER "03030000movie"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -54,6 +54,7 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
|||
myPartialFrameFlag(false),
|
||||
myAutoFrameEnabled(false),
|
||||
myFrameCounter(0),
|
||||
myPALFrameCounter(0),
|
||||
myBitsEnabled(true),
|
||||
myCollisionsEnabled(true)
|
||||
|
||||
|
@ -137,8 +138,35 @@ void TIA::reset()
|
|||
// Should undriven pins be randomly driven high or low?
|
||||
myTIAPinsDriven = mySettings.getBool("tiadriven");
|
||||
|
||||
myFrameCounter = 0;
|
||||
myFrameCounter = myPALFrameCounter = 0;
|
||||
myScanlineCountForLastFrame = 0;
|
||||
|
||||
myCurrentP0Mask = &TIATables::PxMask[0][0][0][0];
|
||||
myCurrentP1Mask = &TIATables::PxMask[0][0][0][0];
|
||||
myCurrentM0Mask = &TIATables::MxMask[0][0][0][0];
|
||||
myCurrentM1Mask = &TIATables::MxMask[0][0][0][0];
|
||||
myCurrentBLMask = &TIATables::BLMask[0][0][0];
|
||||
myCurrentPFMask = TIATables::PFMask[0];
|
||||
|
||||
// Recalculate the size of the display
|
||||
toggleFixedColors(0);
|
||||
frameReset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::frameReset()
|
||||
{
|
||||
// Clear frame buffers
|
||||
clearBuffers();
|
||||
|
||||
// Reset pixel pointer and drawing flag
|
||||
myFramePointer = myCurrentFrameBuffer;
|
||||
|
||||
// Calculate color clock offsets for starting and stopping frame drawing
|
||||
// Note that although we always start drawing at scanline zero, the
|
||||
// framebuffer that is exposed outside the class actually starts at 'ystart'
|
||||
myFramePointerOffset = 160 * myFrameYStart;
|
||||
|
||||
myAutoFrameEnabled = (mySettings.getInt("framerate") <= 0);
|
||||
myFramerate = myConsole.getFramerate();
|
||||
|
||||
|
@ -169,32 +197,6 @@ void TIA::reset()
|
|||
myMaximumNumberOfScanlines = 342;
|
||||
}
|
||||
|
||||
myCurrentP0Mask = &TIATables::PxMask[0][0][0][0];
|
||||
myCurrentP1Mask = &TIATables::PxMask[0][0][0][0];
|
||||
myCurrentM0Mask = &TIATables::MxMask[0][0][0][0];
|
||||
myCurrentM1Mask = &TIATables::MxMask[0][0][0][0];
|
||||
myCurrentBLMask = &TIATables::BLMask[0][0][0];
|
||||
myCurrentPFMask = TIATables::PFMask[0];
|
||||
|
||||
// Recalculate the size of the display
|
||||
toggleFixedColors(0);
|
||||
frameReset();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::frameReset()
|
||||
{
|
||||
// Clear frame buffers
|
||||
clearBuffers();
|
||||
|
||||
// Reset pixel pointer and drawing flag
|
||||
myFramePointer = myCurrentFrameBuffer;
|
||||
|
||||
// Calculate color clock offsets for starting and stopping frame drawing
|
||||
// Note that although we always start drawing at scanline zero, the
|
||||
// framebuffer that is exposed outside the class actually starts at 'ystart'
|
||||
myFramePointerOffset = 160 * myFrameYStart;
|
||||
|
||||
// NTSC screens will process at least 262 scanlines,
|
||||
// while PAL will have at least 312
|
||||
// In any event, at most 320 lines can be processed
|
||||
|
@ -350,6 +352,7 @@ bool TIA::save(Serializer& out) const
|
|||
out.putBool(myHMOVEBlankEnabled);
|
||||
|
||||
out.putInt(myFrameCounter);
|
||||
out.putInt(myPALFrameCounter);
|
||||
|
||||
// Save the sound sample stuff ...
|
||||
mySound.save(out);
|
||||
|
@ -452,7 +455,8 @@ bool TIA::load(Serializer& in)
|
|||
myPreviousHMOVEPos = (Int32) in.getInt();
|
||||
myHMOVEBlankEnabled = in.getBool();
|
||||
|
||||
myFrameCounter = (Int32) in.getInt();
|
||||
myFrameCounter = in.getInt();
|
||||
myPALFrameCounter = in.getInt();
|
||||
|
||||
// Load the sound sample stuff ...
|
||||
mySound.load(in);
|
||||
|
@ -603,6 +607,8 @@ inline void TIA::endFrame()
|
|||
|
||||
// Stats counters
|
||||
myFrameCounter++;
|
||||
if(myScanlineCountForLastFrame >= 287)
|
||||
myPALFrameCounter++;
|
||||
|
||||
// Recalculate framerate. attempting to auto-correct for scanline 'jumps'
|
||||
if(myFrameCounter % 8 == 0 && myAutoFrameEnabled &&
|
||||
|
|
|
@ -216,6 +216,13 @@ class TIA : public Device
|
|||
void enableColorLoss(bool mode)
|
||||
{ myColorLossEnabled = myFramerate <= 55 ? mode : false; }
|
||||
|
||||
/**
|
||||
Answers whether this TIA runs at NTSC or PAL scanrates,
|
||||
based on how many frames of out the total count are PAL frames.
|
||||
*/
|
||||
bool isPAL()
|
||||
{ return float(myPALFrameCounter) / myFrameCounter >= (25.0/60.0); }
|
||||
|
||||
/**
|
||||
Answers the current color clock we've gotten to on this scanline.
|
||||
|
||||
|
@ -605,8 +612,11 @@ class TIA : public Device
|
|||
// Automatic framerate correction based on number of scanlines
|
||||
bool myAutoFrameEnabled;
|
||||
|
||||
// Number of frames displayed by this TIA
|
||||
int myFrameCounter;
|
||||
// Number of total frames displayed by this TIA
|
||||
uInt32 myFrameCounter;
|
||||
|
||||
// Number of PAL frames displayed by this TIA
|
||||
uInt32 myPALFrameCounter;
|
||||
|
||||
// The framerate currently in use by the Console
|
||||
float myFramerate;
|
||||
|
|
Loading…
Reference in New Issue