From b0eff8900295d4fa2d8a72b6e5dbf01696d0bdb5 Mon Sep 17 00:00:00 2001 From: stephena Date: Sun, 5 Apr 2009 18:59:56 +0000 Subject: [PATCH] Added 'EF' (Homestar Runner) bankswitch support as well as autodetection. Improved 'UA' bankswitch format autodetection. Bumped version number. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1690 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/Changes.txt | 12 +- stella/docs/index.html | 1 + stella/src/common/Version.hxx | 4 +- stella/src/emucore/Cart.cxx | 35 ++++- stella/src/emucore/Cart.hxx | 9 +- stella/src/emucore/CartEF.cxx | 197 +++++++++++++++++++++++++++ stella/src/emucore/CartEF.hxx | 150 ++++++++++++++++++++ stella/src/emucore/module.mk | 1 + stella/src/gui/GameInfoDialog.cxx | 3 +- stella/src/gui/GlobalPropsDialog.cxx | 3 +- 10 files changed, 403 insertions(+), 12 deletions(-) create mode 100644 stella/src/emucore/CartEF.cxx create mode 100644 stella/src/emucore/CartEF.hxx diff --git a/stella/Changes.txt b/stella/Changes.txt index bf59be011..86a6ee38d 100644 --- a/stella/Changes.txt +++ b/stella/Changes.txt @@ -12,6 +12,16 @@ Release History =============================================================================== +2.7.5 to XXXXX: (2009) + + * Added support for 'EF' bankswitching (Paul Slocum Homestar Runner), + as well as auto-detection of this format. + + * Improved autodetection for 'UA' bankswitching format. + +-Have fun! + + 2.7.3 to 2.7.5: (Mar. 27, 2009) * After about 2 years, finally fixed the infamous 'red screen' issue when @@ -35,8 +45,6 @@ bytes when using this resolution. This should allow it to work better on devices with small displays. --Have fun! - 2.7.2 to 2.7.3: (Feb. 9, 2009) diff --git a/stella/docs/index.html b/stella/docs/index.html index f9db9a7f5..499d95feb 100644 --- a/stella/docs/index.html +++ b/stella/docs/index.html @@ -2570,6 +2570,7 @@ Ms Pac-Man (Stella extended codes): DPC Pitfall II E0 8K Parker Bros E7 16K M-network + EF 64K Homestar Runner F4 32K Atari F4SC 32K Atari + ram F6 16K Atari diff --git a/stella/src/common/Version.hxx b/stella/src/common/Version.hxx index 98f134056..4d970edd8 100644 --- a/stella/src/common/Version.hxx +++ b/stella/src/common/Version.hxx @@ -13,13 +13,13 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Version.hxx,v 1.54 2009-03-27 15:28:31 stephena Exp $ +// $Id: Version.hxx,v 1.55 2009-04-05 18:59:56 stephena Exp $ //============================================================================ #ifndef VERSION_HXX #define VERSION_HXX -#define STELLA_BASE_VERSION "2.7.5" +#define STELLA_BASE_VERSION "2.7.6_cvs" #ifdef NIGHTLY_BUILD #define STELLA_VERSION STELLA_BASE_VERSION "pre-" NIGHTLY_BUILD diff --git a/stella/src/emucore/Cart.cxx b/stella/src/emucore/Cart.cxx index bd75cb8ba..9ecae91ca 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.48 2009-02-07 21:50:05 stephena Exp $ +// $Id: Cart.cxx,v 1.49 2009-04-05 18:59:56 stephena Exp $ //============================================================================ #include @@ -32,6 +32,7 @@ #include "CartDPC.hxx" #include "CartE0.hxx" #include "CartE7.hxx" +#include "CartEF.hxx" #include "CartF4.hxx" #include "CartF4SC.hxx" #include "CartF6.hxx" @@ -108,6 +109,8 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size, cartridge = new CartridgeE0(image); else if(type == "E7") cartridge = new CartridgeE7(image); + else if(type == "EF") + cartridge = new CartridgeEF(image); else if(type == "F4") cartridge = new CartridgeF4(image); else if(type == "F4SC") @@ -265,6 +268,8 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size) type = "3F"; else if(isProbably4A50(image, size)) type = "4A50"; + else if(isProbablyEF(image, size)) + type = "EF"; else type = "MB"; } @@ -408,13 +413,35 @@ bool Cartridge::isProbablyE7(const uInt8* image, uInt32 size) return false; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Cartridge::isProbablyEF(const uInt8* image, uInt32 size) +{ + // EF cart bankswitching switches banks by accessing addresses 0xFE0 + // to 0xFEF, usually with either a NOP or LDA + // It's likely that the code will switch to bank 0, so that's what is tested + uInt8 signature[2][3] = { + { 0x0C, 0xE0, 0xFF }, // NOP $FFE0 + { 0xAD, 0xE0, 0xFF } // LDA $FFE0 + }; + if(searchForBytes(image, size, signature[0], 3, 1)) + return true; + else + return searchForBytes(image, size, signature[1], 3, 1); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Cartridge::isProbablyUA(const uInt8* image, uInt32 size) { // UA cart bankswitching switches to bank 1 by accessing address 0x240 - // using 'STA $240' - uInt8 signature[] = { 0x8D, 0x40, 0x02 }; // STA $240 - return searchForBytes(image, size, signature, 3, 1); + // using 'STA $240' or 'LDA $240' + uInt8 signature[2][3] = { + { 0x8D, 0x40, 0x02 }, // STA $240 + { 0xAD, 0x40, 0x02 } // LDA $240 + }; + if(searchForBytes(image, size, signature[0], 3, 1)) + return true; + else + return searchForBytes(image, size, signature[1], 3, 1); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/emucore/Cart.hxx b/stella/src/emucore/Cart.hxx index 569c42a93..980373f96 100644 --- a/stella/src/emucore/Cart.hxx +++ b/stella/src/emucore/Cart.hxx @@ -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.hxx,v 1.25 2009-01-01 18:13:35 stephena Exp $ +// $Id: Cart.hxx,v 1.26 2009-04-05 18:59:56 stephena Exp $ //============================================================================ #ifndef CARTRIDGE_HXX @@ -34,7 +34,7 @@ class Settings; game and handles any bankswitching performed by the cartridge. @author Bradford W. Mott - @version $Id: Cart.hxx,v 1.25 2009-01-01 18:13:35 stephena Exp $ + @version $Id: Cart.hxx,v 1.26 2009-04-05 18:59:56 stephena Exp $ */ class Cartridge : public Device { @@ -197,6 +197,11 @@ class Cartridge : public Device */ static bool isProbablyE7(const uInt8* image, uInt32 size); + /** + Returns true if the image is probably a EF bankswitching cartridge + */ + static bool isProbablyEF(const uInt8* image, uInt32 size); + /** Returns true if the image is probably a UA bankswitching cartridge */ diff --git a/stella/src/emucore/CartEF.cxx b/stella/src/emucore/CartEF.cxx new file mode 100644 index 000000000..bd28e37f2 --- /dev/null +++ b/stella/src/emucore/CartEF.cxx @@ -0,0 +1,197 @@ +//============================================================================ +// +// 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: CartEF.cxx,v 1.1 2009-04-05 18:59:56 stephena Exp $ +//============================================================================ + +#include +#include + +#include "System.hxx" +#include "CartEF.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeEF::CartridgeEF(const uInt8* image) +{ + // Copy the ROM image into my buffer + memcpy(myImage, image, 65536); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeEF::~CartridgeEF() +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEF::reset() +{ + // Upon reset we switch to bank 1 + myCurrentBank = 1; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEF::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); + } + + // Install pages for bank 1 + bank(1); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeEF::peek(uInt16 address) +{ + address = address & 0x0FFF; + + // Switch banks if necessary + if((address >= 0x0FE0) && (address <= 0x0FEF)) + bank(address - 0x0FE0); + + return myImage[myCurrentBank * 4096 + address]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEF::poke(uInt16 address, uInt8) +{ +// TODO - determine if writes will switch banks +/* + address = address & 0x0FFF; + + // Switch banks if necessary + if((address >= 0x0FE0) && (address <= 0x0FEF)) + bank(address - 0x0FE0); +*/ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEF::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 = 0x1000; address < (0x1FE0U & ~mask); + address += (1 << shift)) + { + access.directPeekBase = &myImage[offset + (address & 0x0FFF)]; + mySystem->setPageAccess(address >> shift, access); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartridgeEF::bank() +{ + return myCurrentBank; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartridgeEF::bankCount() +{ + return 16; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEF::patch(uInt16 address, uInt8 value) +{ + address = address & 0x0FFF; + myImage[myCurrentBank * 4096 + address] = value; + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8* CartridgeEF::getImage(int& size) +{ + size = 65536; + return &myImage[0]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEF::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 CartridgeEF::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/CartEF.hxx b/stella/src/emucore/CartEF.hxx new file mode 100644 index 000000000..cbeaae703 --- /dev/null +++ b/stella/src/emucore/CartEF.hxx @@ -0,0 +1,150 @@ +//============================================================================ +// +// 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: CartEF.hxx,v 1.1 2009-04-05 18:59:56 stephena Exp $ +//============================================================================ + +#ifndef CARTRIDGEEF_HXX +#define CARTRIDGEEF_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). + 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: CartEF.hxx,v 1.1 2009-04-05 18:59:56 stephena Exp $ +*/ +class CartridgeEF : public Cartridge +{ + public: + /** + Create a new cartridge using the specified image + + @param image Pointer to the ROM image + */ + CartridgeEF(const uInt8* image); + + /** + Destructor + */ + virtual ~CartridgeEF(); + + 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 "CartridgeEF"; } + + 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]; +}; + +#endif diff --git a/stella/src/emucore/module.mk b/stella/src/emucore/module.mk index 0dd55ef08..eec3986b0 100644 --- a/stella/src/emucore/module.mk +++ b/stella/src/emucore/module.mk @@ -21,6 +21,7 @@ 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 e3b1625a7..67c325dc7 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.68 2009-03-19 15:03:50 stephena Exp $ +// $Id: GameInfoDialog.cxx,v 1.69 2009-04-05 18:59:56 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -145,6 +145,7 @@ 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("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 9dae9cf97..b0a813dd8 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.4 2009-01-15 18:45:23 stephena Exp $ +// $Id: GlobalPropsDialog.cxx,v 1.5 2009-04-05 18:59:56 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -76,6 +76,7 @@ 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("F4 (32K Atari)", "F4" ); items.push_back("F4SC (32K Atari + ram)", "F4SC" ); items.push_back("F6 (16K Atari)", "F6" );