immediate-mode GL (glBegin/glVertex3f/glEnd and friends) from scratch on top of GLES, since GLES has none of it. That code compiled but was never actually exercised - no on-screen verification was possible without real Quest hardware - making it the biggest unverified risk in the port. Replace it with GL4ES (MIT-licensed, prebuilt into the build image), a mature desktop-GL-on-GLES translation library used by other Quest/Android game ports for exactly this problem. This cuts 04-android-opengl-es-render.patch by half, deleting the hand-written vertex-accumulation emulation entirely; alpha test, point sprites, and point size stay on their existing GLES-native fixes rather than trusting GL4ES's shakier custom-shader interop for those. Bump build-image/VERSION to 3 - a fresh image with GL4ES cross-compiled for arm64-v8a was built and make apk verified successfully against it.
Questshock
An open source project to play the classic 1994 System Shock on a VR headset, built on top of Shockolate, a cross-platform port of the original game.
Layout
engine/- a vendored snapshot of the Shockolate engine source. Built via Docker; see below.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 soundfont) is fetched and built once into this image - compilingengine/itself needs no network access.build-image.sh/run-image.sh/upload-image.sh- build the image, run it to compile the engine, and push it to a registry, respectively.res/assets/- where you place your own purchased copy of the game (see below);res/assets/extract_assets.shextracts it intoss_ee/.res/run.sh- the launcher script, copied intodist/on build.Makefile- assemblesdist/, a self-contained runnable copy of the game, out of the compiled engine and the extracted assets. Also buildsdist/questshock-<version>-linux-<arch>.tar.gz, a redistributable package that omits the proprietary game assets (make package), anddist/questshock-debug.apkfor the Quest (make apk).android/- the Quest app (JavaSDLActivityglue, Gradle project).android/engine-patches/holds the one small patch needed to buildengine/as an Android shared library instead of a desktop executable- applied to a scratch copy at build time;
engine/itself is never modified.
- applied to a scratch copy at build time;
Building
# 1. Build the engine build-image (once, or after build-image/ changes)
./build-image.sh
# 2. Get your own copy of the game data (see "Game assets" below), then:
res/assets/extract_assets.sh
# 3. Compile the engine and assemble dist/
make dist
# 4. Play
dist/run.sh
make dist always recompiles the engine from the current engine/
source (via run-image.sh), so a fresh build-image plus a re-run of
make dist is all that's needed after pulling engine changes.
Game assets
System Shock's game data is not included in this repository and cannot
be redistributed - you need to own a copy. Buy System Shock: Enhanced
Edition on gog.com, download the offline
installer (a .exe), and drop it into res/assets/. Then run
res/assets/extract_assets.sh, which pulls the classic game's data and
sound files out of the installer (it's an Inno Setup package; the actual
game data lives inside it in a zip-format sshock.kpf) into
res/assets/ss_ee/. That script needs innoextract and unzip; if
they aren't installed locally it falls back to running the extraction in
a throwaway Docker container instead.
Packaging
make package builds dist/questshock-<version>-linux-<arch>.tar.gz: the
compiled binary, its runtime libraries, shaders, a default MIDI
soundfont, license information, and res/GET_ASSETS.txt in place of the
actual game data (which the tarball never includes). Version comes from
the current git tag (push a vX.Y.Z tag to drive a release); without one
it builds an untagged 0.0.0-dev+<sha> placeholder.
A Gitea Actions workflow (.gitea/workflows/build.yml) builds this
package on every push, using the build-image as its container (so no
extra setup is needed in CI beyond the image itself), and publishes the
resulting tarball to dl.ladkau.de.
Playing on Meta Quest
make apk builds dist/questshock-debug.apk - a plain (non-VR) Android
app that runs as a flat, floating panel in the Quest's Home environment,
same as any other sideloaded Android app. It's not a head-tracked 6DoF VR
port (that's a much larger, separate undertaking); play with a Bluetooth
mouse/keyboard connected to the headset.
- Install the APK with SideQuest (or
adb install). - Launch it once. It'll ask for storage permission, then create
/sdcard/questshock/and extract its own bundled files (shaders, a default MIDI soundfont) there -res/data/andres/sound/are deliberately left missing, since that's the proprietary game data. - With the Quest connected to a PC, use SideQuest's file browser (or any
MTP file manager) to copy your own
res/data/andres/sound/(see/sdcard/questshock/GET_ASSETS_QUEST.txt, extracted in step 2, for exactly what's needed and where it comes from) into/sdcard/questshock/res/. - Launch it again.
License
The original tooling in this repository (the Docker build image, build
scripts, Makefile, asset extraction script, and the Quest app in
android/ - aside from org/libsdl/app/, see below) is licensed under
the MIT License.
android/app/src/main/java/org/libsdl/app/ is copied from
SDL2's own android-project template and is
zlib-licensed, same as SDL2 itself.
The Quest build also bundles GL4ES
(lib/arm64-v8a/libGL.so in the APK, prebuilt unmodified into the build
image), which translates the engine's desktop-style OpenGL calls into
GLES/EGL and is MIT-licensed.
The vendored engine snapshot in engine/ is
Shockolate, which is licensed
under the GNU GPLv3 (see engine/LICENSE) - it is included unchanged
and is not relicensed by this project's MIT license. Any build or
distribution of the compiled engine must comply with the GPLv3.
The game assets extracted into res/assets/ss_ee/ are proprietary,
copyrighted game data owned by their respective rightsholders - they are
never committed to this repository (see .gitignore) and must be
supplied by each user from their own legitimate purchase.
