private static void CheckRAMAdapter(IFamicomDumperConnectionExt dumper) { // Just simple test that RAM adapter is connected bool ramAdapterPresent = true; dumper.WriteCpu(0x4023, 0x01); // enable disk registers dumper.WriteCpu(0x4026, 0x00); dumper.WriteCpu(0x4025, 0b00100110); // reset dumper.WriteCpu(0x0000, 0xFF); // to prevent open bus read var ext = dumper.ReadCpu(0x4033); if (ext != 0x00) { ramAdapterPresent = false; } dumper.WriteCpu(0x4026, 0xFF); dumper.WriteCpu(0x0000, 0x00); // to prevent open bus read ext = dumper.ReadCpu(0x4033); if ((ext & 0x7F) != 0x7F) { ramAdapterPresent = false; } if (!ramAdapterPresent) { throw new IOException("RAM adapter IO error, is it connected?"); } }
public override Task <ReadResponse> ReadCpu(ReadRequest request, ServerCallContext context) { var result = new ReadResponse(); try { if (request.Length > 1) { Console.Write($"Reading 0x{request.Address:X4}-0x{request.Address + request.Length - 1:X4} @ CPU... "); } else { Console.Write($"Reading 0x{request.Address:X4} @ CPU... "); } byte[] data; if (request.HasLength) { data = dumper.ReadCpu((ushort)request.Address, (ushort)request.Length); } else { data = new byte[] { dumper.ReadCpu((ushort)request.Address) } }; if (data.Length <= 32) { foreach (var b in data) { Console.Write($"{b:X2} "); } Console.WriteLine(); } else { Console.WriteLine("OK"); } result.Data = ByteString.CopyFrom(data); } catch (Exception ex) { PrintError(ex); result.ErrorInfo = new ErrorInfo() { ExceptionName = ex.GetType().ToString(), ExceptionMessage = ex.Message }; } return(Task.FromResult(result)); }
public static void DumpFDS(IFamicomDumperConnectionExt dumper, string fileName, byte sides = 1, bool dumpHiddenFiles = true, bool useHeader = true) { if (dumper.ProtocolVersion < 3) { throw new NotSupportedException("Dumper firmware version is too old, update it to read/write FDS cards"); } CheckRAMAdapter(dumper); var sideImages = new List <FdsDiskSide>(); for (int side = 1; side <= sides; side++) { var driveStatus = dumper.ReadCpu(0x4032); if ((driveStatus & 1) != 0) { Console.Write($"Please set disk card, side #{side}... "); while ((driveStatus & 1) != 0) { Thread.Sleep(100); driveStatus = dumper.ReadCpu(0x4032); } Console.WriteLine("OK"); } var sideImage = DumpFDSSide(dumper, dumpHiddenFiles, printDiskInfo: true); sideImages.Add(sideImage); if (side < sides) { driveStatus = dumper.ReadCpu(0x4032); if ((driveStatus & 1) == 0) { Console.Write($"Please remove disk card... "); while ((driveStatus & 1) == 0) { Thread.Sleep(100); driveStatus = dumper.ReadCpu(0x4032); } Console.WriteLine("OK"); } } } Console.Write($"Saving to {fileName}... "); var fdsImage = new FdsFile(sideImages); fdsImage.Save(fileName, useHeader); Console.WriteLine("OK"); }
public static void WriteFDS(IFamicomDumperConnectionExt dumper, string fileName, bool needCheck = false) { if (dumper.ProtocolVersion < 3) { throw new NotSupportedException("Dumper firmware version is too old, update it to read/write FDS cards"); } var oldTimeout = dumper.Timeout; try { dumper.Timeout = 30000; //CheckRAMAdapter(dumper); var rom = new FdsFile(fileName); for (int sideNumber = 0; sideNumber < rom.Sides.Count; sideNumber++) { var driveStatus = dumper.ReadCpu(0x4032); if ((driveStatus & 1) != 0) { Console.Write($"Please set disk card, side #{sideNumber + 1}... "); while ((driveStatus & 1) != 0) { Thread.Sleep(100); driveStatus = dumper.ReadCpu(0x4032); } Console.WriteLine("OK"); } PrintDiskHeaderInfo(rom.Sides[sideNumber].DiskInfoBlock); Console.WriteLine($"Number of non-hidden files: {rom.Sides[sideNumber].FileAmount}"); Console.WriteLine($"Number of hidden files: {rom.Sides[sideNumber].Files.Count - rom.Sides[sideNumber].FileAmount}"); var blocks = rom.Sides[sideNumber].GetBlocks().ToArray(); Console.WriteLine($"Total blocks to write: {blocks.Length}"); byte blocksWrited = 0; while (blocksWrited < blocks.Length) { uint totalSize = 1; var blockIDs = new List <byte>(); var blocksToWrite = new List <IFdsBlock>(); for (byte i = blocksWrited; i < blocks.Length; i++) { if (totalSize + blocks[i].Length + 3 <= dumper.MaxWritePacketSize) { blocksToWrite.Add(blocks[i]); blockIDs.Add(i); totalSize += blocks[i].Length + 3; } else { break; } } if (!blocksToWrite.Any()) { throw new OutOfMemoryException("Dumper has not enoght memory to write such big block"); } Console.Write($"Writing block(s): {string.Join(", ", blockIDs)}... "); dumper.WriteFdsBlocks(blockIDs.ToArray(), blocksToWrite.Select(b => b.ToBytes()).ToArray()); Console.WriteLine("OK"); blocksWrited += (byte)blocksToWrite.Count; } if (needCheck) { Console.WriteLine("Starting verification process"); var hiddenFiles = rom.Sides[sideNumber].Files.Count > rom.Sides[sideNumber].FileAmount; var sideImage = DumpFDSSide(dumper, dumpHiddenFiles: hiddenFiles, printDiskInfo: false); if (!sideImage.DiskInfoBlock.Equals(rom.Sides[sideNumber].DiskInfoBlock)) { throw new IOException("Disk info block verification failed"); } if (!sideImage.FileAmount.Equals(rom.Sides[sideNumber].FileAmount)) { throw new IOException("File amount block verification failed"); } if (sideImage.Files.Count < rom.Sides[sideNumber].Files.Count) { throw new IOException($"Invalid file count: {sideImage.Files.Count} < {rom.Sides[sideNumber].Files.Count}"); } for (int f = 0; f < rom.Sides[sideNumber].Files.Count; f++) { if (!sideImage.Files[f].HeaderBlock.Equals(rom.Sides[sideNumber].Files[f].HeaderBlock)) { throw new IOException($"File #{f} header block verification failed"); } if (!sideImage.Files[f].DataBlock.Equals(rom.Sides[sideNumber].Files[f].DataBlock)) { throw new IOException($"File #{f} data block verification failed"); } } Console.WriteLine("Verification successful."); } if (sideNumber + 1 < rom.Sides.Count) { driveStatus = dumper.ReadCpu(0x4032); if ((driveStatus & 1) == 0) { Console.Write($"Please remove disk card... "); while ((driveStatus & 1) == 0) { Thread.Sleep(100); driveStatus = dumper.ReadCpu(0x4032); } Console.WriteLine("OK"); } } } } finally { dumper.Timeout = oldTimeout; } }