diff --git a/Changes.txt b/Changes.txt index ba723ac50..16e7a10a1 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,7 +12,7 @@ Release History =========================================================================== -3.6 to 3.7: (April xx, 2012) +3.6.1 to 3.7: (April xx, 2012) * Updated the CompuMate keyboard handler to recognize more keys on an actual keyboard, instead of having to remember the weird combinations @@ -21,11 +21,23 @@ * Added emulation for MindLink controller; the Bionic Breakthrough ROM now works. + * Updated FA2 bankswitch scheme (Star Castle) to emulate load/save + high score functionality to the Harmony cart flash RAM. + + * Updated internal database for 'Juno First' ROMs; they will now use + an AtariVox/SaveKey when possible. + * Updated included PNG library to latest stable version. -Have fun! +3.6 to 3.6.1: (March 30, 2012) + + * Extended FA2 bankswitch scheme to handle 28K ROMs (in addition to + the previously supported 24K ROMs). + + 3.5.5 to 3.6: (March 16, 2012) * Added support for 2600-daptor II device, including native support diff --git a/src/emucore/Cart.cxx b/src/emucore/Cart.cxx index 565957761..954a39348 100644 --- a/src/emucore/Cart.cxx +++ b/src/emucore/Cart.cxx @@ -62,7 +62,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5, - string& dtype, string& id, Settings& settings) + string& dtype, string& id, const OSystem& system, Settings& settings) { Cartridge* cartridge = 0; string type = dtype; @@ -177,7 +177,8 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5, else if(type == "FA" || type == "FASC") cartridge = new CartridgeFA(image, size, settings); else if(type == "FA2") - cartridge = new CartridgeFA2(image, size, settings); + cartridge = new CartridgeFA2(image, size, settings, + system.eepromDir() + "FA2_flash.dat"); else if(type == "FE") cartridge = new CartridgeFE(image, size, settings); else if(type == "MC") diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx index 6f3b12280..4e3dbc199 100644 --- a/src/emucore/Cart.hxx +++ b/src/emucore/Cart.hxx @@ -61,11 +61,13 @@ class Cartridge : public Device @param dtype The detected bankswitch type of the ROM image @param id Any extra info about the ROM (currently which part of a multiload game is being accessed + @param system The osystem associated with the system @param settings The settings associated with the system @return Pointer to the new cartridge object allocated on the heap */ static Cartridge* create(const uInt8* image, uInt32 size, string& md5, - string& dtype, string& id, Settings& settings); + string& dtype, string& id, + const OSystem& system, Settings& settings); /** Create a new cartridge diff --git a/src/emucore/CartFA2.cxx b/src/emucore/CartFA2.cxx index d1a2938b9..bbc9a2342 100644 --- a/src/emucore/CartFA2.cxx +++ b/src/emucore/CartFA2.cxx @@ -20,12 +20,16 @@ #include #include +#include "Serializer.hxx" #include "System.hxx" #include "CartFA2.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, const Settings& settings) +CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, + const Settings& settings, const string& flashfile) : Cartridge(settings), + myRamRWFlag(false), + myFlashFile(flashfile), mySize(size) { // Allocate array for the ROM image @@ -106,6 +110,12 @@ uInt8 CartridgeFA2::peek(uInt16 address) // Switch banks if necessary switch(address) { + case 0x0FF4: + // Load/save RAM to/from Harmony cart flash + if(mySize == 28*1024 && !bankLocked()) + return ramReadWrite(); + break; + case 0x0FF5: // Set the current bank to the first 4k bank bank(0); @@ -171,6 +181,12 @@ bool CartridgeFA2::poke(uInt16 address, uInt8) // Switch banks if necessary switch(address) { + case 0x0FF4: + // Load/save RAM to/from Harmony cart flash + if(mySize == 28*1024 && !bankLocked()) + ramReadWrite(); + break; + case 0x0FF5: // Set the current bank to the first 4k bank bank(0); @@ -231,14 +247,14 @@ bool CartridgeFA2::bank(uInt16 bank) System::PageAccess access(0, 0, 0, this, System::PA_READ); // Set the page accessing methods for the hot spots - for(uInt32 i = (0x1FF5 & ~mask); i < 0x2000; i += (1 << shift)) + for(uInt32 i = (0x1FF4 & ~mask); i < 0x2000; i += (1 << shift)) { access.codeAccessBase = &myCodeAccessBase[offset + (i & 0x0FFF)]; mySystem->setPageAccess(i >> shift, access); } // Setup the page access methods for the current bank - for(uInt32 address = 0x1200; address < (0x1FF5U & ~mask); + for(uInt32 address = 0x1200; address < (0x1FF4U & ~mask); address += (1 << shift)) { access.directPeekBase = &myImage[offset + (address & 0x0FFF)]; @@ -332,3 +348,58 @@ bool CartridgeFA2::load(Serializer& in) return true; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeFA2::ramReadWrite() +{ + /* The following algorithm implements accessing Harmony cart flash + + 1. Wait for an access to hotspot location $1FF4 (return 1 on first access). + + 2. Read byte 256 of RAM+ memory to determine the operation requested + (1 = read, 2 = write). + + 3. Save or load the entire 256 bytes of RAM+ memory to a file. + + 4. Set byte 256 of RAM+ memory to zero to indicate success. + + 5. Return 0 on the next access to $1FF4. + */ + if(!myRamRWFlag) + { + Serializer serializer(myFlashFile); + if(serializer.isValid()) + { + if(myRAM[255] == 1) // read + { + try + { + for(uInt32 i = 0; i < 256; ++i) + myRAM[i] = (uInt8) serializer.getByte(); + } + catch(const char* msg) + { + memset(myRAM, 0, 256); + } + } + else if(myRAM[255] == 2) // write + { + try + { + for(uInt32 i = 0; i < 256; ++i) + serializer.putByte((char)myRAM[i]); + } + catch(const char* msg) + { + // Maybe add logging here? + } + } + } + return 1; + } + else + { + myRamRWFlag = false; + return 0; + } +} diff --git a/src/emucore/CartFA2.hxx b/src/emucore/CartFA2.hxx index 1ffa5f5b3..8c987deed 100644 --- a/src/emucore/CartFA2.hxx +++ b/src/emucore/CartFA2.hxx @@ -43,8 +43,10 @@ class CartridgeFA2 : public Cartridge @param image Pointer to the ROM image @param size The size of the ROM image @param settings A reference to the various settings (read-only) + @param flashfile The full pathname for the flash file storing internal RAM */ - CartridgeFA2(const uInt8* image, uInt32 size, const Settings& settings); + CartridgeFA2(const uInt8* image, uInt32 size, const Settings& settings, + const string& flashfile); /** Destructor @@ -139,6 +141,13 @@ class CartridgeFA2 : public Cartridge */ bool poke(uInt16 address, uInt8 value); + private: + /** + Either load or save internal RAM to Harmony flash (represented by + a file in emulation). + */ + uInt8 ramReadWrite(); + private: // Indicates which bank is currently active uInt16 myCurrentBank; @@ -149,6 +158,13 @@ class CartridgeFA2 : public Cartridge // The 256 bytes of RAM on the cartridge uInt8 myRAM[256]; + // An access has been made to load/save internal RAM + bool myRamRWFlag; + + // Full pathname of the file to use when emulating load/save + // of internal RAM to Harmony cart flash + string myFlashFile; + // Size of the ROM image uInt32 mySize; }; diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index b4b5a06f1..9c2e15298 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -693,7 +693,7 @@ Console* OSystem::openConsole(const string& romfile, string& md5, string cartmd5 = md5; type = props.get(Cartridge_Type); Cartridge* cart = - Cartridge::create(image, size, cartmd5, type, id, *mySettings); + Cartridge::create(image, size, cartmd5, type, id, *this, *mySettings); // It's possible that the cart created was from a piece of the image, // and that the md5 (and hence the cart) has changed