diff --git a/stella/Changes.txt b/stella/Changes.txt
index 86a6ee38d..8cd9098f4 100644
--- a/stella/Changes.txt
+++ b/stella/Changes.txt
@@ -17,6 +17,10 @@
* Added support for 'EF' bankswitching (Paul Slocum Homestar Runner),
as well as auto-detection of this format.
+ * Added support for 'EFSC' bankswitching, as well as auto-detection of
+ this format. This is similar to the 'EF' scheme, but also includes
+ 128 bytes SuperChip RAM.
+
* Improved autodetection for 'UA' bankswitching format.
-Have fun!
diff --git a/stella/docs/index.html b/stella/docs/index.html
index 499d95feb..f055a873f 100644
--- a/stella/docs/index.html
+++ b/stella/docs/index.html
@@ -2571,6 +2571,7 @@ Ms Pac-Man (Stella extended codes):
E0 | 8K Parker Bros |
E7 | 16K M-network |
EF | 64K Homestar Runner |
+ EFSC | 64K Homestar Runner + ram |
F4 | 32K Atari |
F4SC | 32K Atari + ram |
F6 | 16K Atari |
diff --git a/stella/src/emucore/Cart.cxx b/stella/src/emucore/Cart.cxx
index 9ecae91ca..2d11dbef9 100644
--- a/stella/src/emucore/Cart.cxx
+++ b/stella/src/emucore/Cart.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: Cart.cxx,v 1.49 2009-04-05 18:59:56 stephena Exp $
+// $Id: Cart.cxx,v 1.50 2009-04-05 20:18:41 stephena Exp $
//============================================================================
#include
@@ -33,6 +33,7 @@
#include "CartE0.hxx"
#include "CartE7.hxx"
#include "CartEF.hxx"
+#include "CartEFSC.hxx"
#include "CartF4.hxx"
#include "CartF4SC.hxx"
#include "CartF6.hxx"
@@ -111,6 +112,8 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size,
cartridge = new CartridgeE7(image);
else if(type == "EF")
cartridge = new CartridgeEF(image);
+ else if(type == "EFSC")
+ cartridge = new CartridgeEFSC(image);
else if(type == "F4")
cartridge = new CartridgeF4(image);
else if(type == "F4SC")
@@ -269,7 +272,11 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
else if(isProbably4A50(image, size))
type = "4A50";
else if(isProbablyEF(image, size))
+ {
type = "EF";
+ if(isProbablySC(image, size))
+ type = "EFSC";
+ }
else
type = "MB";
}
diff --git a/stella/src/emucore/CartEFSC.cxx b/stella/src/emucore/CartEFSC.cxx
new file mode 100644
index 000000000..aba91fdd2
--- /dev/null
+++ b/stella/src/emucore/CartEFSC.cxx
@@ -0,0 +1,225 @@
+//============================================================================
+//
+// 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-2009 by Bradford W. Mott and the Stella team
+//
+// See the file "license" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//
+// $Id: CartEFSC.cxx,v 1.1 2009-04-05 20:18:41 stephena Exp $
+//============================================================================
+
+#include
+#include
+
+#include "Random.hxx"
+#include "System.hxx"
+#include "CartEFSC.hxx"
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CartridgeEFSC::CartridgeEFSC(const uInt8* image)
+{
+ // Copy the ROM image into my buffer
+ memcpy(myImage, image, 65536);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+CartridgeEFSC::~CartridgeEFSC()
+{
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void CartridgeEFSC::reset()
+{
+ // Initialize RAM with random values
+ class Random random;
+ for(uInt32 i = 0; i < 128; ++i)
+ myRAM[i] = random.next();
+
+ // Upon reset we switch to bank 1
+ bank(1);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void CartridgeEFSC::install(System& system)
+{
+ mySystem = &system;
+ uInt16 shift = mySystem->pageShift();
+ uInt16 mask = mySystem->pageMask();
+
+ // Make sure the system we're being installed in has a page size that'll work
+ assert((0x1000 & mask) == 0);
+
+ // Set the page accessing methods for the hot spots
+ System::PageAccess access;
+ for(uInt32 i = (0x1FE0 & ~mask); i < 0x2000; i += (1 << shift))
+ {
+ access.directPeekBase = 0;
+ access.directPokeBase = 0;
+ access.device = this;
+ mySystem->setPageAccess(i >> shift, access);
+ }
+
+ // Set the page accessing method for the RAM writing pages
+ for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift))
+ {
+ access.device = this;
+ access.directPeekBase = 0;
+ access.directPokeBase = &myRAM[j & 0x007F];
+ mySystem->setPageAccess(j >> shift, access);
+ }
+
+ // Set the page accessing method for the RAM reading pages
+ for(uInt32 k = 0x1080; k < 0x1100; k += (1 << shift))
+ {
+ access.device = this;
+ access.directPeekBase = &myRAM[k & 0x007F];
+ access.directPokeBase = 0;
+ mySystem->setPageAccess(k >> shift, access);
+ }
+
+ // Install pages for bank 1
+ bank(1);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+uInt8 CartridgeEFSC::peek(uInt16 address)
+{
+ address = address & 0x0FFF;
+
+ // Switch banks if necessary
+ if((address >= 0x0FE0) && (address <= 0x0FEF))
+ bank(address - 0x0FE0);
+
+ // NOTE: This does not handle accessing RAM, however, this function
+ // should never be called for RAM because of the way page accessing
+ // has been setup
+ return myImage[myCurrentBank * 4096 + address];
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void CartridgeEFSC::poke(uInt16 address, uInt8)
+{
+ address = address & 0x0FFF;
+
+ // Switch banks if necessary
+ if((address >= 0x0FE0) && (address <= 0x0FEF))
+ bank(address - 0x0FE0);
+
+ // NOTE: This does not handle accessing RAM, however, this function
+ // should never be called for RAM because of the way page accessing
+ // has been setup
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void CartridgeEFSC::bank(uInt16 bank)
+{
+ if(myBankLocked) return;
+
+ // Remember what bank we're in
+ myCurrentBank = bank;
+ uInt16 offset = myCurrentBank * 4096;
+ uInt16 shift = mySystem->pageShift();
+ uInt16 mask = mySystem->pageMask();
+
+ // Setup the page access methods for the current bank
+ System::PageAccess access;
+ access.device = this;
+ access.directPokeBase = 0;
+
+ // Map ROM image into the system
+ for(uInt32 address = 0x1100; address < (0x1FE0U & ~mask);
+ address += (1 << shift))
+ {
+ access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
+ mySystem->setPageAccess(address >> shift, access);
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int CartridgeEFSC::bank()
+{
+ return myCurrentBank;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int CartridgeEFSC::bankCount()
+{
+ return 16;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartridgeEFSC::patch(uInt16 address, uInt8 value)
+{
+ address = address & 0x0FFF;
+ myImage[myCurrentBank * 4096 + address] = value;
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+uInt8* CartridgeEFSC::getImage(int& size)
+{
+ size = 65536;
+ return &myImage[0];
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartridgeEFSC::save(Serializer& out) const
+{
+ string cart = name();
+
+ try
+ {
+ out.putString(cart);
+
+ out.putInt(myCurrentBank);
+ }
+ catch(const char* msg)
+ {
+ cerr << msg << endl;
+ return false;
+ }
+ catch(...)
+ {
+ cerr << "Unknown error in save state for " << cart << endl;
+ return false;
+ }
+
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool CartridgeEFSC::load(Deserializer& in)
+{
+ string cart = name();
+
+ try
+ {
+ if(in.getString() != cart)
+ return false;
+
+ myCurrentBank = (uInt16) in.getInt();
+ }
+ catch(const char* msg)
+ {
+ cerr << msg << endl;
+ return false;
+ }
+ catch(...)
+ {
+ cerr << "Unknown error in load state for " << cart << endl;
+ return false;
+ }
+
+ // Remember what bank we were in
+ bank(myCurrentBank);
+
+ return true;
+}
diff --git a/stella/src/emucore/CartEFSC.hxx b/stella/src/emucore/CartEFSC.hxx
new file mode 100644
index 000000000..8275b7feb
--- /dev/null
+++ b/stella/src/emucore/CartEFSC.hxx
@@ -0,0 +1,153 @@
+//============================================================================
+//
+// 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-2009 by Bradford W. Mott and the Stella team
+//
+// See the file "license" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//
+// $Id: CartEFSC.hxx,v 1.1 2009-04-05 20:18:41 stephena Exp $
+//============================================================================
+
+#ifndef CARTRIDGEEFSC_HXX
+#define CARTRIDGEEFSC_HXX
+
+class System;
+
+#include "bspf.hxx"
+#include "Cart.hxx"
+
+/**
+ Cartridge class used for Homestar Runner by Paul Slocum.
+ There are 16 4K banks (total of 64K ROM) with 128 bytes of RAM.
+ Accessing $1FE0 - $1FEF switches to each bank.
+
+ This interpretation is based on analysis of the z26 assembly code,
+ as this scheme doesn't seem to be documented anywhere.
+
+ @author Stephen Anthony
+ @version $Id: CartEFSC.hxx,v 1.1 2009-04-05 20:18:41 stephena Exp $
+*/
+class CartridgeEFSC : public Cartridge
+{
+ public:
+ /**
+ Create a new cartridge using the specified image
+
+ @param image Pointer to the ROM image
+ */
+ CartridgeEFSC(const uInt8* image);
+
+ /**
+ Destructor
+ */
+ virtual ~CartridgeEFSC();
+
+ public:
+ /**
+ Reset device to its power-on state
+ */
+ virtual void reset();
+
+ /**
+ Install cartridge in the specified system. Invoked by the system
+ when the cartridge is attached to it.
+
+ @param system The system the device should install itself in
+ */
+ virtual void install(System& system);
+
+ /**
+ Install pages for the specified bank in the system.
+
+ @param bank The bank that should be installed in the system
+ */
+ virtual void bank(uInt16 bank);
+
+ /**
+ Get the current bank.
+
+ @return The current bank, or -1 if bankswitching not supported
+ */
+ virtual int bank();
+
+ /**
+ Query the number of banks supported by the cartridge.
+ */
+ virtual int bankCount();
+
+ /**
+ Patch the cartridge ROM.
+
+ @param address The ROM address to patch
+ @param value The value to place into the address
+ @return Success or failure of the patch operation
+ */
+ virtual bool patch(uInt16 address, uInt8 value);
+
+ /**
+ Access the internal ROM image for this cartridge.
+
+ @param size Set to the size of the internal ROM image data
+ @return A pointer to the internal ROM image data
+ */
+ virtual uInt8* getImage(int& size);
+
+ /**
+ Save the current state of this cart to the given Serializer.
+
+ @param out The Serializer object to use
+ @return False on any errors, else true
+ */
+ virtual bool save(Serializer& out) const;
+
+ /**
+ Load the current state of this cart from the given Deserializer.
+
+ @param in The Deserializer object to use
+ @return False on any errors, else true
+ */
+ virtual bool load(Deserializer& in);
+
+ /**
+ Get a descriptor for the device name (used in error checking).
+
+ @return The name of the object
+ */
+ virtual string name() const { return "CartridgeEFSC"; }
+
+ public:
+ /**
+ Get the byte at the specified address.
+
+ @return The byte at the specified address
+ */
+ virtual uInt8 peek(uInt16 address);
+
+ /**
+ Change the byte at the specified address to the given value
+
+ @param address The address where the value should be stored
+ @param value The value to be stored at the address
+ */
+ virtual void poke(uInt16 address, uInt8 value);
+
+ private:
+ // Indicates which bank is currently active
+ uInt16 myCurrentBank;
+
+ // The 64K ROM image of the cartridge
+ uInt8 myImage[65536];
+
+ // The 128 bytes of RAM
+ uInt8 myRAM[128];
+};
+
+#endif
diff --git a/stella/src/emucore/module.mk b/stella/src/emucore/module.mk
index eec3986b0..432a954f7 100644
--- a/stella/src/emucore/module.mk
+++ b/stella/src/emucore/module.mk
@@ -14,6 +14,8 @@ MODULE_OBJS := \
src/emucore/CartDPC.o \
src/emucore/CartE0.o \
src/emucore/CartE7.o \
+ src/emucore/CartEF.o \
+ src/emucore/CartEFSC.o \
src/emucore/CartF4.o \
src/emucore/CartF4SC.o \
src/emucore/CartF6.o \
@@ -21,7 +23,6 @@ MODULE_OBJS := \
src/emucore/CartF8.o \
src/emucore/CartF8SC.o \
src/emucore/CartFASC.o \
- src/emucore/CartEF.o \
src/emucore/CartFE.o \
src/emucore/CartMB.o \
src/emucore/CartMC.o \
diff --git a/stella/src/gui/GameInfoDialog.cxx b/stella/src/gui/GameInfoDialog.cxx
index 67c325dc7..03c6a315a 100644
--- a/stella/src/gui/GameInfoDialog.cxx
+++ b/stella/src/gui/GameInfoDialog.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: GameInfoDialog.cxx,v 1.69 2009-04-05 18:59:56 stephena Exp $
+// $Id: GameInfoDialog.cxx,v 1.70 2009-04-05 20:18:41 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@@ -131,7 +131,7 @@ GameInfoDialog::GameInfoDialog(
ypos += lineHeight + 3;
new StaticTextWidget(myTab, font, xpos, ypos+1, lwidth, fontHeight,
"Type:", kTextAlignLeft);
- pwidth = font.getStringWidth("MC (C. Wilkson Megacart)");
+ pwidth = font.getStringWidth("EFSC (64K H. Runner + ram)");
items.clear();
items.push_back("Auto-detect", "AUTO-DETECT");
items.push_back("0840 (8K ECONObank)", "0840" );
@@ -145,7 +145,8 @@ GameInfoDialog::GameInfoDialog(
items.push_back("DPC (Pitfall II)", "DPC" );
items.push_back("E0 (8K Parker Bros)", "E0" );
items.push_back("E7 (16K M-network)", "E7" );
- items.push_back("EF (64K Homestar Runner)", "EF" );
+ items.push_back("EF (64K H. Runner)", "EF" );
+ items.push_back("EFSC (64K H. Runner + ram)", "EFSC" );
items.push_back("F4 (32K Atari)", "F4" );
items.push_back("F4SC (32K Atari + ram)", "F4SC" );
items.push_back("F6 (16K Atari)", "F6" );
diff --git a/stella/src/gui/GlobalPropsDialog.cxx b/stella/src/gui/GlobalPropsDialog.cxx
index b0a813dd8..592ae788d 100644
--- a/stella/src/gui/GlobalPropsDialog.cxx
+++ b/stella/src/gui/GlobalPropsDialog.cxx
@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
-// $Id: GlobalPropsDialog.cxx,v 1.5 2009-04-05 18:59:56 stephena Exp $
+// $Id: GlobalPropsDialog.cxx,v 1.6 2009-04-05 20:18:41 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@@ -43,7 +43,7 @@ GlobalPropsDialog::
buttonHeight = font.getLineHeight() + 4;
int xpos, ypos;
int lwidth = font.getStringWidth("Right Difficulty: "),
- pwidth = font.getStringWidth("MC (C. Wilkson Megacart)");
+ pwidth = font.getStringWidth("EFSC (64K H. Runner + ram)");
WidgetArray wid;
StringMap items;
@@ -76,7 +76,8 @@ GlobalPropsDialog::
items.push_back("DPC (Pitfall II)", "DPC" );
items.push_back("E0 (8K Parker Bros)", "E0" );
items.push_back("E7 (16K M-network)", "E7" );
- items.push_back("EF (64K Homestar Runner)", "EF" );
+ items.push_back("EF (64K H. Runner)", "EF" );
+ items.push_back("EFSC (64K H. Runner + ram)", "EFSC" );
items.push_back("F4 (32K Atari)", "F4" );
items.push_back("F4SC (32K Atari + ram)", "F4SC" );
items.push_back("F6 (16K Atari)", "F6" );