Commit Graph
701 Commits
Author SHA1 Message Date
izzy2lostandClaude Opus 5 68d8c74c33 TESTING ONLY: check the APK actually carries the game data
An APK missing any asset GameAssets.kt opens by name installs and launches
fine, then fails on the device during staging — which is how two of them
reached test builds already. Fail the job instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:44:28 -04:00
izzy2lostandClaude Opus 5 7122a674bf TESTING ONLY: add an Android-only CI workflow
GenerateBuilds runs on every push and builds six platforms, which is a long
wait when all you want is an APK to sideload. This builds ghostship.o2r and a
debug APK on its own, on demand or when something the APK contains changes.

Not for the upstream PR either — GenerateBuilds already has a build-android
job. This exists to shorten the device-test loop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:44:28 -04:00
izzy2lostandClaude Opus 5 1d8efef49c TESTING ONLY: point libultraship at the fork with the arm64 tagging fix
Not for the upstream PR. gfx_check_image_signature() rejects Android's tagged
heap pointers, so without this the skybox, title background and HUD render as
noise. Drop this commit once Kenix3/libultraship has the fix and the pin can
move back to an upstream commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:44:28 -04:00
izzy2lostandClaude Opus 5 4d972fd9f7 Check the release APK carries the assets the launcher needs
An APK missing any asset GameAssets.kt opens by name installs and launches
fine, then fails on the device during staging — losing the game data to an
asset merge that had nothing to merge, or a source file to gitignore, both
left the build green. Fail the job instead of shipping it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:43:27 -04:00
izzy2lostandClaude Opus 5 eebb677628 Android: ship the mods placeholder that gitignore was eating
mods/ is ignored repo-wide, which caught the placeholder the launcher copies
into the player's mods directory. It survived locally as an untracked file and
never reached a clean checkout, so CI built an APK without it.

The consequence was out of proportion to a hint file: staging opens it after
unpacking gamedata.zip, the missing asset threw, and the whole of
stageBundledAssets reported failure without writing its stamp — so a build
that had extracted everything correctly still came up unusable, and re-ran the
unpack on every launch. Writing the placeholder is now allowed to fail on its
own.

The gitignore negation follows the one already there for /src/port/mods/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:43:27 -04:00
izzy2lostandClaude Opus 5 3c2bc3ad09 Android: generate the packaged game data through the variant API
The Torch recipes and ghostship.o2r reached the APK as a source-set srcDir
pointing at a directory two tasks filled in. AGP takes the path from that but
not the dependency on the tasks producing it, so packGameData and
stampGameData were absent from the assembleDebug task graph entirely. A clean
checkout merged assets against an empty directory and shipped an APK holding
only gamecontrollerdb.txt and mods/, and the build stayed green because the
missing-archive check never ran to say otherwise. It only worked locally
because an earlier build had left the directory populated.

The two tasks become one PackGameData registered per variant and attached with
addGeneratedSourceDirectory, which is the wiring AGP does follow. It writes
gamedata.zip and the digest beside it into an AGP-owned assets directory,
sorted and at a fixed timestamp so an unchanged zip keeps its digest and the
device does not re-unpack on every update.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:43:27 -04:00
izzy2lostandClaude Opus 5 a4fb8ee186 Android: extract the ROM on device
The player no longer needs a PC. LauncherActivity unpacks the bundled data,
takes a ROM through the document picker, checks it against the supported
SHA-1s, and runs Torch through JNI to produce sm64.o2r — about 27s on a
Pixel 10a. The archive is byte-identical to a host extraction.

GameExtractor gains a GenerateOTRTo() overload taking the two directories
explicitly: the launcher runs before SDL exists, so Ship::Context cannot
resolve a path yet.

The launcher runs in its own process and ends it once the archive is written.
Torch's Companion is deliberately never freed — every platform leaks it, and
its destructor does not survive being run — so ending the process is what
returns that memory before the game starts.

Unpacking the packaged data moves from the engine to the launcher, because
Torch needs config.yml and assets/ymls on disk before the game process starts,
not after. It is the same gamedata.zip from the same Gradle tasks, so the
packaging and the CI artifact are unchanged; AndroidUtils.cpp goes away.

Also adds mods and saves managers behind a button that appears while the
engine menu is open, and fixes edge-to-edge: with targetSdk 36 the system
ignores the old fullscreen flags, so the navigation bar was sitting on top of
the game.

Toolchain moves to NDK 30.0.15729638, SDK 36, Gradle 8.13, AGP 8.13.2 and the
Kotlin DSL, and builds arm64-v8a and armeabi-v7a. CMAKE_BUILD_TYPE=Release is
forced for every variant: the Android plugin builds the release variant as
RelWithDebInfo (-O2), but the root CMakeLists pins Release to -O1
-fno-strict-aliasing because the game's C code is miscompiled above that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:43:16 -04:00
izzy2lostandClaude Opus 5 a9604e38fe Report asset-array entries that fail to resolve
An entry whose CRC resolved to nothing was silently replaced with a null
pointer, so a missing asset surfaced only as corrupted rendering much later.

A zero CRC is a legitimate gap — main_hud_lut is indexed by character code and
is mostly empty — so only a non-zero CRC that resolves to nothing is reported.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 10:39:44 -04:00
izzy2lostandClaude Opus 5 6c82d0f413 Align the remaining __OTR__ asset declarations
Torch emits ALIGN_ASSET(2) for individual texture declarations but not for
the table and ptrlist declarations, leaving 270 of them with alignment 1:

    static const ALIGN_ASSET(2) char water_skybox_texture_00000[] = "__OTR__…/water.0";
    static const char water_skybox_ptrlist[] = "__OTR__…/water_skybox_ptrlist";

The macro is there because gfx_check_image_signature() rejects odd addresses
before it looks for the marker. In an arm64 build 81 of the 270 landed on odd
addresses, where the path string is used as raw texture data instead of being
resolved. Which ones land badly depends only on how the linker packs .rodata,
so it varies by toolchain.

This fixes the generated headers; Torch's codegen needs the same change or
regenerating them reintroduces it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 10:39:27 -04:00
izzy2lostandClaude Opus 5 45192a5517 Resolve app-directory paths on first use, not at load time
savesPath and randomizerFolderPath call GetPathRelativeToAppDirectory() from
a global constructor. On Android the app directory comes from
SDL_AndroidGetExternalStoragePath(), which calls into Java — and a global
constructor runs at dlopen, before SDL's JNI is set up, so the process aborts
before main() with "CallStaticObjectMethod received NULL jclass".

Making them function-local statics defers the lookup to first use. It also
resolves an ODR violation: randomizerFolderPath was a non-static global
defined in two translation units.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 10:39:08 -04:00
izzy2lostandClaude Opus 5 e0ffcc5af3 cmake: build libultraship into the binary tree
add_subdirectory() was given the submodule's own source directory as its
binary directory, so libImGui.a, libstb.a and libmonocypher.a were written
into the libultraship checkout.

With a single target that only pollutes the working tree. With more than one
it breaks the build: Android configures once per ABI, both write the same
archives, and whichever ran last wins — the other then fails to link with
"is incompatible with aarch64linux".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 10:38:52 -04:00
KiritoDv 49c5312a0f Fixed ios support 2026-07-16 09:27:42 -06:00
KiritoDv 03b8845bcf Android support added based on Waterdish work 2026-07-16 09:25:45 -06:00
KiritoDv 731726a243 Updated workflow name 2026-07-15 23:36:13 -06:00
KiritoDv 86d8edeb4b Added new target, iOS <3! 2026-07-15 23:26:09 -06:00
KiritoDv 7e15e88c13 Fixed idbfs 2026-07-13 01:58:04 -06:00
KiritoDv 35a4cd6fd2 Bump torch 2026-07-13 01:12:04 -06:00
KiritoDv 2ecc952a92 Testing emscripten deploy 2026-07-13 00:54:48 -06:00
KiritoDv 98d4de0414 Fixed vulkan missing dlls 2026-07-12 21:48:41 -06:00
KiritoDv d6df12c0f8 Fixed IOS builds in theory heh 2026-07-12 21:36:12 -06:00
KiritoDv 37b77e3070 Bump LUS and fixed CI 2026-06-23 20:28:57 -06:00
KiritoDv 997aefcdb2 Added shader settings 2026-06-12 19:54:47 -06:00
KiritoDv 93d505f9a1 Exposed some variables as custom uniforms 2026-06-12 17:30:40 -06:00
KiritoDv 8636485590 Directly exported symbols 2026-06-04 17:34:33 -06:00
KiritoDv a6162dfdb9 Test 2026-06-04 14:08:52 -06:00