Document ADV history and remaining button paths
This commit is contained in:
@@ -104,9 +104,9 @@ type = "void*"
|
||||
note = "0x78-byte context-record array base (coroutine/script contexts)"
|
||||
[[field]]
|
||||
offset = 0x53d64
|
||||
name = "gfx_obj_record_array"
|
||||
type = "void*"
|
||||
note = "gfx object-record array (field[0]=0xffffffff free; cmd-type at rec+0x24)"
|
||||
name = "frame_script_resource_id"
|
||||
type = "uint"
|
||||
note = "raw packed SYS4/AAI resource id for this 0x78-byte script frame; persisted ReadTextDB script key"
|
||||
[[field]]
|
||||
offset = 0x53d88
|
||||
name = "cmd_type_table"
|
||||
|
||||
@@ -994,16 +994,16 @@ abi_source = "kelebek+decode-validated"
|
||||
[opcode.semantics]
|
||||
name = "label-def"
|
||||
category = "structural"
|
||||
summary = "1 imm; count == T1 table size -> the label/anchor T1 indexes. v1 no-op; revisit if menu/callback dispatch looks up by id"
|
||||
noop_headless = true
|
||||
summary = "(anchor_id) - define a T1 label/anchor, snapshot the current code position, and commit pending read-message records to the shared ReadTextDB."
|
||||
noop_headless = false
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Corpus: count exactly matches each script's T1 table and T1 entries target these records, preserving the structural label role. Ghidra /v2: op_0x71_handler@0x41e540 records (frame_pc-frame_codebase)/4 at the current frame's +0x20 field, snapshots text state, and calls read_text_db_commit_pending@0x46ae20. That drains queued {script_resource_id,message_index,message_count} records into ReadTextDB. script_frame_load_resource@0x40e980 stores the raw packed SYS4/AAI resource id at frame+0x04 (EngineCtx+0x53d64), establishing the persistence key. Therefore 0x71 is not a pure runtime no-op when persistent read history is modeled."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "label/anchor id"
|
||||
observed_types = ["imm", "l-int"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -1020,7 +1020,7 @@ noop_headless = false
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = "Ghidra /v2: op_0x72_handler@0x41e690 fetches operand 1 and calls FUN_00453120(text_manager, layout_slot, -1, &state), then sets the input-wait run-state flags. FUN_00453120 resolves layout slot 0 as current and consumes the indicator descriptor at layout+0x3c configured by op 0x73. SYSTEM4 layout 1 uses SO000's bat strip; the click that completes show-text is consumed before this opcode is reached. The handler also checks ctx+0x55104 (Auto enabled): when ctx+0x6dbe4 has no pending voice it arms the timer with message:AutoMessageTime1, substituting 100 ms for configuration value zero. adv_input_service_poll@0x411230 waits for an active voice to finish and then arms AutoMessageTime0, likewise with a 100-ms zero fallback."
|
||||
evidence = "Ghidra /v2: op_0x72_handler@0x41e690 fetches operand 1 and calls FUN_00453120(text_manager, layout_slot, -1, &state), then sets the input-wait run-state flags. FUN_00453120 resolves layout slot 0 as current and consumes the indicator descriptor at layout+0x3c configured by op 0x73. SYSTEM4 layout 1 uses SO000's bat strip; the click that completes show-text is consumed before this opcode is reached. The handler also checks ctx+0x55104 (Auto enabled): when ctx+0x6dbe4 has no pending voice it arms the timer with message:AutoMessageTime1, substituting 100 ms for configuration value zero. adv_input_service_poll@0x411230 waits for an active voice to finish and then arms AutoMessageTime0, likewise with a 100-ms zero fallback. The same click/Auto completion path calls read_text_db_queue_message@0x469340 with the current script id, resolved per-script message index, and message count; an already-skipped wait queues it directly in op 0x72. Op 0x71 later commits the pending records."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
@@ -1346,18 +1346,18 @@ argc = 1
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u0041B210"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "set-cursor-resource"
|
||||
category = "input"
|
||||
summary = "(resource_id) - load an indexed cursor asset and install it as the active custom cursor."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x86_set_cursor_resource@0x41f0a0 opens operand 1 through asset_open_indexed_entry, extracts the asset payload, passes it to the cursor installer at 0x485ce0, releases the asset, and refreshes the OS cursor when the window is active. HIDEWIN.BIN selects resources 0x3318..0x331f according to the pointer's screen-edge region."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "cursor resource id"
|
||||
observed_types = ["imm"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -1367,14 +1367,14 @@ argc = 0
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u00414D10"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "clear-cursor-resource"
|
||||
category = "input"
|
||||
summary = "Clear the active custom cursor and refresh the OS cursor when the game window is active."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x87_clear_cursor_resource@0x416400 calls the cursor clear/release helper at 0x4856b0 and then the same active-window cursor refresh used by op 0x86. HIDEWIN.BIN calls it when leaving an edge region and on exit."
|
||||
|
||||
[[opcode]]
|
||||
op = 0x88
|
||||
@@ -2064,23 +2064,23 @@ argc = 2
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "mouse_callback"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "register-mouse-callback"
|
||||
category = "input"
|
||||
summary = "(poll_interval_ms)(target_pc) - register a timed per-frame mouse callback in the current script."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "med"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0xcc_register_mouse_callback@0x420f70 stores operand 2 as the callback PC and the current frame_script_resource_id as its owner, then arms operand 1 as the poll interval. HIDEWIN.BIN and HISTORY.BIN both register a 0x10-ms callback. Op 0xcd performs the timed dispatch."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "poll interval (ms)"
|
||||
observed_types = ["imm"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 2
|
||||
role = ""
|
||||
role = "callback code target"
|
||||
observed_types = ["imm"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -2090,14 +2090,14 @@ argc = 0
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "get-input-type"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "dispatch-mouse-callback"
|
||||
category = "input"
|
||||
summary = "Dispatch the registered mouse callback when its polling interval elapses."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "med"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0xcd_dispatch_mouse_callback@0x417e10 compares timeGetTime against the registered interval, pushes the following PC, verifies the callback's saved script resource id matches the current frame, and jumps to the registered callback target. It writes no operand, so the upstream get-input-type label was incorrect."
|
||||
|
||||
[[opcode]]
|
||||
op = 0xd0
|
||||
@@ -2216,23 +2216,23 @@ argc = 2
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "joy_callback"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "register-joy-callback"
|
||||
category = "input"
|
||||
summary = "(input_index)(target_pc) - register one of 32 per-frame joy/input callback targets."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "med"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0xfb_register_joy_callback@0x421270 bounds-checks operand 1 to 0..31 and stores operand 2 in the current script frame's 33-entry callback table. Ops 0xff/0x100 poll and dispatch this table; HISTORY.BIN and HIDEWIN.BIN register indices 0..10."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "input index"
|
||||
observed_types = ["imm"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 2
|
||||
role = ""
|
||||
role = "callback code target"
|
||||
observed_types = ["imm"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -2263,14 +2263,14 @@ argc = 0
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u00415A10"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "poll-joy-callback-input"
|
||||
category = "input"
|
||||
summary = "Poll the current joy/input callback bitmask and initialize the per-dispatch scan state."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "med"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0xff_poll_joy_callback_input@0x416eb0 clears the pending input mask, fills it through the input poller at 0x4608b0, resets the scan index, and snapshots the current input selector. It pairs with op 0x100."
|
||||
|
||||
[[opcode]]
|
||||
op = 0x100
|
||||
@@ -2279,14 +2279,14 @@ argc = 0
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u00415A60"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "dispatch-joy-callbacks"
|
||||
category = "input"
|
||||
summary = "Dispatch registered callbacks for the current or pending joy/input selection."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x100_dispatch_joy_callbacks@0x416f00 scans the bitmask captured by op 0xff (or uses the current selector when no mask is present), pushes a return PC, and jumps through the current frame's callback table populated by op 0xfb."
|
||||
|
||||
[[opcode]]
|
||||
op = 0x101
|
||||
@@ -2337,18 +2337,18 @@ argc = 1
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u00415E70"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "get-mouse-button-state"
|
||||
category = "input"
|
||||
summary = "(out) - return the current mouse-button state bitmask."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x108_get_mouse_button_state@0x428b60 fills a local through the mouse-state helper at 0x4602e0 and writes it to operand 1. HIDEWIN.BIN and HISTORY.BIN test individual bits to detect press/release transitions."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "mouse button bitmask out"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -4054,18 +4054,18 @@ argc = 1
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u0041D910"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "play-history-voice"
|
||||
category = "audio"
|
||||
summary = "(voice_id) - replay a voice id selected from the retained ADV text history, preserving normal Skip and Auto-voice state behavior."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x1bd_play_history_voice@0x420920 stops/replaces the active voice, starts operand 1 through the native voice service when Skip is inactive (or queues it while Skip is active), records the replay in the message voice state when enabled, and sets adv_auto_voice_pending when playback exists. HISTORY.BIN obtains the id from retained text-record metadata before invoking this opcode."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "voice id"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -4218,7 +4218,7 @@ noop_headless = false
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = "Ghidra handler 0x427330 calls vm_operand_write(1, ctx+0x6dbd4). Producer recovered 2026-07-10: adv_update_read_text_skip_state@0x406cd0 and op 0x6e/0x71/0x72 maintain the field from message_ReadTextSkip plus current-PC read-history lookup; adv_interpreter_tick consumes it in click/read-skip control. It is not the 0x223 surface-transition progress flag."
|
||||
evidence = "Ghidra handler 0x427330 calls vm_operand_write(1, ctx+0x6dbd4). adv_refresh_read_skip_state@0x406cd0 and op 0x6e/0x71/0x72 maintain the field from message:ReadTextSkip plus read_text_db_find_message_index@0x468f50 and read_text_db_is_message_read@0x469930. The database is engine-owned shared RT.DAT state keyed by raw packed script resource id and per-script message index, not VM globals or slot-local SAVE##.DAT data. adv_interpreter_tick consumes the result in click/read-skip control; it is not op 0x223 surface-transition progress."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
@@ -4274,28 +4274,28 @@ argc = 3
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u0041BA80"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "step-text-history"
|
||||
category = "adv"
|
||||
summary = "(out_group)(out_record)(delta) - move through retained ADV text-history groups and return the resolved group/record indices, or -1 at a boundary."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x1d0_step_text_history@0x427360 calls text_history_step_group@0x4537c0 with operand 3 and mode mask 2, then writes two outputs. The helper walks the text manager's 8-byte history index vector over its 0x48-byte retained text records, skipping masked records and returning -1 outputs at a boundary. HISTORY.BIN uses negative deltas to count and page backward and positive deltas to page forward."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "history group out"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 2
|
||||
role = ""
|
||||
role = "history record out"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 3
|
||||
role = ""
|
||||
role = "group delta"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -4305,23 +4305,23 @@ argc = 5
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u0041BAE0"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "render-text-history"
|
||||
category = "adv"
|
||||
summary = "(layout_slot)(record_index)(flags)(color_a)(color_b) - render retained ADV text records into a selected text layout/surface."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x1d1_render_text_history@0x41f950 forwards all five operands plus the text manager at ctx+0x14508 to text_history_render_records@0x4526c0. That helper walks 0x48-byte retained text records, applies record flags/colors/font state, measures strings, and rasterizes/binds them to the chosen layout. HISTORY.BIN uses it to draw each visible backlog line."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "layout slot"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 2
|
||||
role = ""
|
||||
role = "history record index"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
@@ -4372,23 +4372,23 @@ argc = 5
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u0041BB90"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "find-text-history-value"
|
||||
category = "adv"
|
||||
summary = "(out_found)(out_value)(direction)(record_index)(value_type) - find typed metadata within one retained ADV message group."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x1d3_find_text_history_value@0x4273c0 calls text_history_find_typed_value@0x450840 and writes its boolean result plus returned value. The helper scans the 0x48-byte text records within a logical group for flag 0x20000000 and matching type in record+0x18, returning record+0x14. HISTORY.BIN queries types 1 and 2 for line decoration/name metadata."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "found out"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 2
|
||||
role = ""
|
||||
role = "value out"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
@@ -4398,12 +4398,12 @@ observed_types = ["imm"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 4
|
||||
role = ""
|
||||
role = "history record index"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 5
|
||||
role = ""
|
||||
role = "metadata type"
|
||||
observed_types = ["imm"]
|
||||
|
||||
[[opcode]]
|
||||
@@ -4413,23 +4413,23 @@ argc = 4
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u0041BC00"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "find-text-history-pair"
|
||||
category = "adv"
|
||||
summary = "(out_a)(out_b)(direction)(record_index) - find paired metadata within one retained ADV message group."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x1d4_find_text_history_pair@0x427430 calls text_history_find_pair@0x4509f0 and writes two outputs. The helper scans the logical group for a record flagged 0x40000000 and returns its +0x14/+0x18 pair. HISTORY.BIN uses the pair to expose voice replay for a backlog entry."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "first value out"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 2
|
||||
role = ""
|
||||
role = "second value out"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
@@ -4439,7 +4439,7 @@ observed_types = ["imm"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 4
|
||||
role = ""
|
||||
role = "history record index"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode]]
|
||||
|
||||
Reference in New Issue
Block a user