The run of work that took the translated build from "boots" to "playable".
Engine:
- Flat guest mapping replaces the software MMU on aarch64 hosts. A 4 GiB
PROT_NONE reservation lets a 32-bit guest address zero-extend safely, so
tcg_out_qemu_ld/st short-circuit before tcg_out_tlb_read and the prologue
materialises the base into X28. Measured 1.24x (51 vs 41 fps, interleaved
A/B). Note the base must be set BEFORE UC_INIT - Unicorn inits lazily, and
setting it after uc_open silently falls back to softmmu.
- num_get<char> facet implemented, which was the real cause of the crash after
the prologue race; a full race is now playable end to end.
- Thread-stack free list + ReleaseThreadEngine, fixing the arena leak that
showed up as a black screen when entering a race. kMaxGuestThreads 16 -> 64.
- Real ARM32 FMOD now runs in-engine via the Java FMODAudioDevice bridge, with
a per-thread JNIEnv. Two of the three blockers were our own single-image-era
guards.
Host/app:
- Native crash handler: async-signal-safe, decodes the host fault back to a
guest address, writes a report file and nothing else. CrashReportActivity
picks it up on the NEXT launch, zips it, and offers to share. No backend, no
automatic upload.
- Game data ships inside the APK and self-extracts on first launch, so a tester
installs one file and plays. Copy-to-.part-then-rename, with a free-space
check up front.
- EGL context preserved across pause, fixing black textures on resume.
- Navigation bar hidden and re-hidden on focus gain; volume keys reported as
system keys, checked before the loading-state gate.
- x86_64 added to abiFilters: the ARM32 guest runs under tcg/i386 with no
houdini in the path. The flat mapping is aarch64-only, so that host falls
back to the software MMU - commented at the abiFilters line.
Ignore rules added for app/translated/ (611 MB of signed release APK, which
also carries the bundled OBB) and ostream_repro/build/.
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes the synthetic car_select jump for cold sessions, makes the loadout
exit chain safe for real (non-synthetic) events, and adds a native->Kotlin
GameEvents bridge (onMapLoaded/onRaceStarted/onRaceEnded/onUpgradesAccepted/
onCarSelected) so both the UI layer and a future native RatNet client can
learn what the player picked - car id, accepted upgrades, and paint color
(name + RGBA) are all resolved live from the game's own engine state
rather than a static extracted table, so they stay correct for any car
added later. Includes a Jetpack Compose overlay as a worked example of a
UI-side GameEventListener consumer.
Full investigation history, root causes, and the several dead ends ruled
out along the way are documented in PROGRESS.md (cont. 30-63b).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>