Skip to content

Fix external stage id docs#2939

Open
MarkMcCaskey wants to merge 6 commits into
doldecomp:masterfrom
MarkMcCaskey:fix-external-stage-id-docs
Open

Fix external stage id docs#2939
MarkMcCaskey wants to merge 6 commits into
doldecomp:masterfrom
MarkMcCaskey:fix-external-stage-id-docs

Conversation

@MarkMcCaskey

Copy link
Copy Markdown
Collaborator

First PR made with agentic runtime inspection, testing and validating the ideas with code injection using @Jacoby6000's https://github.com/Jacoby6000/dolphin/blob/feature/dap-server/Tools/dap/README.md tool.

Claude's more verbose justification for the details here https://gist.github.com/MarkMcCaskey/3645a0880e7293d3518714d686bdd2b5

I found this by accident by automating loading into a stage and we found out there's a mismatch between external and internal ids. This PR is a deeper dive into that concept to clean up the code here.

StartMeleeRules.xE was commented as an InternalStageId, but it holds the external stage ID: Stage_802251E8 uses it as an index into unk_arr_803E9960, whose entries map external IDs to InternalStageId values (runtime-verified in Dolphin: rules.xE = 0x16 loads Venom, internal 0xF; passing 0xF loads Brinstar Depths). Retype the five Stage_ setup functions' index parameters to enum_t, type Stage_8022519C's return as the InternalStageId it fetches, and drop the casts callers used to satisfy the wrong parameter type.

Also replace the internal-enum names PURA and KINOKOROUTE in vi0501 and vi1101 with external ID literals like the sibling cutscene files: external 17 is Green Greens and 0x1F is Battlefield, matching the Adventure stage each cutscene belongs to; those names only worked because the numbers coincide in the external space.

All ten affected translation units compile byte-identical; lbdvd only renumbers anonymous local literal symbols in object metadata.
Names the external->internal mapping (stage_id_map, selected_stage, default_stage_pair, StageIdPair), spells map entries as InternalStageId names, and moves callers onto the new enum. All 18 affected TUs compile byte-identical; stage.c and lbdvd.c differ only in renamed/renumbered local symbol metadata.
@decomp-dev

decomp-dev Bot commented Jul 22, 2026

Copy link
Copy Markdown

Report for GALE01 (9247abd - e3fb4e6)

No changes

Retypes the downstream carriers of external stage IDs (GameCache.stage_id, lbAudioAx_80026EBC, gm_8017CE34's stage parameter, lbaudio's preload local), updates grvenom's local Stage_80225194 declaration, and drops the remaining wrong-space InternalStageId casts. All 15 affected TUs compile byte-identical (grvenom against master; lbdvd modulo anonymous-literal numbering).
…ageId

gm_1BA8 assigns the same u16 to rules.xE and ev->x48, and gmclassic's preload local feeds lbAudioAx_80026EBC; both carry external stage IDs. Both TUs compile byte-identical; a clang -Wenum-conversion scan over all 34 TUs touching the retyped symbols is clean.

@ribbanya ribbanya left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anywhere in the DOL that explicitly maps these? Or just runtime checks?

@PsiLupan

Copy link
Copy Markdown
Collaborator

The cutscene mapping seem like sufficient evidence to me at a glance.

@MarkMcCaskey

Copy link
Copy Markdown
Collaborator Author

Is there anywhere in the DOL that explicitly maps these? Or just runtime checks?

The internal vs external mismatch was identified with code injection to load a specific map and the internal ID didn't line up. The enum was built out by trying all the IDs with the load map code and then reading back memory of a known location for the internal id. So not sure if this is statically encoded but this mapping was created by dynamically editing and reading back memory.

I wonder if it'd be helpful to distill experiments into an easily reproducible form. I think dolphin has something called gecko codes or something and that might be a better way to be able to store this logic for the longer term. Perhaps we could just put that in an emulator and confirm rather than relying on layers of external tools like this.

@Jacoby6000

Jacoby6000 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

The code injection tools in the dap branch are mainly there for doing stuff during runtime, where it may be useful to be able to change execution in the middle of a running game, avoiding having to restart every time you change something.

Gecko would be great for reproducibility I think. Gecko with some EXI and an accompanying launch script that collects the output.

@ribbanya

Copy link
Copy Markdown
Collaborator

Gecko codes just overwrite RAM with arbitrary data, which can be assembly code:
https://wiigeckocodes.github.io/codetypedocumentation.html#C0

@MarkMcCaskey

Copy link
Copy Markdown
Collaborator Author

The code injection tools in the dap branch are mainly there for doing stuff during runtime, where it may be useful to be able to change execution in the middle of a running game, avoiding having to restart every time you change something.

Gecko would be great for reproducibility I think. Gecko with some EXI and an accompanying launch script that collects the output.

Yeah I think the tool you built is ideal for exploration, I'd just want the agent to finish with a self-contained easily reproducible experiment artifact I think

@ribbanya ribbanya added naming ai-assisted Utilizes a LLM to do the heavy lifting labels Jul 22, 2026
@MarkMcCaskey

Copy link
Copy Markdown
Collaborator Author

Okay I set up a way to reproduce and verify the finding. Gecko code here https://github.com/MarkMcCaskey/melee-runtime-audits/blob/main/pr2939/kiosk.gecko.ini use left/right dpad to advance the stages or press A to autoplay.

selected_stage = .sdata:0x804D49E8 can be monitored as the external ID (displayed in game with devtext as ext)
The internal ID can also be monitored at 0x8049E750 (stage_info = .bss:0x8049E6C8 + 0x88) details here

There's also a python script for headless verification but the interactive gecko code + dolphin memory inspector is probably the best way to verify.

@MarkMcCaskey

Copy link
Copy Markdown
Collaborator Author

Happy to provide a more in-depth repro or cover anything else, just let me know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-assisted Utilizes a LLM to do the heavy lifting naming

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants