- 23efd22efb : Fix Stuck issue on some games (Dissidia 012, Full Auto 2, etc) when Failed to connect to Adhoc Server (faked success)
- 7ec860c24f : Adhoc: Stop waiting for a login that has already failed
Drawing now takes the style and scale too, like measuring, so the text
drawers have no font state left. UIContext keeps its current style and
passes it, and fills it in from the theme if nothing has set one yet.
PPGe passes its one font.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pspautotests audio/sceaudio/input and audio/sceaudio/routing.
- sceAudioInput fails until sceAudioInputInit, then checks that the
sample count is a nonzero multiple of 64 before checking the rate
(11025, 22050 or 44100 only). A rate of 0 now gets the PSP's error
instead of the USB mic's. Init takes about 3ms.
- A blocking mic input woke with the byte count rather than the sample
count that the non-blocking call returns.
- The routing functions are exported by both sceAudio and
sceAudioRouting, and the latter had its own copy that ignored the
stored modes. Both now share the one in sceAudio, with the ranges
checked. SetVolumeMode returns 0, not the previous mode, and both
modes start at 0.
sceAudio's savestate section goes to version 5 for the input init flag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- sceHeapDeleteHeap never freed the heap's memory. Allocation failure
returned -1 rather than a null pointer, and a near-4GB size wrapped.
- The USB wait timeout resumed threads that were no longer waiting on
USB, and UsbUpdateState resumed them too, and never rescheduled.
- The Mersenne Twister drew from mt_[index_] with the index taken from
guest memory. It's now taken modulo the state size. sceSfmt19937
checks its index, and that fill arrays are at least a state long,
which the library writes regardless of the length it's given.
- sceCccEncodeUTF16's surrogate test also caught U+F800 - U+FFFF, which
includes the fullwidth forms.
- sceAudioRoutingSetVolumeMode stored the routing mode.
- A sample rate of 0 to sceAudioInput or the camera mic divided by zero,
and a huge sample count sized a host buffer. sceP3daBridgeCore's sizes
could wrap. sceRtc's tz offset could overflow tm_min.
- Camera shutdown freed the frame buffer and config without the lock
the capture thread uses. GPS data is set from the platform's location
thread, so it's now locked too, and the satellite index is bounded.
- A loop in the sys event handler list hung the unregister.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The SAS thread waited without checking the state first, so a mix
queued before it got to the wait was missed, and the next drain hung.
The state is now atomic too.
- SAS raw output mode writes four planes, twice the size it asked for.
- DMACplus colour conversion with a huge stride overflowed its size
math. The syscon serial data index wasn't bounded on reads, writes or
load.
- Replace_memcpy_swizzled copies whole 16x8 blocks, more than the
pitch * h it asked for. The God Eater depth hook tested the color
buffer twice instead of the depth buffer, and its size could wrap.
- GranularMixer used 1/0 before the first FPS sample, and read the
granule being written next when the queue was empty.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The apctl, NpAuth and NpMatching2 event loops kept references to the
front of their deque after popping it, so callbacks could get the
next event's arguments. NpMatching2 also dereferenced its optional
opt param when it was null.
- The resolver was left stopped after any savestate load or reboot,
which broke Outrun 2006 (it relies on it starting out running).
- Getpeername/Getsockname with a namelen under 2 copied a negative size.
They now write the PSP's 16-byte sockaddr truncated to namelen, with
sa_len 16, as pspautotests net/inet/poll shows on hardware.
- Poll handed an fd that isn't open (-1) to FD_SET. It now reports
POLLNVAL for it and counts it, as on hardware (net/inet/poll).
Setsockopt read past a local u32 for larger options, and passed a
negative optlen to the host. A zero cmsg_len looped forever.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pspautotests modules/idlist shows that sceKernelGetModuleIdList still
writes a partial entry at the end of the buffer (a size of 6 gives two
entries), which the previous commit had stopped. A NULL buffer or a
negative size returns ILLEGAL_ADDR without writing the count.
sysmem/kernel/heap shows sceKernelAllocHeapMemory returning null for
sizes near 4GB, rather than wrapping. The WithOption variant already
checked this. The plain one now does too.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- sysclib strchr/strrchr searched for the whole string, not the
character, so they returned 0 for any nonzero c.
- A thread ending with blocks from more than one TLS pool leaked every
other block, since the restarted loop's ++iter skipped an entry.
- FPL's nextBlock grew by up to numBlocks per allocation and eventually
overflowed into a negative block index. Old states with a negative one
now reset it rather than failing to load.
- sysclib strncpy bounded its copy by the source's valid size only, not
the destination's.
- sceKernelAllocHeapMemory wrapped for sizes near 4GB, and
sceKernelGetModuleIdList could write a partial entry past the buffer
size and dereferenced a missing module.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Action type IDs start at 0, and the first one registered is
ActionAfterMipsCall, but MipsCall::DoState used 0 to mean no action.
So every call made with __KernelCallAddress lost its action chain on
load: the thread's wait state was never restored when the call
returned, and chained actions never ran.
Version 2 of the section marks a missing action with -1.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
GameManager translated install errors when storing them, and the install
screens then looked the translated text up again as a key. It now stores the
category and key, and translates when asked. The raw ISO install error gets
the existing "Installation failed" string.
Some other errors went around as strings that were then used as keys:
- A missing savestate file now has its own error code, ERROR_FILE_MISSING,
instead of a key in the failure reason.
- The PKG reader's reasons are technical English, so they're now shown
untranslated under the translated "This PKG file isn't a PSP game update".
- The netconf dialog looked up the channel number. Only "Auto" is translated
now, using the WLAN Channel setting's string.
- Adds the missing "Failed to read old directory" for memstick moves.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The MIPSTracer page's "log file" is the trace file, and some strings had odd
spacing, grammar or capitalization. The auto load savestate toast now uses the
setting's key instead of a duplicate one, and the English fallbacks in code
match en_US.ini.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
These were looked up in a different section from the one with the translation,
so they always showed in English (the savedata error messages, "Done!" after
moving the memstick, "Switch UMD", "Ask for network permission" and others).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
0b1e1a9bb3 put the PopsMMIO entries inside the MeMMIO ones, leaving
unclosed tags, so Visual Studio couldn't load the filters. Also adds
the missing Util\KL4E.h.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
We don't support the headphone remote buttons, so we just leave
the buffer all zeroes. Previously we didn't write, which could cause
games to register a ghost "track forward" or the other buttons.
Should fix the DJ Max 2 OST track-forwarding problem in #7468.
Saves are written on a worker thread, so a state saved just before opening the pause
menu may not be on disk yet when the slots are listed, and the slot stayed empty.
Post SAVESTATE_SLOT_SAVED when a slot save is written, and recreate the pause
screen's views on it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
As on a PSP: pressing HOME in a game shows "Do you want to quit the game?"
over it. The game keeps running but gets no input while it's up (sceCtrl
samples are blanked). Left/right picks Yes or No, the confirm button (our
Confirmation button setting, or what compat forces) chooses, the other face
button or HOME closes it, and Yes/No can be tapped. The volume keys change
the game volume a step at a time, shown on the volume bar.
Yes runs the game's registered exit callback first, like the PSP does,
showing "Please wait..." meanwhile. Then, if the XMB launched the game, the
XMB is booted again; otherwise it's back to the game browser, like Exit to
menu. If the callback hasn't ended the game in 10 s, it's quit anyway. Not
in the XMB itself, the PS1 emulator (its own HOME menu) or GE dumps.
It lives in UI/ImposeHome.cpp; EmuScreen only feeds it input and frames and
draws it over the PSP display.
With a firmware dump installed, it's drawn with the firmware's own art from
flash0:/kd/resource/impose.rsc, which is what impose.prx draws it from:
prerendered text for each system language (the question, Yes/No normal and
highlighted, Enter/Back, Please wait...), the button icons, the lines, the
volume bar, the battery and the clock glyphs. The format is documented in
ImposeHome.cpp. Without one, the same screen is drawn with our font and
simple shapes at the same positions.
Where impose.rsc doesn't say where things go, the layout follows
impose_02g.prx (6.61), decrypted and disassembled:
- The screen is filled with 0x9CE7 (#393939); the images are opaque.
- Lines at (80, 96) and (80, 175); impose.prx grows them from the middle
when it opens, which isn't done here.
- Volume bar: the speaker at (28, 223), 30 steps from x 62, 12 apart. It
shows our game volume in the PSP's 30 steps.
- Button guide: the cross icon always left, the circle right, "Enter" and
"Back" next to whichever confirms and cancels.
- Status bar: the battery at (450, 5) (60% and up full, 30% two bars, 12%
one, then empty), the clock ending next to it at y 5: "M/D H:MM", or
"D/M" for the DD/MM/YYYY format, no leading zero on the month, day or
hour, AM/PM for the 12-hour clock.
The clock is the emulated PSP's local time (__RtcGetCurrentLocalTime, new),
in the system's date and time formats. The battery is this device's, since
the emulated PSP's is always full; a device without one shows it full.
For that, Windows now reports -1 for SYSPROP_BATTERY_PERCENTAGE without a
battery (was 100), as SDL already did; SDL polls the battery even when the
status overlay doesn't show it, and the overlay leaves it out when there's
none.
Core side: __CtrlSetGameInputBlocked; __KernelCanExitToVSH and
__KernelRequestExitToVSH to quit to the XMB from outside a syscall; and
__KernelInvokeRegisteredExitCallback(toVSH), so a callback that returns
without exiting ends in the XMB rather than powering down.
New strings: "Do you want to quit the game?", "Please wait..." (Dialog).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NB244iFpvm14JH2FbwHXeQ
The XMB ejects the disc when it boots without one, and __UmdInit resets
the rest of the UMD state but not UMDInserted. So after visiting the XMB,
any game booted next saw an empty drive and waited forever for its disc
(Brandish: The Dark Revenant stops after registering its UMD callback),
until PPSSPP was restarted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
The video player only gets the AAC flags it needs when the XMB has booted
the ME in mode 3, and an XMB older than 6.60 asks for that under another
NID, which stayed unresolved: on 6.00, SAMPLE.MP4 said "This video cannot
be played". The NIDs come from matching the function in each version's
me_wrapper.prx. hleKernelNids grows three columns for the generations
before 3.95.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Fixes#22764
pspautotests video/mpeg/cscvme shows the two luma buffers are fields, each
with its own chroma, and that the rows land as they do for
sceMpegBaseCscAvc: woven together without a second buffer, packed one per
buffer with one. The XMB's Motion JPEG player passes the second buffer
right after the first with the picture's halves as the fields, which is
why the halves model happened to work for it.
The hardware's colours match the scalar conversion exactly, so CscVme uses
that rather than swscale. Fields packed back to back now reach the GPU as
one write, so a texture over the whole picture isn't cut at the first.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The XMB's video player renders Motion JPEG AVIs with sceMpegBaseYCrCbCopyVme
and sceMpegBaseCscVme (JPCSP's names), which take planar YCbCr in two halves
rather than the ME's tiled layout. The copy sizes follow mpegbase_260.prx.
sceMpegBaseYCrCbCopy took the frame size from the destination descriptor,
which the same player leaves unset. mpegbase_260.prx reads it from the
source, in pixels.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Fixes#22763
The XMB's video player boots the ME in mode 3 through sceMeCore_driver's
sceMeBootStart (5dff5c50), where games get mode 2. Mode 3 only changes the
argument to ME command 0x185 (me_wrapper.prx), and the player sets the AAC
context flag at 0x2d on anything newer than a PSP-1000 and plays those
files, so sceAudiocodecInit now accepts the 0x2c/0x2d flags in mode 3.
Games still get the failure pspautotests audio/audiocodec/context records.
Also implements the two vaudio calls the player uses: a ChReserveBuffering
that routes each buffer through an ME effect (E8E78DC8), and the setter for
its parameter (504E4745). The effect isn't known, so audio goes out as is.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An Android 11 TV played nothing over a Bluetooth headset since the switch
to Oboe, while its speakers worked. Testing on it showed AAudio with MMAP
is silent there and AAudio without MMAP works, as does OpenSL ES (also
when the headset is connected mid-game), whatever the stream usage. MMAP
should never be used for a Bluetooth route, so it's a firmware bug.
Audio settings get an Audio API choice and a Low-latency audio (MMAP)
checkbox, with hints, so other devices with the same kind of bug can be
worked around. The API defaults to OpenSL ES on TVs and before Android
8.1, where the choice isn't offered, and AAudio elsewhere. Changing them
reopens the streams right away. System Information shows the output
stream that got opened (API, MMAP or not, rate, buffers, device) and any
audio error.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>