// But method signature must be like this. Also you can make this method static. void Run(IFamicomDumperConnection dumper, string[] args) { // You can parse additional command line arguments if need // Specify arguments this way: >FamicomDumper.exe script --csfile DemoScript.cs - argument1 argument2 argument3 if (args.Any()) { Console.WriteLine("Command line arguments: " + string.Join(", ", args)); } Console.WriteLine("Please insert MMC3 cartridge and press enter"); Console.ReadLine(); Console.WriteLine("Let's check - how many PRG banks on this MMC3 cartridge"); byte[] firstBank = null; for (var bank = 0; ; bank = bank == 0 ? 1 : bank * 2) { if (bank > 256) { throw new InvalidDataException("Bank number out of range, did you actually insert the MMC3 cartridge?"); } Console.Write($"Reading PRG bank #{bank}... "); dumper.WriteCpu(0x8000, 6, (byte)bank); var data = dumper.ReadCpu(0x8000, 0x2000); Console.WriteLine("OK"); if (bank == 0) { firstBank = data; } else if (Enumerable.SequenceEqual(data, firstBank)) { Console.WriteLine($"There are {bank} PRG banks on this cartridge, {bank * 0x2000 / 1024} KBytes in total"); break; } } Console.WriteLine("Let's check - how many CHR banks on this MMC3 cartridge"); for (var bank = 0; ; bank = bank == 0 ? 1 : bank * 2) { if (bank > 256) { throw new InvalidDataException("Bank number out of range, did you actually insert the MMC3 cartridge?"); } Console.Write($"Reading CHR bank #{bank}... "); dumper.WriteCpu(0x8000, 2, (byte)bank); var data = dumper.ReadPpu(0x1000, 0x0400); Console.WriteLine("OK"); if (bank == 0) { firstBank = data; } else if (Enumerable.SequenceEqual(data, firstBank)) { Console.WriteLine($"There are {bank} CHR banks on this cartridge, {bank * 0x0400 / 1024} KBytes in total"); break; } } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { var banks = size / 0x400; for (var bank = 0; bank < banks; bank++) { Console.Write("Reading CHR bank #{0}... ", bank); dumper.WriteCpu(0x8000, (byte)bank); data.AddRange(dumper.ReadPpu(0x0000, 0x0400)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { var banks = size / 0x2000; for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading CHR bank #{bank}/{banks}... "); dumper.WriteCpu((ushort)(0x8000 | (bank << 1)), 0); data.AddRange(dumper.ReadPpu(0x0000, 0x2000)); Console.WriteLine("OK"); } }
public static byte DetectVersion(IFamicomDumperConnection 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 InvalidDataException("Can't detect COOLBOY version"); } Console.WriteLine($"Version: {version}"); return(version); }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { var banks = size / 0x1000; for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading CHR bank #{bank}/{banks}... "); dumper.WriteCpu(0xB000, (byte)bank); // CHR ROM $FD/0000 bank select dumper.WriteCpu(0xC000, (byte)bank); // CHR ROM $FE/0000 bank select data.AddRange(dumper.ReadPpu(0x0000, 0x1000)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List<byte> data, int size) { var banks = size / 0x400; for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading CHR bank #{bank}/{banks}... "); dumper.WriteCpu(0xB000, (byte)(bank & 0x0F)); // CHR Select 0 low dumper.WriteCpu(0xB002 | 0xB040, (byte)(bank >> 4)); // CHR Select 0 low data.AddRange(dumper.ReadPpu(0x0000, 0x0400)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { var banks = size / 0x2000; dumper.WriteCpu(0x2000, 0); // 8x8 sprites mode dumper.WriteCpu(0x5101, 0); // bank mode #0, one 8KB bank for (var bank = 0; bank < banks; bank++) { Console.Write("Reading CHR bank #{0}... ", bank); dumper.WriteCpu(0x5127, (byte)bank); data.AddRange(dumper.ReadPpu(0x0000, 0x2000)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { dumper.WriteCpu(0x8000, 0x80); WriteMMC1(dumper, 0x8000, 0b11100); var banks = size / 0x1000; for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading CHR bank #{bank}/{banks}... "); WriteMMC1(dumper, 0xA000, (byte)bank); data.AddRange(dumper.ReadPpu(0x0000, 0x1000)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { dumper.WriteCpu(0x8000, 0x80); WriteMMC1(dumper, 0x8000, 0x0C); var banks = size / 0x1000; for (var 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(IFamicomDumperConnection dumper, List <byte> data, int size) { var banks = size / 0x400; if (banks > 256) { throw new ArgumentOutOfRangeException("size", "CHR size is too big"); } for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading CHR banks #{bank}/{banks}... "); dumper.WriteCpu(0x8000, 2, (byte)bank); data.AddRange(dumper.ReadPpu(0x1000, 0x0400)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { var banks = size / 0x400; if (banks > 256) { throw new ArgumentOutOfRangeException("size", "CHR size is too big"); } for (var 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"); } }
// But method signature must be like this. Also you can make this method static. void Run(IFamicomDumperConnection dumper) { Console.WriteLine("Please insert MMC3 cartridge and press any key"); Console.ReadKey(); Console.WriteLine("Let's check - how many PRG banks on this MMC3 cartridge"); byte[] firstBank = null; for (var bank = 0; ; bank = bank == 0 ? 1 : bank * 2) { Console.Write("Reading PRG bank #{0}... ", bank); dumper.WriteCpu(0x8000, new byte[] { 6, (byte)bank }); var data = dumper.ReadCpu(0x8000, 0x2000); Console.WriteLine("OK"); if (bank == 0) { firstBank = data; } else if (Enumerable.SequenceEqual(data, firstBank)) { Console.WriteLine("There are {0} PRG banks on this cartridge, {1} KBytes in total", bank, bank * 0x2000 / 1024); break; } } Console.WriteLine("Let's check - how many CHR banks on this MMC3 cartridge"); for (var bank = 0; ; bank = bank == 0 ? 1 : bank * 2) { Console.Write("Reading CHR bank #{0}... ", bank); dumper.WriteCpu(0x8000, new byte[] { 2, (byte)bank }); var data = dumper.ReadPpu(0x1000, 0x0400); Console.WriteLine("OK"); if (bank == 0) { firstBank = data; } else if (Enumerable.SequenceEqual(data, firstBank)) { Console.WriteLine("There are {0} CHR banks on this cartridge, {1} KBytes in total", bank, bank * 0x0400 / 1024); break; } } }
void Run(IFamicomDumperConnection dumper, string[] args) { int count = -1; if (args.Any()) { count = int.Parse(args.First()); } var rnd = new Random(); while (count != 0) { 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 InvalidDataException("Failed!"); } Console.WriteLine("OK!"); count--; } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { if (prg == null) { prg = dumper.ReadCpu(0x8000, DefaultPrgSize); } var banks = size / 0x2000; for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading CHR bank #{bank}/{banks}... "); // Avoiding bus conflicts for (var i = 0; i < prg.Length; i++) { if (prg[i] == bank) { dumper.WriteCpu((ushort)(0x8000 + i), (byte)bank); break; } } data.AddRange(dumper.ReadPpu(0x0000, 0x2000)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { var banks = size / 0x400; if (banks > 512) { throw new ArgumentOutOfRangeException("size", "CHR size is too big"); } for (var bank = 0; bank < banks; bank += 4) { Console.Write("Reading CHR banks #{0}, #{1}, #{2}, #{3}... ", bank, bank + 1, bank + 2, bank + 3); dumper.WriteCpu(0x6000, (byte)((bank >> 8) & 1)); dumper.WriteCpu(ScrumbleAddress(0x8000), ScrumbleValues(2)); dumper.WriteCpu(ScrumbleAddress(0x8001), (byte)bank); dumper.WriteCpu(ScrumbleAddress(0x8000), ScrumbleValues(3)); dumper.WriteCpu(ScrumbleAddress(0x8001), (byte)(bank | 1)); dumper.WriteCpu(ScrumbleAddress(0x8000), ScrumbleValues(4)); dumper.WriteCpu(ScrumbleAddress(0x8001), (byte)(bank | 2)); dumper.WriteCpu(ScrumbleAddress(0x8000), ScrumbleValues(5)); dumper.WriteCpu(ScrumbleAddress(0x8001), (byte)(bank | 3)); data.AddRange(dumper.ReadPpu(0x1000, 0x1000)); Console.WriteLine("OK"); } }
public void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { var outbanks = size / (256 * 1024); for (var 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 const int banks = 256; for (var 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 void DumpChr(IFamicomDumperConnection dumper, List <byte> data, int size) { Console.Write("Reading CHR... "); data.AddRange(dumper.ReadPpu(0x0000, size)); Console.WriteLine("OK"); }
public static void TestChrRam(IFamicomDumperConnection dumper, int count, int chrSize) { Console.WriteLine($"Testing CHR RAM, size: {chrSize / 1024}KB"); Console.Write("Reset... "); dumper.Reset(); Console.WriteLine("OK"); 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 InvalidDataException("Test failed"); } Console.WriteLine("OK"); } } }