; ============================================================================= ; 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 HudItems: dw BowsGFX dw BoomsGFX dw HookGFX dw BombsGFX dw DekuMaskGFX dw BottlesGFX dw Fire_rodGFX dw Ice_rodGFX dw LampGFX dw HammerGFX dw GoronMaskGFX dw BottlesGFX dw SomariaGFX dw ByrnaGFX dw BookGFX dw JumpFeatherGFX dw BunnyHoodGFX dw BottlesGFX dw OcarinaGFX dw MirrorGFX dw ShovelGFX dw PowderGFX dw StoneMaskGFX dw BottlesGFX HUD_UpdateItemBox: { SEP #$30 ; Dost thou haveth the the bow? LDA $7EF340 : BEQ .havethNoBow LDX.b #$04 ; check how many arrows the player has LDA $7EF377 : BNE .drawBowItemIcon LDX.b #$03 BRA .drawBowItemIcon .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 Menu_ItemIndex, 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 }