System(s) |
Playstation, PSP, PSN (POPS) |
Bug Type | Gameplay |
Region Introduced | |
Patch Version | 2.01.065b |
When you try to use two characters to form a Unite, there is an annoying bug that can come into play. If a character A casts a candidate spell, and two or more others cast compatible spells, then A will unite with all of them. The results you get will depend on your characters' speed and the formation of your party, and can vary widely. In simple terms, you will either get more unites for less cost, or several of your characters will have their actions cancelled.
The bug occurs in step 4 of the list. Since the search is allowed to continue after a Unite is found, the Primary character is allowed to partner with multiple candidates. The effects are determined in step 3. If the Primary is the faster of all pairs found, then he will perform a single action, and all other character's actions will be cancelled. If the Primary is slower in all pairs, then his action will be cancelled, but every faster candidate will perform a Unite.
This bug can be rather confusing. The results are seemingly inconsistent because multiple variables affect its outcomes.
Note: Numbers are the characters' speed. The formation number ascends starting on the left and moving right in each row.
(220) Guardian Earth |
(215) Final Flame |
(205) Final Flame |
(180) Final Flame |
(165) Final Flame |
(140) Final Flame |
Result: Hero casts Scorched Earth> with Viki. Nobody else moves. |
(220) Guardian Earth |
(215) Final Flame |
(205) Final Flame |
(180) Final Flame |
(165) Final Flame |
(140) Shining Wind |
Result: Hero casts Storm Fang> with Viki. Nobody else moves. |
(140) Guardian Earth |
(215) Final Flame |
(205) Final Flame |
(180) Final Flame |
(165) Final Flame |
(220) Final Flame |
Result: Everyone but Viki casts Scorched Earth>. Viki does nothing. |
(220) Guardian Earth |
(215) Final Flame |
(205) Final Flame |
(225) Final Flame |
(165) Final Flame |
(140) Final Flame |
Result: Hero and Mazus cast Scorched Earth>. Nobody else moves. |
Mazus is faster than the Hero in this example. The search will start with the Hero. It finds Nanami, cancels her action, and assigns the Hero Scorched Earth. The same occurs with Luc. When it finds Mazus, he draws the action since he is faster, and the Hero's is cancelled. Then the game moves on and finds Tengaar. Her action is cancelled, and the Hero gets assigned Scorched Earth again. Then it does the same for Viki. The end result is that the Hero unites twice for 1 MP. One instance of the spell will be cast by Mazus, and one instance will be cast by the Hero. After the round, Luc, Tengaar, and Nanami's MP will remain unchanged. Mazus, the Hero, and Viki will all be down 1 fourth-level MP.
There are a ridiculous number of combinations with this bug, and it is not worth going into them all.
The code involved is in two modules, /CDROM/150_BPRG/BUFF0/BP0_FST.BIN and /CDROM/150_BPRG/BUFF0/BP0_SEC.BIN. The former runs during the first round of battle, and the latter during the second onward. Below is a snippet of the code that runs when the Primary partner is casting a Fire spell. In total, the search takes up around 500 operations in each module.
RAM:8003F030 loc_8003F030: # CODE XREF: RAM:8003F0F8j RAM:8003F030 lb $v0, 0x50($s2) # Current Actor using fire... RAM:8003F034 li $a3, 2 RAM:8003F038 bne $v0, $a3, loc_8003F0EC RAM:8003F03C move $a0, $s5 RAM:8003F040 jal sub_8003EDF0 # Get spell level? RAM:8003F044 move $a1, $s1 RAM:8003F048 # --------------------------------------------------------------------------- RAM:8003F048 move $s0, $v0 RAM:8003F04C move $a0, $s5 RAM:8003F050 jal sub_8003EE5C # Get action RAM:8003F054 move $a1, $s1 RAM:8003F058 # --------------------------------------------------------------------------- RAM:8003F058 li $a3, 3 RAM:8003F05C bne $s0, $a3, loc_8003F0EC # Skip if not a idx 3 (4th level) spell? RAM:8003F060 move $v1, $v0 RAM:8003F064 slti $v0, $v1, 0x13 # Other Actor using Earth RAM:8003F068 bnez $v0, loc_8003F0A8 RAM:8003F06C move $a0, $0 RAM:8003F070 slti $v0, $v1, 0x15 RAM:8003F074 beqz $v0, loc_8003F084 RAM:8003F078 li $a0, 0x36 # Scorched Earth RAM:8003F07C j loc_8003F0A8 RAM:8003F080 move $s6, $0 RAM:8003F084 # --------------------------------------------------------------------------- RAM:8003F084 RAM:8003F084 loc_8003F084: # CODE XREF: RAM:8003F074j RAM:8003F084 slti $v0, $v1, 0x1A # Other Actor using Lightning RAM:8003F088 beqz $v0, loc_8003F0A4 RAM:8003F08C slti $v0, $v1, 0x18 RAM:8003F090 bnez $v0, loc_8003F0A8 RAM:8003F094 move $a0, $0 RAM:8003F098 lb $s6, 0x52($s2) RAM:8003F09C j loc_8003F0A8 RAM:8003F0A0 li $a0, 0x3A # Blazing Camp RAM:8003F0A4 # --------------------------------------------------------------------------- RAM:8003F0A4 RAM:8003F0A4 loc_8003F0A4: # CODE XREF: RAM:8003F088j RAM:8003F0A4 move $a0, $0 RAM:8003F0A8 RAM:8003F0A8 loc_8003F0A8: # CODE XREF: RAM:8003F068j RAM:8003F0A8 # RAM:8003F07Cj ... RAM:8003F0A8 beqz $a0, loc_8003F0EC RAM:8003F0AC nop RAM:8003F0B0 lhu $v0, 0x3A($s3) # Speed RAM:8003F0B4 lhu $v1, 0x3A($s2) RAM:8003F0B8 nop RAM:8003F0BC sltu $v0, $v1 RAM:8003F0C0 bnez $v0, loc_8003F0DC RAM:8003F0C4 nop RAM:8003F0C8 sb $s6, 0x52($s3) RAM:8003F0CC sb $a0, 0x51($s3) RAM:8003F0D0 sb $s1, 0x45($s3) RAM:8003F0D4 j loc_8003F0EC # Continue Search??? RAM:8003F0D8 sb $fp, 0x50($s2) RAM:8003F0DC # --------------------------------------------------------------------------- RAM:8003F0DC RAM:8003F0DC loc_8003F0DC: # CODE XREF: RAM:8003F0C0j RAM:8003F0DC sb $fp, 0x50($s3) RAM:8003F0E0 sb $s6, 0x52($s2) RAM:8003F0E4 sb $a0, 0x51($s2) RAM:8003F0E8 sb $s4, 0x45($s2) RAM:8003F0EC
; Suikoden II Rune Unite Fix ; Written by Pyriel ; ; The game initiates a search for each character not already marked as "united". ; When it discovers a compatible spell, it assigns the faster character the unite ; spell, and sets up the slower character to do nothing. ; ; For some bizarre reason, after a compatible spell is found, the search continues ; for the current character. If more compatible spells are found, the unite ; assignment will occur again, and another character could have its actions ; cancelled. ; ; This bug presents itself in multiple ways, depending on the speed of the primary and secondary ; characters in the search/unite. ; ; To fix the problem, the search must be ended after a match is found. This require shuffling ; some operations to make room. .psx .align 4 .openfile BP0_FST.BIN, 0x8002B000 .headersize 0 ; Primary=Fire -- Secondary=Earth or Lightning .org 0x8003F0A8 .area 0x8003F0F0-. primFire: beqz $a0, loc_8003F0EC ; exit if unite not found lhu $v0, 0x3A($s3) ; slid this up to replace a nop lhu $v1, 0x3A($s2) ; need an extra op for a new J to "next" nop sltu $v0, $v1 bnez $v0, loc_8003F0D8 nop sb $s6, 0x52($s3) sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003F4C8 ; end search sb $fp, 0x50($s2) loc_8003F0D8: sb $fp, 0x50($s3) sb $s6, 0x52($s2) sb $a0, 0x51($s2) j 0x8003F4C8 ; end search sb $s4, 0x45($s2) loc_8003F0EC: lbu $v0, 0x340($s5) .endarea ; 0x8003F0A8 - 0x8003F0F0 ; Primary=Water -- Secondary=Wind or Lightning ; Changes identical to above .org 0x8003F1A8 .area 0x8003F1F0-. primWater: beqz $a0, loc_8003F1EC lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003F1D8 nop sb $s6, 0x52($s3) sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003F4C8 sb $fp, 0x50($s2) loc_8003F1D8: sb $fp, 0x50($s3) sb $s6, 0x52($s2) sb $a0, 0x51($s2) j 0x8003F4C8 sb $s4, 0x45($s2) loc_8003F1EC: lbu $v0, 0x340($s5) .endarea ; 0x8003F1A8 - 0x8003F1F0 ; Primary=Wind -- Secondary=Water or Earth ; Changes identical to above (less one SB here for some reason...) .org 0x8003F29C .area 0x8003F2DC-. primWind: beqz $a0, loc_8003F2D8 lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003F2C8 nop sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003F4C8 sb $fp, 0x50($s2) loc_8003F2C8: sb $fp, 0x50($s3) sb $a0, 0x51($s2) j 0x8003F4C8 sb $s4, 0x45($s2) loc_8003F2D8: lbu $v0, 0x340($s5) .endarea ; 0x8003F29C - 0x8003F2D8 ; Primary=Earth -- Secondary=Fire or Wind ; Changes identical to above (less one SB here for some reason...) .org 0x8003F380 .area 0x8003F3C0-. primEarth: beqz $a0, loc_8003F3BC lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003F3AC nop sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003F4C8 sb $fp, 0x50($s2) loc_8003F3AC: sb $fp, 0x50($s3) sb $a0, 0x51($s2) j 0x8003F4C8 sb $s4, 0x45($s2) loc_8003F3BC: lbu $v0, 0x340($s5) .endarea ; 0x8003F380 - 0x8003F3BC ; Primary=Lightning -- Secondary=Fire or Water ; Changes identical to above .org 0x8003F470 .area 0x8003F4B8-. primLightning: beqz $a0, loc_8003F4B4 lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003F4A0 nop sb $s6, 0x52($s3) sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003F4C8 sb $fp, 0x50($s2) loc_8003F4A0: sb $fp, 0x50($s3) sb $a0, 0x51($s2) sb $s6, 0x52($s2) j 0x8003F4C8 sb $s4, 0x45($s2) loc_8003F4B4: lbu $v0, 0x340($s5) .endarea ; 0x8003F470 - 0x8003F4B4 .close ;###################### Begin Second File ################### .openfile BP0_SEC.BIN, 0x8002B000 .headersize 0 ; Primary=Fire -- Secondary=Earth or Lightning .org 0x8003E860 .area 0x8003E8A8-. primFire2: beqz $a0, loc_8003E8A4 ; exit if unite not found lhu $v0, 0x3A($s3) ; slid this up to replace a nop lhu $v1, 0x3A($s2) ; need an extra op for a new J to "next" nop sltu $v0, $v1 bnez $v0, loc_8003E890 nop sb $s6, 0x52($s3) sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003EC80 ; end search sb $fp, 0x50($s2) loc_8003E890: sb $fp, 0x50($s3) sb $s6, 0x52($s2) sb $a0, 0x51($s2) j 0x8003EC80 ; end search sb $s4, 0x45($s2) loc_8003E8A4: lbu $v0, 0x340($s5) .endarea ; 0x8003E860 - 0x8003E8A8 ; Primary=Water -- Secondary=Wind or Lightning ; Changes identical to above .org 0x8003E960 .area 0x8003E9A8-. primWater2: beqz $a0, loc_8003E9A4 lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003E990 nop sb $s6, 0x52($s3) sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003EC80 sb $fp, 0x50($s2) loc_8003E990: sb $fp, 0x50($s3) sb $s6, 0x52($s2) sb $a0, 0x51($s2) j 0x8003EC80 sb $s4, 0x45($s2) loc_8003E9A4: lbu $v0, 0x340($s5) .endarea ; 0x8003E960 - 0x8003E9A8 ; Primary=Wind -- Secondary=Water or Earth ; Changes identical to above (less one SB here for some reason...) .org 0x8003EA54 .area 0x8003EA94-. primWind2: beqz $a0, loc_8003EA90 lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003EA80 nop sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003EC80 sb $fp, 0x50($s2) loc_8003EA80: sb $fp, 0x50($s3) sb $a0, 0x51($s2) j 0x8003EC80 sb $s4, 0x45($s2) loc_8003EA90: lbu $v0, 0x340($s5) .endarea ; 0x8003F29C - 0x8003F2D8 ; Primary=Earth -- Secondary=Fire or Wind ; Changes identical to above (less one SB here for some reason...) .org 0x8003EB38 .area 0x8003EB78-. primEarth2: beqz $a0, loc_8003EB74 lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003EB64 nop sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003EC80 sb $fp, 0x50($s2) loc_8003EB64: sb $fp, 0x50($s3) sb $a0, 0x51($s2) j 0x8003EC80 sb $s4, 0x45($s2) loc_8003EB74: lbu $v0, 0x340($s5) .endarea ; 0x8003EB38 - 0x8003EB78 ; Primary=Lightning -- Secondary=Fire or Water ; Changes identical to above .org 0x8003EC28 .area 0x8003EC70-. primLightning2: beqz $a0, loc_8003EC6C lhu $v0, 0x3A($s3) lhu $v1, 0x3A($s2) nop sltu $v0, $v1 bnez $v0, loc_8003EC58 nop sb $s6, 0x52($s3) sb $a0, 0x51($s3) sb $s1, 0x45($s3) j 0x8003EC80 sb $fp, 0x50($s2) loc_8003EC58: sb $fp, 0x50($s3) sb $a0, 0x51($s2) sb $s6, 0x52($s2) j 0x8003EC80 sb $s4, 0x45($s2) loc_8003EC6C: lbu $v0, 0x340($s5) .endarea ; 0x8003EC28 - 0x8003EC70 .close