Свой первый дампер для картриджей NES/Famicom я собрал по проекту famicom-dumper от @clusterM.
Осознанно выбрал для реализации раннюю версию, она мне больше нравится, ввиду доступности и адекватности выбора комплектующих для своей задачи. Контроллеры ATMEGA64 были в наличии, лежали лет 10, ждали своего часа.
Конечно, у ранней версии нет честного phi2, не все мапперы можно сдампить без постоянного phi2, но для подавляющего большинства этого и не требуется.
В своем форке на гитхабе (https://github.com/pavelkokorin/famicom-dumper), доделал постоянную генерацию phi2 во время idle, для некоторых мапперов многоигровок это помогло.
Моя реализация не отличается красотой, собрано на старой макетке и модулях с алиэкспресс. Главное, что работает.


Основное назначение дампера - исследование и эксперименты с мапперами (оригинальными и клонами), для этой задачи клиент-серверная архитектура ПО с компилируемыми модулями на C# подходит очень хорошо, пользоваться действительно удобно.
Есть другие проекты, например, комбайн cartreader от sanni, где вся логика внутри arduino, что для исследовательских задач менее удобно.
Дампер также умеет прошивать образы в китайские клоны flash картриджей по типу CoolBoy, дампить FDS, тестировать SRAM и прочее.

Исследование "платок" от картриджей - это то, ради чего я собирал дампер, научиться дампить многоигровки (новоделы, староделы) с неизвестными или не полностью известными типами мапперов. Большая часть мапперов, на сегодняшний день, исследована вдоль и поперек, но сложность создает большое их разнообразие, проблема идентификации маппер по косвенным признакам: номерам используемых портов, виду платы, необходимости частичного дизассемблирования дампов.
Дампер также подходит и для исследования лицензионных, но экзотических картриджей. Интересный пример -- DATACH от Bandai.

Внешне выглядит впечатляюще, но дампится достаточно просто с помощью 157 маппера, создать который по спецификации и запрограммировать новый модуль на C# не составляет труда.
// .\mappers\153.cs // Bandai DATACH Joint ROM System class BANDAI_LZ93D50_BARCODE : IMapper { public string Name { get => "BANDAI BARCODE"; } public int Number { get => 157; } public int DefaultPrgSize { get => 256 * 1024; } public int DefaultChrSize { get => 0; } public void DumpPrg(IFamicomDumperConnection dumper, List<byte> data, int size) { var banks = size / 0x4000; for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading PRG bank #{bank}/{banks}... "); dumper.WriteCpu(0x8008, (byte)(bank & 0xFF)); data.AddRange(dumper.ReadCpu(0x8000, 0x4000)); Console.WriteLine("OK"); } } public MirroringType GetMirroring(IFamicomDumperConnection dumper) { return MirroringType.MapperControlled; } }
Запуск
D:\Develop\famicom-dumper-win-x64-self-contained\famicom-dumper>famicom-dumper.exe dump --port COM3 --mapper 157 --chr-size 0k --prg-size 256k --chr-ram-size 8k --file datach.nes Famicom Dumper Client v3.4(c) Alexey 'Cluster' Avdyukhin / https://clusterrr.com / clusterrr@clusterrr.com Dumper initialization... OK Compiling mappers in D:\Develop\famicom-dumper-win-x64-self-contained\famicom-dumper\mappers... Using 157.cs as mapper file Using mapper: #157 (BANDAI BARCODE) Dumping... PRG memory size: 256KB Reading PRG bank #0/16... OK ... Reading PRG bank #15/16... OK Mirroring: MapperControlled Saving ROM as NES 2.0 file: datach.nes... OK Done.

Или другой пример от Bandai, картридж Famicom Jump II - Saikyou no 7 Nin (Japan), со своим уникальным 153 маппером, который использовался только в нем.
// .\mappers\153.cs // The only game "Famicom Jump II - Saikyou no 7 Nin (Japan)" uses this mapper class BANDAI_LZ93D50_WRAM_CHRRAM_PRGROM : IMapper { public string Name { get => "153 BANDAI SRAM"; } public int Number { get => 153; } public int DefaultPrgSize { get => 512 * 1024; } public int DefaultChrSize { get => 0; } public void DumpPrg(IFamicomDumperConnection dumper, List<byte> data, int size) { var banks = size / 0x4000; for (var bank = 0; bank < banks; bank++) { Console.Write($"Reading PRG bank #{bank}/{banks}... "); var outerBank = (byte)((bank & 0x10) >> 4); dumper.WriteCpu(0x8000, outerBank); dumper.WriteCpu(0x8001, outerBank); dumper.WriteCpu(0x8002, outerBank); dumper.WriteCpu(0x8003, outerBank); dumper.WriteCpu(0x8008, (byte)(bank & 0xF)); data.AddRange(dumper.ReadCpu(0x8000, 0x4000)); Console.WriteLine("OK"); } } public MirroringType GetMirroring(IFamicomDumperConnection dumper) { return MirroringType.MapperControlled; } }
Запуск
Famicom Dumper Client v3.4 (c) Alexey 'Cluster' Avdyukhin / https://clusterrr.com / clusterrr@clusterrr.com Dumper initialization... OK Compiling mappers in D:\Develop\famicom-dumper-win-x64-self-contained\famicom-dumper\mappers... Using 153.cs as mapper file Using mapper: #153 (153 BANDAI SRAM) Dumping... PRG memory size: 512KB Reading PRG bank #0/32... OK ... Reading PRG bank #31/32... OK Mirroring: MapperControlled Saving ROM as NES 2.0 file: Famicom Jump II Saikyou no 7-nin 153.nes... OK Done.

Подытоживая, дампером и реализацией доволен, он полностью закрывает мои задачи. Для тех, кто подыскивает подходящий инструмент, рекомендую обратить вниманием именно на https://github.com/ClusterM/famicom-dumper, он прост в изготовлении и функционален.
Ссылки:
