Decode CVINIT voice configuration
This commit is contained in:
@@ -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)
|
||||||
|
|
||||||
5049 globals (316 curated, 4733 auto shape-inferred). Source of truth: `vm-map/globals.toml`.
|
5049 globals (319 curated, 4730 auto shape-inferred). Source of truth: `vm-map/globals.toml`.
|
||||||
|
|
||||||
## choice-output
|
## choice-output
|
||||||
|
|
||||||
@@ -69,6 +69,7 @@
|
|||||||
| `0x53643` | entity_movement_routine_progress | high | investigation | Per-runtime-entity movement-routine progress counters. FIELD clears all fifty rows, movement providers increment the current step, and MVRTN compares it with movement_routine_minimum_progress_counts before enabling a step. |
|
| `0x53643` | entity_movement_routine_progress | high | investigation | Per-runtime-entity movement-routine progress counters. FIELD clears all fifty rows, movement providers increment the current step, and MVRTN compares it with movement_routine_minimum_progress_counts before enabling a step. |
|
||||||
| `0x53e13` | entity_carried_item_ids | high | investigation | Two carried/drop-item slots per runtime entity. SETEN initializes slot 0 from the unit's starting equipment item, FIELD fills an empty or matching slot when treasure is collected, and RTN_M009 requires an empty slot or an item-id match before approaching a chest/treasure object. Columns: 0=slot_0, 1=slot_1. |
|
| `0x53e13` | entity_carried_item_ids | high | investigation | Two carried/drop-item slots per runtime entity. SETEN initializes slot 0 from the unit's starting equipment item, FIELD fills an empty or matching slot when treasure is collected, and RTN_M009 requires an empty slot or an item-id match before approaching a chest/treasure object. Columns: 0=slot_0, 1=slot_1. |
|
||||||
| `0x53e77` | entity_carried_item_counts | high | investigation | Quantities for the two per-entity carried/drop-item slots. SETEN seeds a starting item with quantity one; FIELD adds treasure quantities to the matching slot and caps the result at 999. Columns: 0=slot_0, 1=slot_1. |
|
| `0x53e77` | entity_carried_item_counts | high | investigation | Quantities for the two per-entity carried/drop-item slots. SETEN seeds a starting item with quantity one; FIELD adds treasure quantities to the matching slot and caps the result at 999. Columns: 0=slot_0, 1=slot_1. |
|
||||||
|
| `0x56223` | unit_story_speaker_seen_flags | high | investigation | Scene scripts set and persist a unit's cell when drawing that speaker's name. CONFIG reloads the twelve CVINIT-mapped unit cells and enables each named character-voice control only after its speaker has been encountered. |
|
||||||
| `0x5660b` | skill_info_revealed_flags | high | investigation | Persistent skill-information visibility flags. ADDSKILL sets the selected skill, BTL marks every equipped skill when it is observed in combat, and INFOIT suppresses a skill's icon/handler-driven details until this flag is nonzero. This is broader than skill_acquired_flags. |
|
| `0x5660b` | skill_info_revealed_flags | high | investigation | Persistent skill-information visibility flags. ADDSKILL sets the selected skill, BTL marks every equipped skill when it is observed in combat, and INFOIT suppresses a skill's icon/handler-driven details until this flag is nonzero. This is broader than skill_acquired_flags. |
|
||||||
| `0x56738` | entity_battle_routine_random_rolls | high | investigation | Per-runtime-entity battle-step random rolls. FIELD and BTL fill every active entity's twenty cells with random-modulo-100; BTRTN executes a step when the matching roll is below battle_routine_activation_percents. |
|
| `0x56738` | entity_battle_routine_random_rolls | high | investigation | Per-runtime-entity battle-step random rolls. FIELD and BTL fill every active entity's twenty cells with random-modulo-100; BTRTN executes a step when the matching roll is below battle_routine_activation_percents. |
|
||||||
| `0x56b20` | entity_patrol_waypoint_indices | high | investigation | RTN_M011 compares each step's one-based waypoint_ordinal minus one with the current entity's value. Reaching the selected destination advances this value modulo the largest RTN_M011 waypoint ordinal in the routine set. |
|
| `0x56b20` | entity_patrol_waypoint_indices | high | investigation | RTN_M011 compares each step's one-based waypoint_ordinal minus one with the current entity's value. Reaching the selected destination advances this value modulo the largest RTN_M011 waypoint ordinal in the routine set. |
|
||||||
@@ -77,7 +78,9 @@
|
|||||||
| `0x573bb` | unit_class_change_state | high | investigation | Persistent ten-slot class-change state for each playable unit. CALCCC copies the current unit's row to class_change_state_work before invoking the rule scripts and persists the updated row; CCINIT requires the rule's slot to be zero so each promotion is applied once. Columns: 0=promotion_slot_1, 1=promotion_slot_2, 2=promotion_slot_3, 3=promotion_slot_4, 4=promotion_slot_5, 5=promotion_slot_6, 6=promotion_slot_7, 7=promotion_slot_8, 8=promotion_slot_9, 9=promotion_slot_10. |
|
| `0x573bb` | unit_class_change_state | high | investigation | Persistent ten-slot class-change state for each playable unit. CALCCC copies the current unit's row to class_change_state_work before invoking the rule scripts and persists the updated row; CCINIT requires the rule's slot to be zero so each promotion is applied once. Columns: 0=promotion_slot_1, 1=promotion_slot_2, 2=promotion_slot_3, 3=promotion_slot_4, 4=promotion_slot_5, 5=promotion_slot_6, 6=promotion_slot_7, 7=promotion_slot_8, 8=promotion_slot_9, 9=promotion_slot_10. |
|
||||||
| `0x5f0ed` | scene_decision_seen_flags | high | investigation | Persistent seen-state for progression decisions. Numbered scene scripts set the current scjump_decision_out cell after playback and synchronize it through the persistence opcode; INFOVO uses VIINIT's one-based prerequisites to unlock glossary topics. |
|
| `0x5f0ed` | scene_decision_seen_flags | high | investigation | Persistent seen-state for progression decisions. Numbered scene scripts set the current scjump_decision_out cell after playback and synchronize it through the persistence opcode; INFOVO uses VIINIT's one-based prerequisites to unlock glossary topics. |
|
||||||
| `0x624bf` | unit_voice_family_unit_ids | high | investigation | CNINIT's sparse unit-id keyed voice-family normalization map. Story, history, field, and battle voice paths map the current unit variant through this table before selecting the family-level voice-suppression state; 175 of 277 authored rows alias a variant to another representative unit id. |
|
| `0x624bf` | unit_voice_family_unit_ids | high | investigation | CNINIT's sparse unit-id keyed voice-family normalization map. Story, history, field, and battle voice paths map the current unit variant through this table before selecting the family-level voice-suppression state; 175 of 277 authored rows alias a variant to another representative unit id. |
|
||||||
| `0x628a7` | unit_voice_suppression_flag_ids | high | investigation | Second stage of the shared voice-eligibility chain. Story, history, field, and battle paths normalize the current unit through unit_voice_family_unit_ids, index this table by that representative unit id, and suppress voice playback when the selected character_voice_suppressed cell is nonzero. |
|
| `0x628a7` | unit_voice_suppression_flag_ids | high | investigation | CVINIT's unit-to-setting inverse map for the twelve named character voice controls. Story, history, field, and battle paths normalize the current unit through unit_voice_family_unit_ids, index this table by that representative unit id, and suppress voice playback when the selected character_voice_suppressed cell is nonzero. |
|
||||||
|
| `0x62c8f` | character_voice_setting_unit_ids | high | investigation | CVINIT's CONFIG-row join. CONFIG iterates setting slots 1..12, resolves each unit id through unit_story_display_names for its label, and tests the same unit's unit_story_speaker_seen_flags cell before exposing the row. CVINIT also writes the exact inverse mapping to unit_voice_suppression_flag_ids. Columns: 0=system_or_reserved, 1=lily, 2=sylphine, 3=sasune, 4=vidal, 5=estelle, 6=nelly, 7=tiofania, 8=colette, 9=bridget, 10=octavia, 11=fam, 12=deirdre. |
|
||||||
|
| `0x62cad` | character_voice_preview_asset_ids | high | investigation | CVINIT's thirteen voice-setting preview clips. CONFIG indexes this array by setting slot and plays the selected clip; slot 0 is the non-unit system voice, while slots 1..12 join to character_voice_setting_unit_ids. Columns: 0=system_voice, 1=lily, 2=sylphine, 3=sasune, 4=vidal, 5=estelle, 6=nelly, 7=tiofania, 8=colette, 9=bridget, 10=octavia, 11=fam, 12=deirdre. |
|
||||||
| `0x62cd1` | gallery_image_assets | high | investigation | CGINIT's sparse gallery asset rows. CGMODE tests and displays column 0 as the full-size gallery image. SAVE and SELSTAGE scan column 0 for the current image and, when column 1 is populated, load that 112x84 preview instead of capturing the current screen. Columns: 0=gallery_image_asset_id, 1=save_stage_preview_asset_id. |
|
| `0x62cd1` | gallery_image_assets | high | investigation | CGINIT's sparse gallery asset rows. CGMODE tests and displays column 0 as the full-size gallery image. SAVE and SELSTAGE scan column 0 for the current image and, when column 1 is populated, load that 112x84 preview instead of capturing the current screen. Columns: 0=gallery_image_asset_id, 1=save_stage_preview_asset_id. |
|
||||||
| `0x63c71` | gallery_thumbnail_sheet_ids | high | investigation | CGINIT's gallery thumbnail-atlas selector. CGMODE subtracts one, remaps the configured sheet through gallery_thumbnail_sheet_asset_ids, and groups every populated gallery record under that sheet. |
|
| `0x63c71` | gallery_thumbnail_sheet_ids | high | investigation | CGINIT's gallery thumbnail-atlas selector. CGMODE subtracts one, remaps the configured sheet through gallery_thumbnail_sheet_asset_ids, and groups every populated gallery record under that sheet. |
|
||||||
| `0x64441` | gallery_thumbnail_slot_ids | high | investigation | CGINIT's slot within the selected 6x5 thumbnail atlas. CGMODE subtracts one, draws that one of thirty 126x95 cells, and reports the unlocked/total variant counts associated with the slot. |
|
| `0x64441` | gallery_thumbnail_slot_ids | high | investigation | CGINIT's slot within the selected 6x5 thumbnail atlas. CGMODE subtracts one, draws that one of thirty 126x95 cells, and reports the unlocked/total variant counts associated with the slot. |
|
||||||
@@ -285,7 +288,6 @@
|
|||||||
| `0x522bb` | — | low | auto-shape | array |
|
| `0x522bb` | — | low | auto-shape | array |
|
||||||
| `0x53ede` | — | low | auto-shape | array |
|
| `0x53ede` | — | low | auto-shape | array |
|
||||||
| `0x55e3b` | — | low | auto-shape | array |
|
| `0x55e3b` | — | low | auto-shape | array |
|
||||||
| `0x56223` | — | low | auto-shape | array |
|
|
||||||
| `0x56b52` | — | low | auto-shape | array |
|
| `0x56b52` | — | low | auto-shape | array |
|
||||||
| `0x56f6d` | — | low | auto-shape | array |
|
| `0x56f6d` | — | low | auto-shape | array |
|
||||||
| `0x577a3` | — | low | auto-shape | array |
|
| `0x577a3` | — | low | auto-shape | array |
|
||||||
@@ -300,8 +302,6 @@
|
|||||||
| `0x62469` | — | low | auto-shape | array |
|
| `0x62469` | — | low | auto-shape | array |
|
||||||
| `0x6247d` | — | low | auto-shape | array |
|
| `0x6247d` | — | low | auto-shape | array |
|
||||||
| `0x624a3` | — | low | auto-shape | array |
|
| `0x624a3` | — | low | auto-shape | array |
|
||||||
| `0x62c8f` | — | low | auto-shape | array |
|
|
||||||
| `0x62cad` | — | low | auto-shape | array |
|
|
||||||
| `0x653e1` | — | low | auto-shape | array |
|
| `0x653e1` | — | low | auto-shape | array |
|
||||||
| `0x65bb1` | — | low | auto-shape | array |
|
| `0x65bb1` | — | low | auto-shape | array |
|
||||||
| `0x66421` | — | low | auto-shape | array |
|
| `0x66421` | — | low | auto-shape | array |
|
||||||
|
|||||||
@@ -669,16 +669,17 @@ are *not* story flags — the miner over-tags them; they are recategorized `unkn
|
|||||||
|
|
||||||
The v1 map labels *shapes and tables*; the next increments add *meaning*, cheapest first:
|
The v1 map labels *shapes and tables*; the next increments add *meaning*, cheapest first:
|
||||||
|
|
||||||
1. **Continue INIT semantics by evidence density.** ITINIT/SKINIT, EBINIT, STINIT, CCINIT, SCINIT, RTINIT, MAINIT, ILINIT, CGINIT, ALINIT, AFINIT, and CTINIT now have
|
1. **Continue INIT semantics by evidence density.** ITINIT/SKINIT, EBINIT, STINIT, CCINIT, SCINIT, RTINIT, MAINIT, ILINIT, CGINIT, ALINIT, AFINIT, CTINIT, and CVINIT now have
|
||||||
machine-readable investigation surfaces and semantic joins; EBINIT's populated schema is fully named,
|
machine-readable investigation surfaces and semantic joins; EBINIT's populated schema is fully named,
|
||||||
STINIT's joined object/enemy payloads are decoded, and CCINIT's 71 class-change rules expose predicates
|
STINIT's joined object/enemy payloads are decoded, and CCINIT's 71 class-change rules expose predicates
|
||||||
and effects. SCINIT closes the progression decision-to-scene join, and RTINIT's twenty movement/battle
|
and effects. SCINIT closes the progression decision-to-scene join, and RTINIT's twenty movement/battle
|
||||||
banks are structurally decoded with every populated movement-parameter cell classified and all 1,043
|
banks are structurally decoded with every populated movement-parameter cell classified and all 1,043
|
||||||
shipped movement steps joined to provider behavior. ILINIT/RECOVER closes the condition ABI, CGINIT
|
shipped movement steps joined to provider behavior. ILINIT/RECOVER closes the condition ABI, CGINIT
|
||||||
closes the gallery registry, ALINIT closes the 107-recipe alchemy registry with complete ITINIT
|
closes the gallery registry, ALINIT closes the 107-recipe alchemy registry with complete ITINIT
|
||||||
joins, AFINIT closes the signed affinity/tuning/facility tables, and CTINIT closes INPUTNAME's
|
joins, AFINIT closes the signed affinity/tuning/facility tables, CTINIT closes INPUTNAME's
|
||||||
five-page character palette. With RTINIT's used-provider surface closed and
|
five-page character palette, and CVINIT closes CONFIG's thirteen preview clips plus the
|
||||||
ITMES/SKMES/VIMES/EIMES/CIMES/MAMES joined and INFOMES/MES classified, audit CVINIT next;
|
bidirectional character-to-suppression-setting join. With RTINIT's used-provider surface closed and
|
||||||
|
ITMES/SKMES/VIMES/EIMES/CIMES/MAMES joined and INFOMES/MES classified, audit MPINIT next;
|
||||||
never assign one universal meaning to a parameter bank whose meaning varies by provider selector.
|
never assign one universal meaning to a parameter bank whose meaning varies by provider selector.
|
||||||
2. **Label remaining 2D record tables by their readers** — cross-reference which scripts read each
|
2. **Label remaining 2D record tables by their readers** — cross-reference which scripts read each
|
||||||
`rec[sN]` table and infer purpose from context, preserving reserved rows and sparse cells. RECOVER's
|
`rec[sN]` table and infer purpose from context, preserving reserved rows and sparse cells. RECOVER's
|
||||||
|
|||||||
@@ -2925,6 +2925,30 @@ all 350 positions so layout gaps remain explicit rather than collapsing into a f
|
|||||||
Regressions account for every instruction in both scripts, signed affinity values, all tuning and
|
Regressions account for every instruction in both scripts, signed affinity values, all tuning and
|
||||||
facility curves, representative characters and gaps, and raw-to-semantic projection.
|
facility curves, representative characters and gaps, and raw-to-semantic projection.
|
||||||
|
|
||||||
**Next:** audit CVINIT. Its generic output is already small (37 writes, thirteen rows, ten apparent
|
## Data-semantics sidebar: CVINIT character-voice configuration (2026-07-23)
|
||||||
fields), so direct consumer tracing should quickly distinguish a valid sparse registry from the last
|
|
||||||
remaining ownership artifact before moving to MPINIT.
|
CVINIT's generic thirteen-row shape was close but incomplete: it grouped 35 of the script's 37 writes
|
||||||
|
and presented a twelve-entry inverse map as eight unrelated address-derived fields. The dedicated
|
||||||
|
schema accounts for all 38 instructions (37 static writes plus `exit`) as three coordinated arrays:
|
||||||
|
thirteen CONFIG preview-voice assets at `0x62cad`, twelve setting-slot-to-EBINIT-unit ids at
|
||||||
|
`0x62c8f + slot`, and twelve inverse unit-to-setting ids at `0x628a7 + unit`.
|
||||||
|
|
||||||
|
CONFIG proves the presentation contract. Slot 0 is a non-unit system voice preview; slots 1..12 map
|
||||||
|
to Lily, Sylphine, Sasune, Vidal, Estelle, Nelly, Tiofania, Colette, Bridget, Octavia, Fam, and
|
||||||
|
Deirdre. CONFIG resolves those unit ids through the shared story-display-name table, reloads each
|
||||||
|
unit's persisted speaker-seen flag to decide whether the row is available, plays the slot's preview
|
||||||
|
OGG, and edits the matching cell in the thirteen-entry `character_voice_suppressed` settings array.
|
||||||
|
All thirteen preview ids resolve to shipped audio assets.
|
||||||
|
|
||||||
|
The inverse map closes the runtime voice-filter chain rather than duplicating the CONFIG row map.
|
||||||
|
Story, history, field, and battle paths first normalize the active EBINIT unit through CNINIT's
|
||||||
|
voice-family unit table, then map that representative unit through CVINIT's inverse table and test
|
||||||
|
the selected suppression cell. The twelve forward and inverse entries round-trip exactly. Scene
|
||||||
|
scripts independently set and persist the unit-keyed speaker-seen flags when each speaker first
|
||||||
|
appears, explaining CONFIG's unlock gate.
|
||||||
|
|
||||||
|
Regressions protect complete instruction accounting, all asset and EBINIT joins, the system slot,
|
||||||
|
all twelve round trips, speaker-seen addresses, and raw-to-semantic projection.
|
||||||
|
|
||||||
|
**Next:** audit MPINIT's 1,472 structurally regular footer-array records by their direct map readers,
|
||||||
|
grouping rows into consumer-proven families before naming any shallow address-only fields.
|
||||||
|
|||||||
@@ -115,6 +115,12 @@ reserved zero row, and equipment-tuning/alchemy/magic facility progression thres
|
|||||||
INPUTNAME's separate `5 × 70` character palette: 273 authored hiragana, katakana, Latin, numeral, and
|
INPUTNAME's separate `5 × 70` character palette: 273 authored hiragana, katakana, Latin, numeral, and
|
||||||
symbol cells with all reserved gaps retained.
|
symbol cells with all reserved gaps retained.
|
||||||
|
|
||||||
|
CVINIT is CONFIG's character-voice control registry. Its 37 writes form thirteen preview-voice asset
|
||||||
|
slots, a twelve-entry setting-slot-to-EBINIT-unit map, and the exact inverse unit-to-setting map used
|
||||||
|
after CNINIT's voice-family normalization. Slot 0 is the non-unit system voice; slots 1..12 join to
|
||||||
|
Lily and eleven other named characters. CONFIG uses persisted per-unit speaker-seen flags to reveal those
|
||||||
|
twelve rows, plays the corresponding preview clip, and writes the selected suppression setting.
|
||||||
|
|
||||||
RTINIT is a seventh banked shape. Its 3,336 writes populate twenty parallel `1000 × 20` banks: ten
|
RTINIT is a seventh banked shape. Its 3,336 writes populate twenty parallel `1000 × 20` banks: ten
|
||||||
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
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ All opcode knowledge (ABI, semantics, provenance, `depends_on`) is hand-edited *
|
|||||||
| `extract_message_table.py` | Discover repeated global-id dispatch chains in either fallthrough-body (ITMES/SKMES/MAMES) or branch-target-body (VIMES/EIMES/CIMES) form, reconstruct player-facing text and furigana, preserve guard/body offsets, and emit an ID-keyed message table. Title-bearing tables expose `title`/`description`; EIMES exposes its untitled lines as `summary`/`strategy`; CIMES exposes one untitled multiline `biography`; MAMES exposes untitled `description` text. | `extract_message_table.py <MES> [OUTNAME]` | `<MES>.BIN` → `build/data/<OUTNAME>.json` |
|
| `extract_message_table.py` | Discover repeated global-id dispatch chains in either fallthrough-body (ITMES/SKMES/MAMES) or branch-target-body (VIMES/EIMES/CIMES) form, reconstruct player-facing text and furigana, preserve guard/body offsets, and emit an ID-keyed message table. Title-bearing tables expose `title`/`description`; EIMES exposes its untitled lines as `summary`/`strategy`; CIMES exposes one untitled multiline `biography`; MAMES exposes untitled `description` text. | `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. Dedicated name-mode schemas recover VIINIT's pre-title glossary prerequisites and CIINIT's profile name, backing-unit, optional portrait, and reserved placement columns. 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 schemas where proven. Current schemas cover all nineteen used providers, RTN_M001/002/003/004/005/006/007/008/009/010/011/012/013/014/015/017/051/052/061, including progress-only, randomized roaming, object-slot, coordinate, enemy/ally, treasure and Magic Pillar search, Healing Feather, waypoint, faction-terrain, retreat, reachable normal-attack routing, immediate offensive target/action selection, and immediate allied healing. Parameterless behavior schemas publish an empty `parameter_fields` mapping while still joining `provider_behavior`, target selection, action selection, and completion rules. Provider defaults such as M004's unwritten slot 0, M010's zero/HP resource index, and M013's any-foreign-faction filter are projected explicitly and counted separately from populated source cells. Authored cells proven unread by M001/M008 remain under per-step `ignored_movement_parameters` and contribute to top-level `ignored_movement_parameter_count`; they are not silently discarded or assigned invented meanings. Raw provider banks remain intact, and top-level `movement_provider_parameter_schemas` documents the projection. ITINIT, SKINIT, VIINIT, EBINIT, and CIINIT join their matching MES text. 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. Dedicated name-mode schemas recover VIINIT's pre-title glossary prerequisites and CIINIT's profile name, backing-unit, optional portrait, and reserved placement columns. 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 schemas where proven. Current schemas cover all nineteen used providers, RTN_M001/002/003/004/005/006/007/008/009/010/011/012/013/014/015/017/051/052/061, including progress-only, randomized roaming, object-slot, coordinate, enemy/ally, treasure and Magic Pillar search, Healing Feather, waypoint, faction-terrain, retreat, reachable normal-attack routing, immediate offensive target/action selection, and immediate allied healing. Parameterless behavior schemas publish an empty `parameter_fields` mapping while still joining `provider_behavior`, target selection, action selection, and completion rules. Provider defaults such as M004's unwritten slot 0, M010's zero/HP resource index, and M013's any-foreign-faction filter are projected explicitly and counted separately from populated source cells. Authored cells proven unread by M001/M008 remain under per-step `ignored_movement_parameters` and contribute to top-level `ignored_movement_parameter_count`; they are not silently discarded or assigned invented meanings. Raw provider banks remain intact, and top-level `movement_provider_parameter_schemas` documents the projection. ITINIT, SKINIT, VIINIT, EBINIT, and CIINIT join their matching MES text. 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 report message coverage for title/description, summary/strategy, biography, and description-only layouts; 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` searches every supported message field 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 report message coverage for title/description, summary/strategy, biography, and description-only layouts; 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` searches every supported message field 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, RTINIT banked, ILINIT condition-matrix, CNINIT unit-name/voice-family, CGINIT gallery, ALINIT alchemy-recipe, AFINIT affinity/progression, and CTINIT name-entry-palette extraction; RECOVER ABI validation; 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, RTINIT banked, ILINIT condition-matrix, CNINIT unit-name/voice-family, CGINIT gallery, ALINIT alchemy-recipe, AFINIT affinity/progression, CTINIT name-entry-palette, and CVINIT character-voice extraction; RECOVER ABI validation; 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}` |
|
||||||
|
|
||||||
`extract_init.py` also has name-mode specializations for VIINIT's sparse 200-row glossary table,
|
`extract_init.py` also has name-mode specializations for VIINIT's sparse 200-row glossary table,
|
||||||
@@ -92,6 +92,12 @@ copies into the signed affinity matrix, paired item-tuning bonus/cost curves, an
|
|||||||
progression rows. CTINIT emits five reserved 70-cell INPUTNAME pages with 273 authored characters and
|
progression rows. CTINIT emits five reserved 70-cell INPUTNAME pages with 273 authored characters and
|
||||||
every empty slot preserved. Both retain raw global/stride/footer provenance beside their semantic views.
|
every empty slot preserved. Both retain raw global/stride/footer provenance beside their semantic views.
|
||||||
|
|
||||||
|
Numeric-mode CVINIT classifies all 37 writes into CONFIG's thirteen preview-voice assets, twelve
|
||||||
|
setting-slot-to-EBINIT-unit joins, and the exact inverse unit-to-suppression-setting map. Preview ids
|
||||||
|
join to shipped OGG filenames, character slots join to EBINIT names, and the schema records the
|
||||||
|
per-unit persisted speaker-seen cells that gate CONFIG row availability. Every raw coordinate remains
|
||||||
|
beside the joined setting view.
|
||||||
|
|
||||||
## VM
|
## VM
|
||||||
|
|
||||||
| Tool | Purpose | Run | Reads → Writes |
|
| Tool | Purpose | Run | Reads → Writes |
|
||||||
|
|||||||
@@ -53,15 +53,16 @@
|
|||||||
|
|
||||||
- [x] **2.0 — Project structure.** Established `docs/`, `build/{disasm,text,data,scripts-json}/`, `godot/`; game install stays read-only in place. Also relaxed the loader magic check to the `SYS4` family (`SYS4424` patch scripts now parse — was silently skipping 5 scripts).
|
- [x] **2.0 — Project structure.** Established `docs/`, `build/{disasm,text,data,scripts-json}/`, `godot/`; game install stays read-only in place. Also relaxed the loader magic check to the `SYS4` family (`SYS4424` patch scripts now parse — was silently skipping 5 scripts).
|
||||||
- [x] **2.1 — Text corpora.** `tools/extract_phase2.py` → 481/481 scripts: full disassembly (`build/disasm/*.asm`), per-script strings, `build/text/dialogue.jsonl` (**30,057 show-text lines** — the translation corpus), `build/text/strings.jsonl` (38,449 strings tagged by source opcode), `build/manifest.json`.
|
- [x] **2.1 — Text corpora.** `tools/extract_phase2.py` → 481/481 scripts: full disassembly (`build/disasm/*.asm`), per-script strings, `build/text/dialogue.jsonl` (**30,057 show-text lines** — the translation corpus), `build/text/strings.jsonl` (38,449 strings tagged by source opcode), `build/manifest.json`.
|
||||||
- [x] **2.2 — `*INIT` data and rule sources → JSON.** `tools/extract_init.py` auto-detects shape (`name`/`numeric`/`footer`/`mixed`/`rules`/`dispatch`/`banked`) → **SKINIT (131 skills), ITINIT (287 items), EBINIT (277 units), OBINIT (46 object definitions), CIINIT (24 character-information profiles)** [name: sparse one-based name/description/fields, with CIINIT's dedicated profile registry], **CGINIT (851 sparse gallery images)** [numeric: full image, optional save/stage preview, thumbnail sheet/slot, and variant ordinal in a reserved 2,000-row layout], **ALINIT (107 sparse alchemy recipes)** [numeric: output, level/story gates, point cost, and four paired ingredient slots in a reserved 1,000-row layout], **AFINIT (13 authored affinity rows plus tuning/facility curves)** [name/footer specialization], **CTINIT (five 70-cell name-entry pages)** [string-matrix specialization], **MPINIT (1472 map records)** [footer: length-prefixed arrays], **STINIT (74 stages)** [mixed: selector-dispatched strings/scalars/buffer cells/footer arrays], **CCINIT (71 class-change rules over 33 units)** [rules: unit/level/state predicates plus title/cost/stat/skill effects], **SCINIT (1,209 final decision rows)** [dispatch: scene resource plus authored chapter metadata and overwrite history], and **RTINIT (172 routine sets)** [banked: twenty movement/battle step banks, provider joins, and overwrite history]. Validated; see `build/data/README.md`. Raw addresses remain bytecode provenance; confirmed semantics come from `vm-map/globals.toml`.
|
- [x] **2.2 — `*INIT` data and rule sources → JSON.** `tools/extract_init.py` auto-detects shape (`name`/`numeric`/`footer`/`mixed`/`rules`/`dispatch`/`banked`) → **SKINIT (131 skills), ITINIT (287 items), EBINIT (277 units), OBINIT (46 object definitions), CIINIT (24 character-information profiles)** [name: sparse one-based name/description/fields, with CIINIT's dedicated profile registry], **CGINIT (851 sparse gallery images)** [numeric: full image, optional save/stage preview, thumbnail sheet/slot, and variant ordinal in a reserved 2,000-row layout], **ALINIT (107 sparse alchemy recipes)** [numeric: output, level/story gates, point cost, and four paired ingredient slots in a reserved 1,000-row layout], **AFINIT (13 authored affinity rows plus tuning/facility curves)** [name/footer specialization], **CTINIT (five 70-cell name-entry pages)** [string-matrix specialization], **CVINIT (13 character-voice settings)** [numeric: preview assets, slot-to-unit joins, and inverse suppression-setting map], **MPINIT (1472 map records)** [footer: length-prefixed arrays], **STINIT (74 stages)** [mixed: selector-dispatched strings/scalars/buffer cells/footer arrays], **CCINIT (71 class-change rules over 33 units)** [rules: unit/level/state predicates plus title/cost/stat/skill effects], **SCINIT (1,209 final decision rows)** [dispatch: scene resource plus authored chapter metadata and overwrite history], and **RTINIT (172 routine sets)** [banked: twenty movement/battle step banks, provider joins, and overwrite history]. Validated; see `build/data/README.md`. Raw addresses remain bytecode provenance; confirmed semantics come from `vm-map/globals.toml`.
|
||||||
- [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 all 1,043 steps to all 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_M001/002/003/004/005/006/007/008/009/010/011/012/013/014/015/017/051/052/061 add selector-specific progress, randomized roaming, object-slot, coordinate, enemy/ally, treasure and object search, Healing Feather, waypoint, faction-terrain, retreat, normal-attack routing, offensive target/action selection, and immediate allied-healing semantics. All 977 populated movement-parameter cells are classified: 974 semantic inputs and three M001/M008 cells proven unread; thirteen unwritten defaults are projected separately while the generic raw banks remain intact.
|
- [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 all 1,043 steps to all 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_M001/002/003/004/005/006/007/008/009/010/011/012/013/014/015/017/051/052/061 add selector-specific progress, randomized roaming, object-slot, coordinate, enemy/ally, treasure and object search, Healing Feather, waypoint, faction-terrain, retreat, normal-attack routing, offensive target/action selection, and immediate allied-healing semantics. All 977 populated movement-parameter cells are classified: 974 semantic inputs and three M001/M008 cells proven unread; thirteen unwritten defaults are projected separately while the generic raw banks remain intact.
|
||||||
- [x] **2.3d — Extract `ALINIT`'s alchemy recipes.** Numeric specialization recognizes seven recipe-indexed structures and emits 107 sparse recipes from all 914 static writes. ALCHEMY proves the output, minimum level, required/forbidden story gates, point cost, and four paired ingredient-id/quantity slots. Every output and all 286 ingredient references join to ITINIT; raw coordinates remain beside the semantic and nested ingredient views.
|
- [x] **2.3d — Extract `ALINIT`'s alchemy recipes.** Numeric specialization recognizes seven recipe-indexed structures and emits 107 sparse recipes from all 914 static writes. ALCHEMY proves the output, minimum level, required/forbidden story gates, point cost, and four paired ingredient-id/quantity slots. Every output and all 286 ingredient references join to ITINIT; raw coordinates remain beside the semantic and nested ingredient views.
|
||||||
- [x] **2.3e — Extract `AFINIT` affinity/progression data and `CTINIT` name-entry characters.** AFINIT classifies 27 element strings and 54 footer arrays into thirteen signed effectiveness rows, paired tuning bonus/cost curves, and three facility-progress rows. CTINIT preserves 273 authored characters and 77 empty cells across INPUTNAME's five reserved 70-cell pages. Both schemas account for every instruction and retain raw coordinates.
|
- [x] **2.3e — Extract `AFINIT` affinity/progression data and `CTINIT` name-entry characters.** AFINIT classifies 27 element strings and 54 footer arrays into thirteen signed effectiveness rows, paired tuning bonus/cost curves, and three facility-progress rows. CTINIT preserves 273 authored characters and 77 empty cells across INPUTNAME's five reserved 70-cell pages. Both schemas account for every instruction and retain raw coordinates.
|
||||||
|
- [x] **2.3f — Extract `CVINIT` character-voice settings.** Numeric specialization accounts for all 37 static writes as thirteen preview OGG assets, twelve CONFIG-setting-slot-to-EBINIT-unit joins, and the exact inverse unit-to-suppression-setting map. CONFIG proves preview, row-label, persisted speaker-seen unlock, and setting-edit behavior; the shared CNINIT/CVINIT voice chain proves the inverse map.
|
||||||
- [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: RTINIT is closed at 1,043/1,043 movement steps; the RECOVER/ILINIT condition ABI, ALINIT recipes, AFINIT affinity/progression tables, and CTINIT name palette are closed; ITMES/SKMES/VIMES/EIMES/CIMES/MAMES are joined to their definitions; and the non-table INFOMES/MES ABIs are classified. Next, audit CVINIT's small thirteen-row output, then use Frida only for semantics static consumers cannot settle. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids, SCJUMP decision-to-scene dispatch, the shipped RTINIT movement-provider join, and the six completed message joins are resolved.
|
- [ ] **2.5 — Grow the global-var map (future, incremental).** Static first: RTINIT is closed at 1,043/1,043 movement steps; the RECOVER/ILINIT condition ABI, ALINIT recipes, AFINIT affinity/progression tables, CTINIT name palette, and CVINIT character-voice registry are closed; ITMES/SKMES/VIMES/EIMES/CIMES/MAMES are joined to their definitions; and the non-table INFOMES/MES ABIs are classified. Next, audit MPINIT's structurally regular footer rows by their direct readers, then use Frida only for semantics static consumers cannot settle. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids, SCJUMP decision-to-scene dispatch, the shipped RTINIT movement-provider join, and the six completed message joins are resolved.
|
||||||
|
|
||||||
## 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)*
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
ILINIT is a special name-mode matrix: 30 reserved condition ids by five authored
|
ILINIT is a special name-mode matrix: 30 reserved condition ids by five authored
|
||||||
levels, joined to the runtime condition-state ABI and RECOVER policy.
|
levels, joined to the runtime condition-state ABI and RECOVER policy.
|
||||||
|
|
||||||
|
CVINIT is a special numeric-mode registry: thirteen voice-configuration preview
|
||||||
|
slots, twelve slot-to-unit joins, and the matching unit-to-setting inverse map.
|
||||||
|
|
||||||
Records are {id, name?, desc?, fields:{"0x<col_base>": value}} or, for footer tables,
|
Records are {id, name?, desc?, fields:{"0x<col_base>": value}} or, for footer tables,
|
||||||
{id, global_addr, footer_off, values:[...]}. Column addresses are raw engine globals;
|
{id, global_addr, footer_off, values:[...]}. Column addresses are raw engine globals;
|
||||||
confirmed names come from the generated engine global registry while raw keys remain provenance.
|
confirmed names come from the generated engine global registry while raw keys remain provenance.
|
||||||
@@ -626,6 +629,13 @@ NAME_ENTRY_CHARACTER_PALETTE_ROW_NAMES = (
|
|||||||
"symbols",
|
"symbols",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
VOICE_CONFIG_PREVIEW_ASSET_ARRAY_BASE = 0x62CAD
|
||||||
|
VOICE_CONFIG_SLOT_UNIT_ARRAY_BASE = 0x62C8F
|
||||||
|
VOICE_CONFIG_UNIT_SETTING_ARRAY_BASE = 0x628A7
|
||||||
|
VOICE_CONFIG_SLOT_COUNT = 13
|
||||||
|
VOICE_CONFIG_NAMED_SLOT_COUNT = 12
|
||||||
|
VOICE_CONFIG_SPEAKER_SEEN_ARRAY_BASE = 0x56223
|
||||||
|
|
||||||
RECOVER_CURRENT_ENTITY = 0x152616
|
RECOVER_CURRENT_ENTITY = 0x152616
|
||||||
RECOVER_EFFECTIVE_STATS = 0x4E11B
|
RECOVER_EFFECTIVE_STATS = 0x4E11B
|
||||||
RECOVER_CURRENT_RESOURCES = 0x4E085
|
RECOVER_CURRENT_RESOURCES = 0x4E085
|
||||||
@@ -2702,6 +2712,191 @@ def extract_name_entry_palette(scr):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def extract_voice_configuration(scr):
|
||||||
|
"""Extract CVINIT's preview-voice and character-setting registry."""
|
||||||
|
preview_by_slot: dict[int, int] = {}
|
||||||
|
unit_by_slot: dict[int, int] = {}
|
||||||
|
setting_by_unit: dict[int, int] = {}
|
||||||
|
static_write_count = 0
|
||||||
|
classified_write_count = 0
|
||||||
|
exit_count = 0
|
||||||
|
|
||||||
|
for ins in scr.instructions:
|
||||||
|
write = _static_global_write(ins)
|
||||||
|
if write is None:
|
||||||
|
if sys4load.display_label(ins.opcode) == "exit":
|
||||||
|
exit_count += 1
|
||||||
|
continue
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: unclassified instruction at 0x{ins.offset:x}"
|
||||||
|
)
|
||||||
|
|
||||||
|
static_write_count += 1
|
||||||
|
destination, value = write
|
||||||
|
if not isinstance(value, int):
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: non-static voice-config value "
|
||||||
|
f"at 0x{ins.offset:x}"
|
||||||
|
)
|
||||||
|
|
||||||
|
preview_slot = destination - VOICE_CONFIG_PREVIEW_ASSET_ARRAY_BASE
|
||||||
|
if 0 <= preview_slot < VOICE_CONFIG_SLOT_COUNT:
|
||||||
|
_store_unique(preview_by_slot, preview_slot, value, preview_slot)
|
||||||
|
classified_write_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
unit_slot = destination - VOICE_CONFIG_SLOT_UNIT_ARRAY_BASE
|
||||||
|
if 1 <= unit_slot <= VOICE_CONFIG_NAMED_SLOT_COUNT:
|
||||||
|
_store_unique(unit_by_slot, unit_slot, value, unit_slot)
|
||||||
|
classified_write_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
unit_id = destination - VOICE_CONFIG_UNIT_SETTING_ARRAY_BASE
|
||||||
|
if (
|
||||||
|
0 <= unit_id < CHARACTER_NAME_RECORD_SPAN
|
||||||
|
and 1 <= value <= VOICE_CONFIG_NAMED_SLOT_COUNT
|
||||||
|
):
|
||||||
|
_store_unique(setting_by_unit, unit_id, value, unit_id)
|
||||||
|
classified_write_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: unclassified voice-config write "
|
||||||
|
f"0x{destination:x} at 0x{ins.offset:x}"
|
||||||
|
)
|
||||||
|
|
||||||
|
expected_preview_slots = set(range(VOICE_CONFIG_SLOT_COUNT))
|
||||||
|
expected_named_slots = set(range(1, VOICE_CONFIG_NAMED_SLOT_COUNT + 1))
|
||||||
|
if set(preview_by_slot) != expected_preview_slots:
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: preview slots are "
|
||||||
|
f"{sorted(preview_by_slot)}, expected 0..{VOICE_CONFIG_SLOT_COUNT - 1}"
|
||||||
|
)
|
||||||
|
if set(unit_by_slot) != expected_named_slots:
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: named slots are {sorted(unit_by_slot)}, "
|
||||||
|
f"expected 1..{VOICE_CONFIG_NAMED_SLOT_COUNT}"
|
||||||
|
)
|
||||||
|
if set(setting_by_unit.values()) != expected_named_slots:
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: inverse setting ids are "
|
||||||
|
f"{sorted(setting_by_unit.values())}, expected "
|
||||||
|
f"1..{VOICE_CONFIG_NAMED_SLOT_COUNT}"
|
||||||
|
)
|
||||||
|
if len(setting_by_unit) != VOICE_CONFIG_NAMED_SLOT_COUNT:
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: expected {VOICE_CONFIG_NAMED_SLOT_COUNT} "
|
||||||
|
f"unit-to-setting writes, found {len(setting_by_unit)}"
|
||||||
|
)
|
||||||
|
for slot, unit_id in unit_by_slot.items():
|
||||||
|
if setting_by_unit.get(unit_id) != slot:
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: slot {slot} -> unit {unit_id} does not "
|
||||||
|
f"round-trip through the inverse map"
|
||||||
|
)
|
||||||
|
if exit_count != 1:
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: expected one exit, found {exit_count}"
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_records, _ = extract_name(sys4load.load(resolve("EBINIT")))
|
||||||
|
unit_names = {record["id"]: record["name"] for record in unit_records}
|
||||||
|
missing_unit_ids = sorted(set(unit_by_slot.values()) - set(unit_names))
|
||||||
|
if missing_unit_ids:
|
||||||
|
raise ValueError(
|
||||||
|
f"{scr.path.name}: unknown EBINIT unit ids {missing_unit_ids}"
|
||||||
|
)
|
||||||
|
|
||||||
|
asset_names = callscript_names()
|
||||||
|
preview_key = f"0x{VOICE_CONFIG_PREVIEW_ASSET_ARRAY_BASE:x}"
|
||||||
|
unit_key = f"0x{VOICE_CONFIG_SLOT_UNIT_ARRAY_BASE:x}"
|
||||||
|
inverse_base = f"0x{VOICE_CONFIG_UNIT_SETTING_ARRAY_BASE:x}"
|
||||||
|
records = []
|
||||||
|
for slot in range(VOICE_CONFIG_SLOT_COUNT):
|
||||||
|
preview_asset_id = preview_by_slot[slot]
|
||||||
|
record = {
|
||||||
|
"id": slot,
|
||||||
|
"name": (
|
||||||
|
"system_voice" if slot == 0 else unit_names[unit_by_slot[slot]]
|
||||||
|
),
|
||||||
|
"slot_kind": "system" if slot == 0 else "character",
|
||||||
|
"preview_voice_asset_id": preview_asset_id,
|
||||||
|
"preview_voice_asset_name": asset_names.get(preview_asset_id, ""),
|
||||||
|
"fields": {preview_key: preview_asset_id},
|
||||||
|
"array_fields": {},
|
||||||
|
}
|
||||||
|
if slot:
|
||||||
|
unit_id = unit_by_slot[slot]
|
||||||
|
inverse_key = f"{inverse_base}/{unit_id}"
|
||||||
|
record["fields"][unit_key] = unit_id
|
||||||
|
record["array_fields"][inverse_key] = slot
|
||||||
|
record.update({
|
||||||
|
"unit_id": unit_id,
|
||||||
|
"unit_name": unit_names[unit_id],
|
||||||
|
"voice_suppression_setting_id": slot,
|
||||||
|
"speaker_seen_flag_address": (
|
||||||
|
f"0x{VOICE_CONFIG_SPEAKER_SEEN_ARRAY_BASE + unit_id:x}"
|
||||||
|
),
|
||||||
|
})
|
||||||
|
records.append(record)
|
||||||
|
|
||||||
|
return records, {
|
||||||
|
"schema": "character-voice-configuration",
|
||||||
|
"slot_count": VOICE_CONFIG_SLOT_COUNT,
|
||||||
|
"system_slot": 0,
|
||||||
|
"named_character_slots": list(
|
||||||
|
range(1, VOICE_CONFIG_NAMED_SLOT_COUNT + 1)
|
||||||
|
),
|
||||||
|
"preview_asset_array_base": (
|
||||||
|
f"0x{VOICE_CONFIG_PREVIEW_ASSET_ARRAY_BASE:x}"
|
||||||
|
),
|
||||||
|
"slot_unit_array_base": f"0x{VOICE_CONFIG_SLOT_UNIT_ARRAY_BASE:x}",
|
||||||
|
"unit_setting_array_base": (
|
||||||
|
f"0x{VOICE_CONFIG_UNIT_SETTING_ARRAY_BASE:x}"
|
||||||
|
),
|
||||||
|
"speaker_seen_array_base": (
|
||||||
|
f"0x{VOICE_CONFIG_SPEAKER_SEEN_ARRAY_BASE:x}"
|
||||||
|
),
|
||||||
|
"array_layouts": {
|
||||||
|
inverse_base: {"length": CHARACTER_NAME_RECORD_SPAN},
|
||||||
|
},
|
||||||
|
"array_field_columns": [
|
||||||
|
f"{inverse_base}/{unit_id}" for unit_id in sorted(setting_by_unit)
|
||||||
|
],
|
||||||
|
"static_write_count": static_write_count,
|
||||||
|
"classified_static_write_count": classified_write_count,
|
||||||
|
"exit_count": exit_count,
|
||||||
|
"classified_instruction_count": classified_write_count + exit_count,
|
||||||
|
"preview_asset_join_count": sum(
|
||||||
|
bool(record["preview_voice_asset_name"]) for record in records
|
||||||
|
),
|
||||||
|
"unit_join_count": len(unit_by_slot),
|
||||||
|
"round_trip_mapping_count": sum(
|
||||||
|
setting_by_unit[unit_id] == slot
|
||||||
|
for slot, unit_id in unit_by_slot.items()
|
||||||
|
),
|
||||||
|
"consumer_contract": {
|
||||||
|
"script": "CONFIG.BIN",
|
||||||
|
"preview": (
|
||||||
|
"CONFIG indexes the thirteen preview assets by voice-setting "
|
||||||
|
"slot and plays the selected clip before changing that slot's "
|
||||||
|
"suppression flag."
|
||||||
|
),
|
||||||
|
"character_rows": (
|
||||||
|
"CONFIG lists slots 1..12 by resolving their unit ids through "
|
||||||
|
"the shared unit display-name table. A persisted per-unit "
|
||||||
|
"speaker-seen flag controls whether each row is available."
|
||||||
|
),
|
||||||
|
"runtime_voice_filter": (
|
||||||
|
"Story, history, field, and battle paths normalize a unit to "
|
||||||
|
"its voice family, map that representative unit through the "
|
||||||
|
"CVINIT inverse table, and test the selected one of thirteen "
|
||||||
|
"character_voice_suppressed settings."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def gallery_thumbnail_sheet_assets() -> dict[int, int]:
|
def gallery_thumbnail_sheet_assets() -> dict[int, int]:
|
||||||
"""Read CGMODE's enabled thumbnail-sheet assets from INIT2."""
|
"""Read CGMODE's enabled thumbnail-sheet assets from INIT2."""
|
||||||
@@ -3443,6 +3638,10 @@ def write_data_index(data_dir: Path) -> None:
|
|||||||
"pages (hiragana, katakana, Latin, numerals, and symbols), preserving all reserved",
|
"pages (hiragana, katakana, Latin, numerals, and symbols), preserving all reserved",
|
||||||
"empty slots beside the 273 authored characters.",
|
"empty slots beside the 273 authored characters.",
|
||||||
"",
|
"",
|
||||||
|
"CVINIT's dedicated character-voice schema exposes CONFIG's thirteen preview",
|
||||||
|
"clips, twelve slot-to-unit joins, and the matching unit-to-suppression-setting",
|
||||||
|
"inverse map used by story, history, field, and battle voice filters.",
|
||||||
|
"",
|
||||||
"Mixed-mode tables preserve the sparse selector id, branch offset, condition strings,",
|
"Mixed-mode tables preserve the sparse selector id, branch offset, condition strings,",
|
||||||
"scalar fields, cells within preallocated buffers, and length-prefixed footer arrays.",
|
"scalar fields, cells within preallocated buffers, and length-prefixed footer arrays.",
|
||||||
"STINIT additionally joins confirmed parallel buffers into per-slot `object_placements`",
|
"STINIT additionally joins confirmed parallel buffers into per-slot `object_placements`",
|
||||||
@@ -3526,6 +3725,8 @@ def main() -> int:
|
|||||||
extractor = extract_gallery_definitions
|
extractor = extract_gallery_definitions
|
||||||
elif mode == "numeric" and name == "ALINIT":
|
elif mode == "numeric" and name == "ALINIT":
|
||||||
extractor = extract_alchemy_recipes
|
extractor = extract_alchemy_recipes
|
||||||
|
elif mode == "numeric" and name == "CVINIT":
|
||||||
|
extractor = extract_voice_configuration
|
||||||
recs, meta = extractor(scr)
|
recs, meta = extractor(scr)
|
||||||
if mode == "name" and name in MESSAGE_TABLES:
|
if mode == "name" and name in MESSAGE_TABLES:
|
||||||
message_name = MESSAGE_TABLES[name]
|
message_name = MESSAGE_TABLES[name]
|
||||||
|
|||||||
@@ -1272,6 +1272,93 @@ def test_name_entry_palette() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_voice_configuration() -> None:
|
||||||
|
scripts = paths.scripts()
|
||||||
|
script = sys4load.load(scripts["CVINIT.BIN"])
|
||||||
|
check(
|
||||||
|
extract_init.detect_mode(script) == "numeric",
|
||||||
|
"CVINIT remains compatible with numeric-mode auto-detection",
|
||||||
|
)
|
||||||
|
records, meta = extract_init.extract_voice_configuration(script)
|
||||||
|
by_id = {record["id"]: record for record in records}
|
||||||
|
check(
|
||||||
|
len(records) == 13
|
||||||
|
and meta["static_write_count"] == 37
|
||||||
|
and meta["classified_static_write_count"] == 37
|
||||||
|
and meta["classified_instruction_count"] == 38,
|
||||||
|
"CVINIT classifies every preview, forward-map, inverse-map, and exit instruction",
|
||||||
|
)
|
||||||
|
check(
|
||||||
|
[
|
||||||
|
record["preview_voice_asset_name"]
|
||||||
|
for record in records
|
||||||
|
] == [
|
||||||
|
"EUA0065.OGG",
|
||||||
|
"LILA1424.OGG",
|
||||||
|
"SYL0675.OGG",
|
||||||
|
"SAS0328.OGG",
|
||||||
|
"VID0345.OGG",
|
||||||
|
"EST0562.OGG",
|
||||||
|
"NEL0192.OGG",
|
||||||
|
"TIO0209.OGG",
|
||||||
|
"COL0836.OGG",
|
||||||
|
"BRI0687.OGG",
|
||||||
|
"OKT0357.OGG",
|
||||||
|
"FEM0328.OGG",
|
||||||
|
"DEI0501.OGG",
|
||||||
|
],
|
||||||
|
"CVINIT joins all thirteen preview clips to shipped OGG assets",
|
||||||
|
)
|
||||||
|
check(
|
||||||
|
[by_id[slot]["unit_id"] for slot in range(1, 13)]
|
||||||
|
== [2, 5, 6, 7, 12, 14, 13, 10, 8, 9, 15, 11]
|
||||||
|
and meta["unit_join_count"] == 12,
|
||||||
|
"CVINIT joins its twelve named configuration slots to EBINIT units",
|
||||||
|
)
|
||||||
|
check(
|
||||||
|
all(
|
||||||
|
by_id[slot]["array_fields"][
|
||||||
|
f"0x628a7/{by_id[slot]['unit_id']}"
|
||||||
|
] == slot
|
||||||
|
for slot in range(1, 13)
|
||||||
|
)
|
||||||
|
and meta["round_trip_mapping_count"] == 12,
|
||||||
|
"CVINIT's slot-to-unit and unit-to-setting maps round-trip exactly",
|
||||||
|
)
|
||||||
|
check(
|
||||||
|
by_id[0]["slot_kind"] == "system"
|
||||||
|
and "unit_id" not in by_id[0]
|
||||||
|
and by_id[1]["speaker_seen_flag_address"] == "0x56225"
|
||||||
|
and by_id[12]["speaker_seen_flag_address"] == "0x5622e",
|
||||||
|
"CVINIT preserves the non-unit system slot and speaker-seen joins",
|
||||||
|
)
|
||||||
|
|
||||||
|
semantics = extract_init.field_semantics(
|
||||||
|
records, meta["array_layouts"]
|
||||||
|
)
|
||||||
|
check(
|
||||||
|
len(semantics) == 14
|
||||||
|
and semantics["0x62cad"] == "character_voice_preview_asset_ids"
|
||||||
|
and semantics["0x62c8f"] == "character_voice_setting_unit_ids"
|
||||||
|
and semantics["0x628a7/11"]
|
||||||
|
== "unit_voice_suppression_flag_ids.index_11",
|
||||||
|
"CVINIT raw arrays join to their canonical voice-setting semantics",
|
||||||
|
)
|
||||||
|
extract_init.attach_semantic_fields(records, semantics)
|
||||||
|
check(
|
||||||
|
by_id[12]["semantic_fields"][
|
||||||
|
"character_voice_preview_asset_ids"
|
||||||
|
] == 11412
|
||||||
|
and by_id[12]["semantic_fields"][
|
||||||
|
"character_voice_setting_unit_ids"
|
||||||
|
] == 11
|
||||||
|
and by_id[12]["semantic_fields"][
|
||||||
|
"unit_voice_suppression_flag_ids.index_11"
|
||||||
|
] == 12,
|
||||||
|
"CVINIT retains raw coordinates beside its joined semantic view",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_condition_definitions() -> None:
|
def test_condition_definitions() -> None:
|
||||||
scripts = paths.scripts()
|
scripts = paths.scripts()
|
||||||
script = sys4load.load(scripts["ILINIT.BIN"])
|
script = sys4load.load(scripts["ILINIT.BIN"])
|
||||||
@@ -1485,6 +1572,7 @@ if __name__ == "__main__":
|
|||||||
test_alchemy_recipes()
|
test_alchemy_recipes()
|
||||||
test_affinity_definitions()
|
test_affinity_definitions()
|
||||||
test_name_entry_palette()
|
test_name_entry_palette()
|
||||||
|
test_voice_configuration()
|
||||||
test_condition_definitions()
|
test_condition_definitions()
|
||||||
test_field_semantics()
|
test_field_semantics()
|
||||||
if FAILS:
|
if FAILS:
|
||||||
|
|||||||
@@ -1403,11 +1403,46 @@ address = "0x628a7"
|
|||||||
name = "unit_voice_suppression_flag_ids"
|
name = "unit_voice_suppression_flag_ids"
|
||||||
category = "data-table"
|
category = "data-table"
|
||||||
type = "int[1000]"
|
type = "int[1000]"
|
||||||
value_domain = "index into character_voice_suppressed"
|
value_domain = "0 for no mapped setting; 1..12 index character_voice_suppressed"
|
||||||
usage = "Second stage of the shared voice-eligibility chain. Story, history, field, and battle paths normalize the current unit through unit_voice_family_unit_ids, index this table by that representative unit id, and suppress voice playback when the selected character_voice_suppressed cell is nonzero."
|
usage = "CVINIT's unit-to-setting inverse map for the twelve named character voice controls. Story, history, field, and battle paths normalize the current unit through unit_voice_family_unit_ids, index this table by that representative unit id, and suppress voice playback when the selected character_voice_suppressed cell is nonzero."
|
||||||
source = "investigation"
|
source = "investigation"
|
||||||
confidence = "high"
|
confidence = "high"
|
||||||
depends_on = ["0x2e49"]
|
depends_on = ["0x2e49", "0x62c8f"]
|
||||||
|
|
||||||
|
[[global]]
|
||||||
|
address = "0x56223"
|
||||||
|
name = "unit_story_speaker_seen_flags"
|
||||||
|
category = "data-table"
|
||||||
|
type = "int[1000]"
|
||||||
|
value_domain = "per-EBINIT-unit {0,1}; 1 after that unit has appeared as a story speaker"
|
||||||
|
usage = "Scene scripts set and persist a unit's cell when drawing that speaker's name. CONFIG reloads the twelve CVINIT-mapped unit cells and enables each named character-voice control only after its speaker has been encountered."
|
||||||
|
source = "investigation"
|
||||||
|
confidence = "high"
|
||||||
|
depends_on = ["0x315", "0x62c8f"]
|
||||||
|
|
||||||
|
[[global]]
|
||||||
|
address = "0x62c8f"
|
||||||
|
name = "character_voice_setting_unit_ids"
|
||||||
|
category = "data-table"
|
||||||
|
type = "int[13]"
|
||||||
|
columns = { "0" = "system_or_reserved", "1" = "lily", "2" = "sylphine", "3" = "sasune", "4" = "vidal", "5" = "estelle", "6" = "nelly", "7" = "tiofania", "8" = "colette", "9" = "bridget", "10" = "octavia", "11" = "fam", "12" = "deirdre" }
|
||||||
|
value_domain = "slot 0 unwritten; slots 1..12 contain EBINIT unit ids"
|
||||||
|
usage = "CVINIT's CONFIG-row join. CONFIG iterates setting slots 1..12, resolves each unit id through unit_story_display_names for its label, and tests the same unit's unit_story_speaker_seen_flags cell before exposing the row. CVINIT also writes the exact inverse mapping to unit_voice_suppression_flag_ids."
|
||||||
|
source = "investigation"
|
||||||
|
confidence = "high"
|
||||||
|
depends_on = ["0x315", "0x56223", "0x628a7"]
|
||||||
|
|
||||||
|
[[global]]
|
||||||
|
address = "0x62cad"
|
||||||
|
name = "character_voice_preview_asset_ids"
|
||||||
|
category = "data-table"
|
||||||
|
type = "int[13]"
|
||||||
|
columns = { "0" = "system_voice", "1" = "lily", "2" = "sylphine", "3" = "sasune", "4" = "vidal", "5" = "estelle", "6" = "nelly", "7" = "tiofania", "8" = "colette", "9" = "bridget", "10" = "octavia", "11" = "fam", "12" = "deirdre" }
|
||||||
|
value_domain = "packed OGG asset resource id"
|
||||||
|
usage = "CVINIT's thirteen voice-setting preview clips. CONFIG indexes this array by setting slot and plays the selected clip; slot 0 is the non-unit system voice, while slots 1..12 join to character_voice_setting_unit_ids."
|
||||||
|
source = "investigation"
|
||||||
|
confidence = "high"
|
||||||
|
depends_on = ["0x2e49", "0x62c8f"]
|
||||||
|
|
||||||
[[global]]
|
[[global]]
|
||||||
address = "0x62cd1"
|
address = "0x62cd1"
|
||||||
|
|||||||
Reference in New Issue
Block a user