Commit Graph
6908 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 71b38e58e6 Config: Store the alternative speeds in percent
The settings screen showed them in percent but they were stored as frame
rates out of 60, so the screen kept converted copies and wrote them back. Now
they're stored in percent under new ini keys (AltSpeedPercent,
AltSpeedPercent2, AnalogAltSpeedPercent), migrated from the old frame rate
keys like the audio volumes were, and converted to a frame rate where the
timing needs one.

Low percentages no longer round to a 0 fps limit, which meant unlimited.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 15:28:18 +02:00
Henrik RydgårdandClaude Opus 5.5 a1b4a93cac HLE: Resolve the kernel sceKernelAllocateFpl
It was left unresolved with the kernel mutex calls, as they all let the
flash drivers reach the NAND controller during a VSH boot. It's the
mutexes that do that: with only the FPL resolved, sceIdStorage_Service
allocates from its pool and every firmware's VSH in 1.50-6.61 boots to
the same XMB picture as without it. Resolving the mutexes still hangs on
0xbd101300.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 11:24:14 +02:00
Henrik Rydgård 1adf3c553d Merge pull request #22549 from Kethen/aemu_postoffice_enet
UDP(ENet) mode for adhocctl & aemu_postoffice relay
2026-10-21 23:51:28 +02:00
Henrik RydgårdandClaude Opus 5.5 1fe87ec263 Syphon Filter: Logan's Shadow: Fix the explosion smoke crashing at 60fps
The game shares Resistance: Retribution's effect engine, smoke trails and all: a trail gets a
new node on every update while the nodes expire by the effect's clock, so the faster the game
runs the more smoke there is. When the tank explodes, the smoke grows the display list past its
500KB buffer at a steady 60fps (an overclocked CPU gets there), the list runs into the heap and
the game crashes on a bone array it overwrote. Hook the same two functions as in Resistance:
nodes at most every 1/30 of the effect's clock, and the overflow guard as a backstop. At 428MHz
the list now peaks at 351KB, against 512KB and a crash before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 23:11:23 +02:00
Henrik Rydgård 03457d559b Merge pull request #22716 from hrydgard/vsh-mount-iso
Allow --mount in the app, and make VSH UMD autoboot a setting
2026-10-21 20:57:42 +02:00
Henrik RydgårdandClaude Opus 5.5 2d116a5b76 sceReg: Let a key read a bool setting, use it for VSH UMD autoboot
KeyValue gets an optional pointer to a g_Config bool, which the key
reads as 0/1. The setting wins over guest writes: since category_version
is kept low, the VSH upgrades the registry at every boot and rewrites
every key with its default.

/CONFIG/SYSTEM/umd_autoboot reads the new SystemParam VshUmdAutoboot
(default true, as before). Turned off, --vsh --mount stays in the XMB
with the disc in the Game column instead of starting it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 19:52:38 +02:00
Henrik RydgårdandClaude Opus 5.5 c4034700fc VSH: Return to the XMB with its own args, and when a launch fails
The XMB passes its state as vshmain args (0x400 bytes) when it launches
something. We now keep them and start vshmain with them when the game
exits, so it comes back where it left off instead of booting fresh: no
opening, the launched item selected, and no UMD auto-start. vshmain's
module_start only copies them in when they begin with their size and
0x20, which the kernel has to fill in.

A launch that fails to load (like the Video Demo Disc's game part, whose
EBOOT.BIN is 2384 zero bytes) now goes back to the XMB too, instead of
stopping emulation. Before the args were handed back, this looped: the
fresh XMB auto-started the disc again.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 19:00:01 +02:00
Henrik RydgårdandClaude Opus 5.5 83df04686c sceNet: Register sceNetApctl_lib, for the VSH's network connection screen
pspnet_apctl.prx exports the internal handler, scan and BSS functions to
the VSH under sceNetApctl_lib (as listed by its 6.61 export table). We had
them, but only under sceNetApctl, so the XMB's netconf plugin got an
unresolved import and the browser and online manuals stopped at 8002013A
before their Network Connection screen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 19:00:01 +02:00
Henrik RydgårdandClaude Opus 5.5 9fec7d7fb0 VSH: A game launched from the XMB exits back to it
On a PSP, sceKernelExitGame in a game the XMB launched goes back to the
XMB. Ours ended the session. In a session booted as vshmain.prx, an exit
from anything but the VSH itself now LoadExecs vshmain.prx again; the
shell then plays its opening and comes back on the Game column.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 19:00:01 +02:00
Henrik RydgårdandClaude Opus 5.5 cf29cbdfd7 sceChnnlsv: Allow no key in sceSdGetLastIndex and sceSdCreateList
Both took their key through GetPointerWriteOrException, which raises a
memory exception for 0, though the code behind them treats a null key
as no key. The VSH's Saved Data Utility checks PARAM.SFO hashes without
one, and emulation stopped there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 19:00:01 +02:00
Henrik RydgårdandClaude Opus 5.5 8d6a0134c6 sceIo: The memory stick's raw device (msstor), for the Saved Data Utility
The VSH's Saved Data Utility opens msstor0p1:/ to ask whether a stick is
in and writable (ioctls 0x02125008/9) and what type it is (devctl
0x02125802), and gave up quietly when the open failed. msstor paths now
open as a node with nothing behind it, answering those as msstor.prx's
handlers and a PSP do (pspautotests io/msstor/msstor): in, writable, type
0x40, without rescheduling, and 0x80220183 for a short output buffer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 19:00:01 +02:00
Katharine Chui 07190a820d adhoc load state bring up adhoc before adhocctl and bring down adhoc after adhocctl 2026-10-21 18:13:40 +02:00
Henrik RydgårdandClaude Opus 5.5 3bba517d46 sceMpegbase: Field conversion in sceMpegBaseCscAvc
The descriptor's +0x08 and the second output pointer (pspautotests
video/mpeg/cscavc): with a second buffer the fields are split and packed,
even rows into the first and odd ones into the second, and +0x08 leaves
the odd field out; without one, rows stay in place and +0x08 skips the
odd ones. The VSH's UMD Video player converts the top field of its 720x480
pictures this way, and our 480 full rows ran over the UI library's VRAM
allocator. Each field is converted with its own chroma rows, as
interlaced 4:2:0 has them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:44 +02:00
Henrik RydgårdandClaude Opus 5.5 add84fb36f VSH: sceVaudio_driver, sceVaudioChReserveBuffering and the display panel ID
The VSH's video player outputs sound through vshbridge.prx, which imports
sceVaudio under its driver name, so every sceVaudioOutputBlocking went
nowhere. Register the same functions as sceVaudio_driver. The player
reserves its channel with sceVaudioChReserveBuffering, which in vaudio.prx
is sceVaudioChReserve with a flag set; treat it as that.

It also polls sceDisplay_driver_996881D2 through vshbridge.prx, and skips
setting up its picture output when it's 0. display_02g.prx's init sets
that from the LCD panel type in IdStorage (0x0103000B for type 1,
0x0103020F for type 2), so it's never 0 on a PSP.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:44 +02:00
Henrik RydgårdandClaude Opus 5.5 9f5d074a0e sceVideocodec: Picture records, SEI and sequence timing, for UMD Video
The VSH's UMD Video player reads what the ME writes beside each decoded
picture, which games' mpeg.prx only passes through (pspautotests
video/mpeg/avcdetail, recorded on a PSP):

- Given a 0x540-byte buffer at ctx+0x38, as mpeg_vsh.prx provides in the
  modes the player uses, the ME points each picture descriptor's +0x24
  and +0x28 at two 0xA4-byte records for it. The first is the picture's
  SEI record: cpb_removal_delay at +0x18, dpb_output_delay at +0x1C, the
  pic_struct at +0x20 (which the player picks a duration with), and flags
  of 7 for a keyframe and 2 otherwise. sceVideocodecGetSEI writes the
  record of the last access unit decoded to the buffer at ctx+0x50.
- A descriptor's +0x20 is 1 for a keyframe. The player drops every
  picture after starting or seeking until it sees one.
- The 0x64 bytes at ctx+0x30 carry the VUI timing (num_units_in_tick at
  240000 ticks a second), which the player checks against 5005 for film.

All of it comes from what ffmpeg's H.264 parser reports per access unit,
which AvcDecoder now hands back with each picture.

Each picture also goes into the next of the four frame stores, as the ME
rotates through its own: the player converts a picture in strips spread
over its next few frames, while decoding goes on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:44 +02:00
Henrik RydgårdandClaude Opus 5.5 7d2663bf73 VSH: Insert and eject UMDs from the pause screen
While the XMB is running, the pause screen offers "Insert UMD" with the
drive empty, opening the Switch UMD game picker, and "Eject UMD" with a disc
in. The XMB notices the change through its drive callback, as it does over
the debugger's game.umd.insert/eject. Games keep "Switch UMD".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:43 +02:00
Henrik RydgårdandClaude Opus 5.5 71974b2eab sceMpegbase: Add AC9E717E, CscInit with a caller's colour matrix
In mpegbase_260.prx, sceMpegBaseCscInit calls this with its built-in
22-byte table. The VSH's video player imports it directly. We keep
converting with the standard matrix, and log the one passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:43 +02:00
Henrik RydgårdandClaude Opus 5.5 e5f1e335f6 sceVideocodec: Give the ME 4MB, room for UMD Video's frame buffers
Four 720x480 pictures take 2MB, all of the 2MB ME memory we modelled, so
UMD Video's decoder never got its frame buffers. mpeg.prx accepts ME
addresses up to 4MB. What we allocate still starts at 1MB, so games' videos
get the same addresses as before, and a savestate from before grows its
memory in place.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:43 +02:00
Henrik RydgårdandClaude Opus 5.5 61db5f9459 VSH: Insert UMD Video discs, and report what kind of disc is in the drive
A UMD Video image can now be inserted, and the drive's disc type (devctl
0x01F20001) comes from what's on the disc: PSP_GAME, UMD_VIDEO and UMD_AUDIO
each set their bit. With a video disc the XMB moves to the Video column,
shows the disc with its icon and background, and hands it to the firmware's
video player when selected. sceUmdGetDiscInfo still tells games they're on
a game disc.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:43 +02:00
Henrik RydgårdandClaude Opus 5.5 eee153b220 VSH: An empty UMD drive, and inserting a disc over the WebSocket debugger
The XMB, booted without a game, now starts with an empty drive: when
vsh_module loads with nothing at disc0:, the drive is marked empty, and
activating it tells the shell's drive callback (SceVshMediaDetectUMD)
there's no disc. Activation used to report a readable disc regardless,
so the shell asked for its type and showed "The disc could not be read."
The disc type devctl (0x01F20001) answers 0 without a disc, as JPCSP
does.

game.umd.insert (path) mounts a disc image into the empty drive and
calls the drive callback as inserting one does; game.umd.eject takes it
out. UmdMount() is UmdReplace() without its need for a disc already in.

Inserted into the 6.61 XMB, Daxter shows in the Game column with its
icon, background and animated preview, and launching it boots the game
to its title menu.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:43 +02:00
Katharine Chui c086eab2ed spin down aemu_postoffice during netAdhocInited -> !netAdhocInited load state transition 2026-10-21 16:22:57 +02:00
Katharine Chui 3db71ea1ed fix missing htons in getRelativeLocalIpFromRoutingTable 2026-10-21 16:08:49 +02:00
Katharine Chui ee06afa3bc do not hold adhocctlMutex while adhocctl client is being created 2026-10-21 16:06:29 +02:00
Katharine Chui 23dadb11bf fix savestate enet thread handling again 2026-10-21 15:39:32 +02:00
Henrik RydgårdandClaude Opus 5.5 ed6e5f0e6f Activision Hits Remixed: Limit the front end to one frame per vblank
- Fixes #20287

The menus and manuals flip from a GE finish callback and only sleep 100us
per frame, so the GE's drawing time sets the frame rate. Ours is instant,
so they ran at 400-800fps and the host couldn't keep up. Hook the end of
the per-frame update and wait for a vblank unless one has already passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 15:23:59 +02:00
Katharine Chui 8474ca35b6 guard built-in server warnings with isLocalServer 2026-10-21 14:29:16 +02:00
Katharine Chui 9c8ebfd59f make use of isLocalServer during adhocctl client binding 2026-10-21 14:19:55 +02:00
Katharine Chui 3662d69fb0 restore port offset hint on udp bind failure 2026-10-21 14:19:55 +02:00
Katharine Chui eb9e31a647 refactor initNetwork into adhocctlClientMaintenance 2026-10-21 14:19:55 +02:00
Katharine Chui b8297795ef fix relay + built-in server warning reading stale serverHasRelay 2026-10-21 14:19:55 +02:00
Katharine Chui 3c35584f47 join aemuPostofficeEnetThread if active during load state 2026-10-21 14:19:55 +02:00
Katharine Chui 880158cfdb initial enet mode for adhocctl & aemu_postoffice relay 2026-10-21 14:19:54 +02:00
Henrik RydgårdandClaude Opus 5.5 efaf5e117c HLE: One row per function in the kernel NID alias table
Sony renumbered the kernel NIDs all at once at a few releases, so the
table now has a column per generation (6.60-6.61, 6.30-6.39, 6.00-6.20,
5.01-5.55, 3.95-4.05) and a row per function, instead of an entry per
old NID. A new firmware generation is a new column.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 ad44b4bee2 POPS: Find the disc read's decoder call a few instructions after its size
3.9x's emulators set the block size a few instructions before the jal,
not next to it. Still a single site in every emulator from 4.05 to 6.61.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 74ffca9731 POPS: Boot converted PBPs with firmware 3.95-4.01
They import by 4.05's NIDs; 3.95/3.96's manager is 4.05's at another
layout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 2924e3a090 POPS: Boot converted PBPs with firmware 4.05
The user modules started after the manager now come from the firmware's
own boot configuration (pspbtcnf.bin's POPS mode), since they differ by
version: 4.05's pafmini.prx needs heaparea2.prx first. 6.60's also
lists common_util.prx, which wasn't started before.

4.05 renumbered the kernel NIDs again. Its aliases are checked like
5.55's, and the sysreg ones by what they do to the registers: the call
sites got five of those wrong. Its manager allocates from a pool with
the kernel's sceKernelAllocateFpl, which stays unresolved for kernel
modules (see ThreadManForKernel), so only the manager's import gets the
user one. scePower_driver gets 6.60's clock frequency NID, which 6.20's
and 4.05's old one now map to.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 3c72cc29ab POPS: Boot converted PBPs with firmware 5.01-5.50
They import by 5.55's NIDs, and their managers are 5.55's at other
layouts. 5.0x's scePopsManLoadModule only loads the emulator when its
second argument is nonzero (later ones skip it on 2), so the layout says
what to pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 5460e75265 POPS: Boot converted PBPs with firmware 5.55
5.55's manager is an older design: the kernel hands it the version key
(there's no license probe to replace), and the emulator opens the game
through a manager export that first looks up its license. A converted
PBP has none, so that lookup now returns success, as the MAC checks do.
Store games still need 6.00 or later, so the 5.55 layout only matches
for converted PBPs.

Its code changed too much to map every import by call site, so its NID
aliases are only the ones used here, each checked by its call site (and
the sysreg ones by lowio.prx's code).

The emulator's disc read call is now found by the block size next to
it, which 5.55's pops.prx passes from the other side of the jal: the
same single site as before in every 6.x emulator.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 d008453255 POPS: Boot with firmware 6.00
Its popsman.prx is laid out like 6.10's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 5cefdf7184 POPS: Boot with firmware 6.10
6.10's popsman.prx imports by 6.20's NIDs, and has the same code at
another layout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 23bd32273f POPS: Boot with firmware 6.20
6.20 renumbered the kernel NIDs again, so it gets aliases of its own,
mapped through 6.30's from the call sites in popsman.prx. Its manager has
the same code at another layout, and its scePopsManLoadModule has a
bigger frame (it also picks a model-specific emulator module), so the
layouts now carry that function's frame size for the check.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 d27621d262 POPS: Boot with firmware 6.30-6.39
The manager's code used here is the same from 6.30 on, but 6.30/6.31's
sits at other offsets. The offsets are now a table of layouts, picked by
the code at them when the manager loads, and kept in the savestate (the
patches change that code). With the NID aliases, Crash Bandicoot plays
the same on 6.30, 6.31, 6.35, 6.36, 6.37 and 6.39 as on 6.60/6.61.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 321020a852 HLE: Resolve firmware 6.30-6.39's kernel NIDs through an alias table
Sony renumbered the kernel NIDs between firmware versions, so a module
from 6.3x imports the functions we implement under 6.60's NIDs by other
ones. Rather than a second table entry per function, an alias table maps
the older NID to the implemented one, and GetHLEFuncIndexByNib() falls
back on it. Savestates store the table index, which this doesn't touch.

The 6.30-6.39 entries cover what popsman.prx imports (the same NIDs in
all of them). They come from matching the call sites in popsman.prx's
6.39 and 6.60 builds, whose code is the same, and agree with matching
the exporting modules' code where that's unchanged.

6.30/6.31's popsman.prx also takes the semaphore the main CPU and the ME
share through sysreg calls, which 6.60's does inline: implemented here as
lowio.prx does them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Francisco José García García b3aa456cdd POPS: Pass the manual's name check, and a blank ICON0 for an unusable one
Both as CFW's popcorn does, for any EBOOT. The emulator only shows the
manual when a name the manager hands it matches one it keeps, and popcorn
makes that check pass.

It only takes an 80x80 PNG as ICON0. A converted EBOOT without one hangs,
and one with a 144x80 ICON0 (the size of a PSP game's) crashes it. Such an
ICON0 now reads as a blank 80x80 PNG: its size and its read are replaced.

Both are found by their code, which is the same in pops_01g and pops_02g.
2026-10-21 13:15:30 +02:00
Francisco José García García 478a1e6aa2 sceImpose: Report HOME to POPS from sceImpose_9BA61B49
In impose.prx (6.60), it returns a flag impose's thread sets each pass while
HOME is held, but only if impose leaves HOME to the application. Its init
does that for application types 0x300 (POPS) and 0x400, and
sceImpose_9DBCE0C4 changes it. So games get 0, and the PS1 emulator, which
polls it to open its in-game menu, gets HOME.

It was unimplemented, so it returned SCE_KERNEL_ERROR_LIBRARY_NOT_YET_LINKED.
2026-10-21 13:15:30 +02:00
Francisco José García García bfee675ba5 POPS: Store PS1 games, with the version key from their PGD
The manager's module_start registers its license check with SysMem
(SysMemForKernel_310802A9), and the kernel calls it before loading the game,
which needs the game's license (.rif) and activation. The init thread now
calls it, replaced by one that takes the version key from the disc image's
PGD header (its MAC_70 is the key's MAC), as popcorn does on the Vita. It
latches the key and the content ID fingerprint where the manager's first
successful check would. The disc image's MACs are checked for real, with
sceAmctrl_driver.

Crash Bandicoot's store release is playable, with sound.
2026-10-21 13:15:30 +02:00
Francisco José García García 926bf9d390 POPS: Converted PS1 EBOOTs, as CFW's popcorn plugin runs them
EBOOTs made with popstation and similar tools have a plain disc image of
raw DEFLATE blocks, where a store game has a PGD in the emulator's own
format, and no MACs. Like popcorn: the emulator's decoder calls go to its
scePopsMan_0090B2C8 import, which now inflates; its CD audio track index
check always takes the full-length branch, as the converted image adds CD
audio tracks the index doesn't count; and the manager's two MAC checks
pass.

A converted EBOOT is one whose disc image doesn't start with a PGD.
Crash Bandicoot is playable.
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 0b1e1a9bb3 POPS: Boot PS1 EBOOTs through the firmware's POPS manager
A PS1 EBOOT now boots the installed firmware's POPS manager
(flash0:/kd/popsman.prx), which loads its PS1 emulator (pops_0Xg.prx) for
the game. Load_PSP_POPS stands in for the kernel's reboot into its POPS
configuration: it loads the manager and that configuration's user modules,
and a helper thread makes the kernel init's scePopsManLoadModule(path, 0)
call. InitForKernel reports a POPS boot from the memory stick.

The emulator plays its sound on the Media Engine, so a PS1 boot always
gets the emulated ME, whatever the homebrew setting says, and is refused
on platforms that can't emulate it. The manager boots the ME with its own
code (POPS's reboot has no me_wrapper, so Sony's ME firmware isn't booted
for it), and its ME loop runs there unchanged, playing through the audio
block.

Everything in POPS that reaches hardware registers is kernel code, so a
POPS boot leaves the ME's kernel mode stopgap (g_kernelModeAnywhere) off:
7% fewer host instructions in Crash Bandicoot.

The manager also drives the GE directly: its stall register and FINISH
status are an MMIO device that only answers during a POPS boot, and stall
writes extend the HLE GPU's current list.

The 6.60 and 6.61 popsman.prx and pops_01g/02g.prx have the same code. The
manager's is checked when it's loaded, and any other one fails the boot
with a message. Savestates include the boot's threads.

Reading a game's disc image needs the next two changes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:15:30 +02:00
Henrik RydgårdandClaude Opus 5.5 9d55b8046c ME: The audio block, which the ME plays through
The audio hardware at 0xBE000000, as POPS's ME loop (popsman.prx +2F88)
drives it: after setting it up, it writes one stereo sample (left in the
low half) to 0x70 whenever status 0x28 bit 5 says the FIFO has room,
and sleeps in halt in between on the ME's interrupt source 12. Measured
from the ME on a PSP-1000 (pspautotest me/audiofifo): the FIFO holds 24
samples and plays them at 44.1kHz while 0x04 bit 1 is set; status 0x28
has bit 4 while playing, bit 5 while there's room, and bit 1 once it has
played out its last sample, a sample after the FIFO empties; and source
12 is a level, up while there's room, which halt wakes on with
interrupts disabled. What it plays is mixed into the output.

A halted ME used to sleep until the main CPU's next slice. It now wakes
within the slice when the full FIFO next has room, as POPS's loop sleeps
for every sample.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 12:50:46 +02:00
Henrik RydgårdandClaude Opus 5.5 6936d22b38 HLE: sceSysreg_driver's 6.60 NIDs that the POPS manager uses
popsman.prx starts the Media Engine and sets up audio through them. The
ME reset, bus clock and AVC reset are the calls the older NIDs already
have. The others set bits of registers lowio.prx 6.61 writes for them
(0x50 bit 15+n, 0x58 bit 16+n, 0x60 bit 18, 0x78 bits 7+n and 11), and
C36775AD (called with 0, 1 before audio is set up) isn't read yet. The
system register device now keeps every register it doesn't model.

Under --vsh these stand in for lowio.prx's own, which write the same
registers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 12:50:45 +02:00