diff --git a/Changes.txt b/Changes.txt
index ffaa92033..a3a10218a 100644
--- a/Changes.txt
+++ b/Changes.txt
@@ -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!
diff --git a/docs/index.html b/docs/index.html
index 469f678c7..e79304110 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -10,7 +10,7 @@
A multi-platform Atari 2600 VCS emulator
- Release 3.7
+ Release 3.7.1
User's Guide
@@ -1553,11 +1553,17 @@
- Toggle display palette (NTSC/PAL/SECAM) |
+ Toggle console type in increasing order (NTSC/PAL/SECAM, etc)) |
Control + f |
Control + f |
+
+ Toggle console type in decreasing order (NTSC/PAL/SECAM, etc)) |
+ Shift-Control + f |
+ Shift-Control + f |
+
+
Save current properties to a new properties file |
Control + s |
diff --git a/src/common/Version.hxx b/src/common/Version.hxx
index 891730b39..5f044908b 100644
--- a/src/common/Version.hxx
+++ b/src/common/Version.hxx
@@ -22,7 +22,7 @@
#include
-#define STELLA_VERSION "3.8_svn"
+#define STELLA_VERSION "3.7.1_pre"
#define STELLA_BUILD atoi("$Rev$" + 6)
#endif
diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx
index 36edeb58d..881388cc1 100644
--- a/src/emucore/Console.cxx
+++ b/src/emucore/Console.cxx
@@ -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)
{
diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx
index e420fdfb2..587107866 100644
--- a/src/emucore/Console.hxx
+++ b/src/emucore/Console.hxx
@@ -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;
diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx
index ba72c2a3d..698f24119 100644
--- a/src/emucore/EventHandler.cxx
+++ b/src/emucore/EventHandler.cxx
@@ -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
diff --git a/src/emucore/StateManager.cxx b/src/emucore/StateManager.cxx
index dfbab3ae0..2b61889c3 100644
--- a/src/emucore/StateManager.cxx
+++ b/src/emucore/StateManager.cxx
@@ -30,7 +30,7 @@
#include "StateManager.hxx"
-#define STATE_HEADER "03070000state"
+#define STATE_HEADER "03070100state"
#define MOVIE_HEADER "03030000movie"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/TIA.cxx b/src/emucore/TIA.cxx
index 8a900bcad..32c8cba29 100644
--- a/src/emucore/TIA.cxx
+++ b/src/emucore/TIA.cxx
@@ -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 &&
diff --git a/src/emucore/TIA.hxx b/src/emucore/TIA.hxx
index ef30a94f8..113e723ac 100644
--- a/src/emucore/TIA.hxx
+++ b/src/emucore/TIA.hxx
@@ -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;