GPU: Don't estimate a first-frame safe size for screen-sized buffers

- Fixes #21802

The estimate from #21678 made the first-frame readback read back a part of
any buffer drawn in through mode. In the Japanese GTA games, that writes a
64x320 strip of the 32-bit loading screen into VRAM, where the two 16-bit
display buffers later go. Nothing else writes that memory, and when pausing,
the game shows one of them for a few frames before drawing it, which we then
display from memory, pink strip and all. Before, it was all black.

The estimate was for small render targets (Evangelion Jo's menu text), so
limit it to buffers smaller than the screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-11-09 21:22:21 +01:00
1 parent bf11170ed4
commit 3c6876ac0e
1 file changed
+6 -2
+6 -2
View File
@@ -991,9 +991,13 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
return;
}
// This is the check from #21678 for Evangelion JO.
// This is the check from #21678 for Evangelion JO, whose menu text is rendered into small framebuffers
// that are then used as textures, so they need to reach memory on the first frame.
// Only for buffers smaller than the screen. A partial readback of a screen-sized one leaves a strip of
// stale pixels in VRAM, which GTA's Japanese versions then display for a few frames when pausing (#21802).
// TODO: Make this less specific.
if (gstate.isModeThrough() && gstate.isTextureMapEnabled() && gstate.getColorMask() != 0xFFFFFFFF &&
if (vfb && (vfb->width < 480 || vfb->height < 272) &&
gstate.isModeThrough() && gstate.isTextureMapEnabled() && gstate.getColorMask() != 0xFFFFFFFF &&
gstate.getScissorX1() == 0 && gstate.getScissorY1() == 0 && Memory::IsVRAMAddress(gstate.getFrameBufAddress())) {
int safeWidth;
int safeHeight;