pcsx2 icon indicating copy to clipboard operation
pcsx2 copied to clipboard

[BUG]: Xenosaga Episode III misdetected shuffle (?)

Open JordanTheToaster opened this issue 2 months ago • 4 comments

Describe the Bug

Game has broken graphics likely due to a misdetected shuffle.

Image

Reproduction Steps

Download and run the following GS dumps.

https://drive.google.com/file/d/1sIxDkpGZez8aYr90Xb7WbrYDEH9zKDBw/view?usp=drive_link https://drive.google.com/file/d/11aFdKyfy2wmYTOkTiCgdTNyypj1_XRII/view?usp=drive_link

Expected Behavior

Game no broke.

PCSX2 Revision

v2.5.229

Operating System

Windows 10 (64bit)

If Linux - Specify Distro

No response

CPU

Ryzen 5 5600X

GPU

RTX 2070 Super

GS Settings

No response

Emulation Settings

No response

GS Window Screenshots

No response

Logs & Dumps

No response

JordanTheToaster avatar Oct 17 '25 21:10 JordanTheToaster

Haven't fully determined the issue but it appears that a C16 target @0x1800 is drawn in frame 403 (draws 115822 - 115826) and is read back as a C16 source in frame 405 (draw 116619). For some reason, it is corrupted somewhere in between. It appears to be a regular (non-shuffle) draw for a post-processing blur effect.

TJnotJT avatar Dec 05 '25 23:12 TJnotJT

I thought I fixed that, yeah it's not a shuffle, it's just being misdetected as one then screwed up.

refractionpcsx2 avatar Dec 05 '25 23:12 refractionpcsx2

Hmm, when I stepped through it, I didn't see the possible_shuffle flag set in GSTextureCache::LookupSource(), though it's possible that it's triggered in a different place.

TJnotJT avatar Dec 05 '25 23:12 TJnotJT

idk, you'll have to trace through (it might be the end of the source lookup, where it tries to be smart), but it's probbaly being converted to 32bit, or told it is. But you should be able to to find the draw where the PSM gets updated to CT32 and see why :)

refractionpcsx2 avatar Dec 05 '25 23:12 refractionpcsx2

Notes for future reference (with respect to the large dump above). Occurs around frames 403-405:

  1. A C16 target at 0x1800 is created for a post-processing effect to scale down the main RT. However, there is already a C32 target at 0x1800. Instead of nuking the old C32, it is resized making the new C16 targer larger than it needs to be (should be around 512 x 224 but ends up 512 x 512).
  2. A few draws later, the C16 target at 0x1800 is used as a source for the post-processing effect.
  3. A few draws later, a new RT is draw at 0x1C00. Since this overlaps the larger-than-needed C16 source at 0x1800, the C16 source gets nuked.
  4. A few hundred draws later, another RT is drawn at 0x1C00. This time it triggers a path in GSTextureCache::LookupTarget() that signals that the C16 target at 0x1800 is part of a double buffer, so the C16 target also gets nuked. This is also in part because the C16 target is too large.
  5. A few hundred draws later, we attempt to use the (nonexistent) C16 target at 0x1800 for a similar post-processing effect. Since there is no longer a target or source at 0x1800 we load garbage from memory and get the bugged visuals above.

Proposed solution: Improve the heuristics in step 1 so that we appropriately nuke the old C32 target instead of resizing it. Resizing the target is useless anyway it is being converted to a different format with incompatible swizzle, and is not being used for a shuffle.

TJnotJT avatar Dec 12 '25 02:12 TJnotJT