Document SYS4INI startup settings

This commit is contained in:
gamer147
2026-07-28 18:08:17 -04:00
parent 5ce3a7b6f7
commit be1f454d4c
5 changed files with 180 additions and 14 deletions

View File

@@ -164,6 +164,76 @@ binary for every resolution. `display:ScreenMode`, `display:FullScreenWidth/Heig
related registered settings govern presentation/fullscreen selection separately; they do not redefine the related registered settings govern presentation/fullscreen selection separately; they do not redefine the
authored logical canvas. The serialized trailer location is recorded in `sys4-format-notes.md`. authored logical canvas. The serialized trailer location is recorded in `sys4-format-notes.md`.
### SYS4INI startup-settings catalog (resolved 2026-07-28)
The settings trailer is a real per-game startup profile, not a miscellaneous string appendix. The complete
36-pair serialized inventory and physical offsets are canonical in `sys4-format-notes.md`; this section owns
their native behavior and current port relevance.
The startup order is:
1. `engine_settings_register_defaults@0x46be30` creates AGE's generic registry.
2. `engine_load_sys4ini_and_mount_append_catalogs@0x4099f0` parses the asset directory and VM-bank metadata,
then passes the remaining length-delimited settings record to
`EngineCtx::engine_apply_sys4ini_settings@0x4056d0`.
3. `engine_settings_import_sys4ini_pairs@0x46da80` reads the pair count followed by NUL-terminated CP932
key/value strings, matches external names case-insensitively, and inserts their canonical typed keys.
Unknown external names take the loader error path.
4. `engine_apply_sys4ini_settings` copies `set:WinX`, `set:WinY`, and `set:AntiFontVersion` into context
fields. `engine_initialize_subsystems_from_settings@0x415390` then initializes text, graphics, and audio
from the completed registry before script execution.
Most entries are direct integer/string mappings, but three transforms matter:
- `SAVEVERSION=310` becomes `set:SaveVersion1=3` and `set:SaveVersion2=10` by quotient/remainder division
by 100. It is the source of Himegari's persistence layout and append-catalog compatibility version.
- `NOSETMUSIC=3` stores `set:NoSetMusic=3` and also seeds `sound:Music=2`
(`NOSETMUSIC - 1`). `sound_route_is_enabled@0x405420` treats nonnegative music states as enabled;
`sound_set_music_route_enabled@0x407f80` moves the state between enabled/disabled bands separated by
three. The `set:NoSetMusic` copy itself has no later direct reader in this image.
- `WHEELKEYUP`/`WHEELKEYDOWN` each populate both `set:WheelKey*` and
`message:WheelKey*OnTW`. A nonempty `VERREGPOS` also invokes
`registration_read_class00_version@0x46ae80`; its Windows `CLASS00` registry result replaces
`set:GameVersion`.
The meaningful consumer catalog is:
| Setting group | Native Himegari effect | Classification |
|---|---|---|
| `CREATEOBJECT`, `DRAWMODE` | `CreateObject=2` selects only the retained D3D/object backend; `DrawMode=1` selects its matching draw/text path. Startup verifies that bit `1 << DrawMode` exists in the backend mask. | Active renderer selection |
| `SCREENX`, `SCREENY` | Replaces the generic `640x480` fallback with the `800x600` logical canvas before window/surface creation. | Active core profile |
| `FONT`, `ENABLEANTIFONT`, `ANTIFONTVERSION` | Seeds MS Mincho, enables `message:UseAntiFont`, selects the grayscale glyph-outline path, and records antialias version 3. | Active text profile |
| `DEPENDMOVIESOUND` | Supplies the default movie-audio dependency/routing policy when movie opcode flags do not force another route. | Active media policy |
| `FULLSCREENBIT`, `ALWAYSBACKUPSURFACE` | These are read only inside the legacy `CreateObject & 1` DirectDraw branch of `engine_initialize_graphics_from_settings@0x406480`. Himegari selects only bit 2, so its 32-bit/zero values do not drive the active renderer. | Valid compatibility settings, inert for this profile |
| `SCREENWARNING` | Imported as `set:ScreenWarning`; no reader beyond default registration/import was found in this EXE image. | Loaded, no observed consumer |
| `NOSETMUSIC` | Seeds the live music-route state as described above; the route starts enabled. | Active audio initialization plus otherwise-unused policy copy |
| all seven `MENU_*` keys | Imported as `set:Menu_*`. No direct non-loader reader of these exact registry keys was found; they appear to be shared AGE native-menu capability metadata rather than Himegari script-menu state. `MENU_USEANTIFONT` does **not** disable the independently enabled `message:UseAntiFont`. | Loaded compatibility/menu metadata |
| `ENABLEMEMFLIP` | Gates `op_0x6d`, which swaps VM-bank pointer pairs only when enabled. Himegari disables it and its corpus does not use that opcode. | Compatibility capability gate |
| `CLICKONUP` | Imported as `set:ClickOnUp`, but no direct runtime reader was found in this image. | Loaded, no observed consumer |
| `CANCELMESSKIPONCLICK` | Himegari overrides the zero fallback with 2, enabling `adv_interpreter_tick`'s press/release click-cancel state machine for persistent message Skip. | Active ADV input behavior; currently missing from port |
| `CONTROLDISIBLECURSOR` | The spelling is native. Value 1 suppresses AGE's ordinary cursor-restore call when a bound ADV hotspot action or hover callback is selected. | Active ADV cursor behavior; currently missing from port |
| `COEXISTMESSKIP` | Value 1 lets Auto and all-message Skip remain simultaneously enabled. With zero, `adv_toggle_auto_mode@0x406b70` clears Skip and `adv_toggle_skip_mode@0x406c20` clears Auto. | Active ADV toggle behavior; currently missing from port |
| `REDRAWTEXTONKEY` | Value 0 disables the wheel/key path that traverses and republishes the current text-history view through `CALLBACK_TEXT.BIN`. | Active ADV history-input policy; port uses its script callback path instead |
| `WHEELKEYUP`, `WHEELKEYDOWN` | Rebinds the registry action bits from generic defaults 3/1 to 8/9. `adv_input_service_poll@0x411230` uses them for ADV wheel-key/history handling; raw `WM_MOUSEWHEEL` accumulation for op `0x10d` remains a separate channel. | Active ADV input binding; port does not source these values |
| `USEAPPDATAFOLDER`, `SAVEPATH` | Selects `%LOCALAPPDATA%\Eushully\姫狩りダンジョンマイスター\SAVE` as the native save root. | Active native path policy; intentionally redirected by port |
| `REGFILEPATH` | Supplies the Eushully/product-relative Windows registration-file path used by the native registration integration. | Windows integration only |
| `SAVEVERSION` | Selects numbered-save layout 3.10 and enables the matching append-catalog persistence structures. | Active persistence ABI |
| `GAMEVERSION`, `VERREGPOS` | Seeds display/registration version `1.00`, then permits the GUID-selected Windows registry `CLASS00` value to replace it. | Windows version/registration metadata |
| `REGKEY` | A nonzero value activates `registration_validate_key_file@0x46fc80`, which opens `SYS4RK.BIN`, validates its header/transformed payload and both CRC variants, and publishes the registration result. | Native registration/key validation |
| `COPYRIGHT`, `RCVERSION` | Both are imported; no later direct consumer of the exact registry keys was found in this image. | Loaded product metadata |
This is intentionally a native-behavior catalog, not a mandate to reproduce every Win32-era switch. The
current port already preserves the shipped result of several settings through profile-specific constants:
the `800x600` canvas, requested Mincho/Gothic faces, save version 3.10, and movie/audio behavior. It
deliberately redirects the native AppData path to Godot `user://SAVE`, and it should not reproduce legacy
DirectDraw selection or native registration/key validation.
The actionable generic-profile gap is that `Sys4AssetCatalog` still parses only the directory and the frontend
hard-codes the important results. A future configuration/profile slice should expose the typed trailer values
once and let the runtime apply only cross-platform semantic settings. In particular, click-cancel, Auto/Skip
coexistence, cursor policy, redraw policy, and wheel action ids must be decided from this evidence instead of
AGE's compiled defaults. No runtime behavior changes were made as part of this investigation.
### ops `0x1a2`/`0x1a3` store and restore shared `SAVE.DAT` integer cells (resolved 2026-07-20) ### ops `0x1a2`/`0x1a3` store and restore shared `SAVE.DAT` integer cells (resolved 2026-07-20)
The SCJUMP slice assumed `u00428010` resolved a decision value to a scene. **That premise is wrong**, The SCJUMP slice assumed `u00428010` resolved a decision value to a scene. **That premise is wrong**,
@@ -1632,9 +1702,11 @@ The state queries are deliberately different:
All 301 ordinary ADV button callbacks call `0x88(1)`. `CALLBACK_LOAD.BIN` contains the corpus's only All 301 ordinary ADV button callbacks call `0x88(1)`. `CALLBACK_LOAD.BIN` contains the corpus's only
`0x88(0)` reset. The engine supports an optional click-cancel state machine, but `0x88(0)` reset. The engine supports an optional click-cancel state machine, but
`engine_settings_register_defaults@0x46be30` registers `set:CancelMesSkipOnClick=0`; a nonzero loaded engine `engine_settings_register_defaults@0x46be30` registers `set:CancelMesSkipOnClick=0` only as the generic
configuration is required to enable its press/release cancellation path. The port preserves that default fallback. Himegari's SYS4INI trailer overrides it with `CANCELMESSKIPONCLICK=2`, enabling the
instead of unconditionally inventing click-to-cancel. press/release cancellation path. The port currently preserves the fallback instead because it does not yet
apply the trailer's ADV policy settings; that is now a cataloged parity gap rather than evidence that
Himegari intended click-cancel to remain disabled.
Voice playback also has a native Skip queue. `op_0xc4_handler@0x420610` plays immediately while the skip bit Voice playback also has a native Skip queue. `op_0xc4_handler@0x420610` plays immediately while the skip bit
is clear. While it is set, the handler replaces `ctx+0x6dbf4/+0x6dbf8` with the latest requested voice instead is clear. While it is set, the handler replaces `ctx+0x6dbf4/+0x6dbf8` with the latest requested voice instead

View File

@@ -3329,6 +3329,35 @@ shared-profile registration.
`G[0x3ebe]` (21 references across CALCREVISE, CHMENU, DRAWTIP, GAMECLEAR, GAMESTART, IMPROVE, and `G[0x3ebe]` (21 references across CALCREVISE, CHMENU, DRAWTIP, GAMECLEAR, GAMESTART, IMPROVE, and
TUNE). TUNE).
## SYS4INI startup-settings investigation (2026-07-28)
The post-directory SYS4INI data is now structurally and behaviorally cataloged. Himegari's decompressed
tail contains a `0x90`-byte VM-metadata block followed by a `0x2bb`-byte, 36-pair CP932 startup-settings
record. Native AGE first registers generic defaults, imports those pairs case-insensitively, applies three
special transforms (`SAVEVERSION`, `NOSETMUSIC`, and wheel-key duplication), then initializes the logical
canvas, text, graphics, audio, ADV input policy, persistence, and Windows registration integration from
the completed registry.
The investigation distinguishes active Himegari behavior from loaded compatibility metadata. Active core
results include retained renderer/draw mode, `800x600`, Mincho/antialias profile, movie-audio policy,
save layout 3.10, and AppData save-root selection. The important newly exposed ADV overrides are
`CANCELMESSKIPONCLICK=2`, `CONTROLDISIBLECURSOR=1`, `COEXISTMESSKIP=1`,
`REDRAWTEXTONKEY=0`, and wheel actions 8/9. The port does not currently parse/apply those ADV policy
values; in particular, the earlier click-cancel conclusion accidentally preserved AGE's zero fallback
instead of Himegari's override.
Legacy DirectDraw-only values, unused native-menu flags, and Windows registration/key metadata are now
classified separately so a later generic profile loader does not mistake every serialized setting for a
portable runtime requirement. No gameplay/runtime behavior changed in this investigation. The exact
serialized inventory is canonical in `sys4-format-notes.md`, native consumers and port relevance in
`engine-re.md`, multi-profile direction in `remake-architecture-and-roadmap.md`, and portability impact in
`platform-portability.md`. The `/v2` Ghidra image names/comments the importer and principal graphics,
ADV-toggle, audio, and registration consumers.
**Next:** keep the settings parser/application as a bounded generic-profile/configuration slice. Resume
the Phase-B gameplay spine unless one of the cataloged ADV policy differences becomes a visible gameplay
or input defect.
## ADV requested-face selection implemented (2026-07-28) ## ADV requested-face selection implemented (2026-07-28)
Opcode `0x1a5` is no longer a presentation no-op. The VM retains its requested face in Opcode `0x1a5` is no longer a presentation no-op. The VM retains its requested face in

View File

@@ -27,6 +27,7 @@ or replaced before claiming portable exports.
| Area | Current dependency | Runtime impact | Portability status / future action | | Area | Current dependency | Runtime impact | Portability status / future action |
|---|---|---|---| |---|---|---|---|
| SYS4INI per-game startup profile | `Sys4AssetCatalog` currently parses only the asset directory; the frontend hard-codes Himegari's important results. Native SYS4INI also carries canvas, text, ADV input/skip, save ABI/path, audio, legacy renderer, and Windows registration settings | The port has the correct `800x600`, requested faces, save 3.10, and redirected `user://SAVE` result, but does not source `CancelMesSkipOnClick`, `CoexistMesSkip`, cursor/redraw policy, or wheel action ids from the trailer | Add one typed profile/settings parser. Apply cross-platform semantic keys explicitly; translate save roots through the host; classify DirectDraw/fullscreen-bit and registration/key settings as native compatibility metadata rather than OS-neutral requirements. Canonical inventory and consumers: `sys4-format-notes.md` and `engine-re.md` |
| Retained graphics presentation | Backend-neutral `GfxState`; accepted default Godot `Sprite2D` GPU stage plus the retained software pixel oracle, using runtime `ImageTexture`, canvas transforms/materials, and no native graphics API | GPU backend caches static/color-key variants, updates dynamic surfaces, handles retained range transitions, and falls back whole-frame for the legacy host screen-transition path | Godot owns D3D/Vulkan/Metal/OpenGL selection; validate shader/blend/filter behavior per target rather than adding a platform renderer | | Retained graphics presentation | Backend-neutral `GfxState`; accepted default Godot `Sprite2D` GPU stage plus the retained software pixel oracle, using runtime `ImageTexture`, canvas transforms/materials, and no native graphics API | GPU backend caches static/color-key variants, updates dynamic surfaces, handles retained range transitions, and falls back whole-frame for the legacy host screen-transition path | Godot owns D3D/Vulkan/Metal/OpenGL selection; validate shader/blend/filter behavior per target rather than adding a platform renderer |
| AGE movie decode (`0x236` scene movies; `0x20f` modal LOGO/OP/ED) | `FfmpegMovieDecoder` is the sole factory over the project-owned `native/age_movie_ffmpeg` ABI | Windows-x64 passes the complete 213-payload installed video/audio corpus gate plus audible LOGO/OP/CHAPTER playback | Add target-specific native builds and export packaging | | AGE movie decode (`0x236` scene movies; `0x20f` modal LOGO/OP/ED) | `FfmpegMovieDecoder` is the sole factory over the project-owned `native/age_movie_ffmpeg` ABI | Windows-x64 passes the complete 213-payload installed video/audio corpus gate plus audible LOGO/OP/CHAPTER playback | Add target-specific native builds and export packaging |
| Movie integration | Each surface owns a unique playback-instance id; `MovieRuntime` owns `IMovieDecoder` from an injected factory; video-only streams use monotonic pacing while audio-bearing streams use the Godot output clock | Concurrent/restarted uses of one asset have independent frame/audio/completion/teardown state; managed code is no longer Windows-annotated, while only the win-x64 native bundle exists today | Add Linux/macOS native builds and smoke gates | | Movie integration | Each surface owns a unique playback-instance id; `MovieRuntime` owns `IMovieDecoder` from an injected factory; video-only streams use monotonic pacing while audio-bearing streams use the Godot output clock | Concurrent/restarted uses of one asset have independent frame/audio/completion/teardown state; managed code is no longer Windows-annotated, while only the win-x64 native bundle exists today | Add Linux/macOS native builds and smoke gates |

View File

@@ -677,9 +677,16 @@ from that game's corpus.
The probe also exposed a separate profile/presentation concern: Kamidori creates a `1024x576` render The probe also exposed a separate profile/presentation concern: Kamidori creates a `1024x576` render
target while the current Himegari frontend assumes an `800x600` presentation. Logical canvas geometry, target while the current Himegari frontend assumes an `800x600` presentation. Logical canvas geometry,
scaling, and any game-specific defaults therefore belong in the selected game profile or script-driven scaling, and other game-specific defaults therefore belong in the selected game profile or script-driven
surface state rather than in a forked frontend. This experiment was diagnostic only; no Kamidori support surface state rather than in a forked frontend. The source is now known: after its asset directory and
or `0x1be` semantics were implemented. VM-bank metadata, SYS4INI carries a typed per-game startup-settings record. Himegari uses it for the
canvas, text face/raster mode, ADV input/skip policy, save ABI/path, audio initialization, and native
Windows compatibility metadata. A future generic profile loader should parse that record once, preserve
unknown/profile-specific data for diagnostics, apply cross-platform semantic settings through explicit
runtime seams, and classify legacy renderer/registration switches rather than blindly emulating them.
The current frontend's scattered Himegari constants are acceptable while gameplay is the priority, but
they are not the multi-profile architecture. This experiment was diagnostic only; no Kamidori support or
`0x1be` semantics were implemented.
### Other engine versions (SYS3 / SYS5) — one app, not many ### Other engine versions (SYS3 / SYS5) — one app, not many
Versions differ in: header (SYS4 `0x3C` vs SYS5 `0x44`), string codec (SYS4 cp932^0xFF vs SYS5 Versions differ in: header (SYS4 `0x3C` vs SYS5 `0x44`), string codec (SYS4 cp932^0xFF vs SYS5

View File

@@ -23,15 +23,72 @@ per format.
NUL-delimited per-game engine-settings trailer. `tools/parse_sys4ini.py` currently consumes only the NUL-delimited per-game engine-settings trailer. `tools/parse_sys4ini.py` currently consumes only the
directory prefix. directory prefix.
The Himegari trailer contains `SCREENX=800` and `SCREENY=600`; Kamidori's independent SYS4INI contains After the directory prefix, Himegari's decompressed stream has this tail:
`SCREENX=1024` and `SCREENY=576`. This establishes the authored logical canvas as per-game data. Native
initialization and the executable's `640x480` fallback are documented in `engine-re.md`;
fullscreen/display-mode settings are a separate concern from these logical dimensions.
The same Himegari trailer also contains `USEAPPDATAFOLDER=1` and ```text
`SAVEPATH=Eushully\姫狩りダンジョンマイスター\SAVE`. AGE's native save-root resolver consumes those decompressed offset field
settings to select `%LOCALAPPDATA%` plus that relative path on modern Windows. Filename patterns remain 0x102488 vm_metadata_bytes:u32 = 0x90
native policy rather than trailer or script strings; see `engine-re.md` under "Save-root resolution." 0x10248c vm_metadata[0x90]
0x10251c settings_string_bytes:u32 = 0x2bb
0x102520 setting_pair_count:u32 = 36
0x102524 repeated { key:cstring, value:cstring }[36]
0x1027df end of decompressed stream
```
The string-byte count covers only the concatenated key/value strings, not the preceding pair count.
Keys are ASCII, values are CP932, and every key and value is individually NUL-terminated. Native
`engine_settings_import_sys4ini_pairs@0x46da80` matches keys case-insensitively and rejects an
unrecognized key rather than silently retaining it.
Himegari's complete serialized list, in file order, is:
| # | Key | Value |
|---:|---|---|
| 1 | `CREATEOBJECT` | `2` |
| 2 | `DRAWMODE` | `1` |
| 3 | `DEPENDMOVIESOUND` | `1` |
| 4 | `SCREENX` | `800` |
| 5 | `SCREENY` | `600` |
| 6 | `FONT` | ` 明朝` |
| 7 | `ENABLEANTIFONT` | `1` |
| 8 | `ANTIFONTVERSION` | `3` |
| 9 | `FULLSCREENBIT` | `32` |
| 10 | `SCREENWARNING` | `1` |
| 11 | `NOSETMUSIC` | `3` |
| 12 | `MENU_SAVE` | `0` |
| 13 | `MENU_MESWINA` | `0` |
| 14 | `MENU_RCLICK` | `0` |
| 15 | `MENU_MESSPEED` | `0` |
| 16 | `MENU_USEANTIFONT` | `0` |
| 17 | `MENU_MESSAGE` | `1` |
| 18 | `MENU_SOUNDONOFF` | `0` |
| 19 | `ENABLEMEMFLIP` | `0` |
| 20 | `CLICKONUP` | `1` |
| 21 | `ALWAYSBACKUPSURFACE` | `0` |
| 22 | `CANCELMESSKIPONCLICK` | `2` |
| 23 | `CONTROLDISIBLECURSOR` | `1` |
| 24 | `COEXISTMESSKIP` | `1` |
| 25 | `REDRAWTEXTONKEY` | `0` |
| 26 | `WHEELKEYUP` | `8` |
| 27 | `WHEELKEYDOWN` | `9` |
| 28 | `USEAPPDATAFOLDER` | `1` |
| 29 | `SAVEPATH` | `Eushully\姫狩りダンジョンマイスター\SAVE` |
| 30 | `REGFILEPATH` | `Eushully\姫狩りダンジョンマイスター` |
| 31 | `COPYRIGHT` | `Copyright (c) Eushully 2009` |
| 32 | `SAVEVERSION` | `310` |
| 33 | `GAMEVERSION` | `1.00` |
| 34 | `RCVERSION` | `23` |
| 35 | `VERREGPOS` | `70724B91-F673-40FB-9EC4-5DE21EA68367` |
| 36 | `REGKEY` | `1886538641` |
This list is the canonical serialized-data inventory. Native consumers, compiled fallbacks, settings
that are inert under Himegari's selected renderer, and current port coverage are cataloged in
`engine-re.md` under "SYS4INI startup-settings catalog."
`SCREENX=800` and `SCREENY=600` are independently corroborated by Kamidori's `1024x576` pair, proving
that the authored logical canvas is per-game data. Fullscreen/display-mode settings are separate from
these logical dimensions. `USEAPPDATAFOLDER` and `SAVEPATH` select the native Windows save root; fixed
save filenames remain AGE policy rather than trailer or script strings.
## Native persistence files — Himegari 3.10 ## Native persistence files — Himegari 3.10