Skip to content

Merge latest Purun changes and add an Android arm64 APK build - #11

Merged
MHunterG merged 26 commits into
mainfrom
build/android-latest-20261007
Oct 7, 2026
Merged

MHunterG merged 26 commits into
mainfrom
build/android-latest-20261007

Conversation

@MHunterG

@MHunterG MHunterG commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Merge the latest deck/dev changes and add a repeatable Android arm64 APK build. The script builds pinned SDL3, generates the player-provided executable into the local AOT corpus when needed, builds the game with bundled FFmpeg, and packages it with Purun launcher resources and a fallback font. It checks signing, 16 KiB alignment and imports against Android 10; the game image is installed separately on the device.

Uses PortableKit main after TeamGDB/PortableKit#42 was merged. The submodule points at that merge commit; its source tree is identical to the framework revision used for the validated Android APK.

Validation: full PortableKit build and all 21 CTest tests passed on macOS Apple Silicon. SDL 3.4.16 and FFmpeg built for arm64/API 29. The full 193-unit AOT Android APK build passed with NDK 28.2.13676358, including Java/resources, signing, Android 10 native imports, ZIP alignment, 16 KiB ELF segment alignment and the SDL_main entry point. The APK contains four arm64 libraries and a fallback font, with no game files. It uses a local development signing key; no APK or player-derived files are committed. No Android device is connected: startup, sensors, touch input, audio, movies, saves and gameplay have not been verified.

MHunterG and others added 26 commits September 26, 2026 06:24
…ve that

PortableKit now paces the controller reads and sceDisplayWaitVblank as a
PSP does (TeamGDB/PortableKit#25), and the game flips at every vblank:
59.9 frames a second of its own time where it made 20, at the same game
speed, since it steps its world by the vblank count. The framework under it
also brings Yakumo's renderer work and fast loading (#23, #24) and what the
first levels needed (#27): the hero's body is whole, speech bubbles have no
seams, SAS noise voices play.

The profile says the game's frame is one vblank (frame_vblanks), so frame
interpolation and the Frame rate setting start from 60, and asks for its
orthographic draws to be blended, with a lower share of matching draws
than a 3D game needs, since its particles come and go.

The submodule points at PortableKit's purun-first-levels branch until
that stack is merged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- packaging/: what PortableKit's release scripts take from the game: the
  release description (release.env), third-party notices, the macOS icon
  and read-me, the Linux desktop entry, AppStream data, read-me and icon.
  The icon is original: a drop on a hill, no art from the game.
- The submodule moves to PortableKit's release-packaging branch, which
  holds the release scripts, on top of the frame pacing and first-level
  fixes (TeamGDB/PortableKit#23 to #27 and the packaging PR).
- README: the status (60 frames a second, the hole and the seams fixed)
  and how to play a release.
- docs/MISSING.md: the hole, the seams and the frame rate as traced and
  fixed, the sound as it is now, the black silhouette in the first level
  as not understood, and two fewer stubs.
- docs/RELEASE_NOTES_DRAFT.md: notes for a first release, for the
  maintainer to decide on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The game reads the console's language and confirm button through
sceUtilityGetSystemParamInt (ids 8 and 9) and passes them on to
sceImposeSetLanguageMode. PortableKit answered as a Japanese console, so
the game took circle as confirm: its language screen showed "○ Confirm",
and "confirm on the south button" put circle, not cross, there.

- The profile now reports English and cross (system_language 1,
  confirm_button 1), which the European release UCES-01059 expects.
- PortableKit moves to purun/confirm-cross: e73a866 with the profile's
  console settings from its main branch, a "[sysparam]" trace under
  TRACE_KERNEL, and a pad mapping that puts the console's confirm button
  on the face button input.confirm names, south by default here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
LocoRoco is played by tilting its world with L and R. With Controls >
Tilt controls on, tilting a gamepad with a gyroscope, a phone or a Steam
Deck does the same (off by default).

How the game reads tilt, traced rather than assumed (PURUN_TRACE_PAD,
the pad reader at 0x08A37DD4, and runs with scripted input):
- Every frame it reads one buffer sample and the latch, and keeps the
  held buttons, presses, releases and the stick; its play tests L
  (0x100) and R (0x200) as held bits, and L and R together jump.
- Holding a side eases the world towards it and releasing eases it
  back: pressing R on half or a quarter of the frames leaned the world
  visibly less than holding it, so a small roll of the device presses
  for part of the frames (TiltControls::proportional).
- The stick does not tilt the world.

- The profile names L and R as the tilt buttons (GameProfile::tilt).
- PortableKit moves to purun/tilt-controls: e73a866 with the tilt
  controls (TeamGDB/PortableKit, feature/tilt-controls for main).
- The README describes the settings, the three gyro modes, where the
  motion comes from on each platform, and the two ways to use a Steam
  Deck's gyroscope.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Combines fix/confirm-cross (#9) and feature/gyro-tilt (#10); PortableKit
points at purun/deck-dev, which merges the two PortableKit branches.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PortableKit now reads the Deck's motion sensors straight from its
controller beside Steam Input, switching them on while tilt controls are
on, so Tilt with motion works on a Deck started from Steam without turning
Steam Input off. The README says so, names PURUN_TILT_DECK=0, and drops
the advice to turn Steam Input off or map the gyroscope in Steam.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	portablekit
PortableKit moves the Deck controller's reads and the setting that
switches its motion unit on off the main thread, so the device cannot
hold up a frame.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…uild

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	portablekit
PortableKit now turns the picture back against the game's own tilt of its
world, read from the projection LocoRoco 2 turns by up to 30 degrees,
rather than against the device. The README describes the mode that way,
says the level limit goes to 30 degrees, and names
PURUN_TILT_LEVEL_FROM=device for the old behaviour.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…dev build

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	portablekit
PortableKit adds a Jump button for tilt controls (L3 by default, bindable
to a face button, and a keyboard Jump action) and keeps L and R together a
jump whatever the device's roll. Angle + level horizon is no longer offered
in the menu; PURUN_TILT_MODE=horizon, or input.tilt_mode=level, still turns
it on. The README and the menu's note about jumping say so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…k dev build

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	portablekit
PortableKit's stall watchdog writes every emulated thread's state to the
log when no frame has come for five seconds outside the menu, to find why
the Steam Deck build stops. PURUN_STALL_WATCHDOG=0 turns it off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	portablekit
PortableKit reads the window's events while the stall watchdog sees the
game stalled, so closing it or SIGTERM ends it instead of needing SIGKILL.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	portablekit
The framework's keyboard is for a game with a camera: W A S D to move, the
mouse to look, L on Q. LocoRoco is played by tilting, so Purun now starts
with both hands on tilt (Left arrow or A, Right arrow or D), Space to jump,
Shift for ○, Enter for × (confirm), the D-pad on the arrows' Up and Down
and on W, S, Q and E, and the mouse off. The game's menus and map read the
D-pad, the stick and held L and R in the same handler, so the arrows move
there too. Saved bindings stay; only what settings.ini does not name takes
these (PortableKit's GameProfile::keyboard_defaults).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	portablekit
As on a PSP, the four arrows are the D-pad; L moves to A or Q and R to D or
E, beside them on the left hand. W and S are no longer bound, and the rest
stays: Space jumps, Shift is ○, Enter or Z is ×, C and X are △ and □, Tab
or P is START, Backspace SELECT, and the mouse is off. Saved bindings stay.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@MHunterG
MHunterG marked this pull request as ready for review October 7, 2026 10:21
@MHunterG
MHunterG merged commit 5cd4b67 into main Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant