Cartridge boot · address space filled at load

ludexel.gba — where the bytes land when the game starts.

build 0.9.286
rom 354,344 B
elf .text 0x10ec0 · .rodata 0x43df0
generated from build/ludexel.map

A Game Boy Advance has nine distinct memory regions, each mapped at a fixed base address. When the BIOS hands control to the cartridge, code and data land in specific places — some copied out of ROM into fast RAM, some streamed straight into video memory, some initialised by the engine. The bars below show this project's footprint in each region, sized against the region's real capacity. Segments fill in boot order.

Occupied by engine Full / saturated Asset payload Free — headroom
Base · end
Region · occupancy
Capacity
0x00000000
0x00003FFF
ROM

System BIOS

Nintendo · read-only · not writable

Mapped by the hardware, not the cart. Contains the boot animation, SWI handlers, and interrupt vector. Our code never lives here; we only call into it (SWI 0x05 VBlankIntrWait, 0x0B CpuFastSet).

Nintendo firmware · 16,384 B
0x000016 KiB · 100% by vendor
16
KiB
not ours
0x02000000
0x0203FFFF
RW · slow

External Work RAM · EWRAM

256 KiB · 16-bit bus · 3-cycle access

The big pool. Slower than IWRAM but eight times larger. In this build the linker reports .ewram at 0 bytes — every runtime buffer fits in IWRAM, and EWRAM is reserved as scratch for future dialogue / scene buffers.

headroom · 262,144 B
0x02000000256 KiB · 0% used
256
KiB
0% used
0x03000000
0x03007FFF
RW · fast

Internal Work RAM · IWRAM

32 KiB · 32-bit bus · 1-cycle access · CPU stack lives here

At boot the runtime copies .data (6,452 B of initialised globals) from ROM to 0x0300163C, and zero-fills .bss (5,692 B) at 0x03000000. The rest is stack + free heap for actor state, dialogue working set, and save I/O buffers.

.bss · 5,692 B
.data · 6,452 B
stack + free · ≈20,624 B
0x0300000032 KiB · 37% engine
.bss (zero-init globals)5,692 · 0x163c
.data (copied from ROM)6,452 · 0x1934
stack + heap headroom20,624 · 0x5090
32
KiB
37% engine
0x04000000
0x040003FE
MMIO

I/O registers

1 KiB window · memory-mapped hardware

Not really "memory" — the PPU, DMA, sound, timer, and input registers all sit in this window. Every frame the engine writes DISPCNT, BGxCNT, palette-bank IO, and the DMA channels here.

hardware register file · fully mapped
0x040000001 KiB · fixed layout
1
KiB
fixed
0x05000000
0x050003FF
RW

Palette RAM

1 KiB · 512 colours · 15-bit BGR

Split in two 512-byte halves: BG palette at 0x05000000, OBJ palette at 0x05000200. Each half holds 16 banks × 16 colours. Ludexel uses bank 0 for the shared UI palette; text-bar slots 4–10 hold the HP/XP blue, track, green, yellow, red, and platform shadow. Slot 5 and slots 11–15 are free — the reserved room for the pending MP palette entry.

BG palette · used slots
BG · free (6 slots)
OBJ palette · sprites
0x050000001024 B · 6 BG slots free
1
KiB
~94% used
0x06000000
0x06017FFF
RW · video

Video RAM · VRAM

96 KiB · 4 BG charblocks × 16 KiB, plus OBJ tile pool

The busiest region at boot. Overworld map tiles fill charblock 0. Text and UI share charblock 2 as FONT_CHARBLOCK — 512 tiles, and every slot is taken (font glyphs, box corners, platform tiles, HP/XP/track/yellow/red bar tiles). This is the structural blocker preventing a distinct MP bar tile without a screenblock relocation.

CBB 0 · overworld tiles
CBB 1 · text SB
CBB 2 · FONT · FULL
CBB 3 · notif+menu SB
OBJ tiles · sprites
0x0600000096 KiB · font block saturated
CBB 0 — overworld background tiles16,384 · 0x4000
CBB 1 — text screenblock 12 tucked inside16,384 · 0x4000
CBB 2 — FONT_CHARBLOCK · 512/512 tiles16,384 · 0x4000
CBB 3 — notif SB 26 + menu SB 2816,384 · 0x4000
OBJ tile pool — hero, NPCs, effects32,768 · 0x8000
96
KiB
~100% claimed
0x07000000
0x070003FF
RW · sprites

Object Attribute Memory · OAM

1 KiB · 128 sprite entries × 8 B + 32 affine matrices

Each visible sprite (hero, NPCs, portal arrow, battle animations, notification icons) occupies one 8-byte OAM slot. The engine reserves fixed IDs for the HUD and fills the rest per-scene.

128 sprite attrs · shared pool
affine transforms · 32×
unused this scene
0x070000001024 B · scene-dependent fill
1
KiB
~85% live
0x08000000
0x0806FFFF
ROM · WS0

Cartridge ROM · Wait State 0

Up to 32 MiB addressable · this cart uses 346 KiB

Where every byte of ludexel.gba lives. Code (.text) is executed in place from ROM. Read-only data (.rodata — tilesets, maps, audio, dialogue, portraits) is huge compared to code: assets outweigh code 4:1. The .data initialiser image sits at the tail; the BIOS copies it into IWRAM before main() runs.

.text · 68 KiB code
.rodata · 271 KiB assets
.data init image · 6 KiB
padding
0x08000000346 KiB used · 1% of 32 MiB address space
.text — engine code69,312 · 0x10ec0
.rodata — tiles / maps / audio / dialogue277,488 · 0x43df0
.data — IWRAM initialiser image6,452 · 0x1934
alignment padding to nearest KiB1,092 · 0x0444
346
KiB used
1.05% of 32 MiB
0x0E000000
0x0E007FFF
RW · battery

Cartridge SRAM · save memory

64 KiB addressable · this cart claims the first 32 KiB

Only the first 32 KiB is wired. Three save slots × 8 KiB (0x0000, 0x2000, 0x4000), then the debug-warp block at 0x7000. Each slot holds a SaveData struct — 4,200 B today — leaving generous headroom per slot for roster growth.

slot 0 · 4,200 B
slot 1 · 4,200 B
slot 2 · 4,200 B
debug warp
unmapped · upper 32 KiB
0x0E00000032 KiB used of 64 KiB
32
KiB used
50% claimed
Numbers from build/ludexel.map and arm-none-eabi-size ludexel.elf on build 0.9.286. Charblock accounting from src/engine/text.c, notification.c, menu_runtime.c. Save layout from src/engine/save.h.
Rendered —