Decode RTINIT movement providers 4 6 and 15

This commit is contained in:
gamer147
2026-07-23 15:43:27 -04:00
parent 52780d92a0
commit c55c5ada4c
10 changed files with 183 additions and 33 deletions

View File

@@ -1,7 +1,7 @@
<!-- DO NOT EDIT -- generated from vm-map/globals.toml by tools/globals_build.py --build --> <!-- DO NOT EDIT -- generated from vm-map/globals.toml by tools/globals_build.py --build -->
# Global Variable Reference (generated) # Global Variable Reference (generated)
5038 globals (241 curated, 4797 auto shape-inferred). Source of truth: `vm-map/globals.toml`. 5038 globals (244 curated, 4794 auto shape-inferred). Source of truth: `vm-map/globals.toml`.
## choice-output ## choice-output
@@ -12,7 +12,7 @@
| `0xa68` | — | med | auto-shape | TODO: confirm. Branch-read in 11 scenes / 12 scripts; compared against [0, 1]; writers=['SC0740.BIN', 'SC1580.BIN', 'SC1590.BIN']. | | `0xa68` | — | med | auto-shape | TODO: confirm. Branch-read in 11 scenes / 12 scripts; compared against [0, 1]; writers=['SC0740.BIN', 'SC1580.BIN', 'SC1590.BIN']. |
| `0x62ccc` | scjump_decision_out2 | low | inference | Adjacent to scjump_decision_out (0x62ccf) in the 0x62ccc-0x62ccf progression decision-output cluster; same 136-scene reach, written by CAMP/CLOSE/DEBUGADV. INFERENCE from adjacency — confirm meaning before relying on it. | | `0x62ccc` | scjump_decision_out2 | low | inference | Adjacent to scjump_decision_out (0x62ccf) in the 0x62ccc-0x62ccf progression decision-output cluster; same 136-scene reach, written by CAMP/CLOSE/DEBUGADV. INFERENCE from adjacency — confirm meaning before relying on it. |
| `0x62ccf` | scjump_decision_out | high | investigation | SCJUMP's selected progression decision id. Its chapter/flag decision tree writes one of 847 distinct values across 1,755 sites; SYSTEM4, FIELD, SALLY, and TRAIN use it to index scjump_scene_script_resource_ids and dispatch the corresponding SCxxxx scene script. | | `0x62ccf` | scjump_decision_out | high | investigation | SCJUMP's selected progression decision id. Its chapter/flag decision tree writes one of 847 distinct values across 1,755 sites; SYSTEM4, FIELD, SALLY, and TRAIN use it to index scjump_scene_script_resource_ids and dispatch the corresponding SCxxxx scene script. |
| `0xcc9f1` | movement_search_mode | high | investigation | Transient MVSEEK mode. Zero keeps the caller-supplied origin and broad search allowance; nonzero modes replace them with the current entity tile and movement+1. Mode 2 additionally masks the doubled-coordinate terrain cells occupied by active entities of another faction before the flood fill. MVSEEK resets the mode to zero on exit. | | `0xcc9f1` | movement_search_mode | high | investigation | Transient MVSEEK mode. Zero replaces the caller-supplied origin with the current entity tile and uses movement+1 as the search allowance; nonzero modes retain the caller coordinate and use a broad allowance of 9999. Mode 2 additionally masks the doubled-coordinate terrain cells occupied by active entities of another faction before the flood fill. MVSEEK resets the mode to zero on exit. |
## counter ## counter
@@ -37,7 +37,7 @@
| `0x69f8` | unit_current_stats | high | investigation | Persistent fourteen-stat row for each playable unit, using the same column order as unit_base_stats. CALCCC adds class_change_stat_bonuses to the current unit's row and clamps each result to the shared stat caps. Columns: 0=accuracy, 1=evasion, 2=physical_attack, 3=physical_defense, 4=magic_attack, 5=magic_defense, 6=speed, 7=luck, 8=critical_chance, 9=capture_power, 10=movement, 11=max_hp, 12=max_sp, 13=max_fs. | | `0x69f8` | unit_current_stats | high | investigation | Persistent fourteen-stat row for each playable unit, using the same column order as unit_base_stats. CALCCC adds class_change_stat_bonuses to the current unit's row and clamps each result to the shared stat caps. Columns: 0=accuracy, 1=evasion, 2=physical_attack, 3=physical_defense, 4=magic_attack, 5=magic_defense, 6=speed, 7=luck, 8=critical_chance, 9=capture_power, 10=movement, 11=max_hp, 12=max_sp, 13=max_fs. |
| `0x74e8` | unit_skill_ids | high | investigation | Persistent four-skill row for each playable unit. CALCCC copies positive class_change_skill_awards into the first three slots after a promotion; ADDEXP compares the before/after row to report learned or replaced skills. Columns: 0=skill_slot_1, 1=skill_slot_2, 2=skill_slot_3, 3=skill_slot_4. | | `0x74e8` | unit_skill_ids | high | investigation | Persistent four-skill row for each playable unit. CALCCC copies positive class_change_skill_awards into the first three slots after a promotion; ADDEXP compares the before/after row to report learned or replaced skills. Columns: 0=skill_slot_1, 1=skill_slot_2, 2=skill_slot_3, 3=skill_slot_4. |
| `0x7684` | stage_clear_state | high | investigation | Persistent per-stage completion state indexed by stage id. STAGECLEAR sets the current stage cell to 1, while FORT, SELSTAGE, and FIELD use zero versus one to distinguish an uncleared mission from a cleared replay. | | `0x7684` | stage_clear_state | high | investigation | Persistent per-stage completion state indexed by stage id. STAGECLEAR sets the current stage cell to 1, while FORT, SELSTAGE, and FIELD use zero versus one to distinguish an uncleared mission from a cleared replay. |
| `0x141a4` | stage_object_runtime_state | high | investigation | Per-stage, per-object-slot runtime state. FIELD initializes mode-1 objects from STINIT's first tagged payload on a fresh stage and updates capturable-object ownership; DRAWOBJ uses it as the vertical sprite-row index. Other consumers interpret it by object type. | | `0x141a4` | stage_object_runtime_state | high | investigation | Per-stage, per-object-slot runtime state. FIELD initializes mode-1 objects from STINIT's first tagged payload on a fresh stage and updates capturable-object ownership; DRAWOBJ uses it as the vertical sprite-row index. RTN_M015 treats the state of Magic Pillar types 2..4 as their controlling faction and targets pillars whose value differs from the acting entity's faction. |
| `0x4e021` | entity_runtime_flags | high | investigation | Per-runtime-entity state flags. RTN_M007 requires bit 0 when selecting an injured ally, and MVSEEK mode 2 requires it before masking a foreign entity's occupied terrain cell. | | `0x4e021` | entity_runtime_flags | high | investigation | Per-runtime-entity state flags. RTN_M007 requires bit 0 when selecting an injured ally, and MVSEEK mode 2 requires it before masking a foreign entity's occupied terrain cell. |
| `0x4e085` | entity_current_resources | high | investigation | Per-runtime-entity current resources. DRAWCHP/DRAWENP render columns 0..2 against max-stat columns 11..13, skill/item resource deltas modify the same three columns, and movement search compares path cost with current_fs. Columns: 0=current_hp, 1=current_sp, 2=current_fs. | | `0x4e085` | entity_current_resources | high | investigation | Per-runtime-entity current resources. DRAWCHP/DRAWENP render columns 0..2 against max-stat columns 11..13, skill/item resource deltas modify the same three columns, and movement search compares path cost with current_fs. Columns: 0=current_hp, 1=current_sp, 2=current_fs. |
| `0x4e11b` | entity_effective_stats | high | investigation | Per-runtime-entity effective fourteen-stat row after CALCREVISE applies base data, equipment, skills, and conditions. Combat/UI consumers use columns 0..10 directly; columns 11..13 are the maxima paired with entity_current_resources HP/SP/FS. Columns: 0=accuracy, 1=evasion, 2=physical_attack, 3=physical_defense, 4=magic_attack, 5=magic_defense, 6=speed, 7=luck, 8=critical_chance, 9=capture_power, 10=movement, 11=max_hp, 12=max_sp, 13=max_fs. | | `0x4e11b` | entity_effective_stats | high | investigation | Per-runtime-entity effective fourteen-stat row after CALCREVISE applies base data, equipment, skills, and conditions. Combat/UI consumers use columns 0..10 directly; columns 11..13 are the maxima paired with entity_current_resources HP/SP/FS. Columns: 0=accuracy, 1=evasion, 2=physical_attack, 3=physical_defense, 4=magic_attack, 5=magic_defense, 6=speed, 7=luck, 8=critical_chance, 9=capture_power, 10=movement, 11=max_hp, 12=max_sp, 13=max_fs. |
@@ -126,8 +126,11 @@
| `0xaaa1e` | skill_battle_animation_id | high | investigation | Populated for 101 combat skills. BTL and CALCDMG place this value in the battle-animation selector before calling BTANINIT; most skills reuse their own id, while related skills deliberately share an animation and passive reactions use ids 801..808. | | `0xaaa1e` | skill_battle_animation_id | high | investigation | Populated for 101 combat skills. BTL and CALCDMG place this value in the battle-animation selector before calling BTANINIT; most skills reuse their own id, while related skills deliberately share an animation and passive reactions use ids 801..808. |
| `0xaab4a` | skill_handler_script_id | high | investigation | SKINIT field for all 131 skills. CHMENU and INFOIT look it up and pass it directly to call-script; packed id 0x31ca resolves to SKMES.BIN, the shared per-skill text/behavior dispatcher. | | `0xaab4a` | skill_handler_script_id | high | investigation | SKINIT field for all 131 skills. CHMENU and INFOIT look it up and pass it directly to call-script; packed id 0x31ca resolves to SKMES.BIN, the shared per-skill text/behavior dispatcher. |
| `0xab8c7` | class_change_rule_script_ids | high | investigation | CALCCC iterates these 32 cells and call-scripts every positive entry to evaluate class-change providers. CCINIT is the shipped rule program decoded into build/data/CCINIT.json. | | `0xab8c7` | class_change_rule_script_ids | high | investigation | CALCCC iterates these 32 cells and call-scripts every positive entry to evaluate class-change providers. CCINIT is the shipped rule program decoded into build/data/CCINIT.json. |
| `0xaba96` | pathfinding_remaining_route_steps | high | investigation | MVSEEK's row-major reachability grid. The origin receives movement+1 and each traversed edge decrements the value, so a larger positive value is nearer to the origin. RTN_M007 uses the difference from the origin value as its ally-search radius; RTN_M010 ranks Healing Feathers by the negated value to choose the nearest reachable object. | | `0xaba64` | stage_object_runtime_flags | high | investigation | Per-current-stage object flags. RTN_M010 and RTN_M015 require bit 1 before considering Healing Feathers or Magic Pillars as movement targets; FIELD and object rendering maintain the broader type-dependent bitfield. |
| `0xaba96` | pathfinding_remaining_route_steps | high | investigation | MVSEEK's row-major reachability grid. Mode 0 searches from the current entity with movement+1 at the origin; modes 1/2 search from the caller-supplied coordinate with 9999 at the origin. Each traversed edge decrements the value, so a larger positive value is nearer to the origin. RTN_M006/007/015 use origin-minus-target values as route-step radii; RTN_M010 ranks Healing Feathers by the negated value. |
| `0xb240e` | pathfinding_movement_costs | high | investigation | MVSEEK's row-major movement-cost work grid, indexed as [tile_y][tile_x] with stride 27. FIELD and RTN_M providers accept candidate destinations only when this cost is within the acting entity's current FS or a provider-specific override. | | `0xb240e` | pathfinding_movement_costs | high | investigation | MVSEEK's row-major movement-cost work grid, indexed as [tile_y][tile_x] with stride 27. FIELD and RTN_M providers accept candidate destinations only when this cost is within the acting entity's current FS or a provider-specific override. |
| `0xbf6fe` | pathfinding_filtered_route_scores | high | investigation | SETMVWORK begins by copying pathfinding_remaining_route_steps, then filters occupied entity cells according to faction and the acting entity's usable offensive-action mask/effectiveness. RTN_M providers combine this target-proximity score with a movement-limited MVSEEK grid to select a reachable tile nearest an entity or stage object. |
| `0xcc9f4` | offensive_action_scope_masks | high | investigation | CALCSCOPE clears ten encoded-range cells, sets bit 0 over the equipped/default attack's range, and sets bits 1..4 over each usable offensive skill's range. SETMVWORK uses the range-0 mask and paired attack elements when filtering target cells; RTN_M003/006/016/017/018 require its normal-attack bit. Columns: 0=range_0, 1=range_1, 2=range_2, 3=range_3, 4=range_4, 5=range_5, 6=range_6, 7=range_7, 8=range_8, 9=range_9. |
| `0xe6dee` | object_sprite_state_row_mode | high | investigation | OBINIT metadata indexed by object type. FIELD copies the type-tagged initial payload into stage_object_runtime_state only for mode 1; DRAWOBJ likewise multiplies that runtime state by the object sprite height to select source Y only for mode 1. | | `0xe6dee` | object_sprite_state_row_mode | high | investigation | OBINIT metadata indexed by object type. FIELD copies the type-tagged initial payload into stage_object_runtime_state only for mode 1; DRAWOBJ likewise multiplies that runtime state by the object sprite height to select source Y only for mode 1. |
| `0xe7302` | stage_bgm_id | high | investigation | STINIT's per-stage scalar loaded for all 74 records. FIELD passes the value directly to play-bgm when starting the stage. | | `0xe7302` | stage_bgm_id | high | investigation | STINIT's per-stage scalar loaded for all 74 records. FIELD passes the value directly to play-bgm when starting the stage. |
| `0xe7303` | stage_target_clear_turns | high | investigation | STINIT's target/par turn count. STAGECLEAR divides elapsed turns by this value to derive a performance multiplier; when replaying an already-cleared ordinary stage, FIELD also uses it as the forced-retreat turn limit. | | `0xe7303` | stage_target_clear_turns | high | investigation | STINIT's target/par turn count. STAGECLEAR divides elapsed turns by this value to derive a performance multiplier; when replaying an already-cleared ordinary stage, FIELD also uses it as the forced-retreat turn limit. |
@@ -161,7 +164,7 @@
| `0xe7a0f` | stage_enemy_forbidden_story_flags | high | investigation | Five negative prerequisites per stage enemy. FIELD subtracts one from every populated id and suppresses the spawn when the corresponding story_event_flags cell equals 1. Columns: 0=forbidden_flag_1, 1=forbidden_flag_2, 2=forbidden_flag_3, 3=forbidden_flag_4, 4=forbidden_flag_5. | | `0xe7a0f` | stage_enemy_forbidden_story_flags | high | investigation | Five negative prerequisites per stage enemy. FIELD subtracts one from every populated id and suppresses the spawn when the corresponding story_event_flags cell equals 1. Columns: 0=forbidden_flag_1, 1=forbidden_flag_2, 2=forbidden_flag_3, 3=forbidden_flag_4, 4=forbidden_flag_5. |
| `0xeff78` | movement_routine_provider_selectors | high | investigation | RTINIT movement bank 0. MVRTN indexes it by current_routine_set_id and routine_step_index, resolves the selector through its RTN_M001..018/051..053/061 provider table, and call-scripts the selected movement routine. | | `0xeff78` | movement_routine_provider_selectors | high | investigation | RTINIT movement bank 0. MVRTN indexes it by current_routine_set_id and routine_step_index, resolves the selector through its RTN_M001..018/051..053/061 provider table, and call-scripts the selected movement routine. |
| `0xf4d98` | movement_routine_activation_percents | high | investigation | RTINIT movement bank 1. After all other step gates pass, MVRTN executes the provider only when random-modulo-100 is below this value. | | `0xf4d98` | movement_routine_activation_percents | high | investigation | RTINIT movement bank 1. After all other step gates pass, MVRTN executes the provider only when random-modulo-100 is below this value. |
| `0xf9bb8` | movement_routine_parameter_1 | high | investigation | RTINIT movement bank 2. Its meaning is tagged by movement_routine_provider_selectors: RTN_M005/012 use destination_tile_x, RTN_M007 uses maximum_target_route_steps, RTN_M010 uses resource_index (0=HP, 1=SP, 2=FS; shipped cells are unwritten/default zero), and RTN_M011 uses destination_tile_x. | | `0xf9bb8` | movement_routine_parameter_1 | high | investigation | RTINIT movement bank 2. Its meaning is tagged by movement_routine_provider_selectors: RTN_M004 uses a stage_object_slot_index; RTN_M005/011/012 use destination_tile_x; RTN_M006/007/015 use maximum_target_route_steps; and RTN_M010 uses resource_index (0=HP, 1=SP, 2=FS; shipped cells are unwritten/default zero). |
| `0xfe9d8` | movement_routine_parameter_2 | high | investigation | RTINIT movement bank 3. Its meaning is tagged by movement_routine_provider_selectors: RTN_M005/011/012 use destination_tile_y, RTN_M007 uses maximum_target_hp_percent, and RTN_M010 uses maximum_resource_percent. | | `0xfe9d8` | movement_routine_parameter_2 | high | investigation | RTINIT movement bank 3. Its meaning is tagged by movement_routine_provider_selectors: RTN_M005/011/012 use destination_tile_y, RTN_M007 uses maximum_target_hp_percent, and RTN_M010 uses maximum_resource_percent. |
| `0x1037f8` | movement_routine_parameter_3 | high | investigation | RTINIT movement bank 4. RTN_M011 uses it as a one-based waypoint_ordinal, executing only the step whose ordinal matches the entity's current zero-based waypoint index. | | `0x1037f8` | movement_routine_parameter_3 | high | investigation | RTINIT movement bank 4. RTN_M011 uses it as a one-based waypoint_ordinal, executing only the step whose ordinal matches the entity's current zero-based waypoint index. |
| `0x108618` | movement_routine_parameter_4 | high | investigation | RTINIT movement bank 5. RTN_M011 uses a nonzero value as path_cost_limit_override; zero or an unwritten cell falls back to the entity's current FS. | | `0x108618` | movement_routine_parameter_4 | high | investigation | RTINIT movement bank 5. RTN_M011 uses a nonzero value as path_cost_limit_override; zero or an unwritten cell falls back to the entity's current FS. |
@@ -276,8 +279,6 @@
| `0xaba4b` | — | low | auto-shape | array | | `0xaba4b` | — | low | auto-shape | array |
| `0xaba53` | — | low | auto-shape | array | | `0xaba53` | — | low | auto-shape | array |
| `0xaba5f` | — | low | auto-shape | array | | `0xaba5f` | — | low | auto-shape | array |
| `0xaba64` | — | low | auto-shape | array |
| `0xcc9f4` | — | low | auto-shape | array |
| `0xcc9fe` | — | low | auto-shape | array | | `0xcc9fe` | — | low | auto-shape | array |
| `0xcca3a` | — | low | auto-shape | array | | `0xcca3a` | — | low | auto-shape | array |
| `0xccb66` | — | low | auto-shape | array | | `0xccb66` | — | low | auto-shape | array |
@@ -5036,7 +5037,6 @@
| `0xab7d6` | — | med | auto-shape | record-table[stride 11] | | `0xab7d6` | — | med | auto-shape | record-table[stride 11] |
| `0xab8b2` | — | med | auto-shape | record-table[stride 7] | | `0xab8b2` | — | med | auto-shape | record-table[stride 7] |
| `0xb8d86` | — | med | auto-shape | record-table[stride 27] | | `0xb8d86` | — | med | auto-shape | record-table[stride 27] |
| `0xbf6fe` | — | med | auto-shape | record-table[stride 27] |
| `0xc6077` | — | med | auto-shape | record-table[stride 27] | | `0xc6077` | — | med | auto-shape | record-table[stride 27] |
| `0xcc9f0` | — | low | auto-shape | index/counter? | | `0xcc9f0` | — | low | auto-shape | index/counter? |
| `0xcca08` | — | med | auto-shape | record-table[stride 5] | | `0xcca08` | — | med | auto-shape | record-table[stride 5] |

View File

@@ -444,8 +444,8 @@ keeps its raw `base/20/slot` fields and complete offset-tagged assignment histor
empty reserved banks. Structural and consumer-proven meanings live in `vm-map/globals.toml`; the generic empty reserved banks. Structural and consumer-proven meanings live in `vm-map/globals.toml`; the generic
parameter names remain as raw provenance while each RTN_M/RTN_B consumer proves its tagged schema. parameter names remain as raw provenance while each RTN_M/RTN_B consumer proves its tagged schema.
The provider-specific join now covers RTN_M005/007/010/011/012: 292 movement steps, 758 populated The provider-specific join now covers RTN_M004/005/006/007/010/011/012/015: 508 movement steps, 971
parameters, and seven explicit zero defaults. RTN_M005/011/012 read banks 2/3 as populated parameters, and ten explicit zero defaults. RTN_M005/011/012 read banks 2/3 as
`destination_tile_x` / `destination_tile_y` and approach that exact map tile, incrementing the current `destination_tile_x` / `destination_tile_y` and approach that exact map tile, incrementing the current
step's progress counter after arrival. Their alternate completion test recognizes a type-6 stage object step's progress counter after arrival. Their alternate completion test recognizes a type-6 stage object
at the authored destination and also accepts the object's linked exit tile. RTN_M012 is byte-for-byte at the authored destination and also accepts the object's linked exit tile. RTN_M012 is byte-for-byte
@@ -453,6 +453,17 @@ equivalent to M005 except for its MVSEEK mode: mode 2 masks the doubled-coordina
active foreign-faction entity before the flood fill, so the generated behavior distinguishes this active foreign-faction entity before the flood fill, so the generated behavior distinguishes this
foreign-entity-avoiding route from ordinary M005. foreign-entity-avoiding route from ordinary M005.
RTN_M004's bank-2 value is a zero-based `stage_object_slot_index`. It approaches that current-stage
object and uses the same exact-tile/type-6-linked-exit completion contract as the coordinate providers.
Three of its 70 steps leave the cell unwritten and therefore receive an explicit semantic slot-0 default;
the generic raw bank remains absent in those rows.
RTN_M006 is the nearest-enemy form. Bank 2 is an inclusive `maximum_target_route_steps`, authored from
1 through 7 plus 10 and 20. It requires the normal-attack bit at encoded range 0, selects the nearest
active entity of another faction which remains eligible after SETMVWORK's offensive-action filtering,
randomizes equal-distance ties, and approaches a reachable tile nearest that enemy. Producing a valid
destination increments the step's progress counter.
RTN_M011 is the cyclic-waypoint form. Bank 4 is a one-based `waypoint_ordinal`; only the step whose RTN_M011 is the cyclic-waypoint form. Bank 4 is a one-based `waypoint_ordinal`; only the step whose
ordinal minus one matches `entity_patrol_waypoint_indices[current_entity]` executes. Arrival advances ordinal minus one matches `entity_patrol_waypoint_indices[current_entity]` executes. Arrival advances
that runtime index modulo the largest RTN_M011 ordinal in the selected routine set. Bank 5 is an optional that runtime index modulo the largest RTN_M011 ordinal in the selected routine set. Bank 5 is an optional
@@ -471,13 +482,27 @@ zero/HP default without fabricating a raw assignment. Bank 3 is an inclusive
provider chooses the nearest active OBINIT type 15 or 16 object (`治癒の羽`, full status recovery, or its provider chooses the nearest active OBINIT type 15 or 16 object (`治癒の羽`, full status recovery, or its
single-use red variant) and approaches a reachable tile nearest it. single-use red variant) and approaches a reachable tile nearest it.
RTN_M015 is the Magic Pillar form. It chooses the nearest active OBINIT type 2/3/4 object (small,
medium, or large `魔力の柱`) whose runtime ownership state differs from the acting entity's faction.
Bank 2 is an inclusive `maximum_target_route_steps`, authored from 2 through 6; the provider produces
movement only when the chosen foreign-controlled pillar is within that radius.
MVSEEK's mode contract is also now explicit. Mode 0 replaces the input coordinate with the current
entity tile and seeds the origin with movement+1, producing the movement-limited reachability grid.
Modes 1/2 retain the caller coordinate and seed it with 9999, producing a broad target-distance grid;
mode 2 additionally applies the foreign-entity terrain mask described above. Every traversed edge
decrements `pathfinding_remaining_route_steps`, so origin minus target is the route-step distance used
by M006/007/015.
`movement_steps` now carry these selector-scoped semantic fields beside the original `movement_steps` now carry these selector-scoped semantic fields beside the original
`movement_parameter_1..4`, and top-level `movement_provider_parameter_schemas` records the reusable `movement_parameter_1..4`, and top-level `movement_provider_parameter_schemas` records the reusable
mapping, target-selection rules, and zero/unwritten behavior. No meaning is projected onto other mapping, target-selection rules, and zero/unwritten behavior. No meaning is projected onto other
providers. The supporting runtime joins are now curated too: `entity_runtime_flags`, providers. The supporting runtime joins are now curated too: `entity_runtime_flags`,
`entity_faction_ids`, `entity_tile_x`/`entity_tile_y`, the fourteen-column `entity_effective_stats`, `entity_faction_ids`, `entity_tile_x`/`entity_tile_y`, the fourteen-column `entity_effective_stats`,
current HP/SP/FS, `movement_search_mode`, `pathfinding_remaining_route_steps`, current HP/SP/FS, `stage_object_runtime_flags`, `movement_search_mode`,
`pathfinding_movement_costs`, and the per-entity patrol waypoint index. `offensive_action_scope_masks`, `pathfinding_remaining_route_steps`,
`pathfinding_filtered_route_scores`, `pathfinding_movement_costs`, and the per-entity patrol waypoint
index.
### The curated registry — `vm-map/globals.toml` (2026-07-07) ### The curated registry — `vm-map/globals.toml` (2026-07-07)

View File

@@ -787,12 +787,12 @@ the shared `semantic_fields` join. SCINIT is now the sixth shape: 2,179 paired a
resolved and the full overwrite history retained. RTINIT is now the seventh shape: its twenty parallel resolved and the full overwrite history retained. RTINIT is now the seventh shape: its twenty parallel
1000-by-20 banks produce 172 routine sets, 1,043 movement steps, and fourteen battle steps with RTN_M/RTN_B 1000-by-20 banks produce 172 routine sets, 1,043 movement steps, and fourteen battle steps with RTN_M/RTN_B
provider joins, activation/progress/story gates, six explicit reserved banks, and complete overwrite provider joins, activation/progress/story gates, six explicit reserved banks, and complete overwrite
history. Provider-tagged decoding now covers movement providers 5, 7, 10, 11, and 12: coordinate history. Provider-tagged decoding now covers movement providers 4, 5, 6, 7, 10, 11, 12, and 15:
destinations (including M012's foreign-entity route mask), injured-ally selection by route radius and HP stage-object slots, coordinate destinations (including M012's foreign-entity route mask), nearest-enemy
cutoff, Healing Feather selection gated by current resource percentage, and cyclic waypoints with an and injured-ally searches, resource-gated Healing Feather selection, cyclic waypoints, and
optional path-cost limit. This projects 758 populated parameters plus seven explicit zero/HP defaults foreign-controlled Magic Pillars. This projects 971 populated parameters plus ten explicit defaults
across 292 steps without assigning those meanings to other providers that share the same raw banks. across 508 steps without assigning those meanings to other providers that share the same raw banks.
Continue the remaining parameterized RTN_M consumers by evidence density. Continue with the sparse parameter tail in RTN_M001/008/013/014.
Once the natural spine and first gameplay loop are trustworthy, broaden in independent tracks: Once the natural spine and first gameplay loop are trustworthy, broaden in independent tracks:

View File

@@ -99,10 +99,11 @@ RTINIT is a seventh banked shape. Its 3,336 writes populate twenty parallel `100
movement banks consumed by MVRTN/RTN_M providers and ten battle banks consumed by BTRTN/RTN_B providers. movement banks consumed by MVRTN/RTN_M providers and ten battle banks consumed by BTRTN/RTN_B providers.
The generated 172 routine-set records assemble 1,043 movement steps and fourteen battle steps, join The generated 172 routine-set records assemble 1,043 movement steps and fourteen battle steps, join
provider selectors to script names, retain all 29 overwritten cells, and keep the six reserved empty provider selectors to script names, retain all 29 overwritten cells, and keep the six reserved empty
banks visible. Selector-specific parameter schemas now cover RTN_M005/012 coordinate destinations, banks visible. Selector-specific parameter schemas now cover RTN_M004 stage-object slots,
RTN_M007 injured-ally search, RTN_M010 resource-threshold Healing Feather search, and RTN_M011 cyclic RTN_M005/012 coordinate destinations, RTN_M006 nearest-enemy search, RTN_M007 injured-ally search,
waypoints with an optional path-cost limit. The generated join covers 292 steps, 758 populated parameters, RTN_M010 resource-threshold Healing Feather search, RTN_M011 cyclic waypoints, and RTN_M015
and seven explicit zero/HP defaults while retaining the structurally named raw banks for every provider. foreign-controlled Magic Pillars. The generated join covers 508 steps, 971 populated parameters, and ten
explicit defaults while retaining the structurally named raw banks for every provider.
### Message/string tables (`*MES`) ### Message/string tables (`*MES`)
`ITMES` (64 KB — item text), `VIMES` (43 KB), `EIMES` (37 KB), `SKMES` (31 KB — skill `ITMES` (64 KB — item text), `VIMES` (43 KB), `EIMES` (37 KB), `SKMES` (31 KB — skill

View File

@@ -55,7 +55,7 @@ All opcode knowledge (ABI, semantics, provenance, `depends_on`) is hand-edited *
|---|---|---|---| |---|---|---|---|
| `extract_phase2.py` | Batch: disassembly + text corpora for every script. | `extract_phase2.py` | corpus → `build/disasm/*.asm`, `build/text/{dialogue.jsonl,strings.jsonl,*.strings.txt}`, `build/manifest.json` | | `extract_phase2.py` | Batch: disassembly + text corpora for every script. | `extract_phase2.py` | corpus → `build/disasm/*.asm`, `build/text/{dialogue.jsonl,strings.jsonl,*.strings.txt}`, `build/manifest.json` |
| `extract_message_table.py` | Discover a repeated global-id dispatch chain such as ITMES/SKMES, reconstruct player-facing title/description lines (including furigana surface text and readings), and emit an ID-keyed message table with bytecode provenance. | `extract_message_table.py <MES> [OUTNAME]` | `<MES>.BIN``build/data/<OUTNAME>.json` | | `extract_message_table.py` | Discover a repeated global-id dispatch chain such as ITMES/SKMES, reconstruct player-facing title/description lines (including furigana surface text and readings), and emit an ID-keyed message table with bytecode provenance. | `extract_message_table.py <MES> [OUTNAME]` | `<MES>.BIN``build/data/<OUTNAME>.json` |
| `extract_init.py` | Parse a `*INIT` data source (auto-detects name / numeric / footer / mixed / rules / dispatch / banked shape). Name tables infer their reserved record span, preserve sparse one-based runtime ids, distinguish lookup bases from first written cells, statically evaluate direct and negative-value writes, and separate parallel `fields` from linked row-major `record_fields`; when flat global ranges overlap, a parallel base established by other records wins over a coincidental row-table cell calculation. Mixed tables recover selector-dispatched records, condition strings, scalars, preallocated buffer cells, consumer-confirmed strides, and length-prefixed footer arrays; STINIT additionally assembles confirmed buffers into `object_placements` and `enemy_spawns`, joins object type names and available descriptions from OBINIT, and exposes consumer-proven tagged payloads (teleport, treasure, card, initial faction, non-triggering hazard/barrier faction, and OBINIT-gated initial object state), preserves engine-dead type-27 writes under `ignored_payload_fields`, and exposes reinforcement schedules and first-clear-only enemy gates. Rules mode decodes CCINIT's source-ordered class-change predicates and output accumulators, joining EBINIT unit names, SKINIT skill names, titles, named stat bonuses, cost deltas, and applied-state slots. Dispatch mode decodes SCINIT's paired decision-to-packed-scene and authored-chapter arrays, preserving source-order overwrites, resolving SYS4INI script names, and cross-checking chapter tags against decoded SCJUMP paths. Banked mode decodes RTINIT's twenty parallel 1000-by-20 movement/battle routine banks, retains all assignments and overwrites, assembles final per-slot steps, resolves provider selectors to RTN_M/RTN_B scripts, and applies selector-scoped parameter schemas where proven. Current schemas cover RTN_M005/012 coordinate destinations, RTN_M007 injured-ally search, RTN_M010 resource-threshold Healing Feather search, and RTN_M011 cyclic waypoints; provider defaults such as M010's unwritten zero/HP resource index are projected explicitly and counted separately from populated source cells. Raw provider banks remain intact, and top-level `movement_provider_parameter_schemas` documents the projection. ITINIT and SKINIT join ITMES/SKMES messages. Top-level `field_semantics` maps raw keys to canonical global/column names, while each record's `semantic_fields` is the generated name-keyed join; complete footer copies map to a row and expose its values without the raw provenance wrapper. Raw keys and unresolved tagged payload cells remain provenance. OUTNAME accepts a stem or one `.json` suffix and rejects paths. Refreshes the generated data index. | `extract_init.py <TABLE> [OUTNAME] [--mode …]` | `<TABLE>.BIN` plus EBINIT/SKINIT for CCINIT, OBINIT for STINIT, `build/callscript-names.json` for RTINIT/SCINIT, `build/scjump-decisions.json` for SCINIT, matching `<MES>.BIN` when supported, and `build/globals.json``build/data/<OUTNAME>.json`, `build/data/README.md` | | `extract_init.py` | Parse a `*INIT` data source (auto-detects name / numeric / footer / mixed / rules / dispatch / banked shape). Name tables infer their reserved record span, preserve sparse one-based runtime ids, distinguish lookup bases from first written cells, statically evaluate direct and negative-value writes, and separate parallel `fields` from linked row-major `record_fields`; when flat global ranges overlap, a parallel base established by other records wins over a coincidental row-table cell calculation. Mixed tables recover selector-dispatched records, condition strings, scalars, preallocated buffer cells, consumer-confirmed strides, and length-prefixed footer arrays; STINIT additionally assembles confirmed buffers into `object_placements` and `enemy_spawns`, joins object type names and available descriptions from OBINIT, and exposes consumer-proven tagged payloads (teleport, treasure, card, initial faction, non-triggering hazard/barrier faction, and OBINIT-gated initial object state), preserves engine-dead type-27 writes under `ignored_payload_fields`, and exposes reinforcement schedules and first-clear-only enemy gates. Rules mode decodes CCINIT's source-ordered class-change predicates and output accumulators, joining EBINIT unit names, SKINIT skill names, titles, named stat bonuses, cost deltas, and applied-state slots. Dispatch mode decodes SCINIT's paired decision-to-packed-scene and authored-chapter arrays, preserving source-order overwrites, resolving SYS4INI script names, and cross-checking chapter tags against decoded SCJUMP paths. Banked mode decodes RTINIT's twenty parallel 1000-by-20 movement/battle routine banks, retains all assignments and overwrites, assembles final per-slot steps, resolves provider selectors to RTN_M/RTN_B scripts, and applies selector-scoped parameter schemas where proven. Current schemas cover RTN_M004 stage-object slots, RTN_M005/012 coordinate destinations, RTN_M006/007 enemy/ally searches, RTN_M010 resource-threshold Healing Feather search, RTN_M011 cyclic waypoints, and RTN_M015 foreign-controlled Magic Pillars; provider defaults such as M004's unwritten slot 0 and M010's unwritten zero/HP resource index are projected explicitly and counted separately from populated source cells. Raw provider banks remain intact, and top-level `movement_provider_parameter_schemas` documents the projection. ITINIT and SKINIT join ITMES/SKMES messages. Top-level `field_semantics` maps raw keys to canonical global/column names, while each record's `semantic_fields` is the generated name-keyed join; complete footer copies map to a row and expose its values without the raw provenance wrapper. Raw keys and unresolved tagged payload cells remain provenance. OUTNAME accepts a stem or one `.json` suffix and rejects paths. Refreshes the generated data index. | `extract_init.py <TABLE> [OUTNAME] [--mode …]` | `<TABLE>.BIN` plus EBINIT/SKINIT for CCINIT, OBINIT for STINIT, `build/callscript-names.json` for RTINIT/SCINIT, `build/scjump-decisions.json` for SCINIT, matching `<MES>.BIN` when supported, and `build/globals.json``build/data/<OUTNAME>.json`, `build/data/README.md` |
| `init_table_profile.py` | Build the static investigation surface for an extracted name/numeric/mixed/rules/dispatch/banked table: per-scalar/string/array-cell/footer-array population and value distributions, representative records, and direct opcode/script consumers. Name tables also report message coverage; rule tables summarize covered units, titled and level-independent rules, threshold/slot distributions, and skill awards; dispatch tables summarize assignments, overwrites, script-name resolution, and SCJUMP chapter agreement; banked tables summarize populated/reserved banks, movement/battle steps and providers, selector-specific semantic coverage, and overwrite conflicts. `--message-query REGEX` shows every matching name/message beside all populated fields for semantic correlation. Findings are evidence only; confirmed meanings go in `vm-map/globals.toml`. | `init_table_profile.py <TABLE> [--build] [--limit N] [--message-query REGEX]` | `build/data/<TABLE>.json` + corpus → stdout; with `--build`, `build/data/<TABLE>-field-profile.{json,md}` | | `init_table_profile.py` | Build the static investigation surface for an extracted name/numeric/mixed/rules/dispatch/banked table: per-scalar/string/array-cell/footer-array population and value distributions, representative records, and direct opcode/script consumers. Name tables also report message coverage; rule tables summarize covered units, titled and level-independent rules, threshold/slot distributions, and skill awards; dispatch tables summarize assignments, overwrites, script-name resolution, and SCJUMP chapter agreement; banked tables summarize populated/reserved banks, movement/battle steps and providers, selector-specific semantic coverage, and overwrite conflicts. `--message-query REGEX` shows every matching name/message beside all populated fields for semantic correlation. Findings are evidence only; confirmed meanings go in `vm-map/globals.toml`. | `init_table_profile.py <TABLE> [--build] [--limit N] [--message-query REGEX]` | `build/data/<TABLE>.json` + corpus → stdout; with `--build`, `build/data/<TABLE>-field-profile.{json,md}` |
| `test_extract_init.py`, `test_init_table_profile.py` | Regression checks for sparse one-based, mixed selector-dispatched, CCINIT rule, SCINIT dispatch, and RTINIT banked extraction; MES reconstruction/joins; footer-array accounting and semantic projection; EBINIT/SKINIT/OBINIT definition joins; STINIT object/enemy joins and tagged-payload behavior; overwrite/provider joins; and field/message/rule/dispatch/banked profiling. | run each directly | — | | `test_extract_init.py`, `test_init_table_profile.py` | Regression checks for sparse one-based, mixed selector-dispatched, CCINIT rule, SCINIT dispatch, and RTINIT banked extraction; MES reconstruction/joins; footer-array accounting and semantic projection; EBINIT/SKINIT/OBINIT definition joins; STINIT object/enemy joins and tagged-payload behavior; overwrite/provider joins; and field/message/rule/dispatch/banked profiling. | run each directly | — |
| `global_map.py` | Build the partial global-variable name map from static evidence. | `global_map.py` | corpus + `build/data/``build/global-var-map.{json,md}` | | `global_map.py` | Build the partial global-variable name map from static evidence. | `global_map.py` | corpus + `build/data/``build/global-var-map.{json,md}` |

View File

@@ -57,9 +57,9 @@
- [x] **2.3 — Extract `STINIT`'s 74 sparse stage records.** The mixed mode identifies the dominant `scjump_progress_a` dispatch, recovers 29 preallocated buffer layouts (including six consumer-confirmed row strides), and keeps four condition strings, six scalars, fixed-buffer writes, and all 1,396 footer-array copies separated by stage id. Profiles supply population/value and direct-consumer evidence. Header/map semantics cover conditions, BGM, turn/replay/clear-reward settings, and map texture overrides. The object join assembles 2,312 placements with type/position/gates, OBINIT names and available descriptions, 604 reinforcement schedules, and typed initial-faction, teleport, treasure, card-list, non-triggering-faction, and initial-object-state payloads; FIELD's dedicated special-spawn path proves the final three populated type-27 tagged writes are engine-dead, so they remain visible as ignored provenance rather than unresolved semantics. The 30-cell enemy family contributes 1,378 joined spawns with unit/faction, placement, difficulty/story gates, level scaling, weighted selection, difficulty-specific movement/battle routine sets, and 485 first-clear-only gates. Raw address views remain alongside generated `semantic_fields`. - [x] **2.3 — Extract `STINIT`'s 74 sparse stage records.** The mixed mode identifies the dominant `scjump_progress_a` dispatch, recovers 29 preallocated buffer layouts (including six consumer-confirmed row strides), and keeps four condition strings, six scalars, fixed-buffer writes, and all 1,396 footer-array copies separated by stage id. Profiles supply population/value and direct-consumer evidence. Header/map semantics cover conditions, BGM, turn/replay/clear-reward settings, and map texture overrides. The object join assembles 2,312 placements with type/position/gates, OBINIT names and available descriptions, 604 reinforcement schedules, and typed initial-faction, teleport, treasure, card-list, non-triggering-faction, and initial-object-state payloads; FIELD's dedicated special-spawn path proves the final three populated type-27 tagged writes are engine-dead, so they remain visible as ignored provenance rather than unresolved semantics. The 30-cell enemy family contributes 1,378 joined spawns with unit/faction, placement, difficulty/story gates, level scaling, weighted selection, difficulty-specific movement/battle routine sets, and 485 first-clear-only gates. Raw address views remain alongside generated `semantic_fields`.
- [x] **2.3a — Extract `CCINIT`'s 71 class-change rules.** Rules mode preserves source-order guards and detects the unit id, minimum level, clear applied-state slot, selected title/level, deployment-cost delta, named fourteen-stat bonuses, awarded SKINIT skills, and state slot set by each rule. EBINIT/SKINIT definition joins and the common global semantic projection coexist with raw addresses. CALCCC/ADDEXP establish the apply/report ABI; EVOLVE explains the two level-independent empty-title Lily rules. The generated profile covers 33 units, 69 titled rules, 30 skill awards, three used promotion slots, and 19 populated output fields. - [x] **2.3a — Extract `CCINIT`'s 71 class-change rules.** Rules mode preserves source-order guards and detects the unit id, minimum level, clear applied-state slot, selected title/level, deployment-cost delta, named fourteen-stat bonuses, awarded SKINIT skills, and state slot set by each rule. EBINIT/SKINIT definition joins and the common global semantic projection coexist with raw addresses. CALCCC/ADDEXP establish the apply/report ABI; EVOLVE explains the two level-independent empty-title Lily rules. The generated profile covers 33 units, 69 titled rules, 30 skill awards, three used promotion slots, and 19 populated output fields.
- [x] **2.3b — Extract `SCINIT`'s scene-dispatch registry.** Dispatch mode recognizes 2,179 alternating writes to two 10,000-cell arrays, preserves all 710 overwritten decision ids, and emits 1,209 final rows. The primary column maps decisions to 135 packed SYS4INI ids, all resolved to numbered SC scripts; the parallel column is authored chapter metadata. All 847 live SCJUMP decisions join to rows and 844 final chapter tags agree with the independently decoded paths; three legacy/stale mismatches remain explicit. - [x] **2.3b — Extract `SCINIT`'s scene-dispatch registry.** Dispatch mode recognizes 2,179 alternating writes to two 10,000-cell arrays, preserves all 710 overwritten decision ids, and emits 1,209 final rows. The primary column maps decisions to 135 packed SYS4INI ids, all resolved to numbered SC scripts; the parallel column is authored chapter metadata. All 847 live SCJUMP decisions join to rows and 844 final chapter tags agree with the independently decoded paths; three legacy/stale mismatches remain explicit.
- [x] **2.3c — Extract `RTINIT`'s routine-step banks.** Banked mode recognizes twenty parallel 1000-by-20 tables and emits 172 sparse routine-set rows with all 3,336 source assignments and 3,307 final cells. Movement banks join 1,043 steps to 19 used RTN_M providers (22 dispatchable); battle banks join fourteen steps to all four RTN_B providers. Activation percentages, progress gates, and required/forbidden story flags are consumer-proven; six empty banks remain explicit. RTN_M005/007/010/011/012 add selector-specific coordinate, injured-ally, Healing Feather, and waypoint semantics to 292 steps, 758 populated parameters, and seven explicit defaults while retaining the generic raw banks. - [x] **2.3c — Extract `RTINIT`'s routine-step banks.** Banked mode recognizes twenty parallel 1000-by-20 tables and emits 172 sparse routine-set rows with all 3,336 source assignments and 3,307 final cells. Movement banks join 1,043 steps to 19 used RTN_M providers (22 dispatchable); battle banks join fourteen steps to all four RTN_B providers. Activation percentages, progress gates, and required/forbidden story flags are consumer-proven; six empty banks remain explicit. RTN_M004/005/006/007/010/011/012/015 add selector-specific object-slot, coordinate, enemy/ally search, Healing Feather, waypoint, and Magic Pillar semantics to 508 steps, 971 populated parameters, and ten explicit defaults while retaining the generic raw banks.
- [x] **2.4 — Partial global-var map BUILT + wired into the disassembler.** `tools/global_map.py``build/global-var-map.{json,md}` (16,354/49,435 globals labelled: string tables, `*INIT` field arrays, 122 record tables w/ strides, current-entity index pointers). `sys4load` renders the labels inline (`=rec[s30]`, `=current-entity-index?`). See `docs/name-resolution.md`. - [x] **2.4 — Partial global-var map BUILT + wired into the disassembler.** `tools/global_map.py``build/global-var-map.{json,md}` (16,354/49,435 globals labelled: string tables, `*INIT` field arrays, 122 record tables w/ strides, current-entity index pointers). `sys4load` renders the labels inline (`=rec[s30]`, `=current-entity-index?`). See `docs/name-resolution.md`.
- [ ] **2.5 — Grow the global-var map (future, incremental).** Static first: continue RTINIT's provider-tagged parameters after the completed RTN_M005/007/010/011/012 slices, fold in remaining `*MES` writers, and label other 2D record tables by their reader scripts. Then Frida to name *which stat* each unresolved field is. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids and SCJUMP decision-to-scene dispatch are resolved; see `docs/name-resolution.md` #1 and `docs/scjump-progression.md`. - [ ] **2.5 — Grow the global-var map (future, incremental).** Static first: close RTINIT's sparse parameter tail in RTN_M001/008/013/014 after the completed M004/005/006/007/010/011/012/015 slices, fold in remaining `*MES` writers, and label other 2D record tables by their reader scripts. Then Frida to name *which stat* each unresolved field is. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids and SCJUMP decision-to-scene dispatch are resolved; see `docs/name-resolution.md` #1 and `docs/scjump-progression.md`.
## Phase 3 — Name the unnamed opcodes *(top ~20 BEFORE Phase 4; the rest on demand)* ## Phase 3 — Name the unnamed opcodes *(top ~20 BEFORE Phase 4; the rest on demand)*

View File

@@ -91,6 +91,27 @@ ROUTINE_BANK_ROLES = (
) )
MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = { MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
4: {
"behavior": "approach_stage_object_slot",
"parameter_fields": {
"movement_parameter_1": "stage_object_slot_index",
},
"parameter_defaults": {
"movement_parameter_1": 0,
},
"parameter_notes": {
"stage_object_slot_index": (
"zero-based index into the current stage's object arrays; "
"shipped explicit values are 1 or 2, with three unwritten "
"cells using the zero/slot-0 default"
),
},
"completion": (
"advance the current step's progress counter after reaching the "
"selected object's tile (or, for a type-6 stage object, its linked "
"exit tile)"
),
},
5: { 5: {
"behavior": "approach_destination_tile", "behavior": "approach_destination_tile",
"parameter_fields": { "parameter_fields": {
@@ -102,6 +123,29 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"destination tile (or its linked type-6 stage-object exit tile)" "destination tile (or its linked type-6 stage-object exit tile)"
), ),
}, },
6: {
"behavior": "approach_nearest_enemy",
"parameter_fields": {
"movement_parameter_1": "maximum_target_route_steps",
},
"parameter_notes": {
"maximum_target_route_steps": (
"inclusive route-step radius from the acting entity after "
"SETMVWORK applies offensive-action eligibility; shipped "
"values are 1..7, 10, or 20"
),
},
"target_selection": (
"nearest active entity of another faction within the route-step "
"radius; choose randomly among ties, then approach a reachable "
"tile nearest that enemy; execution also requires the normal-"
"attack bit in offensive_action_scope_masks[0]"
),
"completion": (
"advance the current step's progress counter after producing a "
"valid movement destination toward the selected enemy"
),
},
7: { 7: {
"behavior": "approach_injured_ally", "behavior": "approach_injured_ally",
"parameter_fields": { "parameter_fields": {
@@ -197,6 +241,27 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"destination tile (or its linked type-6 stage-object exit tile)" "destination tile (or its linked type-6 stage-object exit tile)"
), ),
}, },
15: {
"behavior": "approach_foreign_magic_pillar",
"parameter_fields": {
"movement_parameter_1": "maximum_target_route_steps",
},
"parameter_notes": {
"maximum_target_route_steps": (
"inclusive route-step radius; shipped values are 2..6"
),
},
"target_selection": (
"nearest active stage object of OBINIT type 2, 3, or 4 (small, "
"medium, or large Magic Pillar) whose runtime state/faction differs "
"from the acting entity; require it to be within the route-step "
"radius, then approach a reachable tile nearest that object"
),
"completion": (
"produce a movement result only when a foreign-controlled Magic "
"Pillar exists within the configured route-step radius"
),
},
} }
UNIT_STAT_COLUMNS = ( UNIT_STAT_COLUMNS = (

View File

@@ -371,10 +371,10 @@ def test_real_routine_banks() -> None:
and len(meta["used_battle_provider_selectors"]) == 4 and len(meta["used_battle_provider_selectors"]) == 4
and len(meta["record_field_columns"]) == 117, and len(meta["record_field_columns"]) == 117,
"RTINIT assembles every populated movement and battle step") "RTINIT assembles every populated movement and battle step")
check(meta["decoded_movement_provider_count"] == 5 check(meta["decoded_movement_provider_count"] == 8
and meta["decoded_movement_step_count"] == 292 and meta["decoded_movement_step_count"] == 508
and meta["decoded_movement_parameter_count"] == 758 and meta["decoded_movement_parameter_count"] == 971
and meta["decoded_movement_defaulted_parameter_count"] == 7, and meta["decoded_movement_defaulted_parameter_count"] == 10,
"RTINIT reports selector-specific semantic coverage") "RTINIT reports selector-specific semantic coverage")
check([ check([
layout["bank_index"] layout["bank_index"]
@@ -434,6 +434,26 @@ def test_real_routine_banks() -> None:
and provider_12["destination_tile_x"] == 11 and provider_12["destination_tile_x"] == 11
and provider_12["destination_tile_y"] == 68, and provider_12["destination_tile_y"] == 68,
"RTINIT joins RTN_M012's route-mode destination semantics") "RTINIT joins RTN_M012's route-mode destination semantics")
provider_4 = by_id[5]["movement_steps"][0]
check(provider_4["movement_provider_selector"] == 4
and provider_4["provider_behavior"] == "approach_stage_object_slot"
and provider_4["stage_object_slot_index"] == 1,
"RTINIT joins RTN_M004's stage-object slot semantics")
provider_4_default = by_id[17]["movement_steps"][1]
check(provider_4_default["movement_provider_selector"] == 4
and provider_4_default["stage_object_slot_index"] == 0
and "movement_parameter_1" not in provider_4_default,
"RTINIT projects RTN_M004's implicit stage-object slot zero")
provider_6 = by_id[6]["movement_steps"][0]
check(provider_6["movement_provider_selector"] == 6
and provider_6["provider_behavior"] == "approach_nearest_enemy"
and provider_6["maximum_target_route_steps"] == 5,
"RTINIT joins RTN_M006's enemy-search radius")
provider_15 = by_id[2]["movement_steps"][0]
check(provider_15["movement_provider_selector"] == 15
and provider_15["provider_behavior"] == "approach_foreign_magic_pillar"
and provider_15["maximum_target_route_steps"] == 3,
"RTINIT joins RTN_M015's foreign Magic Pillar search radius")
check("provider_behavior" not in movement check("provider_behavior" not in movement
and "destination_tile_x" not in movement, and "destination_tile_x" not in movement,
"RTINIT does not leak provider-specific meanings onto undecoded selectors") "RTINIT does not leak provider-specific meanings onto undecoded selectors")

View File

@@ -33,6 +33,11 @@ def test_load_and_lint():
check(entries[0xaba96]["name"] == "pathfinding_remaining_route_steps" check(entries[0xaba96]["name"] == "pathfinding_remaining_route_steps"
and entries[0xcc9f1]["name"] == "movement_search_mode", and entries[0xcc9f1]["name"] == "movement_search_mode",
"movement-search reachability state is curated") "movement-search reachability state is curated")
check(entries[0xbf6fe]["name"] == "pathfinding_filtered_route_scores"
and entries[0xcc9f4]["name"] == "offensive_action_scope_masks",
"movement target filtering and offensive scope are curated")
check(entries[0xaba64]["name"] == "stage_object_runtime_flags",
"stage-object targeting flags are curated")
check(entries[0xb240e]["name"] == "pathfinding_movement_costs", check(entries[0xb240e]["name"] == "pathfinding_movement_costs",
"movement-cost work grid is curated") "movement-cost work grid is curated")
# lint clean against a permissive address universe (curated addrs are self-consistent) # lint clean against a permissive address universe (curated addrs are self-consistent)

View File

@@ -850,7 +850,7 @@ name = "movement_routine_parameter_1"
category = "data-table" category = "data-table"
type = "int[1000][20]" type = "int[1000][20]"
value_domain = "provider-specific integer" value_domain = "provider-specific integer"
usage = "RTINIT movement bank 2. Its meaning is tagged by movement_routine_provider_selectors: RTN_M005/012 use destination_tile_x, RTN_M007 uses maximum_target_route_steps, RTN_M010 uses resource_index (0=HP, 1=SP, 2=FS; shipped cells are unwritten/default zero), and RTN_M011 uses destination_tile_x." usage = "RTINIT movement bank 2. Its meaning is tagged by movement_routine_provider_selectors: RTN_M004 uses a stage_object_slot_index; RTN_M005/011/012 use destination_tile_x; RTN_M006/007/015 use maximum_target_route_steps; and RTN_M010 uses resource_index (0=HP, 1=SP, 2=FS; shipped cells are unwritten/default zero)."
source = "investigation" source = "investigation"
confidence = "high" confidence = "high"
depends_on = ["0xeff78"] depends_on = ["0xeff78"]
@@ -1292,22 +1292,45 @@ name = "pathfinding_remaining_route_steps"
category = "data-table" category = "data-table"
type = "int[][27]" type = "int[][27]"
value_domain = "0 for unreachable; positive remaining flood-fill steps" value_domain = "0 for unreachable; positive remaining flood-fill steps"
usage = "MVSEEK's row-major reachability grid. The origin receives movement+1 and each traversed edge decrements the value, so a larger positive value is nearer to the origin. RTN_M007 uses the difference from the origin value as its ally-search radius; RTN_M010 ranks Healing Feathers by the negated value to choose the nearest reachable object." usage = "MVSEEK's row-major reachability grid. Mode 0 searches from the current entity with movement+1 at the origin; modes 1/2 search from the caller-supplied coordinate with 9999 at the origin. Each traversed edge decrements the value, so a larger positive value is nearer to the origin. RTN_M006/007/015 use origin-minus-target values as route-step radii; RTN_M010 ranks Healing Feathers by the negated value."
source = "investigation" source = "investigation"
confidence = "high" confidence = "high"
depends_on = ["0x4e11b", "0x5231f", "0x52351", "0xcc9f1"] depends_on = ["0x4e11b", "0x5231f", "0x52351", "0xcc9f1"]
[[global]]
address = "0xbf6fe"
name = "pathfinding_filtered_route_scores"
category = "data-table"
type = "int[][27]"
value_domain = "0 for excluded/unreachable; positive remaining route score"
usage = "SETMVWORK begins by copying pathfinding_remaining_route_steps, then filters occupied entity cells according to faction and the acting entity's usable offensive-action mask/effectiveness. RTN_M providers combine this target-proximity score with a movement-limited MVSEEK grid to select a reachable tile nearest an entity or stage object."
source = "investigation"
confidence = "high"
depends_on = ["0x4e021", "0x522ed", "0xaba96", "0xcc9f4"]
[[global]] [[global]]
address = "0xcc9f1" address = "0xcc9f1"
name = "movement_search_mode" name = "movement_search_mode"
category = "choice-output" category = "choice-output"
type = "int" type = "int"
value_domain = "0..2" value_domain = "0..2"
usage = "Transient MVSEEK mode. Zero keeps the caller-supplied origin and broad search allowance; nonzero modes replace them with the current entity tile and movement+1. Mode 2 additionally masks the doubled-coordinate terrain cells occupied by active entities of another faction before the flood fill. MVSEEK resets the mode to zero on exit." usage = "Transient MVSEEK mode. Zero replaces the caller-supplied origin with the current entity tile and uses movement+1 as the search allowance; nonzero modes retain the caller coordinate and use a broad allowance of 9999. Mode 2 additionally masks the doubled-coordinate terrain cells occupied by active entities of another faction before the flood fill. MVSEEK resets the mode to zero on exit."
source = "investigation" source = "investigation"
confidence = "high" confidence = "high"
depends_on = ["0x4e021", "0x4e11b", "0x522ed", "0x5231f", "0x52351"] depends_on = ["0x4e021", "0x4e11b", "0x522ed", "0x5231f", "0x52351"]
[[global]]
address = "0xcc9f4"
name = "offensive_action_scope_masks"
category = "data-table"
type = "int[10]"
columns = { "0" = "range_0", "1" = "range_1", "2" = "range_2", "3" = "range_3", "4" = "range_4", "5" = "range_5", "6" = "range_6", "7" = "range_7", "8" = "range_8", "9" = "range_9" }
value_domain = "action-availability bitmask: bit 0 normal attack, bits 1..4 equipped active skills"
usage = "CALCSCOPE clears ten encoded-range cells, sets bit 0 over the equipped/default attack's range, and sets bits 1..4 over each usable offensive skill's range. SETMVWORK uses the range-0 mask and paired attack elements when filtering target cells; RTN_M003/006/016/017/018 require its normal-attack bit."
source = "investigation"
confidence = "high"
depends_on = ["0x8d431", "0x8d819", "0xa71de", "0xa730a"]
[[global]] [[global]]
address = "0x152616" address = "0x152616"
name = "current_entity_index" name = "current_entity_index"
@@ -2213,10 +2236,21 @@ name = "stage_object_runtime_state"
category = "data-table" category = "data-table"
type = "int[][50]" type = "int[][50]"
value_domain = "type-dependent small integer state; initial values observed 1..3" value_domain = "type-dependent small integer state; initial values observed 1..3"
usage = "Per-stage, per-object-slot runtime state. FIELD initializes mode-1 objects from STINIT's first tagged payload on a fresh stage and updates capturable-object ownership; DRAWOBJ uses it as the vertical sprite-row index. Other consumers interpret it by object type." usage = "Per-stage, per-object-slot runtime state. FIELD initializes mode-1 objects from STINIT's first tagged payload on a fresh stage and updates capturable-object ownership; DRAWOBJ uses it as the vertical sprite-row index. RTN_M015 treats the state of Magic Pillar types 2..4 as their controlling faction and targets pillars whose value differs from the acting entity's faction."
source = "investigation" source = "investigation"
confidence = "high" confidence = "high"
[[global]]
address = "0xaba64"
name = "stage_object_runtime_flags"
category = "data-table"
type = "int[50]"
value_domain = "runtime stage-object bitfield; bit 1 marks a targetable active slot"
usage = "Per-current-stage object flags. RTN_M010 and RTN_M015 require bit 1 before considering Healing Feathers or Magic Pillars as movement targets; FIELD and object rendering maintain the broader type-dependent bitfield."
source = "investigation"
confidence = "high"
depends_on = ["0xe7389"]
[[global]] [[global]]
address = "0x27b9" address = "0x27b9"
name = "stage_victory_condition_1" name = "stage_victory_condition_1"