The Tantalus games (Cars Race-O-Rama, MX vs ATV Reflex and Untamed, SpongeBob)
turn depth into fog with a CLUT16 read of the swizzled depth mirror, stretched
2x into a 565 view of an 8888 buffer. A following 8888 copy writes the scene's
RGB and keeps the alpha, so each pixel's fog factor is the upper 565 half.
At a higher render scale, the depth X swizzle snapped every render pixel to its
PSP pixel's left edge, so the fog came out in PSP-pixel blocks. It now keeps the
position within the PSP pixel. That leaves the upper half sampling the right
half of the depth texel, half a pixel off the scene, which drew magenta halos on
the right of objects in Cars. With the new DepthCLUTIntoHalves compat flag, the
depal pass outputs twice as wide so each render pixel reads its own 8888 pixel's
depth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shader depal CLUT8 mode now handles 565, 5551 and 4444 framebuffers
(the format goes in the depal format bits, which this mode didn't fill
before), rebuilding the 16-bit pixel and taking its low or high byte.
This replaces SOCOMClut8Replacement, which assumed the high byte.
- The GE samples a pixel at its corner, the GPU at its center. With u
stepping two bytes per pixel (SOCOM and Bend's games use u = 1 + 2x)
that's a whole byte, so the shader steps back to the corner.
- The CLUT index shift, mask and start are applied, as in the other
depal modes.
- The self-render copy region counted CLUT8's U in pixels, not bytes.
SOCOM, Star Wars: The Force Unleashed and the NPJG90068 dumps improve a
lot. Syphon Filter and Resistance: Retribution now read the right bytes,
which exposes a 16-bit precision difference in their bright pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The flare's occlusion result is rendered into every other 16-bit pixel of a
palette whose other half is uploaded from memory, then read back as a CLUT.
Two things broke it at 2x:
- The CLUT8-from-8888 shader depal picked the byte out of each pixel using
the scaled texture size, so at 2x it read the wrong byte. It now works in
PSP units (from u_texclamp, which it now always gets) and samples the
pixel's center, not its edge, which is a render pixel boundary when
scaled.
- The palette upload was linearly filtered when stretched, blending each
16-bit half with its neighbour. Burnout Dominator joins Ridge Racer in
NearestFilteringOnFramebufferCreate.
1x and 3x only worked because their sample points happened to land inside
the right texels.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The same engine as Cars Race-O-Rama, with the same 8x8 copy out of VRAM. Without
the readback the value the CPU reads never changes, so its brightness adaptation
stays frozen; with it, it follows the software renderer's.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The game reduces the scene to 8x8 on the GPU, block transfers that into RAM,
and the CPU sets its brightness adaptation from it. With BlockTransferAllowCreateFB
the copy went into a GPU-side buffer instead, the CPU read stale RAM, and the
game kept getting darker on the hardware backends (#15914).
New compat flag BlockTransferReadbackSmall: transfers of up to 64 pixels into
RAM are still read back, a frame late, so it doesn't stall. Brightness from
the issue's savestate now follows the software renderer's (72 vs 84 at 6 s,
84 vs 95 at 20 s, from 25 and falling), at the same speed as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Partial red, green and blue write masks now always go through the shader with
a framebuffer read. Across the frame dump set this only improves games outside
the old list (Split/Second, Ultimate Ghosts 'n Goblins, older DiRT 2 and OutRun
dumps without a game ID). Partial alpha masks keep the old heuristic: alpha is
the stencil, with its own write mask, and taking the shader path for them made
Pro Yakyu Spirits and Gangs of London worse.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its glow sets the 5551 alpha through a 565 draw with only the top blue bit
unmasked. Without the flag the whole blue channel was written, tinting the
glow; 25276 -> 4274 pixels off the PSP in issue #20728's dump.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
They use the same quadratic interpolator as rcp and friends, with three
twists. sin indexes the quarter wave from the top, and asin and sin work
in a per-segment exponent whose 4-ulp truncation also applies to results
in a lower binade. log2 truncates exponent + log2(1.m) toward zero to 22
significant bits, and where that step is coarser than 2^-24 the datapath
drops coefficient bits to match; that also covers the region just below
1.0 that needed a special case.
vfpu_sincos now reduces the angle once. With every table gone, so are
the asset folder, the loader, InitVFPU and the fallbacks for tables that
failed to load. All seven functions are bit-exact with the table-based
code over every 32-bit input.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The four share one quadratic interpolator: 128 segments picked by the top
7 bits of the input, each with a constant, a linear and a squared-term
coefficient, and a squarer on the top 10 bits of the rest that rounds t^2
up to a multiple of 256. 128 small coefficient sets per function
replace the 1 MB of delta tables. Derived from the output of the
table-based code, and bit-exact with it over every 32-bit input.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There are a few games that seem to rely on performance problems or
timing quirks to hold the correct pace when playing sceMpeg - have not
been able to nail down any other timing mechanism.
This adds a timing enforcement function.
Coded by Claude.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follows each language file's own word for firmware rather than imposing one, so
this reads the way the neighbouring strings in [System] already do: fastvare in
Norwegian, systemprogramvara in Swedish, laiteohjelmisto in Finnish, proshivka
in Russian and Ukrainian, and the English word where that is what the language
has settled on.
Thirteen files keep the English string as a placeholder. Those are the ones with
no translation for the firmware strings already in that section either, so there
was no house style to follow and guessing would leave nobody able to check it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The five new [System] keys, in the 33 languages that already had a rendering of
"firmware" to follow - they disagree on it (fastvare, prosjivka, systemprogramvara,
laiteohjelmisto), so each one matches whatever its own file already chose. The
other 13 fall back to English.
Firmware screen: call it "Uninstall firmware", not "Erase firmware"
Translate the rest of the firmware screen strings
"Uninstall firmware", "No firmware installed" and "Launch XMB", in the same 33
languages as the auto-install strings. XMB stays untranslated - it's Sony's
name for it, and pl_PL already wrote it bare.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
36 languages, following each file's existing handling of the sibling RAIntegration
string - most keep the name as-is, pl_PL uses "Integracja RA", tr_TR "RA Entegrasyonu",
ja_JP "RAインテグレーション" - and its formality. The rest are left to fall back to
English rather than guessed at.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgACRqkQNpfJQ4fjwyoEup
RAIntegration keeps its cache and local achievement data next to the
executable. If PPSSPP is installed somewhere that needs elevation to write -
Program Files being the obvious case - that write fails and takes the emulator
down as soon as a set or code notes are loaded, with no log to show for it since
the log can't be written either.
Check whether the exe directory is writable before handing the DLL to rcheevos,
and if it isn't, say so and point at the portable .zip instead. Achievements
themselves still work, so carry on to the normal login.
Fixes#21260
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgACRqkQNpfJQ4fjwyoEup
31 languages, following each file's existing chat terminology (chatt,
bate-papo, obrolan, sembang, 聊天, الشات, ...). The rest are left to fall
back to English rather than guessed at.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
The file holds the Hebrew strings in visual order, for renderers with no bidi
of their own, but only 101 of its 269 Hebrew entries were actually a reversal
of he_IL. The rest were left unreversed, reversed by word instead of by
character, or garbled outright ("Win" read as gibberish either way round).
Derived them all mechanically instead. The transform reproduces the entries
that were already right, and keeps as single units the things that must not be
spelled backwards: the \n escape, %N placeholders, runs of Latin and digits,
and an & accelerator together with the character it marks.
The [Dialog] save/OSK strings are the exception - he_IL already stores those
reversed, since PPGeDraw draws them and has no bidi, so the invert file just
mirrors he_IL for those 22 keys.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9fKXvYBrnqtp1QQGaGWVv
Adds GameInfoFlags::BUNDLED_UPDATE_INFO, holding the version, title, size
and timestamp of the updater in PSP_GAME/SYSDIR/UPDATE. It comes from the
PARAM.SFO and the directory entry next to the archive, so it's a couple of
small reads on the ISOFileSystem the worker already has open - no
decryption, and DATA.BIN itself is only sniffed for its magic. Only
computed for ISOs; everything else is marked complete with an empty struct.
ISOFileSystem now parses the date out of the ISO9660 directory record,
stored as Unix UTC seconds and reported as the PSP's atime/ctime/mtime.
Those used to always read back as zero, so games calling sceIoGetstat on a
UMD file saw 1900 where hardware gives the mastering date.
Shown on GameScreen as e.g. "Firmware update on disc: 6.60 (2011-10-05),
25.6 MB".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149QcTVgZEXKXbgHyvXF4ZY