В этой доке я распишу как просто и быстро можно добавить поддержку
SRAM (Save RAM – метод для долговременного сохранения данных в памяти) в свои хаки или возможно в какие-либо ромы SMD. Правда не во все, здесь также существуют ограничения, о которых ниже. Сразу скажу, что сначала планировалось сделать перевод вот этого туториала:
http://sonicresearch.org/forums/index.php?showtopic=2233, но, попробовав по нему все проделать, я ничего работающего не получил. Оказывается, тот автор освятил не все нюансы, а мне хотелось быстрее все сделать, и я их не заметил. Здесь постараюсь все подробней расписать.
Итак, чтобы эмулятор знал, что в данном роме есть поддержка SRAM, в заголовок нужно добавить следующие данные:
off_1B0: dc.l $5241F820 ; идентификатор (расшифровка ниже)
dc.l $200000 ; SRAM start
dc.l $2003FF ; SRAM end
Здесь, $5241F820: первые 2 байта всегда $5241, т.е. ‘RA’
3 байт имеет вид %1x1yz000, где х = 1 или 0 если используется backup RAM или non backup RAM соответственно; yz = 10 или 11 для четной SRAM и нечетной SRAM соответственно. Все флеш картриджи используют только нечетную SRAM, это нужно помнить.
4 байт всегда $20.
Начало и конец SRAM, как ни странно, тоже нужно вписывать в заголовок. Хотя конец можно записать довольно большим, это не повлияет ни на что. Главное, чтобы значение конца было больше значения начала. Теперь о грустном ограничении размера SRAM: адресное пространство, которое использует SRAM от $200000 до $203FFF. Размер максимальный, как видите, равен 16384 байт, т.е. всего 16 кБ. Этого конечно хватает с лихвой, но вот то что использовать сохранки можно только на втором мегабайте, это совсем неудобно. Ведь игры больше 2-х мегабайт уже использовать SRAM не могут. Правда есть исключения, например Beyond Oasis, размер которого 3 МБ. Там вроде используется банксвитчинг, поэтому по сути используется также 2-й мегабайт для сохранения. Но как именно он реализуется, я не в курсе.
Один заполненный заголовок не заставит эмулятор выдать вам файл сохранения с расширением *.srm. Нужно обязательно, чтобы игра сама что-то сохранила в процессе, тогда файл создастся. Рассмотрим сохранение текущего уровня в игре Beyond Zero Tolerance. Сборщик лежит тут: http://elektropage.ru/publ/ourwork/zero_tolerance/bzt_disassembly_0_1/19-1-0-59 .
Т.к. ром чуть больше 2 МБ нам сначала нужно его чуть уменьшить. Для этого поудаляем ненужный мусор с метками: ZT_Maps, garbage1 и garbage2. Это освободит около 100 кБ места. Теперь сохраним номер текущего уровня в SRAM. Для этого нужно перейти к процедуре загрузки новой карты (она вызывается, когда игрок приезжает на лифте на новый уровень), которая называется sub_B9828. Вписываем следующее:
sub_B9828: move.b #1,($A130F1).l ; Включить SRAM (обязательно)
lea ($200000).l,a1 ; Начало SRAM
movep.w d0,0(a1) ; Сохранить номер уровня из d0 в SRAM.
Сразу вопрос: почему используем movep? Все просто. Так как метод адресации SRAM у нас нечетный, поэтому пользоваться четными адресами запрещено. Для этого и нужна movep. Она забивает на четные адреса и пишет данные только в нечетные. Например, в d0 было значение 0501. Как оно запишется в SRAM? Вот так 00050001. Дальше рекомендуется выключить SRAM путем инструкции move.b #0, ($A130F1).l, но как я выяснил эмулятору на это наплевать.
Теперь можно запустить собранный ром на эмуляторе и проверить работоспособность нового кода. Дойдите до лифта и переместитесь на новый уровень, скажем на второй. При закрытии эмулятора появится srm файл размером 4 байта, в котором будет лишь 00000001. То есть игра сохранила номер уровня!
Осталось только организовать загрузку с этого уровня. Для этого идем сюда: loc_10C4 (загрузка номера уровня и эпизода после выбора персонажа) и меняем jsr sub_B94A4 на jsr lvl_Load. Дело в том, что сборщик еще не на 100% работает при переставлении кода в роме шиворот навыворот, поэтому вставим новый код в конец рома и напишем на него ссылку, не нарушая, между этим, изначальную целостность рома в пределах программного кода. Итак, в конце рома создаем метку lvl_Load и записываем:
lvl_load: move.b #1,($A130F1).l ; Включить SRAM
lea ($200000).l,a1 ; Начало SRAM
movep.w 0(a1),d1 ; Извлечь из SRAM значение и поместить в d1
jsr sub_B94A4 ; Замененная процедура на $10CC
rts ; Возврат
Откомпилируйте ром. После выбора персонажа вы должны оказаться на втором уровне (ну или на том, который был последним текущим при прошлой игре). Скажу сразу, т.к. игра мега забагована, возможно появление игрока непонятно где. На карте есть ячейка появления персонажа после ввода пароля, так вот они разбросаны по уровням как придется! Но это в принципе не так важно, важна сама суть сохранения и загрузки данных из SRAM, которую вы надеюсь поняли. За сим кланяюсь, всем спасибо!