# CorsixTH browser source and modified-library rebuild

This source package contains the exact CorsixTH 0.70.1 source, all declared
browser patches, Lua/LFS/LPeg, FFmpeg 7.1.1, SDL_mixer 2.8.0, eight browser-port
source archives and prepared trees, Emscripten 5.0.7 runtime/library/tool source,
FreePats 20060219, fflate 0.8.3's preferred TypeScript source, and the complete
Leaf browser adapter. Native output hashes
are in `completed-build.json`; archive/fragment hashes are in
`source/manifest.json`. Every fragment is at most 20 MiB. Original library/file
notices remain in the archives; convenient full license texts are in `legal/`.

Theme Hospital data is **not included**. Building the engine does not require
the private demo archive, a pre-existing repository checkout, an account or a
game server. To play, select legally obtained game files through the local ZIP /
installation-folder picker. The browser never uploads those files.

## Restore and build

Requirements: Docker with Linux/amd64 support, Python 3, Node.js 24 and npm.
The pinned official Emscripten base image includes the compiler. The included
Dockerfile adds CMake/Ninja and ordinary build tools. It reconstructs the build
environment independently of the private, locally named original build image.
The original image fingerprint is retained as provenance, not a required
download. LLVM/compiler/system build tools may be obtained through that image.

From the directory containing this package:

```sh
python3 restore.py . ../corsixth-source-workspace
cd ../corsixth-source-workspace
python3 scripts/expansion/prepare-corsixth.py --verify
bash scripts/expansion/build-corsixth.sh --source-rebuild
```

Restore verifies and concatenates the fragments before extracting, prepares the
six declared engine patches, and reconstructs the original dependency inputs.
It refuses to overwrite a nonempty workspace. The build creates a separate
`leaf-corsixth-source-rebuild-cache` volume, loads the supplied exact prepared
codec sources, and compiles all libraries and the native engine. It does not
depend on the release build's cached libraries. Build commands and original
configuration are also included in the integration archive's `configuration/`.

The completed pair is in `artifacts/expansion/corsixth/build/CorsixTH/`.
`record-corsixth-build.py` records new hashes only after a successful native
build. Byte-identical output is not required for a modified-library build.

## Modify libraries and relink

After restoration and the baseline verification, edit the desired source:

- FFmpeg: `artifacts/expansion/corsixth/deps/ffmpeg/`.
- Lua, LFS or LPeg: their directory under `artifacts/expansion/corsixth/deps/`.
- Browser codecs / SDL / FreeType / PNG / zlib: the corresponding tree under
  `artifacts/expansion/corsixth/browser-ports/`.
- The replaced TiMidity `readmidi.c`: edit
  `artifacts/expansion/corsixth/deps/sdl_mixer/src/codecs/timidity/readmidi.c`.
  This file replaces its SDK archive object. An unchanged original gets the
  declared arithmetic repair; a modified file is preserved without that repair.

Run `build-corsixth.sh --source-rebuild` again to compile and relink your version.
Every source rebuild invalidates the SDK's cached browser-port library archives
so codec edits take effect; ordinary compiler/system libraries can be reused.
If changing FFmpeg configure options or performing a completely clean native
build, remove the standalone workspace's `artifacts/expansion/corsixth/build/`
first. This is a user-owned rebuild workspace; do not remove another checkout's
build directory/cache.
Modified-library mode deliberately permits changed inputs. The normal release
build retains strict pin verification. There is no signature or runtime
checksum restriction preventing a player from using a rebuilt native pair.

## Play the rebuilt engine

Install the two browser build dependencies in the new workspace:

```sh
npm install --no-save --package-lock=false --ignore-scripts esbuild@0.28.1 fflate@0.8.3
python3 scripts/expansion/stage-corsixth-source-player.py
python3 scripts/expansion/serve-corsixth-probe.py --port 50204
```

Open `http://127.0.0.1:50204/?import-required=1`, choose the original game ZIP or
installation folder, then start. This is a functional source-rebuild preview;
the final public player has its own presentation. The preview never serves a
private demo archive. The local server provides the cross-origin isolation
headers required by native threads. Native saves remain in the `corsixth`
browser namespace; diagnostic tests use their separate namespaces.

## Notices

CorsixTH and its native platform patches retain the upstream MIT terms and
individual asset notices. Lua, LFS, LPeg and fflate use their included permissive
licenses. FFmpeg is built without GPL/nonfree components and uses LGPL 2.1 or
later; mpg123 uses LGPL 2.1. The browser adapter includes the shared persistence
module under GPL 3 or later. SDL/TiMidity, FreeType, PNG, Ogg, Vorbis and zlib
retain their individual notices. FreePats is GPL 2 or later with the included
composition exception; its editable patch/config files are supplied unchanged.

The complete source and rebuild/relink path are supplied for the LGPL libraries
as well as the adapter. Modification and debugging of library changes are
permitted. The LGPL static-link exception is in section 6 of
`legal/LGPL-2.1.txt`. See the [FFmpeg distribution guidance](https://ffmpeg.org/legal.html).
No permission to redistribute original Theme Hospital data is implied.

Public packaging and clean rebuild verification are separate from the earlier
private clinic checks. The source package does not prove completion of public
player design, retail-data tests, further treatment/cure flows or deployment.

## Verified source checkpoint — 10 October 2026

The package independently verifies **18 original/integration source archives**
and **20 bounded fragments**, approximately **107 MB** total, all prepared
SDK/library file inventories and the original release native fingerprints.
A new workspace was restored entirely from that package, with no private demo
archive or previous checkout. A clean native build completed all **80 engine
steps** using the reconstructed official-image environment and a new library
cache. A harmless FFmpeg decoder-label edit appeared in its actual Wasm.

A second source rebuild changed an mpg123 error-message label after the first
successful build. The cache invalidation rebuilt the codecs; both edited labels
are present in the resulting **5,072,973-byte Wasm**, SHA-256
`b54d71955353ea605f5e2362f0915ad914033ed7f8ac62b924d528a581b4c632`.
This modified pair is verification output, not the production engine. The
original 5,072,877-byte release pair remains unchanged. An unchanged incremental
source rebuild also reproduced the first modified pair byte for byte.

The standalone preview serves no original game archive. **Eight desktop /
Retina-phone cases pass in 22.4 seconds**, with locally selected original data:
invalid ZIP rejection/recovery, retention of valid imported files, default-URL
import gating, original Smacker video/PCM/completion and original MIDI PCM.
Neither automatic demo fetch nor API upload occurs. Screenshots were reviewed.
The default-URL gate also stays disabled after a rejected selection.

Full `npm run check` passes **117 files / 1,103 unit tests**, **222 exported
pages** and **24 portal packages** after compilation finishes. A first concurrent
check hit the unchanged 400 MB asset-verification test's five-second timeout;
the unchanged test passes in the final run. Python syntax and shell syntax
checks pass. The pinned patch path rejects changed decoder input; explicit
source-rebuild mode preserves a user-edited decoder byte for byte.

Evidence under ignored `artifacts/expansion/corsixth/`: `source-package-final.log`,
`source-restore.log`, `source-clean-rebuild.log`,
`source-modified-codec-rebuild.log`, `source-clean-completed.json`,
`source-codec-completed.json`, `source-stage.log`, `source-browser.log`,
`check-source.log` and `source-guard.log`. Final source downloads are staged
privately in `source-distribution/`; this checkpoint does not publish them or
register CorsixTH in the catalog.

## Player/clock update

The current integration adds `corsixth-browser-clock.h`, the player UI/CSS and
six declared engine source patches. Normal native output is now 242,946-byte JS
and 5,075,203-byte Wasm; current fingerprints remain in `completed-build.json`.
The native clock bridge supports lifecycle suspension without altering the
original simulation or in-game pause/speed. Earlier modified-library proof
hashes above refer to the preceding source checkpoint, not the current output.
Automatic real document-hide verification remains a separate open release gate.

## Bounded runtime player

The source player now packages original engine/instrument resources in
checksum-pinned fragments of at most 20 MiB, instead of serving an oversized
ZIP. `runtime.json` inventories every resource and the exact completed native
pair. The included browser asset worker verifies and expands these resources
before engine execution; preferred TypeScript and the packing/audit scripts
are included in the integration source archive.

To stage a separate import-only player from a prepared workspace:

```sh
python3 scripts/expansion/stage-corsixth-source-player.py --directory artifacts/expansion/corsixth/source-only-parts
python3 scripts/expansion/verify-corsixth-runtime.py artifacts/expansion/corsixth/source-only-parts --source-only
python3 scripts/expansion/serve-corsixth-probe.py --port 50205 --directory artifacts/expansion/corsixth/source-only-parts
```

The audit compares all resource bytes with original prepared files, not just
the manifest. The separate stage rejects a private demo archive and requires
the user's local game files. This is packaging of the existing verified native
pair; earlier clean and modified-library rebuild evidence remains applicable
to the unchanged native build recipes.

The current integration also contains the persistent browser-save failure
notice and expanded read-only clinic observation. Clinic input covers original
GP/general-diagnosis/pharmacy/staff-room construction, hiring and fax decisions. It reports
pharmacy casebook recoveries without assigning any simulation or RNG field.
These are browser/test adapter changes; the completed native pair and all six
declared native platform patches remain unchanged.

Portable-save integration now includes `corsixth-save-transfer.ts`,
`corsixth-saves-worker.ts` and `lib/persistence/corsixth-saves.ts`. It exports
original written save bytes, checks bounded backup inventories before mounting,
previews conflicts, requires explicit replacement and preserves rollback bytes.
Source-only staging bundles the same save worker. These changes do not require
rebuilding the native engine or libraries; the completed native fingerprints
remain unchanged.
