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:
stephena 2012-06-05 16:32:35 +00:00
parent b231dda2a9
commit 6353d118b7
9 changed files with 182 additions and 133 deletions

View File

@ -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!

View File

@ -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>

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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

View File

@ -30,7 +30,7 @@
#include "StateManager.hxx"
#define STATE_HEADER "03070000state"
#define STATE_HEADER "03070100state"
#define MOVIE_HEADER "03030000movie"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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 &&

View File

@ -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;