[BUG]: Pride FC - Fighting Championship | Missing text and textures in Hardware and Software render modes.
Describe the Bug
Pride FC has missing text and textures on the character select screen in both hardware and software modes, Wiki is empty of any test results.

Reproduction Steps
Open a submenu or select a character.
Expected Behavior

(Screenshots taken from a youtube video)
PCSX2 Revision
v1.7.3751
Operating System
Windows 11
If Linux - Specify Distro
.
CPU
i7-7700
GPU
GTX 1060 6GB
GS Settings

Emulation Settings

GS Window Screenshots
.
Logs & Dumps
HW mode GS Dumps: Pride FC - Fighting Championship GS Dumps.zip SW mode GS Dumps : Pride FC - Fighting Championships - GS Dumps (Software mode).zip
Pride FC is also mentioned in #1562
It is COP2 rounding issue. Game run this sequence:
vf06z = 0x3f800000 vf08z = 0x4b7fffffx
vmulax.xyzw ACC,vf04,vf08x vmadday.xyzw ACC,vf05,vf08y vmaddaz.xyzw ACC,vf06,vf08z vmaddw.xyzw vf09, vf07, vf08w
After last opcode value in vf09z is always off by one bit. That's enough to break game. Value is still correct after vmaddaz. Function in game which produce wrong result is at 0x1340D0 for US version of game. I additionally confirmed this with pnach, if vf09z result is not corrupted, game work fine. Worth to note that if vf08z value is not using 19 upper fractional bits set to 1, then result is fine.
Edit: Added patch with explanation.
// Preserve z instead of multiplying by 1 when conditions are met. patch=1,EE,000fffc0,word,8c830040 // load vector pointer patch=1,EE,000fffc4,word,0804d036 // return to old code patch=1,EE,000fffc8,word,8cd90008 // preserve old z value
patch=1,EE,000fffcc,word,84cf000a // load upper 16 bits of z from vector patch=1,EE,000fffd0,word,24184b7f // li 0x4B7F (problematic value upper bits) patch=1,EE,000fffd4,word,15f80004 // jump to jr ra if not match, result untouched patch=1,EE,000fffd8,word,3c0f3f80 // lui 0x3F80 (float 1.0) patch=1,EE,000fffdc,word,8c780028 // load z multiplier from vector patch=1,EE,000fffe0,word,51f80001 // compare if mul is by 1.0 patch=1,EE,000fffe4,word,acb90008 // use preserved value instead of really multiplying by 1 if true patch=1,EE,000fffe8,word,03e00008 // jr ra patch=1,EE,000fffec,word,00000000 // nop
patch=1,EE,001340d0,word,0803fff0 // jump to preserve z patch=1,EE,001340f8,word,0803fff3 // jump to z compare

Alternative can be hack in emu code to do move instead of add if value is added against 0. Because that seems to give that wrong result, not multiply itself. But this is just one game, patch can be better solution.
where is it added against zero? Is there a way we can track when that's the case? because the problem I foresee is being able to know that it's zero at runtime (we don't wanna be checking the value if it's zero live, this would be slow).
Whoops i was looking at wrong line when i wrote that. This isn't add, but mul by 1 which happen here (US release):
0x1340F4:
Before mul:

After:

I don't know if there is a way to detect this in emulator code.
I see, the annoying thing is multiplication by 1 on the PS2 isn't guaranteed to be the same result, either, depending on which is the non-one value.
Ages ago there was semi soft float mul implementation for FPU in pcsx2 codebase, this could fix issues like that. Assuming that VU have similar guardbits mess like FPU, and that implementation is accurate enough.
https://github.com/PCSX2/pcsx2/commit/00f14b5760ab2cd73bd9577993122674852a2f67 Commit that removed "softfloat" mul for FPU. Gonna be pain to implement for VU, just like accurate ADD/SUB.
That looks gross :P But yeah we're gonna need some sort of soft float type system eventually, but that's for future refraction to worry about, right now patches are fine :P
It is COP2 rounding issue. Game run this sequence:
vf06z = 0x3f800000 vf08z = 0x4b7fffffx
vmulax.xyzw ACC,vf04,vf08x vmadday.xyzw ACC,vf05,vf08y vmaddaz.xyzw ACC,vf06,vf08z vmaddw.xyzw vf09, vf07, vf08w
After last opcode value in vf09z is always off by one bit. That's enough to break game. Value is still correct after vmaddaz. Function in game which produce wrong result is at 0x1340D0 for US version of game. I additionally confirmed this with pnach, if vf09z result is not corrupted, game work fine. Worth to note that if vf08z value is not using 19 upper fractional bits set to 1, then result is fine.
Edit: Added patch with explanation.
// Preserve z instead of multiplying by 1 when conditions are met. patch=1,EE,000fffc0,word,8c830040 // load vector pointer patch=1,EE,000fffc4,word,0804d036 // return to old code patch=1,EE,000fffc8,word,8cd90008 // preserve old z value
patch=1,EE,000fffcc,word,84cf000a // load upper 16 bits of z from vector patch=1,EE,000fffd0,word,24184b7f // li 0x4B7F (problematic value upper bits) patch=1,EE,000fffd4,word,15f80004 // jump to jr ra if not match, result untouched patch=1,EE,000fffd8,word,3c0f3f80 // lui 0x3F80 (float 1.0) patch=1,EE,000fffdc,word,8c780028 // load z multiplier from vector patch=1,EE,000fffe0,word,51f80001 // compare if mul is by 1.0 patch=1,EE,000fffe4,word,acb90008 // use preserved value instead of really multiplying by 1 if true patch=1,EE,000fffe8,word,03e00008 // jr ra patch=1,EE,000fffec,word,00000000 // nop
patch=1,EE,001340d0,word,0803fff0 // jump to preserve z patch=1,EE,001340f8,word,0803fff3 // jump to z compare
Alternative can be hack in emu code to do move instead of add if value is added against 0. Because that seems to give that wrong result, not multiply itself. But this is just one game, patch can be better solution.
Hey, I'm new to emulating and all this technological stuff haha. I applied your patch, and it fixed the text and images but there is a slight problem. Everything else just goes haywire! Fighters are fused and their body is just all over the place, the sides of the ring are inside of them too. Maybe I patches it wrong, or maybe it's because I'm playing from the phone on aethersx2 and not pcsx2 on PC but I don't really know. Do you think you could help me resolve this issue while also fixing the text? Thank you! I will provide images and other things if needed, I don't know what is required since I just made this account.
It is COP2 rounding issue. Game run this sequence: vf06z = 0x3f800000 vf08z = 0x4b7fffffx vmulax.xyzw ACC,vf04,vf08x vmadday.xyzw ACC,vf05,vf08y vmaddaz.xyzw ACC,vf06,vf08z vmaddw.xyzw vf09, vf07, vf08w After last opcode value in vf09z is always off by one bit. That's enough to break game. Value is still correct after vmaddaz. Function in game which produce wrong result is at 0x1340D0 for US version of game. I additionally confirmed this with pnach, if vf09z result is not corrupted, game work fine. Worth to note that if vf08z value is not using 19 upper fractional bits set to 1, then result is fine. Edit: Added patch with explanation. // Preserve z instead of multiplying by 1 when conditions are met. patch=1,EE,000fffc0,word,8c830040 // load vector pointer patch=1,EE,000fffc4,word,0804d036 // return to old code patch=1,EE,000fffc8,word,8cd90008 // preserve old z value patch=1,EE,000fffcc,word,84cf000a // load upper 16 bits of z from vector patch=1,EE,000fffd0,word,24184b7f // li 0x4B7F (problematic value upper bits) patch=1,EE,000fffd4,word,15f80004 // jump to jr ra if not match, result untouched patch=1,EE,000fffd8,word,3c0f3f80 // lui 0x3F80 (float 1.0) patch=1,EE,000fffdc,word,8c780028 // load z multiplier from vector patch=1,EE,000fffe0,word,51f80001 // compare if mul is by 1.0 patch=1,EE,000fffe4,word,acb90008 // use preserved value instead of really multiplying by 1 if true patch=1,EE,000fffe8,word,03e00008 // jr ra patch=1,EE,000fffec,word,00000000 // nop patch=1,EE,001340d0,word,0803fff0 // jump to preserve z patch=1,EE,001340f8,word,0803fff3 // jump to z compare
Alternative can be hack in emu code to do move instead of add if value is added against 0. Because that seems to give that wrong result, not multiply itself. But this is just one game, patch can be better solution.
Hey, I'm new to emulating and all this technological stuff haha. I applied your patch, and it fixed the text and images but there is a slight problem. Everything else just goes haywire! Fighters are fused and their body is just all over the place, the sides of the ring are inside of them too. Maybe I patches it wrong, or maybe it's because I'm playing from the phone on aethersx2 and not pcsx2 on PC but I don't really know. Do you think you could help me resolve this issue while also fixing the text? Thank you! I will provide images and other things if needed, I don't know what is required since I just made this account.
I had the same issue running the pal version on ppss22 (android emulator) and i changed to the ntsc rom, put the patch and worked fine, so try with the ntsc rom
This is quite confusing. Can you show me the step-by-step process?