# bit Generations: Orbital — ROM map

Reference ROM: `bit Generations - Orbital (Japan) (En).gba`,
`16,777,216 bytes`, `sha1 437e3093928ce9b0705476053a059d70f9f84ae3`.
Title `ORBITAL`, gamecode `BVEJ`, maker `01`.
Built output `build/orbital.gba` is byte-identical to it (`tools/build_rom.py`).

## Layout

| File off | ROM addr | Size | Kind | Source |
|---|---|---|---|---|
| `0x000000` | `08000000` | `0xC0` | GBA header | `assets/header.bin` (byte-exact copy) |
| `0x0000C0` | `080000C0` | 268B | ARM boot (crt0 + memfill + memcpy) | `src/matched/Boot_Init.s`, also `assets/boot.bin` view |
| `0x0000C0` | `080000C0` | 127,564B | Thumb code | **built** from `asm/all_stubs.s` (`tools/gen_stubs.py` from `function_list_v2.txt`) |
| `0x01F30C` | `0801F30C` | ~44KB | rodata: assert strings (`STAGE`/`EXTRA`/`FINAL`, `Internal Error`, `src/*.h|*.cc`, `%02d...`, build stamp `Dec 22 2005 15:39:53`) + word tables | `assets/rodata.bin` |
| `0x027904`+ | `08027904`+ | — | table cluster (string + int sequences, `0x0666` word runs) | inside rodata/tail |
| `0x02A700` | `0802A700` | rest | data tail (gfx tiles, palettes, level data, samples) | `assets/chunks/chunk_XXXXXX.bin` (254 x 64KB) |

Code section ends where assert strings begin (`0x0801F30C`); stub image is
`0 diffs` (`tools/validate_code_section.py`).

## Pointer index

`assets/tables.json`: 284 distinct `08xxxxxx` targets referenced from code
(aligned words; `09xxxxxx` values are data, not ROM addresses — ROM ends at
`08FFFFFF`). Heavy buckets: `0802xxxx` (161 targets, rodata/tables),
`08020000–08030000` (144), `>=08400000` (82: gfx/level/sound banks),
`08CAxxxx` (76: float/bignum const tables).

## Compression

None found: every `0x10/0x20/0x30` magic hit fails strict GBA decompression
(they are Thumb-code coincidences). High-entropy blocks (`0x200000`,
`0x400000`, `0xC00000`) are raw packed data, not BIOS formats. Graphics are
stored raw (see below).

## Graphics (v1, heuristic)

`tools/decode_gfx.py` renders `assets/gfx/` (stdlib-only PNG writer):
8 auto-found RGB555 palettes (`palette_NN.pal` + swatch, 32+ distinct colors
required to reject code-filler runs like `0x1111`) and 5 tile-sheet offsets
(`0x800000` probe + top tile-likeness windows: `0x228000`, `0x284000`,
`0x8BC000`, `0xB40000`), each as 4bpp-grayscale plus recolors with the top 2
palettes (`assets/gfx/index.json`). Sheets show real tile data; in-game
tilemap layout is not yet reconstructed. Raw `.bin` blobs stay the build
source of truth.

## Header quirk

Header complement byte `0xBD` is `0xBC` on disk but computes to `0xD5` over
`0xA0–0xBC` — the header is preserved byte-exact, never recomputed.

## Round-trip

```bash
python3 tools/extract_assets.py   # ROM -> assets/ (258 regions, lossless)
python3 tools/decode_gfx.py       # assets/ -> assets/gfx/*.png
python3 tools/build_rom.py        # assets/ + asm/all_stubs.s -> build/orbital.gba (sha1-verified)
```

`assets/` and `build/` are generated and gitignored; the tools that produce
them are tracked. Next step (moddable rebuild): replace a blob at its
manifest offset/size and rebuild — offsets stay stable, verification stays
`sha1`.
