Extends the MDL system beyond text overrides: bitmaps/<label>.json names a model/scale and resource list, and mdlp extracts each resource's frames, runs them through an ONNX Runtime CPU upscaler baked into mdlp-image, re-quantizes to the game's palette, and writes the result back - same build-time pipeline as message overrides. Adds animgallery, a standalone viewer that renders any data directory's animated resources as an HTML/GIF gallery with a checkbox-driven MDL JSON generator, and -only-changed to preview just what a mod overrides against the base game. Fixes a real data race in hacked's ChangeNotifier.hashAll() (found via go build -race causing non-deterministic resource counts), via a new numbered patch rather than editing the vendored source. Adds engine-patches/, a general-fixes counterpart to android/engine-patches/ now staged and applied to the desktop builds too (previously unpatched): a real GL_UNPACK_ROW_LENGTH stride bug, an audio error-logging improvement, and two critter-rendering fixes - mod art was losing to the base game's own re-opened resource files, and critters rendered at the wrong size/position once that was fixed, both from how the billboard renderer derives on-screen size and placement straight from bitmap pixel dimensions. Updates README.md and AGENTS.md to document engine-patches/.
This commit is contained in:
@@ -69,7 +69,11 @@ Section "5.1. Installing and playing" has the details.
|
||||
## 2. Layout
|
||||
|
||||
- `engine/` - a vendored snapshot of the Shockolate engine source. Built
|
||||
via Docker; see "4. Desktop build" below.
|
||||
via Docker; see "4. Desktop build" below. `engine-patches/`
|
||||
holds general (not Android-specific) fixes applied to a scratch copy at
|
||||
build time - same convention as `android/engine-patches/` below, but
|
||||
for the Linux/Windows desktop builds; `engine/` itself is never
|
||||
modified. See "4.4. Engine patch reference" below for what each one does.
|
||||
- `build-image/` - the Dockerfile (and supporting scripts) for the engine
|
||||
build environment. Every third-party dependency the engine needs to
|
||||
compile (SDL2, SDL2_mixer, the fluidsynth-lite MIDI synth, a MIDI
|
||||
@@ -244,10 +248,11 @@ of `build-image/Dockerfile`) - no Windows machine, Wine, or VM involved
|
||||
in building it. `engine/CMakeLists.txt` already has working `WIN32`/
|
||||
`MINGW` branches from Shockolate's own upstream Windows build (built
|
||||
natively via Git Bash/MinGW on a real Windows machine - see
|
||||
`engine/build_win64.sh`/`engine/appveyor.yml`), so unlike the Quest
|
||||
build's `android/engine-patches/`, no source patching is needed here -
|
||||
this cross-compiles those same branches offline and reproducibly, from
|
||||
Linux, via Docker.
|
||||
`engine/build_win64.sh`/`engine/appveyor.yml`) - this cross-compiles those
|
||||
same branches offline and reproducibly, from Linux, via Docker. It applies
|
||||
the same `engine-patches/` series the Linux build does (section
|
||||
4.4); unlike the Quest build's `android/engine-patches/`, no
|
||||
Windows-specific source patching is needed on top of that.
|
||||
|
||||
`dist-win/`/the packaged `.zip` ship `systemshock.exe` with its DLLs
|
||||
(SDL2, SDL2_mixer, GLEW, fluidsynth-lite, plus the MinGW pthread runtime)
|
||||
@@ -306,6 +311,75 @@ Both CI systems read the key from these secrets: `ANDROID_KEYSTORE_BASE64`,
|
||||
produces a debug APK and the GitHub build fails on a tag. `*.jks` and
|
||||
`*.keystore` are git-ignored.
|
||||
|
||||
### 4.4. Engine patch reference
|
||||
|
||||
`engine-patches/` (applied to a scratch copy of `engine/` by
|
||||
`build-image/build-engine.sh` and `build-engine-win.sh`) is a plain,
|
||||
numbered patch series, same convention as the Quest build's
|
||||
`android/engine-patches/` (section 5.4) - `engine/` itself is never
|
||||
modified. It only carries fixes that are general (not Android-specific);
|
||||
anything Quest/OpenXR-only belongs in `android/engine-patches/` instead,
|
||||
which the desktop build does not apply.
|
||||
|
||||
- **`01-desktop-texture-row-length.patch`** - `opengl_cache_texture()`/
|
||||
`set_texture()` (`OpenGL.cc`) passed the original 8-bit bitmap's own row
|
||||
stride (`bm->row`) to `GL_UNPACK_ROW_LENGTH`, describing the wrong
|
||||
layout to OpenGL for the actually-uploaded buffer (a separately
|
||||
allocated RGBA32 conversion, `converted->pixels`) whenever the two
|
||||
strides differ - corrupting the texture upload. Uses
|
||||
`converted->pitch / 4` instead.
|
||||
- **`02-desktop-audio-error-detail.patch`** - logs `SDL_GetError()`
|
||||
alongside "Couldn't open audio device" instead of just the bare message.
|
||||
- **`03-desktop-fix-mod-resource-priority.patch`** - `LoadModFiles()`
|
||||
(`Modding.c`) registers mod resource files once at startup, but two
|
||||
places re-open the base game's own object/texture art files afterward -
|
||||
and opening a resource file re-registers every ID it contains,
|
||||
unconditionally, with no check for whether a mod already claimed it (see
|
||||
`ResReadDirEntries()` in `resfile.c`). That silently reverted any mod
|
||||
override for that art back to the base game's own graphics, twice over:
|
||||
`obj_set_secondary_properties()` (`objsim.c`) re-opens `objart2.res`/
|
||||
`objart3.res` transiently, just to read frame-count metadata; later in
|
||||
the same startup sequence, `load_dynamic_memory()` (`cybmem.c`) re-opens
|
||||
`texture.res`/`handart.res`/`objart2.res`/`objart3.res` again, this time
|
||||
persistently - these are the handles actual gameplay renders from, so
|
||||
this second point is what mattered for the mod override actually
|
||||
showing up in-game. Fixed by re-running `LoadModFiles()` right after each
|
||||
place's re-opens, so mods regain priority. Re-registering a mod file's
|
||||
resource IDs means actually reopening it (there's no "just re-register"
|
||||
primitive), so `LoadModFiles()` now closes each mod file's previous
|
||||
handle first - one open handle per mod file at a time, rather than
|
||||
leaking a fresh file slot on every repeat call (a new game or a loaded
|
||||
save can both re-run this whole sequence).
|
||||
- **`04-desktop-fix-critter-sprite-scale.patch`** - critters render as
|
||||
camera-facing 2D billboards (`gameobj.c`'s `FAUBJ_CRIT` case), not
|
||||
UV-mapped 3D polygons, and their on-screen size comes directly from the
|
||||
bitmap's own pixel width/height (`Bitmap.c`'s `g3_bitmap_common()`, via
|
||||
`_g3d_bitmap_u_anchor`/`_g3d_bitmap_v_anchor` and `bm_w`/`bm_h`) - so a
|
||||
mod that replaces a critter's art with a higher-resolution bitmap for
|
||||
more detail made the critter itself render bigger, proportionally to
|
||||
the resolution increase. Fixed by caching every critter view's base-game
|
||||
bitmap size (`objsim.c`'s `cache_critter_native_size()`/
|
||||
`get_critter_native_size()`, keyed by resource ID) while
|
||||
`objart2.res`/`objart3.res`'s base-game data is still the active
|
||||
resolver in `obj_set_secondary_properties()` (before patch 03's
|
||||
`LoadModFiles()` call hands priority to a mod), then using that cached
|
||||
size instead of the bitmap's own (possibly modded) dimensions when
|
||||
computing the sprite's on-screen extent - threaded through
|
||||
`_fr_draw_bitmap()` and `g3_light_anchor_bitmap()`'s new `native_w`/
|
||||
`native_h` parameters, consumed and reset by `g3_bitmap_common()` so an
|
||||
unrelated bitmap draw never inherits a stale override. A mod's higher
|
||||
resolution now only changes visible detail, not the object's size.
|
||||
This depends on the mod's bitmap keeping a real anchor point in its own
|
||||
`Header.Area`, in the original, un-upscaled unit space (see
|
||||
`modding/src/mdlp/upscale.go`'s `imageToBitmap()`) - `_fr_draw_bitmap()`
|
||||
only forwards `native_w`/`native_h` down the anchor-aware rendering path
|
||||
when given a positive anchor, so a zeroed-out one silently skips this
|
||||
patch's override entirely, and an anchor scaled to the mod's higher
|
||||
resolution instead of left in the original unit space visibly offsets
|
||||
the sprite from where it should sit, since it shares its coordinate
|
||||
system with this patch's own size override rather than with the
|
||||
bitmap's real pixel dimensions.
|
||||
|
||||
## 5. Android / Quest build
|
||||
|
||||
**Prerequisites:**
|
||||
|
||||
Reference in New Issue
Block a user