PSX RAM map
The PlayStation has exactly 2 MB of main RAM, and everything the running game is - its code, the party's stats, the loaded scene, the story flags, the item bag - lives somewhere in that window. This map says what lives where: the big regions first, then the globals that anchor an explanation, each with the function or cheat code that pinned it.
At a glance
- Main RAM
- 2 MB at
0x80000000..0x801FFFFF; the 1 KB scratchpad at0x1F800000is separate silicon - Executable
SCUS_942.54loads at0x80010000(~960 KB of code + data); its data segment holds every persistent global- Game state block
0x80084140: four character records at0x80084708 + n*0x414, story flags0x80085600, item bag0x80085958- the bytes a save is composed from- Overlay window
0x801C0000+, 256 KB; field / battle / menu overlays all load at0x801CE818, one at a time- Mode selector
0x8007B83Cpicks which overlay's loop runs next frame- Provenance
- Each row names a
FUN_address, a dump file or the cheat code that pinned it - see how we know - Full table
docs/reference/memory-map.md- grep it for your address
Region map
| Range | Size | Holds |
|---|---|---|
0x80000000..0x8000FFFF | 64 KB | BIOS workspace: kernel, thread state, exception vectors. Game code never touches it. |
0x80010000..0x8005FFFF | 320 KB | SCUS_942.54 code: game logic plus the statically linked PsyQ libraries (libsnd, libspu, libcd, libapi). |
0x80060000..0x800FFFFF | 640 KB | SCUS_942.54 data: jump tables, static game tables, then the live game-state block and the battle actor pool. |
0x80100000..0x801BFFFF | 768 KB | Runtime data buffers: asset slabs (TIMs, TMDs, sound banks), per-scene state, the dialog buffer. |
0x801C0000..0x801FFFFF | 256 KB | Overlay window - the in-RAM PROT TOC at 0x801C70F0, one resident overlay at 0x801CE818, persistent effect state in 0x801F0000+, and the stack growing down from the top. |
0x1F800000..0x1F8003FF | 1 KB | PSX scratchpad - per-frame transients and the field-VM flag word. Table below. |
Interactive map
Order: low addresses on top. Hover for a one-liner, click for full detail.
Click any row above to see details.
How to read an address
- Every address is a PSX virtual address. Main RAM starts at
0x80000000, so0x80084708is byte0x84708into the 2 MB.DAT_8007B83Cis Ghidra's automatic label for data at that address, the wayFUN_8003E4E8labels a function (key functions). - The executable is only the bottom of the picture. Its data segment holds the persistent state, but most game logic lives in overlays - chunks of code streamed off the disc per game mode.
- An overlay-window address is ambiguous on its own. Field, battle and menu code all load at the same base and only one is resident, so the same address means different things in different modes. Rows in that range say which overlay they belong to.
0x1F800000is not main RAM. It is the scratchpad, and a flag a script tests may live there rather than in the 2 MB map.- "Exact semantics open" is a real value. Where a global is only partly understood the row says so rather than guessing.
Game-mode state machine
The game is a loop over a mode - title, field, battle, FMV, menu - and one cell picks which mode runs next frame. These are the companions of the 28-entry × 24-byte mode-dispatch table at 0x8007078C (the table itself is on the boot page).
| Address | Type | Purpose |
|---|---|---|
0x8007B83C | u16 | Next game-mode index (master mode selector): 0x02 field-launch, 0x03 field-run, 0x15 battle, 0x1A STR FMV. Also indexes the mode table, whose +0x14 param seeds the lower 16 bits of the field-VM flag word 0x1F800394 on each mode switch. The front end writes it six times on the way from the logo to the field, and each store lives in the handler that hands off - there is no table field naming the next mode, which is why a trace that samples the word once, early, reads the title screen as running under the logo-init mode rather than the card mode it actually runs under. |
0x8007B87C | index | Mode index rendered on the dev CONFIG / test screen; indexes the same table at stride 24, which independently confirms the entry stride. |
0x8007B7AC | mode | Reads as the outgoing / previous game mode: the mode-entry prologue gates its whole field-state snapshot on == 3 (MAIN MODE). An inference from the guard's purpose, not a pinned writer. |
Static (SCUS-resident) globals
These live in the executable's data segment and mean the same thing in every mode. The persistent game state - the values a save file is composed from - is all here.
| Address | Type | Purpose |
|---|---|---|
0x80084708 + n*0x414 | u8[0x414] | Per-character record (4 slots; display name at +0x2A7). Slot 3 (Terra) runs into the story-flag bitmap, so its tail aliases the globals. Layout: save record. |
0x80085600..0x80085800 | u8[512] | Story-flag bitmap window (Door of Wind, town-visited markers). |
0x80085758 | u8[] | Fourth flag bank - the bitfield the field-VM SET / CLEAR / TEST ops address as (idx >> 3, 0x80 >> (idx & 7)). The opcode encoding spans idx = 0x000..=0xFFF plus 0x8000..=0x8FFF, so it is not a fixed 256-bit array. |
0x80085958 | u8[] | Item inventory (= save block +0x1818), 2-byte stride (id, count). The active window is 128 or 256 slots - never 72, which is the "Have 99 Items" cheat's page span. Mechanism: inventory. |
0x80084540 | u16 | The loaded scene's raw CDNAME define - two above the extraction-frame index (town01 3, town0c 0x15). The "Map Modifier" cheat; View Credits writes 0x030C. |
0x80088758 / 0x8007B806 | record[] / s16 | Resident CDNAME define table (16-byte records, define at +0xC) and its count - what the Door items' travel arts scan for a destination. |
0x80073F00 | i16 | Dialog pager auto-press countdown: op 4C 89 sets it, and the waiting box presses confirm for the player when it runs out. |
0x80084570 | u32 | Game-time play counter - advances per frame (~60/s), not per second; the save screen divides it down for HH:MM:SS. |
0x80084594 / 0x80084598 | u8 / u8[] | Party member count / member ids (sorted insertion, cap 4). 0x80084599 / 0x8008459A are the Noa / Gala join gates. |
0x8008459C / 0x800845A4 | u32 | Party gold / casino coin bank. |
0x800845B4 | u32 | Point Card counter (unmapped by every public cheat archive). The shop buy commit accrues price/20 * qty when item 0xFE is held, capped at 9,999,999. |
0x8008444C | u32 | Persistent fishing-points counter; the lure row, rod stat and point-exchange purchase mask sit beside it at 0x80084450 / 0x80084454 / 0x8008446C (fishing). |
0x80077828 | u8[] | Per-monster steal table, 1-based id at +id*2, each entry [chance, item] - chance first. Not in the monster record. Steal table. |
0x80076C10 | u8[0x18] × 103 | Screen-element placement table - the content boxes every battle plate, party panel and Muscle Dome layout derives its chrome from. One table, three names. |
0x80074358 | 4×u32 | Active-ability bitmask; the party's per-character ability blocks are ORed into it each frame. |
0x8007A6BC | u16 | Shared "currently-acting character" HP/MP scratch - every "Infinite HP/MP" cheat hits this first. |
0x8007B450 | u16 | Menu-request register the menu overlay polls each frame; also the field-VM STATE_RESUME (op 0x49) tristate register. |
0x8007B5FC | u32 | Encounter step counter, one word across doors; every writer is the same reroll routine, from five sites ("No Random Battles" writes 0x0377). |
0x8007B6A8 | u8 | Save-anywhere allow flag: bit 0 of the scene header's second byte, stored at scene entry. The same bit raises the field-fog cap on every overworld. |
0x8007B6F4 / 0x8007B790 | u16 | GTE H projection register (focal length / zoom; the "camera mode word" and "small maps" labels come from a cheat database reading the same word outside world-map mode) / camera pitch, the first of the angle trio. |
0x8007BB80..0x8007BBA0 | u32 / i32 | Menu list-kernel state cluster: window-slide latch, pad-edge word, selected-row payload, scroll top, mode/result, selected row, class nibble, row count (field menu). |
0x8007BB04 / 0x8007BB08 | ptr | The overworld's screen-curvature pair: the second holds a quadratic drop ramp, the first the table of screen-Y offsets built from it, which the overworld's leaves, the fog and the drop shadow add to each vertex's screen Y. |
Battle globals
A battle is addressed through a handful of pointers and small per-seat arrays in the executable's data segment; the actors themselves live in a pool further up.
| Address | Type | Purpose |
|---|---|---|
0x8007BD24 → 0x800EB654 | ptr | Battle context pointer (0 in the field). +0x07 action-state cursor, +0x13 active slot, +0x276 tutorial byte, +0x279 cast-module phase, +0x28A battle-mode counter. |
0x801C9370 | ptr[8] | Battle actor pointer table: party in slots 0-2, monsters in 3-7. |
0x800EC9E8 + n*0x2D4 | u8[0x2D4] | Battle actor pool; HP at +0x14C, AP gauge at +0x170. Cheat citations. |
0x8007BD0C | u8[4] | Formation cell - per-slot monster id (monster m is actor slot m + 3). The AI picker switches on it, so each case is bespoke AI for one monster id. |
0x8007BD10 | u8[] | Per-seat character id, 1-based (1 Vahn, 2 Noa, 3 Gala): selects the record, the mesh install slot, the element row and the attack camera's jump table. |
0x8007BD74 | ptr | Side-band streaming buffer: one 0x10800-byte slot of summon.dat / readef.DAT at a time (summon / readef). |
0x8007B6D8 / 0x8007B724 | u16[4] / u32 | Pending-SFX cue ring (counter at battle ctx +0x9) / last-played SFX id, the cue router's dedupe compare. |
0x801F6950 | u32 | Battle-action overlay PRNG state - overlay-resident, so its draws never perturb the SCUS rand() stream. |
0x801F69D8 | u32 + code | Slot-B overlay window: PROT 0900's jump-table head, the world-map band, and the paged per-spell cast module while a capture-class cast runs. |
Asset chain and actor tables
How the loader and the renderer find what is resident: the in-RAM table of contents, the global mesh table every scene fills, and the linked lists the per-frame actor walk consumes.
| Address | Type | Purpose |
|---|---|---|
0x801C70F0 | TOC | In-RAM PROT.DAT TOC, populated at boot. An entry's size is the sector gap to the next entry (PROT.DAT). |
0x801C6EA4 | ptr | Current world / scene struct pointer. Its +0x2E is the submode stamp and +0x40 the parked return state - a write-only word: no image loads it at any width, and a live read watch across a submode enter records none. |
0x801C6ED8 | [CdlLOC, u32] × 34 | CD-XA streaming-clip table, slot i = file XA<i+1>.XA; built at boot by ISO9660 lookup, so it survives disc relayout (cutscene). |
0x8007C018 | ptr[N] | Global TMD pointer table, one writer. Entries [0..4] are the five character meshes; the rest is the scene's TMD pack. Details. |
0x8007B774 / 0x8007BB38 / 0x8007B824 / 0x8007B6F8 | u32 | Its install counter / last installed index / per-pack start index / kingdom-TMD prefix offset (how far world-map actor kinds are shifted past the party meshes). |
0x8007B7DC / 0x80083E58 | ptr / ptr[N] | VDF buffer pointer / its parallel sub-entry pointer table, consumed for actor instance bring-up. |
0x8007B888 / 0x8007B840 | ptr | MOVE / MOVE2 buffer bases (scene-dependent; not installed into the TMD table). |
0x8007C34C..0x8007C36C | u32[7] | Actor-list slot table: seven linked-list heads the per-frame actor walk dispatches through node[+0x0C]; five are separate render passes. |
0x8007C348 / 0x8007C364 | u32 | Actor allocator free-list stack / player context pointer (0x80083794 in the captures; +0x10 carries the encounter-active flag). |
0x801C6460 / 0x801C66A0 | u16[64] / slots | Scratchpad slot table written by op 0x4C / 64-slot ramp scheduler pool (stride 0x20). |
0x8007326C / 0x8007329C | rows / ptr[2] | TMD per-mode descriptor table (6 × 8 B) / two pointers between it and the widget class table - role unidentified, recorded so they are not read as the class table's head. |
The global TMD pointer table
Every populated entry [0..DAT_8007BB38] is a post-fixup Legaia TMD (magic 0x80000002, group descriptors at +0xC, stride 0x1C). The sole writer is the installer at FUN_80026B4C @ 0x80026BA8; its store through gp[+0x820] is what hides the walker counter from Ghidra's xref database. A settled field-scene snapshot (dolk) holds 143 entries: five character meshes from PROT 0874 section 0, then a contiguous 138-entry scene pack installed by the single descriptor walk. Type-0x05 slot-4 bodies never install here - only dispatcher cases 0x02 / 0x09 reach the installer. Consumers: the world-map top-view renderer, the SCUS and overlay actor allocators, the table walker and the per-party-member equipment-conditional group patch (character mesh).
0x80076C10 - one table, three names
Three subsystems index this array and each named it after itself - a battle "pose-slot array", the party-panel "publish target", the Muscle Dome "element layout table". They cite the same base and the same 0x18 stride; a record is a screen-element placement. The clone helper FUN_801D5778 writes dst[+0xA] = src[+0xA] - 0x140, and 0x140 is 320, the display width: the field is a screen X and the operation is "stage this element one screen to the left".
| Offset | Field |
|---|---|
+0x00 / +0x01 | element id, seat A / seat B (usually equal; records 41 / 42 carry them byte-swapped) |
+0x02 / +0x04 | seat A x / y |
+0x06 / +0x08 | content width / box height, shared by both seats (0x0C for the plate-run family; roster panels 50, framed windows 120 / 42 / 28 / 26) |
+0x0A / +0x0C | seat B x / y - the pair FUN_801D5778 pushes by a screen width; which seat is parked is per record, so "from / to" is the safe name |
+0x0E / +0x0F | kind, seat A / seat B |
+0x10 / +0x12 | 13 on the framed-window and roster rows, else 0, and no spawn arm reads it / zero in all 103 records |
+0x14 | content string pointer, measured by the rendered-width kernel FUN_80035F04 into +0x06; the battle name plaque points it at the actor's display-name buffer actor+0x1BC (not an animation descriptor) |
103 initialised records run 0x80076C10..0x800775B8; index 129 would be the steal table, and the placement shape stops at 103 (every coordinate within ±416). A record is a content box; the chrome is derived, not stored - pen = (x, y - 2), plate = (x - 8, y - 6) sized (w + 16, 20). Parser legaia_asset::screen_elements; packet evidence on battle.
Sound + audio path
The sound subsystem keeps a small cluster of path strings and state words in BSS - what tells the loader to look under sound\, which bank is resident, and the handshake that swaps one BGM for another.
| Address | Purpose | |
|---|---|---|
0x8007B380..0x8007B3DC | Per-extension flag/mode table plus the path-string cluster ("sound\", ".spk", ".LZS", "bse.dat", ".dpk", ".MAP", ".PCH", ".pac", "STR"). 0x8007B3A4 in the middle is not sound data - it is the equipment-swap selector table (character mesh). | |
0x8007B750 | Sound flag word coordinating the BGM track-swap handshake (bit 1 pause, bit 3 load settled, bit 4 release ack) - audio. | |
0x8007B8D0 | Sound subsystem current-bundle pointer (gp+0x5B8): bse.dat's 0x1800-byte buffer during battle, repointed at a scene's prescript bundle on every field load - bse.dat. | |
0x8007B64B | u8 | Backdrop last-object keep flag (gp+0x333): zero means the battle loader FUN_800513F0 trims object index 1 from both backdrop actors; one writer, the field handoff FUN_801D9E1C. |
0x8007B990 | Runtime SFX descriptor-bank record table (gp+0x678), bse.dat's in battle. Written once by FUN_8001FA88; read by the cue router FUN_8004FE5C and the overlay-0971 sound test, both rewriting byte +4 (category) of record[cue_id - 0x200]. | |
0x8007B910 / 0x8008457C | Live audio level (0..255, halved into libsnd's 0..0x7F by every reader) / its persistent reference. Not screen brightness - that is 0x8007B440. | |
0x8007BB20..0x8007BB34 | Timed sound-source auto-release: armed flag, latched level, caller tag, deadline, elapsed (advanced by the tick byte, so the deadline is cadence-invariant). | |
0x8007BAC8 / 0x8007BC64 | BGM request id / the music_01 bank's raw define (990): the pool base for ids ≥ 2000 (music tracks), and for a scene-local id the fallback load + 2 - global slot 2, never a scene bank. The request id has four writers on the whole disc, all in the field overlay: the music opcode’s two arms, the developer menu’s sound-test row, and a conditional clear inside the per-scene initializer - so the scene loader clears the track and the script installs it. | |
0x80070536 | Bound voice id of the field-BGM sound source, written at track attach. | |
0x800788B8 | Streamed-voice clip duration table, 0x110 entries (index = cue id − 0x100), read by the arts shout and the Seru cast voice alike. Live rows run to 0x10F with interior zero runs; neither reader bounds the index, so a consumer modelling a shorter table drops the high cues in silence. | |
0x8007B854 | Ambient-particle master gate. One field-VM opcode raises it and its neighbour clears it, both stores in a jump delay slot; of its six references disc-wide none is pad state, so a field script decides per scene whether ambience emits at all. | |
0x801CD2B8 / 0x801CD2C0 | SsAPI slot-allocation bitmap / 16-entry per-slot sequence-state pointer table. | |
0x8007BD30 / 0x8007BD5C | Effect-runtime pool (16-byte head + 128 child + 32 master slots) / effect 2-pack wrapper buffer pointer - effect VM. | |
0x8007B7F8 / 0x8007B81C | Cosine / sine views of the shared trig LUT (4096 * sin over 5120 i16 entries at 0x80070A2C - one revolution plus the quarter turn cosine needs, which is why consumers mask the angle with 0xFFF). |
Debug flags and the pad
| Address | Purpose |
|---|---|
0x8007B8C2 | Dev/retail loader-path selector: 40 lh reads, written once at cold boot to 1. Details. |
0x8007B98F | In-game debug menu enable - byte 3 of the debug-mode word 0x8007B98C. Poking it to 1 brings up the debug menu on SELECT+Triangle (dev menu). |
0x8007B7C0 / 0x8007B450 | Debug-dispatch trigger / parameter slot. |
0x8007B850 | Per-frame held button mask, packed (face/shoulder byte in bits 0-7, dpad/system byte in bits 8-15); port 1 fills the high half only in debug mode. Engine mirror retail_pad. |
0x8007B7C4 / 0x8007B874 | Changed-this-frame mask / newly-pressed edge mask. |
0x80089128 / 0x8007B938 / 0x8007B93C | 32-entry held-mask history ring / its AND (held for the full window) / the auto-repeat pulse the menus use, rearming every 8 vsyncs. |
0x8007B868 | Dev/dual-mode gate the actor-sound family checks (retail 0); its only stores are a boot store of a constant 0 and a bit-clear, so the developer screens it gates (Baka Fighter's keyframe editor among them) are unreachable on a retail disc. |
0x8007B8C2 - the build-mode selector
Every one of its 40 read sites splits the same way: non-zero opens assets by PROT-TOC index through the in-RAM table; zero opens by filename through FUN_800608F0, whose whole body is break 0x103 - a PsyQ dev-station host trap retail hardware cannot service. main() writes the halfword once at cold boot:
80015f00 jal 0x8003F084 ; two-instruction leaf: returns 1
80015f04 nop
80015f08 sh v0,0x5aa(gp) ; gp = 0x8007B318, so EA = 0x8007B8C2
The store is gp-relative, which is why sweeps for the absolute lui 0x8008 form reported no writer. BSS zero-init does not establish it - the PS-X EXE header carries b_size = 0. The field-VM flag ops cannot reach it either: their index window is [0x80085758, 0x80086957] and the move-VM's signed operand reaches down only to 0x80084758, both above it. A from-scratch engine treats both flags as build-time constants.
JP retail uses build-shifted addresses (+0x1B90 for the debug-menu enable).
Cheat-database code-patch sites
0x2400 is the MIPS nop; a cheat that writes it is patching an instruction, which makes these useful Ghidra anchors.
| Address | Effect | Cheat |
|---|---|---|
0x800422F4 | Inventory-add count = 99 | Bought Any Item / Find Items You Will Get 99 Quantity |
0x8004309E | Inventory count-decrement nop | Infinite Items All Slots |
0x80043910 | Vahn chest draw-call nop | Remove Vahn's Chest |
0x8007EA96 | HP-write branch nop | Maxed HP for All Characters |
The cheat-pinned mini-game cells (fishing tension 0x801D9168, Baka Fighter life 0x801DBFC4, dance points 0x801D53CC, slot-machine punch mode 0x801D3CAC) are on the cheats page.
PSX scratchpad (0x1F800000..0x1F8003FF)
The PSX has 1 KB of fast on-chip RAM here. Legaia uses the high end for per-frame state:
| Address | Type | Purpose |
|---|---|---|
0x1F800314 | i16[] / ctx | Inverted-Y mirror table (op 0x4C nibble-9 sub-E); also the draw-context base whose +0x6A is the depth clip bound and +0x74..+0x7A the 2-D clip rect. |
0x1F80037E | u16 | Near cutoff - a segment whose two transformed Z both fall inside it is rejected. |
0x1F800393 | u8 | Per-frame tick byte - the global frame-time scalar read by WAIT_FRAMES, subtracted from the title-attract countdown, and exposed as World::tick_move_vms_with_delta in the port. |
0x1F800394 | u32 | Field-VM transient flag word - not persisted, distinct from the saved story-flag bitmap. Set/clear/tested by ops 0x2E/0x2F/0x30; lower 16 bits re-seeded on every mode switch. Bit 0x40 is a scene-transition-pending flag, not a "dialog active" lock. Bit 0 is set exactly on the kingdom overworlds, where it gives the fog spawner its depth-tested, lifted arm. |
0x1F8003A0 | ptr | Active primitive/packet write cursor the POLY_* emitters allocate from. |
0x1F80037C | u8 | Current walk-region kind; 0 disables the camera scroll clamp. |
0x1F800384..87 | 4 × u8 | Current walk-region AABB in tiles. |
0x1F8003E8..EB | 4 × i8 | Camera visible tile window [nearX, nearZ, farX, farZ], signed tile offsets from the camera tile; written by FUN_801DBC20 and op 0x46, read by the render library's cell emitters, the scroll clamp FUN_801DAA50, the ambient emitter and the dev menu. |
0x801F2778..84 | 4 × i32 | Write-only mirrors of the window; no reader on the disc. |
0x800846D0..DC | 4 × u32 | Button-mask config words; 0x800846DC = 0x48 (Cross | R1) is the field run button, seeded once by FUN_80034A6C and never rewritten. |
0x1F8003EC | u8[] | Tile-flag bitmap base used by op 0x4C nibble-7 and the walkability grid at +0x4000 (field locomotion). |
0x1F8003F8 / 0x1F8003FA | i16 | Camera-scroll values used by the op 0x23 player path. |
Overlay window (0x801C0000+)
The 256 KB overlay window is shared between several runtime overlays - only one is loaded at any time. Static analysis only sees what was loaded at the time of capture, which is why the repo keeps a separate import per overlay.
| RAM range | Overlay | Subsystems |
|---|---|---|
0x801C0000+ | Title screen | Menu window-widget interpreter (FUN_801D6628); title-overlay tick FUN_801DD35C |
0x801CE818+ | Town / field / dialog (PROT 0897) | Field VM (FUN_801DE840), MES renderer, inventory hub, MAIN INIT |
0x801CE818+ | Battle (PROT 0898) | Per-actor state machine, battle main dispatcher, effect VM cluster |
0x801CE818+ | Options / pause / save / shop menu (PROT 0899) | In-game menu UI |
0x801EF018 | Title-overlay state struct | +0x154 = attract countdown (init 0x8000, underflow → mode 0x1A → MV1.STR); +0x158 = title frame counter |
0x801F0000+ | Persistent band | Survives overlay swaps: battle effect helpers (0x801F5D90, 0x801F5CF8, the particle cluster at 0x801F8004+), the world-map emitter gate and camera state 0x801F3518..0x801F3528, field-overlay effect descriptors from 0x801F291C |
0x801F69D8 | Slot B | Streamed sidecar modules - see battle globals |
Each mini-game likewise gets its own slab of upper RAM, loaded fresh when entered. Menu-overlay cells worth knowing: 0x801E46B0 is the selected item id for the description box (<= 0 draws nothing) and 0x801E46D0 the packed toggle-state word for the options window.
History: the "PROT 0896 @ 0x801C5818" menu-overlay base
An earlier attribution placed the menu overlay at PROT 0896, base 0x801C5818. That base was an over-read artifact of the superseded entry-size expression: the menu overlay is PROT 0899 at 0x801CE818, and live field captures hold an ISO9660 directory cache at 0x801C5818. Catalogued in do not re-walk.
How we know
Ghidra's reference manager does not resolve MIPS lui+addiu pairs or gp-relative stores, so most of these rows were pinned by a writer hunt (Ghidra tooling), a save-state diff, or a cheat code that names the cell.
| Function | Address | What it proves | Dump |
|---|---|---|---|
main() | FUN_80015E90 @ 0x80015F08 | The one gp-relative store that sets the build-mode selector to 1 | ghidra/scripts/funcs/80015e90.txt |
| Pad reader | FUN_8001822C | The packed held / changed / edge masks and the debug-mode gate on port 1 | funcs/8001822c.txt |
| Mode-switch prologue | FUN_8001DCF8 @ 0x8001E17C | Sole non-RMW writer of the field-VM flag word's low 16 bits | funcs/8001dcf8.txt |
| Mode-entry snapshot | FUN_80016230 | Gates the field-state snapshot on 0x8007B7AC == 3 | funcs/80016230.txt |
| CONFIG screen | FUN_800188C8 | Indexes the mode table at stride 24 - confirms the entry stride | funcs/800188c8.txt |
| Overworld curvature builder | FUN_800271A8 | The two 0x8000-byte buffers: a drop ramp and the screen-Y curvature table | funcs/800271a8.txt |
| TMD installer | FUN_80026B4C @ 0x80026BA8 | Sole writer of the global TMD table; the hidden gp[+0x820] counter store | funcs/80026b4c.txt |
| Flag ops | FUN_8003CE08 / _CE34 / _CE64 | The fourth flag bank's (idx >> 3, 0x80 >> (idx & 7)) addressing | funcs/8003ce08.txt |
| Inventory window installer | FUN_8004313C | The only writer of the bag's active window (128 or 256 slots) | funcs/8004313c.txt |
| Placement clone | FUN_801D5778 | dst[+0xA] = src[+0xA] - 0x140: the field is a screen X | funcs/overlay_battle_action_801d5778.txt |
| Shop buy commit | FUN_801DB7F4 | The Point Card accrual into 0x800845B4 | funcs/overlay_shop_save_801db7f4.txt |
| Monster AI picker | FUN_801E9FD4 @ 0x801EB73C | Switches on the formation cell - per-monster-id AI | funcs/overlay_battle_action_801e9fd4.txt |
| Cheat corpus | 557 GameShark / PAR codes | Names the game-state cells directly; none targets the build-mode or debug-menu flags | cheats |
| Save-state library | 60 captured states | 0x8007B8C2 reads 1 in all of them; the TMD table snapshots (dolk, geremi) | mednafen automation |