engine: retain History and wait presentation
This commit is contained in:
@@ -105,8 +105,8 @@ S:\Game Hacking\Eushully\Himegari\ ← workspace root (three siblings)
|
||||
│ ALF asset store, script provider, AGF/LZSS and Windows CUR decoders,
|
||||
│ and resource facade
|
||||
│ ├── Age.Engine/Text/ backend-neutral glyph-mask requests/results, deterministic AGE
|
||||
│ compositor/layout, retained live-glyph publication, and bounded
|
||||
│ font/glyph cache primitives
|
||||
│ compositor/layout, retained live/History glyph and wait-atlas
|
||||
│ publication, and bounded font/glyph cache primitives
|
||||
│ ├── Age.Engine/Persistence/ native S3SD/S4SD + S3RT codecs, shared payload/ReadTextDB,
|
||||
│ layout-3 numbered state/history/gfx, DAT/STH pair + BMP codec,
|
||||
│ and profile-owned state
|
||||
|
||||
@@ -2546,8 +2546,13 @@ Op `0x1d1` asks `AdvTextHistory` to select one retained group, skip metadata/voi
|
||||
host-facing render batch using the target layout configured by `0x70/0x71`, positioned by `0x198`, and
|
||||
seeded by `0x7a`. `HISTORY.BIN` passes zero for flags and both color overrides, so this is its exact ordinary
|
||||
binding path; the native flag-4 raster-without-binding and flag-8 side-effect modes remain outside the live
|
||||
game call site. Godot owns only replaceable labels keyed by target layout, applies the retained font/color/
|
||||
effect snapshot, and clears stale labels whenever `0x71` resets that layout.
|
||||
game call site. The initial port used replaceable labels keyed by target layout. The retained-glyph migration
|
||||
now passes the target's transient surface/handle binding with the batch, rasterizes its text through the
|
||||
shared glyph-mask service, and publishes one ordinary object per edge record. Exact rows therefore inherit
|
||||
native z-order, alpha/tint/fade, clipping, transforms, capture, and range erasure. `0x71` resets the row's
|
||||
surface and records; HISTORY's broad exit erase plus recording re-enable remove all transient row bindings
|
||||
without touching the persisted backlog. The layout-keyed Label remains only as the explicit
|
||||
unavailable-rasterizer fallback.
|
||||
|
||||
The same slice implements the support calls at their natural seams. Op `0x131` reads a host configuration
|
||||
property (currently defaulting to zero; choosing a profile/config persistence backend remains deferred),
|
||||
@@ -2982,8 +2987,7 @@ and returns the five-dword edge records plus final cursor, observed overflow, wr
|
||||
state. It preserves native horizontal precedence: vertical-only overflow stops before compositing, while a
|
||||
simultaneous horizontal overflow follows the wrap/kinsoku path. A reusable bounded LRU provides eviction
|
||||
callbacks for future native font handles; `CachedGlyphMaskRasterizer` applies the same bound to masks. This
|
||||
core now drives immediate surface strings and live ADV; retained History remains on its Label pending the
|
||||
next migration step.
|
||||
core now drives immediate surface strings, live ADV, and retained History.
|
||||
|
||||
The independent Windows reference backend landed alongside, but outside, the neutral engine as
|
||||
`Age.Engine.Text.Windows.WindowsGdiGlyphMaskRasterizer`. It holds one `CreateICA("DISPLAY")` information
|
||||
@@ -3014,7 +3018,8 @@ offscreen capture, fill/copy, and preservation behavior apply without a detached
|
||||
If the exact backend is unavailable, string conversion fails, or the target surface cannot be resolved,
|
||||
the host records one explicit diagnostic and retains the old metadata/Label projection for that draw. The
|
||||
fallback is constructed before surface publication, so it cannot mix a partial new raster with the Label.
|
||||
History and the wait indicator remain on their existing presentation paths for the later staged migration.
|
||||
This fallback now covers immediate, live, and History text; the non-glyph wait indicator is always an
|
||||
ordinary retained atlas object when its script binding is valid.
|
||||
|
||||
Live ADV now uses the same exact surface pixels through ordinary retained objects.
|
||||
`AdvTextLayoutPresentationBinding` is transient engine state: it carries the layout surface (`slot+0x14`),
|
||||
@@ -3059,13 +3064,20 @@ the following click releases the wait.
|
||||
|
||||
**Port implementation:** the single-scene harness now injects SYSTEM4's exact SO000 surface-12 and op-`0x73`
|
||||
configuration alongside its existing SO001 shortcut. The VM forwards all ten operands through the host ABI;
|
||||
`GodotAdvHost` retains configurations by layout and resolves slot 0 to the active Phase-A layout. A separate
|
||||
Godot atlas overlay advances on the 48 ms host clock only while `IsWaiting`, then hides immediately when
|
||||
input releases the wait. A 2026-07-27 polish fix removed the port's erroneous `TerminalFrame + 1`
|
||||
`GodotAdvHost` retains configurations by layout and pairs them with op `0x212`'s script-owned handle and
|
||||
layout origin. `RetainedAdvWaitIndicatorPresentation` binds the current atlas cell as an ordinary
|
||||
`GfxState` object, mutating it only when the 48 ms frame boundary changes. Op `0x20a` recreates an erased
|
||||
current frame; HIDEWIN suspension and wait-service shutdown erase the handle. The former Godot
|
||||
`TextureRect` overlay and raw-callback visibility exception are removed, so normal handle order, source
|
||||
color key, capture, and surface/scene composition apply. A real Vulkan SC0000 page-one capture places the
|
||||
retained bat at `(385,570)`.
|
||||
|
||||
A 2026-07-27 polish fix removed the port's erroneous `TerminalFrame + 1`
|
||||
interpretation, which had selected nonexistent frame `12` once per cycle and made Godot render one empty
|
||||
atlas cell. Frame selection now treats the terminal value as the exclusive frame count and loops `0..11`.
|
||||
Keeping this 30x27 overlay outside the software backbuffer preserves the static-wait compositor optimization.
|
||||
Full SYSTEM4 replay remains Phase-B work; the shortcut carries the same state in the meantime.
|
||||
The retained presenter requests a new frame only when that source cell changes, preserving the static-wait
|
||||
compositor optimization. Full SYSTEM4 replay remains Phase-B work; the shortcut carries the same state in
|
||||
the meantime.
|
||||
|
||||
### SC0000 native SFX / BGM-fade family — `0xb4`/`0xb5`/`0xb6`/`0xba`/`0xc2`/`0xd9` (2026-07-11)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ or replaced before claiming portable exports.
|
||||
| AGE movie decode (`0x236` scene movies; `0x20f` modal LOGO/OP/ED; `0x24d` movie masks) | `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 and real TEST.AGF green-mask decode | 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. Opcode `0x24d` redirects decoded green bytes through the platform-neutral retained rasterizer and exact managed packed-alpha mask helper | Concurrent/restarted uses of one asset have independent frame/audio/completion/teardown state. Ordinary and mask movies share VFS/FFmpeg ownership; the mask result is a backend-neutral dynamic RGBA surface consumed by either Godot renderer. 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 audio | ABI v2 returns timestamped stereo float PCM; bounded managed buffering feeds a per-playback Godot `AudioStreamGenerator` and routes native movie flags to engine buses | All 29 installed audio-bearing streams decode with signal; synchronized LOGO/OP/CHAPTER playback is audibly accepted | Treat absent, distorted, or unsynchronized audio from an audio-bearing movie as a runtime bug |
|
||||
| ADV font discovery/raster fidelity | `Age.Engine.Text` remains OS-neutral. Godot selects the separate `Age.Engine.Text.Windows` backend for immediate `0x204`/`0x205` strings and live ADV when Windows ACP 932 is available; exact masks are cached, composited into layout/numbered RGBA surfaces, and live glyphs become ordinary retained handles. History still uses the existing `Label` path. The fallback loads Windows `MS 明朝`/`MS ゴシック` when available and otherwise chooses the Japanese/default font with FreeType embolden and a Godot outline | Three Mincho/Gothic regular/bold samples byte-match an independent Unicode GDI oracle. Immediate and live text now obey retained ordering, alpha/tint/fade, transforms, clipping, capture, HIDEWIN suspension, partial erase/republication, and reset. Non-Windows/non-932 runs report why exact selection failed and atomically retain the old Label presentations; they do not claim GDI parity | Add an explicitly non-identical portable backend and face-substitution policy, then migrate History/wait-indicator presentation and remove the remaining Label compensations. Keep the GDI project out of non-Windows deliverables rather than hiding failed exact selection |
|
||||
| ADV font discovery/raster fidelity | `Age.Engine.Text` remains OS-neutral. Godot selects the separate `Age.Engine.Text.Windows` backend for immediate `0x204`/`0x205` strings, live ADV, and retained History when Windows ACP 932 is available; exact masks are cached, composited into layout/numbered RGBA surfaces, and published through ordinary retained handles. The wait atlas is likewise bound at its script-configured handle and no longer uses a detached Godot node. The fallback loads Windows `MS 明朝`/`MS ゴシック` when available and otherwise chooses the Japanese/default font with FreeType embolden and a Godot outline | Three Mincho/Gothic regular/bold samples byte-match an independent Unicode GDI oracle. Immediate, live, History, and wait-marker presentation now obey retained ordering, alpha/tint/fade, transforms, clipping, capture, HIDEWIN suspension, partial erase/republication, reset, and History teardown. Non-Windows/non-932 runs report why exact text selection failed and atomically retain the old Label presentations; they do not claim GDI parity | Add an explicitly non-identical portable backend and face-substitution policy, then remove the unavailable-rasterizer Label fallback and its remaining overlay compensations. Keep the GDI project out of non-Windows deliverables rather than hiding failed exact selection |
|
||||
| Filesystem semantics | Several filename and containment comparisons use `OrdinalIgnoreCase`; installed assets are conventionally uppercase | Needs validation on case-sensitive filesystems; may hide casing or containment mistakes | Add Linux/macOS tests with mixed-case synthetic roots and use filesystem-appropriate containment rules |
|
||||
| Save/profile/settings storage | `Sys4PersistencePaths` models AGE's independent `SAVEPATH` and `REGFILEPATH` resolutions. Godot replaces Himegari's related profile directory with `user://`, yielding `user://SAVE` for native S3SD/S4SD/S3RT files and thumbnails plus `user://SYS4REG.INI` for the BOM-less CP932 options file; the preserving writer changes only its nine `[sound]` keys | Save payloads and engine options are isolated together without changing either native format. Native/drop-in resolution remains available through `USEAPPDATAFOLDER` plus both SYS4INI paths. A single-root override is rejected when `SAVEPATH` is not beneath `REGFILEPATH`, preventing cross-profile guesses | Expose explicit profile/native selection through the future launcher and allow independent overrides for profiles whose two native paths are unrelated. Validate CP932 availability, replace/flush, case, permissions, and interrupted-write behavior on each export target |
|
||||
| Game-install and repository discovery | `GameRootSelection` accepts `--game-root`, then probes the executable directory and current working directory for `SYS4INI.BIN`; on Unix the frontend prefers inherited shell `PWD` because Godot may change the process directory during project startup. Godot injects the selected root into its catalog and loose-first ALF store. `Paths.cs` remains the development/test locator for generated opcode data, diagnostics, and CLI conveniences | Installed game data no longer depends on the workspace sibling layout, enabling an executable beside `AGE.EXE`, a terminal launch from the install, or a launcher-supplied absolute profile root. A packaged export still needs its generated runtime metadata bundled independently of repository discovery | Add export packaging for the opcode/profile artifacts, let the future profile launcher pass `--game-root`, and run executable-directory/CWD plus case/permission smoke gates on Linux and macOS |
|
||||
|
||||
@@ -628,11 +628,17 @@ primitive, which cannot be made equivalent by choosing another embolden constant
|
||||
reconstruction. The synthesized Godot VM self-test exercises timed exact reveal and reports
|
||||
`live-adv-text=retained-glyphs`; real GPU captures of SC0000 pages 1 and 7 confirm ordinary and voiced
|
||||
dialogue placement/wrapping alongside the immediate speaker-name surface.
|
||||
6. **Migrate History and the ADV wait indicator through the same retained path.** Op `0x1d1` rasterizes and
|
||||
binds into its target layout instead of creating a layout-keyed Label. Bind the configured wait atlas at
|
||||
the op-`0x212` handle so it follows native z-order and source-cell animation. Once SC0000, HISTORY,
|
||||
STUDY/MAMES, HIDEWIN, and BUNKI pass, delete the game-text Label pools and the modal/raw-callback visibility
|
||||
exceptions whose only purpose was compensating for detached overlays.
|
||||
6. **Migrate History and the ADV wait indicator through the same retained path. — Completed
|
||||
2026-07-30.** Op `0x1d1` now rasterizes each HISTORY row into its target layout surface and publishes its
|
||||
native glyph interval through ordinary `GfxState` bindings. Row reset, wheel redraw, the broad native exit
|
||||
erase, recording re-enable, and surface release all remove the transient presentation without changing
|
||||
the persisted backlog. The configured wait atlas now binds at op `0x212`'s handle, advances source cells
|
||||
only on the configured frame boundary, participates in op-`0x20a` republication and HIDEWIN suspension,
|
||||
and disappears when the wait service stops. The standalone Godot wait `TextureRect` and its raw-callback
|
||||
visibility exception are gone. Exact History no longer enters the layout-keyed Label pool; that code and
|
||||
the live/immediate Label pools remain solely as the explicit unavailable-rasterizer fallback until step 7
|
||||
supplies the portable glyph backend. Focused lifecycle tests, all 579 engine tests, the exact History
|
||||
Godot self-test, and a real SC0000 Vulkan capture cover the retained path.
|
||||
7. **Complete and select the portable backend.** Spike the smallest maintainable way to obtain portable
|
||||
font masks/metrics (Godot/TextServer offscreen extraction versus a bounded FreeType-compatible adapter)
|
||||
before choosing a dependency. Define face substitution and raster policy as profile/configuration data,
|
||||
|
||||
Reference in New Issue
Block a user