static void TestChrRam(FamicomDumperConnection dumper) { var rnd = new Random(); while (true) { var data = new byte[0x2000]; rnd.NextBytes(data); Console.Write("Writing CHR RAM... "); dumper.WritePpu(0x0000, data); Console.Write("Reading CHR RAM... "); var rdata = dumper.ReadPpu(0x0000, 0x2000); bool ok = true; for (int b = 0; b < 0x2000; b++) { if (data[b] != rdata[b]) { Console.WriteLine($"Mismatch at {b:X4}: {rdata[b]:X2} != {data[b]:X2}"); ok = false; } } if (!ok) { File.WriteAllBytes("chrramgood.bin", data); Console.WriteLine("chrramgood.bin writed"); File.WriteAllBytes("chrrambad.bin", rdata); Console.WriteLine("chrrambad.bin writed"); throw new VerificationException("Failed!"); } Console.WriteLine("OK!"); } }
public void DumpChr(FamicomDumperConnection dumper, List <byte> data, int size) { byte outbanks = (byte)(size / (256 * 1024)); for (byte outbank = 0; outbank < outbanks; outbank += 1) { dumper.Reset(); dumper.WriteCpu(0xA001, 0x80); // RAM protect dumper.WriteCpu((ushort)(0x6828 | (outbank << 1)), 0x00); dumper.WriteCpu(0xA001, 0); // disable W-RAM int banks = 256; if (banks > 256) { throw new Exception("CHR size is too big"); } for (int bank = 0; bank < banks; bank += 4) { Console.Write("Reading CHR banks #{4}|{0}, #{4}|{1}, #{4}|{2}, #{4}|{3}... ", bank, bank + 1, bank + 2, bank + 3, outbank); dumper.WriteCpu(0x8000, new byte[] { 2, (byte)bank }); dumper.WriteCpu(0x8000, new byte[] { 3, (byte)(bank | 1) }); dumper.WriteCpu(0x8000, new byte[] { 4, (byte)(bank | 2) }); dumper.WriteCpu(0x8000, new byte[] { 5, (byte)(bank | 3) }); data.AddRange(dumper.ReadPpu(0x1000, 0x1000)); Console.WriteLine("OK"); } } }
public static byte DetectVersion(FamicomDumperConnection dumper) { byte version; Console.Write("Detecting COOLBOY version... "); // 0th CHR bank using both methods dumper.WriteCpu(0x5000, 0, 0, 0, 0x10); dumper.WriteCpu(0x6000, 0, 0, 0, 0x10); // Writing 0 dumper.WritePpu(0x0000, 0); // First CHR bank using both methods dumper.WriteCpu(0x5000, 0, 0, 1, 0x10); dumper.WriteCpu(0x6000, 0, 0, 1, 0x10); // Writing 1 dumper.WritePpu(0x0000, 1); // 0th bank using first method dumper.WriteCpu(0x6000, 0, 0, 0, 0x10); byte v6000 = dumper.ReadPpu(0x0000); // return dumper.WriteCpu(0x6000, 0, 0, 1, 0x10); // 0th bank using second method dumper.WriteCpu(0x5000, 0, 0, 0, 0x10); byte v5000 = dumper.ReadPpu(0x0000); if (v6000 == 0 && v5000 == 1) { version = 1; } else if (v6000 == 1 && v5000 == 0) { version = 2; } else { throw new IOException("Can't detect COOLBOY version"); } Console.WriteLine($"Version: {version}"); return(version); }
public void DumpChr(FamicomDumperConnection dumper, List <byte> data, int size) { dumper.WriteCpu(0x8000, 0x80); WriteMMC1(dumper, 0x8000, 0x0C); byte banks = (byte)(size / 0x1000); for (int bank = 0; bank < banks; bank += 2) { Console.Write("Reading CHR banks #{0} and #{1}... ", bank, bank + 1); WriteMMC1(dumper, 0xA000, (byte)bank); data.AddRange(dumper.ReadPpu(0x0000, 0x2000)); Console.WriteLine("OK"); } }
public void DumpChr(FamicomDumperConnection dumper, List <byte> data, int size) { int banks = size / 0x400; if (banks > 256) { throw new Exception("CHR size is too big"); } for (int bank = 0; bank < banks; bank += 4) { Console.Write("Reading CHR banks #{0}, #{1}, #{2}, #{3}... ", bank, bank + 1, bank + 2, bank + 3); dumper.WriteCpu(0x8000, new byte[] { 2, (byte)bank }); dumper.WriteCpu(0x8000, new byte[] { 3, (byte)(bank | 1) }); dumper.WriteCpu(0x8000, new byte[] { 4, (byte)(bank | 2) }); dumper.WriteCpu(0x8000, new byte[] { 5, (byte)(bank | 3) }); data.AddRange(dumper.ReadPpu(0x1000, 0x1000)); Console.WriteLine("OK"); } }
public void DumpChr(FamicomDumperConnection dumper, List <byte> data, int size) { if (prg == null) { prg = dumper.ReadCpu(0x8000, DefaultPrgSize); } byte banks = (byte)(size / 0x2000); for (int bank = 0; bank < banks; bank++) { Console.Write("Dumping CHR bank #{0}... ", bank); for (int i = 0; i < prg.Length; i++) { if (prg[i] == bank) { dumper.WriteCpu((ushort)(0x8000 + i), (byte)bank); break; } } byte[] d = dumper.ReadPpu(0x0000, 0x2000); data.AddRange(d); Console.WriteLine("OK"); } }
public static void TestChrRam(FamicomDumperConnection dumper, int count = -1, int chrSize = -1) { if (chrSize < 0) { chrSize = 256 * 1024; } Console.WriteLine($"Testing CHR RAM, size: {chrSize / 1024}KB"); Program.Reset(dumper); dumper.WriteCpu(0x5007, 0x2); // enable CHR writing var rnd = new Random(); var data = new byte[0x2000]; rnd.NextBytes(data); Console.WriteLine("Single bank test."); Console.Write("Writing CHR RAM... "); dumper.WritePpu(0x0000, data); Console.Write("Reading CHR RAM... "); var rdata = dumper.ReadPpu(0x0000, 0x2000); bool ok = true; for (int b = 0; b < 0x2000; b++) { if (data[b] != rdata[b]) { Console.WriteLine($"Mismatch at {b:X4}: {rdata[b]:X2} != {data[b]:X2}"); ok = false; } } if (!ok) { File.WriteAllBytes("chrramgood.bin", data); Console.WriteLine("chrramgood.bin writed"); File.WriteAllBytes("chrrambad.bin", rdata); Console.WriteLine("chrrambad.bin writed"); throw new IOException("Test failed"); } Console.WriteLine("OK"); Console.WriteLine("Multibank test."); data = new byte[chrSize]; for (; count != 0; count--) { dumper.WriteCpu(0x5007, 0x2); // enable CHR writing rnd.NextBytes(data); for (byte bank = 0; bank < data.Length / 0x2000; bank++) { Console.WriteLine($"Writing CHR RAM bank #{bank}/{data.Length / 0x2000}..."); dumper.WriteCpu(0x5003, (byte)(bank & 0b00011111)); // select bank, low 5 bits dumper.WriteCpu(0x5005, (byte)((bank & 0b00100000) << 2)); // select bank, 6th bit var d = new byte[0x2000]; Array.Copy(data, bank * 0x2000, d, 0, 0x2000); dumper.WritePpu(0x0000, d); } for (byte bank = 0; bank < data.Length / 0x2000; bank++) { Console.Write($"Reading CHR RAM bank #{bank}/{data.Length / 0x2000}... "); dumper.WriteCpu(0x5003, (byte)(bank & 0b00011111)); // select bank, low 5 bits dumper.WriteCpu(0x5005, (byte)((bank & 0b00100000) << 2)); // select bank, 6th bit rdata = dumper.ReadPpu(0x0000, 0x2000); ok = true; for (int b = 0; b < 0x2000; b++) { if (data[b + bank * 0x2000] != rdata[b]) { Console.WriteLine($"Mismatch at {b:X4}: {rdata[b]:X2} != {data[b + bank * 0x2000]:X2}"); ok = false; } } if (!ok) { File.WriteAllBytes("chrramgoodf.bin", data); Console.WriteLine("chrramgoodf.bin writed"); File.WriteAllBytes("chrrambad.bin", rdata); Console.WriteLine("chrrambad.bin writed"); throw new IOException("Test failed"); } Console.WriteLine("OK"); } } }
public void DumpChr(FamicomDumperConnection dumper, List <byte> data, int size) { Console.Write("Reading CHR... "); data.AddRange(dumper.ReadPpu(0x0000, size)); Console.WriteLine("OK"); }
public LuaMapper() { script = new Script(); script.Globals["ReadPrg"] = script.Globals["ReadCpu"] = (Func <UInt16, int, List <byte> >) delegate(UInt16 address, int length) { if (Verbose) { Console.WriteLine("Reading {0} bytes from CPU:${1:X4}", length, address); } var result = new List <byte>(); result.AddRange(dumper.ReadCpu(address, length)); return(result); }; script.Globals["WritePrg"] = script.Globals["WriteCpu"] = (Action <UInt16, List <byte> >) delegate(UInt16 address, List <byte> data) { if (Verbose) { var a = address; foreach (var v in data) { Console.WriteLine("CPU write ${0:X2} => ${1:X4}", v, a); a++; } } dumper.WriteCpu(address, data.ToArray()); }; script.Globals["AddPrg"] = script.Globals["AddPrgResult"] = (Action <List <byte> >) delegate(List <byte> r) { resultPrg.AddRange(r); }; script.Globals["ReadAddPrg"] = script.Globals["ReadAddCpu"] = (Action <UInt16, int>) delegate(UInt16 address, int length) { if (Verbose) { Console.WriteLine("Reading {0} bytes from CPU:${1:X4}", length, address); } resultPrg.AddRange(dumper.ReadCpu(address, length)); }; script.Globals["ReadChr"] = script.Globals["ReadPpu"] = (Func <UInt16, int, List <byte> >) delegate(UInt16 address, int length) { if (Verbose) { Console.WriteLine("Reading {0} bytes from PPU:${1:X4}", length, address); } var result = new List <byte>(); result.AddRange(dumper.ReadPpu(address, length)); return(result); }; script.Globals["WriteChr"] = script.Globals["WritePpu"] = (Action <UInt16, List <byte> >) delegate(UInt16 address, List <byte> data) { if (Verbose) { var a = address; foreach (var v in data) { Console.WriteLine("PPU write ${0:X2} => ${1:X4}", v, a); a++; } } dumper.WritePpu(address, data.ToArray()); }; script.Globals["ReadAddChr"] = script.Globals["ReadAddPpu"] = (Action <UInt16, int>) delegate(UInt16 address, int length) { if (Verbose) { Console.WriteLine("Reading {0} bytes from PPU:${1:$X4}", length, address); } resultChr.AddRange(dumper.ReadPpu(address, length)); }; script.Globals["AddChr"] = script.Globals["AddChrResult"] = (Action <List <byte> >) delegate(List <byte> r) { resultChr.AddRange(r); }; script.Globals["Reset"] = (Action) delegate { if (Verbose) { Console.Write("Reset... "); } dumper.Reset(); if (Verbose) { Console.WriteLine("OK"); } }; script.Globals["WriteFile"] = (Action <string, List <byte> >) delegate(string filename, List <byte> data) { if (Verbose) { Console.Write("Writing data to \"{0}\"... ", Path.GetFileName(filename)); } File.WriteAllBytes(filename, data.ToArray()); if (Verbose) { Console.WriteLine("OK"); } }; script.Globals["WriteNes"] = (WriteNesDelegate) delegate(string filename, List <byte> prgData, List <byte> chrData, byte mapper, bool vertical) { if (Verbose) { Console.Write("Writing data to NES file \"{0}\" (mapper={1}, mirroring={2})... ", Path.GetFileName(filename), mapper, vertical ? "vertical" : "horizontal"); } var nesFile = new NesFile(); nesFile.PRG = prgData.ToArray(); nesFile.CHR = chrData.ToArray(); nesFile.Mapper = 0; nesFile.Mirroring = vertical ? NesFile.MirroringType.Vertical : NesFile.MirroringType.Horizontal; nesFile.Save(filename); if (Verbose) { Console.WriteLine("OK"); } }; script.Globals["Error"] = (Action <string>) delegate(string message) { throw new Exception(message); }; }