This is intended to be a quick and dirty overview about how stuff is laid out in memory in BN.
All I/O on the GBA is done via a big-ass memory map that goes from address 0x00000000 to 0x0fffffff (roughly). For our intents and purposes, we only really need to care about two regions:
[0x02000000, 0x04000000): WRAM: This is where the working memory of the GBA is resident. In BN, starting at0x02000000, this is actually a copy of the save data (SRAM) after it has been decoded.- This is further split into EWRAM at
[0x02000000, 0x03000000)and IWRAM at[0x03000000, 0x04000000), but we don't have to care too much about this.
- This is further split into EWRAM at
[0x08000000, 0x0a000000): ROM: This is where the ROM on the GBA cartridge gets loaded.
In addition, in BN, there is an extra region that is not mapped to any physical memory:
[0x88000000, 0x8a000000): ROM (LZ77): This is a mirror of the ROM but when accessing from this region, the bytes at(addr ^ ~0x80000000)are decompressed using LZ77 first then a 4 byte header removed.
In Tango, rom::MemoryMapper takes care of this transparently.
The ROM is split up into two major segments. Note that since we're working with the assembled code, we don't know where exactly each segment starts and ends.
.text: This is where the code is stored. It starts at0x08000000and ends where the assembler decides to end it. Stuff that's stored here is:- Code: It's code!
- Data tables: e.g. chip info, NaviCust program info.
.data: This is whatever is after the.textsegment. Stuff that's stored here is:- Static palettes: 16 colors, colors encoded in BGR555. BGR555 conversion can be done with
component * 0xff / 0b11111. - Bitmaps: 8x8 tiles of palette-mapped bitmaps. Each byte actually packs two palette indices: the low nibble (
& 0xf) is the first pixel, the high nibble (>> 4) is the second. - Text archives: Where the text of the game (e.g. dialog, chip names, etc.) is stored.
- Sprite OAM entries: Don't need to care about this.
- Static palettes: 16 colors, colors encoded in BGR555. BGR555 conversion can be done with
When we want to access something outside of the text segment, we should take care to access it via a pointer in the text segment: the .text segment is unlikely to change in e.g. ROM hacks as it would require reassembly. Conversely, stuff in the .data segment is more freely movable and when using tools such as TextPet they will be moved around.
Text archives consist of a header and then data. The header is an index into the following entries. The text archive is variable length. Note that we also don't know where the text archive ends, because there is no final delimiter.
header: [u16; ...]
- header[0]: u16
- header[1]: u16
entries: [[u8; ...]; ...]
- entry[0]: [u8; ...]
- entry[1]: [u8; ...]
Each entry is a sequence of bytes. Any byte above 0xe5 is likely a command code. Common ones include (e.g. in BN1):
0xe5: Extension: This is a multibyte character. Take the next byte and add0xe5.0xe7: EOF: End of this entry.
Command codes may be multibyte. How long they are depends on the game in question.
In Tango, you can parse text archives using rom::text::parse and rom::text::parse_entry (probably more convenient).