Remote linking to avatars
Do not link to Suikosource images on forums, webpages, or anyplace else. If you wish to use the images, place them in your own webspace. We do not allow you to use them from our server.
In the showdown with Luca, this glitch with the hero's party can be exploited for an easy win.
Luca Battle Bug
Bug Details
System(s) Playstation,
PSP,
PSN (POPS)
Bug TypeGameplay
Region Introduced
Patch Version2.01.065b

Regions Affected
This bug allows you to create an otherwise impossible party configuration in the final battle against Luca Blight, allowing you to win the battle without any danger to your Hero.

The final battle with Luca Blight is one of the most difficult fights in the game. Luca can attack three times per turn. He has a three-hit combination with his sword that does enormous damage to one person, a special move that attacks one column of the party for high damage with a fire element bonus, and a second, nearly identical special move that hits one row for slightly less damage per person. Luca can easily mow down most parties, unless the player prepares thoroughly, or invests a fair amount of time leveling up characters. However, the bug can be exploited for a ridiculously easy win.

Triggering
After the Major Battle with Luca's army, the party is automatically emptied, and the Hero is placed in his customary spot, leftmost in the front row. The next event will involve setting up an ambush for Luca Blight. After choosing to deploy, the player will have to select members for three parties, one led by the Hero, one by Viktor, and the last led by Flik. In order to exploit the bug, the player must delay selecting these parties, and instead go to Leona in the tavern. Once there, form a party with the hero in the leftmost spot in the back row (position 4). The party should be formed without using Viktor or Flik (Viktor should not be available anyway). Using them can break the exploit. Other than that, it does not matter who is used, as the event will purge them anyway. After forming the party, return to Shu and continue the events. When selecting the hero's party, do not add or remove anyone. Instead, exit the menu immediately. The formation menu will appear, and the hero will be alone in the party and in the back row. When his party fights Luca, it will be impossible for him to attack (although he can counter), and the player can slowly whittle away Luca's health without any real danger.

Cause
Luca uses a short-range weapon, and all of his attacks must target the front row. Normally, this would not be an issue because the game will not allow you to place characters in the back row until the front row is filled. Unfortunately for Konami, during the events leading up to the Luca battle, a special version of the Party Change module is run that does not fully enforce this rule.

In this situation, where a special module must manage three parties, the bug is that the programmer assumed that no player in their right mind would form anything less than a full party to take on Luca, and they would certainly never let the Hero go alone. It's dangerous. Normally, when even a single character is removed, the party is reorganized so that the front row is filled, and any empty spots are shifted to the back row. There is a convenient function that does all this work. It is simply not called by the special module after emptying the Hero's party. Viktor's party, and Flik's party are both initialized with leaders in the first position, so they cannot be exploited.

The code below is responsible for emptying the Hero's party. It resides in /CDROM/140_HONP/PARTYCE1.BIN. In order to reorganize the party, a single function can be called that resides in the main executable, and is loaded at 0x80073894. After emptying a party, this function would simply shift the hero to the first position. There are also script commands, and code in other modules that similarly empty the party. Had they been used, instead of writing a duplicate routine, the bug would not exist.

RAM:80110C00                 move    $s0, $0
RAM:80110C04                 li      $s1, 0x80072F04  # Routine: GetIDForPartyPos
RAM:80110C0C                 li      $s5, 0x80072844  # Routine: MP_CharaRecStat
RAM:80110C14                 li      $s3, 0x8007344C  # Routine: RemoveFromParty
RAM:80110C1C                 sb      $0, 2($s4)
RAM:80110C20
RAM:80110C20 loc_80110C20:                            # CODE XREF: RAM:80110C78j
RAM:80110C20                 sw      $s1, -0x5304($s2)
RAM:80110C24                 jalr    $s1
RAM:80110C28                 move    $a0, $s0
RAM:80110C2C                 beqz    $v0, loc_80110C70
RAM:80110C30                 nop
RAM:80110C34                 sw      $s1, -0x5304($s2)
RAM:80110C38                 jalr    $s1
RAM:80110C3C                 move    $a0, $s0
RAM:80110C40                 li      $v1, 1
RAM:80110C44                 beq     $v0, $v1, loc_80110C70
RAM:80110C48                 move    $a0, $s0
RAM:80110C4C                 jalr    $s1
RAM:80110C50                 sw      $s1, -0x5304($s2)
RAM:80110C54                 li      $a0, 0x26
RAM:80110C58                 move    $a1, $v0
RAM:80110C5C                 jalr    $s5
RAM:80110C60                 sw      $s5, -0x5304($s2)
RAM:80110C64                 move    $a0, $s0
RAM:80110C68
RAM:80110C68 CallRemoveFromParty_00:                  # After this, it should call 0x80073894 - ReformPartyOnExit
RAM:80110C68                 jalr    $s3
RAM:80110C6C                 sw      $s3, -0x5304($s2)
RAM:80110C70
RAM:80110C70 loc_80110C70:                            # CODE XREF: RAM:80110C2Cj
RAM:80110C70                                          # RAM:80110C44j
RAM:80110C70                 addiu   $s0, 1
RAM:80110C74                 slti    $v0, $s0, 6
RAM:80110C78                 bnez    $v0, loc_80110C20
RAM:80110C7C                 li      $a0, 0x25
RAM:80110C80                 li      $s0, 0x80072844

Fix
After buying some space by eliminating leftover debug/trace code, and shuffling a few operations, the appropriate function just needs to be called.

; Suikoden II Luca Bug/Party Change Fix
; Written by Pyriel
;
 
.psx
.align 4
 
; all the $s registers are pretty much fair game.
; Using $v1 for address (already loaded).
 
.openfile PARTYCE1.BIN, 0x8010DC50
.headersize 0
.org 0x80110C20
; file location will be 0x2FD0
 
.area 0x80110C80-.
; replace loop that empties party
loop:
    jalr    $s1
    move    $a0, $s0
    beqz    $v0, continue
    nop
    jalr    $s1
    move    $a0, $s0
    li      $v1, 1
    beq     $v0, $v1, continue
    move    $a0, $s0
    jalr    $s1
    nop

    li      $a0, 0x26
    jalr    $s5
    move    $a1, $v0
    move    $a0, $s0
    jalr    $s3                ; RemoveFromParty After this, it should call 0x80073894 - ReformPartyOnExit
    nop
continue:
    addiu   $s0, 1
    slti    $v0, $s0, 6
    bnez    $v0, loop
    nop
    jal     0x80073894
    nop
    li    $a0, 0x25
.endarea
.close