Exemplo n.º 1
0
        public static void WriteFDS(FamicomDumperConnection 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.Count(); 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.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;
            }
        }