Suikoden II Bug: Kindness Rune Sets ATK to 999


The Kindness Rune is a weapon-only rune that is intended to give a large, but limited bonus to a character's ATK. When the Rune is attached, each character may receive a bonus of up to 127 points, based on how "kind" you have been to them. Due to the implementation, it is difficult to be certain what the developers intended by allowing characters' "Kindness Ratings" to become negative. It may be intended to hold the bonus at zero for a longer time period, but it appears more likely that the rune was actually intended to subtract from ATK in this event. Regardless, the bug comes into operation when the character's rating drops below zero, and their ATK is maximized to 999.

This is one of many bugs that is actually somewhat beneficial to the player.

How the Kindness Rune Works


There are two ways to increase a character's Kindness Rating, and one way to lower it.

Increase
  • Have the character in the active party (not convoy) when the game's clock reaches a certain time. The 30-minute mark of each hour is confirmed. It may also increase on the hour. This increase is always one point.
  • Use Stones on the character. Any stat stone will do. Each stone used will add one to the rating, with no regard for the amount added to the stone's target stat.
Decrease
  • End a battle while the character is unconscious. Each time you do this, one point is subtracted from the rating.

The rating can range from -128 to +127 and is added into the ATK value after all other bonuses have been applied.

Cause


The bug is caused by bad variable management. The Kindness Rating is mainly managed by a single routine that can set it to a fixed level, or add/subtract from it. This same routine is also used to retrieve the Kindness Rating's value for use in other tasks. The Kindness Rating is handled by this routine as a signed 8-bit number (byte). The problem arises in the ATK calculation, which seems to think it should be getting an unsigned, 16-bit number (half-word). When the Kindness Rating is negative, it gets handed to the ATK calculation properly. However, before it is added into the ATK total, the sign is destroyed, along with part of the value. What's left appears to be a very large, positive number (more than 65,400), and the game immediately sets the ATK total to its limit of 999.

Code taken from the US main executable (SLUS_009.58)
TEXT:80088950 loc_80088950: # CODE XREF: sub_80088864:loc_80088900j
TEXT:80088950 bne $s0, $v0, loc_80088968
TEXT:80088954 move $a0, $0
TEXT:80088958 move $a1, $a0
TEXT:8008895C jal KindnessRating
TEXT:80088960 move $a2, $s1
TEXT:80088964 move $s2, $v0
TEXT:80088968
TEXT:80088968 loc_80088968: # CODE XREF: sub_80088864+94j
TEXT:80088968 # sub_80088864+E4j ...
TEXT:80088968 lhu $v0, 0x38+var_28($sp)
TEXT:8008896C andi $v1, $s4, 0xFFFF
TEXT:80088970 addu $v0, $v1
TEXT:80088974 andi $v1, $s2, 0xFFFF <---- This is the cause of the bug.
TEXT:80088978 addu $v1, $v0, $v1
TEXT:8008897C slti $v0, $v1, 0x3E8
TEXT:80088980 beqz $v0, loc_80088994
TEXT:80088984 li $v0, 0x3E7
TEXT:80088988 bltz $v1, loc_80088994
TEXT:8008898C move $v0, $0
TEXT:80088990 andi $v0, $v1, 0xFFFF
The indicated line is the source of the problem. If, for example, the Kindness Rating is -1, the management routine will retrieve a byte from memory as a signed value. When dealing with byte, 0xFF is -1. Since the Playstation works on 32-bit registers, the sign bit must be propagated to the unused bits of the register to preserve the value. That means that what the $s2 register contains is actually 0xFFFFFFFF. The problem operation does a bitwise and with 0xFFFF. This will retain the least significant 16-bits and clear the high-order bits. After this operation, $s2 will contain 0x0000FFFF. This is 65,535, and not -1. This enormous value is added into the running total by the following line, and the remainder of the lines shown simply enforce bounds of 0 and 999 for the final results.


Fix


The simple fix is to do away with the problem AND operation. This assumes that the developers wanted ATK to be reduced by a bad Kindness Rating. Since the variable used as the bonus is allowed to be negative, and the ATK calculation accounts for the possibility that its result will be negative--raising it zero instead of allowing it--it is believed that is the most likely case.

GameShark Code

If you are playing on a console with an original copy, you can use this code to prevent the bug from occurring.

Fix Kindness Rune Bug
(North American Version)
80088974 1821
80088976 0240



Patch


See the Patch Files page for your version.