public static TAPFile Load(string FileName) { TAPFile file = new TAPFile(); byte[] data = File.ReadAllBytes(FileName); List <TAPBlock> blocks = new List <TAPBlock>(); int pos = 0; while (pos < data.Length) { TAPBlock block = TAPBlock.LoadBlock(data, pos, out pos); if (block == null) { return(null); } blocks.Add(block); } byte[] basicLoader = null; while (blocks.Count > 0) { if (blocks.Count < 2) { return(null); } TAPBlock headerBlock = blocks[0]; blocks.RemoveAt(0); TAPBlock dataBlock = blocks[0]; blocks.RemoveAt(0); if (!headerBlock.IsHeader || dataBlock.IsHeader || !headerBlock.IsValid || !dataBlock.IsValid) { return(null); } TAPHeader realHeader = headerBlock.GetHeader(); byte[] realData = dataBlock.GetData(); if (realHeader.Type == TAPSpectrumDataType.Program) { if (basicLoader != null) { return(null); } basicLoader = realData; } else if (realHeader.Type == TAPSpectrumDataType.Code) { if (realHeader.Length != realData.Length) { return(null); } Buffer.BlockCopy(realData, 0, file.Data, realHeader.Param1, realData.Length); if (realHeader.Param1 < file.StartAddress) { file.StartAddress = realHeader.Param1; } if (realHeader.Param1 + realData.Length > file.EndAddress) { file.EndAddress = realHeader.Param1 + realData.Length; } } else { return(null); } } if (basicLoader == null) { return(null); } file.Header = FindEntryPoint(basicLoader); if (file.Header == null) { return(null); } return(file); }
public ZXSerialLoaderResult LoadFile(string SerialPort, string FileName, int BlockSize, Action <int> Progress) { string ext = Path.GetExtension(FileName).ToLower(); SpectrumFile program; switch (ext) { case ".hex": program = HEXFile.Load(FileName); break; case ".sna": program = SNAFile.Load(FileName); break; case ".z80": program = Z80File.Load(FileName); break; case ".tap": program = TAPFile.Load(FileName); break; default: return(ZXSerialLoaderResult.Unsupported); } if (program == null) { return(ZXSerialLoaderResult.FileError); } try { string dvResponse; using (SerialPort serial = new SerialPort(SerialPort, serialSpeed, Parity.None, 8, StopBits.One)) { serial.Open(); serial.ReadTimeout = 5000; serial.WriteTimeout = 5000; serial.Write(program.Operation); if ((dvResponse = serial.ReadLine()) != "RDY") { return(ZXSerialLoaderResult.UnknownResponse); } if (program.Header != null) { serial.Write(program.Header, 0, program.Header.Length); } int pos = program.StartAddress; bool finished = false; double passPercent = BlockSize * 100 / (program.EndAddress - program.StartAddress); double currentPercent = 0; while (pos < program.EndAddress) { int segLen = Math.Min(BlockSize, program.EndAddress - pos); byte[] tmpBuffer = new byte[2]; if (pos + segLen >= program.EndAddress) //Is last segment? { finished = true; tmpBuffer[0] = 1; } serial.Write(tmpBuffer, 0, 1); //Send last segment tmpBuffer[0] = (byte)(pos & 0xFF); tmpBuffer[1] = (byte)((pos >> 8) & 0xFF); serial.Write(tmpBuffer, 0, 2); //Send segment address tmpBuffer[0] = (byte)(segLen & 0xFF); tmpBuffer[1] = (byte)((segLen >> 8) & 0xFF); serial.Write(tmpBuffer, 0, 2); //Send segment size if ((dvResponse = serial.ReadLine()) != "OK") { return(ZXSerialLoaderResult.UnknownResponse); } //Send segment serial.Write(program.Data, pos, segLen); //Wait for acknowledge if (!finished) { if ((dvResponse = serial.ReadLine()) != "NEXT") { return(ZXSerialLoaderResult.UnknownResponse); } } currentPercent += passPercent; if (Progress != null) { Progress((int)Math.Min(100, currentPercent)); } pos += segLen; } if (Progress != null) { Progress(1000); } Console.WriteLine(serial.ReadLine()); if (Progress != null) { Progress(2000); } Console.WriteLine(serial.ReadLine()); if (Progress != null) { Progress(3000); } serial.Close(); return(ZXSerialLoaderResult.Success); } } catch { return(ZXSerialLoaderResult.SerialPortError); } }