diff --git a/src/emucore/Cart.cxx b/src/emucore/Cart.cxx index 954a39348..91a652930 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, const OSystem& system, Settings& settings) + string& dtype, string& id, const OSystem& osystem, Settings& settings) { Cartridge* cartridge = 0; string type = dtype; @@ -177,8 +177,7 @@ 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, - system.eepromDir() + "FA2_flash.dat"); + cartridge = new CartridgeFA2(image, size, osystem); 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 4e3dbc199..15a352434 100644 --- a/src/emucore/Cart.hxx +++ b/src/emucore/Cart.hxx @@ -191,6 +191,14 @@ class Cartridge : public Device */ virtual string name() const = 0; + /** + Informs the cartridge about the name of the ROM file used when + creating this cart. + + @param name The properties file name of the ROM + */ + virtual void setRomName(const string& name) { } + protected: /** Add the given area to the RamArea list for this cart. diff --git a/src/emucore/CartFA2.cxx b/src/emucore/CartFA2.cxx index bbc9a2342..194ea8949 100644 --- a/src/emucore/CartFA2.cxx +++ b/src/emucore/CartFA2.cxx @@ -20,16 +20,16 @@ #include #include +#include "OSystem.hxx" #include "Serializer.hxx" #include "System.hxx" #include "CartFA2.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, - const Settings& settings, const string& flashfile) - : Cartridge(settings), - myRamRWFlag(false), - myFlashFile(flashfile), +CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, const OSystem& osystem) + : Cartridge(osystem.settings()), + myOSystem(osystem), + myRamAccessTimeout(0), mySize(size) { // Allocate array for the ROM image @@ -349,24 +349,41 @@ bool CartridgeFA2::load(Serializer& in) return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeFA2::setRomName(const string& name) +{ + myFlashFile = myOSystem.eepromDir() + name + "_flash.dat"; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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). + 1. Wait for an access to hotspot location $1FF4 (return 1 in bit 6 + while busy). 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. + 4. Set byte 256 of RAM+ memory to zero to indicate success (will + always happen in emulation). - 5. Return 0 on the next access to $1FF4. + 5. Return 0 (in bit 6) on the next access to $1FF4, if enough time has + passed to complete the operation on a real system (0.5 ms for read, + 101 ms for write). */ - if(!myRamRWFlag) + + // First access sets the timer + if(myRamAccessTimeout == 0) { + // Remember when the first access was made + myRamAccessTimeout = myOSystem.getTicks(); + + // We go ahead and do the access now, and only return when a sufficient + // amount of time has passed Serializer serializer(myFlashFile); if(serializer.isValid()) { @@ -381,6 +398,7 @@ uInt8 CartridgeFA2::ramReadWrite() { memset(myRAM, 0, 256); } + myRamAccessTimeout += 500; // Add 0.5 ms delay for read } else if(myRAM[255] == 2) // write { @@ -391,15 +409,27 @@ uInt8 CartridgeFA2::ramReadWrite() } catch(const char* msg) { - // Maybe add logging here? + // Maybe add logging here that save failed? } + myRamAccessTimeout += 101000; // Add 101 ms delay for write } } - return 1; + // Bit 6 is 1, busy + return myImage[(myCurrentBank << 12) + 0xFF4] | 0x40; } else { - myRamRWFlag = false; - return 0; + // Have we reached the timeout value yet? + if(myOSystem.getTicks() >= myRamAccessTimeout) + { + myRamAccessTimeout = 0; // Turn off timer + myRAM[255] = 0; // Successful operation + + // Bit 6 is 0, ready/success + return myImage[(myCurrentBank << 12) + 0xFF4] & ~0x40; + } + else + // Bit 6 is 1, busy + return myImage[(myCurrentBank << 12) + 0xFF4] | 0x40; } } diff --git a/src/emucore/CartFA2.hxx b/src/emucore/CartFA2.hxx index 8c987deed..f812e13fb 100644 --- a/src/emucore/CartFA2.hxx +++ b/src/emucore/CartFA2.hxx @@ -29,7 +29,9 @@ class System; This is an extended version of the CBS RAM Plus bankswitching scheme supported by the Harmony cartridge. - There are six (or seven) 4K banks and 256 bytes of RAM. + There are six (or seven) 4K banks and 256 bytes of RAM. The 256 bytes + of RAM can be loaded/saved to Harmony cart flash, which is emulated by + storing in a file. @author Chris D. Walton @version $Id$ @@ -42,11 +44,9 @@ 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 + @param osystem A reference to the OSystem currently in use */ - CartridgeFA2(const uInt8* image, uInt32 size, const Settings& settings, - const string& flashfile); + CartridgeFA2(const uInt8* image, uInt32 size, const OSystem& osystem); /** Destructor @@ -124,6 +124,14 @@ class CartridgeFA2 : public Cartridge */ string name() const { return "CartridgeFA2"; } + /** + Informs the cartridge about the name of the ROM file used when + creating this cart. + + @param name The properties file name of the ROM + */ + void setRomName(const string& name); + public: /** Get the byte at the specified address. @@ -145,10 +153,16 @@ class CartridgeFA2 : public Cartridge /** Either load or save internal RAM to Harmony flash (represented by a file in emulation). + + @return The value at $FF4 with bit 6 set or cleared (depending on + whether the RAM access was busy or successful) */ uInt8 ramReadWrite(); private: + // OSsytem currently in use + const OSystem& myOSystem; + // Indicates which bank is currently active uInt16 myCurrentBank; @@ -158,8 +172,11 @@ 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; + // The time after which the first request of a load/save operation + // will actually be completed + // Due to flash RAM constraints, a read/write isn't instantaneous, + // so we need to emulate the delay as well + uInt64 myRamAccessTimeout; // Full pathname of the file to use when emulating load/save // of internal RAM to Harmony cart flash diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 924445e28..9c2a50ded 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -214,6 +214,8 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props) myConsoleInfo.Control0 = myControllers[0]->about(); myConsoleInfo.Control1 = myControllers[1]->about(); myConsoleInfo.BankSwitch = cart->about(); + + myCart->setRomName(myConsoleInfo.CartName); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -