Всем привет.
В этой статье я расскажу, как найти процедуру вывода текста в любой или почти любой игре на
SMD.
Инструментарий:
- Gensida - дебагер-плагин для IDA, позволяющий отлаживать ромы Sega Genesis / Mega Drive, унаследовавший некоторые фичи Gens Rerecordings, Gens KMod, Gens r57shell mod;
- Smd Ida Tools - набор из загрузчика ромов Sega в IDA и подсказчика по отправляемым в VDP-регистры значениям;
- Ром игры (возьмем, например, Caliber .50).
Приступаем:
Для начала, устанавливаем весь необходимый инструментарий (инструкции есть на репозиториях каждой из утилит).
Далее открываем
IDA, кидаем в нее ром игры:
В качестве загрузчика у нас выбран
smd_loader.ldw. Так и оставляем. Жмем
ОК.
Теперь нужно указать дебагер-плагин:
Выбираем "
GensIDA debugger plugin".
Запуск процесса отладки и установка бряков:
Жмем клавишу
F9 (или меню
Debugger->Start process). После запуска процесса мы тут же прерываемся на самом старте эмуляции:
Далее заходим в меню
Tools->Plane Explorer. Откроется окно гляделки:
Теперь давайте выберем текст, который мы хотим найти. Для этого снова нажмем в
IDA клавишу
F9. Мне понравился текст "
20 YEARS LATER." (Вы можете выбрать совершенно другой текст. Принцип останется тем же.):
Жмем кнопку
Pause на клавиатуре, либо на значок паузы в
IDA. Переключаемся на окно
Plane Explorer'а. Видим, что на
Plane A черный экран. Пробуем
Plane B - ага, вот и текст!
Наводим на
первую букву курсор:
И на
последнюю букву:
Красными рамками я выделил информацию о тайлах. Нам нужны значения
ADDRESS, запомним их.
Теперь самое интересное и муторное: установка бряков и анализ каждого из срабатываний. Алгоритм такой:
- Перезапустить эмуляцию;
- Дать игре дойти до места, которое как можно ближе к месту, где текст уже отображен, нажать Pause;
- В IDA перейти на первое значение ADDRESS (клавиша G), которое мы взяли из Plane Explorer'а;
- Установить брейкпоинт (клавиша F2) на запись в VRAM;
- Продолжить эмуляцию (клавиша F9);
- Проанализировать место остановки.
Итак, с первым пунктом понятно. Далее, нужно дойти до места, где чуть далее будет показан искомый текст. У меня получилась такая вот картинка:
Установим бряк на адрес
0xE69A (у Вас адрес может быть другим):
Это окно можно просто пропустить нажатием
OK.
Зато на следующем окошке - собственно установка брейкпоинта:
Обратите внимание на строку диапазона.
Это те самые два значения
ADDRESS из
Plane Explorer'а.
Жмем
OK, и отпускаем эмуляцию дальше... И вот, первое срабатывание:
Судя по диапазону сработавшего бряка, и по коду, на котором остановилась
IDA, это всего лишь очистка
VRAM.
Отпускаем эмуляцию дальше... А вот это уже интереснее:
(Я тут закрыл лишние окна, и оставил самые важные.)
Знающие люди сразу поймут, что этот код именно тот, что нужно. Для менее знающих поясню немного:
ROM:00000A36 movea.l $10(sp),a0
Здесь в
a0 заносится адрес чего-то, что идет сразу за адресом вызова процедуры. В Вашем случае передача адреса может выглядеть по другому. Главное найти
регистр с адресом, откуда читаются символы, которые потом пишутся в
VRAM.
Какой именно регистр нужен, станет понятно далее по коду.
ROM:00000A3A move.w (a0)+,d0
ROM:00000A3C tst.b d0
ROM:00000A3E beq.s loc_A50
ROM:00000A40
ROM:00000A40 loc_A40: ; CODE XREF: sub_A2C+22j
ROM:00000A40 move.w d0,(a6)
ROM:00000A42 move.b (a0)+,d0
ROM:00000A44 move.b (a0)+,d1
ROM:00000A46 tst.b d0
ROM:00000A48 beq.s loc_A50
ROM:00000A4A move.w d0,(a6)
ROM:00000A4C move.b d1,d0
ROM:00000A4E bne.s loc_A40
Весь этот код просто читает из
a0 по два байта (
word) и пишет их в
VDP_DATA. Запись прекращается, когда обнаруживается нулевой байт (
$00).
Теперь посмотрим на места вызовов процедуры, чтобы узнать, какие там данные. Становимся на имя процедуры в
IDA, жмем клавишу
X, и видим три ссылки. Переходим по любой, и видим:
ROM:000040BA jsr sub_A2C
ROM:000040BE or.b $20(a2,d3.w),d0
ROM:000040C2 subq.w #4,d5
ROM:000040C2 ; ---------------------------------------------------------------------------
ROM:000040C4 dc.b $41 ; A
ROM:000040C5 dc.b $52 ; R
ROM:000040C6 dc.b $53 ; S
IDA коряво распознала данные, идущие за вызовом процедуры (оно и понятно, т.к. при
jsr ожидается, что возврат будет выполнен на последующий код. Поправим это.
Становимся на следующую за вызовом инструкцию, жмем
U.
ROM:000040BA jsr sub_A2C
ROM:000040BA ; ---------------------------------------------------------------------------
ROM:000040BE dc.b $80 ; А
ROM:000040BF dc.b $32 ; 2
ROM:000040C0 dc.b $30 ; 0
ROM:000040C1 dc.b $20
ROM:000040C2 dc.b $59 ; Y
ROM:000040C3 dc.b $45 ; E
ROM:000040C4 dc.b $41 ; A
ROM:000040C5 dc.b $52 ; R
ROM:000040C6 dc.b $53 ; S
ROM:000040C7 dc.b $20
ROM:000040C8 dc.b $4C ; L
ROM:000040C9 dc.b $41 ; A
ROM:000040CA dc.b $54 ; T
ROM:000040CB dc.b $45 ; E
ROM:000040CC dc.b $52 ; R
ROM:000040CD dc.b $2E ; .
ROM:000040CE dc.b 0
Ага, вот и текст!=)На этом все... Всем спасибо за внимание!=)
© Dr. MefistO [Lab 313]