At a glance

Naming
FUN_8003E4E8 = the function whose first instruction sits at RAM 0x8003E4E8; DAT_ / PTR_ mark data and pointer tables the same way. "JT" is a jump table.
Resident code
0x80010000..0x8007B800 - the executable SCUS_942.54, always loaded
Overlay code
0x801C0000+ - one game-mode overlay paged in at a time (field, battle, menu, title, cutscene)
Dumps
ghidra/scripts/funcs/<addr>.txt, overlays as overlay_<label>_<addr>.txt (gitignored: Sony-derived; regenerable via Ghidra tooling)
Full directory
Eleven Markdown pages under docs/reference/functions/ - list below
Status per function
Port catalog (dumped / documented / ported)

How to read an entry

The game shipped with no symbol names, so the address is the name and it is stable across every doc and probe in this project. Four things catch people out:

SCUS_942.54 (resident) one function per address, always loaded Overlay window field / battle / menu / title / cutscene - one at a time 0x80010000 0x8007B800 0x801C0000 0x80200000 …
One address in the overlay window can name a different function depending on which overlay was resident when the dump was taken.
TrapWhat to do
Overlay addresses collide. Several overlays share 0x801C0000+.If an entry does not match the code you are reading, check which overlay you have first - overlay capture, overlay window.
"No static caller in SCUS" does not mean dead. Most game logic lives in overlays.Zero callers in the executable means "needs an overlay sweep", not "unused".
Some printed addresses are phantoms. A dump can show a real body beside a VA no runtime image ever used.Before treating an unfamiliar 0x801E… / 0x8020… as new, check overlay VA aliases.
Decompiled C is a rendering. Ghidra promotes intra-function labels to fake FUN_ calls, drops register arguments, reorders stores.Read the disassembly; the artifact catalogue is on the Ghidra page.

Not finding an address here does not mean it is unknown - this page covers the functions that anchor an explanation somewhere on the site.

Highlights by subsystem

Boot + asset loader

How the disc's single big archive (PROT.DAT) gets found, indexed and streamed into RAM.

FunctionRole
FUN_8003E4E8Boot-time TOC loader: first 3 sectors of PROT.DAT into 0x801C70F0
FUN_8003E8A8LBA resolver against the in-RAM TOC
FUN_8003E6BCPath-based file opener (data\battle\efect.dat etc.)
FUN_8003EBE4 / FUN_8003EC70Overlay loaders A / B; two overlays resident at once. B pages in the per-summon Seru-magic overlays
FUN_8001F05CAsset-type dispatcher (type byte → handler)
FUN_80020224Descriptor-pair walker
FUN_8002541CStreaming-asset driver
FUN_80021934Scene-transition streaming actor: streams the destination scene bundle, then hands off to MAIN INIT
Deep dive: overlay loader indexing and the scene-transition actor
  • Loader argument param + 0x381 is a raw TOC index = extraction entry param + 0x37F (the resolver indexes the raw in-RAM PROT head, two above extraction numbering). A player Seru-magic cast (spell id 0x81..0x8B) calls FUN_8003EC70(id - 0x79) → extraction PROT 903..913; the summon's models live in those overlays plus the extraction-0871 etmd.dat library, not in befect_data.
  • FUN_80021934 is a 5-state machine over actor+0x1A (jump table 0x80010760); its real entry is 3 instructions before the 0x80021940 prologue. Spawned by FUN_8001FD44 via FUN_80020DE0 from the descriptor at 0x80070734 (the phase-misaligned family 0x800705FC..0x80070763, not a mode-table row). Streams DATA_FIELD\<scene>.LZS (raw scene_base+3) into _DAT_8007B85C - by PROT index in dev (state 2), by filename in retail (state 4) - then sets _DAT_8007B83C = 2. Dump funcs/80021940.txt.

Game VMs

The bytecode interpreters that run scenes, menus, moves and actor motion - most of the game's logic is script, not native code.

FunctionRole
FUN_801DE840Field / event script VM (43 ops, switch at 0x801E00F4)
FUN_801E0C3CField-VM op 0x4C second-stage dispatcher (16-entry JT 0x801CEE60)
FUN_801E3040Op 0x4C nibble-0xE sub-dispatcher (15-entry JT 0x801CF008)
FUN_801E30E4Op 0x4C 0xE2 FMV trigger: FMV index → _DAT_8007BA78, mode 0x1A → _DAT_8007B83C
FUN_8003CE9CField-VM context resolver (sign-extended u16 read)
FUN_80023070Move-table VM (71 ops, JT 0x80010778)
FUN_801D362CMove-VM extension (61 sub-ops via op 0x2F); one copy, in the field overlay - the world-map, dialog and cutscene modes run on that overlay, not on copies of their own. Its one outward call is the scanline strip emitter FUN_801D31B0
FUN_801D6628Window-widget ("actor") VM of the menu overlay (13 ops, JT 0x801CED70)
FUN_80038158Per-actor motion / bytecode VM; ops 7 / 8 set / clear story flags in DAT_80085758
FUN_8002519CPer-frame actor-list tick iterator (5× per frame from FUN_80016444)
FUN_80021DF4Per-frame actor tick
FUN_800204F8Move-buffer setup (Tactical Arts)
FUN_8003A1E4Field-NPC placement installer; its tail pre-runs the script prologue, which is where a never-walked NPC's initial facing comes from
Deep dive: motion-VM flag writes and NPC initial facing
  • FUN_80038158 is dispatched by FUN_8003BC08 when actor +0x10 & 0x80. Its bytecode is MAN tail-section 1 (installer FUN_8003A9D4, parser legaia_asset::man_motion). The chapter-spine gates 0x142 / 0x482 / 0x1BE and the town01 one-shot 549 appear in no motion stream: the first three are field-VM script bytes, 549 is a direct code path.
  • FUN_8003A1E4 reads [model, anim, tile_x, tile_z] - no facing byte. Its tail (0x8003A474..0x8003A4F8) executes a script's leading ops through FUN_801DE840 when the script opens with op 0x24 / 0x25, until a 0x21 NOP or a sub-0x20 byte; ops 0x4C 0x51 sub-1 and 0x38 write actor+0x26 from the 8-direction heading LUT at 0x80073F04. Port man_field_scripts::placement_initial_facing + World::seed_field_npc_facings; see field locomotion.

Cutscene, FMV and camera

The movie player, the CD-XA voice streamer, and the field camera the story scenes drive.

FunctionRole
FUN_801CEA3CSTR / MDEC master dispatch (cutscene overlay 0970, modes 26 / 27): decoder select, letterbox, play loop, return-scene hand-off
FUN_801CF098FMV main play loop; pad-abort honoured only for fmv_id 0
FUN_8005F024STR frame-demux state machine (St library; ring API FUN_8005BBF8 / FUN_8005EF40 / FUN_8005EE4C)
FUN_8003D764XA-clip drive sequencer / channel selector, armed off the 34-slot XA1..XA34 table at 0x801C6ED8
FUN_8003BDE0Partition-record → VM-context dispatcher: named record + 3 story-flag gates, then script entry
FUN_80037174Narration crawl roller (the [CC F8 80 N] op), spawned as a child context so the timeline keeps running
FUN_8003C764On-screen text-balloon spawner (op 4C E1); centred, Y=180, 120-frame pages - not the opening crawl
FUN_8003C83CField-VM cross-context resolver (0xF8 player / camera anchor, 0xFB system)
FUN_801DB8ECCamera focus + projection setter (ops 0x4C 0x39 / 0x3E) - focus and FOV, not eye position
FUN_801DBC20Camera-zone config loader: splits the 18-byte camera-region record into the camera globals
0x801D0A6C (data)FMV dispatch table, 23 × 32 B (legaia_asset::fmv_dispatch)
0x801CAE08 (data)libcd CdlFILE directory cache
Deep dive: gate math and the camera cluster
  • FUN_8003BDE0(x, z, record, gate): gate C1 blocks if any flag set in DAT_80085758, C2 requires all; script entry at 1 + name_len*2 + (1+C0) + (1+C1*2) + (1+C2*2). Callers: field-VM op 0x44 (ra 0x801DF098) and the walk-on trigger FUN_801D1EC4 → FUN_801D5630 (ra 0x801D218C).
  • FUN_8003D764 sequence: CdlSeekL → Setmode 0xC8 → CdlSetloc → CdlSetfilter {file 1, chan} → CdlReadS → CdlGetlocP poll; armed by FUN_8003D53C / FUN_8003EAE4.
  • FUN_801DB8EC calls FUN_801DAB90(transform, 0x801F3580), sets GTE H from _DAT_8007B6F4, and writes focus globals _DAT_80089118 / _DAT_80089120: tile-derived when camera-mode nibble DAT_8007B607>>4 == 5, else anchor-follow. Eye-back depth lives in the op-0x45 translation trio's slot 5 (_DAT_800840C0).
  • FUN_801DBC20 keys on mode nibble byte[5] >> 4 (3 look-at-anchor, 5 fixed-shot, 6 no-op, else position-sweep) into globals 0x8007B607..0x8007B627; consumers FUN_801DAB90 + FUN_801DB510, defaults in FUN_801DBE9C. Byte split: camera-region table.
  • FUN_801CEA3C's return hand-off: label table 0x801CE8AC → scene-name global 0x80084548 + spawn word 0x80084540.

Renderer + GTE

From an actor's mesh chain to GPU primitives: the per-actor render dispatcher, the TMD emit leaves and the animated-mesh poser.

FunctionRole
FUN_8001ADA4Per-actor render dispatcher (switch on actor[+0x56]); case 5 walks the mesh chain, case 0xB is the ocean CLUT-walk emitter
FUN_8001D140Stack-swap wrapper around the dispatcher; 6× per frame from FUN_80016444 (render pass)
FUN_80043390Per-prim emit selector: SCUS table 0x8007657C or the world-map overlay's fog-enabled table 0x801F8968
FUN_8002735CThe 60-GTE-op table-driven TMD renderer; gated on actor +0x42, and unentered in every sampled mode
FUN_8001B964Animated-mesh renderer: poses TMD object i with ANM bone i (R·v + T); skips unless object count = bone count
FUN_8001BE80ANM per-(bone, frame) entry decoder (port player_anm::BoneTransform)
FUN_80024D78Actor object-table fill from the pool TMD
FUN_80024E80Screen-fade primitive spawn (port engine-core::fade::spawn_fade)
FUN_80026B4C / FUN_800268DCTMD validate + register into DAT_8007C018; group-descriptor fixup
FUN_8002C69CHUD / menu / dialog sprite-batch POLY_FT4 emitter
FUN_801F69D8World-map top-view tile-visibility dispatcher (overlay)
FUN_801D8280DAT_8007C018 table walker (overlay)
0x8007C018 (data)Global TMD pointer table; counters 0x8007B774 / 0x8007BB38 (world-map overlay)
DAT_8007326C (data)Per-mode primitive descriptor table
0x800EB654 (data)Battle context struct (via _DAT_8007BD24)
Deep dive: dispatch details
  • Case 5 of FUN_8001ADA4 dispatches each TMD to FUN_8002735C when actor +0x42 is non-zero, FUN_80029888 (env-mapped) when only +0x7A is, else FUN_80043390 (textured) - the measured leaf. Case 0xB banks acc += DAT_1F800393 and fires a 16×1 MoveImage per kingdom slot-5 table entry when acc >= hold.
  • FUN_80043390 picks its table on _DAT_1F800394 & 1; the overlay variant routes every prim through the fog leaves at 0x801F7644..0x801F8690 - the bulk continent emit path.
  • FUN_80024E80(fade_template, mode) allocates from pool &DAT_80070674 via FUN_80020DE0, stores mode at actor[+0x18], loads the ramp via FUN_80020B00. The battle-action SM uses it for the summon backdrop fade (state 0x33) and the escape white-out (state 0x66).
  • FUN_80026B4C stores at DAT_8007C018[DAT_8007B774++]; reached from FUN_8001F05C cases 2 and 9. FUN_800268DC builds the +0xC descriptor array (0x1C stride).
  • FUN_801F69D8 lives in overlay_world_map_top_ext.bin; in warp-transition captures it is the live caller (ra 0x801F725C). FUN_801D8280 iterates 0..DAT_8007BB38 calling FUN_801D5E20 per sub-record.

Battle

The battle overlay's action state machine, HUD, loaders and the resident stat kernels.

FunctionRole
FUN_801E295CBattle action state machine (16 KB)
FUN_801D0748Battle / level-up main tick; sub-states 0x1E / 0x32 / 0x6E / 0xFE
FUN_801D388CBattle animation dispatcher (switch on animation type)
FUN_801D5854Per-pose camera / presentation driver (the anim system is FUN_80047430 → FUN_8004AD80 → FUN_8004998C)
FUN_801D8DE8HUD element renderer, 80-entry element table; shared with Muscle Dome
FUN_801DA6B4Actor display-state controller (opacity, pose flags)
FUN_801DB81CNext-valid-target scan (actor[+0x14C] != 0, no death / stone)
FUN_801ED710Records / stats screen renderer
FUN_800520F0Battle scene loader: the befect_data cluster + effect-model library into DAT_8007C018[3..32]
FUN_80020050Flame / effect-texture atlas loader (PROT 870 into VRAM) - separate from the bundle loader
FUN_8004E2F0Range / line-of-sight
FUN_80054CB0Monster init (applies the battle-load stat boost)
FUN_80042558Per-frame stat aggregator
FUN_8003FB10 / FUN_800431D0Action validator / ability-bitmask read
FUN_8002CDD0 / FUN_8002C2E4 / FUN_8002C488Status-HUD panel / per-member row / icon drawer; FUN_8002C2E4 pins the status bitfield at record +0x12E
0x801C9370 (data)8-actor pointer table (party 0-2, monsters 3-7); HP at +0x14C
PROT 0967Sparring-tutorial overlay, co-resident at 0x801F69D8 during the Tetsu fight
Deep dive: loaders and the records screen
  • FUN_80020050 uploads PROT entry 0x366 (extraction 870) twice via FUN_8001FC00 → FUN_8003E8A8; VRAM region set up by FUN_80017888 / FUN_8001E54C (arg 0xF000); gated on _DAT_8007B868 == 0. FUN_800520F0 pulls 0x367..0x36D instead.
  • FUN_801ED710 draws nine rows: battles + escapes (cap 99999), play time, six per-character categories over the record at 0x80084140 + n*0x414 (+0x6B4 / +0x6B0, +0x660 / +0x664, +0x74D / +0x704), and averages over the 0x801C6460 counters.

Menu + title overlay

The pause menu's window table and panel renderers, and the title screen's attract timer.

FunctionRole
FUN_801DD35CTitle-overlay per-frame tick; attract countdown underflow starts MV1.STR
FUN_801D33D8Per-character status / party panel renderer (Status / Magic / Moves / Skills), window descriptor 28
0x801E4738 (data)Window descriptor table: 52 × 16 B [content_id][park_edge][class][x,y,w,h][renderer] (parser legaia_asset::menu_windows)
FUN_801E1C1CShared menu-element renderer
FUN_801CF650Equipment stat aggregator: 5 slots at +0x196 → DAT_801EF08C..09C
FUN_801DD0C0Item category / slot validity check
Deep dive: attract timer and window renderers by id
  • FUN_801DD35C decrements the countdown at 0x801DDCCC by _DAT_1F800393 each frame; on underflow writes _DAT_8007B83C = 0x1A and zeroes _DAT_8007BA78 - the same fall-through as the field-VM FMV trigger. Dump funcs/overlay_title_801ddccc.txt.
  • Window renderers by id: 50 FUN_801CFD68 (command list), 49 FUN_801D0148 (money / play time), 51 FUN_801D030C (party panel), 26 / 21 FUN_801D2094 (party list), 27 FUN_801D30A4 (Condition pager), 30 FUN_801D31EC (summary), 22 FUN_801D21C0 (equip), 48 FUN_801DCEF0 (options), 0..4 title tabs. Live windows are 0x5C-stride linked structs with the animated rect at +0xA.
  • FUN_801D33D8 draws into a caller-supplied rect (WX = *(i16*)(a0+0xA), WY = *(i16*)(a0+0xC)), content only; submenu id DAT_801E46C0 & 0xFFF folded to 0..5. Pixel layout: field menu.

Audio (PsyQ)

Sony's libsnd / libspu stack as linked into the executable, plus the game's own bank loaders.

FunctionRole
FUN_8001FA88Sound init / .dpk loader
FUN_8001FC00Streaming-asset loader (sound\)
FUN_800243F0BGM lookup (PROT-relative)
FUN_8003E104monster.snd loader
0x80061000..0x80067FFFlibsnd SsAPI sequencer cluster
FUN_80068D94SsVabOpenHead core: validates pBAV, builds the program → tone-page rank map, allocates SPU memory (port engine-audio::VabBank::upload)
0x80068000..0x8006DFFFlibspu SPU control cluster
FUN_80069B18SPU DMA transfer state machine
FUN_8001EBECEquipment-conditional per-character TMD group patch (objects 10 / 11 swap)
ReferenceAudioVABSEQ

World map + field debug tools

The overworld controller, its developer menu, and the field overlay's debug editors the menu reaches into.

FunctionRole
FUN_801E76D4World-map controller: top-view debug toggle, camera scroll / azimuth / zoom
FUN_801EAD98Developer menu renderer, 24-entry list (display only; port engine_vm::world_map_overlay)
FUN_801EE094 / FUN_801EE328 (0897)The travel arts Riremito / Rula (subsystem handlers 0x29 / 0x2B): what the Door of Light / Door of Wind items run through the pause-menu session FUN_801ED308; each scans the resident CDNAME define table 0x80088758 for its destination. The developer menu reaches them too
FUN_801DBD04 (0897)Dev-menu EVENT FLAG editor over ids 0..0xFFF; can set any story flag including the spine gates
FUN_801EF014 (0897)Flag-window picker widget (op-0x49-installed); only genuine disc use is the Uru Mais warp-pad memory
FUN_801F159C (0897)Subsystem actor handler: jalr by value through the 52-entry id table 0x801F33B4 - 7 the state pick FUN_801F1F4C, 0x30 the pause-menu session, 0x29 / 0x2B the travel arts. Reached by value, so no address reference names a slot
FUN_801ED308 (0897)Pause-menu session (handler 0x30): brightness ramp, menu spawn, parks on the exit code _DAT_8007B43C; its phases 6 / 7 hand a Door of Light / Door of Wind use to Riremito / Rula. Not a fade/flash
FUN_801D2EBC (0897)Timed-flag scheduler consumer (installer op 0x4C 0xD3); retail use: chitei2 escape timer, flag 0x4C7
FUN_801DA51CPer-entity tick; 5-state SM on entity[+0x8A]
FUN_801CFC40Top-view sprite batcher
FUN_80016444Per-frame render tick (SCUS); jal 0x801D7EA0 gated by _DAT_8007BC3C == 2
FUN_801D7EA0 / FUN_801D8258POLY_FT4 batch emitter, one-shot gated by _DAT_801F351C; its gate setter
FUN_801D1344Gate-arm wrapper (field overlay 0897's player master frame handler); 0x801C2B2C is the same body printed 0xE818 low, not a relocated copy
Deep dive: the field-overlay debug editors
  • Warp appliers walk the map table at _DAT_80084628, load the scene via FUN_8001FD44, then teleport the player.
  • The EVENT FLAG editor keeps its cursor at DAT_801F2AA0; SET / CLEAR appliers at 0x801EA4F8 / 52C. It is also the register-pointer editor that produced the FMV trigger corpus.
  • FUN_801EF014: descriptor via _DAT_8007B450, +2 first visible row, +3 visible count; confirming a different row sets base + selection, re-picking the current row or cancelling sets nothing. Disc census (man-scripts --op49-window-census, 209 sites): the only flag-window family is kor / kor3 / kor4 sub-4 base=0x138 count=8; no window contains a spine flag.

BIOS + libapi

PlayStation kernel entry points and C-library routines the executable links in; ignored by the port catalog as PsyQ infrastructure.

AddressRoutine
0x80056678 / 0x80056688EnterCriticalSection / ExitCriticalSection
0x80056658 / 0x8006B844TestEvent / WaitEvent
0x80057024 / 0x8005ACAC / 0x8005E540memmove / memset / memcpy
0x80056698+, stride 0x10BIOS B-vector thunk cluster

Full directory

The complete lookup table is one Markdown page per subsystem in the repo. Grep them for your address, read the row, then open the dump or the linked subsystem page.

Directory pageCoversSite page
asset-loading.mdAsset loading + dispatch, per-stage asset tables, disc / loader chain, scene initAsset loader
runtime-libs.mdPSX runtime libraries, CD / file-system, helpers, static actor templatesBoot
game-modes.mdInput + debug, move / animation, the game-mode state machine, the title overlayBoot, Move VM
battle.mdBattle, HUD + 2D effects, per-frame draw, sparring tutorial (0967), command persistence (0898), field→battle transitionBattle, Battle action SM
cast-modules.mdSlot-B cast / summon module band (PROT 0903..0966) - the addresses that are not entries: each image's own data tail, and the neighbour's bytes every image ends inBattle
script-vms.mdScript VMs, field-locomotion math helpersField VM, Locomotion
renderer.mdRenderer, GPU primitives, ANM, MES / dialog text interpreterRenderer
audio.mdlibsnd / libspu stack, SsAPI sequencer, SPU transfer engine, XA streamingAudio
menus.mdRecords screen, status / equip panels (0897), inventory / spell list, shop panels, menu-overlay callees (0899)Field menu, Shop
world-map.mdWorld map controller, dev menu, render pipelineWorld map
minigames-debug.mdMinigames, debug-menu overlay (0971), other-game minigame overlay (0977)Minigames

docs/reference/functions.md →

See also