Commit Graph
49765 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 bbc6d2e1e4 CMake: Put the bundled FFmpeg's headers first on the include path
On macOS a newer FFmpeg's headers (Homebrew's) came first through another
library's include directory, and AVIDump.cpp failed to build against them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:54 +01:00
Henrik RydgårdandClaude Opus 5.5 d0e3141f43 FFmpeg: Vendor what PPSSPP uses into ext/ffmpeg, drop the submodule
The ffmpeg submodule held prebuilt libraries for every platform next to the
sources (about 1.5 GB checked out), and nothing uses those any more. Only the
needed sources are copied in, from the submodule's commit, along with every
header and template they include. The path is new, so checking out commits on
either side of this works.

It's also cut down to what PPSSPP uses: the H.264, AAC, MP3, ATRAC3 and ATRAC3+
decoders, the H.264 parser, the demuxers as before, and the FFV1 encoder, AVI
muxer and file protocol for AVI dumping. config.h takes its CONFIG_ values from
FFmpeg 3.0.2's own configure run with just those enabled. The raw H.264 demuxer
stays even though nothing opens raw H.264: probing PSMF data uses it to identify
the video stream's codec, which otherwise comes out as none.

On top of that:
- The files nothing links (configure would build them, but they're never pulled
  out of the static library, going by the GCC link map) are left out: mostly
  libavutil's crypto and hashing and the alternative DCT/IDCT/FFT versions.
- libswresample isn't built, now that nothing uses it.
- The H.264 decoder only does 8-bit video, which is all the PSP has. The SPS
  parser rejects any other bit depth, and the DSP files no longer build their 9-
  to 16-bit variants, which the linker kept because the init functions pick one
  by bit depth at run time.

That's 160 files to compile instead of 277, and 391 of FFmpeg's vendored, about
5.8 MB. The README in ext/ffmpeg has what was done, the PPSSPP patches in the
copy, how to add a component, and the tradeoffs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:54 +01:00
Henrik RydgårdandClaude Opus 5.5 a8068d1742 AVI dump: Always use FFV1, remove the option to use MPEG-4
The lossy MPEG-4 encoder (with the MPEG-video encoding code it needs) is most
of what FFmpeg's encoders weigh, and lossy footage is better recorded from the
output with a screen recorder. Dumps are now always lossless FFV1, which also
makes for much larger files than the old default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:54 +01:00
Henrik RydgårdandClaude Opus 5.5 e031502d27 Audio: Convert FFmpeg's output to s16 ourselves, drop libswresample
FFmpegAudioDecoder only used swresample to turn the decoders' output into
interleaved stereo s16, at the same sample rate. A small conversion does that
now, with swresample's rounding: floats go through lrintf and are clamped, and
mono goes to both channels at -3 dB, the coefficient swresample's mixing matrix
uses. Its output is sample-identical to swresample's for the MP3, AAC and
ATRAC3+ decoders, mono and stereo.

With "Use FFMPEG for all compressed audio", ATRAC3 got closed on its first
frame: its decoder sets no channel layout, and swresample refused to set up
without one. The conversion goes by the channel count, so that no longer fails.

The system-FFmpeg build no longer looks for libswresample.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:53 +01:00
Henrik RydgårdandClaude Opus 5.5 ce27034379 Docs: How FFmpeg is built now
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:53 +01:00
Henrik RydgårdandClaude Opus 5.5 03ac2c8ded libretro: Link FFmpeg as a static library of its own
With its objects on it, the MSVC link command line got too long for Windows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:53 +01:00
Henrik RydgårdandClaude Opus 5.5 b0d2f8c92b CI: Check out only the FFmpeg sources, not the prebuilt libraries
Every build compiles FFmpeg now, so the per-platform library paths are gone, and
the Alpine job no longer builds it with the old script.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:53 +01:00
Henrik RydgårdandClaude Opus 5.5 70a0a9dd00 Android, libretro: Build FFmpeg from source
The ndk-build builds (android/jni and libretro/jni) get a static library module
with the files in ext/ffmpeg-build/sources.mk, in place of the prebuilt
libraries. The libretro Makefile compiles them itself, with FFmpeg's include
directories first so its config.h wins over the others on the include path, and
puts the objects in obj-ffmpeg/ rather than next to the sources, where a
configure build may have left its own.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:53 +01:00
Henrik RydgårdandClaude Opus 5.5 3015d1f085 Windows: Build FFmpeg from source, in a project of its own
ext/ffmpeg-build/ffmpeg.vcxproj (and UWP/ffmpeg_UWP for UWP) builds the same
sources as CMake, copied from sources.mk by update_vcxproj.py. It's optimized in
Debug too, and without /Zc:inline, since MSVC otherwise keeps references to
disabled components that FFmpeg expects the compiler to drop.

The projects that linked the prebuilt libraries reference it instead, and take
the headers from the source tree.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:53 +01:00
Henrik RydgårdandClaude Opus 5.5 99727d8fbc FFmpeg: Build it from source with CMake by default, without a configure step
ext/ffmpeg-build now has a committed config.h in place of the configure checks.
Assembly and arch-specific code are off, as in the --disable-asm builds of the
old prebuilt libraries, so only the platform has to be told apart, with a few
preprocessor checks. The sources are listed once in sources.mk, for every build
system to use, and build one static library. ATRAC3 and ATRAC3+ are enabled to
match the prebuilt libraries, and HAVE_AV_CONFIG_H is now defined, as FFmpeg's
own build does.

CMake builds this unless USE_SYSTEM_FFMPEG or FFMPEG_DIR is set, and no longer
looks for the prebuilt libraries in ffmpeg/. MinGW now builds it too, instead
of falling back to the system's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 22:27:53 +01:00
Henrik Rydgård 3a41fca43d Merge pull request #22782 from hrydgard/play-crash-fixes-2
Fixes for crashes and ANRs from the 1.21-beta1 Play reports
2026-10-25 20:22:21 +01:00
Henrik Rydgård 8585cc77bf Merge pull request #22761 from cscd98/libretro-vr
Add Stereoscopic and Immersive VR to libretro core
2026-10-25 20:00:14 +01:00
Henrik Rydgård 9b7d5e605a Merge pull request #22781 from hrydgard/old-firmware-versions
Old firmware version loading/unpack fixes
2026-10-25 19:46:29 +01:00
Henrik RydgårdandClaude Opus 5.5 70f205f2ff Take output screenshots after the ImGui debugger has drawn
The screenshot readback ran in ScreenManager's post-render callback, and
on Vulkan it ends the backbuffer render step. renderImDebugger() draws
after that, so taking a screenshot with the debugger open made its first
SetViewport() write through a null render step (an assert in debug
builds, a Play crash report in release). Do the readback at the end of
the frame in NativeFrame instead, which also puts the debugger in the
screenshot, and remove the now unused callback.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 19:44:21 +01:00
Henrik RydgårdandClaude Opus 5.5 2ce1164725 Log: Don't open the log file while holding its lock
SetFileLogPath() held logFileLock_ while creating the folder and opening
the file, and both log (CreateDir at INFO, OpenCFile for content URIs and
on errors). Logging to the file takes logFileLock_, so the thread
deadlocked on itself, and every thread that logged after it blocked too.
A Play ANR shows the loading thread stuck in CPU_Init's
SetFileLogPath, and the main thread waiting on the same lock to log a
key press.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 19:37:37 +01:00
Henrik RydgårdandClaude Opus 5.5 daf46b1dbc Don't set up a signal alt stack in the memory fault handler
sigaltstack() is per thread. InstallExceptionHandler() runs in CPU_Init()
on the loading thread, which exits after boot, while the faults come from
the CPU thread and UninstallExceptionHandler() runs on the emu thread. So
our stack was never used, and the uninstall "restored" the loading
thread's previous alt stack onto the emu thread. On Android that's the
one bionic gives each thread and frees when the thread exits, so every
later fault on the emu thread ran its handler on freed memory. A Play
crash report shows scudo finding a corrupted chunk header when freeing our
stack in UninstallExceptionHandler().

The alt stack came with the Dolphin code, which needs it to handle its own
stack overflows. Ours only handles guest memory faults, so let the handler
run on the faulting thread's stack, or the alt stack that thread already
has. This also leaves a libretro frontend's alt stack alone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 19:37:23 +01:00
Henrik RydgårdandClaude Opus 5.5 42f9af1744 MemBlockInfo: Clamp marked ranges to the address space
A size that makes addr + size wrap around 32 bits had Split() build a slab
that ends before it starts. Lookups then skipped it, and a later
Merge() ran FillHeads() over it with a huge count, writing far outside
heads_. Sizes come from games through HLE calls, and the large ones are
recorded even without detailed mem info. Seen in a Play crash report, on
the FlushMemInfo thread.

FillHeads() also took the address one past the end of heads_ for a slab
in the last slice, which Debug builds assert on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 19:37:23 +01:00
Henrik RydgårdandClaude Opus 5.5 d8655d8810 Android: Build the bundled zlib in the ndk-build build too
The NDK's zlib is too old for uncompress2(), which the PSAR unpacker now uses,
so link ext/zlib like the CMake build already does on Android. It's linked
whole, since the prebuilt FFmpeg libraries come after it on the link line and
libavformat uses it too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 19:11:03 +01:00
Henrik Rydgård 8a50821839 Merge pull request #22779 from hrydgard/settings-break-out-pages
Setting reorg part #1: Break out Speed Hacks and PSP Settings into their own pages.
2026-10-25 19:03:37 +01:00
Henrik RydgårdandClaude Opus 5.5 6a9b84a714 VSH: Add the 3.6x key for the XMB index
3.60's index.dat carries tag 0x0B2B10F0, which sceResmgr_9DC14891 had no key
for, so the shell couldn't read its item index and stopped on "A serious
error has occurred". The key follows the tag in 3.60's mesg_led_02g.prx, laid
out like the other versions' (3.52's mesg_led.prx has the 3.5x key the same
way). 3.60 now boots to the XMB.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 19:00:55 +01:00
Henrik RydgårdandClaude Opus 5.5 fb371af6bb PSAR: Unpack the 1.00 updater, and the pre-decrypted 3.60 archive
The 1.00 updater's DATA.PSAR is a version 1 archive, the only one there is,
and its blocks carry tag 0x06000000, which the PRX decrypter had no key for.
1.50's mesg_led.prx keeps its keys raw in a table after their tags, the
0x0E000000 one we already use among them, and the 0x06000000 one there
decrypts all of 1.00 (with KIRK code 0x49, following the other tags). Its
first record has no version text either, so the version now comes from the
firmware's own version.txt when that's missing.

Fix a zlib usage bug.

Headless --unpack-updater also exited 0 when every file failed, so now it
fails if any did.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 19:00:48 +01:00
Henrik Rydgård 16103889f4 Merge pull request #22777 from hrydgard/remove-outdated-reporting
Cut down on outdated/useless REPORTing and logging
2026-10-25 18:07:02 +01:00
Henrik Rydgård 21d5c61bad Setting reorg part #1: Break out Speed Hacks and PSP Settings into their own pages.
Also Cardboard VR, though should probably just remove it, it's pretty
useless.

This PR also serves as a demonstration of how to do that. It's easy!
2026-10-25 18:06:23 +01:00
Henrik Rydgård 6c790c701d Merge pull request #22778 from hrydgard/settings-system-page
Settings: Move the System tab to UI/Settings/SystemPage.cpp
2026-10-25 18:04:23 +01:00
Henrik Rydgård 1c329a1e44 Merge pull request #22776 from hrydgard/umd-video-interlace
UMD Video: Give a field pair one SEI record per field
2026-10-25 17:36:27 +01:00
Henrik Rydgård 518795e35f Cut down on outdated/useless REPORTing and logging 2026-10-25 17:33:44 +01:00
Henrik RydgårdandClaude Opus 5.5 827ec470fe Settings: Trim GameSettingsScreen.cpp's includes
Now that all the tabs are built elsewhere, it only needs a fraction of them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 17:26:38 +01:00
Henrik RydgårdandClaude Opus 5.5 0ed9c8542b Settings: Move the System tab's builder to UI/Settings/SystemPage.cpp
Like the other tabs, except that the screen keeps what the page edits that
isn't a config setting (the compatibility reports flag, which is written
back when the screen closes, and the Windows memstick checkboxes' state) in
a SystemPageState it passes in. The page's handlers move with it, as
functions taking the page host or that state.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 17:23:10 +01:00
Henrik RydgårdandClaude Opus 5.5 b570c96d68 Settings: Remove the unused memstick folder callback
Nothing calls CallbackMemstickFolder or sets pendingMemstickFolder_, which
are left over from an older way of changing the folder on Android.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 17:19:46 +01:00
Henrik Rydgård b89a57e9a4 Merge pull request #22774 from hrydgard/xmb-recents-icon
XMB: Show it in Recents, with an icon and its firmware version as the title
2026-10-25 17:08:42 +01:00
Henrik RydgårdandClaude Opus 5.5 22348ddbff UMD Video: Give a field pair one SEI record per field
Family Guy and The Dark Knight are coded as separate field pictures,
bottom field first. ffmpeg hands each pair back as one frame, and we
described it with the first field's SEI record only.

The UMD Video player (video_main_plugin.prx) shows such a picture a field
per vsync, and takes the field order from comparing the output times of
the picture's two records. With the second left empty it always chose
top first, so every pair ran backwards in time and the picture jittered
between frames. Now the pair carries both fields' timing, the top field's
record first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 16:51:24 +01:00
Henrik Rydgård 588d2e5745 Merge pull request #22773 from hrydgard/settings-pages-moves
Settings: Move the settings pages to a file each, and rename DeveloperToolsScreen
2026-10-25 16:25:30 +01:00
Henrik RydgårdandClaude Opus 5.5 a64d590c94 XMB: Show it in Recents, with an icon and its firmware version as the title
The XMB (vshmain.prx) was kept out of Recents because it had no icon. Now
the game list shows it as "XMB 6.61" (the installed firmware's version, from
its version.txt), with an abstract XMB icon in white on blue, and the window
title says the same instead of "Unidentified PSP title".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 16:15:24 +01:00
Henrik RydgårdandClaude Opus 5.5 7fd4029333 DevTools: Rename DeveloperToolsScreen to DeveloperSettingsPages
There's no screen in it any more, only the developer tools' settings pages.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 16:01:35 +01:00
Henrik RydgårdandClaude Opus 5.5 a5b470b2c3 Settings: Move the settings tabs' builders to a file each in UI/Settings
Only moves code. The tabs other than System were built by static functions
in GameSettingsScreen.cpp, in place of the old methods, to keep the previous
change's diff readable. Now each tab has its own file, with just the
includes it needs, and MainSettingsPages.h declares their builders.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 16:01:34 +01:00
Henrik Rydgård ed8c15cf14 Merge pull request #22771 from hrydgard/settings-pages
Settings: Build the settings screen from pages described as data
2026-10-25 15:54:03 +01:00
Henrik Rydgård 3b36f85b6b Merge pull request #22772 from hrydgard/android-inputbox-no-fullscreen
Android: Keep the keyboard from covering the text input dialog
2026-10-25 15:35:14 +01:00
Henrik RydgårdandClaude Opus 5.5 b91bd6af86 Settings: Build the settings screen from pages described as data
Each tab is now a SettingsPage: a list of items (headers, settings, buttons,
hints, links to other pages) that a function builds and views are created
from. Settings are added with page->Setting(&g_Config.x), which takes
the label, the kind of view, the range or choices, units, labels for special
values and the default from the config. The pages keep what depends on the
UI (which settings to show and when, enable rules, and behavior that needs the
screen), and reach the screen through the page's SettingsPageHost.

A page can link to other pages, which open on top of it in the same tab,
under a bar showing where you are, like Tools > Developer tools > Graphics,
where the earlier pages can be clicked to go back to them. The bar has back,
search and help buttons, and the back key also goes back a page (or out of a
search) before leaving the screen. Each page remembers its scroll position.
In portrait there's no tab strip: a page links to the tabs, and the bar shows
just the current page's title. Rotating keeps showing the same page. Moving
between pages only focuses an item when navigating with a keyboard or
controller.

The developer tools are now pages linked from the Tools tab, instead of a
screen of their own. The in-game developer menu and
--start-screen=developertools open the settings on that page. The toggles of
live state (the remote debugger and the MIPS tracer) show and change it
through functions, and pretending to be in-game for the notification tests is
a flag on the OSD. The memory map and memstick tests, only reachable from
commented-out code, are removed.

Search lists the matching settings from all tabs and the pages they link to,
grouped by where they are. Each result goes to the setting on its page,
scrolled to and highlighted (outlined, when picked with a mouse or touch), or
for a page, opens it. This replaces the search tab and the old filter that
hid the views that didn't match, and with them ShowSearchControls. Changing
tabs leaves the search.

The pages, the bar and search are in SettingsPagesDialogScreen, between the
tabbed dialog screen and the settings screen, so the other tabbed screens
keep plain tabs.

Other visible changes:
- Reset buttons that went to the wrong value now go to the real default: the
  touch control auto-hide delay (was 20 seconds instead of 8), the mouse
  wheel delay (1 ms, below its own range, instead of 80) and the UI size (0
  instead of -1 on desktop). The alternative speeds get a reset button.
- Units are shown on more sliders (frames, MHz, seconds, Hz), and popups no
  longer spell out what 0 means in the units, since the zero label does.
  Units of up to three characters (%, x, ms, MHz) aren't translated.
- The Android HW scaler hides the scales the display is too small for,
  instead of cutting the list short.
- Choices are translated in the setting's own section.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 15:26:58 +01:00
Henrik RydgårdandClaude Opus 5.5 9e63ff623d Lang: Move and copy strings into the sections of the settings that use them
Settings will translate everything about them (label, choices, units) in one
category, the label's, so:
- "Achievement sound volume" moves from Achievements to Audio, where the other
  volumes are.
- The choice strings of the ad hoc relay mode and chat positions are copied
  from Dialog to Networking, the notification position's to System, and the
  leaderboard tracker position's to Achievements.
- "seconds" is added to Controls and System, for the units of the touch
  control auto-hide delay and the rewind snapshot interval.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 15:12:24 +01:00
Henrik RydgårdandClaude Opus 5.5 3bb4664fd6 Config: Describe the settings for the UI, and find them by pointer
ConfigSetting gets a ConfigSettingInfo, set with constexpr chained setters:
a label, choices, a range with step and units, labels for 0 and negative
values (like Unlimited and Disabled), and a callback for what has to happen
when the UI changes the value. Using a setter on the wrong type of setting is
a compile error. The settings in the config tables now have these, so the
settings screen can take them from there instead of repeating them, including
what changing them needs (resize and GPU config messages, fullscreen, audio
and camera notifications and so on). The settings screen starts using them
in a later commit.

Config::FindSetting finds a setting from a pointer to its value. Defaults can
now also be looked up for blocks that reset as a whole (display layouts, touch
and gesture controls), by reading them from a freshly reset copy of the block.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 15:12:24 +01:00
Henrik RydgårdandClaude Opus 5.5 d41b29607b Android: Keep the keyboard from covering the text input dialog
In landscape, keyboards went fullscreen with an edit box of their own,
covering the dialog and forwarding what was typed to it. Now the dialog's
field asks for no fullscreen editing, and the dialog moves up above the
keyboard.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 15:08:58 +01:00
Henrik Rydgård 09b899845a Merge pull request #22770 from hrydgard/settings-refactor-prep
UI: Small additions ahead of the settings screen rework
2026-10-25 14:22:33 +01:00
Henrik Rydgård 50005d1b1b Merge pull request #22769 from hrydgard/android-mmap-policy-fix
Android: Don't enable MMAP beyond the device's own policy
2026-10-25 14:19:00 +01:00
Henrik RydgårdandClaude Opus 5.5 5cdf4df765 Android: Don't enable MMAP beyond the device's own policy
setMMapEnabled(true) doesn't mean "allow it", it sets the process's MMAP
policy to AUTO, overriding a device whose aaudio.mmap_policy disables
MMAP. Since #22766 we did that on every audio start, and a Xiaomi Pad 5
Pro (Android 13) has been stuck on a blank screen at launch since then.
The likely cause, not yet confirmed on the device: opening a stream on a
MMAP path the vendor turned off, from the UI thread.

Now the checkbox can only turn MMAP off, as on the Bluetooth TV.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 13:49:04 +01:00
Henrik RydgårdandClaude Opus 5.5 4f322eed61 UI: Start normally when --start-screen names an unknown screen
It left no screen at all, just a log full of "No current screen!".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 13:44:44 +01:00
Henrik RydgårdandClaude Opus 5.5 d887057b83 UI: Add a thin chevron image
I_CHEVRON_RIGHT, a thin > for marking items that open another page.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 13:44:44 +01:00
Henrik RydgårdandClaude Opus 5.5 30c9dd3b45 UI: Let clickable views be highlighted without the focus
SetHighlighted outlines the view, following its round corners, to point it
out without giving it the focus, which would turn on keyboard navigation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 13:44:44 +01:00
Henrik RydgårdandClaude Opus 5.5 1c067f32a4 UI: Add ScrollView::ScrollToCenter and GetEnclosingScrollView
For bringing a given view into the middle of the scroll view it's in, rather
than just into sight like focusing does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 13:44:43 +01:00
Henrik Rydgård 68c85fd694 Merge pull request #22768 from hrydgard/xmb-video-formats
XMB video: play MP4 and Motion JPEG from the memory stick
2026-10-25 12:03:10 +01:00
Henrik RydgårdandClaude Opus 5.5 b1401dcbf6 Docs: One HLE entry per function, other firmwares' NIDs go in hleKernelNids
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 11:38:51 +01:00