Commit Graph
879 Commits
Author SHA1 Message Date
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 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 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 a5c90b61df Android: Use OpenSL ES for audio on TVs, add audio API and MMAP settings
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>
2026-10-24 23:58:42 +02:00
Henrik RydgårdandClaude Opus 5.5 0da3129a69 Touch controls: Add a HOME button, and list HOME with the standard PSP controls
POPS (the PS1 emulator) uses HOME for its menu. The touch button is hidden by
default, and HOME still has no default key mapping. It's also appended to the
custom button and gesture key lists.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 14:14:17 +02:00
Henrik RydgårdandClaude Opus 5.5 8e146f4c24 Android: Keep folder and shortcut grants, re-take the folders we use
Pruning now only runs when the config was really read: when the memory
stick isn't reachable at startup (an unmounted SD card, or right after
boot), NativeInit falls back to defaults and the recent list is empty, so
every recent game's grant looked unused and was released.

Grants for the memory stick, the Games tab folder and pinned folders are
re-taken at every startup. That moves their persisted time up, so they're
the last the system drops if we ever reach its limit. The new time is
written out with the next grant change, which is also the only time the
system prunes.

Home screen shortcuts can't be enumerated, so the 64 most recently
created or launched are remembered in a new [Shortcuts] section of
ppsspp.ini, and their grants are kept. ShortcutActivity runs without the
config loaded, so it queues them in SharedPreferences until the next
startup saves them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 13:54:31 +02:00
Henrik RydgårdandClaude Opus 5.5 04ae3fea5b External display setting: Show the game, or mirror the screen
Graphics > "External display" on iOS and Android. "Show the game" (the
default) is the TV mode, "Mirror the screen" leaves the TV to the system.
A change applies right away. It's disabled on backends that can't draw to
a second swapchain.

On Android 12 and up, a second screen that's part of the device (like a
dual-screen handheld's) isn't used, so the game doesn't move there by
itself.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 22:31:07 +02:00
Henrik Rydgård 679d804c26 Merge pull request #22730 from hrydgard/config-constexpr-parentptr
Config: Alternative speeds in percent, constexpr setting tables, view parent pointers
2026-10-22 18:41:48 +02:00
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
LunaMooandClaude Opus 5.5 3ce3973781 Add overlay (bezel) support
Draws a user image around or behind the PSP screen, to fill the black bars
on displays whose aspect ratio doesn't match the PSP's (#20325).

- Overlays are PNGs in PSP/OVERLAYS. A plain PNG there just works: it's
  drawn in front of the game, and its transparent hole is found by walking
  from the image center to each edge until a nearly opaque pixel. Existing
  RetroArch overlay images can be dropped in as-is.
- A subfolder with an overlay.ini can define overlays with a Name, Layer
  (Foreground/Background) and an explicit Hole=x,y,w,h.
- "Load overlay image..." in the display layout screen imports any PNG
  (including Android content URIs) into the overlays folder and selects it.
- The overlay is fit to the screen (aspect preserved, centered). The hole is
  mapped with the same scale, and the game is fit into it with the normal
  stretch / integer scale / aspect ratio options. Offset and scale don't
  apply while an overlay with a hole is active. This goes through
  CalculateDisplayOutputRect, so touch mapping and post shaders agree.
- The selection is a per-orientation, per-game DisplayLayout setting.
- Disabled in VR, Cardboard, and with skip buffer effects (except software
  rendering), since the presentation path doesn't run there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBg32EFPsTXjAFu7dnTcz
2026-10-22 14:09:51 +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 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
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 f84e63f753 Tilt: Steady the tilt input with the gyroscope where there is one
Tilt used the raw accelerometer as the gravity vector, which jitters with
sensor noise and jumps when the device is shaken. Now, when gyro data is
coming in, a complementary filter integrates the gyro rates and only pulls
the result toward the accelerometer with a 0.5 s time constant, trusting
the accelerometer less the further it reads from 1g. The fused vector goes
through the same ProcessTilt path, so calibration and sensitivity work as
before. Without a gyro, nothing changes.

The fusion lives in TiltEventProcessor behind NativeGyroscope(), so other
sources (DualSense) can feed it too. Android registers TYPE_GYROSCOPE next
to the accelerometer. A "Use gyroscope" checkbox (on by default, per game)
appears in tilt setup once gyro data has been seen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 10:45:37 +02:00
Henrik RydgårdandClaude Opus 5.5 fef84cf0ca CPU: Add the Media Engine core, off by default
MeCore owns a second MIPSState in the ME's address space, held in reset
until released (SetReset). It runs on the interpreter, a slice behind the
main CPU: CoreTiming runs it for the cycles the main CPU has just used, in
Advance and ForceCheck. Its own PRId (COP0 22) and mfic/mtic flag; MMIO
counts as kernel mode on it, and a syscall stops it with an error rather
than reaching HLE. The interpreter's block stepping reads delay slots
through the stepping CPU's memory, and cache instructions log at verbose
level, as ME code flushes its caches in a loop.

Created at boot only for homebrew (PBP with MG category or no SFO, ELF;
the VSH counts, as vshmain.prx loads as an ELF), when "Enable ME
emulation for homebrew" is on: a global checkbox in developer settings,
off by default and not translated yet, or --me-core. Saved in its own
section after MMIO (SaveStart v5), with its own memory; loading a state
creates or removes the ME to match.

The boot page now starts with a reset stub that sends the ME on to
0xBFC00040, where homebrew puts its code (from the firmware's reset code,
read on a PSP-1000).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 22:22:40 +02:00
Henrik Rydgård 6015ff06a7 Merge pull request #22616 from LunaMoo/native-cso-pack
Add built-in CSO packing functionality
2026-10-19 18:53:00 +02:00
Claude 363d816789 Game screen: Compress game as CSO
"Compress game" in the game screen's ... menu, for ISO, CSO, CHD and PSN
EBOOT.PBP games. It opens a list of the CSO presets (and Extract to ISO
for anything that's not an ISO already):

- Best: libdeflate level 12, 64K blocks
- PSP Compatible: zlib level 9, 2K blocks, readable by custom firmware

These match maxcso's presets, and the CSOs come out byte-identical to its.
The writer, Core/FileSystems/CSOCompress, reads the input through PPSSPP's
own block devices, so recompressing is a single pass with no temporary
file.

The original is deleted when done, unless "Keep the original file" is
checked (off by default). When the new name is taken, by a kept original
or another file, a number is added to it.

The work runs on a thread using every core, with a progress bar and time
left at the bottom of the game screen. It keeps going when the screen is
left, and the ... menu offers Cancel meanwhile. On the game list the
game's icon is covered by "Compressing...", and clicking it opens the
game screen instead of playing. When done, recents follow the new file
and the game screen and lists refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CCxekYqPnzNr5d8Tp1q7aZ
2026-10-19 16:01:53 +02:00
Henrik RydgårdandClaude Opus 5.5 ab94767522 VFPU: Drop the inaccurate dot product paths
- Fixes #12082

The bit-exact VFPU dot product is the default everywhere and fast enough,
so the plain multiply-add paths in the interpreter and the IR frontend go,
along with the AccurateVdot setting, --accurate-vdot, the ForceAccurateVdot
compat flag and the Vec4Dot IR op, which nothing emits any more.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 12:11:46 +02:00
Henrik RydgårdandClaude Opus 5.5 57601a9d3b Game browser: Give Recent the toolbar, and the large list by default
Recent gets the view mode and grid settings buttons. It has no path,
nothing to navigate, and its list comes from memory, so the path,
navigation and refresh stay out. Its old grid setting is no longer
migrated, like Games and Homebrew.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 12:32:42 +02:00
Henrik Rydgård 0a9b57371f Delete the spline quality setting 2026-10-16 13:27:26 +02:00
Henrik RydgårdandClaude Opus 5.5 1d5e2689b5 JIT: Add --jit-profile, a sampling profiler for the CPU cores
The native IR JITs get the emulator thread's host PC sampled every 50 us (a
signal on macOS and Linux, SuspendThread on Windows), mapped to blocks, the
routines they call and host functions. The report has each hot block's MIPS,
IR and host code with the samples per host instruction. The IR interpreter's
block timing, previously behind IR_PROFILING, now runs on the same switch.
Both cost nothing when off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 11:01:52 +02:00
Henrik RydgårdandClaude Opus 5.5 1952d20805 Config: Add AccurateVdot, and --accurate-vdot to set it
Not wired to anything yet. It will make every core compute the VFPU's dot
products (vdot, vmmul, vtfm and the rest) bit-exactly like the PSP, through
vfpu_dot().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 edef36d97e Load game patches installed on a PSP, given its Fuse ID
- Fixes #12343

Killzone: Liberation's Chapter 5 DLC is an installer that the PSP turns
into ms0:/PSP/GAME/<id>/KZL.PRX, which the game loads with
sceKernelLoadModuleDNAS. That file is a PGD around a type 3 PRX (decrypt
mode 18), both keyed to the console that installed it. Its Fuse ID
gives everything needed:

- libkirk: the per-console key derivation, and KIRK commands 3, 5 and 8
  built on it (KIRK ROM per uofw, key mesh per psdevwiki).
- PrxDecrypter: type 3, which is type 5 with the first step through
  KIRK command 3 (JPCSP's PRX.java), and the DNAS PGD unwrap.
- sceKernelLoadModuleDNAS uses the new FuseID setting (or --fuse-id).
  Without one, or with the wrong one, the game falls back to its stock
  module and an OSD message says why.
- Headless --re-decrypt takes --re-decrypt-key and --fuse-id, to decrypt
  such a file offline.

Verified with a patch installed on a real PSP: the v1.20 module loads,
starts and reads CHAPTER5.BIN. Type 5 output is unchanged (an NPJH50521
PBOOT.PBP decrypts byte-identically). How to install one over PSPLink is
in docs/dnas-patches.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 18:10:08 +02:00
Henrik Rydgård 4e442b22b2 Merge pull request #22559 from hrydgard/game-browser-xmb-list
Game browser: Add a more XMB-like list format, make default
2026-10-14 14:04:34 +02:00
Henrik RydgårdandClaude Opus 5.5 754e49c6d6 Game browser: Switch existing installs to the large list on Games and Homebrew
Their old grid setting is no longer migrated, so everyone gets the new
view there. Recent and Remote still keep theirs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:12:00 +02:00
Henrik RydgårdandClaude Opus 5.5 ce8f48980a Game browser: Default to the large list for Games and Homebrew, bigger folders
The old GridView keys are now read as ints, so a missing key can be told
apart from false. Configs without them get the new defaults, while
existing ones still migrate their choice.

Folders get taller lines in the large list too, though not as tall as
the games.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:00:00 +02:00
Henrik RydgårdandClaude Opus 5.5 0066599f9a Game browser: Add an XMB-style large list mode
- Fixes #22202

A third view mode next to grid and list: a list with full size icons,
scaled by the grid icon size setting. Like the XMB, the selected (or
hovered) game plays its ICON1.PMF in place of the icon.

The per-tab grid bools become GameBrowserView1-4 ints. The old GridView
keys are still read, to pick the default, but no longer saved.

The PMF decoding moved out of GameScreen's PMFView into a shared
PMFVideoTexture.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 10:24:32 +02:00
Henrik RydgårdandClaude Opus 5.5 4f47475a69 Headless: Support --appendconfig
Merges the settings in an ini file over headless's own defaults, for runs that
need something like JitDisableFlags. Unlike in the app, the result is never
saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:29 +02:00
Henrik RydgårdandClaude Opus 5.5 a89fdb2c9a SoftGPU: Remove the pixel and sampler JITs
The C++ paths draw and sample four pixels at a time in vector lanes,
while a JIT function only does one, and with a JIT function in use the
span and quad paths were skipped. On x86 the JITs had become slower:
Wipeout took 13% more wall time and 25% more CPU with them, God of War
3% more. They were also a second implementation of every GE rule, and
ARM never had them.

The SoftwareRendererJit setting goes with them. RasterizerRegCache.h
keeps only the types the pixel and sampler functions take, as
RasterizerTypes.h.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:44:48 +02:00
Henrik Rydgård 2fe24d1182 Add warning if you run the 32-bit version on 64-bit window. 2026-09-22 10:04:31 -06:00
Henrik RydgårdandClaude Opus 5 c39db565da Run sceMpeg and sceMp4 for real by default
Both now graduate to AlwaysDisableHLEFlags, so a firmware dump gets the real
mpeg.prx, libmp4.prx and mp4msv.prx without anyone having to find the setting.
The checkbox moves from "Disable HLE" to "Force-enable HLE" on its own, so a
game that regresses still has a way back.

Neither can be counted on being there, so HLECheckModuleAvailability drops the
flag when the module is missing and the HLE serves as before - the same thing
sceFont does when flash0:/font is empty. Its sceMp4 check asked the setting,
which is no longer where the answer is now that the default is on; it asks
AlwaysDisableHLEFlags instead, and sceMpeg gets a check of its own.

Both are quiet about it now. Missing firmware used to mean a request we couldn't
honour, which was worth a warning on screen; now it just means the user has no
dump, which is the ordinary way to run PPSSPP.

The cost is that a disc carrying its own mpeg.prx also falls back when there's
no firmware, though it would have run fine. The choice has to be made before the
game's imports are resolved and there's no telling then whether a module will
appear later, and getting it wrong leaves the game importing from a module that
never loads.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 12:55:08 -06:00
Henrik RydgårdandClaude Opus 5 ad06cbe2c4 Auto-install firmware from the game disc on boot
Most UMDs carry a firmware updater, and having a real firmware in the NAND is
what the LLE modules want. On boot, if the disc's updater is newer than what's
installed - or nothing identifiable is installed, which is what a fonts-only
NAND looks like - unpack it, with a progress bar on the OSD. Controlled by
bAutoUpgradeFirmware, on by default, with a checkbox on the firmware screen.
Off in headless, which shouldn't rewrite the NAND during a test run.

The install itself is now shared with the install screen, and hardened, since
it can run without anyone watching:

- It stages into <NAND>/install-staging and only erases the installed firmware
  once the new one is complete on disk, so a failure leaves what's there alone.
- A single entry that didn't unpack fails the whole install. A firmware with
  holes still looks installed, so nothing would ever replace it.
- A truncated archive is rejected instead of unpacking to half a firmware that
  every stat reports as a clean install. The PSAR header records the length;
  it was being clamped to the buffer rather than checked against it.

Also falls back to the version in the archive's own header when the PARAM.SFO
next to the updater is unreadable, which it is on a fair number of discs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 15:52:53 -06:00
Henrik RydgårdandClaude Opus 5 fbdf611fc4 Chat: keep more lines of history, and add timestamps
The log was trimmed to 50 lines, which isn't enough to scroll back
through a conversation - now 250. Chat entries also carry the time they
arrived, shown as a dimmed HH:MM in front of the name, behind a new
"Show timestamps in chat" setting.

The timestamp is kept next to the text rather than baked into it, since
the chat view finds the sender by splitting the line at the first colon.

Fixes #15444

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
2026-09-04 13:10:54 -06:00
Henrik RydgårdandClaude Opus 5 bd505b7f1c Interpreter: implement the FPU divide-by-zero exception
div.s now maintains fcr31's Cause.Z and (when the trap is masked) sticky
Flag.Z bits, in the standard MIPS bit positions. Only a finite non-zero
dividend counts, so 0/0, inf/0 and NaN operands are excluded per IEEE 754.

When the guest has the trap unmasked, the new Core_FPUException() reports it
with the usual module suffix and MIPS call stack, and fd is left unwritten as
hardware would. That's gated behind a new developer setting, off by default:
PSP threads start with fcr31 = 0x00000e00, i.e. three of the traps already
enabled, and games divide by zero without meaning anything by it. The fcr31
bits are updated either way, so what the game reads back doesn't depend on
the setting.

Interpreter only - the JITs are unchanged, and none of this is reachable
under them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9fKXvYBrnqtp1QQGaGWVv
2026-08-29 23:40:48 +02:00
Henrik Rydgård 78ef1eae82 Instead of flash0directory, have a NAND subdirectory under PSP, where you can keep flash0, flash1 etc.
Also make it configurable via command line.
2026-08-24 09:53:37 +02:00
Henrik RydgårdandClaude Opus 5 05f5668dfe Save symbols outside any module to a per-game file, and only save real names
Module symbols are keyed by module+crc so they're shared by every game that
loads that module. But symbols the user attaches to addresses that aren't in
any module - the heap, the stack, scratchpad, a hardware register, typically
after a memory.search - describe one game's own memory layout and are worthless
to any other game. Those now go to PSP/SYSTEM/SYMBOLS/<gameID>_syms.ppsym.

They're module index 0 ("absolute"), which already round-trips through the
existing per-module code: GetModuleRelativeAddr/GetModuleAbsoluteAddr are
identity for it, so the file format is unchanged, just with absolute addresses.
SaveModuleSymbols only needed to stop requiring a ModuleEntry. Auto-load/save
hang off CPU_Init/CPU_Shutdown rather than module load/unload, gated on the same
bAutoSaveLoadSymbols setting - and deliberately not on SYSPROP_HAS_DEBUGGER,
which only the Windows port reports true for, so LoadSymbolsIfSupported next to
it does nothing at all on headless. hle.game.saveSymbols/loadSymbols expose it.

Four things found while doing it:

- Symbols outside any module were being dropped on the floor. AddFunction/
  AddData/AddLabel take moduleIndex -1 as "work it out", pass it to
  GetModuleIndex(), and store whatever comes back - but that returns -1 when no
  module contains the address, and -1 is never an active module, so the symbol
  never reached the active maps: invisible to every lookup and to any save.
  hle.data.add had spotted this and normalized -1 to 0 locally; nothing else
  did, so e.g. hle.func.add outside a module silently did nothing. Fixed
  centrally in a new ResolveModuleIndex() the three of them share.
  (This only became reachable with the GetModuleIndex() fix in 29a38af37e -
  before that it returned a wrong-but-valid module index instead.)

- The saved files were almost entirely noise. Every function the analyzer finds
  is named z_un_<addr> and every import stub zz_<name>, both regenerated from
  scratch on each load. One real module wrote 13KB - 443 unnamed functions and
  64 stub names - for the four names a human had actually chosen. Worse, on the
  next run those were loaded back as authoritative and would beat the module's
  own symbols to the address. Now only names that aren't regenerated get saved,
  and a module with none writes no file at all (and removes a stale one, so
  deleting a symbol sticks). That module's file went 13020 -> 81 bytes.

- LoadModuleSymbols trusted the addresses in the file. It's meant to be
  hand-edited and can outlive the build it came from, so relative addresses past
  the end of the module are now skipped with a warning instead of landing at
  nonsense addresses.

- AddFunction and AddData both erased the map entry they were updating and then
  read back through the now-dangling iterator to refresh the active copy. Only
  latent: the refresh is guarded on the active copy's module matching the new
  one, which is false exactly when the erase happens. Re-point the iterator at
  the entry's new home instead, so it can't rot if that guard ever changes.
  AddLabel already did the equivalent correctly, via a local copy.

Filename sanitizing goes through SanitizeString with a new FileName restriction
rather than being open-coded; unlike the existing restrictions it substitutes
'_' instead of dropping, so two module names can't collapse onto one file.

Verified end to end on headless with cpu_alu.prx: named a function inside the
module and data/functions in scratchpad and the heap, let it exit, checked both
files, rebooted and confirmed all of it came back at the right addresses.
Unit tests 51/51, pspautotests 314/314.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 16:53:48 +02:00
Henrik RydgårdandClaude Sonnet 5 29a38af37e Per-module symbol save/load, module identity via crc, GetModuleIndex fix
SymbolMap:
- Fix GetModuleIndex(): it only checked the end of an active module's range
  (via activeModuleEnds.upper_bound), never the start, so an address sitting
  in the gap before a module was silently misattributed to it. Added
  GetModuleIndexByName() as a companion lookup.
- AddModule() gains an optional crc param, stored per ModuleEntry. Reactivating
  a module by name now also requires the crc to agree when both sides know it,
  so two unrelated binaries that happen to share a name no longer get merged
  into one symbol table (addresses the old TODO at the top of SymbolMap.h).
- AddLabel()/AddFunction() gain an updateName param (default false, preserving
  existing "first writer wins" behavior) so a trusted source - like a loaded
  symbol file - can be allowed to overwrite a name that a lower-confidence
  automatic pass already assigned.
- New SaveModuleSymbols()/LoadModuleSymbols()/GetModuleSymbolsPath(): save or
  restore one module's functions/data/labels to/from a small human-editable
  text file, addressed relative to the module (so the file stays valid however
  the module ends up positioned on a later run). Keyed by
  PSP/SYSTEM/SYMBOLS/<moduleName>_<crc>.ppsym - deliberately by module+crc
  rather than by game, so it's shared by every game/homebrew that loads the
  exact same module. A "# game <id> <title>" comment records who last saved
  it, informational only.

WebSocket debugger: hle.module.saveSymbols/loadSymbols expose the above.

sceKernelModule.cpp: auto-load a module's saved symbols right after it's
registered with the symbol map (both the real ELF-load path and the
savestate-load path), and auto-save on unload (before UnloadModule(), while
its symbols are still active) - gated behind the new bAutoSaveLoadSymbols
config setting (default off), with a matching Developer Tools checkbox and
a --auto-save-load-symbols command-line override for headless use.

Includes some in-progress cleanup already staged: DescribeAddress now calls
g_symbolMap->GetDescription() directly instead of through the now-removed
MIPSDebugInterface::getDescription() wrapper.

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
nmkd 8e9a8b8d76 Allow disabling dithering when using software rendering 2026-08-16 15:27:41 +02:00
Henrik Rydgård db30fabf03 Add a setting (defaulting to false) for enabling file handler plugins 2026-08-03 11:24:36 +02:00
Henrik Rydgård 34454f9d03 Claude's crazy exception handler hack 2026-07-27 23:41:13 +02:00
Henrik Rydgård 3139d7ccfe Add command line parameters for controlling the behavior on memory/instruction exceptions 2026-07-27 18:37:26 +02:00
Henrik Rydgård 993c3a9c67 Avoid accurately computing disk space on iOS and Android (where it can be slow). Add a setting. 2026-07-14 22:22:29 +02:00
Henrik Rydgård 61e1ef8f7a Remove the "Software skinning" option. Now always on. 2026-07-14 17:02:57 +02:00
Henrik Rydgård 5f7281bd8e Remove old vestiges of geometry shader support 2026-07-08 18:25:08 +02:00
Henrik Rydgård 623545bd24 Delete the "Hardware tessellation" feature.
Very hard to maintain and debug, not worth it.
2026-06-16 16:17:14 +02:00
Henrik Rydgård 5265422c0e Remove the old "Fragment ubershader" setting. It's been on by default for years and is not really an ubershader. 2026-06-10 09:54:52 +02:00
Henrik Rydgård 36bdde68f9 Delete the "Lazy texture cache" option 2026-06-09 23:49:54 +02:00
jasaaved 95006cf1d3 Changed bFullScreenExclusive to bAllowFullScreenExclusive
There's no guarantee VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT will enter Fullscreen exclusive (FSE). Under the right conditions, the driver and/or DWM can grant FSE. Adding "allow" to the FSE setting should make this a bit clearer.
2026-06-04 12:54:52 -07:00
jasaaved 0c23cdaf3d Windows Vulkan: default to borderless fullscreen, add exclusive option
Vulkan swapchain now explicitly sets VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT by default, enabling proper borderless fullscreen behavior with benefits including better Alt+Tab, VRR/G-Sync/FreeSync, and Auto HDR support.
2026-06-03 17:15:13 -07:00
Henrik Rydgård 2d7ebe0835 Merge pull request #21688 from RRDVD/cross-shaped-anti-deadzone
Add Steam Input-style advanced deadzone controls to analog calibration
2026-06-03 10:40:47 +02:00