Commit Graph
50455 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 63ff8c8382 GameBrowser: Drop the small list, the large list is now just the list
The grid and the list each get their own icon size (GameGridScale and the new
GameListScale), changed by the zoom shortcuts and the settings popup for the
view mode of the browser it's opened from. A saved view of 2 (the old large
list) reads as the list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 21:17:38 +01:00
Henrik Rydgård 3809223111 Merge pull request #22965 from hrydgard/more-ui-tweaks
More UI tweaks: Two-pane memory stick move screen, PPGe font
2026-11-06 19:13:38 +01:00
Henrik RydgårdandClaude Opus 5.5 29cc2f20bb ConfirmMemstickMoveScreen: Make it a two-pane screen, like the memory stick screen
The two columns of loose text didn't fit in portrait. Now the status, warnings
and folders are in groups on the left (or on top), and Move Data and OK on the
right (or below). The move's progress gets a progress bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:34:24 +01:00
Henrik RydgårdandClaude Opus 5.5 55d98c24dc ProgressBar: Draw the track, and the done part in the focus color
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:29:59 +01:00
Henrik RydgårdandClaude Opus 5.5 da79b621b0 TwoPane dialogs: Respect NoBackButton in landscape too
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:29:59 +01:00
Henrik Rydgård 3229e79003 Merge pull request #22964 from hrydgard/symbolmap-roundtrip
SymbolMap: Fix loading symbol maps while a game runs
2026-11-06 18:28:50 +01:00
Henrik Rydgård c37c089bc5 Use the wider version of the font for PPGe drawing (PSP dialogs). 2026-11-06 18:16:31 +01:00
Henrik Rydgård 7a88c1521e Merge pull request #22962 from hrydgard/memstick-screen-fixes
MemStickScreen: Folder checks, safe moves, progress and readable folder names
2026-11-06 18:16:25 +01:00
Henrik RydgårdandClaude Opus 5.5 5c0b39e8f6 SymbolMap: Fix loading a symbol map while a game runs, and saving unnamed data
Loading a .ppmap cleared the map first, which also forgot which modules were
loaded and where. The file's modules came back at the addresses they had when
it was saved, and none of them active, so every symbol in a module vanished
until that module happened to load again. It now merges into the map: the
file's modules are matched to ours by name, and its names win.

Unnamed data was saved with "(null)" as its name, which came back as a label,
and data without a name was dropped on load.

The no$ format only has absolute addresses, so it now only saves functions of
loaded modules, and loading attaches them to the module they're in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:01:35 +01:00
Henrik Rydgård c6db1e0b46 Merge pull request #22963 from hrydgard/ptprecv-buffer-end
sceNetAdhocPtpRecv: Take a buffer that runs past the end of memory
2026-11-06 17:58:19 +01:00
Henrik RydgårdandClaude Opus 5.5 784b9e4b44 MemStick: Compare folder locations as a StorageLocation struct
Instead of "volume:path" strings, the volume and the path in it are kept
apart, and IsInside() says which side is the folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 17:53:02 +01:00
Henrik RydgårdandClaude Opus 5.5 b3aee84a8e Path: Recognize content URIs on every platform
So code that handles them can be tested anywhere. Elsewhere, file operations
on them just fail, as they did when they were taken for native paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 17:53:02 +01:00
Henrik RydgårdandClaude Opus 5.5 185bbd5b5d sceNetAdhocPtpRecv: Take a buffer that runs past the end of memory
It's possible to try to recv more than fits in memory using
sceNetAdhocPtpRecv, but it's ok as long as the received data fits,
as shown by the new pspautotests net/adhoc/ptp. We refused it with
INVALID_ARG on every call. Now the recv is limited to what fits in
memory, and the game's length is put back if the call fails without
waiting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 17:32:46 +01:00
Henrik Rydgård 494968509b Merge pull request #22961 from hrydgard/apctl-scan-ids
sceNetApctl: Access point scans like a PSP's (MGS: Portable Ops and Peace Walker recruiting)
2026-11-06 16:45:28 +01:00
Henrik RydgårdandClaude Opus 5.5 a61893dcc1 Translations: Memory stick folder checks, move progress and failures
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 16:16:29 +01:00
Henrik RydgårdandClaude Opus 5.5 edff9f4a95 MemStick: Delete the originals by top-level folder on content URIs
DeleteDir takes a folder's contents along there, so a copying move's cleanup
is one storage call per top-level item instead of one per file and folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 16:16:29 +01:00
Henrik RydgårdandClaude Opus 5.5 ec532bd420 MemStickScreen: Count save states as existing data, warn that a move replaces files
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 16:16:29 +01:00
Henrik RydgårdandClaude Opus 5.5 57313b0673 sceNetApctl: ScanSSID2 is a scan of its own, scans take time before they end
From pspautotests net/inet/apscan2: sceNetApctlScanSSID2 takes an SSID
to look for (or NULL), doesn't change the state, and ends with
SCAN_STOP about 2.2s later. Its results, read with GetBSSDescIDList2
and GetBSSDescEntry2, are separate from the User ones and cleared when
it starts, and a ScanUser called meanwhile runs after it. A scan for
one SSID looks among the access points recent scans made up.

A User scan's SCAN_REQUEST now comes at once and SCAN_COMPLETE 2.2s
later; the handler used to see both at the end. Results are filled in
when a scan ends, so both lists are empty until then, and a second
ScanUser before the first ends fails with 0x80410a80 (net/inet/offline).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 15:30:09 +01:00
Henrik RydgårdandClaude Opus 5.5 d4b11f8870 sceNetApctl: Scan results like a PSP's, new made-up access points each scan
- Fixes #20703

MGS: Portable Ops makes a recruit from the strongest access point a scan
finds (after mashing O to fill the meter), and won't take the same one
again for a long time. The made-up access points never changed, and the
configured one was always the strongest at 99%, so after a recruit or
two every scan came up empty. Now each scan makes up new BSSIDs, SSIDs
and strengths, and sorts them strongest first.

The User functions now also match pspautotests net/inet/apscan and
net/inet/offline: IDs from 1 (slot 0 is valid but empty), 0x80410a09
past the last one found and 0x80410a82 past the 20 slots, a 33-byte
SSID, and no SCAN_STOP event after SCAN_COMPLETE. The ...2 functions
Peace Walker uses keep their old numbering and SCAN_STOP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 15:10:04 +01:00
Henrik RydgårdandClaude Opus 5.5 4079be9a05 StorageTest: Test the memory stick move and folder checks too
The rename, copy and undo paths of MoveDirectoryContentsSafe(), and
CheckNewMemstickFolder() on a renamed PSP folder, in the scratch folder,
so on a device they run through content URIs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:37 +01:00
Henrik RydgårdandClaude Opus 5.5 745602bd5c MemStickScreen: Count down five seconds to the restart after a move
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:37 +01:00
Henrik RydgårdandClaude Opus 5.5 dbca4f8069 MemStickScreen: Show the move's progress, and the free space after views are recreated
The spacer column was FILL_PARENT high, which in the new row of columns
took the whole screen and pushed the progress below off it. The free
space was set on a view that RecreateViews() then replaced with a new
one saying "...", so it's kept and used when creating the views.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:37 +01:00
Henrik RydgårdandClaude Opus 5.5 1c0d8a2b96 MemStickScreen: Readable folder names, say what the move is doing
- Folders show as "Internal storage / PSP" or "SD card (1234-ABCD) / PSP",
  and the app's own folder as "App private data", instead of content URIs
  and /storage/emulated/0/Android/data/... paths. Here and in the
  settings.
- The move's progress names the pass it's in (moving, finding files,
  copying, checking, deleting the originals, putting things back) with
  the count, on a line of its own above the file, across the whole width.
- A successful move shows "Done!" for three seconds before restarting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:37 +01:00
Henrik RydgårdandClaude Opus 5.5 86fcd95a4f Add a memory stick start screen for Tools/android_run.py
--start-screen=memstick opens the memory stick screen as the settings do, for
moving an existing memory stick, where memsticksetup is the first-boot one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:37 +01:00
Henrik RydgårdandClaude Opus 5.5 481a15ed93 Path: Make ToVisualString's relative root work off Windows
The non-Windows handling sat inside the content URI branch, after its
return, so the root was ignored. Found by PathMore on Android.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik RydgårdandClaude Opus 5.5 3088cf5d3d Path, AndroidContentURI: Stop ComputePathTo at whole folder names, more tests
ComputePathTo() trusted StartsWith(), a plain string prefix, so "/a/b" was
a parent of "/a/bcd" (giving "d"), and "primary:Games" of
"primary:Games2/x". AndroidContentURI's also always skipped a separator,
so from a volume root like "1234-ABCD:" the first letter of the next
folder went missing. CreateFullPath() computes paths from the tree root
this way.

New tests cover parsing and building content URIs, escaping, extensions
and navigation, and Path's components, joining, prefixes, HTTP paths and
visual strings. EXPECT_EQ_STR now parenthesizes its arguments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik RydgårdandClaude Opus 5.5 261d33f5a1 MemStick: Recognize renamed PSP folders, safer leaving after a move
- A PSP folder under another name is recognized: picking one is refused,
  since the data would go into a new PSP folder inside it, and so is
  picking anything in it. On disk that's SAVEDATA with SYSTEM or GAME, or
  PPSSPP_STATE. For a picked tree, whose parents we can't see, a SAVEDATA
  or PPSSPP_STATE anywhere in its path.
- The new folder is saved as the one to use after a rename-based move
  too, not only a copy. So leaving the screen after the data moved but
  the switch failed restarts onto the new folder, instead of staying on
  the emptied old one.
- Picked folders get the same write test as native ones, so a
  write-protected SD card is refused before anything is moved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik RydgårdandClaude Opus 5.5 cff780f339 MemStick: Undo a failed move, save the new folder before deleting
A move that failed partway left the data split: what was renamed before
renaming gave up stayed in the new folder, and the copy's leftovers too.
The screen said "Failed to move some files!", which then wasn't even
shown. The move now records what it renames and creates, and a failure
puts it all back. The screen says nothing was changed, or in the rare
case that something couldn't be moved back, that the data is now partly
in each folder.

The copying move also deleted the originals before the new folder was
saved as the one to use, so being killed while deleting left the config
on a half-emptied folder. memstick_dir.txt is now written once the
copies are verified, before anything is deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik RydgårdandClaude Opus 5.5 6f44800232 MemStickScreen: Finish directly, the screen manager handles it now
24d8955531 fixed a caller finishing itself from dialogFinished(), which
this screen worked around with a flag picked up in update().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik RydgårdandClaude Opus 5.5 ed5ffe3d1d MemStickScreen: Don't blame the folder after the data has moved
If switching failed after the data was moved, the screen said the folder
doesn't work as a memory stick, though the data was already in it.

The switch's checks (the new folder and the one holding memstick_dir.txt
are writable) now run before anything is moved, where that message is
accurate. If the switch still fails after a move, a new message says the
data is in the new folder, and OK only retries the switch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik RydgårdandClaude Opus 5.5 86a12a7df2 MemStick: Fix data loss and leftovers in the copying move
When moving data can't rename (another device, or merging into a folder
with data), it copies, verifies, and deletes the old folders. On content
URIs that delete is recursive, but a subfolder that failed to list, or a
file whose relative path couldn't be computed, was silently left out of
the copy, and so got deleted with its folder. Any listing failure now
aborts the move before anything is copied.

On native paths, the same fallback never deleted the old files, only the
then non-empty folders, so "Move Data" left a full copy behind. The
verified originals are now deleted first, on both.

SwitchMemstickFolderTo() fails if it can't write memstick_dir.txt, rather
than restarting onto the old, by then emptied, folder. "Skip for now" in
setup only leaves when the switch worked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik RydgårdandClaude Opus 5.5 1832c9aced MemStickScreen: Refuse folders inside a memory stick's PSP folder
Picking the new memory stick folder is checked by CheckNewMemstickFolder(),
which compares locations across content URIs and Android storage paths,
case-insensitively and on whole folder names:

- Inside the current memory stick's PSP folder: refused. This used to be a
  warning only, compared by string prefix (so "Games2" was "inside"
  "Games"), and missed URIs from a different volume or a native path.
- Inside some other memory stick's PSP folder (like after a reinstall):
  refused. Found on disk among the parents of native paths, and from the
  names for picked trees, whose parents we can't look at.
- Same PSP folder as the current one (a PSP folder and its parent), or the
  current one inside the new one: allowed, without moving data.

GetPSPFolderOf() is the PSP folder rule GetSysDirectory() uses, now shared
with the move, which compared "PSP" case-sensitively and so could move data
into psp/PSP. FolderSeemsToBeUsed() looks in that folder too, and "Move
Data" starts unchecked when the new folder already has data, since merging
overwrites it.

Switching to a folder without a config no longer resets settings to the
defaults: the current ones are written there instead. Typing a manual path
without the leading slash works again (the fixup was unreachable).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:53:36 +01:00
Henrik Rydgård fc8392b01a Merge pull request #22960 from hrydgard/firmware-install-fixes
Firmware install: Fix regressions unpacking updaters, create flash1/vsh/theme
2026-11-06 14:39:27 +01:00
Henrik Rydgård b69424e8f2 Merge pull request #22932 from hrydgard/http-ids-npauth-ticket
sceHttp: Stable ids; NpAuth: Return the ticket param asked for
2026-11-06 14:11:19 +01:00
Henrik RydgårdandClaude Opus 5.5 1908ac5e92 PSAR: Bound entries by the file size, not the declared size
The last entry's contents can run past the size the header declares (1.x
updaters, and the 4.21 and 5.70 PSARs), so the wraparound check from
c5673294ab refused them. The file size is enough to stop the wrap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:08:58 +01:00
Henrik RydgårdandClaude Opus 5.5 004dcdfe93 PSAR: Accept zlib 1.4's error for streams without a checksum
zlib 1.4's uncompress2 returns Z_DATA_ERROR, not Z_BUF_ERROR, when the input
runs out with the output full, so every file in the pre-decrypted 3.60 archive
failed to inflate after the zlib update.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:08:57 +01:00
Henrik Rydgård 3e82948c28 Merge pull request #22956 from hrydgard/gamebrowser-ctrl-wheel-zoom
Game browser: Ctrl/Cmd+wheel and Ctrl/Cmd+Plus/Minus icon zoom; unify wheel units; drop SDL2 leftovers
2026-11-06 14:02:16 +01:00
Henrik RydgårdandClaude Opus 5.5 a0af2bc403 Firmware install: Create flash1/vsh/theme
The shell refuses to install a theme without it, and the updater's archive doesn't have it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:01:34 +01:00
Henrik RydgårdandClaude Opus 5.5 8c31d80b8b PSAR: Pad the second block size from the first block to 16 bytes
The 6.61 updater records its second block as 408 bytes, but the block is padded to 416 and
only decrypts at that size, so the install failed with "Couldn't read the PSAR's second block".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:01:34 +01:00
Henrik Rydgård 727805e193 Merge pull request #22959 from hrydgard/storage-fixes
Android storage: No numbered duplicates, real errors, faster startup
2026-11-06 13:46:51 +01:00
Henrik Rydgård a4296e57b8 Merge pull request #22958 from hrydgard/xmb-mac-address
VSH: Show the configured MAC address in System Information
2026-11-06 13:43:45 +01:00
Henrik RydgårdandClaude Opus 5.5 cdc4f522f4 Fewer storage calls at startup
CreateSysDirectories() lists the PSP folder once instead of checking each
folder, and only writes .nomedia into folders it creates, instead of
rewriting it into all of them every time. PreferUpperCaseDir() doesn't
check for both spellings on content URIs, where storage is
case-insensitive. Theme and post shader loading don't list an empty
folder of their own a second time through File::GetFilesInDir.

On a phone with the memory stick on a content URI, startup now makes 12
storage provider calls before the game list, down from 82.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:53:31 +01:00
Henrik RydgårdandClaude Opus 5.5 ad748f31e9 Android: Don't reload the config for the storage permission startup report
Android reports the storage permission at every startup, and the handler
took it for a new grant: it created the system directories, reloaded the
whole config, and created them again. With a memory stick on a content
URI that was about half a second of storage calls in every startup. Only
redo it when the config couldn't be loaded before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:53:31 +01:00
Henrik RydgårdandClaude Opus 5.5 f519f40f65 Android storage: Never make numbered duplicates, report real errors
Given a taken name, the storage provider makes "name (1)" rather than
fail. Renaming onto an existing file did exactly that and reported
success, so a game's sceIoRename onto a save file left a duplicate
instead of failing like on a PSP. Creating, renaming and copying now
check the name the document ended up with, undo a renamed one, and
return ALREADY_EXISTS. A new storage test checks that no operation onto
a taken name leaves a duplicate.

The Java side only ever returned UNKNOWN. It now maps a missing file to
NOT_FOUND and a full disk to DISK_FULL, and OpenFD/OpenCFile set errno
from those, so DirectoryFileSystem reports a full disk on content URIs
like on native paths, instead of "file not found".

That also lets writing open first, and only create when the file is
missing: overwriting a file is one call to the provider instead of two
(18.6 -> 13.2 ms in the storage test on an SD card).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:53:31 +01:00
Henrik Rydgård 37a0d427ac Merge pull request #22957 from hrydgard/storage-tests
Android: Storage tests for content URIs, and fixes from running them
2026-11-06 12:52:42 +01:00
Henrik Rydgård c7e7ee2821 Config: Default UI scale factor 0 on Android and iOS
PPSSPP_PLATFORM(LINUX) is also true on Android, so it got the desktop
default of -1, which was never intended.
2026-11-06 12:46:34 +01:00
Henrik RydgårdandClaude Opus 5.5 f1ef96e3dd SDL: Halve wheel deltas on macOS, and zoom by the fingers' direction
Trackpad scrolling went about twice as far as it should. SDL3's wheel
event doesn't tell a trackpad from a mouse, so this applies to both.

With natural scrolling the wheel direction is the opposite of the
fingers', which is right for scrolling but made the icon zoom feel
backwards. SDL's FLIPPED direction is now passed on as WHEEL_FLIPPED, and
the zoom undoes it, so fingers up make the icons bigger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:39:50 +01:00
Henrik RydgårdandClaude Opus 5.5 a3cbbd086b VSH: Show the configured MAC address in System Information
- See #22924

The page reads IdStorage key 0x44 (6 bytes at offset 0) through
vshbridge.prx, as does wlan.prx's sceWlanGetEtherAddr. The real
idstorage.prx never finishes its init (it stops at the kernel mutexes we
leave unresolved), so every lookup failed and the page showed "-".

sceIdStorageLookup is now HLE, answering key 0x44 from the same MAC
sceWlanGetEtherAddr uses. Other keys fail with 0x80000108, what the real
driver returns uninitialized, and the rest of the library still resolves
to idstorage.prx. Taken from the 6.61 modules' disassembly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:34:02 +01:00
Henrik RydgårdandClaude Opus 5.5 360b48706b Remove the SDL2 leftovers
FindSDL2.cmake and the cmake/sdl module path, SDL/macbundle.sh (which
only copied SDL2.framework into the bundle, and nothing calls any more),
b.sh's --no-sdl2 and its USE_SYSTEM_LIBSDL2 flags (no such option exists),
and SDL2 mentions in the README, a log message and a commented-out CI line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:14:13 +01:00
Henrik RydgårdandClaude Opus 5.5 666dfd2187 Android: Hold a client for the storage provider between calls
Without one, every query and DocumentsContract call acquires the provider
and releases it again, and when our reference count drops to zero, each
of those is a binder call to the system as well. Holding an unstable
ContentProviderClient keeps the count up, without tying our process to
the provider's. Queries go through it, and a dead provider is dropped
and acquired again.

Storage test timings on an SD card, median of five runs before and after:
exists 9.3 -> 6.7 ms, file info 10.4 -> 7.4, overwrite 21.8 -> 18.6,
read 28.5 -> 26.6. Creating, deleting and listing are dominated by the
provider's own work, and gain a few percent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:09:55 +01:00