Commit Graph
284 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5 049bcd5483 Demangle C++ symbol names when loading ELF symbols
C++ homebrew has an unreadable symbol table -
everything is _ZN10PxRenderer7DrawImmE... - which makes the disassembly and
symbol list nearly useless. Add an Itanium C++ ABI demangler and run ELF
symbols through it on load, in both ElfReader::LoadSymbols (unstripped EXECs,
which is what a CMake pspdev EBOOT actually contains) and the companion-ELF
path.

The demangling standard is called Itanium for historical reasons - it
was defined for Itanium but ended up being almost universally
applicable.

Written from scratch rather than using __cxa_demangle, which doesn't exist on
MSVC/UWP, or vendoring LLVM's demangler, whose license doesn't fit. Anything
unrecognized (arbitrary constant expressions, decltype) aborts the parse and
the caller gets the original mangled name back, so a caller never sees a
half-parsed result. Recursion is depth-capped since the input comes from a
file we didn't write.

Checked against c++filt as an oracle: of 1089 mangled symbols in a real C++
homebrew EBOOT, one differs; of 55189 from libstdc++/libLLVM/cc1plus, 22
differ and 413 are declined. Fuzzed with 220k mutated and random inputs under
ASan/UBSan.

Also adds a right-click menu to the ImDebugger symbol list.

Note that SymbolMap stores names in char[128], so the longest STL names get
truncated in the UI. Still far more readable than the mangled form.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X3DbkJ8ShYiXU7q5Tv1LZu
2026-08-26 08:12:45 +02:00
Henrik RydgårdandClaude Opus 5 e7e8d362f0 Add sceResmgr, which is what the VSH uses to decrypt the XMB index
Found the cause of the red error screen the VSH ends on. Every resource load in
the boot succeeds - fonts, all the plugin RCOs, topmenu_icon.rco - and then:

  sceIoOpen(flash0:/vsh/etc/index_02g.dat) -> fd 8
  sceIoRead(8, 092a2d40, 496)
  sceIoClose(8)
  unresolved import sceResmgr/9dc14891, called from 'vsh_module'
  sceKernelExitDeleteThread(1)

index_02g.dat is the index of what the XMB displays, and it is encrypted (it
starts "PSPsysGP"). sceResmgr_9DC14891 decrypts it. There was no sceResmgr module
at all, so the call trapped, the index stayed encrypted, and the ScePafJob thread
building the top menu exited - a shell with everything loaded and nothing to show.

This adds the module and the three tags it needs (0x0B2B90F0/91F0/92F0, keys and
code 0x5C) to PrxDecrypter.

It is not the whole fix yet: pspDecryptPRX() tries decryption types 0, 1, 2, 5
and 6, and this needs type 9, which JPCSP passes explicitly. So the call is now
reached and fails cleanly with a logged error instead of trapping, but does not
yet decrypt. Type 9 is a variant of type 2 and is the next job; the notes in
docs/VSHBootInvestigation.md say where it is in JPCSP and how to check a port
(159 bytes out, starting "release:").

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-24 11:12:59 +02:00
Henrik Rydgård ed5c05fb28 VSH boot: load real kd/ kernel driver modules
Extends LoadAndStartVshKernelModules() to load the 11 real kd/*.prx
kernel drivers for --vsh (dmacman, systimer, memlmd_01g,
loadexec_01g, lowio, idstorage, syscon, rtc, wlan, wlanfirm_01g, utility),
ahead of the existing 4 VSH-specific modules.
Only active when g_runningVSH, no effect on normal game boot.

Improve implementations of sceKernelSm1ReferOperations and sceKernelIsIntrContext.

Add some more MMIO stubs (GPIO, SYSCON).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
(cherry picked from commit 7f3168b7df85e47438900016c9ee7d7ef01a0a28)
2026-08-24 10:58:35 +02:00
Henrik RydgårdandClaude Sonnet 5 04a8948ded Add a VSH-only allowlist for real-loading flash0 modules, sceVshCommonUtil stub and sceVshBridge
Load and start VSH's kernel modules before booting vshmain.prx

A few flash0 modules (vshbridge.prx, paf.prx, common_gui.prx,
common_util.prx) should run for real once we know we're
actually booting the VSH rather than a game, since our fakes are unlikely
to be good substitutes for the genuine thing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSNaZnHCjmryS3ziVN9gZU
2026-08-24 10:58:34 +02:00
Henrik Rydgård a0ecf545a6 Implement or stub assorted functions the VSH is calling 2026-08-21 10:56:06 +02:00
Henrik RydgårdandClaude Opus 5 322b5122d8 Unpack the firmware out of an official updater EBOOT.PBP
An updater's DATA.PSAR is a flat sequence of records - each is 0x150 bytes of
PRX-style encryption header, a 0x110 byte entry describing one file, and then
its compressed contents. So to get the files, you don't actually have to run it
and let it self-unpack - we can just do it.

Two steps per record. First "demangle": the 0x130 bytes at +0x20 are AES-CBC
encrypted on top of everything else and hide the PRX tag at +0xD0, so a KIRK
CMD7 pass with keyseed 0x55 comes first. Then the record is an ordinary PRX blob
for the decrypter we already have, once it knows the tag - 0x0E000000, which is
new here. Its key needs the kirk7 scramble applied, unlike every other key in
that table, which are stored already scrambled; hence the flag on TAG_INFO.

UnpackPSAR() takes a prefix filter, since the planned main use for this is pulling
flash0:/font out of an updater the user supplies (or from an ISO) rather than
extracting whole firmwares, although that can also be interesting for running
the VSH.

Tested on a 6.61 updater: 436 entries, all 418 files decrypt and decompress,
nothing fails. The contents are what they should be - 295 ~PSP modules, 61 PRF
files, 18 PGF fonts, and the encrypted XMB indices.

Two things it doesn't do yet. Every entry in that archive is named with a
five-digit token rather than a path; the real names live in tables 00001-00012
inside the archive itself, under their own separate encryption, so files come
out under the short name for now and the prefix filter can't match them.
And only the zlib compression format is currently supported.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-20 22:41:58 +02:00
Henrik RydgårdandClaude Opus 5 c5e7c4890a Debugger: decode DWARF line info, and show source locations
Homebrew commonly ships its unstripped ELF next to the EBOOT, which is already
how the symbol loader turns z_un_08841f98 into a function name. That same ELF
carries a DWARF .debug_line section, so the addresses can be mapped to source
files and lines too - and a backtrace stops being four hex numbers:

  08841f98  move sp,fp          mesh.zig:163
  0883afa4  li v0,0x0           MenuState.zig:821
  088260d8  andi at,v0,0xFFFF   State.zig:40
  0882a27c  andi at,v0,0xFFFF   engine.zig:468

Surfaced in three places: per frame in hle.backtrace, in the "hit" object that
cpu.breakpoint.hit and cpu.stepping share, and appended to the disassembly
window's status bar. The breakpoint case keys on the pc rather than the address,
since for a memory breakpoint the useful source location is the instruction that
did the access, not the data it touched.

Storage is a plain sorted table of absolute addresses per module. SymbolMap
keeps module-relative addresses because its .ppsym files are meant to be
reloaded by a different game that pulls in the same module; none of this is ever
written anywhere - it's regenerated from the ELF each boot - so there'd be
nothing for relative addresses to buy. Each module owns its own rows and file
names outright and is keyed the way SymbolMap::UnloadModule is, so unloading one
module drops its lines and nobody else's.

The subtle part is end-of-sequence markers. Without them a lookup for an address
in a gap - a compilation unit built without debug info - confidently reports the
last line of an unrelated file. A prototype run over one test binary
mis-attributed 70 of its 349 functions that way, so sequence ends are recorded
as rows with line 0 and a lookup landing on one reports nothing instead.

DWARF 2 through 4 are decoded (psp-gcc emits 2, Zig 4). Version 5 re-encoded the
file table, so those units are skipped with a warning rather than mis-parsed -
nothing targeting the PSP produces it today.

Scope, since it's narrower than it sounds: PRX conversion strips every .debug
section. I checked all 437 pspautotests .prx and CrossCraft's own app.prx -
none have any. Of 24 installed homebrew EBOOTs, zero carry debug info; CrossCraft
only does because it ships app.elf separately. So this helps someone developing
homebrew, and does nothing at all for a commercial game.

Costs about 1.2 MB for a large Zig binary (98383 rows, 438 files) and nothing
for anything without debug info. Follows bAutoSaveLoadSymbols like the symbols
do.

pspautotests 314/314, UnitTest 55/55, CoreUWP builds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-18 13:42:14 +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 d718bda178 Rename MIPSInt/MIPSIntVFPU to Interpreter/InterpreterVFPU
Just a file rename (plus updating all build configs and includes) to
give the interpreter source files clearer names. No functional change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019SKhm9wKEQzRUsx9mTrrtQ
2026-08-12 10:04:40 +02:00
Henrik Rydgård 94d56ab51d Remove irrelevant stuff from the Windows makefile libretro build.
Fixes #22081 , hopefully.
2026-08-11 18:08:55 +02:00
Henrik Rydgård 4160414b31 Vulkan: remove libretro's global function-pointer wrapper hack
libretro/libretro_vulkan.cpp got PPSSPP's libretro core working with
RetroArch's Vulkan integration by globally monkey-patching PPSSPP's Vulkan
loader function pointers (vkCreateInstance, vkCreateDevice,
vkCreateSwapchainKHR, vkAcquireNextImageKHR, vkQueuePresentKHR,
vkQueueSubmit, etc.) so the unmodified VulkanContext class would end up
wrapping RetroArch's already-existing VkInstance/VkDevice instead of
creating its own, and so a fake VkSwapchainKHR (a self-managed array of
images synced against RetroArch's retro_hw_render_interface_vulkan
callbacks) could stand in for the real swapchain that libretro's Vulkan
model doesn't have. Flagged in-code as "a wacky wrapper".

Replaces that with first-class support in VulkanContext for the two things
libretro actually needs:

- Adopting an externally-created instance/device instead of faking
  vkCreateInstance/vkCreateDevice: VulkanContext::CreateInstanceExternal()
  adopts RetroArch's VkInstance; CreateDevice() gained optional
  extraDeviceExtensions/extraRequiredFeatures params so RetroArch's
  requirements get merged into a real vkCreateDevice() call;
  ownsInstance_/ownsDevice_ flags (the latter set via
  SetDeviceExternallyOwned()) mean DestroyInstance()/DestroyDevice() skip
  the real vkDestroy* calls when something else owns the object, without
  needing to intercept anything. VulkanLoader gained
  VulkanLoadFromGetInstanceProcAddr() for bootstrapping from a
  host-supplied proc-addr getter instead of dlopen/dlsym-ing the loader
  ourselves - vkGetDeviceProcAddr is resolved via the real instance handle
  (not NULL), since per the Vulkan spec it's not one of the handful of
  commands queryable with a NULL instance.
- A pluggable presentation backend (Common/GPU/Vulkan/VulkanPresentation.h)
  for hosts with no real VK_KHR_swapchain, replacing the fake-swapchain-
  handle trick. VulkanContext::GetPresentation() is null by default, so
  every existing platform's real-swapchain code path is untouched;
  libretro/LibretroVulkanPresentation implements this interface directly
  against retro_hw_render_interface_vulkan, as real class state instead of
  file-scope globals. Several pieces of state that are normally only
  populated as a side effect of ReinitSurface()/InitSwapchain() - the
  graphics queue/queue family index (ChooseQueue() is entangled with
  real-surface presentation-support checks), the swapchain format, and
  the available present modes - needed presentation-aware fallbacks since
  libretro never calls that real-surface path at all.

libretro/LibretroVulkanContext.cpp now drives VulkanContext's real, public
API directly - no more hijacked function pointers, no more fake surface or
swapchain. libretro/libretro_vulkan.cpp is deleted.

Verified with a full build+run in RetroArch (not just compile-time
checks): the libretro Makefile doesn't track header dependencies
(cl.exe doesn't support -MMD/-MP, and Makefile.common never sets up an
equivalent), so a `make clean` full rebuild is required after any header
change to avoid linking stale object code from before the change - several
of the fixes above were initially masked by exactly that.
2026-08-06 17:07:05 +02:00
Henrik Rydgård e3d36e2741 Move the VulkanGraphicsContext to its correct location in Common/GPU/Vulkan 2026-07-26 14:15:15 +02:00
Henrik Rydgård 0b47955c64 Delete geometry shader culling support. Is mostly replaced, and will be fully replaced with software transform. 2026-05-30 19:07:59 +02:00
Chris Healy ba59170b0b OpenGL: Add GLProfiler for GPU timestamp profiling
Adds a new GLProfiler class for GPU-side timestamp profiling, similar to
VulkanProfiler. Uses GL_EXT_disjoint_timer_query (GLES) or GL_ARB_timer_query
(desktop GL).

Features:
- Scoped Begin()/End() profiling with printf-style naming
- Automatic GPU disjoint detection (frequency changes invalidate results)
- Millisecond timing output via INFO_LOG
- Pre-allocated query pool (1024 queries max per frame)
- Nested scope support with indented output

Signed-off-by: Chris Healy <cphealy@gmail.com>
2026-03-18 09:52:43 -07:00
Henrik Rydgård f046857d2b Delete remains of support for the MIPS architecture as host 2026-02-17 10:20:51 +01:00
Katharine Chui f3e11110ed bump aemu_postoffice
extend max pdp block size, due to user report of the following in
dissidia:

07:53:752 MatchingEven I[SCENET]: HLE\sceNetAdhocMatching.cpp:1188 EventLoop[1]: Matching Event [1=HELLO][00:02:02:02:02:02] OptSize=4696
2026-02-06 11:43:32 +01:00
刘皓 924b30b607 Revert "Disable the libretro VFS on non-Android platforms" 2026-02-06 00:04:19 -05:00
Henrik Rydgård 7d987cd78b Make fast_matrix_mul_4x4 inlineable 2026-01-30 14:10:32 +01:00
Henrik Rydgård ed5a052258 Remove unused initial work for adding NEON support to ARM JITs.
Our SIMD strategy for ARM is the JitUsingIR.
2026-01-29 17:41:57 +01:00
Eric Warmenhoven 58eaf56c5e libretro: build fix
gcc9 and the version of msvc19 that the libretro builders use don't
have _mm_storeu_si32. Using _m_cvtsi128_si32 followed by memcpy is
picked up by compilers that support _mm_storeu_si32 as being the same
and they generate the same assembly, so this is no harm to them.
2026-01-28 00:15:35 -05:00
Henrik Rydgård 34938e3de6 Move Notice to Common/UI 2026-01-25 15:10:26 +01:00
刘皓 84b2744fd7 Disable the libretro VFS on non-Android platforms 2026-01-22 12:07:58 -05:00
Katharine Chui 5aa266934b import aemu_postoffice as a submodule instead 2026-01-19 22:14:51 +01:00
Henrik Rydgård f4dbff0f14 Merge branch 'master' into aemu_postoffice_integrate_v2 2026-01-19 11:40:38 +01:00
Katharine Chui bf30de1527 initial github.com/kethen/aemu_postoffice integration ported from github.com/kethen/aemu 2026-01-11 18:53:54 +01:00
Henrik Rydgård 3f3b353350 Merge pull request #21092 from white-axe/libretro-vfs
Use the libretro VFS interface in libretro builds
2026-01-10 16:36:01 +01:00
Henrik Rydgård e33ff46ffd Extract the rewind code from SaveState.cpp, to make it more managable. 2026-01-08 22:22:46 +01:00
刘皓 cb3a89542c Enable the libretro VFS in libretro builds that use Make 2026-01-02 12:44:50 -05:00
刘皓 6fef11a47d Fix libretro builds that use Make 2026-01-02 12:17:09 -05:00
刘皓 a018cfc017 Update libretro-common and remove redundant libretro header files 2025-12-30 23:06:58 -05:00
Eric Warmenhoven 23bd33748e Fix libretro windows builds 2025-11-25 12:03:47 -05:00
Henrik Rydgård b8fced5b41 Path code cleanup, move some UI code (#21037)
* Move a bunch of path logic into Core/Util/PathUtil.cpp/h

.

* Move GameImageView out from SaveDataScreen

* More cleanup, add a translation string
2025-11-25 00:44:24 +01:00
Henrik Rydgård b304fbe0c9 Build armips in libretro builds (requirement for some lua functionality) 2025-10-08 09:45:44 -06:00
Bobby Smith 46a07943cc [Libretro] Fix Windows build + D3D11 glitches 2025-08-29 02:29:54 +02:00
Henrik Rydgård 92ab532813 No need to build hash.c after all? 2025-08-24 15:25:52 +02:00
Henrik Rydgård 65285e59c4 Bump rcheevos to v12.0.0 2025-08-24 14:58:53 +02:00
Henrik Rydgård 9028866b7f Update libzstd 2025-08-24 14:47:05 +02:00
Nemoumbra acdee76b92 Added dummy NetAdhocCommon files 2025-07-01 19:56:09 +03:00
Henrik Rydgård a82e418ea9 Another libretro buildfix 2025-06-10 18:52:38 +02:00
Henrik Rydgård fd59e7a2ef Don't copy the d3dcompiler dll to distributions 2025-06-10 17:06:34 +02:00
Henrik Rydgård bc63bd7fea Merge pull request #19951 from hrydgard/remove-dx9
Remove D3D9 support, to make future changes easier
2025-06-10 15:29:10 +02:00
Henrik Rydgård 6cfea96e58 Remove D3D9 support, to make future changes easier 2025-06-10 15:07:16 +02:00
Henrik Rydgård a90ef6f430 Update libchdr to latest 2025-06-10 15:05:18 +02:00
Henrik Rydgård fffbed53bc Add a ZipFileLoader, which can let us load any single-file file type from a zip.
Useful for loading framedumps from github without manually having to
unzip each one, for example.
2025-04-12 22:23:23 +02:00
Henrik Rydgård a97ea04827 ImGui: Add "repeatshift" buttons that auto-repeat if you hold shift. 2025-04-09 11:58:31 +02:00
Henrik Rydgård a555fe8924 Partially implement sceReg 2025-04-03 14:13:50 +02:00
Henrik Rydgård cf059ff84c Stub a lua console, add the sol lua wrapper library 2025-03-27 08:59:37 +01:00
Henrik Rydgård 8d9b3f28f2 Reintroduce "cache ISO in RAM" 2025-03-27 00:46:31 +01:00
Henrik Rydgård a156697822 Break out the "Recent ISOs" code into its own file so it's more practical to work on it 2025-03-26 17:31:47 +01:00
Henrik Rydgård 4eaad7d5af Remove the "Cache full ISO in RAM" feature
It's been broken for years and nobody has even noticed enough to report
it.
2025-03-26 09:06:33 +01:00