mirror of https://github.com/stella-emu/stella.git
More work on Chetiry bankswitch scheme. Preliminary version can
now load and play test ROMs, complete with emulation of timing delays due to slow accesses on real Harmony hardware. Still TODO is the tunes, DPC+ stuff, which is stubbed out at this point. Fixed bug in EFSC bankswitching; state files didn't contain extended RAM information. Cleaned up the Serializer API, resulting in slightly faster operation and smaller state files. Because of this, the state file format has changed for this release (old state files will no longer work). git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2487 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
f14d47f042
commit
01c9bc30c3
|
@ -44,6 +44,13 @@
|
||||||
their high-byte truncated, and system equates (TIA and I/O registers)
|
their high-byte truncated, and system equates (TIA and I/O registers)
|
||||||
are now properly marked as such.
|
are now properly marked as such.
|
||||||
|
|
||||||
|
* Fixed bug in EFSC state saving; the Superchip RAM wasn't actually
|
||||||
|
being loaded and saved to state files.
|
||||||
|
|
||||||
|
* Improved speed of loading and saving state files, as well as slightly
|
||||||
|
reducing their size. Because of this, old state files will not work
|
||||||
|
with this release.
|
||||||
|
|
||||||
* Replaced commandline argument 'uselauncher' with 'exitlauncher'. The
|
* Replaced commandline argument 'uselauncher' with 'exitlauncher'. The
|
||||||
new option specifies the behaviour of the ROM launcher when exiting
|
new option specifies the behaviour of the ROM launcher when exiting
|
||||||
a ROM (always exit to launcher, or only when the launcher was actually
|
a ROM (always exit to launcher, or only when the launcher was actually
|
||||||
|
@ -1948,7 +1955,7 @@
|
||||||
|
|
||||||
* A new Windows port has been created, with the GUI based on StellaX.
|
* A new Windows port has been created, with the GUI based on StellaX.
|
||||||
This is the first new release for Windows since Stella 1.2.
|
This is the first new release for Windows since Stella 1.2.
|
||||||
(software mode is not yet optimized; OpenGL mode works much better)
|
(software mode is not yet optimized; OpenGL mode works much better)
|
||||||
|
|
||||||
* A new Mac OSX port has been created by Mark Grebe. This is the first new
|
* A new Mac OSX port has been created by Mark Grebe. This is the first new
|
||||||
release for Mac OSX since Stella 1.2.
|
release for Mac OSX since Stella 1.2.
|
||||||
|
|
|
@ -397,12 +397,12 @@ bool SoundSDL::save(Serializer& out) const
|
||||||
reg6 = myTIASound.get(0x1a);
|
reg6 = myTIASound.get(0x1a);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.putByte((char)reg1);
|
out.putByte(reg1);
|
||||||
out.putByte((char)reg2);
|
out.putByte(reg2);
|
||||||
out.putByte((char)reg3);
|
out.putByte(reg3);
|
||||||
out.putByte((char)reg4);
|
out.putByte(reg4);
|
||||||
out.putByte((char)reg5);
|
out.putByte(reg5);
|
||||||
out.putByte((char)reg6);
|
out.putByte(reg6);
|
||||||
|
|
||||||
out.putInt(myLastRegisterSetCycle);
|
out.putInt(myLastRegisterSetCycle);
|
||||||
}
|
}
|
||||||
|
@ -425,12 +425,12 @@ bool SoundSDL::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt8 reg1 = (uInt8) in.getByte(),
|
uInt8 reg1 = in.getByte(),
|
||||||
reg2 = (uInt8) in.getByte(),
|
reg2 = in.getByte(),
|
||||||
reg3 = (uInt8) in.getByte(),
|
reg3 = in.getByte(),
|
||||||
reg4 = (uInt8) in.getByte(),
|
reg4 = in.getByte(),
|
||||||
reg5 = (uInt8) in.getByte(),
|
reg5 = in.getByte(),
|
||||||
reg6 = (uInt8) in.getByte();
|
reg6 = in.getByte();
|
||||||
|
|
||||||
myLastRegisterSetCycle = (Int32) in.getInt();
|
myLastRegisterSetCycle = (Int32) in.getInt();
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,7 @@ Cartridge* Cartridge::create(const uInt8* image, uInt32 size, string& md5,
|
||||||
else if(type == "CM")
|
else if(type == "CM")
|
||||||
cartridge = new CartridgeCM(image, size, settings);
|
cartridge = new CartridgeCM(image, size, settings);
|
||||||
else if(type == "CTY")
|
else if(type == "CTY")
|
||||||
cartridge = new CartridgeCTY(image, size, settings);
|
cartridge = new CartridgeCTY(image, size, osystem);
|
||||||
else if(type == "CV")
|
else if(type == "CV")
|
||||||
cartridge = new CartridgeCV(image, size, settings);
|
cartridge = new CartridgeCV(image, size, settings);
|
||||||
else if(type == "DPC")
|
else if(type == "DPC")
|
||||||
|
|
|
@ -198,7 +198,7 @@ bool Cartridge0840::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,7 @@ bool Cartridge0840::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16)in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,9 +58,9 @@ void Cartridge3E::reset()
|
||||||
// Initialize RAM
|
// Initialize RAM
|
||||||
if(mySettings.getBool("ramrandom"))
|
if(mySettings.getBool("ramrandom"))
|
||||||
for(uInt32 i = 0; i < 32768; ++i)
|
for(uInt32 i = 0; i < 32768; ++i)
|
||||||
myRam[i] = mySystem->randGenerator().next();
|
myRAM[i] = mySystem->randGenerator().next();
|
||||||
else
|
else
|
||||||
memset(myRam, 0, 32768);
|
memset(myRAM, 0, 32768);
|
||||||
|
|
||||||
// We'll map the startup bank into the first segment upon reset
|
// We'll map the startup bank into the first segment upon reset
|
||||||
bank(myStartBank);
|
bank(myStartBank);
|
||||||
|
@ -111,7 +111,7 @@ uInt8 Cartridge3E::peek(uInt16 address)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(address < 0x0400)
|
if(address < 0x0400)
|
||||||
return myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)];
|
return myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Reading from the write port triggers an unwanted write
|
// Reading from the write port triggers an unwanted write
|
||||||
|
@ -122,7 +122,7 @@ uInt8 Cartridge3E::peek(uInt16 address)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
triggerReadFromWritePort(peekAddress);
|
triggerReadFromWritePort(peekAddress);
|
||||||
return myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value;
|
return myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ bool Cartridge3E::bank(uInt16 bank)
|
||||||
// Map read-port RAM image into the system
|
// Map read-port RAM image into the system
|
||||||
for(address = 0x1000; address < 0x1400; address += (1 << shift))
|
for(address = 0x1000; address < 0x1400; address += (1 << shift))
|
||||||
{
|
{
|
||||||
access.directPeekBase = &myRam[offset + (address & 0x03FF)];
|
access.directPeekBase = &myRAM[offset + (address & 0x03FF)];
|
||||||
access.codeAccessBase = &myCodeAccessBase[mySize + offset + (address & 0x03FF)];
|
access.codeAccessBase = &myCodeAccessBase[mySize + offset + (address & 0x03FF)];
|
||||||
mySystem->setPageAccess(address >> shift, access);
|
mySystem->setPageAccess(address >> shift, access);
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ bool Cartridge3E::bank(uInt16 bank)
|
||||||
// Map write-port RAM image into the system
|
// Map write-port RAM image into the system
|
||||||
for(address = 0x1400; address < 0x1800; address += (1 << shift))
|
for(address = 0x1400; address < 0x1800; address += (1 << shift))
|
||||||
{
|
{
|
||||||
access.directPokeBase = &myRam[offset + (address & 0x03FF)];
|
access.directPokeBase = &myRAM[offset + (address & 0x03FF)];
|
||||||
access.codeAccessBase = &myCodeAccessBase[mySize + offset + (address & 0x03FF)];
|
access.codeAccessBase = &myCodeAccessBase[mySize + offset + (address & 0x03FF)];
|
||||||
mySystem->setPageAccess(address >> shift, access);
|
mySystem->setPageAccess(address >> shift, access);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ bool Cartridge3E::patch(uInt16 address, uInt8 value)
|
||||||
if(myCurrentBank < 256)
|
if(myCurrentBank < 256)
|
||||||
myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value;
|
myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value;
|
||||||
else
|
else
|
||||||
myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value;
|
myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
myImage[(address & 0x07FF) + mySize - 2048] = value;
|
myImage[(address & 0x07FF) + mySize - 2048] = value;
|
||||||
|
@ -274,12 +274,8 @@ bool Cartridge3E::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByteArray(myRAM, 32768);
|
||||||
// Output RAM
|
|
||||||
out.putInt(32768);
|
|
||||||
for(uInt32 addr = 0; addr < 32768; ++addr)
|
|
||||||
out.putByte((char)myRam[addr]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -298,12 +294,8 @@ bool Cartridge3E::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
in.getByteArray(myRAM, 32768);
|
||||||
// Input RAM
|
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 addr = 0; addr < limit; ++addr)
|
|
||||||
myRam[addr] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -174,7 +174,7 @@ class Cartridge3E : public Cartridge
|
||||||
uInt8* myImage;
|
uInt8* myImage;
|
||||||
|
|
||||||
// RAM contents. For now every ROM gets all 32K of potential RAM
|
// RAM contents. For now every ROM gets all 32K of potential RAM
|
||||||
uInt8 myRam[32 * 1024];
|
uInt8 myRAM[32 * 1024];
|
||||||
|
|
||||||
// Size of the ROM image
|
// Size of the ROM image
|
||||||
uInt32 mySize;
|
uInt32 mySize;
|
||||||
|
|
|
@ -192,7 +192,7 @@ bool Cartridge3F::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -211,7 +211,7 @@ bool Cartridge3F::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -452,14 +452,12 @@ bool Cartridge4A50::save(Serializer& out) const
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
|
||||||
// The 32K bytes of RAM
|
// The 32K bytes of RAM
|
||||||
out.putInt(32768);
|
out.putByteArray(myRAM, 32768);
|
||||||
for(uInt32 i = 0; i < 32768; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
|
|
||||||
// Index pointers
|
// Index pointers
|
||||||
out.putInt(mySliceLow);
|
out.putShort(mySliceLow);
|
||||||
out.putInt(mySliceMiddle);
|
out.putShort(mySliceMiddle);
|
||||||
out.putInt(mySliceHigh);
|
out.putShort(mySliceHigh);
|
||||||
|
|
||||||
// Whether index pointers are for ROM or RAM
|
// Whether index pointers are for ROM or RAM
|
||||||
out.putBool(myIsRomLow);
|
out.putBool(myIsRomLow);
|
||||||
|
@ -468,7 +466,7 @@ bool Cartridge4A50::save(Serializer& out) const
|
||||||
|
|
||||||
// Last address and data values
|
// Last address and data values
|
||||||
out.putByte(myLastData);
|
out.putByte(myLastData);
|
||||||
out.putInt(myLastAddress);
|
out.putShort(myLastAddress);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -487,14 +485,12 @@ bool Cartridge4A50::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
in.getByteArray(myRAM, 32768);
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// Index pointers
|
// Index pointers
|
||||||
mySliceLow = (uInt16) in.getInt();
|
mySliceLow = in.getShort();
|
||||||
mySliceMiddle = (uInt16) in.getInt();
|
mySliceMiddle = in.getShort();
|
||||||
mySliceHigh = (uInt16) in.getInt();
|
mySliceHigh = in.getShort();
|
||||||
|
|
||||||
// Whether index pointers are for ROM or RAM
|
// Whether index pointers are for ROM or RAM
|
||||||
myIsRomLow = in.getBool();
|
myIsRomLow = in.getBool();
|
||||||
|
@ -502,8 +498,8 @@ bool Cartridge4A50::load(Serializer& in)
|
||||||
myIsRomHigh = in.getBool();
|
myIsRomHigh = in.getBool();
|
||||||
|
|
||||||
// Last address and data values
|
// Last address and data values
|
||||||
myLastData = (uInt8) in.getByte();
|
myLastData = in.getByte();
|
||||||
myLastAddress = (uInt16) in.getInt();
|
myLastAddress = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -467,33 +467,23 @@ bool CartridgeAR::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uInt32 i;
|
|
||||||
|
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
|
||||||
// Indicates the offest within the image for the corresponding bank
|
// Indicates the offest within the image for the corresponding bank
|
||||||
out.putInt(2);
|
out.putIntArray(myImageOffset, 2);
|
||||||
for(i = 0; i < 2; ++i)
|
|
||||||
out.putInt(myImageOffset[i]);
|
|
||||||
|
|
||||||
// The 6K of RAM and 2K of ROM contained in the Supercharger
|
// The 6K of RAM and 2K of ROM contained in the Supercharger
|
||||||
out.putInt(8192);
|
out.putByteArray(myImage, 8192);
|
||||||
for(i = 0; i < 8192; ++i)
|
|
||||||
out.putByte((char)myImage[i]);
|
|
||||||
|
|
||||||
// The 256 byte header for the current 8448 byte load
|
// The 256 byte header for the current 8448 byte load
|
||||||
out.putInt(256);
|
out.putByteArray(myHeader, 256);
|
||||||
for(i = 0; i < 256; ++i)
|
|
||||||
out.putByte((char)myHeader[i]);
|
|
||||||
|
|
||||||
// All of the 8448 byte loads associated with the game
|
// All of the 8448 byte loads associated with the game
|
||||||
// Note that the size of this array is myNumberOfLoadImages * 8448
|
// Note that the size of this array is myNumberOfLoadImages * 8448
|
||||||
out.putInt(myNumberOfLoadImages * 8448);
|
out.putByteArray(myLoadImages, myNumberOfLoadImages * 8448);
|
||||||
for(i = 0; i < (uInt32) myNumberOfLoadImages * 8448; ++i)
|
|
||||||
out.putInt(myLoadImages[i]);
|
|
||||||
|
|
||||||
// Indicates how many 8448 loads there are
|
// Indicates how many 8448 loads there are
|
||||||
out.putByte((char)myNumberOfLoadImages);
|
out.putByte(myNumberOfLoadImages);
|
||||||
|
|
||||||
// Indicates if the RAM is write enabled
|
// Indicates if the RAM is write enabled
|
||||||
out.putBool(myWriteEnabled);
|
out.putBool(myWriteEnabled);
|
||||||
|
@ -505,7 +495,7 @@ bool CartridgeAR::save(Serializer& out) const
|
||||||
out.putInt(myPowerRomCycle);
|
out.putInt(myPowerRomCycle);
|
||||||
|
|
||||||
// Data hold register used for writing
|
// Data hold register used for writing
|
||||||
out.putByte((char)myDataHoldRegister);
|
out.putByte(myDataHoldRegister);
|
||||||
|
|
||||||
// Indicates number of distinct accesses when data hold register was set
|
// Indicates number of distinct accesses when data hold register was set
|
||||||
out.putInt(myNumberOfDistinctAccesses);
|
out.putInt(myNumberOfDistinctAccesses);
|
||||||
|
@ -530,31 +520,21 @@ bool CartridgeAR::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt32 i, limit;
|
|
||||||
|
|
||||||
// Indicates the offest within the image for the corresponding bank
|
// Indicates the offest within the image for the corresponding bank
|
||||||
limit = (uInt32) in.getInt();
|
in.getIntArray(myImageOffset, 2);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myImageOffset[i] = (uInt32) in.getInt();
|
|
||||||
|
|
||||||
// The 6K of RAM and 2K of ROM contained in the Supercharger
|
// The 6K of RAM and 2K of ROM contained in the Supercharger
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myImage, 8192);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myImage[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The 256 byte header for the current 8448 byte load
|
// The 256 byte header for the current 8448 byte load
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myHeader, 256);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myHeader[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// All of the 8448 byte loads associated with the game
|
// All of the 8448 byte loads associated with the game
|
||||||
// Note that the size of this array is myNumberOfLoadImages * 8448
|
// Note that the size of this array is myNumberOfLoadImages * 8448
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myLoadImages, myNumberOfLoadImages * 8448);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myLoadImages[i] = (uInt8) in.getInt();
|
|
||||||
|
|
||||||
// Indicates how many 8448 loads there are
|
// Indicates how many 8448 loads there are
|
||||||
myNumberOfLoadImages = (uInt8) in.getByte();
|
myNumberOfLoadImages = in.getByte();
|
||||||
|
|
||||||
// Indicates if the RAM is write enabled
|
// Indicates if the RAM is write enabled
|
||||||
myWriteEnabled = in.getBool();
|
myWriteEnabled = in.getBool();
|
||||||
|
@ -566,10 +546,10 @@ bool CartridgeAR::load(Serializer& in)
|
||||||
myPowerRomCycle = (Int32) in.getInt();
|
myPowerRomCycle = (Int32) in.getInt();
|
||||||
|
|
||||||
// Data hold register used for writing
|
// Data hold register used for writing
|
||||||
myDataHoldRegister = (uInt8) in.getByte();
|
myDataHoldRegister = in.getByte();
|
||||||
|
|
||||||
// Indicates number of distinct accesses when data hold register was set
|
// Indicates number of distinct accesses when data hold register was set
|
||||||
myNumberOfDistinctAccesses = (uInt32) in.getInt();
|
myNumberOfDistinctAccesses = in.getInt();
|
||||||
|
|
||||||
// Indicates if a write is pending or not
|
// Indicates if a write is pending or not
|
||||||
myWritePending = in.getBool();
|
myWritePending = in.getBool();
|
||||||
|
|
|
@ -202,15 +202,10 @@ bool CartridgeCM::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
out.putByte(myRamState);
|
out.putByte(myRamState);
|
||||||
out.putByte(myColumn);
|
out.putByte(myColumn);
|
||||||
|
out.putByteArray(myRAM, 2048);
|
||||||
// The 2048 bytes of RAM
|
|
||||||
out.putInt(2048);
|
|
||||||
for(uInt32 i = 0; i < 2048; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -229,14 +224,10 @@ bool CartridgeCM::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
myRamState = (uInt8) in.getByte();
|
myRamState = in.getByte();
|
||||||
myColumn = (uInt8) in.getByte();
|
myColumn = in.getByte();
|
||||||
|
in.getByteArray(myRAM, 2048);
|
||||||
// The 2048 bytes of RAM
|
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,13 +20,18 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "OSystem.hxx"
|
||||||
|
#include "Serializer.hxx"
|
||||||
#include "System.hxx"
|
#include "System.hxx"
|
||||||
#include "CartCTYTunes.hxx"
|
#include "CartCTYTunes.hxx"
|
||||||
#include "CartCTY.hxx"
|
#include "CartCTY.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeCTY::CartridgeCTY(const uInt8* image, uInt32 size, const Settings& settings)
|
CartridgeCTY::CartridgeCTY(const uInt8* image, uInt32 size, const OSystem& osystem)
|
||||||
: Cartridge(settings)
|
: Cartridge(osystem.settings()),
|
||||||
|
myOSystem(osystem),
|
||||||
|
myOperationType(0),
|
||||||
|
myRamAccessTimeout(0)
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
// Copy the ROM image into my buffer
|
||||||
memcpy(myImage, image, BSPF_min(32768u, size));
|
memcpy(myImage, image, BSPF_min(32768u, size));
|
||||||
|
@ -35,7 +40,7 @@ CartridgeCTY::CartridgeCTY(const uInt8* image, uInt32 size, const Settings& sett
|
||||||
// This cart contains 64 bytes extended RAM @ 0x1000
|
// This cart contains 64 bytes extended RAM @ 0x1000
|
||||||
registerRamArea(0x1000, 64, 0x40, 0x00);
|
registerRamArea(0x1000, 64, 0x40, 0x00);
|
||||||
|
|
||||||
// Remember startup bank
|
// Remember startup bank (not bank 0, since that's ARM code)
|
||||||
myStartBank = 1;
|
myStartBank = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,10 +54,12 @@ void CartridgeCTY::reset()
|
||||||
{
|
{
|
||||||
// Initialize RAM
|
// Initialize RAM
|
||||||
if(mySettings.getBool("ramrandom"))
|
if(mySettings.getBool("ramrandom"))
|
||||||
for(uInt32 i = 0; i < 256; ++i)
|
for(uInt32 i = 0; i < 64; ++i)
|
||||||
myScoreRAM[i] = mySystem->randGenerator().next();
|
myRAM[i] = mySystem->randGenerator().next();
|
||||||
else
|
else
|
||||||
memset(myScoreRAM, 0, 256);
|
memset(myRAM, 0, 64);
|
||||||
|
|
||||||
|
myRAM[0] = myRAM[1] = myRAM[2] = myRAM[3] = 0xFF;
|
||||||
|
|
||||||
// Upon reset we switch to the startup bank
|
// Upon reset we switch to the startup bank
|
||||||
bank(myStartBank);
|
bank(myStartBank);
|
||||||
|
@ -62,32 +69,16 @@ void CartridgeCTY::reset()
|
||||||
void CartridgeCTY::install(System& system)
|
void CartridgeCTY::install(System& system)
|
||||||
{
|
{
|
||||||
mySystem = &system;
|
mySystem = &system;
|
||||||
uInt16 shift = mySystem->pageShift();
|
|
||||||
uInt16 mask = mySystem->pageMask();
|
uInt16 mask = mySystem->pageMask();
|
||||||
|
uInt16 shift = mySystem->pageShift();
|
||||||
|
|
||||||
// Make sure the system we're being installed in has a page size that'll work
|
// Make sure the system we're being installed in has a page size that'll work
|
||||||
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
|
assert(((0x1000 & mask) == 0) && ((0x1080 & mask) == 0));
|
||||||
|
|
||||||
|
// Map all RAM accesses to call peek and poke
|
||||||
System::PageAccess access(0, 0, 0, this, System::PA_READ);
|
System::PageAccess access(0, 0, 0, this, System::PA_READ);
|
||||||
|
for(uInt32 i = 0x1000; i < 0x1080; i += (1 << shift))
|
||||||
// Set the page accessing method for the RAM writing pages
|
mySystem->setPageAccess(i >> shift, access);
|
||||||
access.type = System::PA_WRITE;
|
|
||||||
for(uInt32 j = 0x1000; j < 0x1080; j += (1 << shift))
|
|
||||||
{
|
|
||||||
access.directPokeBase = &myScoreRAM[j & 0x007F];
|
|
||||||
access.codeAccessBase = &myCodeAccessBase[j & 0x007F];
|
|
||||||
mySystem->setPageAccess(j >> shift, access);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the page accessing method for the RAM reading pages
|
|
||||||
access.directPokeBase = 0;
|
|
||||||
access.type = System::PA_READ;
|
|
||||||
for(uInt32 k = 0x1080; k < 0x1100; k += (1 << shift))
|
|
||||||
{
|
|
||||||
access.directPeekBase = &myScoreRAM[k & 0x007F];
|
|
||||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (k & 0x007F)];
|
|
||||||
mySystem->setPageAccess(k >> shift, access);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install pages for the startup bank
|
// Install pages for the startup bank
|
||||||
bank(myStartBank);
|
bank(myStartBank);
|
||||||
|
@ -98,12 +89,14 @@ uInt8 CartridgeCTY::peek(uInt16 address)
|
||||||
{
|
{
|
||||||
uInt16 peekAddress = address;
|
uInt16 peekAddress = address;
|
||||||
address &= 0x0FFF;
|
address &= 0x0FFF;
|
||||||
|
uInt8 peekValue = myImage[(myCurrentBank << 12) + address];
|
||||||
|
|
||||||
// Switch banks if necessary
|
// In debugger/bank-locked mode, we ignore all hotspots and in general
|
||||||
if((address >= 0x0FF4) && (address <= 0x0FFB))
|
// anything that can change the internal state of the cart
|
||||||
bank(address - 0x0FF4);
|
if(bankLocked())
|
||||||
|
return peekValue;
|
||||||
|
|
||||||
if(address < 0x0080) // Write port is at 0xF000 - 0xF080 (128 bytes)
|
if(address < 0x0040) // Write port is at $1000 - $103F (64 bytes)
|
||||||
{
|
{
|
||||||
// Reading from the write port triggers an unwanted write
|
// Reading from the write port triggers an unwanted write
|
||||||
uInt8 value = mySystem->getDataBusState(0xFF);
|
uInt8 value = mySystem->getDataBusState(0xFF);
|
||||||
|
@ -113,28 +106,102 @@ uInt8 CartridgeCTY::peek(uInt16 address)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
triggerReadFromWritePort(peekAddress);
|
triggerReadFromWritePort(peekAddress);
|
||||||
return myScoreRAM[address] = value;
|
return myRAM[address] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(address < 0x0080) // Read port is at $1040 - $107F (64 bytes)
|
||||||
// NOTE: This does not handle accessing RAM, however, this function
|
{
|
||||||
// should never be called for RAM because of the way page accessing
|
address -= 0x40;
|
||||||
// has been setup
|
switch(address) // FIXME for actual return values (0-3)
|
||||||
return myImage[(myCurrentBank << 12) + address];
|
{
|
||||||
|
case 0x00: // Error code after operation
|
||||||
|
return myRAM[0];
|
||||||
|
case 0x01: // Get next Random Number (8-bit LFSR)
|
||||||
|
cerr << "Get next Random Number (8-bit LFSR)\n";
|
||||||
|
return 0xFF;
|
||||||
|
case 0x02: // Get Tune position (low byte)
|
||||||
|
cerr << "Get Tune position (low byte)\n";
|
||||||
|
return 0x00;
|
||||||
|
case 0x03: // Get Tune position (high byte)
|
||||||
|
cerr << "Get Tune position (high byte)\n";
|
||||||
|
return 0x00;
|
||||||
|
default:
|
||||||
|
return myRAM[address];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Check hotspots
|
||||||
|
{
|
||||||
|
switch(address)
|
||||||
|
{
|
||||||
|
case 0x0FF4:
|
||||||
|
// Bank 0 is ARM code and not actually accessed
|
||||||
|
return ramReadWrite();
|
||||||
|
case 0x0FF5:
|
||||||
|
case 0x0FF6:
|
||||||
|
case 0x0FF7:
|
||||||
|
case 0x0FF8:
|
||||||
|
case 0x0FF9:
|
||||||
|
case 0x0FFA:
|
||||||
|
case 0x0FFB:
|
||||||
|
// Banks 1 through 7
|
||||||
|
bank(address - 0x0FF4);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return myImage[(myCurrentBank << 12) + address];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeCTY::poke(uInt16 address, uInt8)
|
bool CartridgeCTY::poke(uInt16 address, uInt8 value)
|
||||||
{
|
{
|
||||||
address &= 0x0FFF;
|
address &= 0x0FFF;
|
||||||
|
|
||||||
// Switch banks if necessary
|
//cerr << "POKE: address=" << HEX4 << address << ", value=" << HEX2 << value << endl;
|
||||||
if((address >= 0x0FF4) && (address <= 0x0FFB))
|
if(address < 0x0040) // Write port is at $1000 - $103F (64 bytes)
|
||||||
bank(address - 0x0FF4);
|
{
|
||||||
|
switch(address) // FIXME for functionality
|
||||||
// NOTE: This does not handle accessing RAM, however, this function
|
{
|
||||||
// should never be called for RAM because of the way page accessing
|
case 0x00: // Operation type for $1FF4
|
||||||
// has been setup
|
myOperationType = value;
|
||||||
|
break;
|
||||||
|
case 0x01: // Set Random seed value
|
||||||
|
cerr << "Set random seed value = " << HEX2 << (int)value << endl;
|
||||||
|
break;
|
||||||
|
case 0x02: // Reset fetcher to beginning of tune
|
||||||
|
cerr << "Reset fetcher to beginning of tune\n";
|
||||||
|
break;
|
||||||
|
case 0x03: // Advance fetcher to next tune position
|
||||||
|
cerr << "Advance fetcher to next tune position\n";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
myRAM[address] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Check hotspots
|
||||||
|
{
|
||||||
|
switch(address)
|
||||||
|
{
|
||||||
|
case 0x0FF4:
|
||||||
|
// Bank 0 is ARM code and not actually accessed
|
||||||
|
ramReadWrite();
|
||||||
|
break;
|
||||||
|
case 0x0FF5:
|
||||||
|
case 0x0FF6:
|
||||||
|
case 0x0FF7:
|
||||||
|
case 0x0FF8:
|
||||||
|
case 0x0FF9:
|
||||||
|
case 0x0FFA:
|
||||||
|
case 0x0FFB:
|
||||||
|
// Banks 1 through 7
|
||||||
|
bank(address - 0x0FF4);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +226,7 @@ bool CartridgeCTY::bank(uInt16 bank)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the page access methods for the current bank
|
// Setup the page access methods for the current bank
|
||||||
for(uInt32 address = 0x1100; address < (0x1FF4U & ~mask);
|
for(uInt32 address = 0x1080; address < (0x1FF4U & ~mask);
|
||||||
address += (1 << shift))
|
address += (1 << shift))
|
||||||
{
|
{
|
||||||
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
access.directPeekBase = &myImage[offset + (address & 0x0FFF)];
|
||||||
|
@ -186,12 +253,12 @@ bool CartridgeCTY::patch(uInt16 address, uInt8 value)
|
||||||
{
|
{
|
||||||
address &= 0x0FFF;
|
address &= 0x0FFF;
|
||||||
|
|
||||||
if(address < 0x0100)
|
if(address < 0x0080)
|
||||||
{
|
{
|
||||||
// Normally, a write to the read port won't do anything
|
// Normally, a write to the read port won't do anything
|
||||||
// However, the patch command is special in that ignores such
|
// However, the patch command is special in that ignores such
|
||||||
// cart restrictions
|
// cart restrictions
|
||||||
myScoreRAM[address & 0x007F] = value;
|
myRAM[address & 0x003F] = value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
myImage[(myCurrentBank << 12) + address] = value;
|
myImage[(myCurrentBank << 12) + address] = value;
|
||||||
|
@ -212,12 +279,9 @@ bool CartridgeCTY::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByte(myOperationType);
|
||||||
// The 256 bytes of RAM
|
out.putByteArray(myRAM, 64);
|
||||||
out.putInt(256);
|
|
||||||
for(uInt32 i = 0; i < 256; ++i)
|
|
||||||
out.putByte((char)myScoreRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -236,11 +300,9 @@ bool CartridgeCTY::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
myOperationType = in.getByte();
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
in.getByteArray(myRAM, 64);
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myScoreRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -253,3 +315,170 @@ bool CartridgeCTY::load(Serializer& in)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeCTY::setRomName(const string& name)
|
||||||
|
{
|
||||||
|
myEEPROMFile = myOSystem.eepromDir() + name + "_eeprom.dat";
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt8 CartridgeCTY::ramReadWrite()
|
||||||
|
{
|
||||||
|
/* The following algorithm implements accessing Harmony cart EEPROM
|
||||||
|
|
||||||
|
1. Wait for an access to hotspot location $1FF4 (return 1 in bit 6
|
||||||
|
while busy).
|
||||||
|
|
||||||
|
2. Determine operation from myOperationType.
|
||||||
|
|
||||||
|
3. Save or load relevant EEPROM memory to/from a file.
|
||||||
|
|
||||||
|
4. Set byte 0 of RAM+ memory to zero to indicate success (will
|
||||||
|
always happen in emulation).
|
||||||
|
|
||||||
|
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 s for read,
|
||||||
|
1 s for write).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(bankLocked()) return 0xff;
|
||||||
|
|
||||||
|
// First access sets the timer
|
||||||
|
if(myRamAccessTimeout == 0)
|
||||||
|
{
|
||||||
|
// Opcode and value in form of XXXXYYYY (from myOperationType), where:
|
||||||
|
// XXXX = index and YYYY = operation
|
||||||
|
uInt8 index = myOperationType >> 4;
|
||||||
|
switch(myOperationType & 0xf)
|
||||||
|
{
|
||||||
|
case 1: // Load tune (index = tune)
|
||||||
|
if(index < 7)
|
||||||
|
{
|
||||||
|
// Add 0.5 s delay for read
|
||||||
|
myRamAccessTimeout = myOSystem.getTicks() + 500000;
|
||||||
|
loadTune(index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // Load score table (index = table)
|
||||||
|
if(index < 4)
|
||||||
|
{
|
||||||
|
// Add 0.5 s delay for read
|
||||||
|
myRamAccessTimeout = myOSystem.getTicks() + 500000;
|
||||||
|
loadScore(index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: // Save score table (index = table)
|
||||||
|
if(index < 4)
|
||||||
|
{
|
||||||
|
// Add 1 s delay for write
|
||||||
|
myRamAccessTimeout = myOSystem.getTicks() + 1000000;
|
||||||
|
saveScore(index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4: // Wipe all score tables
|
||||||
|
// Add 1 s delay for write
|
||||||
|
myRamAccessTimeout = myOSystem.getTicks() + 1000000;
|
||||||
|
wipeAllScores();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Bit 6 is 1, busy
|
||||||
|
return myImage[(myCurrentBank << 12) + 0xFF4] | 0x40;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Have we reached the timeout value yet?
|
||||||
|
if(myOSystem.getTicks() >= myRamAccessTimeout)
|
||||||
|
{
|
||||||
|
myRamAccessTimeout = 0; // Turn off timer
|
||||||
|
myRAM[0] = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeCTY::loadTune(uInt8 index)
|
||||||
|
{
|
||||||
|
cerr << "load tune " << (int)index << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeCTY::loadScore(uInt8 index)
|
||||||
|
{
|
||||||
|
Serializer serializer(myEEPROMFile, true);
|
||||||
|
if(serializer.isValid())
|
||||||
|
{
|
||||||
|
uInt8 scoreRAM[256];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
serializer.getByteArray(scoreRAM, 256);
|
||||||
|
}
|
||||||
|
catch(const char* msg)
|
||||||
|
{
|
||||||
|
memset(scoreRAM, 0, 256);
|
||||||
|
}
|
||||||
|
// Grab 64B slice @ given index
|
||||||
|
memcpy(myRAM, scoreRAM + (index << 6), 64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeCTY::saveScore(uInt8 index)
|
||||||
|
{
|
||||||
|
Serializer serializer(myEEPROMFile);
|
||||||
|
if(serializer.isValid())
|
||||||
|
{
|
||||||
|
// Load score RAM
|
||||||
|
uInt8 scoreRAM[256];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
serializer.getByteArray(scoreRAM, 256);
|
||||||
|
}
|
||||||
|
catch(const char* msg)
|
||||||
|
{
|
||||||
|
memset(scoreRAM, 0, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add 64B RAM to score table @ given index
|
||||||
|
memcpy(scoreRAM + (index << 6), myRAM, 64);
|
||||||
|
|
||||||
|
// Save score RAM
|
||||||
|
serializer.reset();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
serializer.putByteArray(scoreRAM, 256);
|
||||||
|
}
|
||||||
|
catch(const char* msg)
|
||||||
|
{
|
||||||
|
// Maybe add logging here that save failed?
|
||||||
|
cerr << name() << ": ERROR saving score table " << (int)index << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeCTY::wipeAllScores()
|
||||||
|
{
|
||||||
|
Serializer serializer(myEEPROMFile);
|
||||||
|
if(serializer.isValid())
|
||||||
|
{
|
||||||
|
// Erase score RAM
|
||||||
|
uInt8 scoreRAM[256];
|
||||||
|
memset(scoreRAM, 0, 256);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
serializer.putByteArray(scoreRAM, 256);
|
||||||
|
}
|
||||||
|
catch(const char* msg)
|
||||||
|
{
|
||||||
|
// Maybe add logging here that save failed?
|
||||||
|
cerr << name() << ": ERROR wiping score tables" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ class CartridgeCTY : 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
|
||||||
*/
|
*/
|
||||||
CartridgeCTY(const uInt8* image, uInt32 size, const Settings& settings);
|
CartridgeCTY(const uInt8* image, uInt32 size, const OSystem& osystem);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destructor
|
Destructor
|
||||||
|
@ -119,6 +119,14 @@ class CartridgeCTY : public Cartridge
|
||||||
*/
|
*/
|
||||||
string name() const { return "CartridgeCTY"; }
|
string name() const { return "CartridgeCTY"; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
||||||
|
@ -137,18 +145,52 @@ class CartridgeCTY : public Cartridge
|
||||||
bool poke(uInt16 address, uInt8 value);
|
bool poke(uInt16 address, uInt8 value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
Either load or save internal RAM to Harmony EEPROM (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();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Actions initiated by accessing $FF4 hotspot.
|
||||||
|
*/
|
||||||
|
void loadTune(uInt8 index);
|
||||||
|
void loadScore(uInt8 index);
|
||||||
|
void saveScore(uInt8 index);
|
||||||
|
void wipeAllScores();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// OSsytem currently in use
|
||||||
|
const OSystem& myOSystem;
|
||||||
|
|
||||||
// Indicates which bank is currently active
|
// Indicates which bank is currently active
|
||||||
uInt16 myCurrentBank;
|
uInt16 myCurrentBank;
|
||||||
|
|
||||||
// The 32K ROM image of the cartridge
|
// The 32K ROM image of the cartridge
|
||||||
uInt8 myImage[32768];
|
uInt8 myImage[32768];
|
||||||
|
|
||||||
// The 256 bytes of score-table RAM
|
// The 64 bytes of RAM accessible at $1000 - $1080
|
||||||
uInt8 myScoreRAM[256];
|
uInt8 myRAM[64];
|
||||||
uInt8* myScorePtr;
|
|
||||||
|
// Operation type (written to $1000, used by hotspot $1FF4)
|
||||||
|
uInt8 myOperationType;
|
||||||
|
|
||||||
// The 8K Harmony RAM (used for tune data)
|
// The 8K Harmony RAM (used for tune data)
|
||||||
|
// Data is accessed from Harmony EEPROM
|
||||||
uInt8 myTuneRAM[8192];
|
uInt8 myTuneRAM[8192];
|
||||||
|
|
||||||
|
// 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
|
||||||
|
string myEEPROMFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -204,11 +204,7 @@ bool CartridgeCV::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
out.putByteArray(myRAM, 1024);
|
||||||
// Output RAM
|
|
||||||
out.putInt(1024);
|
|
||||||
for(uInt32 addr = 0; addr < 1024; ++addr)
|
|
||||||
out.putByte((char)myRAM[addr]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -227,10 +223,7 @@ bool CartridgeCV::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Input RAM
|
in.getByteArray(myRAM, 1024);
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 addr = 0; addr < limit; ++addr)
|
|
||||||
myRAM[addr] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -477,40 +477,29 @@ bool CartridgeDPC::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uInt32 i;
|
|
||||||
|
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
|
||||||
// Indicates which bank is currently active
|
// Indicates which bank is currently active
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
|
||||||
// The top registers for the data fetchers
|
// The top registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putByteArray(myTops, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putByte((char)myTops[i]);
|
|
||||||
|
|
||||||
// The bottom registers for the data fetchers
|
// The bottom registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putByteArray(myBottoms, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putByte((char)myBottoms[i]);
|
|
||||||
|
|
||||||
// The counter registers for the data fetchers
|
// The counter registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putShortArray(myCounters, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putInt(myCounters[i]);
|
|
||||||
|
|
||||||
// The flag registers for the data fetchers
|
// The flag registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putByteArray(myFlags, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putByte((char)myFlags[i]);
|
|
||||||
|
|
||||||
// The music mode flags for the data fetchers
|
// The music mode flags for the data fetchers
|
||||||
out.putInt(3);
|
for(int i = 0; i < 3; ++i)
|
||||||
for(i = 0; i < 3; ++i)
|
|
||||||
out.putBool(myMusicMode[i]);
|
out.putBool(myMusicMode[i]);
|
||||||
|
|
||||||
// The random number generator register
|
// The random number generator register
|
||||||
out.putByte((char)myRandomNumber);
|
out.putByte(myRandomNumber);
|
||||||
|
|
||||||
out.putInt(mySystemCycles);
|
out.putInt(mySystemCycles);
|
||||||
out.putInt((uInt32)(myFractionalClocks * 100000000.0));
|
out.putInt((uInt32)(myFractionalClocks * 100000000.0));
|
||||||
|
@ -532,41 +521,30 @@ bool CartridgeDPC::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt32 i, limit;
|
|
||||||
|
|
||||||
// Indicates which bank is currently active
|
// Indicates which bank is currently active
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
|
||||||
// The top registers for the data fetchers
|
// The top registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myTops, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myTops[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The bottom registers for the data fetchers
|
// The bottom registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myBottoms, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myBottoms[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The counter registers for the data fetchers
|
// The counter registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getShortArray(myCounters, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myCounters[i] = (uInt16) in.getInt();
|
|
||||||
|
|
||||||
// The flag registers for the data fetchers
|
// The flag registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myFlags, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myFlags[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The music mode flags for the data fetchers
|
// The music mode flags for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
for(int i = 0; i < 3; ++i)
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myMusicMode[i] = in.getBool();
|
myMusicMode[i] = in.getBool();
|
||||||
|
|
||||||
// The random number generator register
|
// The random number generator register
|
||||||
myRandomNumber = (uInt8) in.getByte();
|
myRandomNumber = in.getByte();
|
||||||
|
|
||||||
// Get system cycles and fractional clocks
|
// Get system cycles and fractional clocks
|
||||||
mySystemCycles = in.getInt();
|
mySystemCycles = (Int32)in.getInt();
|
||||||
myFractionalClocks = (double)in.getInt() / 100000000.0;
|
myFractionalClocks = (double)in.getInt() / 100000000.0;
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
|
|
|
@ -658,61 +658,41 @@ bool CartridgeDPCPlus::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uInt32 i;
|
|
||||||
|
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
|
||||||
// Indicates which bank is currently active
|
// Indicates which bank is currently active
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
|
||||||
// The top registers for the data fetchers
|
// The top registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putByteArray(myTops, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putByte((char)myTops[i]);
|
|
||||||
|
|
||||||
// The bottom registers for the data fetchers
|
// The bottom registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putByteArray(myBottoms, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putByte((char)myBottoms[i]);
|
|
||||||
|
|
||||||
// The counter registers for the data fetchers
|
// The counter registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putShortArray(myCounters, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putInt(myCounters[i]);
|
|
||||||
|
|
||||||
// The counter registers for the fractional data fetchers
|
// The counter registers for the fractional data fetchers
|
||||||
out.putInt(8);
|
out.putIntArray(myFractionalCounters, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putInt(myFractionalCounters[i]);
|
|
||||||
|
|
||||||
// The fractional registers for the data fetchers
|
// The fractional registers for the data fetchers
|
||||||
out.putInt(8);
|
out.putByteArray(myFractionalIncrements, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putByte((char)myFractionalIncrements[i]);
|
|
||||||
|
|
||||||
// The Fast Fetcher Enabled flag
|
// The Fast Fetcher Enabled flag
|
||||||
out.putBool(myFastFetch);
|
out.putBool(myFastFetch);
|
||||||
out.putBool(myLDAimmediate);
|
out.putBool(myLDAimmediate);
|
||||||
|
|
||||||
// Control Byte to update
|
// Control Byte to update
|
||||||
out.putInt(8);
|
out.putByteArray(myParameter, 8);
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
out.putByte((char)myParameter[i]);
|
|
||||||
|
|
||||||
// The music counters
|
// The music counters
|
||||||
out.putInt(3);
|
out.putIntArray(myMusicCounters, 3);
|
||||||
for(i = 0; i < 3; ++i)
|
|
||||||
out.putInt(myMusicCounters[i]);
|
|
||||||
|
|
||||||
// The music frequencies
|
// The music frequencies
|
||||||
out.putInt(3);
|
out.putIntArray(myMusicFrequencies, 3);
|
||||||
for(i = 0; i < 3; ++i)
|
|
||||||
out.putInt(myMusicFrequencies[i]);
|
|
||||||
|
|
||||||
// The music waveforms
|
// The music waveforms
|
||||||
out.putInt(3);
|
out.putShortArray(myMusicWaveforms, 3);
|
||||||
for(i = 0; i < 3; ++i)
|
|
||||||
out.putInt(myMusicWaveforms[i]);
|
|
||||||
|
|
||||||
// The random number generator register
|
// The random number generator register
|
||||||
out.putInt(myRandomNumber);
|
out.putInt(myRandomNumber);
|
||||||
|
@ -737,65 +717,45 @@ bool CartridgeDPCPlus::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt32 i, limit;
|
|
||||||
|
|
||||||
// Indicates which bank is currently active
|
// Indicates which bank is currently active
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
|
||||||
// The top registers for the data fetchers
|
// The top registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myTops, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myTops[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The bottom registers for the data fetchers
|
// The bottom registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myBottoms, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myBottoms[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The counter registers for the data fetchers
|
// The counter registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getShortArray(myCounters, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myCounters[i] = (uInt16) in.getInt();
|
|
||||||
|
|
||||||
// The counter registers for the fractional data fetchers
|
// The counter registers for the fractional data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getIntArray(myFractionalCounters, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myFractionalCounters[i] = (uInt32) in.getInt();
|
|
||||||
|
|
||||||
// The fractional registers for the data fetchers
|
// The fractional registers for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myFractionalIncrements, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myFractionalIncrements[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The Fast Fetcher Enabled flag
|
// The Fast Fetcher Enabled flag
|
||||||
myFastFetch = in.getBool();
|
myFastFetch = in.getBool();
|
||||||
myLDAimmediate = in.getBool();
|
myLDAimmediate = in.getBool();
|
||||||
|
|
||||||
// Control Byte to update
|
// Control Byte to update
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myParameter, 8);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myParameter[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The music mode counters for the data fetchers
|
// The music mode counters for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getIntArray(myMusicCounters, 3);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myMusicCounters[i] = (uInt32) in.getInt();
|
|
||||||
|
|
||||||
// The music mode frequency addends for the data fetchers
|
// The music mode frequency addends for the data fetchers
|
||||||
limit = (uInt32) in.getInt();
|
in.getIntArray(myMusicFrequencies, 3);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myMusicFrequencies[i] = (uInt32) in.getInt();
|
|
||||||
|
|
||||||
// The music waveforms
|
// The music waveforms
|
||||||
limit = (uInt32) in.getInt();
|
in.getShortArray(myMusicWaveforms, 3);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myMusicWaveforms[i] = (uInt16) in.getInt();
|
|
||||||
|
|
||||||
// The random number generator register
|
// The random number generator register
|
||||||
myRandomNumber = (uInt32) in.getInt();
|
myRandomNumber = in.getInt();
|
||||||
|
|
||||||
// Get system cycles and fractional clocks
|
// Get system cycles and fractional clocks
|
||||||
mySystemCycles = in.getInt();
|
mySystemCycles = (Int32)in.getInt();
|
||||||
myFractionalClocks = (double)in.getInt() / 100000000.0;
|
myFractionalClocks = (double)in.getInt() / 100000000.0;
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
|
|
|
@ -235,10 +235,7 @@ bool CartridgeE0::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
out.putShortArray(myCurrentSlice, 4);
|
||||||
out.putInt(4);
|
|
||||||
for(uInt32 i = 0; i < 4; ++i)
|
|
||||||
out.putInt(myCurrentSlice[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -257,9 +254,7 @@ bool CartridgeE0::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
in.getShortArray(myCurrentSlice, 4);
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myCurrentSlice[i] = (uInt16) in.getInt();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -167,7 +167,7 @@ bool CartridgeE7::poke(uInt16 address, uInt8)
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeE7::bankRAM(uInt16 bank)
|
void CartridgeE7::bankRAM(uInt16 bank)
|
||||||
{
|
{
|
||||||
if(bankLocked()) return;
|
if(bankLocked()) return;
|
||||||
|
|
||||||
// Remember what bank we're in
|
// Remember what bank we're in
|
||||||
|
@ -300,20 +300,10 @@ bool CartridgeE7::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uInt32 i;
|
|
||||||
|
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
out.putShortArray(myCurrentSlice, 2);
|
||||||
out.putInt(2);
|
out.putShort(myCurrentRAM);
|
||||||
for(i = 0; i < 2; ++i)
|
out.putByteArray(myRAM, 2048);
|
||||||
out.putInt(myCurrentSlice[i]);
|
|
||||||
|
|
||||||
out.putInt(myCurrentRAM);
|
|
||||||
|
|
||||||
// The 2048 bytes of RAM
|
|
||||||
out.putInt(2048);
|
|
||||||
for(i = 0; i < 2048; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -332,18 +322,9 @@ bool CartridgeE7::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uInt32 i, limit;
|
in.getShortArray(myCurrentSlice, 2);
|
||||||
|
myCurrentRAM = in.getShort();
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myRAM, 2048);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myCurrentSlice[i] = (uInt16) in.getInt();
|
|
||||||
|
|
||||||
myCurrentRAM = (uInt16) in.getInt();
|
|
||||||
|
|
||||||
// The 2048 bytes of RAM
|
|
||||||
limit = (uInt32) in.getInt();
|
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -146,7 +146,7 @@ bool CartridgeEF::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -165,7 +165,7 @@ bool CartridgeEF::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -208,7 +208,8 @@ bool CartridgeEFSC::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByteArray(myRAM, 128);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -227,7 +228,8 @@ bool CartridgeEFSC::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
in.getByteArray(myRAM, 128);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -160,7 +160,7 @@ bool CartridgeF0::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -179,7 +179,7 @@ bool CartridgeF0::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -151,7 +151,7 @@ bool CartridgeF4::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -170,7 +170,7 @@ bool CartridgeF4::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16)in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -211,12 +211,8 @@ bool CartridgeF4SC::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByteArray(myRAM, 128);
|
||||||
// The 128 bytes of RAM
|
|
||||||
out.putInt(128);
|
|
||||||
for(uInt32 i = 0; i < 128; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -235,11 +231,8 @@ bool CartridgeF4SC::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
in.getByteArray(myRAM, 128);
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -191,7 +191,7 @@ bool CartridgeF6::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -210,7 +210,7 @@ bool CartridgeF6::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -254,13 +254,8 @@ bool CartridgeF6SC::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByteArray(myRAM, 128);
|
||||||
// The 128 bytes of RAM
|
|
||||||
out.putInt(128);
|
|
||||||
for(uInt32 i = 0; i < 128; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -279,12 +274,8 @@ bool CartridgeF6SC::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
in.getByteArray(myRAM, 128);
|
||||||
// The 128 bytes of RAM
|
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,7 +178,7 @@ bool CartridgeF8::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -197,7 +197,7 @@ bool CartridgeF8::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -234,12 +234,8 @@ bool CartridgeF8SC::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByteArray(myRAM, 128);
|
||||||
// The 128 bytes of RAM
|
|
||||||
out.putInt(128);
|
|
||||||
for(uInt32 i = 0; i < 128; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -258,11 +254,8 @@ bool CartridgeF8SC::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
in.getByteArray(myRAM, 128);
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -244,12 +244,8 @@ bool CartridgeFA::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByteArray(myRAM, 256);
|
||||||
// The 256 bytes of RAM
|
|
||||||
out.putInt(256);
|
|
||||||
for(uInt32 i = 0; i < 256; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -268,11 +264,8 @@ bool CartridgeFA::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
in.getByteArray(myRAM, 256);
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -307,12 +307,8 @@ bool CartridgeFA2::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
|
out.putByteArray(myRAM, 256);
|
||||||
// The 256 bytes of RAM
|
|
||||||
out.putInt(256);
|
|
||||||
for(uInt32 i = 0; i < 256; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -331,11 +327,8 @@ bool CartridgeFA2::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16) in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
|
in.getByteArray(myRAM, 256);
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
|
||||||
for(uInt32 i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -391,8 +384,7 @@ uInt8 CartridgeFA2::ramReadWrite()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for(uInt32 i = 0; i < 256; ++i)
|
serializer.getByteArray(myRAM, 256);
|
||||||
myRAM[i] = (uInt8) serializer.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -404,8 +396,7 @@ uInt8 CartridgeFA2::ramReadWrite()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for(uInt32 i = 0; i < 256; ++i)
|
serializer.putByteArray(myRAM, 256);
|
||||||
serializer.putByte((char)myRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,8 +164,8 @@ bool CartridgeFE::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myLastAddress1);
|
out.putShort(myLastAddress1);
|
||||||
out.putInt(myLastAddress2);
|
out.putShort(myLastAddress2);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -184,8 +184,8 @@ bool CartridgeFE::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myLastAddress1 = (uInt16)in.getInt();
|
myLastAddress1 = in.getShort();
|
||||||
myLastAddress2 = (uInt16)in.getInt();
|
myLastAddress2 = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -249,18 +249,13 @@ bool CartridgeMC::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uInt32 i;
|
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
|
||||||
// The currentBlock array
|
// The currentBlock array
|
||||||
out.putInt(4);
|
out.putByteArray(myCurrentBlock, 4);
|
||||||
for(i = 0; i < 4; ++i)
|
|
||||||
out.putByte((char)myCurrentBlock[i]);
|
|
||||||
|
|
||||||
// The 32K of RAM
|
// The 32K of RAM
|
||||||
out.putInt(32 * 1024);
|
out.putByteArray(myRAM, 32 * 1024);
|
||||||
for(i = 0; i < 32 * 1024; ++i)
|
|
||||||
out.putByte((char)myRAM[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -276,20 +271,14 @@ bool CartridgeMC::load(Serializer& in)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uInt32 i, limit;
|
|
||||||
|
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// The currentBlock array
|
// The currentBlock array
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myCurrentBlock, 4);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myCurrentBlock[i] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
// The 32K of RAM
|
// The 32K of RAM
|
||||||
limit = (uInt32) in.getInt();
|
in.getByteArray(myRAM, 32 * 1024);
|
||||||
for(i = 0; i < limit; ++i)
|
|
||||||
myRAM[i] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,7 +178,7 @@ bool CartridgeSB::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -197,7 +197,7 @@ bool CartridgeSB::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16)in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,7 +186,7 @@ bool CartridgeUA::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -205,7 +205,7 @@ bool CartridgeUA::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16)in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -170,7 +170,7 @@ bool CartridgeX07::save(Serializer& out) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
out.putInt(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -189,7 +189,7 @@ bool CartridgeX07::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCurrentBank = (uInt16)in.getInt();
|
myCurrentBank = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -376,34 +376,34 @@ bool M6502::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
out.putString(CPU);
|
out.putString(CPU);
|
||||||
|
|
||||||
out.putByte((char)A); // Accumulator
|
out.putByte(A); // Accumulator
|
||||||
out.putByte((char)X); // X index register
|
out.putByte(X); // X index register
|
||||||
out.putByte((char)Y); // Y index register
|
out.putByte(Y); // Y index register
|
||||||
out.putByte((char)SP); // Stack Pointer
|
out.putByte(SP); // Stack Pointer
|
||||||
out.putByte((char)IR); // Instruction register
|
out.putByte(IR); // Instruction register
|
||||||
out.putInt(PC); // Program Counter
|
out.putShort(PC); // Program Counter
|
||||||
|
|
||||||
out.putBool(N); // N flag for processor status register
|
out.putBool(N); // N flag for processor status register
|
||||||
out.putBool(V); // V flag for processor status register
|
out.putBool(V); // V flag for processor status register
|
||||||
out.putBool(B); // B flag for processor status register
|
out.putBool(B); // B flag for processor status register
|
||||||
out.putBool(D); // D flag for processor status register
|
out.putBool(D); // D flag for processor status register
|
||||||
out.putBool(I); // I flag for processor status register
|
out.putBool(I); // I flag for processor status register
|
||||||
out.putBool(notZ); // Z flag complement for processor status register
|
out.putBool(notZ); // Z flag complement for processor status register
|
||||||
out.putBool(C); // C flag for processor status register
|
out.putBool(C); // C flag for processor status register
|
||||||
|
|
||||||
out.putByte((char)myExecutionStatus);
|
out.putByte(myExecutionStatus);
|
||||||
|
|
||||||
// Indicates the number of distinct memory accesses
|
// Indicates the number of distinct memory accesses
|
||||||
out.putInt(myNumberOfDistinctAccesses);
|
out.putInt(myNumberOfDistinctAccesses);
|
||||||
// Indicates the last address(es) which was accessed
|
// Indicates the last address(es) which was accessed
|
||||||
out.putInt(myLastAddress);
|
out.putShort(myLastAddress);
|
||||||
out.putInt(myLastPeekAddress);
|
out.putShort(myLastPeekAddress);
|
||||||
out.putInt(myLastPokeAddress);
|
out.putShort(myLastPokeAddress);
|
||||||
out.putInt(myLastSrcAddressS);
|
out.putShort(myLastSrcAddressS);
|
||||||
out.putInt(myLastSrcAddressA);
|
out.putShort(myLastSrcAddressA);
|
||||||
out.putInt(myLastSrcAddressX);
|
out.putShort(myLastSrcAddressX);
|
||||||
out.putInt(myLastSrcAddressY);
|
out.putShort(myLastSrcAddressY);
|
||||||
out.putInt(myDataAddressForPoke);
|
out.putShort(myDataAddressForPoke);
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -424,34 +424,34 @@ bool M6502::load(Serializer& in)
|
||||||
if(in.getString() != CPU)
|
if(in.getString() != CPU)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
A = (uInt8) in.getByte(); // Accumulator
|
A = in.getByte(); // Accumulator
|
||||||
X = (uInt8) in.getByte(); // X index register
|
X = in.getByte(); // X index register
|
||||||
Y = (uInt8) in.getByte(); // Y index register
|
Y = in.getByte(); // Y index register
|
||||||
SP = (uInt8) in.getByte(); // Stack Pointer
|
SP = in.getByte(); // Stack Pointer
|
||||||
IR = (uInt8) in.getByte(); // Instruction register
|
IR = in.getByte(); // Instruction register
|
||||||
PC = (uInt16) in.getInt(); // Program Counter
|
PC = in.getShort(); // Program Counter
|
||||||
|
|
||||||
N = in.getBool(); // N flag for processor status register
|
N = in.getBool(); // N flag for processor status register
|
||||||
V = in.getBool(); // V flag for processor status register
|
V = in.getBool(); // V flag for processor status register
|
||||||
B = in.getBool(); // B flag for processor status register
|
B = in.getBool(); // B flag for processor status register
|
||||||
D = in.getBool(); // D flag for processor status register
|
D = in.getBool(); // D flag for processor status register
|
||||||
I = in.getBool(); // I flag for processor status register
|
I = in.getBool(); // I flag for processor status register
|
||||||
notZ = in.getBool(); // Z flag complement for processor status register
|
notZ = in.getBool(); // Z flag complement for processor status register
|
||||||
C = in.getBool(); // C flag for processor status register
|
C = in.getBool(); // C flag for processor status register
|
||||||
|
|
||||||
myExecutionStatus = (uInt8) in.getByte();
|
myExecutionStatus = in.getByte();
|
||||||
|
|
||||||
// Indicates the number of distinct memory accesses
|
// Indicates the number of distinct memory accesses
|
||||||
myNumberOfDistinctAccesses = (uInt32) in.getInt();
|
myNumberOfDistinctAccesses = in.getInt();
|
||||||
// Indicates the last address(es) which was accessed
|
// Indicates the last address(es) which was accessed
|
||||||
myLastAddress = (uInt16) in.getInt();
|
myLastAddress = in.getShort();
|
||||||
myLastPeekAddress = (uInt16) in.getInt();
|
myLastPeekAddress = in.getShort();
|
||||||
myLastPokeAddress = (uInt16) in.getInt();
|
myLastPokeAddress = in.getShort();
|
||||||
myLastSrcAddressS = (uInt16) in.getInt();
|
myLastSrcAddressS = in.getShort();
|
||||||
myLastSrcAddressA = (uInt16) in.getInt();
|
myLastSrcAddressA = in.getShort();
|
||||||
myLastSrcAddressX = (uInt16) in.getInt();
|
myLastSrcAddressX = in.getShort();
|
||||||
myLastSrcAddressY = (uInt16) in.getInt();
|
myLastSrcAddressY = in.getShort();
|
||||||
myDataAddressForPoke = (uInt16) in.getInt();
|
myDataAddressForPoke = in.getShort();
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -301,9 +301,7 @@ bool M6532::save(Serializer& out) const
|
||||||
out.putString(name());
|
out.putString(name());
|
||||||
|
|
||||||
// Output the RAM
|
// Output the RAM
|
||||||
out.putInt(128);
|
out.putByteArray(myRAM, 128);
|
||||||
for(uInt32 t = 0; t < 128; ++t)
|
|
||||||
out.putByte((char)myRAM[t]);
|
|
||||||
|
|
||||||
out.putInt(myTimer);
|
out.putInt(myTimer);
|
||||||
out.putInt(myIntervalShift);
|
out.putInt(myIntervalShift);
|
||||||
|
@ -311,14 +309,11 @@ bool M6532::save(Serializer& out) const
|
||||||
out.putBool(myInterruptEnabled);
|
out.putBool(myInterruptEnabled);
|
||||||
out.putBool(myInterruptTriggered);
|
out.putBool(myInterruptTriggered);
|
||||||
|
|
||||||
out.putByte((char)myDDRA);
|
out.putByte(myDDRA);
|
||||||
out.putByte((char)myDDRB);
|
out.putByte(myDDRB);
|
||||||
out.putByte((char)myOutA);
|
out.putByte(myOutA);
|
||||||
out.putByte((char)myOutB);
|
out.putByte(myOutB);
|
||||||
out.putByte((char)myOutTimer[0]);
|
out.putByteArray(myOutTimer, 4);
|
||||||
out.putByte((char)myOutTimer[1]);
|
|
||||||
out.putByte((char)myOutTimer[2]);
|
|
||||||
out.putByte((char)myOutTimer[3]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -338,24 +333,19 @@ bool M6532::load(Serializer& in)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Input the RAM
|
// Input the RAM
|
||||||
uInt32 limit = (uInt32) in.getInt();
|
in.getByteArray(myRAM, 128);
|
||||||
for(uInt32 t = 0; t < limit; ++t)
|
|
||||||
myRAM[t] = (uInt8) in.getByte();
|
|
||||||
|
|
||||||
myTimer = (uInt32) in.getInt();
|
myTimer = in.getInt();
|
||||||
myIntervalShift = (uInt32) in.getInt();
|
myIntervalShift = in.getInt();
|
||||||
myCyclesWhenTimerSet = (uInt32) in.getInt();
|
myCyclesWhenTimerSet = in.getInt();
|
||||||
myInterruptEnabled = in.getBool();
|
myInterruptEnabled = in.getBool();
|
||||||
myInterruptTriggered = in.getBool();
|
myInterruptTriggered = in.getBool();
|
||||||
|
|
||||||
myDDRA = (uInt8) in.getByte();
|
myDDRA = in.getByte();
|
||||||
myDDRB = (uInt8) in.getByte();
|
myDDRB = in.getByte();
|
||||||
myOutA = (uInt8) in.getByte();
|
myOutA = in.getByte();
|
||||||
myOutB = (uInt8) in.getByte();
|
myOutB = in.getByte();
|
||||||
myOutTimer[0] = (uInt8) in.getByte();
|
in.getByteArray(myOutTimer, 4);
|
||||||
myOutTimer[1] = (uInt8) in.getByte();
|
|
||||||
myOutTimer[2] = (uInt8) in.getByte();
|
|
||||||
myOutTimer[3] = (uInt8) in.getByte();
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,7 @@ Serializer::Serializer(const string& filename, bool readonly)
|
||||||
if(str && str->is_open())
|
if(str && str->is_open())
|
||||||
{
|
{
|
||||||
myStream = str;
|
myStream = str;
|
||||||
|
myStream->exceptions( ios_base::failbit | ios_base::badbit | ios_base::eofbit );
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -59,6 +60,7 @@ Serializer::Serializer(const string& filename, bool readonly)
|
||||||
if(str && str->is_open())
|
if(str && str->is_open())
|
||||||
{
|
{
|
||||||
myStream = str;
|
myStream = str;
|
||||||
|
myStream->exceptions( ios_base::failbit | ios_base::badbit | ios_base::eofbit );
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -77,6 +79,7 @@ Serializer::Serializer(void)
|
||||||
// the stream before it is used for the first time
|
// the stream before it is used for the first time
|
||||||
if(myStream)
|
if(myStream)
|
||||||
{
|
{
|
||||||
|
myStream->exceptions( ios_base::failbit | ios_base::badbit | ios_base::eofbit );
|
||||||
putBool(true);
|
putBool(true);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
@ -104,16 +107,14 @@ bool Serializer::isValid(void)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Serializer::reset(void)
|
void Serializer::reset(void)
|
||||||
{
|
{
|
||||||
|
myStream->clear();
|
||||||
myStream->seekg(ios_base::beg);
|
myStream->seekg(ios_base::beg);
|
||||||
myStream->seekp(ios_base::beg);
|
myStream->seekp(ios_base::beg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
char Serializer::getByte(void)
|
uInt8 Serializer::getByte(void)
|
||||||
{
|
{
|
||||||
if(myStream->eof())
|
|
||||||
throw "Serializer::getByte() end of file";
|
|
||||||
|
|
||||||
char buf;
|
char buf;
|
||||||
myStream->read(&buf, 1);
|
myStream->read(&buf, 1);
|
||||||
|
|
||||||
|
@ -121,20 +122,41 @@ char Serializer::getByte(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int Serializer::getInt(void)
|
void Serializer::getByteArray(uInt8* array, uInt32 size)
|
||||||
{
|
{
|
||||||
if(myStream->eof())
|
myStream->read((char*)array, (streamsize)size);
|
||||||
throw "Serializer::getInt() end of file";
|
}
|
||||||
|
|
||||||
int val = 0;
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
unsigned char buf[4];
|
uInt16 Serializer::getShort(void)
|
||||||
myStream->read((char*)buf, 4);
|
{
|
||||||
for(int i = 0; i < 4; ++i)
|
uInt16 val = 0;
|
||||||
val += (int)(buf[i]) << (i<<3);
|
myStream->read((char*)&val, sizeof(uInt16));
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Serializer::getShortArray(uInt16* array, uInt32 size)
|
||||||
|
{
|
||||||
|
myStream->read((char*)array, sizeof(uInt16)*size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 Serializer::getInt(void)
|
||||||
|
{
|
||||||
|
uInt32 val = 0;
|
||||||
|
myStream->read((char*)&val, sizeof(uInt32));
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Serializer::getIntArray(uInt32* array, uInt32 size)
|
||||||
|
{
|
||||||
|
myStream->read((char*)array, sizeof(uInt32)*size);
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string Serializer::getString(void)
|
string Serializer::getString(void)
|
||||||
{
|
{
|
||||||
|
@ -143,44 +165,49 @@ string Serializer::getString(void)
|
||||||
str.resize((string::size_type)len);
|
str.resize((string::size_type)len);
|
||||||
myStream->read(&str[0], (streamsize)len);
|
myStream->read(&str[0], (streamsize)len);
|
||||||
|
|
||||||
if(myStream->bad())
|
|
||||||
throw "Serializer::getString() file read failed";
|
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool Serializer::getBool(void)
|
bool Serializer::getBool(void)
|
||||||
{
|
{
|
||||||
char b = getByte();
|
return getByte() == (char)TruePattern;
|
||||||
if(b == (char)TruePattern)
|
|
||||||
return true;
|
|
||||||
else if(b == (char)FalsePattern)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
throw "Serializer::getBool() data corruption";
|
|
||||||
|
|
||||||
return false; // to stop compiler from complaining
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Serializer::putByte(char value)
|
void Serializer::putByte(uInt8 value)
|
||||||
{
|
{
|
||||||
myStream->write(&value, 1);
|
myStream->write((char*)&value, 1);
|
||||||
if(myStream->bad())
|
|
||||||
throw "Serializer::putByte() file write failed";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Serializer::putInt(int value)
|
void Serializer::putByteArray(const uInt8* array, uInt32 size)
|
||||||
{
|
{
|
||||||
unsigned char buf[4];
|
myStream->write((char*)array, (streamsize)size);
|
||||||
for(int i = 0; i < 4; ++i)
|
}
|
||||||
buf[i] = (value >> (i<<3)) & 0xff;
|
|
||||||
|
|
||||||
myStream->write((char*)buf, 4);
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
if(myStream->bad())
|
void Serializer::putShort(uInt16 value)
|
||||||
throw "Serializer::putInt() file write failed";
|
{
|
||||||
|
myStream->write((char*)&value, sizeof(uInt16));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Serializer::putShortArray(const uInt16* array, uInt32 size)
|
||||||
|
{
|
||||||
|
myStream->write((char*)array, sizeof(uInt16)*size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Serializer::putInt(uInt32 value)
|
||||||
|
{
|
||||||
|
myStream->write((char*)&value, sizeof(uInt32));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Serializer::putIntArray(const uInt32* array, uInt32 size)
|
||||||
|
{
|
||||||
|
myStream->write((char*)array, sizeof(uInt32)*size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -28,11 +28,12 @@
|
||||||
read from/written to a binary stream in a system-independent way. The
|
read from/written to a binary stream in a system-independent way. The
|
||||||
stream can be either an actual file, or an in-memory structure.
|
stream can be either an actual file, or an in-memory structure.
|
||||||
|
|
||||||
Bytes are written as characters, integers are written as 4 characters
|
Bytes are written as characters, shorts as 2 characters (16-bits),
|
||||||
(32-bit), strings are written as characters prepended by the length of the
|
integers as 4 characters (32-bits), strings are written as characters
|
||||||
string, boolean values are written using a special character pattern.
|
prepended by the length of the string, boolean values are written using
|
||||||
|
a special character pattern.
|
||||||
|
|
||||||
All bytes and ints should be cast to their appropriate data type upon
|
All bytes, shorts and ints should be cast to their appropriate data type upon
|
||||||
method return.
|
method return.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
|
@ -73,18 +74,50 @@ class Serializer
|
||||||
void reset(void);
|
void reset(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reads a byte value (8-bit) from the current input stream.
|
Reads a byte value (unsigned 8-bit) from the current input stream.
|
||||||
|
|
||||||
@result The char value which has been read from the stream.
|
@result The byte value which has been read from the stream.
|
||||||
*/
|
*/
|
||||||
char getByte(void);
|
uInt8 getByte(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reads an int value (32-bit) from the current input stream.
|
Reads a byte array (unsigned 8-bit) from the current input stream.
|
||||||
|
|
||||||
|
@param array The location to store the bytes read
|
||||||
|
@param size The size of the array (number of bytes to read)
|
||||||
|
*/
|
||||||
|
void getByteArray(uInt8* array, uInt32 size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads a short value (unsigned 16-bit) from the current input stream.
|
||||||
|
|
||||||
|
@result The short value which has been read from the stream.
|
||||||
|
*/
|
||||||
|
uInt16 getShort(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads a short array (unsigned 16-bit) from the current input stream.
|
||||||
|
|
||||||
|
@param array The location to store the shorts read
|
||||||
|
@param size The size of the array (number of shorts to read)
|
||||||
|
*/
|
||||||
|
void getShortArray(uInt16* array, uInt32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads an int value (unsigned 32-bit) from the current input stream.
|
||||||
|
|
||||||
@result The int value which has been read from the stream.
|
@result The int value which has been read from the stream.
|
||||||
*/
|
*/
|
||||||
int getInt(void);
|
uInt32 getInt(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads an integer array (unsigned 32-bit) from the current input stream.
|
||||||
|
|
||||||
|
@param array The location to store the integers read
|
||||||
|
@param size The size of the array (number of integers to read)
|
||||||
|
*/
|
||||||
|
void getIntArray(uInt32* array, uInt32 size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reads a string from the current input stream.
|
Reads a string from the current input stream.
|
||||||
|
@ -101,18 +134,49 @@ class Serializer
|
||||||
bool getBool(void);
|
bool getBool(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Writes an byte value (8-bit) to the current output stream.
|
Writes an byte value (unsigned 8-bit) to the current output stream.
|
||||||
|
|
||||||
@param value The byte value to write to the output stream.
|
@param value The byte value to write to the output stream.
|
||||||
*/
|
*/
|
||||||
void putByte(char value);
|
void putByte(uInt8 value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Writes an int value (32-bit) to the current output stream.
|
Writes a byte array (unsigned 8-bit) to the current output stream.
|
||||||
|
|
||||||
|
@param array The bytes to write
|
||||||
|
@param size The size of the array (number of bytes to write)
|
||||||
|
*/
|
||||||
|
void putByteArray(const uInt8* array, uInt32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes a short value (unsigned 16-bit) to the current output stream.
|
||||||
|
|
||||||
|
@param value The short value to write to the output stream.
|
||||||
|
*/
|
||||||
|
void putShort(uInt16 value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes a short array (unsigned 16-bit) to the current output stream.
|
||||||
|
|
||||||
|
@param array The short to write
|
||||||
|
@param size The size of the array (number of shorts to write)
|
||||||
|
*/
|
||||||
|
void putShortArray(const uInt16* array, uInt32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes an int value (unsigned 32-bit) to the current output stream.
|
||||||
|
|
||||||
@param value The int value to write to the output stream.
|
@param value The int value to write to the output stream.
|
||||||
*/
|
*/
|
||||||
void putInt(int value);
|
void putInt(uInt32 value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes an integer array (unsigned 32-bit) to the current output stream.
|
||||||
|
|
||||||
|
@param array The integers to write
|
||||||
|
@param size The size of the array (number of integers to write)
|
||||||
|
*/
|
||||||
|
void putIntArray(const uInt32* array, uInt32 size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Writes a string to the current output stream.
|
Writes a string to the current output stream.
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include "StateManager.hxx"
|
#include "StateManager.hxx"
|
||||||
|
|
||||||
#define STATE_HEADER "03050500state"
|
#define STATE_HEADER "03070000state"
|
||||||
#define MOVIE_HEADER "03030000movie"
|
#define MOVIE_HEADER "03030000movie"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -113,7 +113,7 @@ bool Switches::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putByte((char)mySwitches);
|
out.putByte(mySwitches);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -128,7 +128,7 @@ bool Switches::load(Serializer& in)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mySwitches = (uInt8) in.getByte();
|
mySwitches = in.getByte();
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -338,8 +338,8 @@ bool System::load(Serializer& in)
|
||||||
if(in.getString() != name())
|
if(in.getString() != name())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
myCycles = (uInt32) in.getInt();
|
myCycles = in.getInt();
|
||||||
myDataBusState = (uInt8) in.getByte();
|
myDataBusState = in.getByte();
|
||||||
|
|
||||||
// Next, load state for the CPU
|
// Next, load state for the CPU
|
||||||
if(!myM6502->load(in))
|
if(!myM6502->load(in))
|
||||||
|
|
|
@ -280,58 +280,52 @@ bool TIA::save(Serializer& out) const
|
||||||
out.putInt(myScanlineCountForLastFrame);
|
out.putInt(myScanlineCountForLastFrame);
|
||||||
out.putInt(myVSYNCFinishClock);
|
out.putInt(myVSYNCFinishClock);
|
||||||
|
|
||||||
out.putByte((char)myEnabledObjects);
|
out.putByte(myEnabledObjects);
|
||||||
out.putByte((char)myDisabledObjects);
|
out.putByte(myDisabledObjects);
|
||||||
|
|
||||||
out.putByte((char)myVSYNC);
|
out.putByte(myVSYNC);
|
||||||
out.putByte((char)myVBLANK);
|
out.putByte(myVBLANK);
|
||||||
out.putByte((char)myNUSIZ0);
|
out.putByte(myNUSIZ0);
|
||||||
out.putByte((char)myNUSIZ1);
|
out.putByte(myNUSIZ1);
|
||||||
|
|
||||||
out.putInt(myColor[P0Color]);
|
out.putIntArray(myColor, 8);
|
||||||
out.putInt(myColor[P1Color]);
|
|
||||||
out.putInt(myColor[PFColor]);
|
|
||||||
out.putInt(myColor[BKColor]);
|
|
||||||
out.putInt(myColor[M0Color]);
|
|
||||||
out.putInt(myColor[M1Color]);
|
|
||||||
out.putInt(myColor[BLColor]);
|
|
||||||
|
|
||||||
out.putByte((char)myCTRLPF);
|
out.putByte(myCTRLPF);
|
||||||
out.putByte((char)myPlayfieldPriorityAndScore);
|
out.putByte(myPlayfieldPriorityAndScore);
|
||||||
out.putBool(myREFP0);
|
out.putBool(myREFP0);
|
||||||
out.putBool(myREFP1);
|
out.putBool(myREFP1);
|
||||||
out.putInt(myPF);
|
out.putInt(myPF);
|
||||||
out.putByte((char)myGRP0);
|
out.putByte(myGRP0);
|
||||||
out.putByte((char)myGRP1);
|
out.putByte(myGRP1);
|
||||||
out.putByte((char)myDGRP0);
|
out.putByte(myDGRP0);
|
||||||
out.putByte((char)myDGRP1);
|
out.putByte(myDGRP1);
|
||||||
out.putBool(myENAM0);
|
out.putBool(myENAM0);
|
||||||
out.putBool(myENAM1);
|
out.putBool(myENAM1);
|
||||||
out.putBool(myENABL);
|
out.putBool(myENABL);
|
||||||
out.putBool(myDENABL);
|
out.putBool(myDENABL);
|
||||||
out.putByte((char)myHMP0);
|
out.putByte(myHMP0);
|
||||||
out.putByte((char)myHMP1);
|
out.putByte(myHMP1);
|
||||||
out.putByte((char)myHMM0);
|
out.putByte(myHMM0);
|
||||||
out.putByte((char)myHMM1);
|
out.putByte(myHMM1);
|
||||||
out.putByte((char)myHMBL);
|
out.putByte(myHMBL);
|
||||||
out.putBool(myVDELP0);
|
out.putBool(myVDELP0);
|
||||||
out.putBool(myVDELP1);
|
out.putBool(myVDELP1);
|
||||||
out.putBool(myVDELBL);
|
out.putBool(myVDELBL);
|
||||||
out.putBool(myRESMP0);
|
out.putBool(myRESMP0);
|
||||||
out.putBool(myRESMP1);
|
out.putBool(myRESMP1);
|
||||||
out.putInt(myCollision);
|
out.putShort(myCollision);
|
||||||
out.putInt(myCollisionEnabledMask);
|
out.putInt(myCollisionEnabledMask);
|
||||||
out.putByte((char)myCurrentGRP0);
|
out.putByte(myCurrentGRP0);
|
||||||
out.putByte((char)myCurrentGRP1);
|
out.putByte(myCurrentGRP1);
|
||||||
|
|
||||||
out.putBool(myDumpEnabled);
|
out.putBool(myDumpEnabled);
|
||||||
out.putInt(myDumpDisabledCycle);
|
out.putInt(myDumpDisabledCycle);
|
||||||
|
|
||||||
out.putInt(myPOSP0);
|
out.putShort(myPOSP0);
|
||||||
out.putInt(myPOSP1);
|
out.putShort(myPOSP1);
|
||||||
out.putInt(myPOSM0);
|
out.putShort(myPOSM0);
|
||||||
out.putInt(myPOSM1);
|
out.putShort(myPOSM1);
|
||||||
out.putInt(myPOSBL);
|
out.putShort(myPOSBL);
|
||||||
|
|
||||||
out.putInt(myMotionClockP0);
|
out.putInt(myMotionClockP0);
|
||||||
out.putInt(myMotionClockP1);
|
out.putInt(myMotionClockP1);
|
||||||
|
@ -386,61 +380,55 @@ bool TIA::load(Serializer& in)
|
||||||
myClockStopDisplay = (Int32) in.getInt();
|
myClockStopDisplay = (Int32) in.getInt();
|
||||||
myClockAtLastUpdate = (Int32) in.getInt();
|
myClockAtLastUpdate = (Int32) in.getInt();
|
||||||
myClocksToEndOfScanLine = (Int32) in.getInt();
|
myClocksToEndOfScanLine = (Int32) in.getInt();
|
||||||
myScanlineCountForLastFrame = (uInt32) in.getInt();
|
myScanlineCountForLastFrame = in.getInt();
|
||||||
myVSYNCFinishClock = (Int32) in.getInt();
|
myVSYNCFinishClock = (Int32) in.getInt();
|
||||||
|
|
||||||
myEnabledObjects = (uInt8) in.getByte();
|
myEnabledObjects = in.getByte();
|
||||||
myDisabledObjects = (uInt8) in.getByte();
|
myDisabledObjects = in.getByte();
|
||||||
|
|
||||||
myVSYNC = (uInt8) in.getByte();
|
myVSYNC = in.getByte();
|
||||||
myVBLANK = (uInt8) in.getByte();
|
myVBLANK = in.getByte();
|
||||||
myNUSIZ0 = (uInt8) in.getByte();
|
myNUSIZ0 = in.getByte();
|
||||||
myNUSIZ1 = (uInt8) in.getByte();
|
myNUSIZ1 = in.getByte();
|
||||||
|
|
||||||
myColor[P0Color] = (uInt32) in.getInt();
|
in.getIntArray(myColor, 8);
|
||||||
myColor[P1Color] = (uInt32) in.getInt();
|
|
||||||
myColor[PFColor] = (uInt32) in.getInt();
|
|
||||||
myColor[BKColor] = (uInt32) in.getInt();
|
|
||||||
myColor[M0Color] = (uInt32) in.getInt();
|
|
||||||
myColor[M1Color] = (uInt32) in.getInt();
|
|
||||||
myColor[BLColor] = (uInt32) in.getInt();
|
|
||||||
|
|
||||||
myCTRLPF = (uInt8) in.getByte();
|
myCTRLPF = in.getByte();
|
||||||
myPlayfieldPriorityAndScore = (uInt8) in.getByte();
|
myPlayfieldPriorityAndScore = in.getByte();
|
||||||
myREFP0 = in.getBool();
|
myREFP0 = in.getBool();
|
||||||
myREFP1 = in.getBool();
|
myREFP1 = in.getBool();
|
||||||
myPF = (uInt32) in.getInt();
|
myPF = in.getInt();
|
||||||
myGRP0 = (uInt8) in.getByte();
|
myGRP0 = in.getByte();
|
||||||
myGRP1 = (uInt8) in.getByte();
|
myGRP1 = in.getByte();
|
||||||
myDGRP0 = (uInt8) in.getByte();
|
myDGRP0 = in.getByte();
|
||||||
myDGRP1 = (uInt8) in.getByte();
|
myDGRP1 = in.getByte();
|
||||||
myENAM0 = in.getBool();
|
myENAM0 = in.getBool();
|
||||||
myENAM1 = in.getBool();
|
myENAM1 = in.getBool();
|
||||||
myENABL = in.getBool();
|
myENABL = in.getBool();
|
||||||
myDENABL = in.getBool();
|
myDENABL = in.getBool();
|
||||||
myHMP0 = (uInt8) in.getByte();
|
myHMP0 = in.getByte();
|
||||||
myHMP1 = (uInt8) in.getByte();
|
myHMP1 = in.getByte();
|
||||||
myHMM0 = (uInt8) in.getByte();
|
myHMM0 = in.getByte();
|
||||||
myHMM1 = (uInt8) in.getByte();
|
myHMM1 = in.getByte();
|
||||||
myHMBL = (uInt8) in.getByte();
|
myHMBL = in.getByte();
|
||||||
myVDELP0 = in.getBool();
|
myVDELP0 = in.getBool();
|
||||||
myVDELP1 = in.getBool();
|
myVDELP1 = in.getBool();
|
||||||
myVDELBL = in.getBool();
|
myVDELBL = in.getBool();
|
||||||
myRESMP0 = in.getBool();
|
myRESMP0 = in.getBool();
|
||||||
myRESMP1 = in.getBool();
|
myRESMP1 = in.getBool();
|
||||||
myCollision = (uInt16) in.getInt();
|
myCollision = in.getShort();
|
||||||
myCollisionEnabledMask = in.getInt();
|
myCollisionEnabledMask = in.getInt();
|
||||||
myCurrentGRP0 = (uInt8) in.getByte();
|
myCurrentGRP0 = in.getByte();
|
||||||
myCurrentGRP1 = (uInt8) in.getByte();
|
myCurrentGRP1 = in.getByte();
|
||||||
|
|
||||||
myDumpEnabled = in.getBool();
|
myDumpEnabled = in.getBool();
|
||||||
myDumpDisabledCycle = (Int32) in.getInt();
|
myDumpDisabledCycle = (Int32) in.getInt();
|
||||||
|
|
||||||
myPOSP0 = (Int16) in.getInt();
|
myPOSP0 = (Int16) in.getShort();
|
||||||
myPOSP1 = (Int16) in.getInt();
|
myPOSP1 = (Int16) in.getShort();
|
||||||
myPOSM0 = (Int16) in.getInt();
|
myPOSM0 = (Int16) in.getShort();
|
||||||
myPOSM1 = (Int16) in.getInt();
|
myPOSM1 = (Int16) in.getShort();
|
||||||
myPOSBL = (Int16) in.getInt();
|
myPOSBL = (Int16) in.getShort();
|
||||||
|
|
||||||
myMotionClockP0 = (Int32) in.getInt();
|
myMotionClockP0 = (Int32) in.getInt();
|
||||||
myMotionClockP1 = (Int32) in.getInt();
|
myMotionClockP1 = (Int32) in.getInt();
|
||||||
|
@ -453,8 +441,8 @@ bool TIA::load(Serializer& in)
|
||||||
myStartM0 = (Int32) in.getInt();
|
myStartM0 = (Int32) in.getInt();
|
||||||
myStartM1 = (Int32) in.getInt();
|
myStartM1 = (Int32) in.getInt();
|
||||||
|
|
||||||
mySuppressP0 = (uInt8) in.getByte();
|
mySuppressP0 = in.getByte();
|
||||||
mySuppressP1 = (uInt8) in.getByte();
|
mySuppressP1 = in.getByte();
|
||||||
|
|
||||||
myHMP0mmr = in.getBool();
|
myHMP0mmr = in.getBool();
|
||||||
myHMP1mmr = in.getBool();
|
myHMP1mmr = in.getBool();
|
||||||
|
@ -492,9 +480,7 @@ bool TIA::saveDisplay(Serializer& out) const
|
||||||
{
|
{
|
||||||
out.putBool(myPartialFrameFlag);
|
out.putBool(myPartialFrameFlag);
|
||||||
out.putInt(myFramePointerClocks);
|
out.putInt(myFramePointerClocks);
|
||||||
|
out.putByteArray(myCurrentFrameBuffer, 160*320);
|
||||||
for(int i = 0; i < 160*320; ++i)
|
|
||||||
out.putByte(myCurrentFrameBuffer[i]);
|
|
||||||
}
|
}
|
||||||
catch(const char* msg)
|
catch(const char* msg)
|
||||||
{
|
{
|
||||||
|
@ -511,13 +497,13 @@ bool TIA::loadDisplay(Serializer& in)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
myPartialFrameFlag = in.getBool();
|
myPartialFrameFlag = in.getBool();
|
||||||
myFramePointerClocks = (uInt32) in.getInt();
|
myFramePointerClocks = in.getInt();
|
||||||
|
|
||||||
// Reset frame buffer pointer and data
|
// Reset frame buffer pointer and data
|
||||||
clearBuffers();
|
clearBuffers();
|
||||||
myFramePointer = myCurrentFrameBuffer;
|
myFramePointer = myCurrentFrameBuffer;
|
||||||
for(int i = 0; i < 160*320; ++i)
|
in.getByteArray(myCurrentFrameBuffer, 160*320);
|
||||||
myCurrentFrameBuffer[i] = myPreviousFrameBuffer[i] = (uInt8) in.getByte();
|
memcpy(myPreviousFrameBuffer, myCurrentFrameBuffer, 160*320);
|
||||||
|
|
||||||
// If we're in partial frame mode, make sure to re-create the screen
|
// If we're in partial frame mode, make sure to re-create the screen
|
||||||
// as it existed when the state was saved
|
// as it existed when the state was saved
|
||||||
|
|
Loading…
Reference in New Issue