Investigate INPUTNAME string opcodes

This commit is contained in:
gamer147
2026-07-29 12:57:55 -04:00
parent 2908d38663
commit 862b74ecbc
5 changed files with 130 additions and 56 deletions

View File

@@ -2914,12 +2914,12 @@ abi_source = "kelebek+decode-validated"
[opcode.semantics]
name = "coroutine-label-yield"
category = "control"
summary = "(out)(name_str)(sub_str)(in) — scene-coroutine LOOP ITERATOR / labeled yield. Handler copies name/sub strings + the int operand and calls the NATIVE video/transition service (*DAT_005c6018)(8, ctx[0x54fe8], &{name,sub,in}); writes the returned PC-like value to operand 1. In SC0000 label_462 'ループ開始' (@0x46d): `out=G[0x6be]=LABEL('J',G[0x6be])`; loop runs the intro-setup body (incl. call label_125bd = slot-table fill G[0x3239..0x324e]=4..11) and jmps back until out==G[0x6c3] (a per-scene exit-PC immediate) → mov aba5c 0 → content. The gate G[0xaba5c]==1 that opens this loop is NATIVE scene-entry state (no script sets it to 1). DAT_005c6018 is runtime-resolved (all xrefs READ) = SAME class as the DirectDraw workers we don't model. PORT = HOST-MODEL IMPLEMENTED: synthesize the ADV scene-entry gate, run the LABEL/J setup body once, then return the structurally discovered per-scene terminal; do not emulate the video service. See engine-re.md §Scene-coroutine framework."
summary = "(out)(name_str)(sub_str)(in) — scene-coroutine LOOP ITERATOR / labeled yield. Handler copies name/sub strings + the int operand and calls AGERC host command 8 through g_pfnAgercHostCallback(8, ctx[0x54fe8], &{name,sub,in}); writes the returned PC-like value to operand 1. In SC0000 label_462 'ループ開始' (@0x46d): `out=G[0x6be]=LABEL('J',G[0x6be])`; loop runs the intro-setup body (incl. call label_125bd = slot-table fill G[0x3239..0x324e]=4..11) and jmps back until out==G[0x6c3] (a per-scene exit-PC immediate) → mov aba5c 0 → content. The gate G[0xaba5c]==1 that opens this loop is NATIVE scene-entry state (no script sets it to 1). PORT = HOST-MODEL IMPLEMENTED: synthesize the ADV scene-entry gate, run the LABEL/J setup body once, then return the structurally discovered per-scene terminal; do not emulate the service dialog. See engine-re.md §Scene-coroutine framework."
noop_headless = false
source = "investigation"
confidence = "med"
depends_on = []
evidence = "Ghidra: handler 0x4299c0 (dispatch ctx[0x9b74c]=0x4299c0; created+typed EngineCtx*+annotated; Kelebek u0041F9C0 = VA-drift). Records the generic 9-dword instruction length; op2→local_204, op3→local_104, op4→local_208; (*DAT_005c6018)(8, ctx[0x54fe8], &local_210) → FUN_00425fb0(1,ret). DAT_005c6018: 6 xrefs all READ, no static writer; FUN_00405740 (screen-fade) calls it w/ cmd 3, branches on ret 1/2 = transition progress = native video service."
evidence = "Ghidra: handler 0x4299c0 (dispatch ctx[0x9b74c]=0x4299c0; created+typed EngineCtx*+annotated; Kelebek u0041F9C0 = VA-drift). Records the generic 9-dword instruction length; op2→local_204, op3→local_104, op4→local_208; g_pfnAgercHostCallback(8, ctx[0x54fe8], &local_210) → FUN_00425fb0(1,ret). A read-only probe resolves the callback to AGERC.DLL+0x1050; imported /support/AGERC.DLL identifies agerc_dispatch_host_command@0x100025f0 and its command-8 dialog-resource branch. FUN_00405740 calls the same dispatcher with command 3 and branches on return 1/2 for transition progress. Command 8's exact LABEL iterator calculation remains unresolved, so confidence remains medium."
[[opcode.semantics.args]]
i = 1
@@ -3016,28 +3016,34 @@ record-zero failure. Natural SYSTEM4 boot proves BTANINIT2 -> `$1$AUTORUN.BIN` -
[[opcode]]
op = 0x144
label = "u004259D0"
label = "edit-fullwidth-string-dialog"
argc = 2
abi_source = "kelebek+decode-validated"
[opcode.semantics]
name = "u004259D0"
category = "unknown"
summary = ""
name = "edit-fullwidth-string-dialog"
category = "input"
summary = "(result_inout)(initial_text) - synchronously open AGERC's modal full-width text editor. Accept writes at most eight valid CP932 double-byte characters to operand 1; cancel leaves operand 1 unchanged. Operand 2 supplies the initial edit text and is preserved."
noop_headless = false
source = "kelebek"
confidence = "low"
source = "investigation"
confidence = "high"
depends_on = []
evidence = ""
evidence = "The real /v2 dispatch slot registers op_0x144_edit_fullwidth_string_dialog@0x42bdd0. It copies both resolved string operands into 0x400-byte buffers, calls the runtime host callback g_pfnAgercHostCallback with command 10 and owner HWND, then writes both returned buffers back. A read-only Frida probe of the pristine game resolved that callback to AGERC.DLL+0x1050. Imported /support/AGERC.DLL shows agerc_dispatch_host_command@0x100025f0 opening dialog resource 10 with agerc_fullwidth_text_dialog_proc@0x10002140: edit control 1006 is initialized from operand 2; IDOK rejects more than 16 bytes (`字数オーバーです`) or any non-DBCS cell (`半角文字は使用できません`) before copying the accepted text to operand 1; IDCANCEL closes without changing operand 1. INPUTNAME's sole site at 0xdcd passes its assembled current name in both operands, then resplits operand 1 through 0x2c6/0x2c8."
details = """
This is INPUTNAME's optional native keyboard-entry button, not the surrounding script-authored
character palette. The VM can use a synchronous host seam like the existing diagnostic dialog because
the Godot host runs script execution on its worker thread while the main thread owns the modal UI.
Compatibility requires the native full-width-only and 16-CP932-byte limits before accepting the result.
"""
[[opcode.semantics.args]]
i = 1
role = ""
role = "result/inout string"
observed_types = ["l-str"]
[[opcode.semantics.args]]
i = 2
role = ""
role = "initial edit text"
observed_types = ["l-str"]
[[opcode]]
@@ -6882,64 +6888,66 @@ observed_types = ["g-str", "l-str", "l-str-ptr"]
[[opcode]]
op = 0x2c6
label = "u0042B5E0"
label = "cp932-character-length"
argc = 2
abi_source = "kelebek+decode-validated"
[opcode.semantics]
name = "u0042B5E0"
category = "unknown"
summary = ""
name = "cp932-character-length"
category = "compute"
summary = "(out)(string) - write the Japanese-locale multibyte character count of the CP932 string, counting a valid lead/trail pair as one character."
noop_headless = false
source = "kelebek"
confidence = "low"
source = "investigation"
confidence = "high"
depends_on = []
evidence = ""
evidence = "The real /v2 dispatch slot registers op_0x2c6_cp932_character_length@0x42a6d0. The handler sets LC_ALL to `japanese`, resolves operand 2, calls MSVC _mbstrlen, and writes the result to operand 1. INPUTNAME's sole site at 0x1002 uses this count as the loop bound before slicing each character with opcode 0x2c8."
details = "This is character count rather than .NET UTF-16 length or raw CP932 byte length. The implementation should use VmOptions.NativeStringCodePage and preserve valid CP932 multibyte boundaries."
[[opcode.semantics.args]]
i = 1
role = ""
role = "character count out"
observed_types = ["l-int"]
[[opcode.semantics.args]]
i = 2
role = ""
role = "source string"
observed_types = ["l-str"]
[[opcode]]
op = 0x2c8
label = "u0042B610"
label = "cp932-substring"
argc = 4
abi_source = "kelebek+decode-validated"
[opcode.semantics]
name = "u0042B610"
category = "unknown"
summary = ""
name = "cp932-substring"
category = "compute"
summary = "(out)(string)(start)(count) - copy a CP932 substring selected by multibyte-character index and count without splitting valid lead/trail pairs."
noop_headless = false
source = "kelebek"
confidence = "low"
source = "investigation"
confidence = "high"
depends_on = []
evidence = ""
evidence = "The real /v2 dispatch slot registers op_0x2c8_cp932_substring@0x42c420. It copies operand 2 into a 256-byte buffer, sets LC_ALL to `japanese`, obtains _mbstrlen, reads start and count, clamps end=start+count to the character length when end is below 1 or beyond that length, and walks bytes with _mbbtype so CP932 lead/trail pairs are copied together. It writes the selected byte interval back through operand 1. INPUTNAME's sole site at 0x1021 loops substring(name,index,1) into its eight local character cells."
details = "The release call uses nonnegative in-range indices and count 1. A compatible general implementation should reproduce native end clamping (`end = length` when start+count < 1 or > length) and select the half-open character interval [start,end)."
[[opcode.semantics.args]]
i = 1
role = ""
role = "substring out"
observed_types = ["l-str-ptr"]
[[opcode.semantics.args]]
i = 2
role = ""
role = "source string"
observed_types = ["l-str"]
[[opcode.semantics.args]]
i = 3
role = ""
role = "start character index"
observed_types = ["l-int"]
[[opcode.semantics.args]]
i = 4
role = ""
role = "character count"
observed_types = ["imm"]
[[opcode]]
op = 0x4