docs(oot): a map of the game's lifted functions in docs/oot/ #188

Closed
dyst wants to merge 1 commit from dyst:docs/oot-function-map into main
Member

Why

The game ships without symbols, so every lifted function is just f_<address>, and each person or agent who needs to know what one does has to work it out again from the lifted code. This adds a shared map of what we have already worked out, so the next person can search an address and find it.

What changed

  • docs: docs/oot/ is new, with 32 pages, one per part of the game: jobs and the frame's critical path, actors, AI, animation, navigation, physics, drawing and the NVN calls, rendering, shaders, textures, culling, effects, input, audio, environment, resources, maps, events, the camera, the player, menus, layout, save data and the save list, game data and Master Quest, the frame time, and the hot path. They hold 1,176 function rows, 236 data rows and the structures behind them. Each row says what the function does in our own words and how sure we are: tested (seen in the game), read (worked out from the code) or guess (from names and neighbours). docs/oot/README.md has the conventions and the index.
  • docs: every game function Longshot's code names today (nx2/oot_*.py, host/) has a row, 120 of 120, and each hook a page names (patch_…) is one nx2/oot_patches.py defines.
  • AGENTS.md: a two-line pointer under Make the change: search docs/oot/ for an address before reading lifted code, and add a row when you learn what a function does.

Flags and settings

None.

Measurements

The game doesn't run this change (documentation only), so it is measured by the game-free checks, as AGENTS.md says for docs.

main: 000f19fb (2026-11-13)
this PR: docs/oot-function-map @ 6f350944
Hardware: NVIDIA GeForce RTX 3080, Windows 11 Pro N 22631
Scene: none (no game run)
Method: python -I -B tests/run_all.py twice on each, interleaved, in two worktrees at the same base on the same PC (round 1: both at once; round 2: this PR, then main, alone); plus the pages' own check (below)
How to reproduce: python -I -B tests/run_all.py on each commit

main @ 000f19fb this PR @ 6f350944
tests/run_all.py, round 1 435 passed, 37 failed, 49 skipped 435 passed, 37 failed, 49 skipped
tests/run_all.py, round 2 445 passed, 27 failed, 49 skipped 442 passed, 30 failed, 49 skipped
The pages' own check n/a pass: 32 pages, 1,176 functions, 236 data addresses, 120 of 120 code-named functions
main  round 1: 435 passed, 37 failed, 49 skipped in 346 s (windows, 24 at once)
PR    round 1: 435 passed, 37 failed, 49 skipped in 383 s (windows, 24 at once)
PR    round 2: 442 passed, 30 failed, 49 skipped in 252 s (windows, 24 at once)
main  round 2: 445 passed, 27 failed, 49 skipped in 284 s (windows, 24 at once)

The same 27 checks failed in all four runs, on main as on this PR: they fail on this PC without the change (nx2/test_mesh_first_types, nx2/test_texture_init_barrier, test_audio_output_errors, test_audio_wave_buffer_release, test_bake_portability, test_bug_report, test_capture_dimensions, test_check_third_party, test_control, test_cpp_preflight, test_display_pointer, test_game_font, test_hd_rumble, test_log_batch, test_pcache_header_read, test_pipeline_cache_file, test_pipeline_cache_save, test_pipeline_play_cache, test_portable_setup_transaction, test_prepare_stall, test_prof_clock, test_recorder_sync, test_release, test_rumble_mapping, test_rumble_refresh, test_scene_tonemap_pass, test_spawn_emit). The rest came and went with the load, on both sides: test_gpu_hang_watch and test_seed_reader failed on this PR in round 1 (both suites at once) and pass alone; test_prepare_at_build and test_setup_tar_diagnostics failed on main only; test_audio_voice_biquad, test_display_startup_failure and test_invalidate_vcore failed in round 1 on both and in round 2 on this PR, and pass on main when the machine is quiet (timeouts). Nothing this PR changes is read by a check.

Testing

Tested: tests/run_all.py on main and on this PR (above). The pages' own check, a script kept local and not in this PR: one home per function, every row's table and Sure value, each patch_… a page names exists in nx2/oot_*.py, every relative link resolves, and the README's index lists every page. A scan of every page for game code: no disassembly listings, no lifted C, no decompiled code. Only addresses, names, offsets, constants and descriptions in our own words.

Not tested: nothing in the game: no code changes.

Needs other testers: None

Screenshots

Nothing on screen.

Risk and rollback

Documentation only. A row can be wrong, and the Sure column says how far to trust each one. Reverting the commit removes it all.

Reviewer notes

  • Is a function map wanted in the repository? On Hookshot, NotRexed/Hookshot#2636, hckrman101 ruled that a hand-written table of game-function addresses with names and meanings should stay local. These pages hold no game code. They describe how the game behaves as facts, in our own words, which is how CONTRIBUTING.md's Licensing section treats a function's name and arguments. Whether Longshot wants such a map in the repository is the maintainers' call; if not, closing this PR is the answer.
  • Hookshot numbers: issue and PR numbers such as #2545 are Hookshot's (github.com/NotRexed/Hookshot), where the pages were started; Longshot's are written "Longshot #N" (the README says so).
  • The check stays out for now. The pages' check script is not in this PR. If the map is wanted, it can follow, and with it a rule that a game function new code names gets a row.
  • Where to look first: docs/oot/README.md (conventions and the index), then any page. jobs.md, physics.md and navigation.md hold the frame-rate findings: what the frame waits on, and which jobs run beside it.

Issues

None.

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Docs updated.

🤖 Generated with Claude Code

## Why The game ships without symbols, so every lifted function is just `f_<address>`, and each person or agent who needs to know what one does has to work it out again from the lifted code. This adds a shared map of what we have already worked out, so the next person can search an address and find it. ## What changed - docs: `docs/oot/` is new, with 32 pages, one per part of the game: jobs and the frame's critical path, actors, AI, animation, navigation, physics, drawing and the NVN calls, rendering, shaders, textures, culling, effects, input, audio, environment, resources, maps, events, the camera, the player, menus, layout, save data and the save list, game data and Master Quest, the frame time, and the hot path. They hold 1,176 function rows, 236 data rows and the structures behind them. Each row says what the function does in our own words and how sure we are: **tested** (seen in the game), **read** (worked out from the code) or **guess** (from names and neighbours). `docs/oot/README.md` has the conventions and the index. - docs: every game function Longshot's code names today (`nx2/oot_*.py`, `host/`) has a row, 120 of 120, and each hook a page names (`patch_…`) is one `nx2/oot_patches.py` defines. - AGENTS.md: a two-line pointer under *Make the change*: search `docs/oot/` for an address before reading lifted code, and add a row when you learn what a function does. ## Flags and settings None. ## Measurements The game doesn't run this change (documentation only), so it is measured by the game-free checks, as AGENTS.md says for docs. main: 000f19fb (2026-11-13) this PR: docs/oot-function-map @ 6f350944 Hardware: NVIDIA GeForce RTX 3080, Windows 11 Pro N 22631 Scene: none (no game run) Method: `python -I -B tests/run_all.py` twice on each, interleaved, in two worktrees at the same base on the same PC (round 1: both at once; round 2: this PR, then main, alone); plus the pages' own check (below) How to reproduce: `python -I -B tests/run_all.py` on each commit | | main @ 000f19fb | this PR @ 6f350944 | |---|---|---| | `tests/run_all.py`, round 1 | 435 passed, 37 failed, 49 skipped | 435 passed, 37 failed, 49 skipped | | `tests/run_all.py`, round 2 | 445 passed, 27 failed, 49 skipped | 442 passed, 30 failed, 49 skipped | | The pages' own check | n/a | pass: 32 pages, 1,176 functions, 236 data addresses, 120 of 120 code-named functions | ``` main round 1: 435 passed, 37 failed, 49 skipped in 346 s (windows, 24 at once) PR round 1: 435 passed, 37 failed, 49 skipped in 383 s (windows, 24 at once) PR round 2: 442 passed, 30 failed, 49 skipped in 252 s (windows, 24 at once) main round 2: 445 passed, 27 failed, 49 skipped in 284 s (windows, 24 at once) ``` The same 27 checks failed in all four runs, on main as on this PR: they fail on this PC without the change (nx2/test_mesh_first_types, nx2/test_texture_init_barrier, test_audio_output_errors, test_audio_wave_buffer_release, test_bake_portability, test_bug_report, test_capture_dimensions, test_check_third_party, test_control, test_cpp_preflight, test_display_pointer, test_game_font, test_hd_rumble, test_log_batch, test_pcache_header_read, test_pipeline_cache_file, test_pipeline_cache_save, test_pipeline_play_cache, test_portable_setup_transaction, test_prepare_stall, test_prof_clock, test_recorder_sync, test_release, test_rumble_mapping, test_rumble_refresh, test_scene_tonemap_pass, test_spawn_emit). The rest came and went with the load, on both sides: test_gpu_hang_watch and test_seed_reader failed on this PR in round 1 (both suites at once) and pass alone; test_prepare_at_build and test_setup_tar_diagnostics failed on main only; test_audio_voice_biquad, test_display_startup_failure and test_invalidate_vcore failed in round 1 on both and in round 2 on this PR, and pass on main when the machine is quiet (timeouts). Nothing this PR changes is read by a check. ## Testing **Tested:** `tests/run_all.py` on main and on this PR (above). The pages' own check, a script kept local and not in this PR: one home per function, every row's table and *Sure* value, each `patch_…` a page names exists in `nx2/oot_*.py`, every relative link resolves, and the README's index lists every page. A scan of every page for game code: no disassembly listings, no lifted C, no decompiled code. Only addresses, names, offsets, constants and descriptions in our own words. **Not tested:** nothing in the game: no code changes. **Needs other testers:** None ## Screenshots Nothing on screen. ## Risk and rollback Documentation only. A row can be wrong, and the *Sure* column says how far to trust each one. Reverting the commit removes it all. ## Reviewer notes - **Is a function map wanted in the repository?** On Hookshot, [NotRexed/Hookshot#2636](https://github.com/NotRexed/Hookshot/pull/2636), hckrman101 ruled that a hand-written table of game-function addresses with names and meanings should stay local. These pages hold no game code. They describe how the game behaves as facts, in our own words, which is how CONTRIBUTING.md's *Licensing* section treats a function's name and arguments. Whether Longshot wants such a map in the repository is the maintainers' call; if not, closing this PR is the answer. - **Hookshot numbers:** issue and PR numbers such as #2545 are Hookshot's (github.com/NotRexed/Hookshot), where the pages were started; Longshot's are written "Longshot #N" (the README says so). - **The check stays out for now.** The pages' check script is not in this PR. If the map is wanted, it can follow, and with it a rule that a game function new code names gets a row. - **Where to look first:** `docs/oot/README.md` (conventions and the index), then any page. `jobs.md`, `physics.md` and `navigation.md` hold the frame-rate findings: what the frame waits on, and which jobs run beside it. ## Issues None. ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [x] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [x] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
docs(oot): a map of the game's lifted functions in docs/oot/
All checks were successful
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 6s
Third-party parts / As their notes say (pull_request) Successful in 8s
PR description / Description follows the template (pull_request_target) Successful in 3s
6f35094411
32 pages saying what the f_<address> functions we have looked at do, by
part of the game (jobs, actors, physics, drawing, NVN calls, shaders,
textures, culling, input, audio and more), with their data and
structures and how sure each row is. AGENTS.md points agents to it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
dyst changed title from WIP: docs(oot): a map of the game's lifted functions in docs/oot/ to docs(oot): a map of the game's lifted functions in docs/oot/ 2026-11-13 12:40:36 +00:00
Owner

We want to be extra careful with this one, so here's what to change before it can merge. The pages themselves are good work: they're factual prose (addresses, what each function does, how sure we are), with no lifted code, no runs of assembly or hex bytes, no assets, no keys and no game text. The problems are the parts that copy or catalogue things from the game file, which brushes against our own rule in CONTRIBUTING.md: "No game files, keys, or anything made from them leave your PC."

Please remove or change:

  1. Verbatim strings from the binary. There are about 580 quoted strings across the pages.
    • Drop the SDK and middleware build strings, such as the SMAA/NDSR SDK release string in shaders.md.
    • Drop the debug and profiler strings quoted from the binary.
    • Paraphrase internal identifiers where the role is enough: "the Master Quest name query node" rather than the node's exact class name.
    • Keep an exact name only where Longshot's own code already uses it, and say where.
  2. Resource paths and archive names. Replace full paths of the game's archives and files with a short description of the kind, for example "agl's shader archive" rather than the full .sarc path.
  3. File inventories. Remove counts and lists that describe the dump's contents, like how many .ainb files are loose or in which pack. They don't help anyone port anything, and they describe the game's files in detail.
  4. Proprietary SDK internals.
    • Cut nvn-calls.md (about 400 rows) down to the calls Longshot's own host/nvn_native.c already implements, describing what Longshot does with each. Drop the full census of every NVN entry point the game asks for, and the call-site counts.
    • In the same spirit, keep the Havok class names in physics.md and navigation.md only where needed to explain a Longshot change.
  5. Game and character names. We moved the README and the website to neutral wording (#193). Please follow that here: "the game", "the player", "dungeon N", "the final boss", rather than game, character, place and dungeon names, including in the map and dungeon tables.

Also:

  • A safety note in docs/oot/README.md. State that these pages describe behaviour for interoperability only. They must never quote the game's code, data, text, strings or file listings, and anything copied from the game file belongs in work/, which never leaves the PC. Point agents at that rule from AGENTS.md too, since AGENTS.md now sends them here.
  • Bare refs. The README says Hookshot numbers are written bare ("#2545"). AGENTS.md asks for full URLs: https://github.com/NotRexed/Hookshot/pull/2545.

If trimming this much takes most of the value out, it could live in a private repo or wiki instead, with AGENTS.md linking to it for team members. I'm happy either way; the line we want is that nothing in the public repo is copied or listed from the game file.

We want to be extra careful with this one, so here's what to change before it can merge. The pages themselves are good work: they're factual prose (addresses, what each function does, how sure we are), with no lifted code, no runs of assembly or hex bytes, no assets, no keys and no game text. The problems are the parts that copy or catalogue things *from* the game file, which brushes against our own rule in CONTRIBUTING.md: "No game files, keys, or anything made from them leave your PC." **Please remove or change:** 1. **Verbatim strings from the binary.** There are about 580 quoted strings across the pages. - Drop the SDK and middleware build strings, such as the SMAA/NDSR SDK release string in `shaders.md`. - Drop the debug and profiler strings quoted from the binary. - Paraphrase internal identifiers where the role is enough: "the Master Quest name query node" rather than the node's exact class name. - Keep an exact name only where Longshot's own code already uses it, and say where. 2. **Resource paths and archive names.** Replace full paths of the game's archives and files with a short description of the kind, for example "agl's shader archive" rather than the full `.sarc` path. 3. **File inventories.** Remove counts and lists that describe the dump's contents, like how many `.ainb` files are loose or in which pack. They don't help anyone port anything, and they describe the game's files in detail. 4. **Proprietary SDK internals.** - Cut `nvn-calls.md` (about 400 rows) down to the calls Longshot's own `host/nvn_native.c` already implements, describing what Longshot does with each. Drop the full census of every NVN entry point the game asks for, and the call-site counts. - In the same spirit, keep the Havok class names in `physics.md` and `navigation.md` only where needed to explain a Longshot change. 5. **Game and character names.** We moved the README and the website to neutral wording (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/193). Please follow that here: "the game", "the player", "dungeon N", "the final boss", rather than game, character, place and dungeon names, including in the map and dungeon tables. **Also:** - **A safety note in `docs/oot/README.md`.** State that these pages describe behaviour for interoperability only. They must never quote the game's code, data, text, strings or file listings, and anything copied from the game file belongs in `work/`, which never leaves the PC. Point agents at that rule from AGENTS.md too, since AGENTS.md now sends them here. - **Bare refs.** The README says Hookshot numbers are written bare ("#2545"). AGENTS.md asks for full URLs: https://github.com/NotRexed/Hookshot/pull/2545. If trimming this much takes most of the value out, it could live in a private repo or wiki instead, with AGENTS.md linking to it for team members. I'm happy either way; the line we want is that nothing in the public repo is copied or listed from the game file.
Owner

We are still unsure if this will be accepted btw, due to the nature of the change. Feel free to discuss on Discord

We are still unsure if this will be accepted btw, due to the nature of the change. Feel free to discuss on Discord
dyst closed this pull request 2026-11-13 18:49:23 +00:00
dyst deleted branch docs/oot-function-map 2026-11-13 18:50:06 +00:00
All checks were successful
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 6s
Third-party parts / As their notes say (pull_request) Successful in 8s
PR description / Description follows the template (pull_request_target) Successful in 3s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!188
No description provided.