Commit Graph
33 Commits
Author SHA1 Message Date
moonpower fadd20b658 Host the app in one task, not one per launch source
Main was singleTop, which only dedupes inside a single task, so a game opened
from a file manager or a home-screen shortcut started a second Main in the
caller's task alongside the launcher's copy — two Activities driving one
process-wide runtime and one native VM. A user's logcat caught it: taskId=20
and taskId=4 both hosting com.armsx2.Main. singleTask keeps one instance and
routes the incoming URI through onNewIntent, which already boots it.
0.1.3
2026-08-06 00:48:44 +02:00
moonpower 7be4ca8d52 Stop re-probing the Adreno/Mali busy nodes once SELinux refuses them
Retail Android denies an untrusted app these sysfs reads, so the sampler was
generating a kernel audit record per node twice a second for a number it can
never get — noise that buries the real content of a user's bug report. Latch
the refusal after one round; the OSD still prints "n/a".
2026-08-05 22:49:57 +02:00
moonpower b6cdcd06d7 Stop listing the app's own folders as games
We ship resources/patches.zip; .zip counts as bootable and, on an install with no
custom data root, the folder we copy assets into is also a scan root — so every
library showed a phantom game called "patches", even with an empty game folder.
Block the app-managed directories by name, as bios/covers/cache already were.
2026-08-05 22:34:35 +02:00
moonpower 31713132ef Changelog for 0.1.3 2026-08-05 22:26:35 +02:00
moonpower 5f7b5a424b Boot the game the user just picked when a launch is deferred behind a dying VM
The old VM thread's exit relaunched its closure-captured game, so tapping game B
while game A ran booted A again (and re-pointed per-game settings at it). The
deferred request is now parked under the lifecycle lock, consumed by whichever
relauncher wins, and the deferral path arms the restart watchdog like restart()
does. A game tapped while a BIOS session dies wins over rebooting the BIOS.
2026-08-05 21:04:08 +02:00
moonpower 70c94aec21 Fix dead PBP support and the stop-vs-launch crash chains
PBP: the frontend's IsDiscPath never accepted .pbp (kind=none, 'Invalid launch
request.'), pbp_read_sector returned 0-on-success against the TS_* convention,
and the reader indexed image blocks with the core's 150-based disc LBA. Tracks
now live in absolute LBA space like cue/chd, reads return real TS types, the
subchannel polarity matches chd, and zipped PBPs rank as launch candidates.

Crash chains from the Samsung tombstone: device create()s are calloc'd so a
failed psx_init no longer makes psx_destroy free garbage; psx_disc_create and
the raw-disc malloc are NULL-checked; queue_destroy tolerates NULL; a shutdown
requested between runs is dropped at run() entry instead of killing the next
session on frame 1; its SDL_QUIT push is gated on a live loop (the event-queue
mutex may be destroyed between sessions) and a stale queued quit is flushed
before the loop starts.

Also: disc-probe gate links again (psx/perf.c was missing from its sources).
2026-08-05 21:04:08 +02:00
moonpower 263e7e0120 Generate log file: one-file diagnostic report with core logs, crashes, and symbolized tombstones 2026-08-05 14:41:28 +02:00
moonpower efcf9aee8d Close the pause menu when Restart resets in place, so the reboot is visible again 2026-08-05 14:41:28 +02:00
moonpower c467a83c57 Changelog for 0.1.2 0.1.2 2026-08-05 00:16:07 +02:00
moonpower 208250ec4f Identify SAF games through a scan-time descriptor lease, restoring their cover art 2026-08-04 23:58:23 +02:00
moonpower dc5c9b494d Fix Android rendering, audio, and SAF lifecycle 2026-08-04 22:38:40 +02:00
jpolo1224 02975d4f67 Changelog for 0.1.1 0.1.1 2026-08-03 14:08:20 -04:00
jpolo1224 189e264bb4 Identify .chd discs through the core's own disc reader, so they get cover art
A CHD never produced a serial. Ps1DiscId reads SYSTEM.CNF itself, and it cannot see
inside a compressed container, so every .chd fell through to Ps1TitleSerials -- a
curated filename table of two dozen USA titles behind a USA-only region filter. A CHD
library therefore showed placeholder tiles for everything the table did not list, and
the new Download cover art action could not help because it fetches by serial.

The serial is not only art: RetroAchievements identifies against it, per-game settings
key off it and play time accrues under it. A CHD had none of that either.

Writing a CHD parser in Kotlin would have been wrong twice over. CHD v5 Huffman-
compresses its own hunk map, so it is a few hundred lines of bit-level decoding before
the filesystem is even reachable; and a decoder that is slightly wrong returns a
PLAUSIBLE WRONG serial rather than failing, which silently attaches one game's art,
settings and achievements to another. Relaxing the region filter has the same defect --
a USA serial fetches the wrong regional box art with total confidence.

So the disc goes to the reader that already boots it. psx/discid.c walks the ISO9660
root directory to SYSTEM.CNF and parses its BOOT line through the same psx_disc_t
vtable the emulated drive reads through, which means the build still contains exactly
ONE CHD decoder and there is nothing for a second one to disagree with. Everything
psx_disc_open handles comes along for free: .cue, .bin, .iso, .pbp and .chd.

Geometry is detected, not assumed. The same filesystem arrives in four shapes and
nothing in the container says which: a CHD puts ISO sector 0 at LBA 150 because its
LBA space includes the lead-in, a raw rip puts it at 0 -- or a few sectors in, if the
dump captured the pregap -- and the user data sits 24, 16 or 0 bytes into the sector
depending on MODE2/MODE1/2048. Each candidate is carried through to a serial-shaped
BOOT line before being accepted, so a geometry that finds a plausible volume descriptor
but no SYSTEM.CNF falls through to the next instead of becoming a wrong answer. The
normalisation accepts the same shape Ps1DiscId.kt does, on purpose: the two are routes
to one identity and a disagreement would split a game's settings in half.

Kotlin keeps the fast path. It still reads .bin/.cue/.iso/.pbp itself and only calls
native for containers it cannot open, plus as a last resort when its own walk and byte
scan both came up empty -- which can only add serials where there were none. That does
mean identification can touch native now; it costs nothing, because Pasx2Application
already loads SDL2 + libarmsx on its warm-up thread at process start and MainActivity
calls initializeOnce regardless. Every call is guarded, so a process without the
library degrades to exactly the previous behaviour and says so in serial_probe.log.

Gated by tests/disc_serial.c (make test-disc-serial): the CHD addressing driven through
a synthetic vtable that mimics it, MODE1/MODE2/2048 sectors, pregap rips, a track table
that disagrees with the filesystem, SYSTEM.CNF 9000 sectors in, fourteen BOOT spellings,
and the cases that must yield NOTHING -- PSX.EXE, MAIN.EXE, a PS2 BOOT2 line, a short
serial, a missing SYSTEM.CNF, no volume descriptor, a corrupt root extent. libchdr's
decompression is deliberately not re-tested; it is what already boots these discs.
Pass --image <path> to identify a real image end to end.

One consequence worth knowing: a .chd with no serial in its filename keyed its per-game
settings off the filename stem and now keys off the real serial, so per-game settings,
cheats, custom names, per-game BIOS and the per-game memory card ASSIGNMENT revert to
global once for those entries. Save states are untouched (they key on disc path plus
fingerprint, not serial) and no memory card file is affected.
2026-08-03 14:04:27 -04:00
jpolo1224 78d757a863 Unbreak the core gate suite: pbp.c needs miniz on every target that links the core
disc.c reaches chd.c only under #ifdef USE_CHD, which is why TEST_CORE_SOURCES can
simply filter it out. Its CD_EXT_PBP case has no such guard, so every gate that links
the core also compiles psx/dev/cdrom/pbp.c -- and that #include's miniz.h and calls
into it. Neither the header path nor the archive was on those command lines, so from
the moment PBP support landed the whole suite failed to build with

    psx/dev/cdrom/pbp.c:8:10: fatal error: 'miniz.h' file not found

taking cpu, cpu-spec, gte, cheats, spu-width, mcard-diverge and cdrom-getlocp with it.
A gate that cannot be built is a gate that is not defending anything.

Both come out of the libchdr build (miniz is one of its deps) and both are empty when
USE_CHD=0, so this is the same shape the CHD-aware targets already use. The archive is
an order-only prerequisite so it stays out of the $^ the recipes hand the compiler.
2026-08-03 14:04:00 -04:00
jpolo1224 3a715576a3 Add PBP (PSP EBOOT) disc support: multi-disc PSTITLEIMG, deflate block reader, serial probe 2026-08-03 13:25:23 -04:00
jpolo1224 80469ad93a Default Skip BIOS off: it breaks some games, so the faithful boot is the right default 2026-08-03 13:25:23 -04:00
jpolo1224 cf8f441ce1 Pre-fetch cover art to <DataRoot>/covers with a Download cover art action 2026-08-03 13:25:23 -04:00
jpolo1224 5eb3fb119a Onboarding: require all-files access before adding a game folder, not only for a custom data root 2026-08-03 13:25:23 -04:00
jpolo1224 f0c3c6793f Reject non-PS1 images in the BIOS picker instead of accepting any 128KB-8MB file 0.1 2026-08-03 11:30:13 -04:00
jpolo1224 4c5c5ee2d8 Onboarding: write the chosen BIOS into settings.toml, not just a SharedPreference 2026-08-03 11:30:13 -04:00
jpolo1224 9f28d82a9a Default new installs to Material You on Android 12+ instead of the blue baseline palette 2026-08-03 11:07:15 -04:00
jpolo1224 f183295e8c Add 0.1.0 changelog 2026-08-03 10:49:08 -04:00
jpolo1224 a557b17931 Enable R8 for release; keep the JNI bridge and app packages so native callbacks survive 2026-08-03 10:49:08 -04:00
jpolo1224 16d0e8e045 Default GPU presentation to OpenGL ES instead of software 2026-08-03 10:49:08 -04:00
jpolo1224 860c2e7cfd GPU: return GPU type 2 for GPUINFO(7); latch GPUREAD instead of rebuilding from zero 2026-08-03 10:49:08 -04:00