C64: Apply savestate info to cartridge subsystem.

This commit is contained in:
Anthony Konzel 2016-03-01 13:50:07 -06:00
parent 472616c4f7
commit 1e2c9e45f0
9 changed files with 330 additions and 276 deletions

View File

@ -1,268 +1,276 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
public abstract partial class CartridgeDevice
{
// ---------------------------------
public static CartridgeDevice Load(byte[] crtFile)
{
var mem = new MemoryStream(crtFile);
var reader = new BinaryReader(mem);
if (new string(reader.ReadChars(16)) != "C64 CARTRIDGE ")
{
return null;
}
var chipAddress = new List<int>();
var chipBank = new List<int>();
var chipData = new List<int[]>();
var chipType = new List<int>();
var headerLength = ReadCRTInt(reader);
var version = ReadCRTShort(reader);
var mapper = ReadCRTShort(reader);
var exrom = reader.ReadByte() != 0;
var game = reader.ReadByte() != 0;
// reserved
reader.ReadBytes(6);
// cartridge name
reader.ReadBytes(0x20);
// skip extra header bytes
if (headerLength > 0x40)
{
reader.ReadBytes(headerLength - 0x40);
}
// read chips
while (reader.PeekChar() >= 0)
{
if (new string(reader.ReadChars(4)) != "CHIP")
{
break;
}
var chipLength = ReadCRTInt(reader);
chipType.Add(ReadCRTShort(reader));
chipBank.Add(ReadCRTShort(reader));
chipAddress.Add(ReadCRTShort(reader));
var chipDataLength = ReadCRTShort(reader);
chipData.Add(reader.ReadBytes(chipDataLength).Select(x => (int)x).ToArray());
chipLength -= chipDataLength + 0x10;
if (chipLength > 0)
reader.ReadBytes(chipLength);
}
if (chipData.Count <= 0)
{
return null;
}
CartridgeDevice result;
switch (mapper)
{
case 0x0000:
result = new Mapper0000(chipAddress, chipBank, chipData, game, exrom);
break;
case 0x0005:
result = new Mapper0005(chipAddress, chipBank, chipData);
break;
case 0x000B:
result = new Mapper000B(chipAddress, chipBank, chipData);
break;
case 0x000F:
result = new Mapper000F(chipAddress, chipBank, chipData);
break;
case 0x0011:
result = new Mapper0011(chipAddress, chipBank, chipData);
break;
case 0x0012:
result = new Mapper0012(chipAddress, chipBank, chipData);
break;
case 0x0013:
result = new Mapper0013(chipAddress, chipBank, chipData);
break;
case 0x0020:
result = new Mapper0020(chipAddress, chipBank, chipData);
break;
default:
throw new Exception("This cartridge file uses an unrecognized mapper: " + mapper);
}
result.HardReset();
return result;
}
private static int ReadCRTShort(BinaryReader reader)
{
return (reader.ReadByte() << 8) |
reader.ReadByte();
}
private static int ReadCRTInt(BinaryReader reader)
{
return (reader.ReadByte() << 24) |
(reader.ReadByte() << 16) |
(reader.ReadByte() << 8) |
reader.ReadByte();
}
// ---------------------------------
protected bool pinExRom;
protected bool pinGame;
protected bool pinIRQ;
protected bool pinNMI;
protected bool pinReset;
protected bool validCartridge;
public virtual void ExecutePhase1()
{
}
public virtual void ExecutePhase2()
{
}
public bool ExRom
{
get
{
return pinExRom;
}
}
public bool Game
{
get
{
return pinGame;
}
}
public virtual void HardReset()
{
pinIRQ = true;
pinNMI = true;
pinReset = true;
}
public bool IRQ
{
get
{
return pinIRQ;
}
}
public bool NMI
{
get
{
return pinNMI;
}
}
public virtual int Peek8000(int addr)
{
return 0xFF;
}
public virtual int PeekA000(int addr)
{
return 0xFF;
}
public virtual int PeekDE00(int addr)
{
return 0xFF;
}
public virtual int PeekDF00(int addr)
{
return 0xFF;
}
public virtual void Poke8000(int addr, int val)
{
}
public virtual void PokeA000(int addr, int val)
{
}
public virtual void PokeDE00(int addr, int val)
{
}
public virtual void PokeDF00(int addr, int val)
{
}
public virtual int Read8000(int addr)
{
return 0xFF;
}
public virtual int ReadA000(int addr)
{
return 0xFF;
}
public virtual int ReadDE00(int addr)
{
return 0xFF;
}
public virtual int ReadDF00(int addr)
{
return 0xFF;
}
public bool Reset
{
get
{
return pinReset;
}
}
public virtual void SyncState(Serializer ser)
{
SaveState.SyncObject(ser, this);
}
public bool Valid
{
get
{
return validCartridge;
}
}
public virtual void Write8000(int addr, int val)
{
}
public virtual void WriteA000(int addr, int val)
{
}
public virtual void WriteDE00(int addr, int val)
{
}
public virtual void WriteDF00(int addr, int val)
{
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
public abstract partial class CartridgeDevice
{
public static CartridgeDevice Load(byte[] crtFile)
{
var mem = new MemoryStream(crtFile);
var reader = new BinaryReader(mem);
if (new string(reader.ReadChars(16)) != "C64 CARTRIDGE ")
{
return null;
}
var chipAddress = new List<int>();
var chipBank = new List<int>();
var chipData = new List<int[]>();
var chipType = new List<int>();
var headerLength = ReadCRTInt(reader);
var version = ReadCRTShort(reader);
var mapper = ReadCRTShort(reader);
var exrom = reader.ReadByte() != 0;
var game = reader.ReadByte() != 0;
// reserved
reader.ReadBytes(6);
// cartridge name
reader.ReadBytes(0x20);
// skip extra header bytes
if (headerLength > 0x40)
{
reader.ReadBytes(headerLength - 0x40);
}
// read chips
while (reader.PeekChar() >= 0)
{
if (new string(reader.ReadChars(4)) != "CHIP")
{
break;
}
var chipLength = ReadCRTInt(reader);
chipType.Add(ReadCRTShort(reader));
chipBank.Add(ReadCRTShort(reader));
chipAddress.Add(ReadCRTShort(reader));
var chipDataLength = ReadCRTShort(reader);
chipData.Add(reader.ReadBytes(chipDataLength).Select(x => (int)x).ToArray());
chipLength -= chipDataLength + 0x10;
if (chipLength > 0)
reader.ReadBytes(chipLength);
}
if (chipData.Count <= 0)
{
return null;
}
CartridgeDevice result;
switch (mapper)
{
case 0x0000:
result = new Mapper0000(chipAddress, chipData, game, exrom);
break;
case 0x0005:
result = new Mapper0005(chipAddress, chipBank, chipData);
break;
case 0x000B:
result = new Mapper000B(chipAddress, chipData);
break;
case 0x000F:
result = new Mapper000F(chipAddress, chipBank, chipData);
break;
case 0x0011:
result = new Mapper0011(chipAddress, chipBank, chipData);
break;
case 0x0012:
result = new Mapper0012(chipAddress, chipBank, chipData);
break;
case 0x0013:
result = new Mapper0013(chipAddress, chipBank, chipData);
break;
case 0x0020:
result = new Mapper0020(chipAddress, chipBank, chipData);
break;
default:
throw new Exception("This cartridge file uses an unrecognized mapper: " + mapper);
}
result.HardReset();
return result;
}
private static int ReadCRTShort(BinaryReader reader)
{
return (reader.ReadByte() << 8) |
reader.ReadByte();
}
private static int ReadCRTInt(BinaryReader reader)
{
return (reader.ReadByte() << 24) |
(reader.ReadByte() << 16) |
(reader.ReadByte() << 8) |
reader.ReadByte();
}
[SaveState.SaveWithName("ExRom")]
protected bool pinExRom;
[SaveState.SaveWithName("Game")]
protected bool pinGame;
[SaveState.SaveWithName("IRQ")]
protected bool pinIRQ;
[SaveState.SaveWithName("NMI")]
protected bool pinNMI;
[SaveState.SaveWithName("Reset")]
protected bool pinReset;
[SaveState.DoNotSave]
protected bool validCartridge;
public virtual void ExecutePhase1()
{
}
public virtual void ExecutePhase2()
{
}
[SaveState.DoNotSave]
public bool ExRom
{
get
{
return pinExRom;
}
}
[SaveState.DoNotSave]
public bool Game
{
get
{
return pinGame;
}
}
public virtual void HardReset()
{
pinIRQ = true;
pinNMI = true;
pinReset = true;
}
[SaveState.DoNotSave]
public bool IRQ
{
get
{
return pinIRQ;
}
}
[SaveState.DoNotSave]
public bool NMI
{
get
{
return pinNMI;
}
}
public virtual int Peek8000(int addr)
{
return 0xFF;
}
public virtual int PeekA000(int addr)
{
return 0xFF;
}
public virtual int PeekDE00(int addr)
{
return 0xFF;
}
public virtual int PeekDF00(int addr)
{
return 0xFF;
}
public virtual void Poke8000(int addr, int val)
{
}
public virtual void PokeA000(int addr, int val)
{
}
public virtual void PokeDE00(int addr, int val)
{
}
public virtual void PokeDF00(int addr, int val)
{
}
public virtual int Read8000(int addr)
{
return 0xFF;
}
public virtual int ReadA000(int addr)
{
return 0xFF;
}
public virtual int ReadDE00(int addr)
{
return 0xFF;
}
public virtual int ReadDF00(int addr)
{
return 0xFF;
}
[SaveState.DoNotSave]
public bool Reset
{
get
{
return pinReset;
}
}
public virtual void SyncState(Serializer ser)
{
SaveState.SyncObject(ser, this);
}
[SaveState.DoNotSave]
public bool Valid
{
get
{
return validCartridge;
}
}
public virtual void Write8000(int addr, int val)
{
}
public virtual void WriteA000(int addr, int val)
{
}
public virtual void WriteDE00(int addr, int val)
{
}
public virtual void WriteDF00(int addr, int val)
{
}
}
}

View File

@ -8,15 +8,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
private sealed class Mapper0000 : CartridgeDevice
{
[SaveState.DoNotSave]
private readonly int[] _romA;
[SaveState.SaveWithName("RomMaskA")]
private readonly int _romAMask;
[SaveState.DoNotSave]
private readonly int[] _romB;
[SaveState.SaveWithName("RomMaskB")]
private readonly int _romBMask;
// standard cartridge mapper (Commodore)
// note that this format also covers Ultimax carts
public Mapper0000(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData, bool game, bool exrom)
public Mapper0000(IList<int> newAddresses, IList<int[]> newData, bool game, bool exrom)
{
pinGame = game;
pinExRom = exrom;

View File

@ -9,12 +9,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
private sealed class Mapper0005 : CartridgeDevice
{
[SaveState.DoNotSave]
private readonly int[][] _banksA; //8000
[SaveState.DoNotSave]
private readonly int[][] _banksB = new int[0][]; //A000
[SaveState.SaveWithName("BankMask")]
private readonly int _bankMask;
[SaveState.SaveWithName("BankNumber")]
private int _bankNumber;
[SaveState.DoNotSave]
private int[] _currentBankA;
[SaveState.DoNotSave]
private int[] _currentBankB;
[SaveState.DoNotSave]
private readonly int[] _dummyBank;
public Mapper0005(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)

View File

@ -14,9 +14,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
private sealed class Mapper000B : CartridgeDevice
{
[SaveState.DoNotSave]
private readonly int[] _rom = new int[0x4000];
public Mapper000B(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
public Mapper000B(IList<int> newAddresses, IList<int[]> newData)
{
validCartridge = false;

View File

@ -16,9 +16,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
private class Mapper000F : CartridgeDevice
{
[SaveState.DoNotSave]
private readonly int[][] _banks; //8000
[SaveState.SaveWithName("BankMask")]
private readonly int _bankMask;
[SaveState.SaveWithName("BankNumber")]
private int _bankNumber;
[SaveState.SaveWithName("CurrentBank")]
private int[] _currentBank;
public Mapper000F(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)

View File

@ -8,9 +8,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
private sealed class Mapper0012 : CartridgeDevice
{
[SaveState.DoNotSave]
private readonly int[] _bankMain;
[SaveState.DoNotSave]
private readonly int[][] _bankHigh;
[SaveState.SaveWithName("BankHighSelected")]
private int[] _bankHighSelected;
[SaveState.SaveWithName("BankIndex")]
private int _bankIndex;
// Zaxxon and Super Zaxxon cartridges

View File

@ -16,10 +16,15 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
private sealed class Mapper0013 : CartridgeDevice
{
[SaveState.DoNotSave]
private readonly int[][] _banks; //8000
[SaveState.SaveWithName("BankMask")]
private readonly int _bankMask;
[SaveState.SaveWithName("BankNumber")]
private int _bankNumber;
[SaveState.DoNotSave]
private int[] _currentBank;
[SaveState.SaveWithName("ROMEnable")]
private bool _romEnable;
public Mapper0013(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)

View File

@ -26,15 +26,29 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
private sealed class Mapper0020 : CartridgeDevice
{
[SaveState.SaveWithName("BankOffset")]
private int _bankOffset = 63 << 13;
private readonly int[] _banksA = new int[64 << 13]; //8000
private readonly int[] _banksB = new int[64 << 13]; //A000
[SaveState.DoNotSave]
private int[] _banksA = new int[64 << 13]; //8000
[SaveState.DoNotSave]
private int[] _banksB = new int[64 << 13]; //A000
[SaveState.DoNotSave]
private readonly int[] _originalMediaA; //8000
[SaveState.DoNotSave]
private readonly int[] _originalMediaB; //A000
[SaveState.SaveWithName("BoardLed")]
private bool _boardLed;
[SaveState.SaveWithName("Jumper")]
private bool _jumper = false;
[SaveState.SaveWithName("StateBits")]
private int _stateBits;
[SaveState.SaveWithName("RAM")]
private readonly int[] _ram = new int[256];
[SaveState.SaveWithName("CommandLatch55")]
private bool _commandLatch55;
[SaveState.SaveWithName("CommandLatchAA")]
private bool _commandLatchAa;
[SaveState.SaveWithName("InternalROMState")]
private int _internalRomState;
public Mapper0020(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
@ -75,6 +89,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
_commandLatch55 = false;
_commandLatchAa = false;
_internalRomState = 0;
// back up original media
_originalMediaA = _banksA.Select(d => d).ToArray();
_originalMediaB = _banksB.Select(d => d).ToArray();
}
private void BankSet(int index)
@ -265,6 +283,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
_ram[addr] = val & 0xFF;
}
public override void SyncState(Serializer ser)
{
SaveState.SyncDeltaBytes("MediaStateA", ser, _originalMediaA, ref _banksA);
SaveState.SyncDeltaBytes("MediaStateB", ser, _originalMediaB, ref _banksB);
base.SyncState(ser);
}
}
}
}

View File

@ -19,10 +19,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
{
public string Name { get; set; }
public SaveWithName()
{
}
public SaveWithName(string name)
{
Name = name;