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.
Multiple sets of Guardian Deity Plans can be found, or they can sometimes be impossible to find.
Guardian Deity Plans Bug
Bug Details
System(s) Playstation,
PSP,
PSN (POPS)
Bug TypeGameplay
Region Introduced
Patch Version2.01.065b

Regions Affected
This bug has gone relatively unnoticed for years. In investigating other bugs, it has been discovered that the code that manages Guardian Deity Plans is badly flawed. Triggering this bug would require a combination of bad luck, and waiting to acquire the plans until very late in the game, or handing in plans very early. Most people will never run afoul of this problem, because the character the Plans are used with is not recruited until very late in the game. Compared to the Recipes Bug this is totally invisible.

The most likely effect of this bug is getting duplicate plans. Any plan you give to your sculptor that is not unique, e.g., a battle or mini-game prize, can be gotten again.

Cause
When Guardian Deity Plan are handed into Jude, bit-flags are set to indicate this. These flags will inform other aspects of the game that it is no longer appropriate for these plans to be dropped by enemies or given as prizes. There are sixteen plans in total, which means two bytes are necessary to indicate the status of all plans. However, the way the check was coded, it will examine four bytes, and only the first four bits of each. So the first four plans will be checked properly; the second set of four will be checked against the flags for the third set of four, and the last eight plans will be checked against flags that are not even for plans.

This code resides in /CDROM/150_BPRG/BUFF0/BP0_AFT.BIN

RAM:8002D8A0 BlueprintFlags:                          # CODE XREF: OnetimeFlags+D8j
RAM:8002D8A0                 sltiu   $v0, $a0, 0x10   # is item a plan?
RAM:8002D8A4                 beqz    $v0, WindowFlags # if no, check windows
RAM:8002D8A8                 move    $v1, $a0
RAM:8002D8AC                 bgez    $v1, loc_8002D8B8# this check is pointless
RAM:8002D8B0                 move    $v0, $v1
RAM:8002D8B4                 addiu   $v0, $s3, 0xFFE8
RAM:8002D8B8
RAM:8002D8B8 loc_8002D8B8:                            # CODE XREF: OnetimeFlags+108j
RAM:8002D8B8                 sra     $v0, 2           # Shift blueprint number right 2.  Intended to set the byte number.
RAM:8002D8BC                 sll     $v1, $v0, 2      # Shift the result left 2.  This will be used to calculate the bit shift amount.
RAM:8002D8C0                 addu    $v0, $s4, $v0    # Add byte number to base address
RAM:8002D8C4                 lbu     $v0, 0x1FA($v0)  # Load flags byte
RAM:8002D8C8                 subu    $v1, $a0, $v1    # Subtract result of left shift from recipe number.  This is the shift amount.
RAM:8002D8CC                 srav    $v0, $v1         # Shift the desired bit into the lowest-order position
RAM:8002D8D0                 andi    $v0, 1           # Isolate bit.
RAM:8002D8D4                 bnez    $v0, loc_8002D92C# If bit is on, plan was handed in.
RAM:8002D8D8                 li      $v0, 1

The code determines what byte the flag is in, so it can load it, then it determines what bit number within the byte will represent that plan. If the bit is 1, then you already handed it over to Jude. This code behaves as though every byte consists of only four bits. Therefore, the first four plans are checked properly, and thereafter the wrong byte is being analyzed. Furthermore, only the four least-significant bits in every byte can be analyzed.

As a bonus, not only does it analyze the wrong bytes, when setting the flags, Konami swapped the Rabbit and Turtle Plans around. As the highest item numbers, the Turtle plans should take up the uppermost 4 bits, but they are instead indicated by the least-significant 4 bits.

Flags are at 0x8006AA3A, occupying 16-bits (half-word). All items are type 5 with quantity 0 (0x50).

Plans Bit Flags
Bit Offset Item Digit Plan Number Plan Name
0 0x1B 1 Dragon Plans #1
1 0x1C 2 Dragon Plans #2
2 0x1D 3 Dragon Plans #3
3 0x1E 4 Dragon Plans #4
4 0x1F 5 Unicorn Plans #1
5 0x20 6 Unicorn Plans #2
6 0x21 7 Unicorn Plans #3
7 0x22 8 Unicorn Plans #4
8 0x27 13 Turtle Plans #1
9 0x28 14 Turtle Plans #2
10 0x29 15 Turtle Plans #3
11 0x2A 16 Turtle Plans #4
12 0x23 9 Rabbit Plans #1
13 0x24 10 Rabbit Plans #2
14 0x25 11 Rabbit Plans #3
15 0x26 12 Rabbit Plans #4

As you can see, it goes from item 0x22 to 0x27. The flag number is calculated in the check routines by first subtracting 0x1B from the Item Digit. However, the calculation cannot be so simple here, because they failed to keep the linear increases consistent. Setting flags is typically done by including a byte index and a bit mask, so this would be an easy mistake to make. Somebody forgot which set of four came first, and then the person responsible for the bit-flag check routines did their usual botched job.

Fix
With the additional bug involving the setting of the flags, this becomes complicated to fix. The routine has been recoded to access the flags as a single half-word, and checks have been added to calculate the bit offset correctly.

.area 0x8002D8DC - 0x8002D8A0 			; check that the LI macro doesn't expand too far.
blueprintflags:
	sltiu	v0, a0, 0x10			; this section reorganizes the checks and changes
	beqz	v0, windowflags			; the logic to check a halfword field instead of byte
	sltiu	v0, a0, 8
	bne	v0, zero, load
	li	v1, 0
	sltiu	v0, a0, 0xC
	bne	v0, zero, load
	li	v1, 0xFFFFFFFC
	li	v1, 4
load:
	lhu	v0, 0x1FA(s4)
	subu	v1, a0, v1
	srav	v0, v0, v1
	andi	v0, v0, 1
	bnez	v0, exit
	li	v0, 1
.endarea