BizHawk/EMU7800/Core/DeserializationContext.cs

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
}
}