Tier D - variable-length relocation
On a door-randomizer seed the exit from Rim Elm can lead to Biron Monastery. That single change breaks the one rule every other data tier keeps: a scene-transition door carries its destination's name inline, so pointing it somewhere with a longer name makes the record longer. Everything positioned after it in the script moves, and every table that recorded a position is wrong.
At a glance
- Target
- A MAN record whose length changes - the
0x3Fscene-transition's inline destination name, or an inserted block of instructions - Engine
legaia_asset::man_edit- rebuild, resize, fix every disturbed offset- Fix-ups
- Partition tables · partition-2 record-offset table · the
u24length at+0x28· intra-record jump deltas · the external descriptor size word - Bound
- Recompressed stream must fit the asset footprint; otherwise the scene is skipped
- Mods
--doors·--starting-items(variant: splice)- Confidence
- Confirmed - oracles re-decode every relocated scene and walk its scripts
- Oracles
door_patch_real.rs·starting_bag_real.rs
What a resize disturbs
A MAN is a partitioned bundle: a header with partition tables, then records reached through a per-partition offset table. A door's destination lives in a partition-2 record, name inline. Grow that record and every structure encoding a position past it is stale.
| Structure | Why it breaks |
|---|---|
| partition tables | every partition after the edit starts Δ bytes later |
| partition-2 record-offset table | indexes the very records that moved, including the door destinations |
u24 length at +0x28 | records the bundle's decompressed size |
| intra-record jump deltas | a relative branch that straddles the edit lands Δ bytes short or long |
| external descriptor size word | the loader reads the decompressed size from the scene bundle's descriptor, outside the MAN |
Miss one and the script desyncs or the door points into garbage. The relocation engine fixes all five in one rebuild - byte layout on the MAN relocation page.
Two shapes of edit
- Re-point a record (
--doors). The canonical relocation: the inline name resizes the record, the engine fixes the offsets, the MAN recompresses within footprint. Coupling is bidirectional (a door and its return both move) or one-way, by flag. - Insert a block (
--starting-items, the splice variant). The high-capacity starting bag inserts a guarded grant block into the opening scene's script - a story-flag test, a run of give-item ops, and a flag set so it fires once.man_edit::apply_insertionsrelocates it like any other length change, lifting the seven-slot cap of the same-size new-game seed path.
Relocation composes with the same-size tiers because they leave descriptor offsets fixed: a relocation pass runs on the stable footprint the tier-C budget is read from.
How we know
| Claim | Evidence | Reference |
|---|---|---|
MAN partition layout + the +0x28 length | Scene-bundle loader walk; parser legaia_asset::man_edit | man-relocation, scene-bundles |
Door op 0x3F carries the name inline | Field-VM dispatcher FUN_801DE840 | script-vm |
Grant block ops 0x70 / 0x39 / 0x50 | Same dispatcher; the engine's field VM executes the inserted block in the runtime oracle | starting_bag_real.rs |
| Every fix-up is sufficient | Door oracle re-decodes each relocated scene and walks every record to its terminator | door_patch_real.rs |
Details: adding a tier-D mod
- Enumerate every offset, table and delta the resize disturbs from the container layout.
- Fix them in one rebuild through
man_edit. - Keep the recompressed stream within the asset footprint; skip on overflow.
- Add a disc-gated oracle that re-decodes the patched image and walks the scripts.