devlog.

Project · Dataset

AtlasGB

Memory maps for Game Boy cartridges where every claim carries the evidence for itself. Maps for these games already exist, and they are transcriptions — somebody read an address once and everybody since has copied it. AtlasGB asks each row how do you know? and stores the answer next to it.

2,898
Evidenced claims
39
Covered by an invariant
7
Marked unevidenced, on purpose
0
Entries disagreeing with the cartridge

One atlas is published: Pokémon Red and Blue, English USA/Europe. Work RAM and high RAM are fully accounted for with no holes. The two games build from one source and share their work RAM map, so one atlas covers both.

What it does

The product

One file per cartridge

  • A tab-separated file is the source of truth. Every page, index, table and JSON file in the repository is generated from it
  • Each row: region, bank, address, length, symbol, role, section, group, evidence tier, description
  • Atlas content is CC BY-SA 4.0; tooling and schema are MIT. The boundary is a path, not a judgement call

Evidence

Three tiers, or none

  • R — the address appears in the ROM image as the operand of an instruction that takes one. A byte scan, so it records the hit count; one hit is weak, dozens is a real address. It cannot produce a false negative
  • L — the byte changed while the cartridge ran a fixed button script on a cycle-accurate emulator, from a cold boot with no save
  • I — a hand-written check proved the entry means what it says, not merely that it exists. The only tier that can catch an address which is real, live, and describing the wrong thing
  • An entry with none of the three says so

How the tiers are produced

By a run, not by hand

  • Proving an address against a running cartridge needs an emulator, so the tiers arrive as a report from TerminalGB
  • The evidence record stores the run's provenance and a SHA-256 of the evidence column it produced. Editing a tier by hand turns CI red
  • Adding a symbol without re-running verification also turns CI red: the atlas grew, so the last run no longer covers it
  • The digest is over symbol → tier only, so rewording a description does not invalidate a run

Invariants

Deliberately not clever

  • Every nybble of the money field must be 0–9, because it is packed decimal
  • The party arrays must agree three ways — the count, the flat species list, and the species inside each 44-byte structure
  • Every species you carry, converted through the Pokédex-order table read out of the cartridge, must have its bit set in the owned bitfield. Shifting that table by one byte breaks it
  • A check that cannot prove what it looks like it proves reports that, rather than a pass it has not earned

The evidence, counted

1,419 claims are backed by both the ROM and a live run. A further 1,239 are live-only and 141 ROM-only. 39 carry an invariant, 34 of those on top of both other tiers. 60 carry nothing.

0 2,898 CLAIMS R the cartridge names it 1,594 · 55.0% L observed live 2,694 · 93.0% I an invariant covers it 39 · 1.3% · no token at all 60 · 2.1% The tiers are not exclusive: 1,419 claims carry both R and L, and 34 carry all three. Only 3 claims rest on an invariant alone.
Read straight from the atlas file, and reproducing the repository's own committed evidence record exactly.

The sixty with nothing

Most of the gap is not a check that failed to run. It is a gap in what the checks are built to look at.

WhatCountWhy it has nothing
ROM routines and data tables53 The operand scan is scoped to RAM addresses — the right question for a byte of storage, the wrong one for a routine's entry point. The live sweep cannot apply either, because a ROM byte never changes. Three are covered by a byte-signature content check; the other 50 have no method wired up, and the method already exists.
Storage bytes the script never touches3 Real work-RAM addresses that need a battle, a full sprite roster or a storage box. Extending the button script closes these.
Cartridge-RAM free markers4 These rows assert "this byte is unallocated", to keep the completeness invariant honest. Nothing about a cartridge run can confirm or deny that.

Separately, seven storage entries carry no evidence and are listed by name in the evidence record. The validator prints them on every run so they cannot quietly disappear.

Limits worth knowing

Milestones

25 Aug 2026

Re-verified from scratch, zero entries moved

The tiers were produced again against a second independent boot of the same cartridge and save, run twice for determinism. Both runs were byte-identical and both agreed with the published run. The atlas's 2,898 claims disagree with the cartridge in zero places.

24 Aug 2026

Writer-group linkage, measured rather than named

A tool steps a real playthrough and records which code writes each address, when and to what. Grouping by the writing routine produced real linkage — a sound engine initialising nine channel fields together, two shadow sprite slots never touched independently. Six of thirty-one measured groups were written up; the rest were held back because the prose did not yet stand behind them.

23 Aug 2026

TACKLE is 95 per cent

A number this atlas had published was computed from a percentage rather than read from the cartridge, and it had propagated into three other files. Read it →

Writing


Where these numbers come from

The claim and tier counts are read from the atlas's own source of truth and cross-checked against the committed evidence record, which names the emulator commit that produced the run, the cartridge by title, region and SHA-1, the script that was played, and the run date of 25 Aug 2026.

The addresses, symbol names and structure layouts are facts about the cartridge, derived from a built pret/pokered checkout. The names are the disassembly projects' work and are not claimed here; their prose is not ours to copy, so every description is written from scratch. No ROM is distributed — the reproduction commands point at your own. Pokémon, Game Boy and Nintendo are trade marks of their respective owners.

← All projects