System(s) |
Playstation, PSP, PSN (POPS) |
Bug Type | Gameplay |
Region Introduced | |
Patch Version | 2.01.065b |
A total of 25 items are available, three seeds each for Cabbage, Potatoes, Spinach, and Tomatoes; three Chicks, Pigs, and Cows; and four Sheep. Konami packs these bits into three bytes, which complicates retrieving and setting them, but not as much as their code would indicate. Here is how the data breaks down.
Item Type | Count Address | Flag 1 | Flag 2 | Flag 3 | Flag 4 | ||||
---|---|---|---|---|---|---|---|---|---|
Address | Bit | Address | Bit | Address | Bit | Address | Bit | ||
Cabbage | 0x8006AA2B | 0x8006A91C | 0 | 0x8006A91C | 1 | 0x8006A91C | 2 | ||
Potato | 0x8006AA2C | 0x8006A91C | 3 | 0x8006A91C | 4 | 0x8006A91C | 5 | ||
Spinach | 0x8006AA2D | 0x8006A91C | 6 | 0x8006A91C | 7 | 0x8006A91D | 0 | ||
Tomato | 0x8006AA2E | 0x8006A91D | 1 | 0x8006A91D | 2 | 0x8006A91D | 3 | ||
Chick | 0x8006AA2F | 0x8006A91D | 4 | 0x8006A91D | 5 | 0x8006A91D | 6 | ||
Pig | 0x8006AA30 | 0x8006A91D | 7 | 0x8006A91E | 0 | 0x8006A91E | 1 | ||
Sheep | 0x8006AA31 | 0x8006A91E | 2 | 0x8006A91E | 3 | 0x8006A91E | 4 | 0x8006A91E | 5 |
Cow | 0x8006AA31 | 0x8006A91E | 6 | 0x8006A91E | 7 | 0x8006A91F | 0 |
The code below is taken from the routine that accepts seeds. It is slightly simpler, owing to the fact that there are only three of each kind of item it has to deal with. Still, it has to span bytes and handle the data in somewhat ugly ways. The snippet is after the counting of seeds in the party's inventory. There is nothing wrong with the way the count is done. All the relevant code is in /CDROM/110_ARK/VK19.BIN.
RAM:8015E198 lbu $a0, 0x1A2B($v1) RAM:8015E19C li $v0, 1 RAM:8015E1A0 bne $a0, $v0, loc_8015E1B4 RAM:8015E1A4 nop RAM:8015E1A8 lbu $v0, 0x191C($v1) RAM:8015E1AC j loc_8015E1E4 RAM:8015E1B0 ori $v0, 1 RAM:8015E1B4 # --------------------------------------------------------------------------- RAM:8015E1B4 RAM:8015E1B4 loc_8015E1B4: # CODE XREF: TakeSeeds+134j RAM:8015E1B4 li $v0, 2 RAM:8015E1B8 bne $a0, $v0, loc_8015E1CC RAM:8015E1BC nop RAM:8015E1C0 lbu $v0, 0x191C($v1) RAM:8015E1C4 j loc_8015E1E4 RAM:8015E1C8 ori $v0, 2 RAM:8015E1CC # --------------------------------------------------------------------------- RAM:8015E1CC RAM:8015E1CC loc_8015E1CC: # CODE XREF: TakeSeeds+14Cj RAM:8015E1CC li $v0, 3 RAM:8015E1D0 bne $a0, $v0, loc_8015E1E8 RAM:8015E1D4 nop RAM:8015E1D8 lbu $v0, 0x191C($v1) RAM:8015E1DC nop RAM:8015E1E0 ori $v0, 4 RAM:8015E1E4 RAM:8015E1E4 loc_8015E1E4: # CODE XREF: TakeSeeds+140j RAM:8015E1E4 # TakeSeeds+158j RAM:8015E1E4 sb $v0, 0x191C($v1) RAM:8015E1E8 RAM:8015E1E8 loc_8015E1E8: # CODE XREF: TakeSeeds+164j RAM:8015E1E8 ori $v1, $s7, 0x8000 RAM:8015E1EC lbu $a0, 0x1A2C($v1) RAM:8015E1F0 li $v0, 1 RAM:8015E1F4 bne $a0, $v0, loc_8015E208 RAM:8015E1F8 nop RAM:8015E1FC lbu $v0, 0x191C($v1) RAM:8015E200 j loc_8015E238 RAM:8015E204 ori $v0, 8 RAM:8015E208 # --------------------------------------------------------------------------- RAM:8015E208 RAM:8015E208 loc_8015E208: # CODE XREF: TakeSeeds+188j RAM:8015E208 li $v0, 2 RAM:8015E20C bne $a0, $v0, loc_8015E220 RAM:8015E210 nop RAM:8015E214 lbu $v0, 0x191C($v1) RAM:8015E218 j loc_8015E238 RAM:8015E21C ori $v0, 0x10 RAM:8015E220 # --------------------------------------------------------------------------- RAM:8015E220 RAM:8015E220 loc_8015E220: # CODE XREF: TakeSeeds+1A0j RAM:8015E220 li $v0, 3 RAM:8015E224 bne $a0, $v0, loc_8015E23C RAM:8015E228 nop RAM:8015E22C lbu $v0, 0x191C($v1) RAM:8015E230 nop RAM:8015E234 ori $v0, 0x20 RAM:8015E238 RAM:8015E238 loc_8015E238: # CODE XREF: TakeSeeds+194j RAM:8015E238 # TakeSeeds+1ACj RAM:8015E238 sb $v0, 0x191C($v1) RAM:8015E23C RAM:8015E23C loc_8015E23C: # CODE XREF: TakeSeeds+1B8j RAM:8015E23C ori $v1, $s7, 0x8000 RAM:8015E240 lbu $a0, 0x1A2D($v1) RAM:8015E244 li $v0, 1 RAM:8015E248 bne $a0, $v0, loc_8015E264 RAM:8015E24C li $v0, 2 RAM:8015E250 lbu $v0, 0x191C($v1) RAM:8015E254 nop RAM:8015E258 ori $v0, 0x40 RAM:8015E25C j loc_8015E29C RAM:8015E260 sb $v0, 0x191C($v1) RAM:8015E264 # --------------------------------------------------------------------------- RAM:8015E264 RAM:8015E264 loc_8015E264: # CODE XREF: TakeSeeds+1DCj RAM:8015E264 bne $a0, $v0, loc_8015E280 RAM:8015E268 li $v0, 3 RAM:8015E26C lbu $v0, 0x191C($v1) RAM:8015E270 nop RAM:8015E274 ori $v0, 0x80 RAM:8015E278 j loc_8015E298 RAM:8015E27C sb $v0, 0x191C($v1) RAM:8015E280 # --------------------------------------------------------------------------- RAM:8015E280 RAM:8015E280 loc_8015E280: # CODE XREF: TakeSeeds:loc_8015E264j RAM:8015E280 bne $a0, $v0, loc_8015E298 RAM:8015E284 nop RAM:8015E288 lbu $v0, 0x191D($v1) RAM:8015E28C nop RAM:8015E290 ori $v0, 1 RAM:8015E294 sb $v0, 0x191D($v1) RAM:8015E298 RAM:8015E298 loc_8015E298: # CODE XREF: TakeSeeds+20Cj RAM:8015E298 # TakeSeeds:loc_8015E280j RAM:8015E298 ori $v1, $s7, 0x8000 RAM:8015E29C RAM:8015E29C loc_8015E29C: # CODE XREF: TakeSeeds+1F0j RAM:8015E29C lbu $a0, 0x1A2E($v1) RAM:8015E2A0 li $v0, 1 RAM:8015E2A4 bne $a0, $v0, loc_8015E2B8 RAM:8015E2A8 nop RAM:8015E2AC lbu $v0, 0x191D($v1) RAM:8015E2B0 j loc_8015E2E8 RAM:8015E2B4 ori $v0, 2 RAM:8015E2B8 # --------------------------------------------------------------------------- RAM:8015E2B8 RAM:8015E2B8 loc_8015E2B8: # CODE XREF: TakeSeeds+238j RAM:8015E2B8 li $v0, 2 RAM:8015E2BC bne $a0, $v0, loc_8015E2D0 RAM:8015E2C0 nop RAM:8015E2C4 lbu $v0, 0x191D($v1) RAM:8015E2C8 j loc_8015E2E8 RAM:8015E2CC ori $v0, 4 RAM:8015E2D0 # --------------------------------------------------------------------------- RAM:8015E2D0 RAM:8015E2D0 loc_8015E2D0: # CODE XREF: TakeSeeds+250j RAM:8015E2D0 li $v0, 3 RAM:8015E2D4 bne $a0, $v0, loc_8015E2F0 RAM:8015E2D8 li $v0, 1 RAM:8015E2DC lbu $v0, 0x191D($v1) RAM:8015E2E0 nop RAM:8015E2E4 ori $v0, 8 RAM:8015E2E8 RAM:8015E2E8 loc_8015E2E8: # CODE XREF: TakeSeeds+244j RAM:8015E2E8 # TakeSeeds+25Cj RAM:8015E2E8 sb $v0, 0x191D($v1) RAM:8015E2EC li $v0, 1
There really is not an easy way to modify the existing routine to work correctly. So it had to be rewritten. This is actually pretty easy to do. The existing routine is huge and bloated, and can be replaced with a routine about a third of the size. Code just needs to be inserted after the inventory count, to replace the setting of flags.
.openfile VK19.BIN, 0x8015DC50 .headersize 0 .org 0x8015E198 ; file location will be 0x540 ; start with cabbage. cabbage: lbu v0, 0x1A2B(v1) ; cabbage count lw s4, 0x191C(v1) ; flags (seeds and stock) li s6, 7 ; mask base li s5, 3 ; max count (this will keep) subu v0, s5, v0 ; shift amount srlv v0, s6, v0 ; 0x7 >> (3 - cabbage count) or s4, s4, v0 ; flags |= mask potato: lbu v0, 0x1A2C(v1) ; count li s6, 7 ; load delay subu v0, s5, v0 srlv v0, s6, v0 sll v0, v0, 3 ; finish mask or s4, s4, v0 spinach: lbu v0, 0x1A2D(v1) ; count li s6, 7 ; load delay subu v0, s5, v0 srlv v0, s6, v0 sll v0, v0, 6 ; finish mask or s4, s4, v0 tomato: lbu v0, 0x1A2E(v1) ; count li s6, 7 ; load delay subu v0, s5, v0 srlv v0, s6, v0 sll v0, v0, 9 ; finish mask or s4, s4, v0 store: sw s4, 0x191C(v1) beq zero, zero, 0x8015E2EC ; skip the rest nop .close
The above takes the counts, and uses them to construct an appropriate mask that will be used to set the required bits in the game's data. It sets all the bits indicated by the counts, each time the routine is called. In this way, you can turn in none or all the seeds at one time, and the flags will be retained or set as needed. It also treats the entire 32-bit value allocated to the farm flags (both seeds and livestock) as a single variable. Doing this, the code does not need to worry about moving ahead bytes. It just has to set the right bits in the data. Since the only modification done to the flags is a bitwise OR, it can never unset anything by accident.