using System; using System.IO; using System.Linq; namespace EMU7800.Core { /// /// A context for deserializing objects. /// 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() { } /// /// Instantiates a new instance of . /// /// internal DeserializationContext(BinaryReader binaryReader) { if (binaryReader == null) throw new ArgumentNullException("binaryReader"); _binaryReader = binaryReader; } #endregion } }