C64: Faster loading savestates. Also fix input not working after loading state.
This commit is contained in:
parent
43ac625a95
commit
a06dd5f768
|
@ -102,22 +102,22 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
|||
{
|
||||
case C64.VicType.Ntsc:
|
||||
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);
|
||||
break;
|
||||
case C64.VicType.Pal:
|
||||
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);
|
||||
break;
|
||||
case C64.VicType.NtscOld:
|
||||
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);
|
||||
break;
|
||||
case C64.VicType.Drean:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -89,6 +89,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
|||
return !_restorePressed && Cia1.ReadIrq() && CartPort.ReadNmi();
|
||||
}
|
||||
|
||||
private bool[] Input_ReadJoysticks()
|
||||
{
|
||||
return _joystickPressed;
|
||||
}
|
||||
|
||||
private bool[] Input_ReadKeyboard()
|
||||
{
|
||||
return _keyboardPressed;
|
||||
}
|
||||
|
||||
private bool Pla_ReadCharen()
|
||||
{
|
||||
return (Cpu.PortData & 0x04) != 0;
|
||||
|
|
|
@ -286,8 +286,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
|
|||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
SaveState.SyncDeltaBytes("MediaStateA", ser, _originalMediaA, ref _banksA);
|
||||
SaveState.SyncDeltaBytes("MediaStateB", ser, _originalMediaB, ref _banksB);
|
||||
SaveState.SyncDelta("MediaStateA", ser, _originalMediaA, ref _banksA);
|
||||
SaveState.SyncDelta("MediaStateB", ser, _originalMediaB, ref _banksB);
|
||||
base.SyncState(ser);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
}
|
||||
}
|
||||
|
||||
public static Cia Create(C64.CiaType type, bool[] keyboard, bool[] joysticks)
|
||||
public static Cia Create(C64.CiaType type, Func<bool[]> keyboard, Func<bool[]> joysticks)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
|
|
@ -36,37 +36,40 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
{
|
||||
[SaveState.DoNotSave] private int _ret;
|
||||
[SaveState.DoNotSave] private int _tst;
|
||||
[SaveState.DoNotSave] private readonly bool[] _joyData;
|
||||
[SaveState.DoNotSave] private readonly bool[] _keyData;
|
||||
[SaveState.DoNotSave] private readonly Func<bool[]> _readJoyData;
|
||||
[SaveState.DoNotSave] private readonly Func<bool[]> _readKeyData;
|
||||
|
||||
public JoystickKeyboardPort(bool[] joyData, bool[] keyData)
|
||||
public JoystickKeyboardPort(Func<bool[]> readJoyData, Func<bool[]> readKeyData)
|
||||
{
|
||||
_joyData = joyData;
|
||||
_keyData = keyData;
|
||||
_readJoyData = readJoyData;
|
||||
_readKeyData = readKeyData;
|
||||
}
|
||||
|
||||
private int GetJoystick1()
|
||||
{
|
||||
var joyData = _readJoyData();
|
||||
return 0xE0 |
|
||||
(_joyData[0] ? 0x00 : 0x01) |
|
||||
(_joyData[1] ? 0x00 : 0x02) |
|
||||
(_joyData[2] ? 0x00 : 0x04) |
|
||||
(_joyData[3] ? 0x00 : 0x08) |
|
||||
(_joyData[4] ? 0x00 : 0x10);
|
||||
(joyData[0] ? 0x00 : 0x01) |
|
||||
(joyData[1] ? 0x00 : 0x02) |
|
||||
(joyData[2] ? 0x00 : 0x04) |
|
||||
(joyData[3] ? 0x00 : 0x08) |
|
||||
(joyData[4] ? 0x00 : 0x10);
|
||||
}
|
||||
|
||||
private int GetJoystick2()
|
||||
{
|
||||
var joyData = _readJoyData();
|
||||
return 0xE0 |
|
||||
(_joyData[5] ? 0x00 : 0x01) |
|
||||
(_joyData[6] ? 0x00 : 0x02) |
|
||||
(_joyData[7] ? 0x00 : 0x04) |
|
||||
(_joyData[8] ? 0x00 : 0x08) |
|
||||
(_joyData[9] ? 0x00 : 0x10);
|
||||
(joyData[5] ? 0x00 : 0x01) |
|
||||
(joyData[6] ? 0x00 : 0x02) |
|
||||
(joyData[7] ? 0x00 : 0x04) |
|
||||
(joyData[8] ? 0x00 : 0x08) |
|
||||
(joyData[9] ? 0x00 : 0x10);
|
||||
}
|
||||
|
||||
private int GetKeyboardRows(int activeColumns)
|
||||
{
|
||||
var keyData = _readKeyData();
|
||||
var result = 0xFF;
|
||||
for (var r = 0; r < 8; r++)
|
||||
{
|
||||
|
@ -75,7 +78,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
var i = r << 3;
|
||||
for (var c = 0; c < 8; c++)
|
||||
{
|
||||
if (_keyData[i++])
|
||||
if (keyData[i++])
|
||||
{
|
||||
result &= ~(1 << c);
|
||||
}
|
||||
|
@ -88,6 +91,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
|
||||
private int GetKeyboardColumns(int activeRows)
|
||||
{
|
||||
var keyData = _readKeyData();
|
||||
var result = 0xFF;
|
||||
for (var c = 0; c < 8; c++)
|
||||
{
|
||||
|
@ -96,7 +100,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
var i = c;
|
||||
for (var r = 0; r < 8; r++)
|
||||
{
|
||||
if (_keyData[i])
|
||||
if (keyData[i])
|
||||
{
|
||||
result &= ~(1 << r);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
_todDen = todDen;
|
||||
}
|
||||
|
||||
public Cia(int todNum, int todDen, bool[] keyboard, bool[] joysticks) : this(todNum, todDen)
|
||||
public Cia(int todNum, int todDen, Func<bool[]> keyboard, Func<bool[]> joysticks) : this(todNum, todDen)
|
||||
{
|
||||
_port = new JoystickKeyboardPort(joysticks, keyboard);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
|||
[SaveState.DoNotSave] public const int FluxBitsPerEntry = 32;
|
||||
[SaveState.DoNotSave] public const int FluxBitsPerTrack = 16000000 / 5;
|
||||
[SaveState.DoNotSave] public const int FluxEntriesPerTrack = FluxBitsPerTrack/FluxBitsPerEntry;
|
||||
[SaveState.DoNotSave] private readonly List<int[]> _tracks;
|
||||
[SaveState.DoNotSave] private int[][] _tracks;
|
||||
[SaveState.DoNotSave] private readonly int[] _originalMedia;
|
||||
[SaveState.DoNotSave] public bool Valid;
|
||||
|
||||
|
@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
|||
/// </summary>
|
||||
public Disk(int trackCapacity)
|
||||
{
|
||||
_tracks = new List<int[]>(trackCapacity);
|
||||
_tracks = new int[trackCapacity][];
|
||||
FillMissingTracks();
|
||||
_originalMedia = SerializeTracks(_tracks);
|
||||
Valid = true;
|
||||
|
@ -35,7 +35,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
|||
/// <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)
|
||||
{
|
||||
_tracks = Enumerable.Repeat<int[]>(null, trackCapacity).ToList();
|
||||
_tracks = new int[trackCapacity][];
|
||||
for (var i = 0; i < trackData.Count; i++)
|
||||
{
|
||||
_tracks[trackNumbers[i]] = ConvertToFluxTransitions(trackDensities[i], trackData[i], 0);
|
||||
|
@ -82,7 +82,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
|||
|
||||
private void FillMissingTracks()
|
||||
{
|
||||
for (var i = 0; i < _tracks.Count; i++)
|
||||
for (var i = 0; i < _tracks.Length; i++)
|
||||
{
|
||||
if (_tracks[i] == null)
|
||||
{
|
||||
|
@ -99,36 +99,44 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
|||
/// <summary>
|
||||
/// Combine the tracks into a single bitstream.
|
||||
/// </summary>
|
||||
private int[] SerializeTracks(IEnumerable<int[]> tracks)
|
||||
private int[] SerializeTracks(int[][] tracks)
|
||||
{
|
||||
return tracks.SelectMany(t => t).ToArray();
|
||||
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 IEnumerable<int[]> DeserializeTracks(int[] data)
|
||||
private int[][] DeserializeTracks(int[] data)
|
||||
{
|
||||
var trackCount = data.Length/FluxEntriesPerTrack;
|
||||
var result = new int[trackCount][];
|
||||
for (var i = 0; i < trackCount; i++)
|
||||
{
|
||||
yield return data.Skip(i*FluxEntriesPerTrack).Take(FluxEntriesPerTrack).ToArray();
|
||||
result[i] = new int[FluxEntriesPerTrack];
|
||||
Array.Copy(data, i * FluxEntriesPerTrack, result[i], 0, FluxEntriesPerTrack);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
if (ser.IsReader)
|
||||
{
|
||||
var mediaState = new int[_originalMedia.Length];
|
||||
SaveState.SyncDeltaInts("MediaState", ser, _originalMedia, ref mediaState);
|
||||
_tracks.Clear();
|
||||
_tracks.AddRange(DeserializeTracks(mediaState));
|
||||
SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState);
|
||||
_tracks = DeserializeTracks(mediaState);
|
||||
}
|
||||
else if (ser.IsWriter)
|
||||
{
|
||||
var mediaState = SerializeTracks(_tracks);
|
||||
SaveState.SyncDeltaInts("MediaState", ser, _originalMedia, ref mediaState);
|
||||
SaveState.SyncDelta("MediaState", ser, _originalMedia, ref mediaState);
|
||||
}
|
||||
SaveState.SyncObject(ser, this);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
@ -38,31 +40,72 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
|||
return delta;
|
||||
}
|
||||
|
||||
public static void SyncDeltaBytes(string name, Serializer ser, int[] source, ref int[] data)
|
||||
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)
|
||||
{
|
||||
byte[] delta = null;
|
||||
if (ser.IsWriter && data != null)
|
||||
{
|
||||
delta = GetDelta(source, data).Select(d => unchecked((byte)d)).ToArray();
|
||||
delta = CompressInts(GetDelta(source, data));
|
||||
}
|
||||
ser.Sync(name, ref delta, false);
|
||||
if (ser.IsReader && delta != null)
|
||||
{
|
||||
data = GetDelta(source, delta.Select(d => (int)d).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static void SyncDeltaInts(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);
|
||||
data = GetDelta(source, DecompressInts(delta));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue