Load/save from Harmony cart flash RAM is now supported for the FA2

bankswitch scheme (currently, only the 256 internal RAM is used).


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2439 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2012-04-12 23:23:12 +00:00
parent 186fa5c1be
commit 967fb73d2d
6 changed files with 111 additions and 9 deletions

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -20,12 +20,16 @@
#include <cassert>
#include <cstring>
#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;
}
}

View File

@ -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;
};

View File

@ -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