Bunny Pocket

Freedom of the press

Here's the exact code of the HandleYItem routine, with comments to understand it.

LDA $3C
Check B button
BEQ no_b_button
B button not held
CMP #$09
How long has B been held?
BCC exit_b
<9 frames; so exit; leads to an RTS
no_b_button
LDA $02E0
Check bunny status
BEQ not_bunny
0=not bunny graphics
LDA $0303
Which Y-item is equipped?
CMP #$0B
Is it a bottle?
BEQ not_bunny
We can use it
CMP #$14
Is it the mirror?
BEQ not_bunny
We can use it
RTS
Exit; we can't use an item
not_bunny
LDY $03FC
Do we have a forced item override?
BEQ no_forced_item
No override
LDA $02E0
Check bunny graphics
BNE no_forced_item
Bunny can't use overrides
CPY #$02
Is the override for bow?
BEQ forced_bow
If bow, use bow
BRL $A31C
Otherwise, go to shovel routine
forced_bow
BRL $9FF6
Go to bow routine
no_forced_item
LDY $0304
Check our actively used item
CPY $0303
Compare it to our equipped item
BEQ items_match
It's the same, so move on
LDA $0304
Why use A? Y has this value
CMP #$08
Are we using the shovel/flute?
BNE check_cape
If not, just carry on
LDA $7EF34C
Check what flute slot item we have
AND #$02
Look a bit 1, is it 0?
BEQ check_cape
In theory, that means shovel
LDA $3A
Check B/Y presses
AND #$BF
This clears the Y button flag
STA $3A
I would have used TRB myself
check_cape
LDA $0304
Again, why are we using A?
CMP #$13
Are we using cape?
BNE items_match
If not, skip ahead
LDA $55
Check the cape flag
BEQ items_match
If it's 0, do nothing
JSR $AE30
This subroutine adds the poof
items_match
LDA $0301
Check the held item bitfield
ORA $037A
Add in its complement
BNE check_rods
We're using an item; skip ahead
LDY $0303
If we're not using an item then
STY $0304
Make our held and active item match
check_rods
BEQ $9B81
Seems to handle no items
CPY #$05
Are we using fire rod?
BEQ using_rod
We are!!!
CPY #$06
What about ice rod?
BNE handle_item
We're not :(
using_rod
LDA $0304
Setting up a flag for which rod
SEC
Where 1=fire; 2=ice
SBC #$05
This should have been SBC #$04
INC A
And this should not have been
STA $0307
Save the flag
handle_item
DEY
Prep for a jump table
BMI exit
If Y was 0, just exit
TYA
Standard stuff to double
ASL A
Since we're indexing a table of words
TAX
Okay here we gooooo
JMP ($9AD6, X)
JUMP!
exit
RTS
Leave

We have a few particular values of interest here to explain our item storage:

When either of the bitfields has anything flagged, it skips code that syncs our equipped and used items. When we use a Y-item, the value of the Y register (heh) is what's used to create the index into the jump table. Within this routine, there are 3 places where Y.

The first instance is at $079B17, where it is used to check whether or not we have an item override, such as the shovel during the digging game. If we do have an override (or if we're a bunny), then the remainder of the routine is skipped, and the item's routine is executed immediately.

The next instance is at $079B2B, where Y loads $0304, our currently used item, and compares it to $0303, our currently equipped item.

The last instance is at $079B5E, where Y is used to sync the used and active items, by loading $0303 and writing it to $0304. This only occurs when both of the bitfields are unflagged; this condition is important to keep in mind as we delve further.

Take note that none of this code actually checks for a press of the Y button. That check is, for whatever reason, left to the individual items' routines. We'll be taking a look at one of those next, to find more clues about what causes this glitch.

Hammer time

Nah. That's such a cliché. Okay. Stab me in the eye, and I'll stab you back.

Hammerabi's code

That's so bad it'll work!

For our example, we'll be looking into the hammer. But to cover all bases and keep the investigation smooth, let's start by looking at what constitutes a Y press.

This is the TestYButton routine, disassembled from the JP1.0 ROM:

TestYButton:
BIT $3A
Check for Y press in bit 6 of $3A
BVS fail
Overflow flag is set as bit 6
LDA $46
Check for recoil
BNE fail
Ignore input when recoiling
LDA $F4
Read player 1 joypad input
AND #$40
Get bit 6 for Y
BEQ fail
No bit means no press
TSB $3A
Set bit 6 here
SEC
Set carry flag to indicate success
RTS
fail
CLC
Clear carry to indicate failure
RTS

And with that, here's the routine for using the hammer:

hammer_data
db 3
Just some data used by the routine
db 3
db 16
LinkItem_Hammer
LDA $0301
Check used item bitfield
AND #$10
This checks for the bow, but why?
BNE exit_a
Exit if using bow
BIT $3A
Check for Y press
BVS y_was
If we had pressed Y, continue on
LDA $6C
Are we in a door?
BNE exit_a
If so, no hammer
JSR $B064
Middle of TestYButton
BCS init_hammer
We pressed Y, so continue
exit_a
BRL $9F48
This coulda just been RTS itself
init_hammer
LDA $9F68
First byte of hammer_data ($03)
STA $3D
Save that as first animation step length
LDA #$01
Set bit 0 of $50
TSB $50
Which indicates Link cannot turn
STZ $2E
Reset animation step counter (not used for hammer)
LDA $0301
What a waste of cycles
AND #$00
This zeros the loaded value
ORA #$02
And this could have just been LDA #$02
STA $0301
But it does set the hammer flag in this field
STZ $0300
At least they got this right (clear animation step)
y_was
JSR $AE4E
This routine handles tile interaction for attacks
LDA $67
This takes the "direction moving" bitfield
AND #$F0
And clears the bottom 4 bytes
STA $67
I don't think the top nibble is used at all though…
DEC $3D
Decrement the animation step counter
BPL exit_b
If the animation is still running, stop
LDA $0300
More bad code
INC A
Could have just done INC $0300
STA $0300
And then
TAX
LDX $0300
LDA $9F68, X
Use animation step for next duration
STA $3D
And then save it here
CPX #$01
Are we on the second animation step?
BNE skip_stars
PHX
Save the step
LDY #$03
Hammer ID for tile interaction
JSR $D060
Perform some tile interaction
LDY #$00
0 means 1 star is allowed to exist
LDA #$16
Ancilla ID of the stars
JSL $098024
Creates the ancillae, including sound effects
PLX
Recover the step
LDA $012E
See if a sound effect is playing
BNE skip_stars
If one already is, skip
LDA #$10
Load SFX 16
JSR $8028
Queue it up for SFX set 2
JSL $1AFF3C
Adds a water splash, if necessary
skip_stars
CPX #$03
Are we on step 3?
BNE exit_b
Nope, so just leave
STZ $0300
Step 3 is actually too far
STZ $3D
So the rest of this code is just clean up
LDA $3A
AND #$BF
STA $3A
LDA $50
AND #$FE
STA $50
LDA $0301
AND #$FD
STA $0301
exit_b
RTS

Connect the dots

So now that we have every piece of information we need, let's piece this together step by step. Imagine we want to arm our pockets with the hammer. Once outside, as a bunny, we switch to the mirror and press Y. Here's how that plays out:

    First, the arming:
    Now the item usage:
  1. We're not using the B-button, so that doesn't matter.
  2. We are a bunny, so we need to check what item we have equipped at $0303.
  3. Since we have the mirror equipped, we pass, and can continue.
  4. Now our item override is checked.
  5. It's nothing, so we continue on.
  6. Check our active item at $0304. It's $04 for the hammer.
  7. Compare that to our equipped item at $0303. That value is currently $14, for the mirror
  8. These do not match, so we need to perform a couple additional checks.
  9. Our active item is not the flute ($08), so we can skip that section.
  10. Nor is it the cape ($13), so we can skip that too.
  11. We look at both bitfields. We'll find that $0301 has a value of $02, the bit for the hammer, while $037A has a value of $00.
  12. Logically ORing these two together gives us $02, a nonzero value, so we skip ahead to the next set of checks.
  13. We're not using either rod, so both of those checks fail.
  14. Our final item index we have in Y is $04, which we read from our actively used item.
  15. After converting this value into a table index, we end up executing the hammer routine.