System(s) |
Playstation, PSN (POPS) |
Bug Type | Translation |
Region Introduced | |
Patch Version | 2.01.065b |
This bug was not present in the Japanese version, because the character sets are entirely different. It was fixed in the European versions.
Below is the routine responsible, with a few comments. They have to make a number of adjustments, because of the odd ways in which they modified the character set from game to game.
RAM:80110E0C strcpyS1toS2: # CODE XREF: RAM:8010F92Cp RAM:80110E0C # RAM:8010F944p ... RAM:80110E0C blez $a2, locret_80110E70 RAM:80110E10 move $a3, $0 RAM:80110E14 RAM:80110E14 loc_80110E14: # CODE XREF: strcpyS1toS2+5Cj RAM:80110E14 addu $v0, $a0, $a3 # This whole thing fails to take terminating nulls into account. RAM:80110E18 lbu $v1, 0($v0) RAM:80110E1C nop RAM:80110E20 addiu $v0, $v1, 0xFFF0 RAM:80110E24 sltiu $v0, 0x1B # Check for lower case. RAM:80110E28 bnez $v0, loc_80110E60 # #Skip it, if lowercase. Oops. RAM:80110E2C addiu $v0, $v1, 0xFFD5 RAM:80110E30 sltiu $v0, 0x1A RAM:80110E34 bnez $v0, loc_80110E5C RAM:80110E38 addiu $v0, $v1, 0x10 RAM:80110E3C addiu $v0, $v1, 0xFFBB RAM:80110E40 sltiu $v0, 0x13 RAM:80110E44 bnez $v0, loc_80110E5C RAM:80110E48 addiu $v0, $v1, 0x53 RAM:80110E4C addiu $v0, $v1, 0xFFA8 RAM:80110E50 sltiu $v0, 0x15 RAM:80110E54 beqz $v0, loc_80110E60 RAM:80110E58 addiu $v0, $v1, 0x10 RAM:80110E5C RAM:80110E5C loc_80110E5C: # CODE XREF: strcpyS1toS2+28j RAM:80110E5C # strcpyS1toS2+38j RAM:80110E5C sb $v0, 0($a1) RAM:80110E60 RAM:80110E60 loc_80110E60: # CODE XREF: strcpyS1toS2+1Cj RAM:80110E60 # strcpyS1toS2+48j RAM:80110E60 addiu $a3, 1 RAM:80110E64 slt $v0, $a3, $a2 RAM:80110E68 bnez $v0, loc_80110E14 RAM:80110E6C addiu $a1, 1 RAM:80110E70 RAM:80110E70 locret_80110E70: # CODE XREF: strcpyS1toS2j RAM:80110E70 jr $ra RAM:80110E74 nop
Essentially, they branch 1 operation too far after determining that the character is lowercase. The problem that remains is the lack of support for terminating nulls.
The fix eliminates the check on the destination pointer. This would be potentially dangerous, except for the fact that this code is only called from three places in one module, and in all cases the destination is a non-zero address.