Commit Graph
8 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 4bfeb59fcd Debugger: Add wait to game.state.load/save
With wait: true, respond once the savestate operation has finished (with its
message), or with an error if it failed or was dropped without running.
Otherwise a client only learns the operation was queued.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 10:10:25 +02:00
Henrik RydgårdandClaude Opus 5.5 16a03f16e8 Adhoc: Restore the inited flags from savestates
Loading a savestate kept the current session's netAdhocInited,
netAdhocctlInited and matching-inited flags rather than the saved ones.
Loaded into a fresh boot, a state saved with adhocctl initialized (but not
connected) then failed every adhocctl call with NOT_INITIALIZED. MGS Peace
Walker shuts ad hoc down before a cutscene and retried
sceNetAdhocctlDisconnect forever, leaving the screen black.

Take the flags from the state, and bring the host side in line: start the
friendFinder and log in again when the state has adhocctl up and we don't,
stop it in the opposite case. Also save the product code, which that login
sends.

Also add a game.state.save debugger command, used to reproduce this.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:15:51 +02:00
Henrik RydgårdandClaude Opus 5.5 9720041ecf Debugger: Add game.state.load
Queues loading a savestate file, for scripting repros that load a state partway
through a run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 14:50:19 +02:00
Henrik RydgårdandClaude Opus 5 44b832f755 Debugger: add game.speed.get/set for fast-forward and a speed percentage
Both mechanisms already existed and just weren't reachable from the WebSocket
API: PSP_CoreParameter().fastForward for unlimited, and an FPSLimit mode plus a
target frame rate for everything else. FrameTimingLimit() in sceDisplay.cpp is
where they all resolve to a single number.

The one thing worth being careful about is which knob to drive. Reusing
CUSTOM1/CUSTOM2 - the user's own alternative speeds - would have meant writing
g_Config.iFpsLimit1, which is persisted per game, so a debugger session would
permanently overwrite whatever speed the user had configured. Same class of
mistake as a debug setting leaking into the saved config. So this gets its own
FPSLimit::DEBUGGER mode and a debuggerFpsLimit field on CoreParameter, which
isn't persisted and is value-initialized on every boot. Two things fall out for
free: the analog-speed handler already backs off for any mode it doesn't own
(EmuScreen.cpp), and a debugger can't leave a game slowed down after a restart.

Percentages are relative to 60 FPS, the same convention GameSettingsScreen uses
when presenting the alternative speeds, so "200%" means one thing across the
app. Unlimited is fastForward rather than percent 0, so there's a single way to
express it.

The response reports limitFps straight from FrameTimingLimit(), exposed for the
purpose. That's the number the frame timing actually consumes, so a client never
has to reconstruct the interaction between fast-forward, this override and the
user's own hotkeys - which is exactly the sort of thing that goes stale.

Requests fail rather than being quietly ignored when something else owns the
speed: achievements hardcore mode, or netplay without the "allow speed control
while connected" option. Being ignored with a successful response is the worst
outcome for an automation client.

Verified against a running headless instance: percent 200 with fast-forward off
resolves to limitFps 120, fast-forward takes it to 0 while remembering the 200
underneath, an explicit null clears it, and out-of-range or empty requests are
rejected. The throttle *behaviour* is not verified end to end - a debug,
software-rendered headless build runs this game at about 1% of real time, so it
never reaches any of these targets and the limit can't be observed. That path is
shared with the existing CUSTOM1/CUSTOM2 speeds and unchanged.

sceNet.h is forward-declared rather than included: it reaches windows.h through
proAdhoc.h, which redefines the OPTIONAL macro that collides with
DebuggerParamType::OPTIONAL - the hazard this file's header comment already
warns about.

pspautotests 314/314, UnitTest 55/55.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-18 13:42:13 +02:00
Unknown W. Brackets 6e128eb510 Debugger: Expose API to reset game.
This can be useful to put the game back to a known-good state before
setting up breakpoints, overwriting memory, and processing replay data.
2021-05-30 21:12:30 -07:00
Unknown W. Brackets 4ce2b64ef7 Debugger: Refactor to allow simpler broadcasting.
It's okay to mix a bit for simple ones, I think.
2018-09-01 10:15:22 -07:00
Unknown W. Brackets b756d92139 Debugger: Add version event for future proofing.
Game isn't precisely right, but it's close enough.
2018-06-08 06:59:17 -07:00
Unknown W. Brackets 3dac5f2103 Debugger: Add current game info. 2018-06-08 06:59:17 -07:00