System(s) |
Playstation, PSP, PSN (POPS) |
Bug Type | Gameplay |
Region Introduced | |
Patch Version | 2.01.065b |
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.
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.
.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