Files
oracle-of-secrets/Menu/menu_hud.asm
2022-10-03 04:15:21 -05:00

707 lines
15 KiB
NASM

; =============================================================================
; headsup display
org $0DFB91
JSL HUD_Update
RTS
newIgnoreItemBox:
JSL HUD_Update_ignoreItemBox
RTS
org $0DDD21
JSR newIgnoreItemBox
org $0DF1BC
JSL HUD_AnimateHeartRefill
RTS
org $268000
HUD_Update:
{
JSR HUD_UpdateItemBox
.ignoreItemBox ; ALTERNATE ENTRY POINT
SEP #$30
; need to draw partial heart still though.
LDA.b #$FD : STA $0A
LDA.b #$F9 : STA $0B
LDA.b #$0D : STA $0C
LDA.b #$44 : STA $07
LDA.b #$C7 : STA $08
LDA.b #$7E : STA $09
REP #$30
; Load Capacity health.
LDA $7EF36C : AND.w #$00FF : STA $00 : STA $02 : STA $04
; First, just draw all the empty hearts (capacity health)
JSR HUD_UpdateHearts
SEP #$30
LDA.b #$03 : STA $0A
LDA.b #$FA : STA $0B
LDA.b #$0D : STA $0C
LDA.b #$44 : STA $07
LDA.b #$C7 : STA $08
LDA.b #$7E : STA $09
; Branch if at full health
LDA $7EF36C : CMP $7EF36D : BEQ .healthUpdated
; Seems absurd to have a branch of zero bytes, right?
SEC : SBC #$04 : CMP $7EF36D : BCS .healthUpdated
.healthUpdated
; A = actual health + 0x03;
LDA $7EF36D : SEC : SBC #$03
REP #$30
AND.w #$00FC : STA $00 : STA $04
LDA $7EF36C : AND.w #$00FF : STA $02
; filling in the full and partially filled hearts (actual health)
JSR HUD_UpdateHearts
.ignoreHealth ; *$6FC09 ALTERNATE ENTRY POINT ; reentry hook
REP #$30
; Magic amount indicator (normal, 1/2, or 1/4)
LDA $7EF37B : AND.w #$00FF : CMP.w #$0001 : BCC .normalMagicMeter
; draw 1/2 magic meter
LDA.w #$2851 : STA $7EC730
LDA.w #$28FA : STA $7EC732
.normalMagicMeter
; check player magic (ranges from 0 to 0x7F)
; X = ((MP & 0xFF)) + 7) & 0xFFF8)
; LDA $7EF36E : AND.w #$00FF : CLC : ADC #$0007 : AND.w #$FFF8 : TAX
; these four writes draw the magic power bar based on how much MP you have
; LDA MagicTilemap+0, X : STA $7EC746
; LDA MagicTilemap+2, X : STA $7EC786
; LDA MagicTilemap+4, X : STA $7EC7C6
; LDA MagicTilemap+6, X : STA $7EC806
; Load how many rupees the player has
LDA $7EF362
JSR HexToDecimal
REP #$30
; The tile index for the first rupee digit
LDA $03 : AND.w #$00FF : ORA.w #$2400 : STA $7EC79C
; The tile index for the second rupee digit
LDA $04 : AND.w #$00FF : ORA.w #$2400 : STA $7EC79E
; The tile index for the third rupee digit
LDA $05 : AND.w #$00FF : ORA.w #$2400 : STA $7EC7A0
; Number of bombs Link has.
LDA $7EF343 : AND.w #$00FF
JSR HexToDecimal
REP #$30
; The tile index for the first bomb digit
LDA $04 : AND.w #$00FF : ORA.w #$2400 : STA $7EC7B0
; The tile index for the second bomb digit
LDA $05 : AND.w #$00FF : ORA.w #$2400 : STA $7EC7B2
; ; Number of Arrows Link has.
; LDA $7EF377 : AND.w #$00FF
; ; converts hex to up to 3 decimal digits
; JSR HexToDecimal
; REP #$30
; ; The tile index for the first arrow digit
; LDA $04 : AND.w #$00FF : ORA.w #$2400 : STA $7EC75E
; ; The tile index for the second arrow digit
; LDA $05 : AND.w #$00FF : ORA.w #$2400 : STA $7EC760
; LDA.w #$007F : STA $05
; ; Load number of Keys Link has
; LDA $7EF36F : AND.w #$00FF : CMP.w #$00FF : BEQ .noKeys
; JSR HexToDecimal
; .noKeys
; REP #$30
; ; The key digit, which is optionally drawn.
; ; Also check to see if the key spot is blank
; LDA $05 : AND.w #$00FF : ORA.w #$2400 : STA $7EC764
; CMP.w #$247F : BNE .dontBlankKeyIcon
; ; If the key digit is blank, also blank out the key icon.
; STA $7EC724
; .dontBlankKeyIcon
; SEP #$30
RTL
}
; =============================================================================
; *$6DB92-$6DD29 BRANCH LOCATION
HUD_RefillLogic:
{
; Check current rupees (362) against goal rupees (360)
; goal refers to how many we really have and current refers to the
; number currently being displayed. When you buy something,
; goal rupees are decreased by, say, 100, but it takes a while for the
; current rupees indicator to catch up. When you get a gift of 300
; rupees, the goal increases, and current has to catch up in the other direction.
LDA $7EF362
CMP $7EF360 : BEQ .doneWithRupeesRefill
BMI .addRupees
DEC A : BPL .subtractRupees
LDA.w #$0000 : STA $7EF360
BRA .subtractRupees
.addRupees
; If current rupees <= 1000 (decimal)
INC A : CMP.w #1000 : BCC .subtractRupees
; Otherwise just store 999 to the rupee amount
LDA.w #999 : STA $7EF360
.subtractRupees
STA $7EF362
SEP #$30
LDA $012E : BNE .doneWithRupeesRefill
; looks like a delay counter of some sort between
; invocations of the rupee fill sound effect
LDA $0CFD : INC $0CFD : AND.b #$07 : BNE .skipRupeeSound
LDA.b #$29 : STA $012E
BRA .skipRupeeSound
.doneWithRupeesRefill
SEP #$30
STZ $0CFD
.skipRupeeSound
LDA $7EF375
BEQ .doneRefillingBombs
; decrease the bomb refill counter
LDA $7EF375 : DEC A : STA $7EF375
; use the bomb upgrade index to know what max number of bombs Link can carry is
LDA $7EF370 : TAY
; if it matches the max, you can't have no more bombs, son. It's the law.
LDA $7EF343 : CMP $DB48, Y : BEQ .doneRefillingBombs
; You like bombs? I got lotsa bombs!
INC A : STA $7EF343
.doneRefillingBombs
; check arrow refill counter
LDA $7EF376
BEQ .doneRefillingArrows
LDA $7EF376 : DEC A : STA $7EF376
; check arrow upgrade index to see how our max limit on arrows, just like bombs.
LDA $7EF371 : TAY
LDA $7EF377 : CMP $DB58, Y
; I reckon you get no more arrows, pardner.
BEQ .arrowsAtMax
INC A : STA $7EF377
.arrowsAtMax
; see if we even have the bow.
LDA $7EF340
BEQ .doneRefillingArrows
AND.b #$01 : CMP.b #$01
BNE .doneRefillingArrows
; changes the icon from a bow without arrows to a bow with arrows.
LDA $7EF340 : INC A : STA $7EF340
JSL $0DDB7F
.doneRefillingArrows
; a frozen Link is an impervious Link, so don't beep.
LDA $02E4
BNE .doneWithWarningBeep
; if heart refill is in process, we don't beep
LDA $7EF372
BNE .doneWithWarningBeep
LDA $7EF36C : LSR #3 : TAX
; checking current health against capacity health to see
; if we need to put on that annoying beeping noise.
LDA $7EF36D : CMP $DB60, X
BCS .doneWithWarningBeep
LDA $04CA
BNE .decrementBeepTimer
; beep incessantly when life is low
LDA $012E
BNE .doneWithWarningBeep
LDA.b #$20 : STA $04CA
LDA.b #$2B : STA $012E
.decrementBeepTimer
; Timer for the low life beep sound
DEC $04CA
.doneWithWarningBeep
; if nonzero, indicates that a heart is being "flipped" over
; as in, filling up, currently
LDA $020A
BNE .waitForHeartFillAnimation
; If no hearts need to be filled, branch
LDA $7EF372
BEQ .doneRefillingHearts
; check if actual health matches capacity health
LDA $7EF36D : CMP $7EF36C
BCC .notAtFullHealth
; just set health to full in the event it overflowed past 0xA0 (20 hearts)
LDA $7EF36C : STA $7EF36D
; done refilling health so deactivate the health refill variable
LDA.b #$00 : STA $7EF372
BRA .doneRefillingHearts
.notAtFullHealth
; refill health by one heart
LDA $7EF36D : CLC : ADC.b #$08 : STA $7EF36D
LDA $012F
BNE .soundChannelInUse
; play heart refill sound effect
LDA.b #$0D : STA $012F
.soundChannelInUse
; repeat the same logic from earlier, checking if health's at max and setting it to max
; if it overflowed
LDA $7EF36D : CMP $7EF36C
BCC .healthDidntOverflow
LDA $7EF36C : STA $7EF36D
.healthDidntOverflow
; subtract a heart from the refill variable
LDA $7EF372 : SEC : SBC.b #$08 : STA $7EF372
; activate heart refill animation
; (which will cause a small delay for the next heart if we still need to fill some up.)
INC $020A
LDA.b #$07 : STA $0208
.waitForHeartFillAnimation
REP #$30
LDA.w #$FFFF : STA $0E
JSL HUD_Update_ignoreHealth
JSL HUD_AnimateHeartRefill
SEP #$30
INC $16
PLB
RTL
.doneRefillingHearts
REP #$30
LDA.w #$FFFF : STA $0E
JSL HUD_Update_ignoreItemBox
SEP #$30
INC $16
PLB
RTL
}
; =============================================================================
; *$6F14F-$6F1B2 LOCAL
HUD_AnimateHeartRefill:
{
SEP #$30
; $00[3] = $7EC768 (wram address of first row of hearts in tilemap buffer)
LDA.b #$44 : STA $00
LDA.b #$C7 : STA $01
LDA.b #$7E : STA $02
DEC $0208 : BNE .return
REP #$30
; Y = ( ( ( (current_health & 0x00F8) - 1) / 8 ) * 2)
LDA $7EF36D : AND.w #$00F8 : DEC A : LSR #3 : ASL A : TAY : CMP.w #$0014
BCC .halfHealthOrLess
SBC.w #$0014 : TAY
; $00[3] = $7EC7A8 (wram address of second row of hearts)
LDA $00 : CLC : ADC.w #$0040 : STA $00
.halfHealthOrLess
SEP #$30
LDX $0209 : LDA $0DFA11, X : STA $0208
TXA : ASL A : TAX
LDA $0DFA09, X : STA [$00], Y
INY : LDA $0DFA0A, X : STA [$00], Y
LDA $0209 : INC A : AND.b #$03 : STA $0209
BNE .return
SEP #$30
JSL $0DFA70
STZ $020A
.return
CLC
RTS
}
; ============================================================================
; *$6FAFD-$6FB90 LOCAL
HUD_UpdateItemBox:
{
SEP #$30
; Dost thou haveth the the bow?
LDA $7EF340 : BEQ .havethNoBow
; Dost thou haveth the silver arrows?
; (okay I'll stop soon)
; CMP.b #$03 : BCC .havethNoSilverArrows
; Draw the arrow guage icon as silver rather than normal wood arrows.
; LDA.b #$86 : STA $7EC71E
; LDA.b #$24 : STA $7EC71F
; LDA.b #$87 : STA $7EC720
; LDA.b #$24 : STA $7EC721
LDX.b #$04
; check how many arrows the player has
LDA $7EF377 : BNE .drawBowItemIcon
LDX.b #$03
BRA .drawBowItemIcon
; .havethNoSilverArrows
; LDX.b #$02
; LDA $7EF377 : BNE .drawBowItemIcon
; LDX.b #$01
.drawBowItemIcon
; values of X correspond to how the icon will end up drawn:
; 0x01 - normal bow with no arrows
; 0x02 - normal bow with arrows
; 0x03 - silver bow with no silver arrows
; 0x04 - silver bow with silver arrows
TXA : STA $7EF340
.havethNoBow
REP #$30
LDX $0202 : BEQ .noEquippedItem
LDA $7EF33F, X : AND.w #$00FF
CPX.w #$0004 : BNE .bombsNotEquipped
LDA.w #$0001
.bombsNotEquipped
CPX.w #$0010 : BNE .bottleNotEquipped
TXY : TAX : LDA $7EF35B, X : AND.w #$00FF : TYX
.bottleNotEquipped
STA $02
TXA : DEC A : ASL A : TAX
LDA $FA93, X : STA $04
LDA $02 : ASL #3 : TAY
; These addresses form the item box graphics.
LDA ($04), Y : STA $7EC776 : INY #2
LDA ($04), Y : STA $7EC778 : INY #2
LDA ($04), Y : STA $7EC7B6 : INY #2
LDA ($04), Y : STA $7EC7B8 : INY #2
.noEquippedItem
RTS
}
; =============================================================================
HUD_UpdateHearts:
{
; Draws hearts in a painfully slow loop
; I used DMA to speed it up in my custom code
; (but still needs fixing to work on 1/1/1 hardware)
LDX.w #$0000
.nextHeart
LDA $00 : CMP.w #$0008 : BCC .lessThanOneHeart
; Notice no SEC was needed since carry is assumedly set.
SBC.w #$0008 : STA $00
LDY.w #$0004
JSR .drawHeart
INX #2
BRA .nextHeart
.lessThanOneHeart
CMP.w #$0005 : BCC .halfHeartOrLess
LDY.w #$0004
BRA .drawHeart
.halfHeartOrLess
CMP.w #$0001 : BCC .emptyHeart
LDY.w #$0002
BRA .drawHeart
.emptyHeart
RTS
.drawHeart
; Compare number of hearts so far on current line to 10
CPX.w #$0014 : BCC .noLineChange
; if not, we have to move down one tile in the tilemap
LDX.w #$0000
LDA $07 : CLC : ADC #$0040 : STA $07
.noLineChange
LDA [$0A], Y : TXY : STA [$07], Y
RTS
}
; =============================================================================
MagicTilemap:
dw $3CF5, $3CF5, $3CF5, $3CF5
dw $3CF5, $3CF5, $3CF5, $3C5F
dw $3CF5, $3CF5, $3CF5, $3C4C
dw $3CF5, $3CF5, $3CF5, $3C4D
dw $3CF5, $3CF5, $3CF5, $3C4E
dw $3CF5, $3CF5, $3C5F, $3C5E
dw $3CF5, $3CF5, $3C4C, $3C5E
dw $3CF5, $3CF5, $3C4D, $3C5E
dw $3CF5, $3CF5, $3C4E, $3C5E
dw $3CF5, $3C5F, $3C5E, $3C5E
dw $3CF5, $3C4C, $3C5E, $3C5E
dw $3CF5, $3C4D, $3C5E, $3C5E
dw $3CF5, $3C4E, $3C5E, $3C5E
dw $3C5F, $3C5E, $3C5E, $3C5E
dw $3C4C, $3C5E, $3C5E, $3C5E
dw $3C4D, $3C5E, $3C5E, $3C5E
dw $3C4E, $3C5E, $3C5E, $3C5E
; =============================================================================
HexToDecimal:
{
REP #$30
STZ $0003
LDX.w #$0000
LDY.w #$0002
.nextDigit
CMP $F9F9, Y : BCC .nextLowest10sPlace
SEC : SBC $F9F9, Y
INC $03, X
BRA .nextDigit
.nextLowest10sPlace
INX : DEY #2
BPL .nextDigit
STA $05
SEP #$30
LDX.b #$02
.setNextDigitTile
LDA $03, X : CMP.b #$7F
BEQ .blankDigit
ORA.b #$90
.blankDigit
STA $03, X
DEX : BPL .setNextDigitTile
RTS
}
; =============================================================================
; $6FE77-$6FFC0
org $0DFE77
HUD_Tilemap:
{
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F
; magic bar top part
dw $200B, $200C, $200C, $200C, $200C, $200C
; item frame top part
dw $206C, $206D, $206E, $206F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F
; magic bar
dw $201B, $344B
dw $344B, $344B, $344B, $344B
; item frame left part
dw $20DE, $207F, $207F, $20DF
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F
; magic bar bottom part
dw $A00B, $A00C
dw $A00C, $A00C, $A00C, $A00C
; item frame right part
dw $20EE, $207F, $207F, $20EF
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F
; item frame bottom part
dw $207C, $207D, $207E, $201D
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F, $207F, $207F, $207F, $207F, $207F, $207F, $207F
dw $207F
}