Merge pull request #588 from TASVideos/c64-delta-savestates
C64 delta savestates
This commit is contained in:
commit
ab74a9274b
|
@ -2,23 +2,23 @@
|
||||||
{
|
{
|
||||||
public sealed partial class Motherboard
|
public sealed partial class Motherboard
|
||||||
{
|
{
|
||||||
private readonly int[] _joystickPressed = new int[10];
|
private readonly bool[] _joystickPressed = new bool[10];
|
||||||
private readonly int[] _keyboardPressed = new int[64];
|
private readonly bool[] _keyboardPressed = new bool[64];
|
||||||
|
|
||||||
private static readonly string[,] JoystickMatrix = {
|
private static readonly string[][] JoystickMatrix = {
|
||||||
{"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Button"},
|
new[] {"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Button"},
|
||||||
{"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button"}
|
new[] {"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Button"}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly string[,] KeyboardMatrix = {
|
private static readonly string[][] KeyboardMatrix = {
|
||||||
{ "Key Insert/Delete", "Key Return", "Key Cursor Left/Right", "Key F7", "Key F1", "Key F3", "Key F5", "Key Cursor Up/Down" },
|
new[] { "Key Insert/Delete", "Key Return", "Key Cursor Left/Right", "Key F7", "Key F1", "Key F3", "Key F5", "Key Cursor Up/Down" },
|
||||||
{ "Key 3", "Key W", "Key A", "Key 4", "Key Z", "Key S", "Key E", "Key Left Shift" },
|
new[] { "Key 3", "Key W", "Key A", "Key 4", "Key Z", "Key S", "Key E", "Key Left Shift" },
|
||||||
{ "Key 5", "Key R", "Key D", "Key 6", "Key C", "Key F", "Key T", "Key X" },
|
new[] { "Key 5", "Key R", "Key D", "Key 6", "Key C", "Key F", "Key T", "Key X" },
|
||||||
{ "Key 7", "Key Y", "Key G", "Key 8", "Key B", "Key H", "Key U", "Key V" },
|
new[] { "Key 7", "Key Y", "Key G", "Key 8", "Key B", "Key H", "Key U", "Key V" },
|
||||||
{ "Key 9", "Key I", "Key J", "Key 0", "Key M", "Key K", "Key O", "Key N" },
|
new[] { "Key 9", "Key I", "Key J", "Key 0", "Key M", "Key K", "Key O", "Key N" },
|
||||||
{ "Key Plus", "Key P", "Key L", "Key Minus", "Key Period", "Key Colon", "Key At", "Key Comma" },
|
new[] { "Key Plus", "Key P", "Key L", "Key Minus", "Key Period", "Key Colon", "Key At", "Key Comma" },
|
||||||
{ "Key Pound", "Key Asterisk", "Key Semicolon", "Key Clear/Home", "Key Right Shift", "Key Equal", "Key Up Arrow", "Key Slash" },
|
new[] { "Key Pound", "Key Asterisk", "Key Semicolon", "Key Clear/Home", "Key Right Shift", "Key Equal", "Key Up Arrow", "Key Slash" },
|
||||||
{ "Key 1", "Key Left Arrow", "Key Control", "Key 2", "Key Space", "Key Commodore", "Key Q", "Key Run/Stop" }
|
new[] { "Key 1", "Key Left Arrow", "Key Control", "Key 2", "Key Space", "Key Commodore", "Key Q", "Key Run/Stop" }
|
||||||
};
|
};
|
||||||
|
|
||||||
[SaveState.DoNotSave] int _pollIndex;
|
[SaveState.DoNotSave] int _pollIndex;
|
||||||
|
@ -33,9 +33,10 @@
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
_joystickPressed[_pollIndex++] = Controller[JoystickMatrix[j, i]] ? -1 : 0;
|
_joystickPressed[_pollIndex] = Controller[JoystickMatrix[j][i]];
|
||||||
|
_pollIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan keyboard
|
// scan keyboard
|
||||||
_pollIndex = 0;
|
_pollIndex = 0;
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
{
|
{
|
||||||
for (var j = 0; j < 8; j++)
|
for (var j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
_keyboardPressed[_pollIndex++] = Controller[KeyboardMatrix[i, j]] ? -1 : 0;
|
_keyboardPressed[_pollIndex++] = Controller[KeyboardMatrix[i][j]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,22 +102,22 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
{
|
{
|
||||||
case C64.VicType.Ntsc:
|
case C64.VicType.Ntsc:
|
||||||
Vic = Chip6567R8.Create(borderType);
|
Vic = Chip6567R8.Create(borderType);
|
||||||
Cia0 = Chip6526.Create(C64.CiaType.Ntsc, _keyboardPressed, _joystickPressed);
|
Cia0 = Chip6526.Create(C64.CiaType.Ntsc, Input_ReadKeyboard, Input_ReadJoysticks);
|
||||||
Cia1 = Chip6526.Create(C64.CiaType.Ntsc, Cia1_ReadPortA);
|
Cia1 = Chip6526.Create(C64.CiaType.Ntsc, Cia1_ReadPortA);
|
||||||
break;
|
break;
|
||||||
case C64.VicType.Pal:
|
case C64.VicType.Pal:
|
||||||
Vic = Chip6569.Create(borderType);
|
Vic = Chip6569.Create(borderType);
|
||||||
Cia0 = Chip6526.Create(C64.CiaType.Pal, _keyboardPressed, _joystickPressed);
|
Cia0 = Chip6526.Create(C64.CiaType.Pal, Input_ReadKeyboard, Input_ReadJoysticks);
|
||||||
Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA);
|
Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA);
|
||||||
break;
|
break;
|
||||||
case C64.VicType.NtscOld:
|
case C64.VicType.NtscOld:
|
||||||
Vic = Chip6567R56A.Create(borderType);
|
Vic = Chip6567R56A.Create(borderType);
|
||||||
Cia0 = Chip6526.Create(C64.CiaType.NtscRevA, _keyboardPressed, _joystickPressed);
|
Cia0 = Chip6526.Create(C64.CiaType.NtscRevA, Input_ReadKeyboard, Input_ReadJoysticks);
|
||||||
Cia1 = Chip6526.Create(C64.CiaType.NtscRevA, Cia1_ReadPortA);
|
Cia1 = Chip6526.Create(C64.CiaType.NtscRevA, Cia1_ReadPortA);
|
||||||
break;
|
break;
|
||||||
case C64.VicType.Drean:
|
case C64.VicType.Drean:
|
||||||
Vic = Chip6572.Create(borderType);
|
Vic = Chip6572.Create(borderType);
|
||||||
Cia0 = Chip6526.Create(C64.CiaType.Pal, _keyboardPressed, _joystickPressed);
|
Cia0 = Chip6526.Create(C64.CiaType.Pal, Input_ReadKeyboard, Input_ReadJoysticks);
|
||||||
Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA);
|
Cia1 = Chip6526.Create(C64.CiaType.Pal, Cia1_ReadPortA);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
return !_restorePressed && Cia1.ReadIrq() && CartPort.ReadNmi();
|
return !_restorePressed && Cia1.ReadIrq() && CartPort.ReadNmi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool[] Input_ReadJoysticks()
|
||||||
|
{
|
||||||
|
return _joystickPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool[] Input_ReadKeyboard()
|
||||||
|
{
|
||||||
|
return _keyboardPressed;
|
||||||
|
}
|
||||||
|
|
||||||
private bool Pla_ReadCharen()
|
private bool Pla_ReadCharen()
|
||||||
{
|
{
|
||||||
return (Cpu.PortData & 0x04) != 0;
|
return (Cpu.PortData & 0x04) != 0;
|
||||||
|
|
|
@ -1,268 +1,276 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
public abstract partial class CartridgeDevice
|
public abstract partial class CartridgeDevice
|
||||||
{
|
{
|
||||||
// ---------------------------------
|
public static CartridgeDevice Load(byte[] crtFile)
|
||||||
|
{
|
||||||
public static CartridgeDevice Load(byte[] crtFile)
|
var mem = new MemoryStream(crtFile);
|
||||||
{
|
var reader = new BinaryReader(mem);
|
||||||
var mem = new MemoryStream(crtFile);
|
|
||||||
var reader = new BinaryReader(mem);
|
if (new string(reader.ReadChars(16)) != "C64 CARTRIDGE ")
|
||||||
|
{
|
||||||
if (new string(reader.ReadChars(16)) != "C64 CARTRIDGE ")
|
return null;
|
||||||
{
|
}
|
||||||
return null;
|
|
||||||
}
|
var chipAddress = new List<int>();
|
||||||
|
var chipBank = new List<int>();
|
||||||
var chipAddress = new List<int>();
|
var chipData = new List<int[]>();
|
||||||
var chipBank = new List<int>();
|
var chipType = new List<int>();
|
||||||
var chipData = new List<int[]>();
|
|
||||||
var chipType = new List<int>();
|
var headerLength = ReadCRTInt(reader);
|
||||||
|
var version = ReadCRTShort(reader);
|
||||||
var headerLength = ReadCRTInt(reader);
|
var mapper = ReadCRTShort(reader);
|
||||||
var version = ReadCRTShort(reader);
|
var exrom = reader.ReadByte() != 0;
|
||||||
var mapper = ReadCRTShort(reader);
|
var game = reader.ReadByte() != 0;
|
||||||
var exrom = reader.ReadByte() != 0;
|
|
||||||
var game = reader.ReadByte() != 0;
|
// reserved
|
||||||
|
reader.ReadBytes(6);
|
||||||
// reserved
|
|
||||||
reader.ReadBytes(6);
|
// cartridge name
|
||||||
|
reader.ReadBytes(0x20);
|
||||||
// cartridge name
|
|
||||||
reader.ReadBytes(0x20);
|
// skip extra header bytes
|
||||||
|
if (headerLength > 0x40)
|
||||||
// skip extra header bytes
|
{
|
||||||
if (headerLength > 0x40)
|
reader.ReadBytes(headerLength - 0x40);
|
||||||
{
|
}
|
||||||
reader.ReadBytes(headerLength - 0x40);
|
|
||||||
}
|
// read chips
|
||||||
|
while (reader.PeekChar() >= 0)
|
||||||
// read chips
|
{
|
||||||
while (reader.PeekChar() >= 0)
|
if (new string(reader.ReadChars(4)) != "CHIP")
|
||||||
{
|
{
|
||||||
if (new string(reader.ReadChars(4)) != "CHIP")
|
break;
|
||||||
{
|
}
|
||||||
break;
|
|
||||||
}
|
var chipLength = ReadCRTInt(reader);
|
||||||
|
chipType.Add(ReadCRTShort(reader));
|
||||||
var chipLength = ReadCRTInt(reader);
|
chipBank.Add(ReadCRTShort(reader));
|
||||||
chipType.Add(ReadCRTShort(reader));
|
chipAddress.Add(ReadCRTShort(reader));
|
||||||
chipBank.Add(ReadCRTShort(reader));
|
var chipDataLength = ReadCRTShort(reader);
|
||||||
chipAddress.Add(ReadCRTShort(reader));
|
chipData.Add(reader.ReadBytes(chipDataLength).Select(x => (int)x).ToArray());
|
||||||
var chipDataLength = ReadCRTShort(reader);
|
chipLength -= chipDataLength + 0x10;
|
||||||
chipData.Add(reader.ReadBytes(chipDataLength).Select(x => (int)x).ToArray());
|
if (chipLength > 0)
|
||||||
chipLength -= chipDataLength + 0x10;
|
reader.ReadBytes(chipLength);
|
||||||
if (chipLength > 0)
|
}
|
||||||
reader.ReadBytes(chipLength);
|
|
||||||
}
|
if (chipData.Count <= 0)
|
||||||
|
{
|
||||||
if (chipData.Count <= 0)
|
return null;
|
||||||
{
|
}
|
||||||
return null;
|
|
||||||
}
|
CartridgeDevice result;
|
||||||
|
switch (mapper)
|
||||||
CartridgeDevice result;
|
{
|
||||||
switch (mapper)
|
case 0x0000:
|
||||||
{
|
result = new Mapper0000(chipAddress, chipData, game, exrom);
|
||||||
case 0x0000:
|
break;
|
||||||
result = new Mapper0000(chipAddress, chipBank, chipData, game, exrom);
|
case 0x0005:
|
||||||
break;
|
result = new Mapper0005(chipAddress, chipBank, chipData);
|
||||||
case 0x0005:
|
break;
|
||||||
result = new Mapper0005(chipAddress, chipBank, chipData);
|
case 0x000B:
|
||||||
break;
|
result = new Mapper000B(chipAddress, chipData);
|
||||||
case 0x000B:
|
break;
|
||||||
result = new Mapper000B(chipAddress, chipBank, chipData);
|
case 0x000F:
|
||||||
break;
|
result = new Mapper000F(chipAddress, chipBank, chipData);
|
||||||
case 0x000F:
|
break;
|
||||||
result = new Mapper000F(chipAddress, chipBank, chipData);
|
case 0x0011:
|
||||||
break;
|
result = new Mapper0011(chipAddress, chipBank, chipData);
|
||||||
case 0x0011:
|
break;
|
||||||
result = new Mapper0011(chipAddress, chipBank, chipData);
|
case 0x0012:
|
||||||
break;
|
result = new Mapper0012(chipAddress, chipBank, chipData);
|
||||||
case 0x0012:
|
break;
|
||||||
result = new Mapper0012(chipAddress, chipBank, chipData);
|
case 0x0013:
|
||||||
break;
|
result = new Mapper0013(chipAddress, chipBank, chipData);
|
||||||
case 0x0013:
|
break;
|
||||||
result = new Mapper0013(chipAddress, chipBank, chipData);
|
case 0x0020:
|
||||||
break;
|
result = new Mapper0020(chipAddress, chipBank, chipData);
|
||||||
case 0x0020:
|
break;
|
||||||
result = new Mapper0020(chipAddress, chipBank, chipData);
|
default:
|
||||||
break;
|
throw new Exception("This cartridge file uses an unrecognized mapper: " + mapper);
|
||||||
default:
|
}
|
||||||
throw new Exception("This cartridge file uses an unrecognized mapper: " + mapper);
|
result.HardReset();
|
||||||
}
|
|
||||||
result.HardReset();
|
return result;
|
||||||
|
}
|
||||||
return result;
|
|
||||||
}
|
private static int ReadCRTShort(BinaryReader reader)
|
||||||
|
{
|
||||||
private static int ReadCRTShort(BinaryReader reader)
|
return (reader.ReadByte() << 8) |
|
||||||
{
|
reader.ReadByte();
|
||||||
return (reader.ReadByte() << 8) |
|
}
|
||||||
reader.ReadByte();
|
|
||||||
}
|
private static int ReadCRTInt(BinaryReader reader)
|
||||||
|
{
|
||||||
private static int ReadCRTInt(BinaryReader reader)
|
return (reader.ReadByte() << 24) |
|
||||||
{
|
(reader.ReadByte() << 16) |
|
||||||
return (reader.ReadByte() << 24) |
|
(reader.ReadByte() << 8) |
|
||||||
(reader.ReadByte() << 16) |
|
reader.ReadByte();
|
||||||
(reader.ReadByte() << 8) |
|
}
|
||||||
reader.ReadByte();
|
|
||||||
}
|
[SaveState.SaveWithName("ExRom")]
|
||||||
|
protected bool pinExRom;
|
||||||
// ---------------------------------
|
[SaveState.SaveWithName("Game")]
|
||||||
|
protected bool pinGame;
|
||||||
protected bool pinExRom;
|
[SaveState.SaveWithName("IRQ")]
|
||||||
protected bool pinGame;
|
protected bool pinIRQ;
|
||||||
protected bool pinIRQ;
|
[SaveState.SaveWithName("NMI")]
|
||||||
protected bool pinNMI;
|
protected bool pinNMI;
|
||||||
protected bool pinReset;
|
[SaveState.SaveWithName("Reset")]
|
||||||
protected bool validCartridge;
|
protected bool pinReset;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public virtual void ExecutePhase1()
|
protected bool validCartridge;
|
||||||
{
|
|
||||||
}
|
public virtual void ExecutePhase1()
|
||||||
|
{
|
||||||
public virtual void ExecutePhase2()
|
}
|
||||||
{
|
|
||||||
}
|
public virtual void ExecutePhase2()
|
||||||
|
{
|
||||||
public bool ExRom
|
}
|
||||||
{
|
|
||||||
get
|
[SaveState.DoNotSave]
|
||||||
{
|
public bool ExRom
|
||||||
return pinExRom;
|
{
|
||||||
}
|
get
|
||||||
}
|
{
|
||||||
|
return pinExRom;
|
||||||
public bool Game
|
}
|
||||||
{
|
}
|
||||||
get
|
|
||||||
{
|
[SaveState.DoNotSave]
|
||||||
return pinGame;
|
public bool Game
|
||||||
}
|
{
|
||||||
}
|
get
|
||||||
|
{
|
||||||
public virtual void HardReset()
|
return pinGame;
|
||||||
{
|
}
|
||||||
pinIRQ = true;
|
}
|
||||||
pinNMI = true;
|
|
||||||
pinReset = true;
|
public virtual void HardReset()
|
||||||
}
|
{
|
||||||
|
pinIRQ = true;
|
||||||
public bool IRQ
|
pinNMI = true;
|
||||||
{
|
pinReset = true;
|
||||||
get
|
}
|
||||||
{
|
|
||||||
return pinIRQ;
|
[SaveState.DoNotSave]
|
||||||
}
|
public bool IRQ
|
||||||
}
|
{
|
||||||
|
get
|
||||||
public bool NMI
|
{
|
||||||
{
|
return pinIRQ;
|
||||||
get
|
}
|
||||||
{
|
}
|
||||||
return pinNMI;
|
|
||||||
}
|
[SaveState.DoNotSave]
|
||||||
}
|
public bool NMI
|
||||||
|
{
|
||||||
public virtual int Peek8000(int addr)
|
get
|
||||||
{
|
{
|
||||||
return 0xFF;
|
return pinNMI;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public virtual int PeekA000(int addr)
|
|
||||||
{
|
public virtual int Peek8000(int addr)
|
||||||
return 0xFF;
|
{
|
||||||
}
|
return 0xFF;
|
||||||
|
}
|
||||||
public virtual int PeekDE00(int addr)
|
|
||||||
{
|
public virtual int PeekA000(int addr)
|
||||||
return 0xFF;
|
{
|
||||||
}
|
return 0xFF;
|
||||||
|
}
|
||||||
public virtual int PeekDF00(int addr)
|
|
||||||
{
|
public virtual int PeekDE00(int addr)
|
||||||
return 0xFF;
|
{
|
||||||
}
|
return 0xFF;
|
||||||
|
}
|
||||||
public virtual void Poke8000(int addr, int val)
|
|
||||||
{
|
public virtual int PeekDF00(int addr)
|
||||||
}
|
{
|
||||||
|
return 0xFF;
|
||||||
public virtual void PokeA000(int addr, int val)
|
}
|
||||||
{
|
|
||||||
}
|
public virtual void Poke8000(int addr, int val)
|
||||||
|
{
|
||||||
public virtual void PokeDE00(int addr, int val)
|
}
|
||||||
{
|
|
||||||
}
|
public virtual void PokeA000(int addr, int val)
|
||||||
|
{
|
||||||
public virtual void PokeDF00(int addr, int val)
|
}
|
||||||
{
|
|
||||||
}
|
public virtual void PokeDE00(int addr, int val)
|
||||||
|
{
|
||||||
public virtual int Read8000(int addr)
|
}
|
||||||
{
|
|
||||||
return 0xFF;
|
public virtual void PokeDF00(int addr, int val)
|
||||||
}
|
{
|
||||||
|
}
|
||||||
public virtual int ReadA000(int addr)
|
|
||||||
{
|
public virtual int Read8000(int addr)
|
||||||
return 0xFF;
|
{
|
||||||
}
|
return 0xFF;
|
||||||
|
}
|
||||||
public virtual int ReadDE00(int addr)
|
|
||||||
{
|
public virtual int ReadA000(int addr)
|
||||||
return 0xFF;
|
{
|
||||||
}
|
return 0xFF;
|
||||||
|
}
|
||||||
public virtual int ReadDF00(int addr)
|
|
||||||
{
|
public virtual int ReadDE00(int addr)
|
||||||
return 0xFF;
|
{
|
||||||
}
|
return 0xFF;
|
||||||
|
}
|
||||||
public bool Reset
|
|
||||||
{
|
public virtual int ReadDF00(int addr)
|
||||||
get
|
{
|
||||||
{
|
return 0xFF;
|
||||||
return pinReset;
|
}
|
||||||
}
|
|
||||||
}
|
[SaveState.DoNotSave]
|
||||||
|
public bool Reset
|
||||||
public virtual void SyncState(Serializer ser)
|
{
|
||||||
{
|
get
|
||||||
SaveState.SyncObject(ser, this);
|
{
|
||||||
}
|
return pinReset;
|
||||||
|
}
|
||||||
public bool Valid
|
}
|
||||||
{
|
|
||||||
get
|
public virtual void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
return validCartridge;
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public virtual void Write8000(int addr, int val)
|
public bool Valid
|
||||||
{
|
{
|
||||||
}
|
get
|
||||||
|
{
|
||||||
public virtual void WriteA000(int addr, int val)
|
return validCartridge;
|
||||||
{
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void WriteDE00(int addr, int val)
|
public virtual void Write8000(int addr, int val)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void WriteDF00(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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,15 +8,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
private sealed class Mapper0000 : CartridgeDevice
|
private sealed class Mapper0000 : CartridgeDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[] _romA;
|
private readonly int[] _romA;
|
||||||
|
[SaveState.SaveWithName("RomMaskA")]
|
||||||
private readonly int _romAMask;
|
private readonly int _romAMask;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[] _romB;
|
private readonly int[] _romB;
|
||||||
|
[SaveState.SaveWithName("RomMaskB")]
|
||||||
private readonly int _romBMask;
|
private readonly int _romBMask;
|
||||||
|
|
||||||
// standard cartridge mapper (Commodore)
|
// standard cartridge mapper (Commodore)
|
||||||
// note that this format also covers Ultimax carts
|
// 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;
|
pinGame = game;
|
||||||
pinExRom = exrom;
|
pinExRom = exrom;
|
||||||
|
|
|
@ -9,12 +9,19 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
private sealed class Mapper0005 : CartridgeDevice
|
private sealed class Mapper0005 : CartridgeDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[][] _banksA; //8000
|
private readonly int[][] _banksA; //8000
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[][] _banksB = new int[0][]; //A000
|
private readonly int[][] _banksB = new int[0][]; //A000
|
||||||
|
[SaveState.SaveWithName("BankMask")]
|
||||||
private readonly int _bankMask;
|
private readonly int _bankMask;
|
||||||
|
[SaveState.SaveWithName("BankNumber")]
|
||||||
private int _bankNumber;
|
private int _bankNumber;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private int[] _currentBankA;
|
private int[] _currentBankA;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private int[] _currentBankB;
|
private int[] _currentBankB;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[] _dummyBank;
|
private readonly int[] _dummyBank;
|
||||||
|
|
||||||
public Mapper0005(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
public Mapper0005(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
||||||
|
|
|
@ -14,9 +14,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
private sealed class Mapper000B : CartridgeDevice
|
private sealed class Mapper000B : CartridgeDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[] _rom = new int[0x4000];
|
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;
|
validCartridge = false;
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
private class Mapper000F : CartridgeDevice
|
private class Mapper000F : CartridgeDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[][] _banks; //8000
|
private readonly int[][] _banks; //8000
|
||||||
|
[SaveState.SaveWithName("BankMask")]
|
||||||
private readonly int _bankMask;
|
private readonly int _bankMask;
|
||||||
|
[SaveState.SaveWithName("BankNumber")]
|
||||||
private int _bankNumber;
|
private int _bankNumber;
|
||||||
|
[SaveState.SaveWithName("CurrentBank")]
|
||||||
private int[] _currentBank;
|
private int[] _currentBank;
|
||||||
|
|
||||||
public Mapper000F(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
public Mapper000F(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
||||||
|
|
|
@ -8,9 +8,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
private sealed class Mapper0012 : CartridgeDevice
|
private sealed class Mapper0012 : CartridgeDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[] _bankMain;
|
private readonly int[] _bankMain;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[][] _bankHigh;
|
private readonly int[][] _bankHigh;
|
||||||
|
[SaveState.SaveWithName("BankHighSelected")]
|
||||||
private int[] _bankHighSelected;
|
private int[] _bankHighSelected;
|
||||||
|
[SaveState.SaveWithName("BankIndex")]
|
||||||
private int _bankIndex;
|
private int _bankIndex;
|
||||||
|
|
||||||
// Zaxxon and Super Zaxxon cartridges
|
// Zaxxon and Super Zaxxon cartridges
|
||||||
|
|
|
@ -16,10 +16,15 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
private sealed class Mapper0013 : CartridgeDevice
|
private sealed class Mapper0013 : CartridgeDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private readonly int[][] _banks; //8000
|
private readonly int[][] _banks; //8000
|
||||||
|
[SaveState.SaveWithName("BankMask")]
|
||||||
private readonly int _bankMask;
|
private readonly int _bankMask;
|
||||||
|
[SaveState.SaveWithName("BankNumber")]
|
||||||
private int _bankNumber;
|
private int _bankNumber;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private int[] _currentBank;
|
private int[] _currentBank;
|
||||||
|
[SaveState.SaveWithName("ROMEnable")]
|
||||||
private bool _romEnable;
|
private bool _romEnable;
|
||||||
|
|
||||||
public Mapper0013(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
public Mapper0013(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
||||||
|
|
|
@ -26,15 +26,29 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
private sealed class Mapper0020 : CartridgeDevice
|
private sealed class Mapper0020 : CartridgeDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.SaveWithName("BankOffset")]
|
||||||
private int _bankOffset = 63 << 13;
|
private int _bankOffset = 63 << 13;
|
||||||
private readonly int[] _banksA = new int[64 << 13]; //8000
|
[SaveState.DoNotSave]
|
||||||
private readonly int[] _banksB = new int[64 << 13]; //A000
|
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;
|
private bool _boardLed;
|
||||||
|
[SaveState.SaveWithName("Jumper")]
|
||||||
private bool _jumper = false;
|
private bool _jumper = false;
|
||||||
|
[SaveState.SaveWithName("StateBits")]
|
||||||
private int _stateBits;
|
private int _stateBits;
|
||||||
|
[SaveState.SaveWithName("RAM")]
|
||||||
private readonly int[] _ram = new int[256];
|
private readonly int[] _ram = new int[256];
|
||||||
|
[SaveState.SaveWithName("CommandLatch55")]
|
||||||
private bool _commandLatch55;
|
private bool _commandLatch55;
|
||||||
|
[SaveState.SaveWithName("CommandLatchAA")]
|
||||||
private bool _commandLatchAa;
|
private bool _commandLatchAa;
|
||||||
|
[SaveState.SaveWithName("InternalROMState")]
|
||||||
private int _internalRomState;
|
private int _internalRomState;
|
||||||
|
|
||||||
public Mapper0020(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
public Mapper0020(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
|
||||||
|
@ -75,6 +89,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
_commandLatch55 = false;
|
_commandLatch55 = false;
|
||||||
_commandLatchAa = false;
|
_commandLatchAa = false;
|
||||||
_internalRomState = 0;
|
_internalRomState = 0;
|
||||||
|
|
||||||
|
// back up original media
|
||||||
|
_originalMediaA = _banksA.Select(d => d).ToArray();
|
||||||
|
_originalMediaB = _banksB.Select(d => d).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BankSet(int index)
|
private void BankSet(int index)
|
||||||
|
@ -265,6 +283,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
||||||
{
|
{
|
||||||
_ram[addr] = val & 0xFF;
|
_ram[addr] = val & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void SyncState(Serializer ser)
|
||||||
|
{
|
||||||
|
SaveState.SyncDelta("MediaStateA", ser, _originalMediaA, ref _banksA);
|
||||||
|
SaveState.SyncDelta("MediaStateB", ser, _originalMediaB, ref _banksB);
|
||||||
|
base.SyncState(ser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,62 @@
|
||||||
using System;
|
using System;
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
|
||||||
{
|
{
|
||||||
public sealed class CassettePort
|
public sealed class CassettePort
|
||||||
{
|
{
|
||||||
public Func<bool> ReadDataOutput = () => true;
|
[SaveState.DoNotSave]
|
||||||
public Func<bool> ReadMotor = () => true;
|
public Func<bool> ReadDataOutput = () => true;
|
||||||
private CassettePortDevice _device;
|
[SaveState.DoNotSave]
|
||||||
private bool _connected;
|
public Func<bool> ReadMotor = () => true;
|
||||||
|
|
||||||
public void HardReset()
|
[SaveState.SaveWithName("Device")]
|
||||||
{
|
private CassettePortDevice _device;
|
||||||
if (_connected)
|
[SaveState.SaveWithName("Connected")]
|
||||||
{
|
private bool _connected;
|
||||||
_device.HardReset();
|
|
||||||
}
|
public void HardReset()
|
||||||
}
|
{
|
||||||
|
if (_connected)
|
||||||
public void ExecutePhase()
|
{
|
||||||
{
|
_device.HardReset();
|
||||||
if (_connected)
|
}
|
||||||
{
|
}
|
||||||
_device.ExecutePhase2();
|
|
||||||
}
|
public void ExecutePhase()
|
||||||
}
|
{
|
||||||
|
if (_connected)
|
||||||
public bool ReadDataInputBuffer()
|
{
|
||||||
{
|
_device.ExecutePhase2();
|
||||||
return !_connected || _device.ReadDataInputBuffer();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ReadSenseBuffer()
|
public bool ReadDataInputBuffer()
|
||||||
{
|
{
|
||||||
return !_connected || _device.ReadSenseBuffer();
|
return !_connected || _device.ReadDataInputBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public bool ReadSenseBuffer()
|
||||||
{
|
{
|
||||||
SaveState.SyncObject(ser, this);
|
return !_connected || _device.ReadSenseBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Connect(CassettePortDevice device)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
_connected = device != null;
|
SaveState.SyncObject(ser, this);
|
||||||
_device = device;
|
}
|
||||||
if (_device == null)
|
|
||||||
{
|
public void Connect(CassettePortDevice device)
|
||||||
return;
|
{
|
||||||
}
|
_connected = device != null;
|
||||||
|
_device = device;
|
||||||
_device.ReadDataOutput = () => ReadDataOutput();
|
if (_device == null)
|
||||||
_device.ReadMotor = () => ReadMotor();
|
{
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
_device.ReadDataOutput = () => ReadDataOutput();
|
||||||
|
_device.ReadMotor = () => ReadMotor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,34 +1,36 @@
|
||||||
using System;
|
using System;
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
|
||||||
{
|
{
|
||||||
public abstract class CassettePortDevice
|
public abstract class CassettePortDevice
|
||||||
{
|
{
|
||||||
public Func<bool> ReadDataOutput;
|
[SaveState.DoNotSave]
|
||||||
public Func<bool> ReadMotor;
|
public Func<bool> ReadDataOutput;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public virtual void ExecutePhase2()
|
public Func<bool> ReadMotor;
|
||||||
{
|
|
||||||
}
|
public virtual void ExecutePhase2()
|
||||||
|
{
|
||||||
public virtual void HardReset()
|
}
|
||||||
{
|
|
||||||
}
|
public virtual void HardReset()
|
||||||
|
{
|
||||||
public virtual bool ReadDataInputBuffer()
|
}
|
||||||
{
|
|
||||||
return true;
|
public virtual bool ReadDataInputBuffer()
|
||||||
}
|
{
|
||||||
|
return true;
|
||||||
public virtual bool ReadSenseBuffer()
|
}
|
||||||
{
|
|
||||||
return true;
|
public virtual bool ReadSenseBuffer()
|
||||||
}
|
{
|
||||||
|
return true;
|
||||||
public virtual void SyncState(Serializer ser)
|
}
|
||||||
{
|
|
||||||
SaveState.SyncObject(ser, this);
|
public virtual void SyncState(Serializer ser)
|
||||||
}
|
{
|
||||||
}
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,40 +1,41 @@
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
|
using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette
|
||||||
{
|
{
|
||||||
public class TapeDrive : CassettePortDevice
|
public class TapeDrive : CassettePortDevice
|
||||||
{
|
{
|
||||||
private Tape _tape;
|
[SaveState.SaveWithName("Tape")]
|
||||||
|
private Tape _tape;
|
||||||
public override void ExecutePhase2()
|
|
||||||
{
|
public override void ExecutePhase2()
|
||||||
if (_tape != null && !ReadMotor()) _tape.ExecuteCycle();
|
{
|
||||||
}
|
if (_tape != null && !ReadMotor()) _tape.ExecuteCycle();
|
||||||
|
}
|
||||||
public override void HardReset()
|
|
||||||
{
|
public override void HardReset()
|
||||||
if (_tape != null) _tape.Rewind();
|
{
|
||||||
}
|
if (_tape != null) _tape.Rewind();
|
||||||
|
}
|
||||||
public override bool ReadDataInputBuffer()
|
|
||||||
{
|
public override bool ReadDataInputBuffer()
|
||||||
return _tape == null || _tape.Read();
|
{
|
||||||
}
|
return _tape == null || _tape.Read();
|
||||||
|
}
|
||||||
public override bool ReadSenseBuffer()
|
|
||||||
{
|
public override bool ReadSenseBuffer()
|
||||||
return _tape == null;
|
{
|
||||||
}
|
return _tape == null;
|
||||||
|
}
|
||||||
public override void SyncState(Serializer ser)
|
|
||||||
{
|
public override void SyncState(Serializer ser)
|
||||||
SaveState.SyncObject(ser, this);
|
{
|
||||||
}
|
SaveState.SyncObject(ser, this);
|
||||||
|
}
|
||||||
public void Insert(Tape tape)
|
|
||||||
{
|
public void Insert(Tape tape)
|
||||||
_tape = tape;
|
{
|
||||||
}
|
_tape = tape;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cia Create(C64.CiaType type, int[] keyboard, int[] joysticks)
|
public static Cia Create(C64.CiaType type, Func<bool[]> keyboard, Func<bool[]> joysticks)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,37 +36,40 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
||||||
{
|
{
|
||||||
[SaveState.DoNotSave] private int _ret;
|
[SaveState.DoNotSave] private int _ret;
|
||||||
[SaveState.DoNotSave] private int _tst;
|
[SaveState.DoNotSave] private int _tst;
|
||||||
[SaveState.DoNotSave] private readonly int[] _joyData;
|
[SaveState.DoNotSave] private readonly Func<bool[]> _readJoyData;
|
||||||
[SaveState.DoNotSave] private readonly int[] _keyData;
|
[SaveState.DoNotSave] private readonly Func<bool[]> _readKeyData;
|
||||||
|
|
||||||
public JoystickKeyboardPort(int[] joyData, int[] keyData)
|
public JoystickKeyboardPort(Func<bool[]> readJoyData, Func<bool[]> readKeyData)
|
||||||
{
|
{
|
||||||
_joyData = joyData;
|
_readJoyData = readJoyData;
|
||||||
_keyData = keyData;
|
_readKeyData = readKeyData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetJoystick1()
|
private int GetJoystick1()
|
||||||
{
|
{
|
||||||
|
var joyData = _readJoyData();
|
||||||
return 0xE0 |
|
return 0xE0 |
|
||||||
(_joyData[0] == 0 ? 0x01 : 0x00) |
|
(joyData[0] ? 0x00 : 0x01) |
|
||||||
(_joyData[1] == 0 ? 0x02 : 0x00) |
|
(joyData[1] ? 0x00 : 0x02) |
|
||||||
(_joyData[2] == 0 ? 0x04 : 0x00) |
|
(joyData[2] ? 0x00 : 0x04) |
|
||||||
(_joyData[3] == 0 ? 0x08 : 0x00) |
|
(joyData[3] ? 0x00 : 0x08) |
|
||||||
(_joyData[4] == 0 ? 0x10 : 0x00);
|
(joyData[4] ? 0x00 : 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetJoystick2()
|
private int GetJoystick2()
|
||||||
{
|
{
|
||||||
|
var joyData = _readJoyData();
|
||||||
return 0xE0 |
|
return 0xE0 |
|
||||||
(_joyData[5] == 0 ? 0x01 : 0x00) |
|
(joyData[5] ? 0x00 : 0x01) |
|
||||||
(_joyData[6] == 0 ? 0x02 : 0x00) |
|
(joyData[6] ? 0x00 : 0x02) |
|
||||||
(_joyData[7] == 0 ? 0x04 : 0x00) |
|
(joyData[7] ? 0x00 : 0x04) |
|
||||||
(_joyData[8] == 0 ? 0x08 : 0x00) |
|
(joyData[8] ? 0x00 : 0x08) |
|
||||||
(_joyData[9] == 0 ? 0x10 : 0x00);
|
(joyData[9] ? 0x00 : 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetKeyboardRows(int activeColumns)
|
private int GetKeyboardRows(int activeColumns)
|
||||||
{
|
{
|
||||||
|
var keyData = _readKeyData();
|
||||||
var result = 0xFF;
|
var result = 0xFF;
|
||||||
for (var r = 0; r < 8; r++)
|
for (var r = 0; r < 8; r++)
|
||||||
{
|
{
|
||||||
|
@ -75,7 +78,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
||||||
var i = r << 3;
|
var i = r << 3;
|
||||||
for (var c = 0; c < 8; c++)
|
for (var c = 0; c < 8; c++)
|
||||||
{
|
{
|
||||||
if (_keyData[i++] != 0)
|
if (keyData[i++])
|
||||||
{
|
{
|
||||||
result &= ~(1 << c);
|
result &= ~(1 << c);
|
||||||
}
|
}
|
||||||
|
@ -88,6 +91,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
||||||
|
|
||||||
private int GetKeyboardColumns(int activeRows)
|
private int GetKeyboardColumns(int activeRows)
|
||||||
{
|
{
|
||||||
|
var keyData = _readKeyData();
|
||||||
var result = 0xFF;
|
var result = 0xFF;
|
||||||
for (var c = 0; c < 8; c++)
|
for (var c = 0; c < 8; c++)
|
||||||
{
|
{
|
||||||
|
@ -96,7 +100,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
||||||
var i = c;
|
var i = c;
|
||||||
for (var r = 0; r < 8; r++)
|
for (var r = 0; r < 8; r++)
|
||||||
{
|
{
|
||||||
if (_keyData[i] != 0)
|
if (keyData[i])
|
||||||
{
|
{
|
||||||
result &= ~(1 << r);
|
result &= ~(1 << r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
||||||
_todDen = todDen;
|
_todDen = todDen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cia(int todNum, int todDen, int[] keyboard, int[] joysticks) : this(todNum, todDen)
|
public Cia(int todNum, int todDen, Func<bool[]> keyboard, Func<bool[]> joysticks) : this(todNum, todDen)
|
||||||
{
|
{
|
||||||
_port = new JoystickKeyboardPort(joysticks, keyboard);
|
_port = new JoystickKeyboardPort(joysticks, keyboard);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
||||||
{
|
{
|
||||||
public sealed class Disk
|
public sealed class Disk
|
||||||
{
|
{
|
||||||
public const int FLUX_BITS_PER_ENTRY = 32;
|
[SaveState.DoNotSave] public const int FluxBitsPerEntry = 32;
|
||||||
public const int FLUX_BITS_PER_TRACK = 16000000 / 5;
|
[SaveState.DoNotSave] public const int FluxBitsPerTrack = 16000000 / 5;
|
||||||
public const int FLUX_ENTRIES_PER_TRACK = FLUX_BITS_PER_TRACK/FLUX_BITS_PER_ENTRY;
|
[SaveState.DoNotSave] public const int FluxEntriesPerTrack = FluxBitsPerTrack/FluxBitsPerEntry;
|
||||||
|
[SaveState.DoNotSave] private int[][] _tracks;
|
||||||
private class Track
|
[SaveState.DoNotSave] private readonly int[] _originalMedia;
|
||||||
{
|
|
||||||
public int Index;
|
|
||||||
public bool Present;
|
|
||||||
public int[] FluxData;
|
|
||||||
}
|
|
||||||
|
|
||||||
[SaveState.DoNotSave] private readonly Track[] _tracks;
|
|
||||||
[SaveState.DoNotSave] public bool Valid;
|
[SaveState.DoNotSave] public bool Valid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -26,9 +19,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Disk(int trackCapacity)
|
public Disk(int trackCapacity)
|
||||||
{
|
{
|
||||||
_tracks = new Track[trackCapacity];
|
_tracks = new int[trackCapacity][];
|
||||||
FillMissingTracks();
|
FillMissingTracks();
|
||||||
Valid = true;
|
_originalMedia = SerializeTracks(_tracks);
|
||||||
|
Valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -41,46 +35,71 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
||||||
/// <param name="trackCapacity">Total number of tracks on the media.</param>
|
/// <param name="trackCapacity">Total number of tracks on the media.</param>
|
||||||
public Disk(IList<byte[]> trackData, IList<int> trackNumbers, IList<int> trackDensities, IList<int> trackLengths, int trackCapacity)
|
public Disk(IList<byte[]> trackData, IList<int> trackNumbers, IList<int> trackDensities, IList<int> trackLengths, int trackCapacity)
|
||||||
{
|
{
|
||||||
_tracks = new Track[trackCapacity];
|
_tracks = new int[trackCapacity][];
|
||||||
for (var i = 0; i < trackData.Count; i++)
|
for (var i = 0; i < trackData.Count; i++)
|
||||||
{
|
{
|
||||||
var track = new Track
|
_tracks[trackNumbers[i]] = ConvertToFluxTransitions(trackDensities[i], trackData[i], 0);
|
||||||
{
|
|
||||||
Index = trackNumbers[i],
|
|
||||||
Present = true,
|
|
||||||
FluxData = ConvertToFluxTransitions(trackDensities[i], trackData[i], 0)
|
|
||||||
};
|
|
||||||
_tracks[trackNumbers[i]] = track;
|
|
||||||
}
|
}
|
||||||
FillMissingTracks();
|
FillMissingTracks();
|
||||||
Valid = true;
|
Valid = true;
|
||||||
}
|
_originalMedia = SerializeTracks(_tracks);
|
||||||
|
}
|
||||||
|
|
||||||
private int[] ConvertToFluxTransitions(int density, byte[] bytes, int fluxBitOffset)
|
private int[] ConvertToFluxTransitions(int density, byte[] bytes, int fluxBitOffset)
|
||||||
{
|
{
|
||||||
var result = new int[FLUX_ENTRIES_PER_TRACK];
|
var paddedLength = bytes.Length;
|
||||||
var length = bytes.Length;
|
switch (density)
|
||||||
var lengthBits = length*8;
|
{
|
||||||
|
case 3:
|
||||||
|
paddedLength = Math.Max(bytes.Length, 7692);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
paddedLength = Math.Max(bytes.Length, 7142);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
paddedLength = Math.Max(bytes.Length, 6666);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
paddedLength = Math.Max(bytes.Length, 6250);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
paddedLength++;
|
||||||
|
var paddedBytes = new byte[paddedLength];
|
||||||
|
Array.Copy(bytes, paddedBytes, bytes.Length);
|
||||||
|
for (var i = bytes.Length; i < paddedLength; i++)
|
||||||
|
{
|
||||||
|
paddedBytes[i] = 0xAA;
|
||||||
|
}
|
||||||
|
var result = new int[FluxEntriesPerTrack];
|
||||||
|
var length = paddedLength;
|
||||||
|
var lengthBits = (paddedLength * 8) - 7;
|
||||||
var offsets = new List<long>();
|
var offsets = new List<long>();
|
||||||
|
var remainingBits = lengthBits;
|
||||||
|
|
||||||
const long bitsNum = FLUX_ENTRIES_PER_TRACK * FLUX_BITS_PER_ENTRY;
|
const long bitsNum = FluxEntriesPerTrack * FluxBitsPerEntry;
|
||||||
long bitsDen = lengthBits;
|
long bitsDen = lengthBits;
|
||||||
|
|
||||||
for (var i = 0; i < length; i++)
|
for (var i = 0; i < paddedLength; i++)
|
||||||
{
|
{
|
||||||
var byteData = bytes[i];
|
var byteData = paddedBytes[i];
|
||||||
for (var j = 0; j < 8; j++)
|
for (var j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
var offset = fluxBitOffset + ((i * 8 + j) * bitsNum / bitsDen);
|
var offset = fluxBitOffset + ((i * 8 + j) * bitsNum / bitsDen);
|
||||||
var byteOffset = (int)(offset / FLUX_BITS_PER_ENTRY);
|
var byteOffset = (int)(offset / FluxBitsPerEntry);
|
||||||
var bitOffset = (int)(offset % FLUX_BITS_PER_ENTRY);
|
var bitOffset = (int)(offset % FluxBitsPerEntry);
|
||||||
offsets.Add(offset);
|
offsets.Add(offset);
|
||||||
result[byteOffset] |= ((byteData & 0x80) != 0 ? 1 : 0) << bitOffset;
|
result[byteOffset] |= ((byteData & 0x80) != 0 ? 1 : 0) << bitOffset;
|
||||||
byteData <<= 1;
|
byteData <<= 1;
|
||||||
}
|
remainingBits--;
|
||||||
}
|
if (remainingBits <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (remainingBits <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FillMissingTracks()
|
private void FillMissingTracks()
|
||||||
|
@ -89,27 +108,58 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
||||||
{
|
{
|
||||||
if (_tracks[i] == null)
|
if (_tracks[i] == null)
|
||||||
{
|
{
|
||||||
_tracks[i] = new Track
|
_tracks[i] = new int[FluxEntriesPerTrack];
|
||||||
{
|
|
||||||
Index = i,
|
|
||||||
FluxData = new int[FLUX_ENTRIES_PER_TRACK]
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] GetDataForTrack(int halftrack)
|
public int[] GetDataForTrack(int halftrack)
|
||||||
{
|
{
|
||||||
return _tracks[halftrack].FluxData;
|
return _tracks[halftrack];
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<int> GetPresentTracks()
|
/// <summary>
|
||||||
|
/// Combine the tracks into a single bitstream.
|
||||||
|
/// </summary>
|
||||||
|
private int[] SerializeTracks(int[][] tracks)
|
||||||
{
|
{
|
||||||
return _tracks.Where(t => t.Present).Select(t => t.Index);
|
var trackCount = tracks.Length;
|
||||||
}
|
var result = new int[trackCount * FluxEntriesPerTrack];
|
||||||
|
for (var i = 0; i < trackCount; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(tracks[i], 0, result, i * FluxEntriesPerTrack, FluxEntriesPerTrack);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Split a bitstream into tracks.
|
||||||
|
/// </summary>
|
||||||
|
private int[][] DeserializeTracks(int[] data)
|
||||||
|
{
|
||||||
|
var trackCount = data.Length/FluxEntriesPerTrack;
|
||||||
|
var result = new int[trackCount][];
|
||||||
|
for (var i = 0; i < trackCount; i++)
|
||||||
|
{
|
||||||
|
result[i] = new int[FluxEntriesPerTrack];
|
||||||
|
Array.Copy(data, i * FluxEntriesPerTrack, result[i], 0, FluxEntriesPerTrack);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
|
if (ser.IsReader)
|
||||||
|
{
|
||||||
|
var mediaState = new int[_originalMedia.Length];
|
||||||
|
SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState);
|
||||||
|
_tracks = DeserializeTracks(mediaState);
|
||||||
|
}
|
||||||
|
else if (ser.IsWriter)
|
||||||
|
{
|
||||||
|
var mediaState = SerializeTracks(_tracks);
|
||||||
|
SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState);
|
||||||
|
}
|
||||||
SaveState.SyncObject(ser, this);
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,101 +1,103 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
||||||
{
|
{
|
||||||
/**
|
public class Tape
|
||||||
* This class represents a tape. Only TAP-style tapes are supported for now.
|
{
|
||||||
*/
|
[SaveState.DoNotSave] private readonly byte[] _tapeData;
|
||||||
public class Tape
|
[SaveState.DoNotSave] private readonly byte _version;
|
||||||
{
|
[SaveState.DoNotSave] private readonly int _start;
|
||||||
[SaveState.DoNotSave] private readonly byte[] _tapeData;
|
[SaveState.DoNotSave] private readonly int _end;
|
||||||
[SaveState.DoNotSave] private readonly byte _version;
|
|
||||||
[SaveState.DoNotSave] private readonly int _start;
|
[SaveState.SaveWithName("Position")]
|
||||||
[SaveState.DoNotSave] private readonly int _end;
|
private int _pos;
|
||||||
private int _pos, _cycle;
|
[SaveState.SaveWithName("Cycle")]
|
||||||
private bool _data;
|
private int _cycle;
|
||||||
|
[SaveState.SaveWithName("Data")]
|
||||||
public Tape(byte version, byte[] tapeData, int start, int end)
|
private bool _data;
|
||||||
{
|
|
||||||
_version = version;
|
public Tape(byte version, byte[] tapeData, int start, int end)
|
||||||
_tapeData = tapeData;
|
{
|
||||||
_start = start;
|
_version = version;
|
||||||
_end = end;
|
_tapeData = tapeData;
|
||||||
Rewind();
|
_start = start;
|
||||||
}
|
_end = end;
|
||||||
|
Rewind();
|
||||||
public void ExecuteCycle()
|
}
|
||||||
{
|
|
||||||
if (_cycle == 0)
|
public void ExecuteCycle()
|
||||||
{
|
{
|
||||||
if (_pos >= _end)
|
if (_cycle == 0)
|
||||||
{
|
{
|
||||||
_data = true;
|
if (_pos >= _end)
|
||||||
return;
|
{
|
||||||
}
|
_data = true;
|
||||||
|
return;
|
||||||
_cycle = _tapeData[_pos++] * 8;
|
}
|
||||||
if (_cycle == 0)
|
|
||||||
{
|
_cycle = _tapeData[_pos++] * 8;
|
||||||
if (_version == 0)
|
if (_cycle == 0)
|
||||||
{
|
{
|
||||||
_cycle = 256 * 8; // unspecified overflow condition
|
if (_version == 0)
|
||||||
}
|
{
|
||||||
else
|
_cycle = 256 * 8; // unspecified overflow condition
|
||||||
{
|
}
|
||||||
_cycle = (int)(BitConverter.ToUInt32(_tapeData, _pos - 1) >> 8);
|
else
|
||||||
_pos += 3;
|
{
|
||||||
if (_cycle == 0)
|
_cycle = (int)(BitConverter.ToUInt32(_tapeData, _pos - 1) >> 8);
|
||||||
{
|
_pos += 3;
|
||||||
throw new Exception("Bad tape data");
|
if (_cycle == 0)
|
||||||
}
|
{
|
||||||
}
|
throw new Exception("Bad tape data");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_cycle++;
|
}
|
||||||
}
|
|
||||||
|
_cycle++;
|
||||||
// Send a single negative pulse at the end of a cycle
|
}
|
||||||
_data = --_cycle != 0;
|
|
||||||
}
|
// Send a single negative pulse at the end of a cycle
|
||||||
|
_data = --_cycle != 0;
|
||||||
// Rewinds the tape back to start
|
}
|
||||||
public void Rewind()
|
|
||||||
{
|
// Rewinds the tape back to start
|
||||||
_pos = _start;
|
public void Rewind()
|
||||||
_cycle = 0;
|
{
|
||||||
}
|
_pos = _start;
|
||||||
|
_cycle = 0;
|
||||||
// Reads from tape, this will tell the caller if the flag pin should be raised
|
}
|
||||||
public bool Read()
|
|
||||||
{
|
// Reads from tape, this will tell the caller if the flag pin should be raised
|
||||||
return _data;
|
public bool Read()
|
||||||
}
|
{
|
||||||
|
return _data;
|
||||||
// Try to construct a tape file from file data. Returns null if not a tape file, throws exceptions for bad tape files.
|
}
|
||||||
// (Note that some error conditions aren't caught right here.)
|
|
||||||
public static Tape Load(byte[] tapeFile)
|
// Try to construct a tape file from file data. Returns null if not a tape file, throws exceptions for bad tape files.
|
||||||
{
|
// (Note that some error conditions aren't caught right here.)
|
||||||
Tape result = null;
|
public static Tape Load(byte[] tapeFile)
|
||||||
|
{
|
||||||
if (Encoding.ASCII.GetString(tapeFile, 0, 12) == "C64-TAPE-RAW")
|
Tape result = null;
|
||||||
{
|
|
||||||
var version = tapeFile[12];
|
if (Encoding.ASCII.GetString(tapeFile, 0, 12) == "C64-TAPE-RAW")
|
||||||
if (version > 1) throw new Exception("This tape has an unsupported version");
|
{
|
||||||
var size = BitConverter.ToUInt32(tapeFile, 16);
|
var version = tapeFile[12];
|
||||||
if (size + 20 != tapeFile.Length)
|
if (version > 1) throw new Exception("This tape has an unsupported version");
|
||||||
{
|
var size = BitConverter.ToUInt32(tapeFile, 16);
|
||||||
throw new Exception("Tape file header specifies a length that doesn't match the file size");
|
if (size + 20 != tapeFile.Length)
|
||||||
}
|
{
|
||||||
result = new Tape(version, tapeFile, 20, tapeFile.Length);
|
throw new Exception("Tape file header specifies a length that doesn't match the file size");
|
||||||
}
|
}
|
||||||
return result;
|
result = new Tape(version, tapeFile, 20, tapeFile.Length);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
public void SyncState(Serializer ser)
|
}
|
||||||
{
|
|
||||||
SaveState.SyncObject(ser, this);
|
public void SyncState(Serializer ser)
|
||||||
}
|
{
|
||||||
}
|
SaveState.SyncObject(ser, this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -14,9 +17,99 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SaveWithName : Attribute
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public SaveWithName(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly Encoding Encoding = Encoding.Unicode;
|
private static readonly Encoding Encoding = Encoding.Unicode;
|
||||||
|
|
||||||
public static void SyncObject(Serializer ser, object obj)
|
private static int[] GetDelta(IList<int> source, IList<int> data)
|
||||||
|
{
|
||||||
|
var length = Math.Min(source.Count, data.Count);
|
||||||
|
var delta = new int[length];
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
delta[i] = source[i] ^ data[i];
|
||||||
|
}
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] CompressInts(int[] data)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
var length = data.Length;
|
||||||
|
var bytes = new byte[length * 4];
|
||||||
|
for (int i = 0, j = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
var c = data[i];
|
||||||
|
bytes[j++] = (byte)(c);
|
||||||
|
bytes[j++] = (byte)(c >> 8);
|
||||||
|
bytes[j++] = (byte)(c >> 16);
|
||||||
|
bytes[j++] = (byte)(c >> 24);
|
||||||
|
}
|
||||||
|
using (var mem = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (var compressor = new DeflateStream(mem, CompressionMode.Compress))
|
||||||
|
{
|
||||||
|
var writer = new BinaryWriter(compressor);
|
||||||
|
writer.Write(bytes.Length);
|
||||||
|
writer.Write(bytes);
|
||||||
|
compressor.Flush();
|
||||||
|
}
|
||||||
|
mem.Flush();
|
||||||
|
return mem.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] DecompressInts(byte[] data)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
using (var mem = new MemoryStream(data))
|
||||||
|
{
|
||||||
|
using (var decompressor = new DeflateStream(mem, CompressionMode.Decompress))
|
||||||
|
{
|
||||||
|
var reader = new BinaryReader(decompressor);
|
||||||
|
var length = reader.ReadInt32();
|
||||||
|
var bytes = reader.ReadBytes(length);
|
||||||
|
var result = new int[length >> 2];
|
||||||
|
for (int i = 0, j = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
int d = bytes[i++];
|
||||||
|
d |= bytes[i++] << 8;
|
||||||
|
d |= bytes[i++] << 16;
|
||||||
|
d |= bytes[i] << 24;
|
||||||
|
result[j++] = d;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SyncDelta(string name, Serializer ser, int[] source, ref int[] data)
|
||||||
|
{
|
||||||
|
int[] delta = null;
|
||||||
|
if (ser.IsWriter && data != null)
|
||||||
|
{
|
||||||
|
delta = GetDelta(source, data);
|
||||||
|
}
|
||||||
|
ser.Sync(name, ref delta, false);
|
||||||
|
if (ser.IsReader && delta != null)
|
||||||
|
{
|
||||||
|
data = GetDelta(source, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SyncObject(Serializer ser, object obj)
|
||||||
{
|
{
|
||||||
const BindingFlags defaultFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
|
const BindingFlags defaultFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
|
||||||
var objType = obj.GetType();
|
var objType = obj.GetType();
|
||||||
|
@ -29,6 +122,14 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var name = member.Name;
|
||||||
|
var nameAttribute = member.GetCustomAttributes(true).FirstOrDefault(a => a is SaveWithName);
|
||||||
|
if (nameAttribute != null)
|
||||||
|
{
|
||||||
|
name = ((SaveWithName) nameAttribute).Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
object currentValue = null;
|
object currentValue = null;
|
||||||
var fail = false;
|
var fail = false;
|
||||||
var fieldInfo = member as FieldInfo;
|
var fieldInfo = member as FieldInfo;
|
||||||
|
@ -54,34 +155,35 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
break;
|
break;
|
||||||
case "Bit":
|
case "Bit":
|
||||||
var refBit = (Bit)currentValue;
|
var refBit = (Bit)currentValue;
|
||||||
ser.Sync(member.Name, ref refBit);
|
ser.Sync(name, ref refBit);
|
||||||
currentValue = refBit;
|
currentValue = refBit;
|
||||||
break;
|
break;
|
||||||
case "Boolean":
|
case "Boolean":
|
||||||
var refBool = (bool)currentValue;
|
var refBool = (bool)currentValue;
|
||||||
ser.Sync(member.Name, ref refBool);
|
ser.Sync(name, ref refBool);
|
||||||
currentValue = refBool;
|
currentValue = refBool;
|
||||||
break;
|
break;
|
||||||
case "Boolean[]":
|
case "Boolean[]":
|
||||||
{
|
{
|
||||||
var tmp = (bool[])currentValue;
|
var tmp = (bool[])currentValue;
|
||||||
ser.Sync(member.Name, ref tmp, false);
|
ser.Sync(name, ref tmp, false);
|
||||||
currentValue = tmp;
|
currentValue = tmp;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Byte":
|
case "Byte":
|
||||||
var refByte = (byte)currentValue;
|
var refByte = (byte)currentValue;
|
||||||
ser.Sync(member.Name, ref refByte);
|
ser.Sync(name, ref refByte);
|
||||||
currentValue = refByte;
|
currentValue = refByte;
|
||||||
break;
|
break;
|
||||||
case "Byte[]":
|
case "Byte[]":
|
||||||
refByteBuffer = new ByteBuffer((byte[])currentValue);
|
refByteBuffer = new ByteBuffer((byte[])currentValue);
|
||||||
ser.Sync(member.Name, ref refByteBuffer);
|
ser.Sync(name, ref refByteBuffer);
|
||||||
currentValue = refByteBuffer.Arr;
|
currentValue = refByteBuffer.Arr.Select(d => d).ToArray();
|
||||||
|
refByteBuffer.Dispose();
|
||||||
break;
|
break;
|
||||||
case "ByteBuffer":
|
case "ByteBuffer":
|
||||||
refByteBuffer = (ByteBuffer)currentValue;
|
refByteBuffer = (ByteBuffer)currentValue;
|
||||||
ser.Sync(member.Name, ref refByteBuffer);
|
ser.Sync(name, ref refByteBuffer);
|
||||||
currentValue = refByteBuffer;
|
currentValue = refByteBuffer;
|
||||||
break;
|
break;
|
||||||
case "Func`1":
|
case "Func`1":
|
||||||
|
@ -89,29 +191,30 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
break;
|
break;
|
||||||
case "Int16":
|
case "Int16":
|
||||||
var refInt16 = (short)currentValue;
|
var refInt16 = (short)currentValue;
|
||||||
ser.Sync(member.Name, ref refInt16);
|
ser.Sync(name, ref refInt16);
|
||||||
currentValue = refInt16;
|
currentValue = refInt16;
|
||||||
break;
|
break;
|
||||||
case "Int32":
|
case "Int32":
|
||||||
refInt32 = (int)currentValue;
|
refInt32 = (int)currentValue;
|
||||||
ser.Sync(member.Name, ref refInt32);
|
ser.Sync(name, ref refInt32);
|
||||||
currentValue = refInt32;
|
currentValue = refInt32;
|
||||||
break;
|
break;
|
||||||
case "Int32[]":
|
case "Int32[]":
|
||||||
refIntBuffer = new IntBuffer((int[])currentValue);
|
refIntBuffer = new IntBuffer((int[])currentValue);
|
||||||
ser.Sync(member.Name, ref refIntBuffer);
|
ser.Sync(name, ref refIntBuffer);
|
||||||
currentValue = refIntBuffer.Arr;
|
currentValue = refIntBuffer.Arr.Select(d => d).ToArray();
|
||||||
|
refIntBuffer.Dispose();
|
||||||
break;
|
break;
|
||||||
case "IntBuffer":
|
case "IntBuffer":
|
||||||
refIntBuffer = (IntBuffer)currentValue;
|
refIntBuffer = (IntBuffer)currentValue;
|
||||||
ser.Sync(member.Name, ref refIntBuffer);
|
ser.Sync(name, ref refIntBuffer);
|
||||||
currentValue = refIntBuffer;
|
currentValue = refIntBuffer;
|
||||||
break;
|
break;
|
||||||
case "Point":
|
case "Point":
|
||||||
refPointX = ((Point)currentValue).X;
|
refPointX = ((Point)currentValue).X;
|
||||||
refPointY = ((Point)currentValue).Y;
|
refPointY = ((Point)currentValue).Y;
|
||||||
ser.Sync(member.Name + "_X", ref refPointX);
|
ser.Sync(name + "_X", ref refPointX);
|
||||||
ser.Sync(member.Name + "_Y", ref refPointY);
|
ser.Sync(name + "_Y", ref refPointY);
|
||||||
currentValue = new Point(refPointX, refPointY);
|
currentValue = new Point(refPointX, refPointY);
|
||||||
break;
|
break;
|
||||||
case "Rectangle":
|
case "Rectangle":
|
||||||
|
@ -119,31 +222,32 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
refPointY = ((Rectangle)currentValue).Y;
|
refPointY = ((Rectangle)currentValue).Y;
|
||||||
var refRectWidth = ((Rectangle)currentValue).Width;
|
var refRectWidth = ((Rectangle)currentValue).Width;
|
||||||
var refRectHeight = ((Rectangle)currentValue).Height;
|
var refRectHeight = ((Rectangle)currentValue).Height;
|
||||||
ser.Sync(member.Name + "_X", ref refPointX);
|
ser.Sync(name + "_X", ref refPointX);
|
||||||
ser.Sync(member.Name + "_Y", ref refPointY);
|
ser.Sync(name + "_Y", ref refPointY);
|
||||||
ser.Sync(member.Name + "_Height", ref refRectHeight);
|
ser.Sync(name + "_Height", ref refRectHeight);
|
||||||
ser.Sync(member.Name + "_Width", ref refRectWidth);
|
ser.Sync(name + "_Width", ref refRectWidth);
|
||||||
currentValue = new Rectangle(refPointX, refPointY, refRectWidth, refRectHeight);
|
currentValue = new Rectangle(refPointX, refPointY, refRectWidth, refRectHeight);
|
||||||
break;
|
break;
|
||||||
case "SByte":
|
case "SByte":
|
||||||
var refSByte = (sbyte)currentValue;
|
var refSByte = (sbyte)currentValue;
|
||||||
ser.Sync(member.Name, ref refSByte);
|
ser.Sync(name, ref refSByte);
|
||||||
currentValue = refSByte;
|
currentValue = refSByte;
|
||||||
break;
|
break;
|
||||||
case "String":
|
case "String":
|
||||||
var refString = (string)currentValue;
|
var refString = (string)currentValue;
|
||||||
var refVal = new ByteBuffer(Encoding.GetBytes(refString));
|
var refVal = new ByteBuffer(Encoding.GetBytes(refString));
|
||||||
ser.Sync(member.Name, ref refVal);
|
ser.Sync(name, ref refVal);
|
||||||
currentValue = Encoding.GetString(refVal.Arr);
|
currentValue = Encoding.GetString(refVal.Arr);
|
||||||
|
refVal.Dispose();
|
||||||
break;
|
break;
|
||||||
case "UInt16":
|
case "UInt16":
|
||||||
var refUInt16 = (ushort)currentValue;
|
var refUInt16 = (ushort)currentValue;
|
||||||
ser.Sync(member.Name, ref refUInt16);
|
ser.Sync(name, ref refUInt16);
|
||||||
currentValue = refUInt16;
|
currentValue = refUInt16;
|
||||||
break;
|
break;
|
||||||
case "UInt32":
|
case "UInt32":
|
||||||
var refUInt32 = (uint)currentValue;
|
var refUInt32 = (uint)currentValue;
|
||||||
ser.Sync(member.Name, ref refUInt32);
|
ser.Sync(name, ref refUInt32);
|
||||||
currentValue = refUInt32;
|
currentValue = refUInt32;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -151,7 +255,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
if (t.IsEnum)
|
if (t.IsEnum)
|
||||||
{
|
{
|
||||||
refInt32 = (int)currentValue;
|
refInt32 = (int)currentValue;
|
||||||
ser.Sync(member.Name, ref refInt32);
|
ser.Sync(name, ref refInt32);
|
||||||
currentValue = refInt32;
|
currentValue = refInt32;
|
||||||
}
|
}
|
||||||
else if (t.IsArray)
|
else if (t.IsArray)
|
||||||
|
@ -159,7 +263,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
||||||
var currentValueArray = (Array) currentValue;
|
var currentValueArray = (Array) currentValue;
|
||||||
for (var i = 0; i < currentValueArray.Length; i++)
|
for (var i = 0; i < currentValueArray.Length; i++)
|
||||||
{
|
{
|
||||||
ser.BeginSection(string.Format("{0}_{1}", member.Name, i));
|
ser.BeginSection(string.Format("{0}_{1}", name, i));
|
||||||
SyncObject(ser, currentValueArray.GetValue(i));
|
SyncObject(ser, currentValueArray.GetValue(i));
|
||||||
ser.EndSection();
|
ser.EndSection();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,29 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
{
|
{
|
||||||
public sealed partial class Drive1541
|
public sealed partial class Drive1541
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private const long LEHMER_RNG_PRIME = 48271;
|
private const long LEHMER_RNG_PRIME = 48271;
|
||||||
|
[SaveState.SaveWithName("DiskDensityCounter")]
|
||||||
private int _diskDensityCounter; // density .. 16
|
private int _diskDensityCounter; // density .. 16
|
||||||
|
[SaveState.SaveWithName("DiskSupplementaryCounter")]
|
||||||
private int _diskSupplementaryCounter; // 0 .. 16
|
private int _diskSupplementaryCounter; // 0 .. 16
|
||||||
|
[SaveState.SaveWithName("DiskFluxReversalDetected")]
|
||||||
private bool _diskFluxReversalDetected;
|
private bool _diskFluxReversalDetected;
|
||||||
|
[SaveState.SaveWithName("DiskBitsRemainingInDataEntry")]
|
||||||
private int _diskBitsLeft;
|
private int _diskBitsLeft;
|
||||||
|
[SaveState.SaveWithName("DiskDataEntryIndex")]
|
||||||
private int _diskByteOffset;
|
private int _diskByteOffset;
|
||||||
|
[SaveState.SaveWithName("DiskDataEntry")]
|
||||||
private int _diskBits;
|
private int _diskBits;
|
||||||
|
[SaveState.SaveWithName("DiskCurrentCycle")]
|
||||||
private int _diskCycle;
|
private int _diskCycle;
|
||||||
|
[SaveState.SaveWithName("DiskDensityConfig")]
|
||||||
private int _diskDensity;
|
private int _diskDensity;
|
||||||
|
[SaveState.SaveWithName("PreviousCA1")]
|
||||||
private bool _previousCa1;
|
private bool _previousCa1;
|
||||||
|
[SaveState.SaveWithName("CountsBeforeRandomTransition")]
|
||||||
private int _countsBeforeRandomTransition;
|
private int _countsBeforeRandomTransition;
|
||||||
|
[SaveState.SaveWithName("CurrentRNG")]
|
||||||
private int _rngCurrent;
|
private int _rngCurrent;
|
||||||
|
|
||||||
// Lehmer RNG
|
// Lehmer RNG
|
||||||
|
@ -40,12 +51,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
if (_diskBitsLeft <= 0)
|
if (_diskBitsLeft <= 0)
|
||||||
{
|
{
|
||||||
_diskByteOffset++;
|
_diskByteOffset++;
|
||||||
if (_diskByteOffset == Disk.FLUX_ENTRIES_PER_TRACK)
|
if (_diskByteOffset == Disk.FluxEntriesPerTrack)
|
||||||
{
|
{
|
||||||
_diskByteOffset = 0;
|
_diskByteOffset = 0;
|
||||||
}
|
}
|
||||||
_diskBits = _trackImageData[_diskByteOffset];
|
_diskBits = _trackImageData[_diskByteOffset];
|
||||||
_diskBitsLeft = Disk.FLUX_BITS_PER_ENTRY;
|
_diskBitsLeft = Disk.FluxBitsPerEntry;
|
||||||
}
|
}
|
||||||
if ((_diskBits & 1) != 0)
|
if ((_diskBits & 1) != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,11 +8,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
{
|
{
|
||||||
public sealed partial class Drive1541 : IDisassemblable
|
public sealed partial class Drive1541 : IDisassemblable
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
IEnumerable<string> IDisassemblable.AvailableCpus
|
IEnumerable<string> IDisassemblable.AvailableCpus
|
||||||
{
|
{
|
||||||
get { yield return "Disk Drive 6502"; }
|
get { yield return "Disk Drive 6502"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SaveState.DoNotSave]
|
||||||
string IDisassemblable.Cpu
|
string IDisassemblable.Cpu
|
||||||
{
|
{
|
||||||
get { return "Disk Drive 6502"; }
|
get { return "Disk Drive 6502"; }
|
||||||
|
@ -21,6 +23,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SaveState.DoNotSave]
|
||||||
string IDisassemblable.PCRegisterName
|
string IDisassemblable.PCRegisterName
|
||||||
{
|
{
|
||||||
get { return "PC"; }
|
get { return "PC"; }
|
||||||
|
|
|
@ -13,28 +13,49 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
{
|
{
|
||||||
public sealed partial class Drive1541 : SerialPortDevice
|
public sealed partial class Drive1541 : SerialPortDevice
|
||||||
{
|
{
|
||||||
|
[SaveState.SaveWithName("Disk")]
|
||||||
private Disk _disk;
|
private Disk _disk;
|
||||||
|
[SaveState.SaveWithName("BitHistory")]
|
||||||
private int _bitHistory;
|
private int _bitHistory;
|
||||||
|
[SaveState.SaveWithName("BitsRemainingInLatchedByte")]
|
||||||
private int _bitsRemainingInLatchedByte;
|
private int _bitsRemainingInLatchedByte;
|
||||||
|
[SaveState.SaveWithName("Sync")]
|
||||||
private bool _sync;
|
private bool _sync;
|
||||||
|
[SaveState.SaveWithName("ByteReady")]
|
||||||
private bool _byteReady;
|
private bool _byteReady;
|
||||||
[SaveState.DoNotSave] private readonly int _driveCpuClockNum;
|
[SaveState.SaveWithName("DriveCpuClockNumerator")]
|
||||||
|
private readonly int _driveCpuClockNum;
|
||||||
|
[SaveState.SaveWithName("TrackNumber")]
|
||||||
private int _trackNumber;
|
private int _trackNumber;
|
||||||
|
[SaveState.SaveWithName("MotorEnabled")]
|
||||||
private bool _motorEnabled;
|
private bool _motorEnabled;
|
||||||
|
[SaveState.SaveWithName("LedEnabled")]
|
||||||
private bool _ledEnabled;
|
private bool _ledEnabled;
|
||||||
|
[SaveState.SaveWithName("MotorStep")]
|
||||||
private int _motorStep;
|
private int _motorStep;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
private int _via0PortBtemp;
|
private int _via0PortBtemp;
|
||||||
|
[SaveState.SaveWithName("CPU")]
|
||||||
private readonly MOS6502X _cpu;
|
private readonly MOS6502X _cpu;
|
||||||
|
[SaveState.SaveWithName("RAM")]
|
||||||
private readonly int[] _ram;
|
private readonly int[] _ram;
|
||||||
|
[SaveState.SaveWithName("VIA0")]
|
||||||
public readonly Via Via0;
|
public readonly Via Via0;
|
||||||
|
[SaveState.SaveWithName("VIA1")]
|
||||||
public readonly Via Via1;
|
public readonly Via Via1;
|
||||||
|
[SaveState.SaveWithName("SystemCpuClockNumerator")]
|
||||||
private readonly int _cpuClockNum;
|
private readonly int _cpuClockNum;
|
||||||
|
[SaveState.SaveWithName("SystemDriveCpuRatioDifference")]
|
||||||
private int _ratioDifference;
|
private int _ratioDifference;
|
||||||
|
[SaveState.SaveWithName("DriveLightOffTime")]
|
||||||
private int _driveLightOffTime;
|
private int _driveLightOffTime;
|
||||||
[SaveState.DoNotSave] private int[] _trackImageData = new int[1];
|
[SaveState.DoNotSave]
|
||||||
|
private int[] _trackImageData = new int[1];
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public Func<int> ReadIec = () => 0xFF;
|
public Func<int> ReadIec = () => 0xFF;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public Action DebuggerStep;
|
public Action DebuggerStep;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public readonly Chip23128 DriveRom;
|
public readonly Chip23128 DriveRom;
|
||||||
|
|
||||||
public Drive1541(int clockNum, int clockDen)
|
public Drive1541(int clockNum, int clockDen)
|
||||||
|
@ -191,7 +212,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
if (_disk != null)
|
if (_disk != null)
|
||||||
{
|
{
|
||||||
_trackImageData = _disk.GetDataForTrack(_trackNumber);
|
_trackImageData = _disk.GetDataForTrack(_trackNumber);
|
||||||
_diskBits = _trackImageData[_diskByteOffset] >> (Disk.FLUX_BITS_PER_ENTRY - _diskBitsLeft);
|
_diskBits = _trackImageData[_diskByteOffset] >> (Disk.FluxBitsPerEntry - _diskBitsLeft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
{
|
{
|
||||||
public sealed class SerialPort : IDriveLight
|
public sealed class SerialPort : IDriveLight
|
||||||
{
|
{
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public Func<bool> ReadMasterAtn = () => true;
|
public Func<bool> ReadMasterAtn = () => true;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public Func<bool> ReadMasterClk = () => true;
|
public Func<bool> ReadMasterClk = () => true;
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public Func<bool> ReadMasterData = () => true;
|
public Func<bool> ReadMasterData = () => true;
|
||||||
|
|
||||||
|
[SaveState.SaveWithName("Device")]
|
||||||
private SerialPortDevice _device;
|
private SerialPortDevice _device;
|
||||||
|
[SaveState.SaveWithName("Connected")]
|
||||||
private bool _connected;
|
private bool _connected;
|
||||||
|
|
||||||
public void HardReset()
|
public void HardReset()
|
||||||
|
@ -75,7 +80,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
_device.ReadMasterData = () => ReadMasterData();
|
_device.ReadMasterData = () => ReadMasterData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public bool DriveLightEnabled { get { return true; } }
|
public bool DriveLightEnabled { get { return true; } }
|
||||||
|
[SaveState.DoNotSave]
|
||||||
public bool DriveLightOn { get { return ReadDeviceLight(); } }
|
public bool DriveLightOn { get { return ReadDeviceLight(); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,50 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||||
{
|
{
|
||||||
public abstract class SerialPortDevice
|
public abstract class SerialPortDevice
|
||||||
{
|
{
|
||||||
public Func<bool> ReadMasterAtn;
|
[SaveState.DoNotSave]
|
||||||
public Func<bool> ReadMasterClk;
|
public Func<bool> ReadMasterAtn;
|
||||||
public Func<bool> ReadMasterData;
|
[SaveState.DoNotSave]
|
||||||
|
public Func<bool> ReadMasterClk;
|
||||||
public virtual void ExecutePhase()
|
[SaveState.DoNotSave]
|
||||||
{
|
public Func<bool> ReadMasterData;
|
||||||
}
|
|
||||||
|
public virtual void ExecutePhase()
|
||||||
public virtual void ExecuteDeferred(int cycles)
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
public virtual void ExecuteDeferred(int cycles)
|
||||||
public virtual void HardReset()
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
public virtual void HardReset()
|
||||||
public virtual bool ReadDeviceClk()
|
{
|
||||||
{
|
}
|
||||||
return true;
|
|
||||||
}
|
public virtual bool ReadDeviceClk()
|
||||||
|
{
|
||||||
public virtual bool ReadDeviceData()
|
return true;
|
||||||
{
|
}
|
||||||
return true;
|
|
||||||
}
|
public virtual bool ReadDeviceData()
|
||||||
|
{
|
||||||
public virtual bool ReadDeviceLight()
|
return true;
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}
|
public virtual bool ReadDeviceLight()
|
||||||
|
{
|
||||||
public virtual void SyncState(Serializer ser)
|
return false;
|
||||||
{
|
}
|
||||||
SaveState.SyncObject(ser, this);
|
|
||||||
}
|
public virtual void SyncState(Serializer ser)
|
||||||
}
|
{
|
||||||
}
|
SaveState.SyncObject(ser, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue