Commit Graph
139 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 932d1e3b36 IconCache: Expire only avatars after a day, other icons after 30 days
Achievement badges and game icons don't change, so re-downloading them
daily was wasted. InsertIcon now takes a max age, and each entry saves
its expiry time. Leaderboard avatars get a day, everything else 30 days.
Bumps the cache version.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 ab8fc0d1bb Achievements: Remove unused ResetRuntime
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 77cc6a8071 Achievements: Don't pass a null error message to %s
error_message is null on success, which is when these two lines log.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 39797c4a44 Achievements: Reload RAIntegration when achievements are re-enabled
With RAIntegration, Initialize leaves login to the DLL load, but WinMain
only calls InitializeRAIntegration once and Shutdown unloads the DLL, so
turning achievements off and on left you logged out until restart.
Remember the window and load the DLL again on its thread.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 8aac115e91 Achievements: Use the sized progress (de)serializers for savestates
The deprecated unsized rc_client_deserialize_progress parses with no
bound, so a truncated or corrupt state could make it read past the
buffer. data_size is known, so pass it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 19082ce1af Achievements: Don't start a password login while a token login is pending
rc_client answers a second login with RC_INVALID_STATE, synchronously,
and login_password_callback then cleared g_isLoggingIn while the token
login was still running. IsBlockingExecution stopped blocking, and a game
started then ran without achievements.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 efc3f5d556 Achievements: Stop retrying a login token the server rejected
On invalid credentials the token was kept, and Idle() retried it every
10 seconds for the rest of the session, silently after the first attempt.
Clear it, as was already done for an expired token, so the settings show
the login form. On access denied, stop retrying.

Show a rejection even when it comes from a background retry, since it
won't repeat, and have LoginProblems return the server's message.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 5c0a802518 Achievements: Clamp a truncated rich presence message
rc_client_get_rich_presence_message returns the length it needed rather
than what it wrote, so a message of 512 characters or more made the pause
screen read past its buffer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 c8b32dda0a Achievements: Keep a shut-down client alive until its requests finish
rc_client keeps raw pointers to itself in the callback data of award,
leaderboard submit and ping requests, so destroying it with one in flight
(disabling achievements mid-game) had the late callback write to freed
memory. Count requests per client, retire a busy client instead of
destroying it, and destroy it when its last request completes.

Request timeouts in naett are per operation and the plain HTTP client has
none for the body, so a retired client is also destroyed after 60 seconds
regardless. Its late callbacks are then dropped, leaking their data.
Clients are tracked by ID so a new client at a reused address can't get an
old one's callbacks. At app exit, pending requests are cancelled without
callbacks, so everything is destroyed immediately.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 fde1a467ca Achievements: Report transport failures to rc_client as retryable
naett reports a connection failure as -1, which rcheevos reads as
RC_API_SERVER_RESPONSE_CLIENT_ERROR, a non-retryable client error. An
unlock or leaderboard submission during a network dropout was then
treated as a server rejection and dropped, on every platform using naett.
Map any non-HTTP result to RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 2291a4a9a7 Achievements: Don't leave boot blocked after an aborted login or load
rc_client doesn't call back for a game load aborted by unload, or for
anything pending when the client is destroyed. g_isIdentifying or
g_isLoggingIn then stayed set, and IsBlockingExecution kept every later
boot on a black screen until restart. Quitting during identification, or
disabling achievements during a token login, was enough.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 00208d3d80 Achievements: Enable HTTPS on UWP, retry failed icon downloads
UWP compiled naett with the WinHTTP backend but never reported
SYSPROP_SUPPORTS_HTTPS, so achievement traffic and badge icons went over
plain http. When the media server redirected to https, icons failed.

A failed icon download also left the URL marked pending, so it was never
retried for the rest of the session. Mark it failed instead, and let
IconCache retry it after 30 seconds.

The set-completed badge also skipped RemoveHttpsIfNeeded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 2e5edcd298 Savestate: Don't break event callbacks when a save fails
CoreTiming::DoState replaced every event's callback with the anti-crash
one in every mode, relying on each module's restore to put it back. A save
that failed partway never got to those, and left the running game with
events that break into the debugger. The missing-section fallbacks then
also ran on the save: cheats and the mic re-registered events into the
wrong slots, and achievements reset the runtime.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 09:34:06 -06:00
Henrik RydgårdandClaude Opus 5.5 0a687b9435 Savestate: Bounds-check sizes from the file, and plug leaks on load
Reject sizes past the end of the state before allocating (FPL, PGF,
achievements, SAS grain, savedata list, the memory fast path), fail
instead of desyncing on a SAS voice count mismatch, and free what old
states' paths and shrinking pointer containers dropped.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 09:34:06 -06:00
Henrik RydgårdandClaude Opus 5 afeab27186 Don't load RAIntegration from an install we can't write to
RAIntegration keeps its cache and local achievement data next to the
executable. If PPSSPP is installed somewhere that needs elevation to write -
Program Files being the obvious case - that write fails and takes the emulator
down as soon as a set or code notes are loaded, with no log to show for it since
the log can't be written either.

Check whether the exe directory is writable before handing the DLL to rcheevos,
and if it isn't, say so and point at the portable .zip instead. Achievements
themselves still work, so carry on to the normal login.

Fixes #21260

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgACRqkQNpfJQ4fjwyoEup
2026-09-05 16:15:45 -06:00
Henrik Rydgård e2ab84087e Fix five ways to end up stuck, crashed, or silently degraded
System.cpp stamped BootState::Complete unconditionally after InitGPU(), overwriting
the Failed that InitGPU sets when GPU_Init() fails - after it has already run
CPU_Shutdown(). PSP_InitUpdate then took the success path on a core that no longer
existed, down to a null Memory::base, and the first guest access dereferenced it.
InitGPU now reports failure and both callers honor it. (The libretro path had the
same problem from the other direction: it calls InitGPU after the Failed check.)

HandleAssert called g_assertCancelCallback directly on the IDCANCEL path, without
the null check its own BreakIntoPSPDebugger() helper does - and EmuScreen clears the
callback when a game is unloaded. So any assert after returning to the menu turned
"Cancel: skip and break into PPSSPP debugger" into a null jump, from the one button
whose entire purpose is surviving the assert.

__CheatDoState registered the cheat event type when the savestate had no CwCheat
section, but never scheduled it. CoreTiming::DoState has already swapped in the
state's event queue by then, which doesn't contain one either - so loading an old
savestate silently killed cheats, and the enable/disable polling with them, for the
rest of the session.

Achievements::ChangeUMD set g_isIdentifying and returned without clearing it when
hashing failed, leaving IsBlockingExecution() true forever - EmuScreen stops running
the CPU and the game is frozen until restart. Reachable from a disc swap on any ISO
whose PARAM.SFO or EBOOT.BIN can't be read.

x64Analyzer routed opcode 0x88 into the write path but had no case for it, so it hit
the default, logged from inside the crash handler, and failed. 0x88 is exactly what
the x64 JIT emits for a guest sb, so MemFault could never skip or ignore a bad byte
store the way it can a word one. Handle the 8-bit forms, and drop the 0x8a/0x8b cases
in the read path that the same 0xF0 mask made unreachable. Covered by a new
CheckAnalyze case, which fails without this change.

314 pspautotests pass, all unit tests pass.
2026-08-31 12:27:24 +02:00
Henrik Rydgård d3c7279e9f Fix unnecessary RAIntegration error message if you have the DLL but RA is disabled 2026-07-28 00:16:12 +02:00
Henrik Rydgård 9949c2bf49 RAIntegration / retroachievements: Improve memory range checks 2026-07-27 18:37:28 +02:00
Henrik Rydgård 456cfb0f5a RAIntegration crashfix 2026-07-27 18:37:28 +02:00
Henrik Rydgård 72ee82844d Doesn't yet work 2026-06-24 23:04:17 +02:00
Henrik Rydgård 05018fb40d RetroAchievement images: Workaround for lack of https on Linux
Fixes #21843
2026-06-17 16:20:53 +02:00
Henrik Rydgård 9793172eba More UI refinements 2026-04-07 20:52:38 -06:00
Henrik Rydgård 3083d37728 Add support for the raintegration menu rebuild event 2026-03-26 17:18:12 -06:00
Henrik Rydgård 910b60defc Merge pull request #21463 from hrydgard/misc
Add a new file dumping setting to dump the raw ISO file from NPDRM-packed demos
2026-03-19 22:18:01 +01:00
Henrik Rydgård 0e55129fab Prepare for dumping NPDRM isos, use shared_ptr to manage lifetime of BlockDevice 2026-03-19 13:59:04 +01:00
Kevin Reinholz f020bcdd75 Create option to build with system freetype, libchdr, and rapidjson instead of bundled modules. Add a couple of FreeBSD-specific tweaks to CMakeLists.txt while at it 2026-03-10 18:03:06 -07:00
Henrik Rydgård 1a95e9e4e9 Fetch the public adhoc server list from metadata.ppsspp.org/adhoc-servers.json 2026-03-06 13:25:07 +01:00
Henrik Rydgård ab4ca14773 Add a simple utility to help bug reporting: Copy ppsspp.ini to clipboard 2026-02-17 10:18:08 +01:00
Henrik Rydgård db0a557590 Make it possible to have RetroAchievements enabled in a game config.
Fixes #21175
2026-01-30 09:43:31 +01:00
Henrik Rydgård 6a9b2e1e87 RetroAchievements: Improve completion messages (subset, differentiate hardcore mode) 2026-01-20 18:25:48 +01:00
Henrik Rydgård 63658bcb2f Lambda capture cleanup 2026-01-20 14:29:13 +01:00
Henrik Rydgård 0fb2be2cbe Simplify image caching for RetroAchievements 2026-01-20 14:25:59 +01:00
Wes Copeland 7a98df5297 Achievements: support rc_client_set_host 2025-11-16 17:54:56 -05:00
Nab 5bfd4b390c GameRegion improvements 2025-09-03 14:17:55 +02:00
Henrik Rydgård 6f76c579fc Delete dead code, more std::string_view 2025-09-01 00:15:23 +02:00
Henrik Rydgård b472eb8b8b Remove a lot of unnecessary string constructors 2025-08-31 15:49:29 +02:00
Henrik Rydgård 65285e59c4 Bump rcheevos to v12.0.0 2025-08-24 14:58:53 +02:00
Henrik Rydgård ddc8093b34 RetroAchievements: Better error messages on login, don't delete the username on failure 2025-06-13 19:09:35 +02:00
Henrik Rydgård 77f9a27c35 Add a way for errors to bubble up out of BlockDevice creation 2025-06-07 12:30:20 +02:00
Henrik Rydgård 06b29ccb85 RetroAchievements: Correct memory address check in read_memory_callback 2025-06-05 10:56:11 +02:00
Henrik Rydgård e0a98ea54c Improve the "No game loaded" RA popup 2025-06-01 11:47:07 +02:00
Henrik Rydgård 4c631e77f5 RetroAchievements: Show region when showing the info popu. Refactor region detection a little. 2025-06-01 11:34:59 +02:00
Henrik Rydgård a4e6e84a0a Move achievement handling to EmuScreen and the main thread. Fixes black screen. 2025-04-09 18:07:13 +02:00
Henrik Rydgård ee90d2acc1 PSP boot: Move more of the startup process into the loading thread. Simplifies the code a bit. 2025-03-30 11:22:16 +02:00
Henrik Rydgård 31cf5771f4 Turn the break reason into an enum, fix some minor issues 2025-02-19 16:01:11 -06:00
Henrik Rydgård ccf814bcd0 Some shutdown logging improvements 2025-01-28 13:32:31 +01:00
Henrik Rydgård eb719c43e8 HTTP: Replace ProgressBarMode with a new RequestFlags enum 2025-01-23 12:09:56 +01:00
Henrik Rydgård c91169e702 Restore removed <algorithm> includes.
Turns out these were needed after all. For some reason, on Windows and
Mac, <algorithm> gets auto-included by something else so I don't notice
when it's missing, and MSVC's include dependency tracker doesn't see it
either.
2024-12-19 09:53:07 +01:00
Henrik Rydgård 3e198c53b2 More include cleanup 2024-12-18 13:57:26 +01:00
Henrik Rydgård c8d43198d3 RAIntegration: Fix the filename in the not-found messages. 2024-11-06 14:47:48 +01:00