Попробую пошагово описать как вшить эту меню в контру Contra (U) [!].nes.
1. Файл alnum.2bpp.chr содержит шрифт, который грузится в chr-ram. Содержит всего 48 символов.
Грузится со смещением так что бы соответствовать кодировке ascii.
Посмотреть и отредактировать еще можно в специальных редакторах, например, Tile Molester.
2. Файл menu.txt содержит выводимое меню, редактируемое обычным текстовым редактором.
Длинна строки не должна превышать 32 символа. Использовать можно только те 48 символов,
которые описаны alnum.2bpp.chr. Любые другие будут выводить пустоту.
3. Файл pack-text.py это скрипт на питоне, который преобразует menu.txt в некую последовательность,
удобную для записи в ppu:
количество пробелов - количество символов - символы - количество пробелов -...
$ python ./pack-text.py menu.txt
.byt 74, 12, "UNROM 4 IN 1"
.byt 49, 18, "PUSH ^ _ START KEY"
.byt 77, 8, "1:CONTRA"
.byt 56, 13, "2:MEGAMAN RUS"
.byt 51, 15, "3:GUN:SMOKE RUS"
.byt 49, 17, "4:GHOST;N;GOBLINS"
.byt 0
Вывод этой программы надо вставить в файле menu-unrom.asm после метки text_menu.
4. Комментируем все директивы
.org если они расскомментированы и компилируем.
$ ca65 menu-unrom.asm -o menu-unrom.o
$ ld65 menu-unrom.o -o menu-unrom.nes -C nesfile-unrom.ini
Получившийся файл menu-unrom.nes должен запуститься в эмуляторе.
5. Открывает в hex-редакторе ром и ищем незанятое место, куда бы можно было поместить наш код.
В UxROM используется chr-ram, а это значит что ром не содержит chr-rom данных. И можно смотреть с конца рома.
Я использую wxHexEditor в нем очень удобно помечать произвольные области.
И вроде бы он даже мультиплатформенный.
Смотрим с конца файла.Ура! Нам даже повезло, в последнем непереключаемом банке есть даже место.
Смещение на начало свободного места: $1f623
Смещение на конец свободного места:$1fc0e
Итого: $1fc0e-$1f623=1515 байт данных.
6. Предпоследняя пара байтов содержит вектор сброса. После сброса процессор начинает выполнять код по адресу, на который указывается в этой паре.
Адрес записывается наоборот, сначала младший байт, потом старший.
Вектор сброса на скрине: $0c01
7. А вот здесь уже нужны знания ассемблера.
Вшить в кастельванию было несколько тяжелее, потому что в непереключаемом банке не было место под меню. Поэтому в непереключчаемом банке был код,
который переключал на банк с меню и передавал туда управление. С контрой проще.
Все что связано с OFFSET_LOAD, нам не нужно. Комментируем или удаляем.
Для RESET_OLD указывает вектор сброса из п.6
Для OFFSET_MENU указывает смещение из п.5
RESET_OLD = $c001 ; старое значение вектора сброса
OFFSET_MENU = $1f623 ; смещение на неиспользуемое место для кода меню
Перед .proc reset,.расскоментируем .org ORG_MENU.
Компилируем. Теперь полученный ром запуститься в эмуле не должен.
8. Открывает в hex-редакторе получившийся ром и ищем код меню.
Копируем, начиная с цифры 78(это код sei) до конца, а потом вставляем в выбранное место.
9. При компиляции в консоле был напечатан новый вектор сброса:
$ ./build.sh
new reset = $F613
Исправим его тоже.Пишется также в обратном порядке, те 13 F6
10. Сохраняем, запускам.
Первым пунктом в меню всегда идет вшитая игра. Остальные в порядке склейки.
Все что получилось есть в приложенном архиве.
Кстати, если кто-то знает почему линковщик ld65 игнорирует директивы .org и лепит все подряд, а не по указанному адресу, подскажите. Буду признателен.