; ============================================================================= ; 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 }