Match native surface persistence policy
This commit is contained in:
@@ -1750,9 +1750,9 @@ diagnostic/extended-mode surface.
|
||||
#### Layout-3 restore mechanics and port correspondence (2026-07-24)
|
||||
|
||||
The port tracks the native global banks separately at runtime, captures the marked frame chain, serializes
|
||||
live surfaces and retained objects, and reloads host textures from the 20-byte surface records. Full load
|
||||
first replaces each serialized mutable bank prefix while preserving initialization-authored cells beyond
|
||||
its count, restores history/gfx and retained audio, unwinds the obsolete managed call chain, runs
|
||||
live surfaces and retained objects, and applies the 20-byte surface records' explicit reload flags. Full
|
||||
load first replaces each serialized mutable bank prefix while preserving initialization-authored cells
|
||||
beyond its count, restores history/gfx and retained audio, unwinds the obsolete managed call chain, runs
|
||||
`CALLBACK_LOAD.BIN` when
|
||||
the mounted script provider resolves it, starts the saved root at its `0xae` rendezvous, recursively
|
||||
reconstructs child frames, resumes parents after their saved T2 call sites,
|
||||
@@ -1775,6 +1775,31 @@ tracks both lifecycles through `0xbf`/`0xc2` and `0xb4`/`0xb6`, serializes them,
|
||||
track plus saved SFX resources. The new EngineCtx fields and function annotations are applied to the
|
||||
saved `/v2` image.
|
||||
|
||||
The surface records have a related preservation boundary. Resource id is at `+0x00`, packed color key at
|
||||
`+0x04`, `+0x08` is a reload flag rather than a general presence bit, `+0x0c` remains unknown, and
|
||||
`+0x10` marks a blank/mutable created surface. `gfx_surface_record_tables_init@0x472700` zeroes both
|
||||
1,000-record tables and initializes every resource id to `-1`.
|
||||
`gfx_surface_create_blank@0x477370` writes resource `-1` and created flag one;
|
||||
`gfx_surface_load_asset@0x477c40` writes resource/color and clears the created flag. Neither operation
|
||||
changes the reload flag. The layout-3 serializer copies all 20,000 live record bytes verbatim, rather
|
||||
than deriving reloadability from the presence of an asset.
|
||||
|
||||
The restore loop calls `gfx_surface_load_asset` only when the saved reload flag is one and resource id is
|
||||
nonnegative. Otherwise the already-initialized surface survives. The optional all-surface release is
|
||||
separately gated by both `set:CreateObject` and `set:AutoFreeTex`; the registered defaults at
|
||||
`engine_settings_register_defaults@0x46be30` are one and zero respectively, matching Himegari's active
|
||||
path. Opcode `0x259` is also a real lifecycle operation:
|
||||
`op_0x259_script_entry_clear_surface_persistence_flags@0x417660` clears record `+0x08` and `+0x0c`
|
||||
across both native tables at every script entry.
|
||||
Installed slot 15 records resource `0x3383` with reload flag zero. SYSTEM4 loads that atlas before the
|
||||
save UI, and BUNKI cuts its reusable choice-box corners, borders, and winged top ornament from it. The
|
||||
port formerly released all 1,000 host surfaces unconditionally, so post-load BUNKI retained its black
|
||||
backing but lost the atlas decoration. Restoration now preserves live surfaces and overlays only flagged
|
||||
reload records by default, while `VmOptions.CreateObject && VmOptions.AutoFreeTextures` reproduces the
|
||||
native all-release branch. Port-authored saves emit the exact resource/reload/created fields, including
|
||||
`-1` for unused records, and opcode `0x259` clears the modeled reload policy without releasing textures.
|
||||
The corrected native functions are renamed/commented in the saved `/v2` image.
|
||||
|
||||
### Opcode `0xae` continues numbered-save stack restoration (2026-07-20)
|
||||
|
||||
Opcode `0xae` is the load-side rendezvous paired with serialized script-frame state. Its handler,
|
||||
|
||||
@@ -924,6 +924,11 @@ The setter get-or-creates the object and writes the complete operand. During ret
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: op_0x24e_handler@0x425070 writes operand 1 directly to EngineCtx.gfx_animation_service_flags at +0x51b80. The mapped field is also read by op 0x243: bit 1 suppresses its force-complete/clock-reset request.
|
||||
|
||||
### 0x259 `script-entry` (script-entry, argc 0)
|
||||
- **summary:** zero-arg script/prologue entry; clears surface-record persistence fields +0x08 and +0x0c across both 1,000-record native tables before the declaration chain continues
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: op_0x259_script_entry_clear_surface_persistence_flags@0x417660 loops over both 20,000-byte surface-record tables (1,000 records x 20 bytes), writing zero to record +0x08 and +0x0c. SC0000 offset 0x0 and every observed script entry begins with this opcode; 0x258 continues the declaration chain. Port clears its modeled +0x08 reload policy; +0x0c remains opaque/unmodeled.
|
||||
|
||||
## input
|
||||
|
||||
### 0x86 `set-cursor-resource` (u0041B210, argc 1)
|
||||
@@ -1149,11 +1154,6 @@ Port status (2026-07-24): implemented through the same profile-lifetime setting
|
||||
- **summary:** 2 imm; runs in a chain right after script-entry 0x259, enumerating ids — prologue declaration/registration?
|
||||
- **grounding:** source=harness, confidence=low, noop_headless=True
|
||||
|
||||
### 0x259 `script-entry` (u00416410, argc 0)
|
||||
- **summary:** zero-arg; the first instruction of a script (offset 0), opens the decl chain that 0x258 continues — script/prologue entry marker, structural
|
||||
- **grounding:** source=harness, confidence=low, noop_headless=True
|
||||
- **evidence:** SC0000 offset 0x0 = op 0x259 (argc 0); 0x258's summary names it 'script-entry 0x259'; VM treats it as no-op (default stub) across all 279 CLEAN A0 scenes
|
||||
|
||||
## unknown
|
||||
|
||||
### 0x2 `exit` (exit, argc 0)
|
||||
|
||||
@@ -3597,6 +3597,37 @@ then confirmed that CHMENU, unit management, SELSTAGE, and FORT audio populate c
|
||||
visible load-specific discrepancy is the reusable choice-box frame losing its top winged flourish after
|
||||
restoration; that is the next independent investigation slice.
|
||||
|
||||
### Persistence implementation step 9 — preserve flag-zero system surfaces (2026-07-24)
|
||||
|
||||
The post-load choice-box discrepancy came from the graphics half of the same ownership rule. BUNKI builds
|
||||
the common modal frame from SYSTEM4's texture slot 15: resource `0x3383` supplies its corners, borders,
|
||||
selection bar, and winged top ornament. The installed layout-3 record retains that resource id but stores
|
||||
zero at record `+0x08`.
|
||||
|
||||
Native RE confirms `+0x08` is a reload flag, not general surface presence.
|
||||
`save_data_deserialize_and_begin_restore@0x40fd10` calls `gfx_surface_load_asset` only for flag-one
|
||||
records. Flag-zero system surfaces remain live unless a separate all-1,000 release path is enabled by
|
||||
both `set:CreateObject` and `set:AutoFreeTex`. The port instead released every host surface and cleared
|
||||
the complete managed surface map before applying only flag-one records. That removed slot 15, leaving
|
||||
BUNKI's black backing but none of its atlas decoration.
|
||||
|
||||
Full load now preserves the current surface registry, overlays explicitly reloadable saved records, and
|
||||
still replaces retained objects and the range transform. Regressions retain an initialized flag-zero
|
||||
slot across a synthetic full load, prove that it is not redundantly reopened, and pin the installed
|
||||
slot-15 resource/reload-flag oracle. The `/v2` deserializer annotation records the corrected ownership
|
||||
boundary and the program is saved. Manual slot-000 acceptance confirms the stage-entry and later BUNKI
|
||||
choices retain the complete winged frame.
|
||||
|
||||
The follow-up fidelity pass closes the two deferred policy gaps. `VmOptions` now carries the native
|
||||
`CreateObject`/`AutoFreeTex` settings with Himegari's registered defaults (`true`/`false`), and enables
|
||||
the all-1,000 host/model release only when both are true. Surface snapshots carry a named per-slot reload
|
||||
bit; ordinary texture loads no longer manufacture it. Native encoding initializes unused resource ids to
|
||||
`-1`, preserves resource/color/reload/created fields, and decoding distinguishes stored records from the
|
||||
subset that must actually be reopened. Opcode `0x259`, formerly treated as a structural marker, is now
|
||||
mapped and implemented as the script-entry clear of record `+0x08`/`+0x0c` (the port models `+0x08`).
|
||||
Regressions cover native-default preservation, opt-in all-release, flag-for-flag port-authored output,
|
||||
script-entry clearing, and the installed all-zero reload-bit oracle.
|
||||
|
||||
## Data-semantics sidebar: focused append EBINIT inspection (2026-07-24)
|
||||
|
||||
The static INIT surface now accepts a universal packed script id for focused append inspection.
|
||||
|
||||
@@ -477,7 +477,10 @@ the `0xae` rendezvous. The real `SAVE.BIN` script is covered end to end for list
|
||||
read-only installed-save gate now continues through `CALLBACK_LOAD`, reconstructs
|
||||
`SYSTEM4.BIN → FORT.BIN`, and reaches FORT's `CHMENU` gameplay poll. Full restoration replaces only the
|
||||
serialized mutable bank prefixes (preserving initialized unit/stage/string definitions), restores the
|
||||
retained BGM/SFX state, and rebuilds graphics/history/frame state. JSON inspection/export,
|
||||
retained BGM/SFX state, preserves initialized flag-zero system surfaces while overlaying explicit saved
|
||||
reload records, reproduces the native configuration-gated all-surface release when explicitly enabled,
|
||||
and writes native per-slot reload/created metadata rather than treating every texture as reloadable.
|
||||
Opcode `0x259` supplies its real script-entry reload-policy clear. JSON inspection/export,
|
||||
namespaced mod data, and migrations remain additive extended-mode work rather than 1.0 compatibility
|
||||
requirements.
|
||||
|
||||
|
||||
@@ -252,11 +252,27 @@ Retained graphics then uses:
|
||||
... native allocation slack
|
||||
```
|
||||
|
||||
The 1,000 surface records preserve resource reload state; mapped fields include resource id at `+0x00`,
|
||||
packed color key at `+0x04`, and presence at `+0x08`. A retained `0x2d4` record is structurally complete
|
||||
but not every internal graphics field is semantically named. The native allocation is larger than the
|
||||
records actually written (`0x2e1 + object_count * 0x2d8` DWORDs in the graphics sizing term), leaving
|
||||
zero/slack bytes after the meaningful range record.
|
||||
The 1,000 surface records preserve the native 20-byte metadata cells verbatim:
|
||||
|
||||
| Offset | Size | Meaning |
|
||||
|---:|---:|---|
|
||||
| `+0x00` | 4 | signed resource id; `-1` means no reloadable asset |
|
||||
| `+0x04` | 4 | packed color key |
|
||||
| `+0x08` | 4 | reload-on-restore flag |
|
||||
| `+0x0c` | 4 | unknown lifecycle field; cleared with `+0x08` at script entry |
|
||||
| `+0x10` | 4 | blank/mutable created-surface flag |
|
||||
|
||||
Initialization writes resource id `-1` to every otherwise-zero record. Ordinary asset load, blank-surface
|
||||
creation, and release do not synthesize or clear the reload flag; opcode `0x259` clears `+0x08` and
|
||||
`+0x0c` across both live/saved tables at script entry. During normal layout-3 restoration AGE reopens only
|
||||
records whose reload flag is one and whose resource id is nonnegative. Flag-zero records describe
|
||||
surfaces expected to remain live across the load. The installed file is decisive: all 1,000 reload flags
|
||||
are zero, while SYSTEM4's reusable choice-frame atlas remains recorded as resource `0x3383` in slot 15.
|
||||
A separate configuration-gated path can release all 1,000 surfaces before this loop, but Himegari's
|
||||
registered `CreateObject=1`, `AutoFreeTex=0` defaults leave it inactive. A retained `0x2d4`
|
||||
record is structurally complete but not every internal graphics field is semantically named. The native
|
||||
allocation is larger than the records actually written (`0x2e1 + object_count * 0x2d8` DWORDs in the
|
||||
graphics sizing term), leaving zero/slack bytes after the meaningful range record.
|
||||
|
||||
The installed `SAVE00.DAT` validates the complete layout-3 decode: cutoff 1, global-bank counts
|
||||
`[402459,1,789,1,1,1]`, current BGM id `0x18`, retained SFX ids `0x3321` (channel 1) and
|
||||
|
||||
Reference in New Issue
Block a user