248 lines
7.5 KiB
C#
248 lines
7.5 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace EMU7800.Core
|
|
{
|
|
/// <summary>
|
|
/// A context for deserializing <see cref="MachineBase"/> objects.
|
|
/// </summary>
|
|
public class DeserializationContext
|
|
{
|
|
#region Fields
|
|
|
|
readonly BinaryReader _binaryReader;
|
|
|
|
#endregion
|
|
|
|
public bool ReadBoolean()
|
|
{
|
|
return _binaryReader.ReadBoolean();
|
|
}
|
|
|
|
public byte ReadByte()
|
|
{
|
|
return _binaryReader.ReadByte();
|
|
}
|
|
|
|
public ushort ReadUInt16()
|
|
{
|
|
return _binaryReader.ReadUInt16();
|
|
}
|
|
|
|
public int ReadInt32()
|
|
{
|
|
return _binaryReader.ReadInt32();
|
|
}
|
|
|
|
public uint ReadUInt32()
|
|
{
|
|
return _binaryReader.ReadUInt32();
|
|
}
|
|
|
|
public long ReadInt64()
|
|
{
|
|
return _binaryReader.ReadInt64();
|
|
}
|
|
|
|
public ulong ReadUInt64()
|
|
{
|
|
return _binaryReader.ReadUInt64();
|
|
}
|
|
|
|
public double ReadDouble()
|
|
{
|
|
return _binaryReader.ReadDouble();
|
|
}
|
|
|
|
/*
|
|
public BufferElement ReadBufferElement()
|
|
{
|
|
var be = new BufferElement();
|
|
for (var i = 0; i < BufferElement.SIZE; i++)
|
|
be[i] = ReadByte();
|
|
return be;
|
|
}
|
|
*/
|
|
|
|
public byte[] ReadBytes()
|
|
{
|
|
var count = _binaryReader.ReadInt32();
|
|
if (count <= 0)
|
|
return new byte[0];
|
|
if (count > 0x40000)
|
|
throw new Emu7800SerializationException("Byte array length too large.");
|
|
return _binaryReader.ReadBytes(count);
|
|
}
|
|
|
|
public byte[] ReadExpectedBytes(params int[] expectedSizes)
|
|
{
|
|
var count = _binaryReader.ReadInt32();
|
|
if (!expectedSizes.Any(t => t == count))
|
|
throw new Emu7800SerializationException("Byte array length incorrect.");
|
|
return _binaryReader.ReadBytes(count);
|
|
}
|
|
|
|
public byte[] ReadOptionalBytes(params int[] expectedSizes)
|
|
{
|
|
var hasBytes = _binaryReader.ReadBoolean();
|
|
return (hasBytes) ? ReadExpectedBytes(expectedSizes) : null;
|
|
}
|
|
|
|
public ushort[] ReadUnsignedShorts(params int[] expectedSizes)
|
|
{
|
|
var bytes = ReadExpectedBytes(expectedSizes.Select(t => t << 1).ToArray());
|
|
var ushorts = new ushort[bytes.Length >> 1];
|
|
Buffer.BlockCopy(bytes, 0, ushorts, 0, bytes.Length);
|
|
return ushorts;
|
|
}
|
|
|
|
public int[] ReadIntegers(params int[] expectedSizes)
|
|
{
|
|
var bytes = ReadExpectedBytes(expectedSizes.Select(t => t << 2).ToArray());
|
|
var integers = new int[bytes.Length >> 2];
|
|
Buffer.BlockCopy(bytes, 0, integers, 0, bytes.Length);
|
|
return integers;
|
|
}
|
|
|
|
public uint[] ReadUnsignedIntegers(params int[] expectedSizes)
|
|
{
|
|
var bytes = ReadExpectedBytes(expectedSizes.Select(t => t << 2).ToArray());
|
|
var uints = new uint[bytes.Length >> 2];
|
|
Buffer.BlockCopy(bytes, 0, uints, 0, bytes.Length);
|
|
return uints;
|
|
}
|
|
|
|
public bool[] ReadBooleans(params int[] expectedSizes)
|
|
{
|
|
var bytes = ReadExpectedBytes(expectedSizes);
|
|
var booleans = new bool[bytes.Length];
|
|
for (var i = 0; i < bytes.Length; i++)
|
|
booleans[i] = (bytes[i] != 0);
|
|
return booleans;
|
|
}
|
|
|
|
public int CheckVersion(params int[] validVersions)
|
|
{
|
|
var magicNumber = _binaryReader.ReadInt32();
|
|
if (magicNumber != 0x78000087)
|
|
throw new Emu7800SerializationException("Magic number not found.");
|
|
var version = _binaryReader.ReadInt32();
|
|
if (!validVersions.Any(t => t == version))
|
|
throw new Emu7800SerializationException("Invalid version number found.");
|
|
return version;
|
|
}
|
|
|
|
public MachineBase ReadMachine()
|
|
{
|
|
var typeName = _binaryReader.ReadString();
|
|
if (string.IsNullOrWhiteSpace(typeName))
|
|
throw new Emu7800SerializationException("Invalid type name.");
|
|
|
|
var type = Type.GetType(typeName);
|
|
if (type == null)
|
|
throw new Emu7800SerializationException("Unable to resolve type name: " + typeName);
|
|
|
|
return (MachineBase)Activator.CreateInstance(type, new object[] { this });
|
|
}
|
|
|
|
public AddressSpace ReadAddressSpace(MachineBase m, int addrSpaceShift, int pageShift)
|
|
{
|
|
var addressSpace = new AddressSpace(this, m, addrSpaceShift, pageShift);
|
|
return addressSpace;
|
|
}
|
|
|
|
public M6502 ReadM6502(MachineBase m, int runClocksMultiple)
|
|
{
|
|
var cpu = new M6502(this, m, runClocksMultiple);
|
|
return cpu;
|
|
}
|
|
|
|
public Maria ReadMaria(Machine7800 m, int scanlines)
|
|
{
|
|
var maria = new Maria(this, m, scanlines);
|
|
return maria;
|
|
}
|
|
|
|
public PIA ReadPIA(MachineBase m)
|
|
{
|
|
var pia = new PIA(this, m);
|
|
return pia;
|
|
}
|
|
|
|
public TIA ReadTIA(MachineBase m)
|
|
{
|
|
var tia = new TIA(this, m);
|
|
return tia;
|
|
}
|
|
|
|
public TIASound ReadTIASound(MachineBase m, int cpuClocksPerSample)
|
|
{
|
|
var tiaSound = new TIASound(this, m, cpuClocksPerSample);
|
|
return tiaSound;
|
|
}
|
|
|
|
public RAM6116 ReadRAM6116()
|
|
{
|
|
var ram6116 = new RAM6116(this);
|
|
return ram6116;
|
|
}
|
|
|
|
public InputState ReadInputState()
|
|
{
|
|
var inputState = new InputState(this);
|
|
return inputState;
|
|
}
|
|
|
|
public HSC7800 ReadOptionalHSC7800()
|
|
{
|
|
var exist = ReadBoolean();
|
|
return exist ? new HSC7800(this) : null;
|
|
}
|
|
|
|
public Bios7800 ReadOptionalBios7800()
|
|
{
|
|
var exist = ReadBoolean();
|
|
return exist ? new Bios7800(this) : null;
|
|
}
|
|
|
|
public PokeySound ReadOptionalPokeySound(MachineBase m)
|
|
{
|
|
var exist = ReadBoolean();
|
|
return exist ? new PokeySound(this, m) : null;
|
|
}
|
|
|
|
public Cart ReadCart(MachineBase m)
|
|
{
|
|
var typeName = _binaryReader.ReadString();
|
|
if (string.IsNullOrWhiteSpace(typeName))
|
|
throw new Emu7800SerializationException("Invalid type name.");
|
|
|
|
var type = Type.GetType(typeName);
|
|
if (type == null)
|
|
throw new Emu7800SerializationException("Unable to resolve type name: " + typeName);
|
|
|
|
return (Cart)Activator.CreateInstance(type, new object[] { this, m });
|
|
}
|
|
|
|
#region Constructors
|
|
|
|
private DeserializationContext()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Instantiates a new instance of <see cref="DeserializationContext"/>.
|
|
/// </summary>
|
|
/// <param name="binaryReader"/>
|
|
internal DeserializationContext(BinaryReader binaryReader)
|
|
{
|
|
if (binaryReader == null)
|
|
throw new ArgumentNullException("binaryReader");
|
|
_binaryReader = binaryReader;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|