Implement INPUTNAME string opcodes

This commit is contained in:
gamer147
2026-07-29 13:21:15 -04:00
parent 764fda417e
commit 353bf9404f
12 changed files with 443 additions and 4 deletions

View File

@@ -2891,6 +2891,13 @@ character cells, copies that text into both `0x144` operands, then calls `0x2c6`
the VM worker blocks while Godot's main thread presents a LineEdit dialog, validates the CP932 byte limit
and full-width-only rule, and signals the worker on accept or cancel. No save/profile format is involved.
**Port implementation (2026-07-29).** `Cp932Text` now owns the byte-level character count, substring,
and AGERC acceptance rules. The VM dispatches all three handlers and exposes the modal as an explicit
accept/cancel `IHost` exchange, so cancellation cannot overwrite operand 1. Godot uses a main-thread
`FullwidthTextEditorDialog` while its VM worker waits; over-16-byte and non-double-byte submissions retain
focus and show AGERC's exact Japanese errors. The helper operates on the C-string prefix and encodes through
the configured native code page, avoiding both UTF-16 indexing and accidental splitting of CP932 pairs.
`0xc2` is BGM rather than SFX: `op_0xc2_bgm_fade@0x4204c0` sets run-state `0x200`, arms the service timer,
and calls `bgm_fade_arm@0x464830`. `bgm_fade_tick@0x464960` linearly interpolates current to target percent;
durations at least 1000 ms take 100 steps, shorter durations take 10, and target zero releases the source.

View File

@@ -423,14 +423,14 @@ This is raw strlen(bytes), not a .NET UTF-16 character count. BUNKI compares all
- **grounding:** source=investigation, confidence=high
- **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.
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.
This is character count rather than .NET UTF-16 length or raw CP932 byte length. Port status (2026-07-29): implemented by encoding the C-string prefix through VmOptions.NativeStringCodePage and counting valid CP932 lead/trail pairs as one character; focused tests cover mixed single-byte and double-byte characters.
### 0x2c8 `cp932-substring` (cp932-substring, argc 4)
- **summary:** (out)(string)(start)(count) - copy a CP932 substring selected by multibyte-character index and count without splitting valid lead/trail pairs.
- **grounding:** source=investigation, confidence=high
- **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.
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).
The release call uses nonnegative in-range indices and count 1. Port status (2026-07-29): implemented over encoded byte spans, preserving every valid lead/trail pair and reproducing native end clamping (`end = length` when start+count < 1 or > length) before selecting the half-open character interval [start,end).
## control
@@ -1256,6 +1256,11 @@ character palette. The VM can use a synchronous host seam like the existing diag
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.
Port status (2026-07-29): implemented. The VM issues an explicit accept/cancel request through IHost;
headless hosts preserve the inout value by default. Godot parks the VM worker, opens a main-thread modal
LineEdit, keeps it open on either native validation error, and resumes the worker only after valid accept
or cancel. Accept replaces operand 1 and cancel leaves it untouched; operand 2 is never modified.
### 0x19a `get-message-skip` (u00414E50, argc 1)
- **summary:** (out) - return the current all-message skip state set by op 0x88.

View File

@@ -930,6 +930,23 @@ gaps and 3 of 11 instructions; no persistence or save-format work is involved.
**NEXT:** implement and test `0x144`/`0x2c6`/`0x2c8` together, including CP932 mixed-width helper cases,
the native 16-byte/full-width acceptance rules, accept/cancel behavior, and INPUTNAME's split/rejoin shape.
**INPUTNAME string/input slice implemented (2026-07-29):** the VM now dispatches all three opcodes.
`0x2c6` counts CP932 characters rather than UTF-16 units or bytes, and `0x2c8` slices encoded character
spans with native end clamping. A shared validator applies command 10's 16-byte limit first and then
requires every accepted cell to be a valid CP932 lead/trail pair.
`0x144` uses an explicit synchronous host result, preserving operand 1 on cancel and operand 2 in both
paths. Godot parks the VM worker while a main-thread modal editor owns input; invalid submissions leave
the editor open with AGERC's original error text. Headless hosts cancel safely by default. Focused
regressions cover mixed-width count/slicing, end clamping, valid and invalid names, accept replacement,
cancel preservation, and operand-2 preservation. The slice removes three gaps and three instructions,
leaving 6 effectful opcodes / 8 instructions. Validation passes 493/493 engine tests, opcode and
EngineCtx lint, a zero-warning Godot build, clean diff checking, and the Himegari-targeted threaded
`SELFTEST OK`.
**NEXT:** rerank the remaining six gaps; begin with the two-site `0x24d` and check whether adjacent
`0x248` belongs to the same native subsystem before choosing the next implementation boundary.
## Later Phase B breadth
**INIT data-semantics side track started (2026-07-22).** Before naming more gameplay state, the static