Skip to content

feat(mhfu): one memory interface and the overlay and EBOOT analysis on rabbitizer - #6

Merged
sp00ktober merged 38 commits into
mainfrom
feat/mhfu-analysis
Sep 29, 2026
Merged

sp00ktober merged 38 commits into
mainfrom
feat/mhfu-analysis

Conversation

@sp00ktober

@sp00ktober sp00ktober commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Part of sp00ktober/MHFU-ModKit#62 (the offline half; the live half is stacked on this PR).

  • One memory interface: Live over ppsspp-debug, Image for a RAM dump, an overlay or BOOT.BIN, Space for several. Typed views take offset and type from addresses.toml, and a mismatch fails at import.
  • mips.Code on rabbitizer (Allegrex): functions, calls with vtable slots and tail calls, lui/lo pairs through its RegistersTracker, switches, constants. It replaces mips_dis.py, capstone and the bit masking.
  • One mhfu CLI:
    • dis, xref, switch, reloc
    • moveset, phases, chain, effects, attacks, abi, census
    • intel --all (schema mhfu.species_intel/1 kept, so the monster editor still reads it)
    • hitzones, hitboxes, stage, inject, addresses
  • census skips transitions a script forced (FORCED in the log) and the visits they cut short, so it measures only what the monster chose; intel reports how many it skipped. The old tool counted them.
  • MIT, no mhp-formats dependency: inject takes finished bytes, and the stage file codec stays in mhp-formats.

Old bugs fixed, found by comparing old and new on all 17 em overlays, 267 stage overlays, game_task, game_sub and BOOT.BIN:

  • An overlay's text section starts at 0x40, not 0x80. The old layout hid em55/em59's attack tables (now 26 and 10 attacks) and ran 14 overlays' data past their file.

  • The relocator:

    • moved game_sub's bss as if it were an em "lower BSS" (169 references);
    • overshot the footprint end;
    • missed 24 luis in delay slots and the ctor range.

    The framework's C port has the same bugs, now an item in Behaviour graph: a node canvas replaces the rule list #65.

  • The 16 st046 variant PACs (file_06074..06089) were missing, and stage 0's PAC id pointed at stage266.ovl.

  • Tail and virtual tail calls: pairs that hand off went from 806 to 1581, and abi callers 8 from 29 to 95.

  • Constant reads now follow register moves, pointer arguments, branch-likely delay slots and every path. They also no longer stop at a 3000-instruction cut-off, and em_effects no longer crashes on em07.

Test plan

  • uv run pytest: passes without game data, and with MHFU_DATA
  • Installed from the wheels: mhfu intel --all writes all 17 species files in 8 s, and the monster editor loads them
  • spimdisasm agrees on every lui/lo pair and jump in the em, stage, task and sub overlays

🤖 Generated with Claude Code

sp00ktober and others added 30 commits September 28, 2026 23:23
…ore, one CLI

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es are zero

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bss, not the overlay's

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pendency

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mips.Code decodes a text range once and answers what the old tools each
re-implemented: function bounds, calls (direct, virtual by vtable slot,
tail), lui/lo pairs through rabbitizer's RegistersTracker as spimdisasm
walks it, jump tables with their bound and bias, and the constant a
register holds at a site.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n files

mhfu.stage reads a stage overlay's parameter object (exits, spheres, the raw
surface table), the map table, and the live resident-file, gathering-spot and
small-monster spawn tables. mhfu.hitzone and mhfu.hitbox read the part system
and the attack tables through the species row and the setter call. mhfu.inject
places finished files for the framework's live injection. files.py covers all
282 stage PACs, the 16 st046 lobby variants included.

CLI: mhfu stage ids|maps|exits|surfaces|spots|spawns, mhfu hitzones,
mhfu hitboxes, mhfu inject.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
References come from mhfu.mips: j/jal targets, lui/lo pairs as
rabbitizer's RegistersTracker pairs them (matching spimdisasm on every
em, stage, game_task and game_sub overlay) and data words into the
overlay's own image and bss. The header's load address and ctor list
move with it; the bss of game_sub below an em overlay does not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ecies and LOBBY_TASK in one place each

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code.table gives the table an indexed load reads (lw v0, 0(table +
index)), the one idiom hitbox needed that Code.constant does not cover.
relocate() now starts from Overlay.file, so a moved overlay keeps its
disc padding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hitbox.setter_calls replaces calls_to, Code.constant the lui/addiu
window, and Code.table the try-every-register loop for the volume table;
the stage parameter object is what any function returns in v0.
Identical results: 22 attack tables with their 355 volume sets and all
267 stage parameter objects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The synthetic setter call stores a table entry the way the game does,
lw v0, 0(table + index), instead of relying on a scan of every register.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The game's code from BOOT.BIN or an overlay (a file id, game_task,
game_sub, emNN or stageNNN); an address may be a name from the table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… operands

rabbitizer reports or rd, rs, $zero as cpu_move; move_source names the
copied register for it and for addu/or with $zero.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… effect-id bias

Addresses for the intel section: the framed and positional effect spawns, the entity
factory and the run of attack-node constructors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… fits the table

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… dispatch sites

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, attack tables, census

The per-pair join waits for the moveset, phase and chain analyses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the overlay

Moveset reads the action tick's (main, sub) pairs, their handlers and the
animation ids each hands the executor; phases the gates a handler waits on;
chain the pair a handler enters when it ends, through enter-action and the
per-main translators. One path walker interprets handlers for both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
source, constant and the virtual-call slot now take every path into a
site within its function, jump-table edges included, instead of stopping
at the first label: a vptr loaded on both arms of a branch-likely now
gives its slot (three more vt+0x28 calls in game_task). A j to a run no
branch reaches starts a function when it lies in another function or
right after the j, and a prologue a j reaches is no longer taken for a
second frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…th values

Gates read the handler's body over tail jumps and each frame on every path;
budget seeds through walker probes. The walker follows tail calls as
continuations, learns entity cells from stores and branches, and the chain
treats a tail-calling thunk as the wrapper it leads to. An enter-action id
that sets nothing is told apart from a computed one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reads raise Unmapped

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ommands

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sp00ktober and others added 7 commits September 29, 2026 01:04
…ees past labels

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…el/1)

An inline case keeps its own note instead of the census-only one; the overlay's text is
the section's true range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
modkit_testing.mips replaces nine per-file encoder sets; each encoder is
checked against rabbitizer's decode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t short

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sp00ktober
sp00ktober merged commit d833200 into main Sep 29, 2026
4 checks passed
@sp00ktober
sp00ktober deleted the feat/mhfu-analysis branch September 29, 2026 06:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant