База nescartdb, конвертированная в формат JSON, используется для определения типа PCB картриджей NES/Famicom по содержимому их дампов PRG/CHR.
Эта папка — единственный источник данных об идентификации картриджей для всех потребителей Breaknes: нативного ядра (BreaksCore), управляемого приложения (Breaknes), SDL-порта и инструментов (PPUPlayer, APUPlayer).
1. Зачем нужна эта папка
Старый компонент Mappers определяет картриджи по заголовку iNES и номеру маппера iNES.
Для функционального симулятора это плохо подходит:
- Один и тот же номер маппера iNES покрывает много электрически разных плат.
- Заголовок не говорит, какие микросхемы стоят на плате и как они соединены.
- Нелицензионные платы и платы Famiclone часто вообще нельзя выразить средствами iNES.
Решение (issue #508) — определять картриджи по типу платы, используя базу nescartdb, которая описывает фактическую PCB каждого дампированного картриджа (компоненты, размеры, CRC, зеркалирование).
В нативном коде нет XML-движка, поэтому XML nescartdb один раз конвертируется в JSON, хранится здесь и используется всеми.
2. Источник данных
| База данных | nescartdb (bootgod / brizzo) |
| Используемый экспорт | forum.nesdev.org - tepples/NesCarts (2017-08-21).utf8.xml из зеркала MetaFight/NesCartDB |
| Содержимое | ~3179 записей картриджей, 273 различных типа плат, для всех регионов (NES-NTSC, NES-PAL, Famicom, Dendy, ...) |
Экспорт — это статический снимок (2017-08-21). Конвертация детерминирована: один и тот же XML всегда даёт один и тот же JSON, поэтому JSON можно в любой момент перегенерировать.
3. Файлы в этой папке
Nescartdb/
Readme.md <- this file
nescarts.json <- the full converted database (generated, committed)
index.json <- flattened lookup index: prg_crc/chr_crc -> board type (generated, committed)
boards/ <- board definitions (authored, not generated) + the family index
nescarts.json— полная база, точно соответствующая XML: вложенностьgame→cartridge→boardсо всеми атрибутами (см. §5).index.json— плоский массив записей для поиска (prg_crc,chr_crc,board.type,board.pcb,mapper,system), сгенерированный изnescarts.json. Во время выполнения загружается этот небольшой файл, чтобы отвечать на вопрос «какие типы плат соответствуют этим CRC PRG/CHR?», не обходя всю базу.boards/— JSON-определения плат (nrom.json,unrom.json,aorom.json,sgrom.json, плюсcnrom.json/shrom.jsonдля iNES-фолбэка) иindex.json— отображение семейств «тип платы → файл определения» (см. §6.1).
Сгенерированные файлы коммитятся в репозиторий, чтобы ни при сборке, ни во время выполнения не требовался доступ к сети.
4. Конвейер конвертации
Tools/NescartdbConvert/convert.py
XML (tepples export) ---> nescarts.json ---> index.json
- Конвертер — небольшой Python-скрипт (вроде
Tools/DumpRegdump/DumpRegdump.py), лежит вTools/NescartdbConvert/. - Он запускается вручную (или в CI), когда обновляется исходный XML; его результат коммитится.
- Конвертер нормализует данные для нативного потребления:
- размеры:
"256k"→ байты (262144),"8k"→8192и т. д.; - булевы значения:
battery→true/false,prototype→true/false; - имена атрибутов сохраняются 1:1, где это возможно (см. таблицу соответствия в §5).
- размеры:
5. JSON-схема (nescarts.json)
Прямое отображение структуры XML:
{
"source": {
"name": "NesCartDB",
"agent": "NesCartDB",
"author": "BootGod",
"export": "forum.nesdev.org - tepples/NesCarts (2017-08-21).utf8.xml",
"converted_at": "2026-09-01T00:00:00Z",
"converter": "Tools/NescartdbConvert/convert.py"
},
"games": [
{
"name": "10-Yard Fight",
"altname": "10ヤードファイト",
"class": "Licensed",
"subclass": "3rd-Party",
"catalog": "IF-02",
"publisher": "Irem",
"developer": "Irem",
"portdeveloper": null,
"region": "Japan",
"players": 2,
"date": "1985-08-30",
"cartridges": [
{
"system": "Famicom",
"revision": null,
"crc": "836C4FA7",
"dump": "ok",
"dumper": "bootgod",
"datedumped": "2007-05-06",
"prototype": false,
"board": {
"type": "IREM-NROM-128",
"pcb": "IREM-01-V",
"mapper": 0,
"prg": { "name": null, "id": null, "size": 16384, "crc": "D3D248C9" },
"chr": { "name": null, "id": null, "size": 8192, "crc": "9C124A53" },
"wram": null,
"vram": null,
"chips": [],
"cic": [],
"pad": { "h": 0, "v": 1 },
"peripherals": []
}
}
]
}
]
}
5.1 Отображение XML → JSON
| XML | JSON | Примечания |
|---|---|---|
<database> | source | version, conformance, agent, author, timestamp свёрнуты в source; конвертер добавляет export, converted_at, converter |
<game> | games[] | name, altname, class, subclass, catalog, publisher, developer, portdeveloper, region, players, date |
<cartridge> | games[].cartridges[] | system, revision, crc, dump, dumper, datedumped, prototype (sha1 намеренно опущен — идентификация только по CRC) |
<board> | ...board | type (тип платы), pcb (ревизия платы), mapper (номер маппера iNES — только для информации, не используется для идентификации) |
<prg> / <chr> | board.prg / board.chr | name, id, size (байты), crc (sha1 намеренно опущен) |
<wram> / <vram> | board.wram / board.vram | size, battery, id |
<chip> | board.chips[] | type (например, MMC1A, MMC3B), battery |
<cic> | board.cic[] | type (например, 3193A, 6113) |
<pad> | board.pad | h, v (зеркалирование) |
<peripherals>/<device>/<pin> | board.peripherals[] | сквозная передача сырых данных о пинах |
5.2 Поисковый индекс (index.json)
[
{
"prg_crc": "D3D248C9",
"chr_crc": "9C124A53",
"system": "Famicom",
"type": "IREM-NROM-128",
"pcb": "IREM-01-V",
"mapper": 0
}
]
- По одной записи на каждый картридж с известной парой CRC PRG/CHR.
- Идентификация только по CRC32 PRG + CRC32 CHR (SHA1 не используется): во время выполнения вычисляется CRC32 дампов PRG и CHR и выполняется поиск по
prg_crc+chr_crc. - Несколько записей могут иметь одинаковые CRC (одни и те же ROM на разных PCB) — возвращаются все совпадения, а подходящее выбирает вызывающий код (см.
CartPcb/Readme.md§8). - Записи могут содержать паяльные перемычки зеркалирования
"h"/"v"(информационно). Перемычки используют термины зеркалирования iNES — обратные термину scroll PCB (issue #525):v=1(iNES «вертикальное зеркалирование») означает, что джампер scroll картриджа установлен в H Scroll (VRAM_A10 = PA10), аh=1— в V Scroll (VRAM_A10 = PA11). Во время выполнения перемычки не используются для переопределения заголовка.nes: scroll плат с джампером scroll всегда следует за заголовком.
6. Потребители
| Потребитель | Как использует эту папку |
|---|---|
| BreaksCore (native) | CartPcb::NesCartDb загружает index.json для поиска «CRC → тип платы». |
| CartPcb (native) | Board JSON, на которые ссылается индекс (встроенные определения + пользовательские переопределения). |
| Управляемое приложение Breaknes | Ищет JSON рядом с исполняемым файлом (копируется при сборке) и может разбирать его напрямую для нужд UI (тип платы показывается пользователю). |
| SDL-порт | Тот же нативный путь, что и у BreaksCore. |
| PPUPlayer / APUPlayer | Используют те же данные Nescartdb через нативное ядро или собственную копию. |
Развёртывание: файлы из Nescartdb/ (включая boards/*.json) при сборке
копируются в выходной каталог (Breaknes.csproj и BreaknesSDL.vcxproj копируют их рядом
с исполняемым файлом). Нативный код ищет их относительно исполняемого файла: управляемое приложение передаёт свой
базовый каталог через SetNescartdbDir; SDL-порт использует папку Nescartdb рядом
с исполняемым файлом (можно переопределить переменной окружения NESCARDB_DIR). Пользовательские
платы попадают в пользовательский каталог плат (по умолчанию в управляемом приложении это CustomBoards/
рядом с исполняемым файлом, настраивается через SetUserBoardsDir).
6.1 Определения плат (boards/)
Папка boards/ содержит board JSON, в которые PcbLoader преобразует тип платы:
index.json— отображение семейств: тип платы → файл определения платы (например, все типы*-NROM-*отображаются наnrom.json). Плата NamcoNAMCOT-3305(The Tower of Druaga, Pac-Land) электрически является NROM-256 (2x16K PRG + 8K CHR, без логики маппера, жёстко заданный H-scroll) и тоже отображается наnrom.json(issue #527).nrom.json,unrom.json,aorom.json,sgrom.json— встроенные определения плат для семейств NROM/UxROM/AxROM/MMC1 (определения UNROM и AOROM включают реальную клеевую логику 74LS161/74LS32, см.CartPcb/Readme.md§5.3).cnrom.json,shrom.json— платы, добавленные для iNES-фолбэка «диких» дампов (issue #514): маппер 3 (CNROM, переключение банков CHR на защёлках) и маппер 1 с CHR-RAM (разводка MMC1 в стиле SHROM).
Определения плат пишутся вручную (не генерируются из XML): nescartdb описывает перечень компонентов, а CartPcb
добавляет разводку (circuit). Новые типы плат, на которые ссылаются вывод конвертера или iNES-фолбэк,
нужно добавлять здесь вручную.
7. Политика версионирования и регенерации
nescarts.jsonиindex.json— генерируемые артефакты, но они коммитятся (нет сети во время выполнения, история различима через diff).- Когда исходный XML обновляется: заново запустите
Tools/NescartdbConvert/convert.py, закоммитьте перегенерированный JSON и поднимите метку времениsource.converted_at. - Схема JSON версионируется через
source.version; ломающие изменения схемы поднимают версию и согласуются с загрузчикомCartPcb.
8. Лицензирование и атрибуция
- Данные — это база nescartdb от bootgod (сайт ведут bootgod и brizzo), зеркало — MetaFight/NesCartDB.
- В вышестоящем зеркале нет явной лицензии, поэтому с данными нужно обращаться как с защищёнными всеми правами: сохраняйте атрибуцию (блок
sourceв JSON иNescartdb/Readme.md) и проверяйте условия распространения перед любой упаковкой релиза. - Сам XML-экспорт происходит из поста на forum.nesdev.org от tepples (2017-08-21); авторство сохранено в
source.export.
9. Связь с CartPcb и JSONES
Nescartdb/обеспечивает идентификацию (какая это PCB?) — см.CartPcb/Readme.md§8.CartPcbобеспечивает симуляцию опознанной PCB — формат board JSON определён вCartPcb/Readme.md§5.- «Дикие» дампы (issue #514): когда CRC PRG/CHR дампа нет в
index.json(homebrew, недокументированные дампы),CartPcb::InesTranslatorоткатывается к заголовку iNES (номер маппера + размеры PRG/CHR) и сопоставляет его с одним из типов плат выше; дальше дамп проходит по тому же пути платы. Это трансляция, а не идентификация: заголовок жёсткий и теряет данные, поэтому фолбэк покрывает только распространённые простые мапперы. - JSONES (issue #189) — подмножество формата плат CartPcb: JSON одного картриджа с вложенностью
game→cartridge→board, пригодный в качестве пользовательского определения платы в дополнение к встроенным данным nescartdb (CartPcb/Readme.md§6.5).