Commit Graph
333 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5 a96dfc1390 Share SetupCRT with the unit tests so they can't pop a modal dialog
UnitTest.exe runs on CI and from tooling, where an assert or an abort() puts
up a message box that nothing will ever click, and the run just hangs until it
is killed. Headless already solved this; move its SetupCRT() into Common
(ExceptionHandlerSetup, which is where the rest of the process-level fault
setup lives) and call it from the unit tests too.

No behaviour change for headless. The OS-level SetErrorMode() call is now
guarded for UWP, which doesn't have it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 13:11:16 +02:00
Henrik Rydgård 9b9083d3e5 Fix for headless port problem by Claude 2026-08-16 23:09:12 +02:00
Henrik Rydgård 5cffcd34ad Get rid of the confusing old USING_WIN_UI define. Make a more clear system property for headless. 2026-08-16 12:19:41 +02:00
Henrik Rydgård c138bbf482 Headless on Windows: Set up CRT to output abort() to stderr instead of dialogs 2026-08-12 11:09:41 +02:00
Henrik RydgårdandClaude Sonnet 5 d000d5366a Wire the generated ExecInstruction dispatcher into the interpreter's hot loop
Adds Core/MIPS/InterpreterDispatch.cpp, the checked-in output of
GenerateInterpreterDispatch() (see the previous commit), and hooks it
into RunUntilFast() in MIPSTables.cpp in place of the old
MIPSGetInstruction()-based table walk + indirect call through
instr->interpret. The checked-with-breakpoints/memchecks path
(RunUntilWithChecks) is untouched for now, since it inspects
MIPSInstruction flags directly and correctness there matters most.

Also fixes a real crash in headless.cpp found while testing this:
cmdLineOptions.gpuBackend.value() would throw when unset (e.g. with
--graphics=software), now uses value_or().

Verified with `test.py -g --cpu=interpreter --graphics=software`:
313/314 pass; the one failure (cpu/fpu/fpu) is a pre-existing
interpreter-vs-JIT denormal (flush-to-zero) difference, confirmed to
fail identically with the old table-walking dispatch, so unrelated to
this change.

Adds Tools/update-dispatcher.py to regenerate InterpreterDispatch.cpp
from a built PPSSPPHeadless binary whenever the MIPSTables.cpp tables
change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019SKhm9wKEQzRUsx9mTrrtQ
2026-08-12 10:52:47 +02:00
Henrik RydgårdandClaude Sonnet 5 65495c76c0 Add a codegen tool to generate a fast switch-tree interpreter dispatcher
MIPSTables.cpp has walked a tree of tables on every single interpreted
instruction since forever, with a standing TODO asking for exactly this:
"generate smart dispatcher functions from above tables instead of this
slow method." GenerateInterpreterDispatch() does that - it walks the
same tables MIPSGetInstruction() walks at runtime, but resolves the
walk into a nested switch tree once, at generation time, with each
leaf calling straight into the existing MIPSInt::Int_* handlers and
returning that instruction's fixed cycle count. Anything not covered
(invalid opcodes, and the handful of instructions with no interpreter
implemented at all, e.g. tge/tlt/teq) falls back to the existing
MIPSInterpret()/MIPSGetInstructionCycleEstimate() slow path, so the
result is total over all 32-bit inputs, same as the table-walking path.

Wired up via a new headless --generate-interpreter-dispatch flag,
which prints the generated Core/MIPS/InterpreterDispatch.cpp source to
stdout and exits.

Also widens CmdLine.cpp's --help column formatting, which silently
truncated any option name longer than 24 characters - the new option's
name was the first to hit it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019SKhm9wKEQzRUsx9mTrrtQ
2026-08-12 10:24:01 +02:00
Henrik Rydgård 71122389da Headless: Restore the old default config. 2026-08-11 22:37:03 +02:00
Henrik Rydgård e062c90bf7 Try to fix the test difference (basically by replicating an old misfeature of headless...) 2026-08-11 22:36:47 +02:00
Henrik Rydgård 2d0e54f422 Headless (and main): Improve crash reporting 2026-08-11 22:36:47 +02:00
Henrik Rydgård 6a873df4ea Work on improving crash log output 2026-08-11 22:36:47 +02:00
Henrik Rydgård a44c2c0bde Replace System_SendDebugOutput with a registered callback
I normally try to avoid registrations when not needed, but in this case
only headless uses this, so it's motivated.
2026-08-11 22:36:47 +02:00
Henrik Rydgård 8c9bf04add Headless: force opaque PNG screenshots by default, add --screenshot-keep-alpha
Games often use the framebuffer alpha channel for non-visual purposes,
so saved PNGs could look fully transparent in image viewers. Force alpha
to 255 when writing PNG screenshots unless --screenshot-keep-alpha is
passed. The MSE comparison ignores alpha either way.
2026-08-09 13:41:39 +02:00
Henrik Rydgård 893ac3e3db Frametests: add framedump rendering test runner and PNG screenshot support
- Add frametests.py: walks a dump tree, renders each dump per config variant
  through PPSSPPHeadless, generates reference images when missing and compares
  MSE when present, and writes a self-contained HTML report. The JSON config
  (which lives with the test set, not in the repo) points at the data tree
  and defines variants as suffix -> CLI args, e.g. 'soft': '--graphics=software'.
- Headless: --screenshot-save saves PNG when the path ends in .png; new
  --screenshot-diff always writes a visual comparison when comparing;
  screenshot comparison failures (mismatch or unloadable reference) now fail
  the test instead of passing silently.
- Read back framebuffers top-down, flipping only for BMP output/input
  (fixes upside-down PNG references). Sync libretro copy accordingly.
- Document the system in docs/frametest.md; add AGENTS.md reference.
2026-08-09 13:41:39 +02:00
Henrik RydgårdandClaude Sonnet 5 b1f0112cef Debugger: Remove opcode-fusion display and fix cpu step size units
DisassemblyManager used to fuse lui+addiu/load/store into single pseudo-
instructions ("li", fused loads/stores) for display. This only applied to a
handful of opcodes, complicated DisassemblyManager, and was the root cause of
a stepping bug: Core_PerformCPUStep's Into/Over cases treated stepSize as a
byte count, while the WebSocket cpu.stepInto handler computed it as an
instruction count (needed to step over a whole fused macro in one go) - so a
plain, non-fused stepInto silently executed zero instructions.

Removed the fusion logic entirely (DisassemblyMacro, DISTYPE_MACRO) - every
disassembly line is now exactly one 4-byte instruction. With that,
"how many instructions does this line span" is always 1, so the
getInstructionSizeAt() byte-size queries in the legacy Windows and ImGui
debuggers are gone too; step requests just pass 1. Core_RequestCPUStep's
stepSize is now consistently in instructions everywhere.

Also fixes the PPSSPPHeadless build, broken since 0ed1f3e added
OpenWebDebugger() (which calls System_LaunchUrl) without a headless stub.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hqm11k99viLfbJm2MkH4BH
2026-08-08 11:16:36 +02:00
Henrik Rydgård c490d4ef36 Headless SDL: Add support for Vulkan rendering 2026-08-06 11:06:03 +02:00
Henrik RydgårdandClaude Sonnet 5 5bd1ff8066 Move remaining manual command line parsing into CmdLine.cpp
Headless.cpp, NativeApp.cpp, and SDLMain.cpp each still hand-parsed a few
argv flags directly (mount/log/state/ignore/loglevel in headless and the
app, xres/yres/dpi/scale in SDL), duplicating and in some cases conflicting
with the shared CommandLineOptions parser. Consolidate all of it into
CmdLine.cpp/.h so there's a single source of truth, and drop the now-dead
remain_argc/remain_argv filtering in SDLMain.cpp since NativeInit no longer
reads argv itself.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfFvWzpHxErWgRhKqqSewN
2026-08-05 16:02:49 +02:00
Henrik Rydgård e0c942e862 Windows ARM64 buildfix (no GL available) 2026-08-05 09:24:12 +02:00
Henrik Rydgård 905650921e Android hang fix when switching backends, buildfix 2026-08-05 00:59:33 +02:00
Henrik Rydgård 4add25e6c7 Buildfixes, bump gradle 2026-08-05 00:15:56 +02:00
Henrik Rydgård ecae62e737 Fix headless with OpenGL for SDL 2026-08-05 00:15:56 +02:00
Henrik Rydgård 551e4cd0ab Headless: Make all GPU backends work correctly on Windows 2026-08-05 00:15:56 +02:00
Henrik Rydgård 25cf52176f Misc headless work 2026-08-05 00:15:56 +02:00
Henrik Rydgård e0ddfc7109 Add --print-equal-lines option to headless, good for context when looking at output 2026-07-29 18:55:00 +02:00
Henrik Rydgård c99a303646 Fix behavior so we can turn off "IgnoreBadMemAccess" in headless 2026-07-29 18:38:25 +02:00
Henrik Rydgård 54618c67c6 Headless improvements 2026-07-29 16:27:33 +02:00
Henrik Rydgård e30b90e709 Quiet and improve some logs 2026-07-27 18:37:28 +02:00
Henrik Rydgård 5ef736f6a7 More command line improvements 2026-07-27 18:37:28 +02:00
Henrik Rydgård 4bf36fc7f8 Add command line option --vsh to try to boot the VSH. Logspam reduction, improve printf logs. 2026-07-27 14:58:59 +02:00
Henrik RydgårdandClaude Opus 5 afe9b09278 Headless: make ApplyToConfig() the final authority over g_Config
Reordered main() to: g_Config.RestoreDefaults() -> headless's own hardcoded
overrides for deterministic test execution -> cmdLineOptions.ApplyToConfig()
-> CoreParameter setup -> launch. Previously ApplyToConfig() ran first and
got silently overwritten by both RestoreDefaults() and the hardcoded
overrides, so no command-line flag touching a g_Config setting actually took
effect for a real run (this is what required the "set iRemoteISOPort again"
workaround for --debugger=PORT, now removed).

The two hardcoded lines that used to read coreParameter.renderScaleFactor/
gpuCore now compute the same values directly from cmdLineOptions/glWorking/
gpuCore instead, since CoreParameter is no longer built yet at that point -
it's now constructed after ApplyToConfig(), which is what let those two
comments' "above"/"below" wording get corrected too.

Verified: --debugger=PORT still binds the exact requested port and pauses
the CPU, and a normal --compare test run (cpu_alu) still passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDNwPPuidmNxQGRJxBuRL6
2026-07-27 10:44:36 +02:00
Henrik RydgårdandClaude Opus 5 7e5dca0309 Unify --debugger=PORT for both the app and headless builds
The headless build's own --debugger=PORT never actually worked on
Windows: headless/Headless.cpp never called net::Init() (WSAStartup),
so socket binding silently failed ("Unable to listen on any port
(debugger - webserver)"). Fixed by calling net::Init()/net::Shutdown()
there, gated on --debugger being passed since headless has no other use
for networking.

With that confirmed working, move parsing into the shared
Core/CmdLine.cpp auto-param table as a single --debugger=PORT option
(0 = pick automatically) available on both CmdLineMode::Application and
CmdLineMode::Headless, replacing the previous app-only boolean
--debugger flag and headless's separate ad hoc argv scan for it.

Behavior differs deliberately by build, same as before:
- App: just starts the debugger, game boots and runs normally.
- Headless: also forces coreParameter.startBreak = true (break before
  anything runs), as it always has. Headless re-applies iRemoteISOPort
  after its own g_Config.RestoreDefaults() call, which runs after
  ApplyToConfig() and would otherwise wipe the requested port.

Verified live: headless now binds the requested port and responds to
cpu.status/game.status; the app build binds the requested port and
runs the game normally (not paused).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDNwPPuidmNxQGRJxBuRL6
2026-07-26 21:49:37 +02:00
Henrik Rydgård 3eb056ad86 Move Common/GraphicsContext.h to Common/GPU/GraphicsContext.h 2026-07-26 13:58:17 +02:00
Henrik Rydgård afe4d5beaf Buildfixes, dependency shuffling to make things more logical 2026-07-24 14:43:34 +02:00
Henrik Rydgård 16c7ec390f Headless: Start taking logic out of the "HeadlessHost"
Also update some agent files
2026-07-21 11:01:48 +02:00
Henrik Rydgård 8666a3cd57 Add resolution scale parameter to headless 2026-07-20 21:40:14 +02:00
Henrik Rydgård 9a2342b98e SDL buildfix, headless logic fix 2026-07-20 19:18:18 +02:00
Henrik Rydgård 4b24c187f2 Move more command line parameters to the new parser 2026-07-20 17:44:19 +02:00
Henrik Rydgård a886cfb5ab First step of centralizing command line parsing 2026-07-20 12:02:07 +02:00
Henrik Rydgård f5a8ad172e Fix various issues with the headless build (for running frame dumps) 2026-07-19 00:09:06 +02:00
Henrik Rydgård 6b9596cf4e Make D3D11 work for framedump testing 2026-07-18 20:06:03 +02:00
Henrik Rydgård 8ff9793e32 Headless: Update the documentation, remove outdated teamcity stuff (used DeepSeek V4 Flash) 2026-07-18 18:35:46 +02:00
Henrik Rydgård 4eae44f98a Make Headless a bit more flexible about saving screenshots 2026-07-18 18:28:32 +02:00
Henrik Rydgård 61e1ef8f7a Remove the "Software skinning" option. Now always on. 2026-07-14 17:02:57 +02:00
Henrik Rydgård eb234a1563 Finish the split. Greatly simplifies the render code in EmuScreen. 2026-02-08 10:46:16 +01:00
Henrik Rydgård f01aaeafb1 Split CopyDisplayToOutput in preparation for the next step 2026-02-08 01:06:32 +01:00
Henrik Rydgård 7853881210 GPU header cleanup: Avoid including GPUCommon.h in some places 2025-11-23 20:37:37 +01:00
Henrik Rydgård 67010ff2af Split the display layout config between landscape and portrait orientations 2025-11-05 12:49:51 +01:00
Henrik Rydgård a656496953 Remove setting for fast-forward mode 2025-10-20 19:53:21 +02:00
Henrik Rydgård 461f8586b6 Use config defaults in the headless binary.
Fixes #19332
2025-09-24 11:56:51 -06:00
Henrik Rydgård b472eb8b8b Remove a lot of unnecessary string constructors 2025-08-31 15:49:29 +02:00
Henrik Rydgård 380fa19d3c Another std::string_view change, buildfix 2025-08-31 15:24:33 +02:00