Commit Graph
77 Commits
Author SHA1 Message Date
Henrik Rydgård 49f92ebcb6 Merge pull request #22368 from hrydgard/remove-minimp3
Remove minimp3
2026-09-28 11:31:40 -06:00
Henrik RydgårdandClaude Opus 5.5 761e2f3706 Remove minimp3
MP3 emulation already went through FFmpeg, leaving MiniMp3Audio dead.
The one live user was loading MP3 UI sound effects (custom achievement
sounds), which now splits the file into frames and decodes them with
the FFmpeg MP3 decoder.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 10:57:02 -06:00
Henrik RydgårdandClaude Opus 5.5 5f261bd7ff Utility: Stand in for the HtmlViewer, offering to open the page in a browser
Instead of the PSP's web browser, a dialog shows the URL the game wants
and opens it in the host's browser on X, or backs out on O. Either way the
game sees the browser closed normally. Platforms that can't open a URL
(the new SYSPROP_CAN_LAUNCH_URL) only offer to back out. Only plain
printable-ASCII http(s) addresses are handed over, and on Linux without a
shell.

What the firmware does (sceUtility_Driver, 6.61, plus
utility/dialog/htmlviewer): the HtmlViewer has its own state apart from the
other dialogs, so they don't block each other, and its calls return
WRONG_TYPE until one has started. The request size picks the 2.00 to 3.00
layout, and InitStart allocates 3.5MB of user memory (4.5MB with options
bit 0x400 from 2.70 on), failing with 800200d9 without it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 12:50:23 -06:00
Henrik RydgårdandClaude Opus 5.5 e932d55f1c Build: Only turn off floating-point contraction for CPU emulation
The vertex decoder's C++ steps may fuse, like the vertex JITs do; with
contraction off everywhere, RISC-V's VertexJit test found the JIT and
the steps disagreeing on morphed float UVs. The flag now applies to
Core/MIPS only, in CMake and the libretro Makefile. ndk-build has no
per-file flags, so the legacy Android.mk goes back to the default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:59:04 -06:00
Henrik Rydgård 428c1a6aa6 Merge pull request #22343 from hrydgard/vfpu-interpolator
VFPU: Replace fp64's correction tables with accurate implementation of special functions
2026-09-24 10:46:33 -06:00
Henrik RydgårdandClaude Opus 5.5 d6b3d590eb VFPU: Compute log2, sin/cos and asin without correction tables, too
They use the same quadratic interpolator as rcp and friends, with three
twists. sin indexes the quarter wave from the top, and asin and sin work
in a per-segment exponent whose 4-ulp truncation also applies to results
in a lower binade. log2 truncates exponent + log2(1.m) toward zero to 22
significant bits, and where that step is coarser than 2^-24 the datapath
drops coefficient bits to match; that also covers the region just below
1.0 that needed a special case.

vfpu_sincos now reduces the angle once. With every table gone, so are
the asset folder, the loader, InitVFPU and the fallbacks for tables that
failed to load. All seven functions are bit-exact with the table-based
code over every 32-bit input.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 10:07:01 -06:00
Henrik RydgårdandClaude Opus 5.5 30fada5833 Utility: Run GameSharing through a placeholder dialog, quiet its WRONG_TYPE logs
GameSharing InitStart used to return 0 without starting anything, so its
GetStatus stayed at NONE and a game waiting for the dialog to finish
would hang. It now goes through the normal lifecycle (INIT, RUNNING,
FINISHED, SHUTDOWN, NONE) and reports that the user cancelled.

PSPPlaceholderDialog was abstract and unused (and missing from CMake);
it's now that stand-in.

WRONG_TYPE from GameSharing GetStatus/Update/ShutdownStart is what a PSP
returns whenever another dialog type was the last one started, so log it
at debug like the other dialogs. Sega Rally polls it every frame.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 19:25:24 -06:00
Henrik RydgårdandClaude Opus 5 184c2cb4ea Implement sceVideocodec, the ME's H.264 decoding interface
The last piece mpeg.prx needs from us. It decodes through AvcDecoder and writes
the result where sceMpegbase expects to read it: for type 0, the eight-buffer
tiled layout, produced here as the exact inverse of the reader added with the
colour conversion. Type 1 hands back plain planar YUV instead.

The descriptor mpeg.prx passes in is empty - on hardware the Media Engine owns
the frame buffers and reports back where it put them - so they are allocated
here and their addresses filled in, and sceMpegbase can recover the full set
from that allocation afterwards. The list is only read as addresses once it
holds addresses: a caller that leaves small integers there used to take us
straight into a memory exception.

Both those buffers and the block sceVideocodecGetEDRAM hands out live in a
model of the ME's own 2MB of embedded DRAM rather than in either PSP partition,
with a BlockAllocator carving it up. The CPU can't reach ME memory on hardware:
mpeg.prx keeps the EDRAM value and hands it back without ever dereferencing it,
and it has no way to say where the frame buffers should go - sceVideocodecSetMemory
is given a frame size and a buffer count, 480, 272 and 2 for a full-screen movie.
Taking either from the game would push its own allocations around or spend memory
a real PSP never spends, so sceMpegbase reads the frame through a host pointer
into that block instead of through Memory::.

A game can hold several contexts at once - Silent Hill Origins runs two, one
that owns the EDRAM and one that does every decode - so the decoder, the frame
buffers and the EDRAM address are per context, keyed by context address the way
sceAudiocodec keys its decoders. The EDRAM itself the firmware tracks in the
caller's context struct and nowhere else, including refusing a second request
rather than replacing the first, as videocodec_260.prx shows, so we do the same.

Registered at the end of RegisterAllModules, since a savestate stores the
syscall opcode encoding that order.

GetSEI, ScanHeader, GetFrameCrop and the two unnamed NIDs return 0 and log -
mpeg.prx calls them but nothing yet shows what they need to return, and
guessing seemed worse than being loud about it.

Untested: nothing calls this until mpeg.prx is loaded, which is the next step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 12:53:13 -06:00
Henrik RydgårdandClaude Opus 5 3276cdf65f Add AvcDecoder, a plain access-unit-in, frame-out H.264 decoder
sceVideocodec is the interface the Media Engine really exposes: the caller owns
the buffers and hands over one access unit at a time. MediaEngine can't serve
that shape - it is built around sceMpeg's own model, with the PSMF demuxer, the
ringbuffer and its own frame pacing wrapped around the decoder - so this is a
second, separate path rather than a refactor of code every game that plays
video depends on. Merging the two is worth doing once sceVideocodec has earned
its keep.

Nothing calls it yet; sceVideocodec is the next piece.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 12:53:13 -06:00
Henrik RydgårdandClaude Opus 5 7c6f9d18b8 sceMpegbase: implement the colour conversion functions
Five of the six functions in this module were registered as nullptr, so any
caller reaching them got nothing. mpeg.prx needs all of them, and this is the
first of the pieces required before the real module can run in place of our
sceMpeg HLE.

The module gets its own file at the same time. It was a tail of sceMpeg.cpp,
which is long enough already, and everything below is new code for it.

sceMpegBaseCscAvc and sceMpegBaseCscAvcRange convert the ME's decoded output to
RGB. The 48-byte descriptor holds the frame size in macroblocks at 0x10 and
0x14 - it appears at 0x00/0x04 too, but scaled differently depending on which
path built it, so the second pair is the one every caller agrees on - and the
four luma buffers at 0x20. What they point at is not planar: luma arrives as
16-pixel-wide vertical strips alternating between buffers on every other line,
and chroma as Cb/Cr pairs interleaved across four more. All eight are untangled
into planes once per frame before converting, which keeps the pixel loop
readable.

sceMpegBaseCscInit carries the default buffer width for callers that pass zero.
sceMpegBaseCscSetPixelMode (0x0530BE4E - the official name isn't known) carries
the output format, in mpegbase's own numbering rather than the GE's: mpeg.prx
gets it by indexing a table of {1, 2, 3, 0} with the pixel mode the game gave
sceMpegAvcDecodeMode, making 0 ABGR8888 and 2 ABGR5551. Read as a GE mode it
turned Thrillville's black into blue.

sceMpegBaseYCrCbCopy copies the descriptor but not the buffers it points at,
and says so in its log - nothing seen so far needs more, and inventing the
buffer copy without something to test it against seemed worse than a note.

Behaviour is cross-checked against JPCSP, which implements all of these.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 11:52:09 -06:00
Henrik Rydgård f161e7f9f9 Revert "Expose the MIPSTracer over the WebSocket debugger"
This reverts commit ccdaa94f53.
2026-09-09 08:07:19 -06:00
Henrik RydgårdandClaude Opus 5 5089caf2a0 Add a reader for PKG game update packages
PSP game updates were distributed as NPDRM .pkg files holding a patched
EBOOT (PBOOT.PBP) plus the data files the patch replaces. PkgUnpack reads
one: header, item table, both PARAM.SFOs, and the AES-128-CTR that covers
everything past the header - including the per-item key split, where an
item's pspType byte picks between the PSP and PS3 keys.

Nothing new is needed to decrypt these. All packages checked use PRX
tag 0x2E5E10F0 for their PBOOT, which PrxDecrypter already has a key for.

Also adds "PPSSPPHeadless --install-pkg=DIR", a sibling of --unpack-updater,
which installs without any UI. All packages install through it byte
-identically to a reference implementation.

Format notes are in docs/pkg_notes.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 11:15:11 -06:00
Henrik RydgårdandClaude Opus 5 ccdaa94f53 Expose the MIPSTracer over the WebSocket debugger
The tracer records every basic block the CPU executes and can write the
instruction stream out to a file, which is the tool you want when something
corrupts state and the question is "what actually ran just before". It was
only reachable from Developer Tools in the UI, so a scripted session had no
way to turn it on, and reconstructing the same thing from log-only breakpoints
means guessing what to watch before you know what happened.

Five events: cpu.tracer.start/stop/flush/clear/status. start takes the two
buffer sizes and clears the JIT cache by default, because blocks compiled
before tracing was on don't carry the LogIRBlock instruction the tracer feeds
on - without that a hot loop compiled earlier simply never appears. The trace
ring is cyclic, so a finished recording holds the last maxTraceSize blocks:
start it, run into a crash, and the tail of the file is the instructions that
led there.

Only the IR cores drive the tracer, so start refuses on the others and says
which core is loaded rather than recording nothing; status reports the same
thing as `supported` so a client can tell that apart from "nothing executed".
Everything that mutates tracer state goes through Core_RunOnCPUThread, per
docs/DebuggerThreading.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 18:43:38 -06:00
Henrik RydgårdandClaude Opus 5 917cb1b0fc Implement KL4E/KL3E decompression, so firmware modules that use it can load
KL4E is Sony's second compression scheme for ~PSP modules, alongside gzip:
LZ77 tokens where every bit is arithmetic-coded, structurally close to LZMA.
PPSSPP could detect it but not decode it, so any module packed with it failed
to load at all - the loader reached the gzip path and bailed there.

Which scheme a compressed module uses is now decided by the payload's own
magic rather than assuming gzip. On a 6.61 flash0 dump this takes the kd/
modules that load from 126 to 129 of 129; libmp3.prx, libaac.prx and
libmp4.prx were the ones affected, and libmp3.prx decompresses to exactly the
elf_size its PRX header declares.

Two bounds problems in the format are fixed rather than reproduced: the match
copy is unchecked against the output buffer on real hardware, so a crafted
stream can write up to 255 bytes past it, and a long enough distance code
indexes copyDistProbs out of range. Input reads are bounded too - the format
carries no length and trusts the stream to terminate itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 11:06:17 -06:00
Katharine Chui 2731918f05 cleanup aemu_postoffice building in cmake project files 2026-09-06 14:09:33 +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ård e64ed141b3 Merge pull request #22124 from hrydgard/psar-unpack
PSAR file format support: Automatic unpacking of firmware updates
2026-08-21 10:31:58 +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ård 0ed6b97921 First step towards drawing a cleaner line between what should be in the libretro core and not. 2026-08-20 08:32:11 +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 83b1d13c88 Debugger: add kernel object introspection over the WebSocket API
New events, all read-only (never mutate kernel state, no cleanup/sort calls
- see HLEKernelObjectSubscriber.cpp's header comment):

- hle.object.list: every live kernel object of every type at once (uid,
  type, name, one-line quickInfo), with an optional 'type' filter. Uses
  KernelObjectPool::IterateAll(), a new type-agnostic sibling of the
  existing Iterate<T>().
- hle.eventflag.list/info, hle.mutex.list/info, hle.semaphore.list/info,
  hle.msgpipe.list/info, hle.callback.list/info: per-type full detail
  (all Native* status struct fields plus waiting-thread lists), reading
  straight off the classes exposed in the previous commit.

Also adds JsonWriter::DictScope/ArrayScope (Common/Data/Format/JSONWriter.h)
- RAII push/pop for pushDict()/pushArray(), used throughout the new
  handlers. A forgotten or early-returned pop() previously just produced
  silently malformed JSON; with 11 new handlers each writing a handful of
  nested arrays/dicts, that seemed worth fixing at the API level rather
  than trusting every call site to pair things up by hand. Existing
  handlers are untouched - this is purely additive.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 16:01:23 +02:00
Henrik RydgårdandClaude Sonnet 5 ce33c964f7 Debugger: add log.channels.list/log.channel.set over the WebSocket API
Lets a client query all log categories (Common/Log.h's Log enum) with their
current level/enabled state, and change a channel's level and/or enabled
state at runtime - same data LogConfigScreen already exposes in the UI, now
reachable from the debugger protocol. Levels are named strings (notice,
error, warning, info, debug, verbose) rather than the 1-6 numbers the
existing passive 'log' event uses (LogBroadcaster.cpp, left unchanged) -
clearer for a config-style API where you're not scanning a stream.

Registered as a new subscriber alongside the others in WebSocket.cpp, and
wired into all the build systems that need a new source file (CMake, the
Windows and UWP vcxprojs, Android.mk - libretro's Makefile.common doesn't
build any WebSocket debugger files so needs no entry).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 16:01:23 +02:00
Henrik RydgårdandClaude Sonnet 5 2ee4f2fadb Debugger: add gpu.displaylist.disasm - a GE display list decoder over the WebSocket API
Decoding a GE display list previously meant memory.read-ing the raw bytes
and hand-decoding each 32-bit command word against GPU/ge_constants.h's
GECommand enum - which is exactly what it took to find this session's
actual headline VSH boot finding (a display list that clears the screen
once, sets up per-icon render state 6 times, and never issues a single
further draw call - see docs/VSHBootInvestigation.md Attempt 22). That
manual process is real, repeatable, and error-prone by hand; PPSSPP
already has a proper GE disassembler (GPU/GeDisasm.cpp's
GeDisassembleOp(), and GPUCommon::DisassembleOpRange() built on top of
it) used by the ImGui/Windows GE debugger UI - it just wasn't reachable
from the WebSocket API.

New Core/Debugger/WebSocket/GPUDisasmSubscriber.cpp exposes
gpu->DisassembleOpRange() as gpu.displaylist.disasm, mirroring
memory.disasm's own parameter conventions (address+count or
address+end, capped at 10000 commands) and compact mode (one string per
command, "AAAAAAAA  desc", instead of the full {address,cmd,op,desc}
object) added in the previous commit. GE command words live in normal
guest RAM like CPU code, so - unlike gpu.buffer.* - this doesn't require
the CPU/GPU to be paused first, matching memory.disasm's own live-read
behavior.

Added to all 6 build systems that compile the WebSocket debugger
(CMakeLists.txt, Core.vcxproj(.filters), UWP's CoreUWP.vcxproj(.filters),
android/jni/Android.mk - libretro doesn't build any Debugger/WebSocket
files at all, so nothing to add there).

Verified live via PPSSPPHeadless + wsdbg against a real demo ELF: both
compact and full-JSON modes correctly decode real GE command words (NOP/
NOP_FF) with no errors. UnitTest.exe all: 49/49 passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-14 11:04:32 +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 3c81d6b121 More manual Read_U32 cleanup
Buildfix
2026-08-11 10:28:36 +02:00
Kevin Reinholz 615da42df3 Fix build when USE_SYSTEM_MINIUPNPC cmake option is enabled. Adding a compile definition for it in Core/CMakeLists.txt is not enough; rather than add a duplicate definition in UI/CMakeLists.txt so NativeApp.cpp's include of Core/Util/PortManager.h handles the conditional location of miniupnpc headers correctly, adding it once in the root CMakeLists.txt ensures both Core and UI handle it properly 2026-07-26 13:10:50 -07:00
copilot-swe-agent[bot] 0e2995b30e Fix iOS build: use CMAKE_BINARY_DIR for git-version.cpp so it stays at the build root 2026-07-24 23:25:32 +02:00
Henrik RydgårdandClaude Sonnet 5 688eb99a53 Fix miniUPnPc add_compile_definitions ordering in Core/CMakeLists.txt
Same class of bug as the USE_DISCORD fix: add_compile_definitions() only
affects targets created after the call, but the whole USE_MINIUPNPC block
sat after add_library(Core STATIC ...). That meant Core/Util/PortManager.cpp,
built as part of that same add_library call, never actually saw WITH_UPNP
or any of the other miniupnpc defines - UPnP support was silently compiled
out on every platform.

Split the block: compile definitions and the miniupnpc source-file/include
setup now run before add_library(Core STATIC ...), while building the
bundled miniupnpc target and linking it into Core (which needs the Core
target to already exist) stays after, in its original spot.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSNaZnHCjmryS3ziVN9gZU
2026-07-24 20:16:07 +02:00
Henrik RydgårdandClaude Sonnet 5 abe6786ae1 Rename core to Core and extract it and GPU into their own CMakeLists.txt
Mirrors the earlier Common extraction. The old "core" target folded in
all of GPU/ (~200 files) plus a few ext/ files wholesale; Windows
already treats GPU as its own project (GPU.vcxproj), so GPU/CMakeLists.txt
splits that out too. GPU has a genuine two-way dependency with Core
(Core/System.cpp calls GPU_Init(), GPU/* calls back into Core for
Memory/Config/CoreTiming/etc), so GPU is a CMake OBJECT library: its
object files are always included wherever consumed instead of being
lazily pulled from an archive, avoiding the GNU ld single-pass
archive-ordering problem a two-way STATIC dependency would hit.

Also fixed a few library misattributions discovered while tracing what
each file actually uses:
- GlslangLibs (glslang/spirv-cross) moved from Core to Common, since
  it's Common/GPU/ShaderTranslation.cpp and VulkanContext.cpp that
  call into it directly. It only worked before because Core happened
  to always be linked after Common.
- ZSTD and OPENGL_LIBRARIES/X11_LIBRARIES moved from Core to GPU,
  matching where they're actually called (GPU/Debugger/Record.cpp and
  Playback.cpp for ZSTD, GPU/GLES for raw gl*() calls).
- GPU also needs Ext::Snappy directly (Playback.cpp calls
  snappy_uncompress) and the libretro-common include dir under
  LIBRETRO, both previously inherited for free by accident.

Also fixed USE_DISCORD's add_compile_definitions ordering: it was
being defined after ppsspp_ui's add_library call, so the UI target
never actually saw it on non-MSVC platforms.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSNaZnHCjmryS3ziVN9gZU
2026-07-24 20:16:07 +02:00
Henrik Rydgård c6789c28f9 Remove unused Core/CMakeLists.txt 2015-09-26 19:23:54 +02:00
sum2012 6aec7238fb Attempt to fix linux build 2015-03-08 12:40:30 +08:00
Henrik Rydgard 62d86f3246 Remove useless indirection class "PSPMixer" 2015-01-11 12:02:49 +01:00
daniel229 1ff9507f7c Add sceUsbGps module 2014-08-13 00:11:26 +08:00
Unknown W. Brackets b9ede6aade Add a class to create helper threads from HLE.
This should be usable from sceIo as well.
2014-05-22 23:38:21 -07:00
raven02 8ed82f3d25 Fixes #5779 with new PSPScreenShotDiag class 2014-04-30 19:28:05 +08:00
raven02 161d8b29fb Implement sceMt19937() 2014-01-25 20:17:53 +08:00
shenweip ce50086c81 Add new files to cmake and Android.mk 2013-10-13 10:32:56 +08:00
shenweip 82ad9ba853 Add GamedataInstallDialog to CMakeLists and Android.mk 2013-09-13 23:19:53 +08:00
Unknown W. Brackets 7ac67a8931 Add a function to walk the stack, not yet perfect.
Could use improvements, but with a decent symbol table does very well so
far in the games I tested it in.
2013-08-12 01:54:14 -07:00
Unknown W. Brackets e6b42768fe Add a class to manage IO on a separate thread.
Also separate the logic for exiting the loop based on coreState.  IO and
audio won't necessarily be tied to the frame.
2013-08-11 11:46:55 -07:00
Unknown W. Brackets 256394b2bf Move VirtualDiscFileSystem to its own file. 2013-07-28 12:31:48 -07:00
sum2012 c2091de3d5 Add dummy sceCcc
Fix loading of Gensou Chronicle
2013-06-30 20:21:56 +08:00
oioitff 6fb2abd0fb Add sceAudiocodec stuff 2013-06-09 01:28:58 +08:00
mattweb28 d3ded6639a Added sceJpeg & sceMd5 2013-05-15 19:49:34 +08:00
Jacky TSUI 95addc09b1 Separate sceMp3 from sceMpeg 2013-05-06 21:14:58 +08:00
sum2012 76cdbb7f5e build fix for other 2013-04-30 01:34:23 +08:00