From 93d9f58758694b9429952fc30d3a4ef47c2c4816 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Tue, 28 Jul 2026 12:25:24 -0400 Subject: [PATCH] Record remaining engine RE findings --- docs/global-reference.md | 8 ++++---- docs/name-resolution.md | 6 +++++- docs/scjump-progression.md | 5 +++-- docs/script-inventory.md | 23 +++++++++++++++++++++++ docs/tools-reference.md | 5 ++++- vm-map/globals.toml | 28 ++++++++++++++++++++-------- 6 files changed, 59 insertions(+), 16 deletions(-) diff --git a/docs/global-reference.md b/docs/global-reference.md index ae37140..d45ce9f 100644 --- a/docs/global-reference.md +++ b/docs/global-reference.md @@ -1,7 +1,7 @@ # Global Variable Reference (generated) -4278 globals (445 curated, 3833 auto shape-inferred). Source of truth: `vm-map/globals.toml`. +4278 globals (446 curated, 3832 auto shape-inferred). Source of truth: `vm-map/globals.toml`. ## choice-output @@ -34,7 +34,6 @@ | `0x6727` | training_action_execution_counts | high | investigation | Per-action completed execution counts. TRAIN uses the prior count as the column in training_action_event_story_flag_ids, increments the selected cell, and treats a zero next event as the cap; GAMESTART restores each count and replays its completed event flags. | | `0x204f4` | current_stage_turn | high | investigation | FIELD initializes this to 1, increments it after end-of-turn processing, compares it with STINIT's stage turn limit and timed object schedules, and displays it through DRAWCHP. Card generation divides it by each CDINIT growth interval to increase that card's weighted-selection share. | | `0x204f8` | party_reference_level | high | investigation | FIELD's enemy auto-level reference. It averages all eligible party units when at most five exist, otherwise the five highest-level units. SETEN raises scalable enemies above unit_starting_level by the positive gap divided by the selected auto-level divisor before applying stage level clamps. Difficulty separately adds -5/0/+5 stat-growth iterations and does not change this stored runtime level. | -| `0x2052e` | scjump_progress_b | med | inference | Second SCJUMP switch input (1223 comparison reads) — progression counter/position. INFERENCE from SCJUMP usage. | | `0x20530` | current_spirit | high | investigation | Current 精気 (spirit/essence) resource. TRAIN rejects a selected action when adding its negative TRINIT spirit delta would fall below zero, deducts the cost on execution, and passes the updated value to DRAWCHP. Field and scene reward paths update the same resource and clamp it to maximum_spirit. | | `0x20534` | maximum_spirit | high | investigation | Maximum 精気 capacity paired with current_spirit. TRAIN clamps the post-cost current value against it, DRAWCHP renders the current/maximum gauge, and field/scene reward paths raise or restore the same capacity. | | `0x4dfbb` | stage_card_spendable_point_bonus | high | investigation | FIELD clears this on stage entry and adds CDINIT2 type-3 card bonuses. STAGECLEAR adds the accumulated amount to its computed stage award before increasing shared_spendable_points. | @@ -128,7 +127,7 @@ | `0x716de` | unit_icon_id | high | investigation | EBINIT icon selector populated for all 277 units. READICON returns it for unit ids; CHMENU, DRAWCHP, EXILE, SALLY, and SUMMON convert the value into icon-atlas page and cell coordinates. | | `0x71ac6` | unit_species_category | med | investigation | Broad EBINIT species/allegiance category for 198 units: value 1 covers humans and allied heroines, 2 covers demons including Emilio and Lily as well as many demonic monsters, and 3 covers other monsters, dragons, and elementals. CHMENU uses it for equipment restrictions, CALCDMG for category-sensitive effects, and INFOCH/INFOEN for display. | | `0x71eae` | unit_sex_category | high | investigation | EBINIT sex category for 251 units. Named character records establish the three values; CHMENU tests it against item_sex_restriction_mask, while INFOCH and INFOEN use the same category in unit presentation. | -| `0x72296` | unit_boss_class | med | investigation | Nonzero for 112 bosses, special encounters, summoned adds, and map hazards. CALCDMG grants every nonzero class the boss adjustment, CALCILL grants condition immunity, and FIELD/MAGIC/USEMAGIC exclude nonzero classes from ordinary-unit rules. On stages whose clear rule is defeat-boss targets, FIELD blocks victory only while a positive-class enemy remains; negative peers keep boss treatment but are ignored, as with Octavia beside Bridget, Deirdre's shadows, EX-8 adds beside Tiamat, and the final boss's three organs. Classes 1..3 are otherwise authoring categories with no distinct shipped-script branch. Either sign of class 4 selects the final-boss battle BGM and special tactical-map presentation. | +| `0x72296` | unit_boss_class | med | investigation | Nonzero for 112 bosses, special encounters, summoned adds, and map hazards. CALCDMG grants every nonzero class the boss adjustment, CALCILL grants condition immunity, and FIELD/MAGIC/USEMAGIC exclude nonzero classes from ordinary-unit rules. FIELD draws the normal faction-colored unit banner for classes 0 and ±1..±3, then adds the separate yellow boss marker below it when this value is nonzero; class ±4 suppresses both standard markers for its special presentation. On stages whose clear rule is defeat-boss targets, FIELD blocks victory only while a positive-class enemy remains; negative peers keep boss treatment but are ignored, as with Octavia beside Bridget, Deirdre's shadows, EX-8 adds beside Tiamat, and the final boss's three organs. Classes 1..3 are otherwise authoring categories with no distinct shipped-script branch. Either sign of class 4 selects the final-boss battle BGM and special tactical-map presentation. | | `0x7267e` | unit_canonical_id | high | investigation | Maps 106 alternate, boss, brainwashed, EX, and enemy variants back to their canonical character or recruitable archetype. For example all Estelle bosses map to 12, brainwashed Sylphine maps to 5, and ordinary/EX orcs map to recruitable orc 52. Setup, menus, inventory, dismissal, and combat normalize through this id. | | `0x72a66` | unit_capturable | high | investigation | Capture eligibility for 74 ordinary enemy archetypes. SELACT and FIELD allow the capture skill only when this flag is nonzero and the acting unit's capture power meets the target-level check; successful resolution displays the explicit 'Captured the enemy' message. | | `0x72e4e` | unit_roster_state_flag_base_index | high | investigation | Persistent roster-state block for seven recruitable heroines. SALLY's first three unit actions mark offsets 1, 2, and 0 respectively; UNITECH marks the offset selected by its recruitment mode; DELCH, REMOVECH, SALLY, and EXILE mark offset 3 when the unit is removed or released. The values are relative indices into the shared flag bank, not absolute global addresses. | @@ -303,6 +302,7 @@ | `0x15261f` | battle_triggered_passive_skill_flags | high | investigation | Per-exchange passive-skill activation matrix. CALCDMG clears both 300-cell side rows, considers the four equipped skills on each battle entity, retains category-4 passives allowed for that actor/target role, rolls skill_proc_chance_percent, and applies species, boss, movement-skill, action-category, and mutual-exclusion filters. BTL consumes the surviving flags to draw triggered-passive icons, play each passive's battle animation, and execute Roar, Counter, Reflect, Absorb, Pierce, Shield, Parry, and Revive behavior. | | `0x152877` | battle_entity_indices | high | investigation | The two runtime entity rows participating in BTL. battle_actor_side_index and battle_target_side_index select these cells before BTL and CALCDMG access HP, unit definitions, skills, animation state, and voice banks. Columns: 0=side_0, 1=side_1. | | `0x152879` | battle_selected_skill_ids | high | investigation | Selected skill for each battle side. BTL displays a positive entry through the skill-name table and selects skill-use voice columns; CALCDMG uses the same id for skill parameters. A zero entry follows the equipped/default ordinary-attack path. Columns: 0=side_0, 1=side_1. | +| `0x152883` | battle_critical_chance_percent | high | investigation | Final per-side critical chance for the current exchange. CALCBTPARAM starts with the side's effective critical-chance stat plus its effective luck minus the opposing side's effective luck, applies selected-skill and applicable target-tile terrain critical/luck deltas through the same channels, and clamps the result to 0..100. Equipment has already entered through entity_effective_stats: CT affects only its owner's outgoing critical chance, whereas luck both raises outgoing chance and lowers the opponent's. After a successful hit, CALCDMG rolls random-modulo-100 against this value; success sets battle_hit_result to 2 and doubles the signed HP delta. Columns: 0=side_0, 1=side_1. | | `0x15288e` | battle_animation_effect_ids | high | investigation | BTANINIT2's sparse battle-animation composition table. BTANINIT expands the selected row into six runtime effect work slots. BTL anchors requested effects in slots 0 and 1 to the actor and slots 2 through 5 to the target; shipped data never populates slot 4. Columns: 0=effect_slot_0, 1=effect_slot_1, 2=effect_slot_2, 3=effect_slot_3, 4=reserved_effect_slot_4, 5=effect_slot_5. | | `0x153ffe` | battle_animation_effect_start_delays_ms | high | investigation | Per-effect start delays paired with battle_animation_effect_ids. BTL passes each populated value to movie/sprite animation setup and adds it to the effect-local sound and hit-pulse offsets. Shipped data authors delays only for slots 2, 3, and 5. Columns: 0=effect_slot_0, 1=effect_slot_1, 2=effect_slot_2, 3=effect_slot_3, 4=reserved_effect_slot_4, 5=effect_slot_5. | | `0x15576e` | battle_animation_duration_ms | high | investigation | Overall timing boundary for one BTANINIT2 animation row. BTL uses it to schedule delayed battle voice and to begin the 500 ms HP interpolation after the main animation. The passive/defeat auxiliary rows 801..809 intentionally omit it. | @@ -422,7 +422,6 @@ | `0x15287d` | — | low | auto-shape | array | | `0x15287f` | — | low | auto-shape | array | | `0x152881` | — | low | auto-shape | array | -| `0x152883` | — | low | auto-shape | array | | `0x152885` | — | low | auto-shape | array | | `0x152887` | — | low | auto-shape | array | | `0x152889` | — | low | auto-shape | array | @@ -438,6 +437,7 @@ |---|---|---|---|---| | `0x32f1` | difficulty_index | high | investigation | GAMESTART's three-way difficulty selection. SETEN uses the zero-based index to select difficulty stat adjustments; FIELD indexes three-column stage-enemy arrays with it, and SETOBJ tests it against each object's difficulty mask. | | `0x6718` | selected_party_slot | high | investigation | Current/selected slot in the 100-entry party-unit arrays. UNITECH chooses a free slot here before populating it; CHMENU replaces it with the selected sorted roster slot, then uses it to index party_slot_flags, party_slot_character_id, and companion per-slot tables. A natural New Game enters SC0000 with slot 2 selected. | +| `0x2052e` | current_faction_id | high | investigation | Active tactical faction/side. FIELD initializes it during stage entry, assigns 1 for the player phase, advances (value + 1) modulo 4 between phases, filters runtime entities and capturable objects by faction equality, and uses it as the bit index into tile_faction_traversal_masks. SCJUMP reads the same live stage context; this is not a story-progress counter. | | `0x53edd` | selected_training_action_id | high | investigation | TRAIN's selected action row. It indexes all TRINIT eligibility, effect, text, award, and event arrays during detail rendering and execution. | | `0x62424` | adv_gfx_resource_id | high | investigation | Transient ADV graphics-load input. Scene scripts set this immediately before their common layer loader, which passes it to set-texture together with adv_gfx_surface_slot_work. | | `0x62450` | adv_gfx_layer_index | high | investigation | Current ADV graphics-layer row. All immediate assignments across the corpus are 0..7; common scene loaders use it to index adv_gfx_object_handles, per-layer geometry arrays, and adv_layer_surface_slots. | diff --git a/docs/name-resolution.md b/docs/name-resolution.md index ac662a9..3ed2d64 100644 --- a/docs/name-resolution.md +++ b/docs/name-resolution.md @@ -194,7 +194,11 @@ same drop-item ids. Third, explicit menu messages and state updates identify cap listing, summon unlock indices/knowledge thresholds/point costs, essence yield, automatic enemy level scaling, and the large-battle-sprite layout flag. The signed `unit_boss_class` remains medium-confidence as an authoring vocabulary, but its runtime split is now concrete. Every nonzero value receives the shared -boss damage adjustment, condition immunity, targeting exclusions, and boss battle treatment. FIELD's +boss damage adjustment, condition immunity, targeting exclusions, and boss battle treatment. Its yellow +map flag is also a separate boss marker rather than a fifth faction: FIELD draws the ordinary banner from +the runtime faction id, then adds the yellow badge for a nonzero class ±1..±3. Class ±4 suppresses both +standard markers for the final boss's special presentation. DRAWMINIMAP continues to color its 3×3 unit +dot solely from the four-valued runtime faction id. FIELD's `stage_clear_rule == -2` path scans only living enemy units whose class is positive, so a positive class is a required defeat-boss target while the matching negative class is a boss-treated add, decoy, or hazard that does not delay victory. STINIT confirms the distinction in the same encounters: Bridget is positive diff --git a/docs/scjump-progression.md b/docs/scjump-progression.md index e054dc0..a16a6bc 100644 --- a/docs/scjump-progression.md +++ b/docs/scjump-progression.md @@ -7,8 +7,9 @@ readable, VM-verified table. ## Mechanism - **Top switch** on `0x3234` (`chapter_mode`, 1..9) dispatches to a per-chapter block (`1→0x81, 2→0x9f, 3→0x1ded, 4→0x1e6d, 5→0x54c1, 6→0x93c4, 7→0x1e868, 8→0x2aa42, 9→0x2b8a3`). -- Each chapter block is an **acyclic tree** (0 back-edges) of comparisons on progress counters - (`scjump_progress_a/b/d` = `0x4dfbc`/`0x2052e`/`0xe6c5d`), `battle_outcome_flags` +- Each chapter block is an **acyclic tree** (0 back-edges) of comparisons on stage/context inputs + (`scjump_progress_a`, `current_faction_id`, and `scjump_progress_d` = + `0x4dfbc`/`0x2052e`/`0xe6c5d`; the first and third names remain provisional), `battle_outcome_flags` (`0x152618`; low bits target-defeated/actor-defeated/both-survived), story flags, **and a native computed value** (see below). - At each of **1755 decision sites** it writes `0x0 = 1` (decision-valid) and diff --git a/docs/script-inventory.md b/docs/script-inventory.md index b91eb2d..8de7576 100644 --- a/docs/script-inventory.md +++ b/docs/script-inventory.md @@ -131,6 +131,29 @@ The dedicated view joins 66 named stage definitions to 53 unique rectangles, pre groups and 47 nonzero border-context cells, and resolves terrain ids through LAINIT's name, texture-slot, area-fill, and layout-class columns. +Conceptually, MPINIT is the game's master dungeon terrain plan. A mapped STINIT2 row does not identify a +standalone map resource; it selects an inclusive tile-coordinate rectangle from that plan through +min/max X/Y bounds (equivalently, an origin plus derived width and height). FIELD makes the active +rectangle mutable, while STINIT overlays the stage-specific mission content: objects, enemies, +reinforcements, conditions, BGM, and texture overrides. The left minimap deliberately preserves the +larger-floor illusion. DRAWMINIMAP reads the mutable current-stage grid inside the active rectangle but +reads the immutable MPINIT atlas outside it, so nearby authored terrain can remain visible without +bringing in another stage's enemies or interactable objects. The STINIT2 minimap-origin field chooses +the vertically packed atlas band shown for that stage; MPINIT itself contains terrain cells, not stage +adjacency metadata. + +Factions are a fixed four-side tactical convention rather than INIT-defined faction records: +0=gray, 1=red/player, 2=blue, and 3=green. STINIT assigns a side id to each enemy spawn and initial +ownership to faction-bearing objects; FIELD assigns deployed party entities to side 1 and copies enemy +spawn ids into their runtime entity records. The same ids select the active turn, compare allied versus +foreign entities, represent capturable-object ownership, and index faction bits in terrain traversal +masks. Generic tactical logic treats equal ids as allied and unequal ids as foreign—there is no +discovered alliance/diplomacy matrix—so gray is a fourth independent side, not an intrinsically +non-hostile neutral category. A unit definition is not faction-bound: the same EBINIT unit can be +instantiated on different sides by different STINIT entries. The separate yellow map flag is a boss +badge selected by EBINIT's `unit_boss_class`, not a fifth faction or object-owner value; minimap unit +dots still use only the four faction ids. + LAINIT defines the twenty shipped terrain ids inside a reserved thirty-row registry. Its sparse strings provide seventeen names and five effect summaries; its numeric surface provides texture-slot, area-fill, layout-class, required-skill, and ten-column combat-stat data. CALCBTPARAM diff --git a/docs/tools-reference.md b/docs/tools-reference.md index aae82c7..1d4652d 100644 --- a/docs/tools-reference.md +++ b/docs/tools-reference.md @@ -208,7 +208,10 @@ In a live Godot run, **F6** writes an observe-only stall snapshot under `SCRIPT@offset · stall snapshot ` to the clipboard. The JSON contains the current call stack, a bounded 128-instruction ring, VM/host wait flags, surface/movie completion state, decoder state, and the exact finite graphics channels capable of holding an op-`0x21c` presentation wait. Press it while the apparent stall is still -active; unlike `--timeline-log`, it does not require a special launch or emit a continuous per-op stream. +active; unlike `--timeline-log`, it does not require a special launch or emit a continuous per-op stream. Active +and pending movie records include `first_frame_source_pts_ms`; the ordinary `movie first frame` console line prints +the same source PTS alongside the render frame, which distinguishes encoded stream lead-in from decode/presentation +latency. ## Native FFmpeg movie shim (Windows x64) diff --git a/vm-map/globals.toml b/vm-map/globals.toml index 2649d40..bef7eac 100644 --- a/vm-map/globals.toml +++ b/vm-map/globals.toml @@ -699,7 +699,7 @@ name = "unit_boss_class" category = "data-table" type = "int[1000]" value_domain = "0=ordinary; signed boss class ±1..±4: 1=named/story character, 2=monster/special encounter, 3=demon-lord class, 4=final boss; positive values are defeat-boss victory targets and negative values are exempt" -usage = "Nonzero for 112 bosses, special encounters, summoned adds, and map hazards. CALCDMG grants every nonzero class the boss adjustment, CALCILL grants condition immunity, and FIELD/MAGIC/USEMAGIC exclude nonzero classes from ordinary-unit rules. On stages whose clear rule is defeat-boss targets, FIELD blocks victory only while a positive-class enemy remains; negative peers keep boss treatment but are ignored, as with Octavia beside Bridget, Deirdre's shadows, EX-8 adds beside Tiamat, and the final boss's three organs. Classes 1..3 are otherwise authoring categories with no distinct shipped-script branch. Either sign of class 4 selects the final-boss battle BGM and special tactical-map presentation." +usage = "Nonzero for 112 bosses, special encounters, summoned adds, and map hazards. CALCDMG grants every nonzero class the boss adjustment, CALCILL grants condition immunity, and FIELD/MAGIC/USEMAGIC exclude nonzero classes from ordinary-unit rules. FIELD draws the normal faction-colored unit banner for classes 0 and ±1..±3, then adds the separate yellow boss marker below it when this value is nonzero; class ±4 suppresses both standard markers for its special presentation. On stages whose clear rule is defeat-boss targets, FIELD blocks victory only while a positive-class enemy remains; negative peers keep boss treatment but are ignored, as with Octavia beside Bridget, Deirdre's shadows, EX-8 adds beside Tiamat, and the final boss's three organs. Classes 1..3 are otherwise authoring categories with no distinct shipped-script branch. Either sign of class 4 selects the final-boss battle BGM and special tactical-map presentation." source = "investigation" confidence = "med" @@ -2212,6 +2212,18 @@ usage = "Selected skill for each battle side. BTL displays a positive entry thro source = "investigation" confidence = "high" +[[global]] +address = "0x152883" +name = "battle_critical_chance_percent" +category = "data-table" +type = "int[2]" +columns = { "0" = "side_0", "1" = "side_1" } +value_domain = "0..100 percentage points" +usage = "Final per-side critical chance for the current exchange. CALCBTPARAM starts with the side's effective critical-chance stat plus its effective luck minus the opposing side's effective luck, applies selected-skill and applicable target-tile terrain critical/luck deltas through the same channels, and clamps the result to 0..100. Equipment has already entered through entity_effective_stats: CT affects only its owner's outgoing critical chance, whereas luck both raises outgoing chance and lowers the opponent's. After a successful hit, CALCDMG rolls random-modulo-100 against this value; success sets battle_hit_result to 2 and doubles the signed HP delta." +source = "investigation" +confidence = "high" +depends_on = ["0x4e11b", "0xa99b6", "0xe6afe", "0x15261c", "0x152877", "0x152879"] + [[global]] address = "0x26b4" name = "class_change_title_output" @@ -3121,14 +3133,14 @@ depends_on = [] [[global]] address = "0x2052e" -name = "scjump_progress_b" -category = "counter" +name = "current_faction_id" +category = "index-pointer" type = "int" -value_domain = "progress index" -usage = "Second SCJUMP switch input (1223 comparison reads) — progression counter/position. INFERENCE from SCJUMP usage." -source = "inference" -confidence = "med" -depends_on = [] +value_domain = "{0,1,2,3}; 0 = gray, 1 = red/player, 2 = blue, 3 = green" +usage = "Active tactical faction/side. FIELD initializes it during stage entry, assigns 1 for the player phase, advances (value + 1) modulo 4 between phases, filters runtime entities and capturable objects by faction equality, and uses it as the bit index into tile_faction_traversal_masks. SCJUMP reads the same live stage context; this is not a story-progress counter." +source = "investigation" +confidence = "high" +depends_on = ["0x522ed", "0x141a4", "0x20543"] [[global]] address = "0x152618"