000e14a4: ori r2,r0,0x0002
000e14a8: lui r3,0x800f
000e14ac: lbu r3,0x38a4(r3)// 800F38A4=02 ➝ Phase 2 of W-Item
000e14b0: nop
000e14b4: bne r3,r2,0x000e156c
000e14b8: ori r2,r0,0x000a
000e14bc: lui r3,0x800f
000e14c0: lbu r3,0x389d(r3)// 800F389D=0A ➝ W-Item Menu
000e14c4: nop
000e14c8: bne r3,r2,0x000e156c
000e14cc: nop
000e14d0: lui r2,0x800f
000e14d4: lhu r2,0x562c(r2)//800F562C ➝ Store position of first item used.
000e14d8: nop
000e14dc: sll r3,r2,0x01
000e14e0: addu r3,r3,r2
000e14e4: sll r3,r3,0x01
000e14e8: addu r3,r3,r19
000e14ec: lbu r2,0x0002(r3)
000e14f0: nop
000e14f4: bne r2,r0,0x000e150c
000e14f8: nop
000e14fc: lui r2,0x800f
000e1500: lhu r2,0x314e(r2) // 0x800F314E ➝ Store ID of first item used.
000e1504: nop
000e1508: sh r2,0x0000(r3)
000e150c: lui r3,0x800f
000e1510: lhu r3,0x562c(r3)
000e1514: nop
000e1518: sll r2,r3,0x01
000e151c: addu r2,r2,r3
000e1520: sll r2,r2,0x01
000e1524: addu r2,r2,r19
000e1528: lbu r3,0x0002(r2)
000e152c: nop
000e1530: addiu r3,r3,0x0001 // Add 1 item.
000e1534: sb r3,0x0002(r2)
000e1538: lui r3,0x800f
000e153c: lhu r3,0x562c(r3)
000e1540: nop
000e1544: sll r2,r3,0x01
000e1548: addu r2,r2,r3
000e154c: sll r2,r2,0x01
000e1550: addu r3,r2,r19
000e1554: lbu r2,0x0002(r3)
000e1558: nop
000e155c: sltiu r2,r2,0x0064
000e1560: bne r2,r0,0x000e156c
000e1564: ori r2,r0,0x0063 // Quanty limit (99)
000e1568: sb r2,0x0002(r3)
000e14a4: ori r2,r0,0x0002
000e14a8: lui r3,0x800f
000e14ac: lbu r3,0x38a4(r3) // 800F38A4=02 -> Phase 2 of W-Item
000e14b0: nop
000e14b4: bne r3,r2,0x000e156c // branch if phase not 2?
000e14b8: ori r2,r0,0x000a
000e14bc: lui r3,0x800f
000e14c0: lbu r3,0x389d(r3) // 800F389D=0A -> W-Item Menu
000e14c4: nop
000e14c8: bne r3,r2,0x000e156c // branch if menu ID not 10?
000e14cc: nop
000e14d0: lui r2,0x800f
000e14d4: lhu r2,0x562c(r2) // 800F562C -> Load position of first item used.
000e14d8: nop
000e14dc: sll r3,r2,0x01
000e14e0: addu r3,r3,r2
000e14e4: sll r3,r3,0x01
000e14e8: addu r3,r3,r19 // (position of first item * 6) + constant
000e14ec: lbu r2,0x0002(r3) // get quantity of first used item
000e14f0: nop
000e14f4: bne r2,r0,0x000e150c // branch if nonzero
000e14f8: nop
000e14fc: lui r2,0x800f
000e1500: lhu r2,0x314e(r2) // 0x800F314E -> Load ID of first item used.
000e1504: nop
000e1508: sh r2,0x0000(r3)
000e150c: lui r3,0x800f
000e1510: lhu r3,0x562c(r3) // 800F562C -> Load position of first item used.
000e1514: nop
000e1518: sll r2,r3,0x01
000e151c: addu r2,r2,r3
000e1520: sll r2,r2,0x01
000e1524: addu r2,r2,r19 // (position of first item * 6) + constant
000e1528: lbu r3,0x0002(r2) // get quantity of first used item
000e152c: nop
000e1530: addiu r3,r3,0x0001 // Add 1 to it
000e1534: sb r3,0x0002(r2) // save new value
000e1538: lui r3,0x800f
000e153c: lhu r3,0x562c(r3) // 800F562C -> Load position of first item used.
000e1540: nop
000e1544: sll r2,r3,0x01
000e1548: addu r2,r2,r3
000e154c: sll r2,r2,0x01
000e1550: addu r3,r2,r19 // (position of first item * 6) + constant
000e1554: lbu r2,0x0002(r3) // get quantity of first used item
000e1558: nop
000e155c: sltiu r2,r2,0x0064 // is it less than 100?
000e1560: bne r2,r0,0x000e156c // branch if so
000e1564: ori r2,r0,0x0063 // Quantity limit (99)
000e1568: sb r2,0x0002(r3) // save capped quantity
is 800F562C normalized to the first item slot; that is, will it hold 0 when the first W-Item used was in Slot 0?Yes, it doesn't include any constant. Slot 0 is 00, Slot 1 is 01... Slot 15 is 0F, etc...
also, i'm hoping that 0x800F314E indeed holds the ID of first W-Item used all of the time, and isn't one of the things that's clobbered by an intervening Morph?Yes, I confirm it. Potion=00, S Potion=01, Ink=3A, etc...
000e14a4: ori r2,r0,0x0002
000e14a8: lui r3,0x800f
000e14ac: lbu r3,0x38a4(r3) // 800F38A4=02 -> Phase 2 of W-Item
000e14b0: nop
000e14b4: bne r3,r2,noAddBack // branch if phase not 2
000e14b8: ori r2,r0,0x000a
000e14bc: lui r3,0x800f
000e14c0: lbu r3,0x389d(r3) // 800F389D=0A -> W-Item Menu
000e14c4: nop
000e14c8: bne r3,r2,noAddBack // branch if menu ID not 10
000e14cc: nop
// Add cancelled first item for W-Item back to inventory, using one of three
// methods, in order of preference:
//
// 1) The slot from where the item was used, provided it still has at least 1
// of that type.
// 2) The first slot that does hold at least 1 of that type.
// 3) The first slot with 0 item quantity (i.e. an empty slot).
000e14d0: lui r2,0x800f
000e14d4: lhu r2,0x562c(r2) // 800F562C -> Load position of first item used.
000e14d8: nop
000e14dc: sll r3,r2,0x01
000e14e0: addu r3,r3,r2
000e14e4: sll r3,r3,0x01
000e14e8: addu r3,r3,r19 // (position of first item * 6) + constant
000e14ec: lbu r2,0x0002(r3) // get quantity of item in slot we used from
000e14f0: nop
000e14f4: beq r2,r0,findMatch // branch if zero, indicative of nothing there.
000e14f8: nop
000e14fc: lui r2,0x800f
000e1500: lhu r2,0x314e(r2) // 0x800F314E -> Load ID of first item used.
000e1504: nop
000e1508: lhu r3,0x0000(r3) // get ID of item in slot we used from
000e150c: nop
000e1510: beq r2,r3,useCurrent // branch if it indeed matches the actual item used.
// intervening Morph/etc can cause mismatch.
000e1514: nop
findMatch:
000e1518: or r3,r0,0 // start loop counter at item slot 0
findLoop1: // our original slot was claimed, so next, look for
// a matching item anywhere in inventory.
000e151c: addu r3,r3,r19 // (position of current item * 6) + constant
000e1520: lbu r2,0x0002(r3) // get quantity of item in current slot
000e1524: nop
000e1528: beq r2,r0,nextSlot // branch if zero, indicative of nothing there.
000e152c: nop
000e1530: lui r2,0x800f
000e1534: lhu r2,0x314e(r2) // 0x800F314E -> Load ID of first item used.
000e1538: nop
000e153c: addiu sp,sp,-4 // can probably skip this and other SP instruction,
// as they're used very close to each other, and
// just save and load from -4(sp). but in
// off-chance something can interrupt these, i
// want to be safe.
000e1540: sw r3,0(sp) // save our loop counter to stack
000e1544: nop
000e1548: lbu r3,0x0000(r3) // get ID of item in current slot
000e154c: nop
000e1550: xor r2,r3,r2 // does it match that of first item used? save test
// result in r2.
000e1554: lw r3,0(sp) // retrieve our loop counter from stack
000e1558: nop
000e155c: addiu sp,sp,4
000e1560: beq r2,r0,useCurrent // branch if current slot's item matches the first
// item used; we've found somewhere to add it back.
000e1564: nop
nextSlot:
000e1568: subu r3,r3,r19 // temporarily convert loop counter to 0-based index
000e156c: addiu r3,r3,6 // advance to next item slot
000e1570: sltiu r2,r3,1536 // are we pointing past the 256th (0-based) slot?
000e1574: bne r2,r0,findLoop1 // loop and check next slot if not
000e1578: nop
findEmpty:
000e157c: or r3,r0,0 // start loop counter at item slot 0
findLoop2: // we found no matching contents, so next, look for
// our first empty slot.
000e1580: addu r3,r3,r19 // (position of current item * 6) + constant
000e1584: lbu r2,0x0002(r3) // get quantity of item in current slot
000e1588: nop
000e158c: beq r2,r0,useCurInit // branch if zero, indicative of nothing there,
// which is our desired home at this point.
000e1590: nop
000e1594: subu r3,r3,r19 // temporarily convert loop counter to 0-based index
000e1598: addiu r3,r3,6 // advance to next item slot
000e159c: sltiu r2,r3,1536 // are we pointing past the 256th (0-based) slot?
000e15a0: bne r2,r0,findLoop2 // loop and check next slot if not
000e15a4: nop
000e15a8: beq r0,r0,noAddBack // all 3 methods couldn't find a suitable slot, so
// don't add back item anywhere.
000e15ac: nop
useCurInit:
000e15b0: lui r2,0x800f
000e15b4: lhu r2,0x314e(r2) // 0x800F314E -> Load ID of first item used.
000e15b8: nop
000e15bc: sh r2,0x0000(r3) // save Item ID in our chosen slot
useCurrent:
000e15c0: lbu r2,0x0002(r3) // get quantity of item in chosen slot
000e15c4: nop
000e15c8: addiu r2,r2,0x0001 // Add 1 to it
000e15cc: sb r2,0x0002(r3) // save new quantity
000e15d0: nop
000e15d4: sltiu r2,r2,0x0064 // is it less than 100?
000e15d8: bne r2,r0,keepVal // branch if so
000e15dc: ori r2,r0,0x0063 // Quantity limit (99)
000e15e0: sb r2,0x0002(r3) // save capped quantity
keepVal:
noAddBack:
5) is the in-battle item list 256 entries long? if not, modify the two "sltiu r2,r3,1536" accordingly.
however, i wouldn't be surprised if the game already has an Add_Item_ID_to_Inventory function that you can call.
000e1508: lhu r3,0x0000(r3) // get ID of item in slot we used from
000e150c: nop
000e1510: beq r2,r3,useCurrent // branch if it indeed matches the actual item used.
// intervening Morph/etc can cause mismatch.
000e1548: lbu r3,0x0000(r3) // get ID of item in current slot
000e14a4: ori r2,r0,0x0002
000e14a8: lui r3,0x800f
000e14ac: lbu r3,0x38a4(r3) // 800F38A4=02 -> Phase 2 of W-Item
000e14b0: nop
000e14b4: bne r3,r2,noAddBack // branch if phase not 2
000e14b8: ori r2,r0,0x000a
000e14bc: lui r3,0x800f
000e14c0: lbu r3,0x389d(r3) // 800F389D=0A -> W-Item Menu
000e14c4: nop
000e14c8: bne r3,r2,noAddBack // branch if menu ID not 10
000e14cc: nop
// Add cancelled first item for W-Item back to inventory, using one of three
// methods, in order of preference:
//
// 1) The slot from where the item was used, provided it still has at least 1
// of that type.
// 2) The first slot that does hold at least 1 of that type.
// 3) The first slot with 0 item quantity (i.e. an empty slot).
000e14d0: lui r2,0x800f
000e14d4: lhu r2,0x562c(r2) // 800F562C -> Load position of first item used.
000e14d8: nop
000e14dc: sll r3,r2,0x01
000e14e0: addu r3,r3,r2
000e14e4: sll r3,r3,0x01
000e14e8: addu r3,r3,r19 // (position of first item * 6) + constant
000e14ec: lbu r2,0x0002(r3) // get quantity of item in slot we used from
000e14f0: nop
000e14f4: beq r2,r0,findMatch // branch if zero, indicative of nothing there.
000e14f8: nop
000e14fc: lui r2,0x800f
000e1500: lhu r2,0x314e(r2) // 0x800F314E -> Load ID of first item used.
000e1504: nop
000e1508: addiu sp,sp,-4 // can probably skip this and other SP instruction,
// as they're used very close to each other, and
// just save and load from -4(sp). but in
// off-chance something can interrupt these, i
// want to be safe.
000e150c: sw r3,0(sp) // save our loop counter to stack
000e1510: nop
000e1514: lhu r3,0x0000(r3) // get ID of item in current slot
000e1518: nop
000e151c: xor r2,r3,r2 // does it match that of first item used? save test
// result in r2.
000e1520: lw r3,0(sp) // retrieve our loop counter from stack
000e1524: nop
000e1528: addiu sp,sp,4
000e152c: beq r2,r0,useCurrent // branch if it indeed matches the actual item used.
// intervening Morph/etc can cause mismatch.
000e1530: nop
findMatch:
000e1534: ori r3,r0,0x0000 // start loop counter at item slot 0
findLoop1: // our original slot was claimed, so next, look for
// a matching item anywhere in inventory.
000e1538: addu r3,r3,r19 // (position of current item * 6) + constant
000e153c: lbu r2,0x0002(r3) // get quantity of item in current slot
000e1540: nop
000e1544: beq r2,r0,nextSlot // branch if zero, indicative of nothing there.
000e1548: nop
000e154c: lui r2,0x800f
000e1550: lhu r2,0x314e(r2) // 0x800F314E -> Load ID of first item used.
000e1554: nop
000e1558: addiu sp,sp,-4 // can probably skip this and other SP instruction,
// as they're used very close to each other, and
// just save and load from -4(sp). but in
// off-chance something can interrupt these, i
// want to be safe.
000e155c: sw r3,0(sp) // save our loop counter to stack
000e1560: nop
000e1564: lhu r3,0x0000(r3) // get ID of item in current slot
000e1568: nop
000e156c: xor r2,r3,r2 // does it match that of first item used? save test
// result in r2.
000e1570: lw r3,0(sp) // retrieve our loop counter from stack
000e1574: nop
000e1578: addiu sp,sp,4
000e157c: beq r2,r0,useCurrent // branch if current slot's item matches the first
// item used; we've found somewhere to add it back.
000e1580: nop
nextSlot:
000e1584: subu r3,r3,r19 // temporarily convert loop counter to 0-based index
000e1588: addiu r3,r3,6 // advance to next item slot
000e158c: sltiu r2,r3,0x0780 // are we pointing past the 320th (0-based) slot?
000e1590: bne r2,r0,findLoop1 // loop and check next slot if not
000e1594: nop
findEmpty:
000e1598: ori r3,r0,0x0000 // start loop counter at item slot 0
findLoop2: // we found no matching contents, so next, look for
// our first empty slot.
000e159c: addu r3,r3,r19 // (position of current item * 6) + constant
000e15a0: lbu r2,0x0002(r3) // get quantity of item in current slot
000e15a4: nop
000e15a8: beq r2,r0,useCurInit // branch if zero, indicative of nothing there,
// which is our desired home at this point.
000e15ac: nop
000e15b0: subu r3,r3,r19 // temporarily convert loop counter to 0-based index
000e15b4: addiu r3,r3,6 // advance to next item slot
000e15b8: sltiu r2,r3,0x0780 // are we pointing past the 320th (0-based) slot?
000e15bc: bne r2,r0,findLoop2 // loop and check next slot if not
000e15c0: nop
000e15c4: beq r0,r0,noAddBack // all 3 methods couldn't find a suitable slot, so
// don't add back item anywhere.
000e15c8: nop
useCurInit:
000e15cc: lui r2,0x800f
000e15d0: lhu r2,0x314e(r2) // 0x800F314E -> Load ID of first item used.
000e15d4: nop
000e15d8: sh r2,0x0000(r3) // save Item ID in our chosen slot
useCurrent:
000e15dc: lbu r2,0x0002(r3) // get quantity of item in chosen slot
000e15e0: nop
000e15e4: addiu r2,r2,0x0001 // Add 1 to it
000e15e8: sb r2,0x0002(r3) // save new quantity
000e15ec: nop
000e15f0: sltiu r2,r2,0x0064 // is it less than 100?
000e15f4: bne r2,r0,keepVal // branch if so
000e15f8: ori r2,r0,0x0063 // Quantity limit (99)
000e15fc: sb r2,0x0002(r3) // save capped quantity
keepVal:
noAddBack:
The items can be used by the W-Item command are those that have an ID from 00 to 45 (In hexadecimal).
000df4dc: 1040000b beq r2,r0,0x000df50c
000df4e0: 00000000 nop ← This is where I relocate the code. The following code is similar to where it was originally. It seems that the Square programmer was wrong to place it.
to be sure: only one at a time, or is the targeting cursor unmovable? also, i assume these values are in hex? (they almost always are, but since i lack the game to test, i ask some normally silly questions.)You can move the cursor to select only one of the three allies.
1) r1 looks like it'll be safe to use. both for reading data to put in the fourth and fifth bytes of the item list, and as a general temporary register. however, i'd like to see whether and how 0x000bb9b8 uses the register, to be sure.
000bb9b8: 27bdffe8 addiu r29,r29,0xffe8
000bb9bc: 3c02800f lui r2,0x800f
000bb9c0: 24424ad0 addiu r2,r2,0x4ad0
000bb9c4: 34030030 ori r3,r0,0x0030
000bb9c8: 3084ffff andi r4,r4,0xffff
000bb9cc: afbf0010 sw r31,0x0010(r29)
000bb9d0: a4430000 sh r3,0x0000(r2)
000bb9d4: 3c01800f lui r1,0x800f
000bb9d8: ac244ad4 sw r4,0x4ad4(r1)
000bb9dc: 3c01800f lui r1,0x800f
000bb9e0: ac244ad8 sw r4,0x4ad8(r1)
000bb9e4: 0c00b7e2 jal 0x0002df88
000bb9e8: 00402021 addu r4,r2,r0
000bb9ec: 8fbf0010 lw r31,0x0010(r29)
000bb9f0: 27bd0018 addiu r29,r29,0x0018
000bb9f4: 03e00008 jr r31
2) what branches to or calls 000e14a0 or 000e14a4? it doesn't matter much with your fix going elsewhere, but it's got me curious how that code is reached.
000e11e4: 30620020 andi r2,r3,0x0020 "Circle button"
000e11e8: 104000ad beq r2,r0,0x000e14a0
000e11ec: 30620040 andi r2,r3,0x0040 "X button"
3)what are you putting in the NOP slot? are you aware of CPU pipelining, and that the instruction after 000df4dc will get run even when that branch is taken? also, from what i've read, having jumps/branches in that "branch delay slot" (i.e. where the NOP originally is) is a no-no, that produces unpredictable or nonsensical behavior.I put the jump to the new code in 000df4e4.