jevsnes.git / packages / alttp / README.md
1# Chapter 3: alttp, reading Hyrule out of 128 KiB
2
3Chapter 2 gave us the machine's work RAM: 131,072 bytes that change sixty
4times a second. Somewhere in there is everything the game knows. Byte
5`$7E0010` says which part of the game is running (the title, the overworld,
6a dungeon, a text box). `$7E0022` and `$7E0020` are Link's position in
7pixels. `$7EF36D` is his health, in eighths of a heart, because that is how
8the HUD draws half and quarter hearts.
9
10This crate turns those bytes into names. Hand it the whole of work RAM and
11you get a `State` back:
12
13```rust
14let state = alttp::State::read(console.wram());
15state.mode      // Mode::Overworld
16state.step      // what that mode is doing, by the game's own table
17state.world     // World::Light or World::Dark
18state.place     // Place::Outdoors(area) or Place::Indoors(room)
19state.hearts()  // 3.5
20state.control   // whether the pad moves Link this very frame
21```
22
23It is `Serialize`, so the same value is what the window's State panel
24shows (chapter 7) and what the MCP `state` tool returns (chapter 8).
25
26> **Aside: where do the names come from?** Not from guessing. The game was
27> taken apart long ago by the romhacking community, and
28> [snesrev/zelda3](https://github.com/snesrev/zelda3) is a C
29> reimplementation that compiles to a bit-exact match of the real ROM. A
30> mode's name here is the name of the routine the game's own dispatch table
31> jumps to for that byte, and each table is cited on the type it produced.
32> A byte with no table behind it stays `Unrecognised(byte)` or `Numbered`,
33> carrying its value, rather than getting a plausible name.
34
35The most careful function in here is `has_control`. "Link is in a walking
36mode" is not the same as "the player's buttons move him": four other flags
37(a spell animation, an immobilised flag, a menu block, and on the overworld a
38special-entrance trigger) can each hold him in place. The rule is copied out
39of the two functions in the game that enforce it, and a test sets each flag
40in turn to prove each one takes control away.
41
42`Mode::kind` sorts every mode into what a caller has to do about it (play,
43an overlay, a title, a load that ends by itself, ...), and it has no wildcard
44arm: a new mode is a compile error until someone says which kind it is.
45
46> **Try it.** `nix develop -c buck2 test //packages/alttp:test` runs the
47> control-gate tests, the text-box test and the opening-flags test. No ROM
48> needed: they build work RAM by hand.
49
50## For the people who maintain it
51
52### In this folder
53
54| Path | What |
55| --- | --- |
56| [src/lib.rs](src/lib.rs) | `State::read` and its parts: `Mode` and `Kind`, `Step` and `Interface`, `World`, `Place`, `Player` (Link's state machine), `Progress`, `Opening`, `Follower`, `Direction`; the control gate; the tests. |
57| [BUCK](BUCK) | The `rust_library` (its only dependency is `serde`) and `//packages/alttp:test`. |
58
59The addresses and what they mean come from
60[research/alttp-ram-map.md](../../research/alttp-ram-map.md), which cites
61the disassemblies it read them from. Who reads a `State`: `packages/panels`,
62`packages/mcp`, `packages/zbanks` (its stall detector uses `Place`), and the
63apps.
64
65← Previous: [Chapter 2, console/](../console/) · Up: [packages](../) · Next: [Chapter 4, zbanks/](../zbanks/) →