Add validated Linux Godot export
This commit is contained in:
@@ -124,6 +124,11 @@ S:\Game Hacking\Eushully\Himegari\ ← workspace root (three siblings)
|
||||
and TITLE-only F4 debug scene launcher
|
||||
```
|
||||
|
||||
The Godot deliverable includes `Himegari.sln` because Godot's .NET exporter requires a solution,
|
||||
`export_presets.cfg` for the Linux x86_64 target, and `build/.gdignore` so disposable capture frames below
|
||||
the project do not enter its import or export scan. `tools/export-linux-x64.ps1` produces and validates the
|
||||
complete disposable artifact under `build/export/linux-x64/`.
|
||||
|
||||
The disposable `build/page-map-<SCENE>.jsonl` files are produced by editor/development Godot runs and map
|
||||
runtime ADV page ordinals to their authoritative script offsets for `tools/locate_page.py`. Packaged exports
|
||||
have no repository output tree and write their automatic maps below `user://diagnostics/page-maps` instead.
|
||||
|
||||
@@ -28,10 +28,13 @@ The VM and content pipeline are already mostly platform-neutral:
|
||||
process and rejects unreserved architectures instead of silently looking in the wrong directory.
|
||||
|
||||
The sole movie path now uses the project-owned FFmpeg C ABI rather than a Windows multimedia API. Reproducible
|
||||
Windows-x64 and Linux-x64 native bundles are built and staged; the Linux ABI and complete installed corpus pass
|
||||
under WSL, but an exported Linux Godot executable has not yet received window/audio/font/filesystem smoke tests.
|
||||
The accepted DirectShow fallback was deleted after the corpus and audible LOGO/OP/CHAPTER gates passed. There
|
||||
are also softer Windows assumptions that should be tested or replaced before claiming portable exports.
|
||||
Windows-x64 and Linux-x64 native bundles are built and staged. A committed Godot 4.7 .NET Linux-x64 preset and
|
||||
guarded exporter produce a self-contained artifact whose headless self-test passes under Ubuntu/WSL with the
|
||||
portable TextServer backend and installed Noto CJK fonts. This establishes the packaged loader, archive, font,
|
||||
managed host, and teardown paths; a real Linux desktop must still validate window/input/audio behavior and a
|
||||
case-sensitive install/profile. The accepted DirectShow fallback was deleted after the corpus and audible
|
||||
LOGO/OP/CHAPTER gates passed. There are also softer Windows assumptions that should be tested or replaced before
|
||||
claiming portable exports.
|
||||
|
||||
## Dependency inventory
|
||||
|
||||
@@ -39,13 +42,13 @@ are also softer Windows assumptions that should be tested or replaced before cla
|
||||
|---|---|---|---|
|
||||
| SYS4INI per-game startup profile | `Sys4AssetCatalog` parses and retains the bounded ordered startup trailer; `Sys4LogicalCanvas` applies `SCREENX`/`SCREENY` with AGE's independent `640x480` fallbacks. Native SYS4INI also carries text, ADV input/skip, save ABI/path, audio, legacy renderer, and Windows registration settings | Godot uses the selected canvas for content scaling, backbuffers/compositor bounds, primary surfaces, layout/input fallbacks, and the default windowed client. `--window-width`/`--window-height` vary only the physical client while preserving the canvas and letterbox policy. The port still does not source `CancelMesSkipOnClick`, `CoexistMesSkip`, cursor/redraw policy, or wheel action ids from the trailer | Validate the existing presentation policy on Linux/macOS window managers. Apply further semantic keys explicitly, translate save roots through the host, and classify DirectDraw/fullscreen-bit and registration/key settings as native compatibility metadata. 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 |
|
||||
| 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 and Linux-x64 both pass the complete 213-payload installed video/audio corpus gate; Windows also passes audible LOGO/OP/CHAPTER playback and real TEST.AGF green-mask decode | Add macOS native builds, distributable source-offer packaging, and Linux/macOS Godot runtime smoke gates |
|
||||
| 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 and Linux-x64 both pass the complete 213-payload installed video/audio corpus gate. The Linux library bundle is present in a validated Godot export; Windows also passes audible LOGO/OP/CHAPTER playback and real TEST.AGF green-mask decode | Add macOS native builds, distributable source-offer packaging, and real Linux/macOS window/audio movie 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. 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, and target-aware builds stage either the win-x64 or Linux-x64 native bundle | Add macOS native builds and Linux/macOS in-engine 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. On compatible ACP-932 Windows, `auto` selects the separate exact `Age.Engine.Text.Windows` GDI gray-4 backend. Otherwise Godot TextServer supplies Unicode masks and metrics from ordered system-font substitutions in `godot/config/himegari-text-rendering.json`; this policy is explicitly not GDI pixel-exact. Immediate `0x204`/`0x205`, live ADV, retained History, and the wait atlas all enter ordinary RGBA surfaces/retained handles | Three Mincho/Gothic regular/bold samples byte-match an independent Unicode GDI oracle. Forced exact and forced portable self-tests cover immediate, live, and History rasterization, bounded caching, complete-line materialization, retained ordering, alpha/tint/fade, transforms, clipping, capture, HIDEWIN suspension, partial erase/republication, reset, and teardown. Gameplay `Label` pools and overlay projection are gone | Produce and smoke-test Linux/macOS exports, confirm installed family availability/fallback selection there, and keep the GDI project out of non-Windows deliverables |
|
||||
| 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, runtime metadata, 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. `Himegari.csproj` embeds generated `build/opcodes.json`, and the frontend loads that assembly resource rather than `Paths.OpcodesJson`. `Paths.cs` remains a development/test locator; its page-map use is compiled only for `TOOLS` builds | Installed game data and packaged VM metadata no longer depend on the workspace sibling layout. An executable can sit beside the game, inherit a terminal-launched install directory, or receive a launcher-supplied absolute profile root. Exported automatic page maps use `user://diagnostics/page-maps`; editor/development runs preserve `build/page-map-<SCENE>.jsonl` | Add the export preset/artifact pipeline, let the future profile launcher pass `--game-root`, and run executable-directory/CWD plus case/permission smoke gates on Linux and macOS |
|
||||
| Game-install, runtime metadata, 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. `Himegari.csproj` embeds generated `build/opcodes.json`, and the frontend loads that assembly resource rather than `Paths.OpcodesJson`. `Paths.cs` remains a development/test locator; its page-map use is compiled only for `TOOLS` builds | Installed game data and packaged VM metadata no longer depend on the workspace sibling layout. The Linux export passed an explicit absolute game root outside the repository and read the installed archives. Exported automatic page maps use `user://diagnostics/page-maps`; editor/development runs preserve `build/page-map-<SCENE>.jsonl` | Let the future profile launcher pass `--game-root`, and run executable-directory/CWD plus case/permission smoke gates on Linux and macOS |
|
||||
| Archive parity oracle | One integration test launches `bin/BinExtractALF.exe` | Windows-only test helper, not a shipped runtime dependency | Skip/replace on non-Windows CI; runtime ALF/AAI readers do not depend on it |
|
||||
| Native RE tools | Frida/Ghidra helpers target the original `AGE.EXE`; supporting utilities include Windows executables and Windows command conventions | Development/research only | Keep separate from export requirements; document platform prerequisites per tool |
|
||||
| Python workflow | Operating guide uses Windows `py -3.11` invocation | Developer workflow only | Add equivalent `python3` instructions if non-Windows development becomes active |
|
||||
@@ -198,9 +201,17 @@ five required SONAME libraries and license under disposable `build/native/linux-
|
||||
2.28, matching the provider baseline enforced by the build script. A self-contained Linux corpus-gate executable
|
||||
under Ubuntu 20.04 decoded all 213 installed payloads with 0 failures in 10.696 seconds. A zero-warning
|
||||
`ExportRelease` Linux-target assembly build staged the shim, five libraries, and license beside `Himegari.dll`
|
||||
without the Windows GDI assembly or DLLs. These gates establish Linux loader/ABI/decoder and managed staging
|
||||
compatibility; they do not yet establish an exported Godot window, live audio timing, font realization, or
|
||||
case-sensitive install/profile behavior.
|
||||
without the Windows GDI assembly or DLLs.
|
||||
|
||||
The Godot Linux-x64 artifact pipeline landed the same day. `godot/export_presets.cfg` and the .NET-export-required
|
||||
`godot/Himegari.sln` are committed; `tools/export-linux-x64.ps1` replaces only its exact disposable output,
|
||||
performs a bounded Godot shutdown, verifies the complete artifact, and rejects Windows-only runtime files.
|
||||
`godot/build/.gdignore` prevents historical capture frames from being imported and packed. The exported ELF64
|
||||
x86-64 executable, PCK, self-contained .NET runtime, and local FFmpeg bundle passed `--selftest` under Ubuntu/WSL
|
||||
against an explicit installed-game path using the portable text backend, with a clean exit and no Godot errors or
|
||||
leaked-object warning. Minimal Ubuntu required `fonts-noto-cjk`; before installation the exact same artifact
|
||||
failed explicitly on Japanese glyph U+59EB. This gate does not establish a real Linux desktop window, physical
|
||||
input, audible output/timing, or case-sensitive install/profile behavior.
|
||||
|
||||
The Windows-x64 installed-corpus gate passed on 2026-07-22 with the pinned dependency: all 213 signature-selected
|
||||
MPEG payloads opened and reached EOF under a 30-second per-item bound. It decoded all 15,788 frames across twelve
|
||||
|
||||
@@ -321,6 +321,33 @@ resolved against the current working directory, and repeated overrides use the l
|
||||
Godot preserves the shell launch directory through inherited `PWD` because editor/project startup may
|
||||
change the process directory before managed code runs.
|
||||
|
||||
**Linux x64 export** uses the committed `godot/export_presets.cfg` preset and `godot/Himegari.sln`:
|
||||
|
||||
```powershell
|
||||
.\tools\export-linux-x64.ps1 -GodotConsole <path-to-Godot-4.7-.NET-console.exe>
|
||||
```
|
||||
|
||||
Install the Godot 4.7 .NET export templates first and build the pinned native bundle under
|
||||
`build/native/linux-x64` with the commands in “Native FFmpeg movie shim” above. The script safely replaces
|
||||
only `build/export/linux-x64`, invokes the release preset with a bounded headless shutdown, verifies the
|
||||
executable/PCK/self-contained managed payload plus all six project-owned FFmpeg files, and rejects the
|
||||
Windows GDI adapter and Windows FFmpeg DLLs. Output is `build/export/linux-x64/Himegari.x86_64` with its
|
||||
PCK and `data_Himegari_linuxbsd_x86_64/` runtime directory. Do not relocate only the executable; the three
|
||||
items are one artifact.
|
||||
|
||||
The portable font policy requires a Japanese-capable system font. A minimal Ubuntu install needs, for
|
||||
example, `sudo apt install fonts-noto-cjk`; absence is a startup failure rather than silent missing-glyph
|
||||
output. The exported headless smoke command is:
|
||||
|
||||
```bash
|
||||
./build/export/linux-x64/Himegari.x86_64 --headless -- \
|
||||
--selftest --game-root "/absolute/path/to/Himegari_Game" --text-backend portable
|
||||
```
|
||||
|
||||
This validates the packaged .NET/Godot runtime, archive access, portable text realization, retained
|
||||
rendering logic, audio payload parsing, and teardown. It does not validate a desktop window, physical
|
||||
input, or audible output; run those gates on a real Linux desktop.
|
||||
|
||||
With the exported executable placed in an AGE install, a no-argument launch therefore uses that install
|
||||
and starts the persistent `SYSTEM4.BIN` root naturally. Direct development runs are hosted by the Godot
|
||||
editor executable, so pass `--game-root <install>` after Godot's `--` separator; the local
|
||||
|
||||
Reference in New Issue
Block a user