В рамках вот этой темы решил покопаться в потрохах GameBoy'евской Зельды. Вначале через эмулятор BGB. Там, конечно, и дизассемблер есть, и отладчик, но всё равно мало что понятно - хочется иметь полный листинг перед глазами, чтобы можно было процедуры и переменные переименовать для более глубокого понимания. Попробовал разные инструменты, которые смог найти, а именно:
1. Эмуляторы BGB и no$gmb. Результат обоих эмуляторов совершенно одинаков, видимо, они близкие родственники. В общем-то, из них можно выгрузить дизассемблер доступной для Z80 памяти, но там есть лишние колонки и работать с метками в текстовом редакторе в итоге оказывается, мягко говоря, не слишком удобно. Опять же, нет доступа к коду, который располагается в неактивных в данный момент банках ПЗУ.
Код:
ROM0:28C5 2A ldi a,(hl)
ROM0:28C6 12 ld (de),a
ROM0:28C7 13 inc de
ROM0:28C8 0B dec bc
ROM0:28C9 78 ld a,b
ROM0:28CA B1 or c
ROM0:28CB 20 F8 jr nz,28C5
ROM0:28CD C9 ret
2. gb-disasm - результат понравился. На выходе имеем полноценный листинг. Кроме того, данный дизассемблер пытается понять, что было переключение банка памяти и дизассемблирует этот дополнительный код. Но в результате работы остаётся слишком много мест, которые данный дизассемблер отказывается распознавать. В результате имеем такой листинг:
Код:
jmp_8b:
LD A,$0C
LD [$2100],A
RET
INCBIN "Legend of Zelda, The - Link's Awakening (USA, Europe).gb",$91,$100-$91
NOP
JP jmp_150
INCBIN "Legend of Zelda, The - Link's Awakening (USA, Europe).gb",$104,$150-$104
jmp_150:
CALL sub_2881
LD SP,$DFFF
XOR A
LDH [$47],A ;bg pal
LDH [$48],A ;obj pal0
LDH [$49],A ;obj pal1
LD HL,$8000
LD BC,$1800
CALL sub_2999
CALL sub_28a8
CALL sub_298a
3. GameBoy Assembler Plus - может дизассемблировать куски кода, но при попытке дизассемблировать весь ROM начисто вешается. Получаемый листинг имеет такой вид:
Код:
#org 28C5
Label28C5:
ldi a,(hl)
ld (de),a
inc de
dec bc
ld a,b
or a,c
jr nz,Label28C5
ret
4. IDA Pro - хотя эта программа в моём списке и последняя, но этот инструмент, самый первый, который приходит в голову, когда хочется что-то дизассемблировать. Инструмент очень мощный, с кучей возможностей, но, к сожалению, в силу отсутствия опыта и полноценной документации, у меня до конца не получается настроить эту среду на работу с образом GB-игры.
Прежде всего я снял дамп памяти из эмуляторы и с помощью IDA Pro попытался дизассемблировать его. Попереименовывал некоторые переменные и процедуры. Всё здорово: меняешь в одном месте - меняется везде! Кое-что с кодом начало проясняться. Но вот я добрался до переключения банков памяти. По началу всё было нормально - переключение использовалось для переброса данных из дополнительной памяти в ВидеоОЗУ. Но потом я добрался до таких конструкций:
Код:
ROM:03B5 ld a, 1
ROM:03B7 ld [BANK], a
ROM:03BA call sub_5D03
ROM:03BD ld a, $1F
ROM:03BF ld [BANK], a
ROM:03C2 call loc_7F80
Инструкция ld [BANK],a включает в адресное пространство #4000-#7FFF банк памяти, указанный в регистре a. И видно, что после этого вызывается код из этих страниц. В эмуляторе я могу всё это протрассировать, но как поступить в IDA Pro? Всё, что у меня получается сделать - это жёстко задать в указанном диапазоне какую-то одну страницу.
Поискал как народ поступает. Но всё, что удалось найти - это только лоадер, который сам разбивает память на сегменты, распознаёт заголовок и задаёт имя стандартным системным переменным. Однако при использовании данного лоадера вообще игнорируется код, который располагается выше #4000. То есть дизассемблировать можно только первые 16к картриджа.
Не может быть, чтобы такая мощная программа, как IDA Pro, не умела бы переключать страницы ПЗУ! Но вот у меня никак не получается Может быть кто-то, кто более продвинут в IDA Pro, подскажет как это сделать? Или есть ещё какие-то мысли?