mirror of https://github.com/stella-emu/stella.git
Improvements to the FA2 Harmony flash load/save functionality:
- delays are now emulated (0.5 ms for reads, 101 ms for writes) - the flash file is now saved according to the ROM name - correctly return values with bit 6 set to zero or one, instead of just using 0x00 or 0xff git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2440 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
967fb73d2d
commit
1dbefe043d
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5,
|
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;
|
Cartridge* cartridge = 0;
|
||||||
string type = dtype;
|
string type = dtype;
|
||||||
|
@ -177,8 +177,7 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5,
|
||||||
else if(type == "FA" || type == "FASC")
|
else if(type == "FA" || type == "FASC")
|
||||||
cartridge = new CartridgeFA(image, size, settings);
|
cartridge = new CartridgeFA(image, size, settings);
|
||||||
else if(type == "FA2")
|
else if(type == "FA2")
|
||||||
cartridge = new CartridgeFA2(image, size, settings,
|
cartridge = new CartridgeFA2(image, size, osystem);
|
||||||
system.eepromDir() + "FA2_flash.dat");
|
|
||||||
else if(type == "FE")
|
else if(type == "FE")
|
||||||
cartridge = new CartridgeFE(image, size, settings);
|
cartridge = new CartridgeFE(image, size, settings);
|
||||||
else if(type == "MC")
|
else if(type == "MC")
|
||||||
|
|
|
@ -191,6 +191,14 @@ class Cartridge : public Device
|
||||||
*/
|
*/
|
||||||
virtual string name() const = 0;
|
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:
|
protected:
|
||||||
/**
|
/**
|
||||||
Add the given area to the RamArea list for this cart.
|
Add the given area to the RamArea list for this cart.
|
||||||
|
|
|
@ -20,16 +20,16 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "OSystem.hxx"
|
||||||
#include "Serializer.hxx"
|
#include "Serializer.hxx"
|
||||||
#include "System.hxx"
|
#include "System.hxx"
|
||||||
#include "CartFA2.hxx"
|
#include "CartFA2.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size,
|
CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, const OSystem& osystem)
|
||||||
const Settings& settings, const string& flashfile)
|
: Cartridge(osystem.settings()),
|
||||||
: Cartridge(settings),
|
myOSystem(osystem),
|
||||||
myRamRWFlag(false),
|
myRamAccessTimeout(0),
|
||||||
myFlashFile(flashfile),
|
|
||||||
mySize(size)
|
mySize(size)
|
||||||
{
|
{
|
||||||
// Allocate array for the ROM image
|
// Allocate array for the ROM image
|
||||||
|
@ -349,24 +349,41 @@ bool CartridgeFA2::load(Serializer& in)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeFA2::setRomName(const string& name)
|
||||||
|
{
|
||||||
|
myFlashFile = myOSystem.eepromDir() + name + "_flash.dat";
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt8 CartridgeFA2::ramReadWrite()
|
uInt8 CartridgeFA2::ramReadWrite()
|
||||||
{
|
{
|
||||||
/* The following algorithm implements accessing Harmony cart flash
|
/* 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
|
2. Read byte 256 of RAM+ memory to determine the operation requested
|
||||||
(1 = read, 2 = write).
|
(1 = read, 2 = write).
|
||||||
|
|
||||||
3. Save or load the entire 256 bytes of RAM+ memory to a file.
|
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);
|
Serializer serializer(myFlashFile);
|
||||||
if(serializer.isValid())
|
if(serializer.isValid())
|
||||||
{
|
{
|
||||||
|
@ -381,6 +398,7 @@ uInt8 CartridgeFA2::ramReadWrite()
|
||||||
{
|
{
|
||||||
memset(myRAM, 0, 256);
|
memset(myRAM, 0, 256);
|
||||||
}
|
}
|
||||||
|
myRamAccessTimeout += 500; // Add 0.5 ms delay for read
|
||||||
}
|
}
|
||||||
else if(myRAM[255] == 2) // write
|
else if(myRAM[255] == 2) // write
|
||||||
{
|
{
|
||||||
|
@ -391,15 +409,27 @@ uInt8 CartridgeFA2::ramReadWrite()
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
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
|
else
|
||||||
{
|
{
|
||||||
myRamRWFlag = false;
|
// Have we reached the timeout value yet?
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,9 @@ class System;
|
||||||
This is an extended version of the CBS RAM Plus bankswitching scheme
|
This is an extended version of the CBS RAM Plus bankswitching scheme
|
||||||
supported by the Harmony cartridge.
|
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
|
@author Chris D. Walton
|
||||||
@version $Id$
|
@version $Id$
|
||||||
|
@ -42,11 +44,9 @@ class CartridgeFA2 : public Cartridge
|
||||||
|
|
||||||
@param image Pointer to the ROM image
|
@param image Pointer to the ROM image
|
||||||
@param size The size of the ROM image
|
@param size The size of the ROM image
|
||||||
@param settings A reference to the various settings (read-only)
|
@param osystem A reference to the OSystem currently in use
|
||||||
@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 OSystem& osystem);
|
||||||
const string& flashfile);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destructor
|
Destructor
|
||||||
|
@ -124,6 +124,14 @@ class CartridgeFA2 : public Cartridge
|
||||||
*/
|
*/
|
||||||
string name() const { return "CartridgeFA2"; }
|
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:
|
public:
|
||||||
/**
|
/**
|
||||||
Get the byte at the specified address.
|
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
|
Either load or save internal RAM to Harmony flash (represented by
|
||||||
a file in emulation).
|
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();
|
uInt8 ramReadWrite();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// OSsytem currently in use
|
||||||
|
const OSystem& myOSystem;
|
||||||
|
|
||||||
// Indicates which bank is currently active
|
// Indicates which bank is currently active
|
||||||
uInt16 myCurrentBank;
|
uInt16 myCurrentBank;
|
||||||
|
|
||||||
|
@ -158,8 +172,11 @@ class CartridgeFA2 : public Cartridge
|
||||||
// The 256 bytes of RAM on the cartridge
|
// The 256 bytes of RAM on the cartridge
|
||||||
uInt8 myRAM[256];
|
uInt8 myRAM[256];
|
||||||
|
|
||||||
// An access has been made to load/save internal RAM
|
// The time after which the first request of a load/save operation
|
||||||
bool myRamRWFlag;
|
// 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
|
// Full pathname of the file to use when emulating load/save
|
||||||
// of internal RAM to Harmony cart flash
|
// of internal RAM to Harmony cart flash
|
||||||
|
|
|
@ -214,6 +214,8 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props)
|
||||||
myConsoleInfo.Control0 = myControllers[0]->about();
|
myConsoleInfo.Control0 = myControllers[0]->about();
|
||||||
myConsoleInfo.Control1 = myControllers[1]->about();
|
myConsoleInfo.Control1 = myControllers[1]->about();
|
||||||
myConsoleInfo.BankSwitch = cart->about();
|
myConsoleInfo.BankSwitch = cart->about();
|
||||||
|
|
||||||
|
myCart->setRomName(myConsoleInfo.CartName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
Loading…
Reference in New Issue