private void save_SPCR(Stream stream, ZXST_Header header) { StreamHelper.Write(stream, Encoding.ASCII.GetBytes("SPCR")); int size = 8; StreamHelper.Write(stream, size); var ula = _spec.BusManager.FindDevice <IUlaDevice>(); var memory = _spec.BusManager.FindDevice <IMemoryDevice>(); byte cmr0 = memory.CMR0; byte cmr1 = memory.CMR1; switch (header.MachineId) { case SzxModelId.ZXSTMID_16K: case SzxModelId.ZXSTMID_48K: cmr0 = 0x30; cmr1 = 0x00; break; } StreamHelper.Write(stream, (byte)(ula.PortFE & 7)); // chBorder StreamHelper.Write(stream, (byte)(cmr0)); // ch7ffd StreamHelper.Write(stream, (byte)(cmr1)); // ch1ffd TODO: port 1ffd/effd StreamHelper.Write(stream, (byte)(ula.PortFE & 0xF8)); // chFe StreamHelper.Write(stream, new byte[4]); // chReserved[4] }
/// <summary> /// ZXSTSPECREGS - The Spectrum's ULA state specifying the current border colour, memory paging status etc. /// </summary> #endregion private void apply_SPCR(byte[] data, ZXST_Header header) { int offset = 0; byte chBorder = data[offset]; offset += 1; byte ch7ffd = data[offset]; offset += 1; byte ch1ffd = data[offset]; offset += 1; // #1ffd/#effd byte chFe = data[offset]; offset += 1; // Only bits 3 and 4 (the MIC and EAR bits) are guaranteed to be valid. //byte[] chReserved = new byte[4]; //for (int i = 0; i < 4; i++) // chReserved[i] = data[i + offset]; byte pFE = (byte)((chFe & 0xF8) | (chBorder & 7)); var ula = _spec.BusManager.FindDevice <IUlaDevice>(); var memory = _spec.BusManager.FindDevice <IMemoryDevice>(); ula.PortFE = pFE; switch (header.MachineId) { case SzxModelId.ZXSTMID_16K: case SzxModelId.ZXSTMID_48K: memory.CMR0 = 0x30; memory.CMR1 = 0; break; default: memory.CMR0 = ch7ffd; memory.CMR1 = ch1ffd; break; } }
private void saveToStream(Stream stream) { var header = new ZXST_Header(); // very ugly, because there is no option for custom configuration machine var memory = _spec.BusManager.FindDevice <IMemoryDevice>(); header.MachineId = GetModelId(_spec.BusManager.ModelId); if (header.MachineId == SzxModelId.ZXSTMID_CUSTOM) { if (memory.RamPages.Length == 8) { header.MachineId = SzxModelId.ZXSTMID_PENTAGON128; } else if (memory.IsMap48) { header.MachineId = SzxModelId.ZXSTMID_48K; } } var ula = _spec.BusManager.FindDevice <IUlaDevice>(); if (ula.IsEarlyTimings) { header.Flags = (byte)(header.Flags & ~ZXSTMF_ALTERNATETIMINGS); } header.Serialize(stream); save_CRTR(stream); save_Z80R(stream); save_SPCR(stream, header); switch (header.MachineId) { case SzxModelId.ZXSTMID_16K: save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]); break; case SzxModelId.ZXSTMID_48K: save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]); save_RAMP(stream, 2, memory.RamPages[memory.Map48[2]]); save_RAMP(stream, 0, memory.RamPages[memory.Map48[3]]); break; default: for (int i = 0; i < memory.RamPages.Length; i++) { save_RAMP(stream, (byte)i, memory.RamPages[i]); } break; } save_AY(stream); save_B128(stream); }
public bool LoadSZX(Stream fs) { for (int f = 0; f < 16; f++) { RAM_BANK[f] = new byte[8192]; } using (BinaryReader r = new BinaryReader(fs)) { int bytesToRead = (int)fs.Length; byte[] buffer = new byte[bytesToRead]; int bytesRead = r.Read(buffer, 0, bytesToRead); if (bytesRead == 0) { return(false); //something bad happened! } GCHandle pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); //Read in the szx header to begin proceedings header = (ZXST_Header)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(), typeof(ZXST_Header)); if (header.MajorVersion != 1) { pinnedBuffer.Free(); return(false); } string formatName = GetID(header.Magic); int bufferCounter = Marshal.SizeOf(header); while (bufferCounter < bytesRead) { //Read the block info ZXST_Block block = (ZXST_Block)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_Block)); bufferCounter += Marshal.SizeOf(block); string blockID = GetID(block.Id); switch (blockID) { case "SPCR": //Read the ZXST_SpecRegs structure specRegs = (ZXST_SpecRegs)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_SpecRegs)); break; case "Z80R": //Read the ZXST_SpecRegs structure z80Regs = (ZXST_Z80Regs)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_Z80Regs)); break; case "KEYB": //Read the ZXST_SpecRegs structure keyboard = (ZXST_Keyboard)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_Keyboard)); break; case "AY\0\0": ayState = (ZXST_AYState)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_AYState)); break; case "+3\0\0": plus3Disk = (ZXST_Plus3Disk)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_Plus3Disk)); numDrivesPresent = plus3Disk.numDrives; plus3DiskFile = new ZXST_DiskFile[plus3Disk.numDrives]; externalDisk = new String[plus3Disk.numDrives]; InsertDisk = new bool[plus3Disk.numDrives]; break; case "DSK\0": ZXST_DiskFile df = (ZXST_DiskFile)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_DiskFile)); plus3DiskFile[df.driveNum] = df; InsertDisk[df.driveNum] = true; int offset2 = bufferCounter + Marshal.SizeOf(df); char[] file = new char[df.uncompressedSize]; Array.Copy(buffer, offset2, file, 0, df.uncompressedSize); //leave out the \0 terminator externalDisk[df.driveNum] = new String(file); break; case "TAPE": tape = (ZXST_Tape)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_Tape)); InsertTape = true; //Embedded tape file if ((tape.flags & 1) != 0) { int offset = bufferCounter + Marshal.SizeOf(tape); //Compressed? if ((tape.flags & 2) != 0) { MemoryStream compressedData = new MemoryStream(buffer, offset, tape.compressedSize); MemoryStream uncompressedData = new MemoryStream(); using (ZInputStream zipStream = new ZInputStream(compressedData)) { byte[] tempBuffer = new byte[2048]; int bytesUnzipped = 0; while ((bytesUnzipped = zipStream.read(tempBuffer, 0, 2048)) > 0) { uncompressedData.Write(tempBuffer, 0, bytesUnzipped); } embeddedTapeData = uncompressedData.ToArray(); compressedData.Close(); uncompressedData.Close(); } } else { embeddedTapeData = new byte[tape.compressedSize]; Array.Copy(buffer, offset, embeddedTapeData, 0, tape.compressedSize); } } else //external tape file { int offset = bufferCounter + Marshal.SizeOf(tape); char[] file2 = new char[tape.compressedSize - 1]; Array.Copy(buffer, offset, file2, 0, tape.compressedSize - 1); //leave out the \0 terminator externalTapeFile = new String(file2); } break; case "RAMP": //Read the ZXST_SpecRegs structure ZXST_RAMPage ramPages = (ZXST_RAMPage)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_RAMPage)); if (ramPages.wFlags == ZXSTRF_COMPRESSED) { int offset = bufferCounter + Marshal.SizeOf(ramPages); int compressedSize = ((int)block.Size - (Marshal.SizeOf(ramPages)));// - Marshal.SizeOf(block) - 1 )); MemoryStream compressedData = new MemoryStream(buffer, offset, compressedSize); MemoryStream uncompressedData = new MemoryStream(); using (ZInputStream zipStream = new ZInputStream(compressedData)) { byte[] tempBuffer = new byte[2048]; int bytesUnzipped = 0; while ((bytesUnzipped = zipStream.read(tempBuffer, 0, 2048)) > 0) { uncompressedData.Write(tempBuffer, 0, bytesUnzipped); } byte[] pageData = uncompressedData.ToArray(); { Array.Copy(pageData, 0, RAM_BANK[ramPages.chPageNo * 2], 0, 8192); Array.Copy(pageData, 0 + 8192, RAM_BANK[ramPages.chPageNo * 2 + 1], 0, 8192); } compressedData.Close(); uncompressedData.Close(); } } else { int bufferOffset = bufferCounter + Marshal.SizeOf(ramPages); { Array.Copy(buffer, bufferOffset, RAM_BANK[ramPages.chPageNo * 2], 0, 8192); Array.Copy(buffer, bufferOffset + 8192, RAM_BANK[ramPages.chPageNo * 2 + 1], 0, 8192); } } break; case "PLTT": palette = (ZXST_PaletteBlock)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferCounter), typeof(ZXST_PaletteBlock)); paletteLoaded = true; break; default: //unrecognised block, so skip to next break; } bufferCounter += (int)block.Size; //Move to next block } pinnedBuffer.Free(); return(true); } }
private void save_SPCR(Stream stream, ZXST_Header header) { StreamHelper.Write(stream, Encoding.ASCII.GetBytes("SPCR")); int size = 8; StreamHelper.Write(stream, size); var ula = _spec.BusManager.FindDevice<IUlaDevice>(); var memory = _spec.BusManager.FindDevice<IMemoryDevice>(); byte cmr0 = memory.CMR0; byte cmr1 = memory.CMR1; switch (header.MachineId) { case MachineId.ZXSTMID_16K: case MachineId.ZXSTMID_48K: cmr0 = 0x30; cmr1 = 0x00; break; } StreamHelper.Write(stream, (byte)(ula.PortFE&7)); // chBorder StreamHelper.Write(stream, (byte)(cmr0)); // ch7ffd StreamHelper.Write(stream, (byte)(cmr1)); // ch1ffd TODO: port 1ffd/effd StreamHelper.Write(stream, (byte)(ula.PortFE & 0xF8)); // chFe StreamHelper.Write(stream, new byte[4]); // chReserved[4] }
private void saveToStream(Stream stream) { var header = new ZXST_Header(); // very ugly, because there is no option for custom configuration machine var memory = _spec.BusManager.FindDevice<IMemoryDevice>(); header.MachineId = MachineId.ZXSTMID_128K; if (memory is ZXMAK2.Hardware.Spectrum.MemoryPlus3) { header.MachineId = MachineId.ZXSTMID_PLUS3; } else if (memory.RamPages.Length != 8) { header.MachineId = MachineId.ZXSTMID_PENTAGON1024; if (memory is ZXMAK2.Hardware.Pentagon.MemoryPentagon512) header.MachineId = MachineId.ZXSTMID_PENTAGON512; else if (memory is ZXMAK2.Hardware.Pentagon.MemoryPentagon1024) header.MachineId = MachineId.ZXSTMID_PENTAGON1024; else if (memory is ZXMAK2.Hardware.Scorpion.MemoryScorpion1024) header.MachineId = MachineId.ZXSTMID_PENTAGON1024; else if (memory is ZXMAK2.Hardware.Scorpion.MemoryScorpion256) header.MachineId = MachineId.ZXSTMID_SCORPION; } else if (memory.IsMap48) { header.MachineId = MachineId.ZXSTMID_48K; } var ula = _spec.BusManager.FindDevice<IUlaDevice>(); if (ula.GetType() == typeof(ZXMAK2.Hardware.Spectrum.UlaSpectrum48_Early) || ula.GetType() == typeof(ZXMAK2.Hardware.Spectrum.UlaSpectrum128_Early)) { header.Flags = (byte)(header.Flags & ~ZXSTMF_ALTERNATETIMINGS); } header.Serialize(stream); save_CRTR(stream); save_Z80R(stream); save_SPCR(stream, header); switch (header.MachineId) { case MachineId.ZXSTMID_16K: save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]); break; case MachineId.ZXSTMID_48K: save_RAMP(stream, 5, memory.RamPages[memory.Map48[1]]); save_RAMP(stream, 2, memory.RamPages[memory.Map48[2]]); save_RAMP(stream, 0, memory.RamPages[memory.Map48[3]]); break; default: for (int i = 0; i < memory.RamPages.Length; i++) save_RAMP(stream, (byte)i, memory.RamPages[i]); break; } save_AY(stream); save_B128(stream); }
private void loadFromStream(Stream stream) { ZXST_Header header = new ZXST_Header(); header.Deserialize(stream); if (header.MajorVersion != 1) throw new NotSupportedException(string.Format("Sorry, but MajorVersion={0} is not supported", header.MajorVersion)); //int num = 0; InitStd128K(); bool eof = false; do { byte[] data = new byte[8]; eof |= stream.Read(data, 0, data.Length) != data.Length; UInt32 id = BitConverter.ToUInt32(data, 0); UInt32 size = BitConverter.ToUInt32(data, 4); data = new byte[size]; eof |= stream.Read(data, 0, data.Length) != data.Length; if (!eof) { string strId = Encoding.ASCII.GetString(BitConverter.GetBytes(id)); //using (FileStream fs = new FileStream((num++).ToString("D2")+"_" + strId.Replace('\0', '_') + ".block", FileMode.Create, FileAccess.Write, FileShare.Read)) // fs.Write(data, 0, data.Length); switch (strId) { case "Z80R": apply_Z80R(data); break; case "SPCR": apply_SPCR(data, header); break; case "AY\0\0": apply_AY(data); break; case "RAMP": apply_RAMP(data); break; case "B128": applyB128(data); break; //case "KEYB": // break; default: //LogAgent.Info("SzxSerializer: skip block '{0}' (unsupported)", strId); break; } } } while (!eof); }
private void apply_SPCR(byte[] data, ZXST_Header header) { int offset = 0; byte chBorder = data[offset]; offset += 1; byte ch7ffd = data[offset]; offset += 1; byte ch1ffd = data[offset]; offset += 1; // #1ffd/#effd byte chFe = data[offset]; offset += 1; // Only bits 3 and 4 (the MIC and EAR bits) are guaranteed to be valid. //byte[] chReserved = new byte[4]; //for (int i = 0; i < 4; i++) // chReserved[i] = data[i + offset]; byte pFE = (byte)((chFe & 0xF8) | (chBorder & 7)); var ula = _spec.BusManager.FindDevice<IUlaDevice>(); var memory = _spec.BusManager.FindDevice<IMemoryDevice>(); ula.PortFE = pFE; switch(header.MachineId) { case MachineId.ZXSTMID_16K: case MachineId.ZXSTMID_48K: memory.CMR0 = 0x30; memory.CMR1 = 0; break; default: memory.CMR0 = ch7ffd; memory.CMR1 = ch1ffd; break; } }
private void loadFromStream(Stream stream) { ZXST_Header header = new ZXST_Header(); header.Deserialize(stream); if (header.MajorVersion != 1) { throw new NotSupportedException(string.Format("Sorry, but MajorVersion={0} is not supported", header.MajorVersion)); } //int num = 0; InitStd128K(); bool eof = false; do { byte[] data = new byte[8]; eof |= stream.Read(data, 0, data.Length) != data.Length; UInt32 id = BitConverter.ToUInt32(data, 0); UInt32 size = BitConverter.ToUInt32(data, 4); data = new byte[size]; eof |= stream.Read(data, 0, data.Length) != data.Length; if (!eof) { string strId = Encoding.ASCII.GetString(BitConverter.GetBytes(id)); //using (FileStream fs = new FileStream((num++).ToString("D2")+"_" + strId.Replace('\0', '_') + ".block", FileMode.Create, FileAccess.Write, FileShare.Read)) // fs.Write(data, 0, data.Length); switch (strId) { case "Z80R": apply_Z80R(data); break; case "SPCR": apply_SPCR(data, header); break; case "AY\0\0": apply_AY(data); break; case "RAMP": apply_RAMP(data); break; case "B128": applyB128(data); break; //case "KEYB": // break; default: //LogAgent.Info("SzxSerializer: skip block '{0}' (unsupported)", strId); break; } } }while (!eof); }