Place names Confirmed
"Rim Elm", "Sol Tower", "Ancient Wind Cave" - a place name shows up in three spots while you play: the quick-travel list, the label floating over the world map, and the banner that slides in when you walk into a town. Each of those reads its own copy off the disc. There is no single name table, which is why a rename that only edits the well-known executable table leaves the world map and the entry banner still saying the old name.
At a glance
- Magic
- none - three carriers: a static table in
SCUS_942.54, the trailer of each kingdom MAN, and section 2 of each scene MAN - Where
- site 1:
0x80073B18(16 cells); site 2: pointerDAT_80073EE0into the kingdom MAN trailer (29 records); site 3:_DAT_801C6EA0into the scene MAN - Parsers
legaia_game_tables::worldmap_menu(site 1),legaia_scene_formats::place_names(sites 2 and 3); editorlegaia-patcher --rename-locationedits all three together- Confidence
- Confirmed - layouts read off the disc, both MAN consumers pinned live, and a rename read back out of RAM on a patched disc
- Used by
- World overview (quick-travel table), Game world, Randomizer, ROM patcher
The three carriers
One name, three displays, three byte layouts. The shared cap for a rename is 23 characters - the tightest of the three.
| Site | What it draws | Carrier | Shape |
|---|---|---|---|
| 1 | the quick-travel / Door-of-Wind destination list | SCUS_942.54 0x80073B18 | 16 fixed 0x20-byte NUL-padded cells |
| 2 | the labels drawn over the world map at each place's position | the trailer of every kingdom MAN (map01 / map02 / map03) | [u8 count][count x 0x20 record] |
| 3 | the banner on entering a scene, and the save-screen location row | each scene MAN's section 2 | bare strlen + 1 NUL-terminated string |
The three name spaces are not the same set. Site 1 holds 16 names; site 2 holds 29, naming 14 places the quick-travel menu has no room for (Hunter's Spring, Mt. Rikuroa, Snowdrift Cave, the Voz Forests, Zeto's Dungeon, Shadow Gate, Sol Tower, Nivora Ravine and so on). Site 3 holds one name per scene bundle, so a multi-scene place repeats its name - Sol Tower across 13 bundles, Rim Elm across 7. Near-miss names are genuinely distinct strings: site 1's "Sol" is not site 2's "Sol Tower".
Site 2 - the world-map location table
MAN section 5 is the chain terminator in every scene bundle, so its "body" is whatever trails the chain. In the three kingdom MANs that trailing data is the location table, and the MAN walker installs a pointer to its count byte (how we know). All three kingdom MANs carry a byte-identical copy of the whole 29-record table, filtered by region at draw time - so a rename must edit every kingdom MAN, not just the one whose continent the place sits on.
The table is a u8 count followed by count fixed 32-byte records:
| Field | Meaning |
|---|---|
region | 0 = Drake, 1 = Sebucus, 2 = Karisto |
x, y | map position in tiles; world coordinate = value << 7 |
flag | discovery flag, queried through FUN_8003CE64 (0x0484..0x04A0; the two element caves share 0x048E and differ by region). Unaligned - it straddles the record's first word. |
| reserved | zero across the retail corpus |
| name | 24 bytes including the terminating NUL, so at most 23 characters - the shared rename cap |
The per-frame label pass in the map display module (PROT 0981, game mode 0x0D - the screen L1 opens on a kingdom map) draws each record whose region matches the current kingdom and whose discovery flag is set (or the show-all debug flag is on): project the map position to the screen, draw the name, measure it, and draw a dialog-skin window as wide as the name around it. So the name is drawn at the place's own map position, gated on having discovered it, inside a box of its own width (the screen around the loop is on world map) (how we know).
Site 3 - the scene display name
MAN section 2's body is the scene's display name. The MAN walker installs the body pointer and, as the last
act of the same load, puts the name on screen itself: when system flag 2 is set and the name is
not empty, it spawns the ordinary one-line text balloon with the name as its line, then clears the flag either way.
The banner is that balloon - centred, 120 frames, no panel of its own - and because the loader gives it no parent
script, talking to someone while it is up dismisses it. The flag is raised by scripts in the three kingdom
(world-map) MANs: leaving the overworld for a place announces the place. The body is not padded -
exactly strlen + 1 bytes - so a longer name means resizing the section.
Separately, the field overlay's fade state machines copy the name into a global buffer, and the menu overlay reads that copy twice, both times for the save screen: once to draw the save-slot location row, once to copy it into the save block's location field. That is why a save state captured mid-scene holds the last scene entered in that buffer: it is filled at save time from the copy, not per frame.
How site 3 was pinned
The banner spawn is read off the MAN walker's disassembly (0x8003BB40..0x8003BBDC). The fade state machines were once taken for the banner, but the panel script they run (0x801F32B4) only closes every panel; they just latch the name. A breakpoint on the glyph renderer FUN_80036888 across an overworld-into-town transition captures the banner draw arriving with a0 == _DAT_801C6EA0, spelling the scene's section-2 name. Probe: scripts/pcsx-redux/autorun_location_banner_source.lua.
How we know
All three layouts are read off the disc; both MAN consumers are traced in the disassembly and the banner draw is confirmed live; and a rename on a patched disc reads back out of RAM at every site.
Provenance: routines and probes
| Function | Address | What it proves | Dump / probe |
|---|---|---|---|
| MAN walker | FUN_8003AEB0 | Installs the site-2 table pointer (DAT_80073EE0) and the site-3 body pointer (_DAT_801C6EA0) | funcs/8003aeb0.txt |
| Map-display label pass | 0x801CF368..0x801CF438 (PROT 0981); discovery query FUN_8003CE64, projection FUN_8003D368, glyph draw FUN_80036888, measure FUN_80035F04 | Per-record region filter, discovery gate (dev show-all _DAT_8007B868), draw-at-map-position | funcs/overlay_monster_test_0981_801ce850.txt |
| Banner spawn | FUN_8003AEB0 0x8003BB40..0x8003BBDC | Name + system flag 2 gate a text-balloon spawn (template 0x8007431C); the flag is cleared on every path | funcs/8003aeb0.txt; live probe autorun_location_banner_source.lua |
| Save-screen latch | fade state machines, stores at 0x801EE638 / 0x801EAC7C / 0x801EEAE4 | The section-2 pointer copied into _DAT_8007B44C; their panel script 0x801F32B4 only closes every panel | PROT 0897 image |
| Save-screen readers | 0x801E1D9C (row draw), 0x801E1A28 (copy to SC block +0x200) | The latch's two menu-overlay consumers - both save-screen, neither per-frame | menu-overlay dumps |
| Patched-disc read-back | - | A rename re-parses at every site; resized banner + edited world-map table read back out of live RAM | patched-disc round trip |
Editing a name
- Site 1 - same-size overwrite of a 32-byte cell, zero-padded.
- Site 2 - same-size overwrite of the record's 24-byte name field, then an LZS re-pack of each kingdom MAN.
- Site 3 - resize the section. No relocation work is needed: the partition tables and
u24_at_28address the region before section 0, and sections 3..5 are reached by walking the chain, so rewriting section 2's length prefix moves every later section correctly by construction. What must move is the MAN's decompressed size in the scene bundle's descriptor word (scene_asset_table::encode_size_word). - Every scene MAN is the last asset in its bundle, so the re-packed stream can grow into the entry's sector padding (smallest headroom in the corpus ~430 bytes). Clamp the budget to the entry's true footprint, never to an over-reading length.
- Two scene bundles (one of them
bubu1) declare five descriptors rather than the usual six or seven; a MAN finder must walk the descriptor table leniently, as the runtime walker does, and confirm the find by decoding it. - Ten scene MANs carry an untranslated Shift-JIS name in section 2 (the ending scenes plus
other7) and seven carry an empty one; both read as "no name".