zladx / ladx-disassembly Goto Github PK
View Code? Open in Web Editor NEWDisassembly of Legend of Zelda: Links Awakening DX
Disassembly of Legend of Zelda: Links Awakening DX
Some notes while I'm here, since I got pinged and figured I'd drop by.
E
: Advance 5 bytes (warp data)C
: Advance 3 bytes (vertical object)8
: Advance 3 bytes (horizontal object)D
, B
, A
, 9
: ¯\_(ツ)_/¯ These don't seem to ever be used by the game.F
, 0-7
: Advance 2 bytes (standard object)map_parser.py
currently treats any FE
as an end-of-room marker, but this appears in warp data for a few rooms (namely Overworld13
and OverworldE3
, maybe others)DungeonsAUnreferenced00
and DungeonsAUnreferenced01
seem to be leftover end-of-room bytes! Kinda weird that they come right after two of the Instrument rooms...DungeonsAUnreferenced02
is the alternate Goriya room you see when you have the Magnifying Glass.DungeonsAUnreferenced03
and beyond are the Color Dungeon pointers (and rooms). You might need to add a manual exception for this in your parser.Beyond that, nice work! I see it also handled the bizarre ordering of Overworld63
well.
Link's Awakening supports Super GameBoy features – that is, displaying this nice colored frame.
The Super GameBoy communication works by sending commands on the Joypad control bits.
The first command is used to detect the SGB presence. Then the subsequent commands tell the Super GameBoy to upload some frame data (tiles, tilemap and palettes).
Between each command, the code busy-loops to wait for the command completion.
The global structure of the code is pretty much figured out (see src/code/super_gameboy.asm). What needs to be done is:
For now color palettes are stored as sequences of bytes.
They would be easier to read with an RBG() macro, that would emit the correct bytes at compile-time.
Now that mgbdis
can disassemble banks almost perfectly, we could add the remaining banks so that the disassembly is stand-alone, and doesn't require the original ROM to fill in the blanks.
Of course much of the disassembled code would actually be data, but this can be fixed later.
64 banks in the original ROM.
See the ROM map for details.
Currently there’s an entity named Octorok
, and one named WingedOctorock
. We should pick a spelling, and rename the entities to have a consistent naming.
peach.tilemap
and peach.attrmap
are committed, but none of the other decoded files are; should they be?convert_background.py decode
on menu_file_selection.tilemap.encoded
and menu_file_selection.attrmap.encoded
fails with an IndexError
. I think this is because they fallthrough into the subsequent tilemap03
data. It might be more useful to combine those files, and instead of the Tilemap03
and Attrmap03
pointers, store either a raw address (like the ._07 dw $D651
) or an offset from the base pointer (e.g. dw MenuFileSelectionAttrmap + $0123
).Tilemap06
and Tilemap09
might also belong combined with another file. This would explain why some decoded files fail to open in Tilemap Studio, e.g. inventory.tilemap
complains "Attrmap is longer than tilemap."There's a list that matches music tracks ids to names – but it seems to be invalid: many names are not the correct ones. (See src/constants/sfx.asm)
By listening to each music track, the constants could be renamed to have the correct names.
Listening to a specific music track id in-game is easy:
$FFB0
(hMusicTrack
), and write a track ID;Each room has a tilemap ID. And a tilemap ID is not an exact resource: a custom handler will load the tilemap, by compositing several tileset fragments into memory.
There handlers are defined at TilemapLoadingHandlersTable
(
LADX-Disassembly/src/code/bank20.asm
Line 1091 in 8f50f17
We should re-label and document the tilemap loaders.
There a huge jump table, jumping to the code for handling every type of entity. It should be easy to track the code it jumps to.
https://github.com/zladx/LADX-Disassembly/blob/master/src/code/entities/_handlers_table.asm#L13
TODO
code/entities
directoryFor now a few pieces of the room-loading code are well-documented:
However converting room objects into actual background tiles requires more than the tileset. It needs to convert the objects into the indices of actual tiles.
$4567
in the order specified by data at $5678
"test.php
): in the code there must be a place where the matching between objects and tiles is done, for reference.LINK_MOTION_UNKNOWN_0A is used in a couple of places (mostly related to the Blaino mini boss), but it is not clear yet what it does.
Find out, and then rename the LINK_MOTION_UNKNOWN_0A
constant accordingly.
The game engine supports loading a BG tilemap asynchronously: the game code requests a BG map to be loaded by writing to wBGMapToLoad
, and later, during the next V-Blank interrupt, the V-Blank interrupt handler copies the requested tilemap to VRAM.
For now the BG maps are stored sequentially in src/data/backgrounds/background_tile_commands.asm
– a file generated automatically by tools/generate_background_data.py
, which dumps these data from the original game. They are named BackgroundTileCommands01
, BackgroundTileCommands02
, and so on.
We should identify and name these BG maps.
The relevant steps could be (with one PR for each step):
BGMAP_*****
constants to src/constants/gfx.asm
, and name them accordingly.BackgroundTileCommands01
is the title screen BG map, we should create a BGMAP_TITLE_SCREEN equ $01
constant.BGMapTitleScreen::
) instead of automatic labels (BackgroundTileCommands01
).revisions/
, by storing only the relevant BG maps that diverge from revision to revision, instead of storing the whole BG maps.NB : additionnaly, once all of this is done, we could write a Python script that can decompress and re-compress BG maps. This would allow to store the BG maps uncompressed, (so they can be easily changed using a tile editor). The BG maps would be re-compressed to the original commands-based format at compile-time.
There are several variables controlling the music track playback:
hMusicTrack
,hNextMusicTrack
,wActiveMusicTrack
These variables are often used together, but seem to have subtle differences (like one of these seems to have immediate effect, and another to store the track to be played after a transition).
We should understand better what these variables do (and maybe rename some of them accordingly).
In src/data/backgrounds/
are some tilemaps that have no name (like tilemap_03, tilemap_06, tilemap_09, etc).
They seem to be related to the inventory, but they are not named yet.
We should understand what they do, and name them accordingly.
Hi! First, great job on this!
I have some questions about the process:
How did you manage to rip all text dialogues?
I know some Game Boy ROMs that have compressed graphics. How do you guarantee that only converting ROM banks will give you all graphics data from the game?
Is there any plan on music and SFX? Maybe a tool or technique to rip that?
Cheers!
The file src/ROM map.md
is formatted such that all banks appear on the same line when viewed in a web browser, rather than each bank on its own line as was likely intended. Consider adding backslashes to the end of each line to insert line breaks, or structure the map as a table.
palettes.asm
has some wrong comments, and data not marked as pointers while they are (and thus labels are missing).
We should turn these data blocks into proper pointers.
For rooms on maps > $0A, background palette data is found by:
Data_021_4413
which is indexed by MapID - $0A
Data_021_443F
which are pointers to the actual palette data.It would be nice to have each PR tested, to ensure the compiled output is still the identical to the original file.
Maybe with a Gitlab-CI integration, or CircleCI.
Since the revisions PR, make
builds all revisions and languages by default.
But make
without arguments is often use to check that the ROM builds correctly. It should be fast by default.
make all
could be used to build all the languages and revisions.
For now a few pieces of the room-loading code are well-documented:
However the code indicating which entities are in a given room, and what is their initial position is still undocumented.
For now there's a few blobs of binary data sorted out as base_map
.
I don't actually really know what these binary data are used for. Are they pointer tables? A list of tilesets?
test.php
), so maybe it uses these base_map
somehow.For now maps have their header and blocks data disassembled, but not their warp data.
From the LALE hacking notes:
Warps
Each screen can have one warp5-Byte Warps
- First byte = Area Type (E tells it to be a warp, 2 = area type)
- 00 = overworld
- 01 = dungeons A
- 02 = dungeons B
- Second byte = Dungeon map (00 = Level 1, 01 = Level 2, etc)
- Third byte = Dest Room (Must be in map of the dest dungeon)
- Fourth byte = X (Tile x, extra X)
- Fifth byte = Y (Add 10, starts at header)
These Warp data can probably be parsed and disassembled to a readable ASM format (by a script similar to tools/generate_map_data.py).
This repo is marked as being a fork of iimarckus/gb-bootstrap, but it isn't really one any more. It might be worth considering asking support to change this into a normal repo for that reason
Not sure if they'll need more information, but the first commit that started this repo seems to be cd58d92 (with 645df59 being the last one from iimarckus/gb-bootstrap)
Has anyone actually managed to use the Nintendo Gigaleak actual source files for Links Awakening DX as a reference for this project?
Sounds effects (i.e. jingles, waveform-based sfx and noise-based sfx) are generated in https://github.com/zladx/LADX-Disassembly/blob/master/src/code/audio/sfx.asm.
The format seems pretty straightforward; probably no op-codes are involved. Still, the code needs documentation, and at least labeling of the different sound effects.
For now map headers data is not separated from the map blocks.
It looks like this:
Overworld00::
db $0B, $E5, $8A, $00, $00, $8A, $10, $00, $8A, $20, $EF, $10, $7C, $11, $7D, $19, $7C, $13, $80, $84, $14, $4D, $17, $81, $23, $37, $83, $24, $0A, $27, $38, $32, $1D, $33, $2E, $34, $48, $36, $49, $37, $4E, $38, $5D, $41, $1D, $42, $37, $43, $39, $44, $E1, $E1, $07, $3A, $58, $10, $82, $45, $3A, $C2, $35, $E0, $47, $3B, $48, $38, $50, $1D, $C3, $51, $37, $C2, $52, $37, $85, $53, $09, $82, $58, $7A, $C2, $60, $37, $85, $63, $09, $68, $38, $72, $2E, $85, $73, $2F, $78, $4E, $69, $50, $79, $09, $FE
This should be improved, by:
tools/generate_map_data.py
) ;data/blocks/overworld_00.blk
).It could look like this:
Overworld00::
db ANIMATION_TARAMANCH ; animated tiles set
db WALLS_NONE | FLOOR_MOUNTAINS ; walls and floor type
incbin 'data/blocks/overworld_00.blk'
All this data is already parsed by tools/generate_map_data.py. It should just be a matter of augmenting the script to output the right informations.
For now a few pieces of the room-loading code are well-documented:
However the code indicating which chests are in a room, and what they contains is undocumented.
Most speed-related variables are named Speed
-Something – but some still use the outdated Velocity
name.
We should rename variables and comments so that “speed” is used everywhere.
When we test the target, md5sum currently prints a warning for each missing file.
azle.gbc: OK
md5sum: stat 'azle-r1.gbc': No such file or directory
md5sum: stat 'azle-r2.gbc': No such file or directory
md5sum: stat 'azlg.gbc': No such file or directory
md5sum: stat 'azlg-r1.gbc': No such file or directory
md5sum: stat 'azlj.gbc': No such file or directory
md5sum: stat 'azlj-r1.gbc': No such file or directory
md5sum: stat 'azlj-r2.gbc': No such file or directory
md5sum: stat 'azlf.gbc': No such file or directory
md5sum: stat 'azlf-r1.gbc': No such file or directory
Instead the make test
target should ignore the missing files.
md5sum
seems to have an --ignore-missing
option, but it doesn't seem to work on macOS. Maybe we'll have to re-implement a small md5sum from scratch.
Some music-generating code has been reverse-engineered (see src/code/audio/music.asm
), but the actual soundtrack has not been disassembled yet.
Forgive me but why are there 61 banks of disassembled data? I thought there should be only 16 banks?
I'm new to this disassembly project but when I run make
it gives me an error:
Error: file not found (../../Zelda.gbc)Makefile:25: recipe for target 'bin/banks/bank_00_0.bin' failed
Is there more to this than simply running make
?
ROM hacks are much easier if code can be added and removed without breaking the game.
For this, all ROM raw addresses need to be labeled. That means turning all direct ROM references (e.g. call $1234
) into a label (e.g. call Func_000_1234
).
(Documenting the label, e.g. call AnimateEntities
is a nice-to-have, but is not strictly required.)
Progress can be tracked by running tools/stats.sh
, which counts the number of remaining raw addresses that need to be labeled.
tools/stats.sh --verbose
.tools/data_to_asm.py <start address> <end address>
The purpose of some audio opcodes is still unknown. We should figure them out.
Each entity has an initialization handler, a function executed once when the entity is initialized.
Extract and label the table and functions of these handlers.
misc_cgb.png
is apparently at least two different graphics: one spritesheet for the photographer, and credits gfx. It should be split it two PNG files.
Many places in the code still have sound effects (sfx, or music tracks) referenced by a numeric value. For instance:
ld a, $35
ld [hNextMusicTrack], a
We should ensure that everywhere in the code, these numeric values are replaced by proper constants (found in constants/sfx.asm
). For instance:
ld a, MUSIC_MAMUS_SONG
ld [hNextMusicTrack], a
A little cutscene plays when taking each photo picture. These cutscenes are defined in https://github.com/zladx/LADX-Disassembly/blob/master/src/code/photos.asm.
Each cutscene is splitted into several small fragments:
These steps are not labeled for now. It should be relatively easy to understand what each step does.
The wGameplaySubtype
variable (at $DB96
) controls the steps of a cutscene: by watching its value change during gameplay in a debugger, it should help understand which step is what.
To access each cutscene individually, you can either:
$DB95
in a debugger to a value between $0E
and 1A
, and $DB96
to 0
. This will bring you directly to the cutscene.ROM_DebugTool3
value. Then use the built-in debug commands to access a fully-filled photo album.Tiles data are stored as PNG files. However sometimes the 4-tiles objects are not aligned: instead they are split between multiple rows or columns.
These files should be converted to a PNG layout easier to edit. The original layout of the binary file could be restored at compile time.
Different projects have different methods to deal with this issue. One is to add special commands to the PNG filename (like .w16.interleave.png
), and then to use pret's gfx.py
tool to convert the PNG back to 2bpp.
However this requires users building the code to have a working Python2 installation on their computer.
Another solution would be to add support for interleaved formats to rgbgfx
(which is in C, bundled with rgbasm
, and generally quite fast). But that's more code to write.
(Also pokecrystal
has an intermediary solution with a Python script wrapping the original gfx.py
; this may be a thing to look at).
At 01:5DE6 sees to be the code for saving the game data to the battery-powered save area.
The format of the saved data has been reverse-engineered, but it is not documented in the disassembly yet.
Maps data location has been documented in other projects. It consists of:
The code for parsing and loading the map data has been partially reverse-engineered and documented to a good extend (see for instance CopyMapToTileMapLoop
in src/bank0.asm
).
However the map data is still in binary form. It could be mangled into a format similar to what pokered uses : a mix of self-described assembly for data-structures, and bin files for data.
This probably involves writing a Python script to parse the overworld and dungeon map data, and write:
The best documentation available about the map data format probably lies in the source of the LALE Zelda Level Editor. Other fragments are available on various web pages:
Link sprite sheet (and NPCs sprite sheets in general) are PNG files, but those are not easy to understand. For a start, the palette seems wrong.
Example of Link's PNG sprite sheet with an incorrect palette
We should edit these PNG sprite sheets to make them easier to edit–beginning with fixing the palette of the PNG files (while still compiling to the same .2bpp
in the end).
rgbgfx
seems to have support for alternate grayscale palettes. Probably the PNG files can be re-extracted using a better palette, and then rgbgfx
invoked with the correct options would be able to compile the file back to the original .2bpp
.
From @Xkeeper0
DungeonsAUnreferenced03 and beyond are the Color Dungeon pointers (and rooms). You might need to add a manual exception for this in your parser.
This means the Color Dungeon map starts at 0x2BB77
.
The map parser should be edited to:
The code for entities AI (i.e. actors, NPCs, enemies, etc) has been entirely decompiled. But much of the code is still undocumented.
A useful task is to pick one of the entities (the files in the src/code/entities/
directory), analyze how it works, and label the functions to document its behavior.
labels.asm
contains a medium-sized list of pre-generated labels.
This is rather kludgy: labels should resolve to either:
For now disassemblies are generated using a fork of the mgbdis
disassembler (https://github.com/kemenaran/mgbdis), with a few cosmetic changes.
This fork should be referenced in the project, so that we know which version of the fork is used for disassembling.
Hello, I'm a beginner to disassembling as well as using GitHub so I'm sorry if this issue is not very well written.
Typing make all
into the command prompt results in the following errors:
File not found - *.asm
File not found - *.png
rgbasm -E -i src/ -o src/main.o src/main.asm
error: Unable to open incbin file 'gfx/characters/link_1.dmg.2bpp'
make: *** [src/main.o] Error 1
Here is a list of things I've tried to resolve the issue, sorted from most prevalent to least prevalent:
shell
command (used for the asm_files
and gfx_files
variables) with the bash
command in the makefile resulted in resolving the "file not found" errors however it still would not compile due to the RGBDS error.OS: Windows 10
Programs used:
When inserting bytes at the beginning of bank 20, Link's palette becomes corrupted.
This is probably because some pointers to palette data in bank 20 are not labeled properly.
Several unknown entities are unused throughout the code.
These are mostly visible in the entities handlers table: all the entities labeled EntityXXXHandler
are not used in the final game–but point to actual code.
For instance these two ones (but there are others)
LADX-Disassembly/src/code/entities/_handlers_table.asm
Lines 120 to 121 in 7f2c25b
It could be interesting to understand what where these entities, and why they were eventually left out of the final game.
Maybe some leftover elements mentioned on The Cutting Room Floor could provide some hints.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.