From e86cccad52047fe75ed9b219e350cb304b58c604 Mon Sep 17 00:00:00 2001 From: aerinon Date: Mon, 28 Apr 2025 14:15:31 -0600 Subject: [PATCH 1/5] fix: fix conveyor bug, unless Helmasaur is present --- enemizer/bosses_moved.asm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/enemizer/bosses_moved.asm b/enemizer/bosses_moved.asm index 4ccf041..c5f518c 100644 --- a/enemizer/bosses_moved.asm +++ b/enemizer/bosses_moved.asm @@ -23,12 +23,13 @@ boss_move: + CMP.b #41 : BNE + ; Is it Skull Woods Boss Room - ; TODO: Add moving floor sprite JSL Sprite_ResetAll ; reset sprites twice in that room for some reasons (fix bug with kholdstare) JSL Dungeon_ResetSprites ; Restore the dungeon_resetsprites - LDA.b #$07 : STA.w $0B00 ;Spawn the moving floor sprite - STZ.w $0B28 - INC.w OverlordXLow + LDA.w $0E20 : CMP.b #$92 : BNE ++ ; Is it Helmasuar King? + LDA.b #$07 : STA.w $0B00 ;Spawn the bugged moving floor sprite + STZ.w $0B28 + INC.w OverlordXLow + ++ BRL .move_to_bottom_right + From aabb649578e186aa54825fd4b90acec69baa140d Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 30 Apr 2025 06:18:08 -0500 Subject: [PATCH 2/5] Initial Follower Shuffle Implementation --- LTTP_RND_GeneralBugfixes.asm | 1 + bugfixes.asm | 14 +- darkworldspawn.asm | 16 +- decompresseditemgraphics.asm | 66 ++- doorrando/dr_lobby.asm | 1 + doorrando/overrides.asm | 12 +- dungeondrops.asm | 1 + enemizer/main.asm | 3 - entrances.asm | 4 +- events.asm | 2 +- follower.asm | 888 +++++++++++++++++++++++++++++++++++ framehook.asm | 2 +- hooks.asm | 45 +- initsramtable.asm | 4 +- keydrop/dynamic_si_vram.asm | 2 +- ram.asm | 2 + sram.asm | 8 +- tables.asm | 56 ++- utilities.asm | 2 +- vanillalabels.asm | 6 + zelda.asm | 9 - 21 files changed, 1054 insertions(+), 90 deletions(-) create mode 100644 follower.asm diff --git a/LTTP_RND_GeneralBugfixes.asm b/LTTP_RND_GeneralBugfixes.asm index 5b1ebf0..b60d6b0 100644 --- a/LTTP_RND_GeneralBugfixes.asm +++ b/LTTP_RND_GeneralBugfixes.asm @@ -118,6 +118,7 @@ incsrc doorframefixes.asm incsrc music.asm incsrc roomloading.asm incsrc icepalacegraphics.asm +incsrc follower.asm warnpc $A18000 org $9C8000 ; text tables for translation diff --git a/bugfixes.asm b/bugfixes.asm index fca00aa..fb2dc40 100644 --- a/bugfixes.asm +++ b/bugfixes.asm @@ -1,12 +1,5 @@ ;================================================================================ -;-------------------------------------------------------------------------------- -AssignKiki: - LDA.b #$00 : STA.l FollowerDropped ; defuse bomb - LDA.b #$0A : STA.l FollowerIndicator ; assign kiki as follower -RTL -;-------------------------------------------------------------------------------- - ;-------------------------------------------------------------------------------- ; Name: AllowSQ ; Returns: Accumulator = 0 if S&Q is disallowed, 1 if allowed @@ -187,6 +180,11 @@ LDA.b IndoorsFlag : BNE + + RTL +PostFixOAMGfx: + JSL FollowerGfxRedraw + REP #$30 : LDA.w #$2000 ; what we wrote over + RTL + ;-------------------------------------------------------------------------------- ; Fix losing VRAM gfx when using quake PostNMIUpdateBGCharHalf: @@ -259,7 +257,7 @@ ParadoxCaveGfxFix: LDA.b #$01 : STA.w DMAENABLE .skipLine - RTL + JML FollowerGfxRedraw .skipMostOfLine ; Set line length to 192 bytes (the first 6 8x8 tiles in the line) diff --git a/darkworldspawn.asm b/darkworldspawn.asm index 806cb0c..dca2cc8 100644 --- a/darkworldspawn.asm +++ b/darkworldspawn.asm @@ -12,6 +12,7 @@ DoWorldFix: + LDA.l Bugfix_MirrorlessSQToLW : BEQ .skip_mirror_check LDA.l FollowerIndicator : CMP.b #$04 : BNE + ; if old man following, skip mirror/aga check + LDA.l FollowerTravelAllowed : CMP.b #$02 : BEQ + LDA.l OldManRetrievalWorld BRA .noMirror + LDA.l MirrorEquipment : AND.b #$02 : BEQ .noMirror ; check if we have the mirror @@ -60,6 +61,7 @@ RTL DoWorldFix_Inverted: LDA.l Bugfix_MirrorlessSQToLW : BEQ .skip_mirror_check LDA.l FollowerIndicator : CMP.b #$04 : BNE + ; if old man following, skip mirror/aga check + LDA.l FollowerTravelAllowed : CMP.b #$02 : BEQ + LDA.l OldManRetrievalWorld BRA .setWorld + LDA.l MirrorEquipment : AND.b #$02 : BEQ .noMirror ; check if we have the mirror @@ -115,12 +117,12 @@ FakeWorldFix: RTL ;-------------------------------------------------------------------------------- GetCurrentWorldForLoad: -LDA FollowerIndicator : CMP #$04 : BNE .default - LDA InvertedMode : BEQ + - LDA #$40 - + RTL +LDA.l FollowerTravelAllowed : CMP.b #$02 : BEQ .default +LDA.l FollowerIndicator : CMP.b #$04 : BNE .default + LDA.l OldManRetrievalWorld + RTL .default -LDA CurrentWorld +LDA.l CurrentWorld RTL ;-------------------------------------------------------------------------------- MasterSwordFollowerClear: @@ -131,7 +133,9 @@ MasterSwordFollowerClear: RTL ;-------------------------------------------------------------------------------- FixAgahnimFollowers: - LDA.b #$00 : STA.l FollowerIndicator ; clear follower + LDA.l FollowerTravelAllowed : CMP.b #$02 : BEQ + + LDA.b #$00 : STA.l FollowerIndicator ; clear follower + + JML PrepDungeonExit ; thing we wrote over ;-------------------------------------------------------------------------------- diff --git a/decompresseditemgraphics.asm b/decompresseditemgraphics.asm index 53ef9c8..0a101b3 100644 --- a/decompresseditemgraphics.asm +++ b/decompresseditemgraphics.asm @@ -202,6 +202,8 @@ DecompressAllItemGraphics: LDX.b #$5C+$73 : JSR AddGfxSheetToBigBuffer LDX.b #$5B+$73 : JSR AddGfxSheetToBigBuffer LDX.b #$5A+$73 : JSR AddGfxSheetToBigBuffer + JSR AddCherryPickGfxToBigBuffer + LDX.b #$01 : STX.w $06FA LDX.b #$06+$73 : JSR AddGfxSheetToBigBuffer LDX.b #$07+$73 : JSR AddGfxSheetToBigBuffer @@ -497,6 +499,11 @@ macro DoPlanesA(offset) XBA ORA.b Decomp3BPPScratch + PHY + LDY.w $06FA : BEQ + + AND.w #$00FF ; idk why this line works but some sheets we pull in aren't correct without it + + + PLY STA.w BigDecompressionBuffer+$10++,X endmacro @@ -520,7 +527,11 @@ macro DoIndirectPlanesA(offset) XBA ORA.b Decomp3BPPScratch - AND.w #$00FF ; idk why this line works but the 2 sheets we pull in aren't correct without it + PHY + LDY.w $06FA : BEQ + + AND.w #$00FF ; idk why this line works but some sheets we pull in aren't correct without it + + + PLY STA.l BigDecompressionBuffer+$10++,X endmacro @@ -612,4 +623,57 @@ Unrolled3BPPConvert: ;=================================================================================================== +macro CherryPickGfx(source,dest,length) + LDX.w #BigDecompressionBuffer+ + LDY.w #BigDecompressionBuffer+ + LDA.w #-1 + MVN BigDecompressionBuffer>>16,BigDecompressionBuffer>>16 + + LDX.w #BigDecompressionBuffer++$200 + LDY.w #BigDecompressionBuffer++$200 + LDA.w #-1 + MVN BigDecompressionBuffer>>16,BigDecompressionBuffer>>16 +endmacro + +;=================================================================================================== + +AddCherryPickGfxToBigBuffer: + ; this is mostly to load and rearrange follower gfx to save on space + ; assumes DecompBufferOffset left off at $A000 (#BigDecompressionBuffer+$2000) + ; adjustments will be needed if anything prior to this changes + LDX.b #$01 : STX.w $06FA + LDX.b #$35+$73 : JSR AddGfxSheetToBigBuffer + LDX.b #$55+$73 : JSR AddGfxSheetToBigBuffer + REP #$30 + %CherryPickGfx($2400,$2140,$40) ; move old man head + %CherryPickGfx($2D40,$20C0,$40) ; move zelda body + LDA.b DecompBufferOffset : SEC : SBC.w #$0C00 : STA.b DecompBufferOffset + SEP #$30 + LDX.b #$11+$73 : JSR AddGfxSheetToBigBuffer + LDX.b #$15+$73 : JSR AddGfxSheetToBigBuffer + REP #$30 + %CherryPickGfx($2940,$2180,$80) ; move locksmith head/body + %CherryPickGfx($2D00,$0440,$40) ; move frog + %CherryPickGfx($31C0,$0500,$40) ; move purple chest + LDA.b DecompBufferOffset : SEC : SBC.w #$1000 : STA.b DecompBufferOffset + SEP #$30 + LDX.b #$59+$73 : JSR AddGfxSheetToBigBuffer + LDX.b #$58+$73 : JSR AddGfxSheetToBigBuffer + REP #$30 + %CherryPickGfx($2880,$0480,$40) ; move kiki head + %CherryPickGfx($2900,$04C0,$40) ; move kiki body + %CherryPickGfx($30C0,$0540,$40) ; move big bomb + %CherryPickGfx($2C40,$0180,$40) ; move duck + LDA.b DecompBufferOffset : SEC : SBC.w #$1000 : STA.b DecompBufferOffset + SEP #$30 + LDX.b #$4D+$73 : JSR AddGfxSheetToBigBuffer + LDX.b #$50+$73 : JSR AddGfxSheetToBigBuffer + REP #$30 + %CherryPickGfx($2880,$0580,$40) ; move smith + %CherryPickGfx($3140,$0140,$40) ; move chicken + LDA.b DecompBufferOffset : SEC : SBC.w #$1000 : STA.b DecompBufferOffset + SEP #$30 + + STZ.w $06FA + RTS diff --git a/doorrando/dr_lobby.asm b/doorrando/dr_lobby.asm index 40a083c..3fc6c05 100644 --- a/doorrando/dr_lobby.asm +++ b/doorrando/dr_lobby.asm @@ -13,6 +13,7 @@ PHP SetDefaultWorld: PHP : SEP #$20 +LDA.l FollowerTravelAllowed : CMP.b #$02 : BEQ .default LDA.l FollowerIndicator : CMP.b #$04 : BNE .default LDA.l OldManRetrievalWorld : BRA + .default diff --git a/doorrando/overrides.asm b/doorrando/overrides.asm index 7656ba1..354e119 100644 --- a/doorrando/overrides.asm +++ b/doorrando/overrides.asm @@ -11,6 +11,7 @@ rtl OnFileLoadOverride: jsl OnFileLoad ; what I wrote over + jsl StartingFollower + lda.l DRFlags : and.b #$02 : beq + ; Mirror Scroll lda.l MirrorEquipment : bne + lda.b #$01 : sta.l MirrorEquipment @@ -52,8 +53,9 @@ GuruguruFix: BlindAtticFix: lda.l DRMode : beq + - lda.b #$01 : rtl - + lda.l FollowerIndicator : cmp.b #$06 + - lda.b #$01 : rtl + + lda.l FollowerTravelAllowed : cmp.b #$02 : beq - + lda.l FollowerIndicator : cmp.b #$06 rtl SuctionOverworldFix: @@ -119,12 +121,6 @@ BlindsAtticHint: SEP #$20 : RTL ; skip the dialog box if the hole is already open + SEP #$20 : JML Main_ShowTextMessage -BlindZeldaDespawnFix: - CMP.b #06 : BEQ + - LDA.w SpritePosYLow,X : BEQ + ; don't despawn follower if maiden isn't "present" - PLA : PLA : PEA.w SpritePrep_BlindMaiden_despawn_follower-1 : RTL - + PLA : PLA : PEA.w SpritePrep_BlindMaiden_kill_the_girl-1 : RTL - BigKeyDoorCheck: CPY.w #$001E : BNE + ; skip if it isn't a BK door LDA.l DRFlags : AND.w #$0400 : BNE + ; skip if the flag is set - bk doors can be double-sided diff --git a/dungeondrops.asm b/dungeondrops.asm index 5a4d741..823a53d 100644 --- a/dungeondrops.asm +++ b/dungeondrops.asm @@ -453,6 +453,7 @@ RTL MaybeSkipCrystalCutsceneFollowerReset: PHA + LDA.l FollowerTravelAllowed : CMP.b #$02 : BEQ .skip ; skip if prizes are shuffled outside of normal boss drops LDA.l InventoryTable_properties+($37*2) : AND.b #$01 : BEQ .continue .skip diff --git a/enemizer/main.asm b/enemizer/main.asm index a90a649..6990fea 100644 --- a/enemizer/main.asm +++ b/enemizer/main.asm @@ -52,8 +52,5 @@ incsrc falling_death.asm incsrc shell_gfx.asm warnpc $B6FFFF ;if we hit this we need to split stuff by bank -org $8684BD -Sprite_Get16BitCoords_long: - org $9EC6FA ;F46FA SpritePrep_Eyegore: \ No newline at end of file diff --git a/entrances.asm b/entrances.asm index b38ccd8..841c5c9 100644 --- a/entrances.asm +++ b/entrances.asm @@ -63,8 +63,8 @@ RTS RTS ;-------------------------------------------------------------------------------- SmithDoorCheck: - LDA.l SmithTravelsFreely : AND.w #$00FF : BEQ .orig - ;If SmithTravelsFreely is set Frog/Smith can enter multi-entrance overworld doors + LDA.l FollowerTravelAllowed : AND.w #$00FF : BEQ .orig + ;If FollowerTravelAllowed is set Frog/Smith can enter multi-entrance overworld doors JML Overworld_Entrance_BRANCH_RHO .orig ; The rest is equivlent to what we overwrote diff --git a/events.asm b/events.asm index a3c422c..0f3b39c 100644 --- a/events.asm +++ b/events.asm @@ -135,7 +135,7 @@ OnFileCreation: ; Resolve instant post-aga if standard SEP #$20 - LDA.l InitProgressIndicator : BIT #$80 : BEQ + + LDA.l InitProgressIndicator : BIT.b #$80 : BEQ + LDA.b #$00 : STA.l ProgressIndicatorSRAM ; set post-aga after zelda rescue LDA.b #$00 : STA.l OverworldEventDataSRAM+$02 ; keep rain state vanilla + diff --git a/follower.asm b/follower.asm new file mode 100644 index 0000000..9d9727d --- /dev/null +++ b/follower.asm @@ -0,0 +1,888 @@ +pushpc +; follower hooks +org $81EBB6 +JSL MaybeSetZeldaCheckpoint +org $899FA1 +db $FF, $FF, $FF ; disable timed follower messages +org $89F544 +JSL MaybeDeleteFollowersOnDeath + +org $85EBCF +JSL SpritePrep_ZeldaFollower : NOP #2 +org $85EC9E +JSL SpriteDraw_ZeldaMaiden +org $85ECD9 +JSL Zelda_WaitingInCell +org $85ED46 +JSL Zelda_BecomeFollower : NOP #2 + +org $9EE902 +JSL SpritePrep_OldManFollower : NOP #2 : db $F0 ; BEQ +org $9DFF18 +JSL SpriteDraw_OldManFollower +org $9EE9BC +JSL Follower_CheckMessageCollision +org $9EE9CC +JSL OldMan_BecomeFollower : NOP #2 + +org $86899C +JSL SpritePrep_BlindMaiden : NOP #2 +org $8689A7 +JSL BlindZeldaDespawnFix : NOP #2 +org $9EE8B0 +JSL SpriteDraw_ZeldaMaiden +org $9EE8CD +JSL Follower_CheckCollision +org $9EE8D7 +JSL BlindMaiden_BecomeFollower : NOP + +org $868A7E +JSL SpritePrep_SmithyFrog : BRA + : NOP #8 : + +org $86B2AA +JSL Follower_CheckMessageCollision +org $86B2B4 +JSL Frog_BecomeFollower : NOP #2 +org $86B341 +JSL SpriteDraw_FrogFollower + +org $868A53 +JSL SpritePrep_PurpleChest : NOP #2 +org $9EE0D7 +JSL SpriteDraw_PurpleChest +org $9EE0E7 +JSL Follower_CheckMessageCollision +org $9EE0ED +JSL PurpleChest_FollowCheck +org $9EE0F7 +JSL PurpleChest_BecomeFollower : NOP + +org $868A0A +JSL SpritePrep_SuperBomb +org $868A4A +SuperBomb_BecomeFollower_exit: +org $9EE16E +BRA + : NOP #6 : + ; fix bomb shop dialog for dwarfless big bomb +org $9EE1E8 +JSL SuperBomb_FollowCheck +org $9EE1F1 +JSL SuperBomb_BecomeFollower : NOP #2 +org $9EE2C0 +JSL SpriteDraw_SuperBomb + +org $868D51 +JSL SpritePrep_Kiki : NOP #2 +org $9EE3E6 +JSL Kiki_OfferToFollow +org $9EE495 +JSL Kiki_FollowCheck : BRA + : NOP #12 : + +org $9EE4AF +JSL Kiki_BecomeFollower : NOP #2 + +org $868D63 +JSL SpritePrep_Locksmith : NOP #2 : db $90 ; BCC +org $868D7E +db $80 ; BRA +org $86BCD9 +JML Locksmith_Chillin_PostMessage +org $86BD7A ; allow follower pickup after purple chest item +LDA.b #$00 : STA.w SpriteActivity, X +JSL Locksmith_RespondToAnswer_PostItem +org $86BDB4 +JSL SpriteDraw_LocksmithFollower +org $86BD09 +JSL Locksmith_BecomeFollower : NOP #2 +pullpc + +MaybeDeleteFollowersOnDeath: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + ; s+q = favor keeping current follower + ; death = favor replacing with unfulfilled starting followers + ; during escape = always favor keeping zelda + LDA.b GameMode : CMP.b #$17 : BEQ .keep + LDA.w DungeonID : NOP #2 : BPL .keep + LDA.l InitFollowerIndicator : BEQ .keep + JSL DetermineFollowerSpawn_check_resolved : BCS .keep + LDA.l ProgressIndicator : CMP.b #$02 : BCS .delete + LDA.l FollowerIndicator : CMP.b #$01 : BEQ .keep +.delete + PLA : PLA : PEA.w $89F558-1 + RTL +.keep + PLA : PLA : PEA.w $89F55E-1 + RTL +.vanilla + LDA.l FollowerIndicator ; what we wrote over + RTL + +StartingFollower: + LDA.l InitFollowerIndicator : BEQ .return + PHA + REP #$20 + ; possible spawn points + LDA.b RoomIndex : CMP.w #$0104 : BEQ + ; links house + CMP.w #$0012 : BEQ + ; sanc + CMP.w #$00E4 : BEQ + ; old man + CMP.w #$0112 : BEQ + ; dark sanc + CMP.w #$011C : BEQ + ; bomb shop + SEP #$20 : PLA : RTL + + + SEP #$20 + LDA.l FollowerIndicator : BEQ + + LDA.l FollowerDropped : CMP.b #$80 : PLA : BCC .return : PHA + + LDA.l ProgressIndicator : CMP.b #$02 : PLA : BCC .escape_check + PHA + JSL DetermineFollowerSpawn_check_resolved + PLA + BCC .issue_follower + BRA .return +.escape_check + CMP.b #$01 : BNE .return + PHA : LDA.l ProgressFlags : AND.b #$04 : CMP.b #$04 : PLA : BCS .return +.issue_follower + STA.l FollowerIndicator + LDA.b #$00 : STA.l FollowerDropped +.return + RTL + +MaybeSetZeldaCheckpoint: + AND.w #$7FFF : TAX ; what we wrote over + SEP #$20 + LDA.l ProgressFlags : AND.b #$04 : BNE .return ; zelda rescued + LDA.l StartingEntrance : CMP.b #$04 : BEQ .return ; throne room checkpoint set + LDA.l FollowerIndicator : CMP.b #$01 : BNE .return ; zelda following + LDA.b RoomIndex : CMP.b #$80 : BNE + ;zelda cell + LDA.l Follower_Zelda : CMP.b #$01 : BNE .return + JSL Dungeon_SaveRoomQuadrantData + BRA .set_checkpoint + + CMP.b #$45 : BNE .return ; maiden cell + CPX.w #$0964 : BNE .return ; top big lock + LDA.l Follower_Maiden : CMP.b #$01 : BNE .return +.set_checkpoint + LDA.b #$02 : STA.l StartingEntrance + JSL SaveDeathCount +.return + REP #$30 + RTL + +FollowerGfxRedraw: + PHP : SEP #$30 + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .return + PHY + LDY.b #$0F + .next + LDA.w SpriteAITable,Y : BEQ ++ + LDA.w SpriteTypeTable,Y : CMP.b #$76 : BEQ + ; zelda + CMP.b #$AD : BEQ + ; old man + CMP.b #$B7 : BEQ + ; maiden + CMP.b #$1A : BEQ + ; frog + CMP.b #$39 : BEQ + ; locksmith + CMP.b #$B6 : BEQ + ; kiki + CMP.b #$B4 : BEQ + ; purple chest + CMP.b #$B5 : BNE ++ ; big bomb + LDA.w SpriteJumpIndex,Y : CMP.b #$02 : BEQ + + BRA ++ + + LDA.b #$01 : STA.w SprRedrawFlag,Y + ++ DEY : BPL .next + PLY +.return + PLP + RTL + +; A = 2 byte VRAM position in OAM2 for head/body +; Scrap06/07/08 = address to OAM group +; Returns with carry flag set if draw occurred +TransferAndDrawFollowerGfx: + PHA + LDA.w SpriteTimerE, X : AND.w #$0008 : BNE .skip_draw ; skip drawing every other frame + LDA.b 1,S + JSR TransferFollowerSpriteGfx ; returns with SEP #$20 + LDA.w SpriteTypeTable, X : CMP.b #$39 : BNE + + ; locksmith location flicker if quest completed but purple chest remains + LDA.w SpriteAux, X : BNE .continue + JSL DetermineFollowerSpawn : BCS .flicker + + BRA .continue + .flicker + LDA.w SpriteTimerE, X : NOP #2 : BNE .continue + LDA.b #$0C : STA.w SpriteTimerE, X + .continue + PLA : XBA : PLA : XBA + JSL SpriteDraw_Follower + SEC + RTL +.skip_draw + PLA + SEP #$20 + CLC + RTL + +; A = 2 byte VRAM position in OAM2 for head/body +TransferFollowerSpriteGfx_skip_transfer: + PLA : PLA + RTS +TransferFollowerSpriteGfx: + PHA : SEP #$20 + LDA.w SprRedrawFlag, X : BEQ .skip_transfer +.redraw + STZ.w SprRedrawFlag, X + JSL DetermineFollower + CMP.b #$01 : BNE + + PLA : XBA : LDA.b #$83 ; zelda body + JSR QueueFollowerSpriteGfx + PLA : XBA : LDA.b #$82 ; zelda head + JMP QueueFollowerSpriteGfx + + CMP.b #$04 : BNE + + PLA : XBA : LDA.b #$84 ; old man body + JSR QueueFollowerSpriteGfx + PLA : XBA : LDA.b #$85 ; old man head + JMP QueueFollowerSpriteGfx + + CMP.b #$06 : BNE + + PLA : XBA : LDA.b #$81 ; maiden body + JSR QueueFollowerSpriteGfx + PLA : XBA : LDA.b #$80 ; maiden head + JMP QueueFollowerSpriteGfx + + CMP.b #$07 : BNE + + PLA : XBA : PLA : LDA.b #$11 ; frog + JMP QueueFollowerSpriteGfx + + CMP.b #$08 : BNE + + PLA : XBA : PLA : LDA.b #$16 ; smith + JMP QueueFollowerSpriteGfx + + CMP.b #$09 : BNE + + PLA : XBA : LDA.b #$87 ; locksmith body + JSR QueueFollowerSpriteGfx + PLA : XBA : LDA.b #$86 ; locksmith head + JMP QueueFollowerSpriteGfx + + CMP.b #$0A : BNE + + PLA : XBA : LDA.b #$13 ; kiki body + JSR QueueFollowerSpriteGfx + PLA : XBA : LDA.b #$12 ; kiki head + JMP QueueFollowerSpriteGfx + + CMP.b #$0C : BNE + + PLA : XBA : PLA : LDA.b #$14 ; purple chest + JMP QueueFollowerSpriteGfx + + PLA : XBA : PLA : LDA.b #$15 ; super bomb + JMP QueueFollowerSpriteGfx + +; A = 2 bytes, dest/src +QueueFollowerSpriteGfx: + PHX : REP #$20 + PHA + AND.w #$00FF : CMP.w #$00FF : BEQ + + ASL #6 : EOR.w #$8000 : BRA .write_src + + LDA.w #$0020 ; blank tile + .write_src + LDX.w ItemStackPtr : STA.l ItemGFXStack,X + PLA : XBA + AND.w #$00FF : ASL #4 : EOR.w #$5000 + STA.l ItemTargetStack,X + TXA : INC #2 : STA.w ItemStackPtr + SEP #$20 : PLX + RTS + +; A = 2 byte VRAM position in OAM2 for head/body +; Scrap06/07/08 = address to OAM group +; Scrap09/0A = address to palette data +SpriteDraw_Follower: + PHB : LDY.b #$7E : PHY : PLB + REP #$20 + PHA + LDY.b #$0E + - LDA.b [Scrap06], Y : STA.w SpriteDynamicOAM, Y + DEY #2 : BPL - + LDA.b Scrap09 : STA.b Scrap06 + PLA + SEP #$20 + STA.w SpriteDynamicOAM+$0C : XBA : STA.w SpriteDynamicOAM+$04 + JSL DetermineFollower : PHA + PHX + TAX : DEX + LDA.b Scrap06 : ORA.b Scrap07 : BEQ + + TXY + LDA.b [Scrap06], Y + BRA .set_palette + + + LDA.l .palette_data, X + .set_palette + STA.w SpriteDynamicOAM+$05 : STA.w SpriteDynamicOAM+$0D + PLX + REP #$20 + LDA.w #$0002 : STA.b Scrap06 + LDA.w #SpriteDynamicOAM : STA.b Scrap08 + SEP #$20 + PLA : CMP.b #$07 : BCC + : CMP.b #$09 : BEQ + : CMP.b #$0A : BEQ + + ; only draw body + PHA + LDA.b #$01 : STA.b Scrap06 + LDA.b #SpriteDynamicOAM+8 : STA.b Scrap08 + PLA + + + ; follower specific adjustments + CMP.b #$04 : BNE + + LDA.w SpriteDynamicOAM+$0A : SEC : SBC.b #8 : STA.w SpriteDynamicOAM+$02 ; old man coords + + + CMP.b #$0A : BNE + + LDA.w SpriteDynamicOAM+$0A : SEC : SBC.b #6 : STA.w SpriteDynamicOAM+$02 ; kiki coords + LDA.w SpriteTypeTable, X : CMP.b #$1A : BEQ ++ : CMP.b #$B4 : BCS ++ : BRA .draw + ++ LDA.w SpriteDynamicOAM+$05 : ORA.b #$40 + STA.w SpriteDynamicOAM+$05 : STA.w SpriteDynamicOAM+$0D ; kiki horiz flip + + + .draw + JSL Sprite_DrawMultiple_player_deferred + PLB + RTL +.palette_data +; 01 04 06 07 08 09 0A 0C 0D +db $00, $00, $00, $00, $00, $06, $00, $00, $06, $00, $00, $00, $00 + + +DetermineFollower: + LDA.w SpriteAux, X : BEQ .skip_stored : RTL ; stored follower +.skip_stored + + LDA.w $0E20,X : CMP.b #$1A : BNE + + LDA.l Follower_Frog : BRA .finalize + + CMP.b #$39 : BNE + + LDA.l Follower_Locksmith : BRA .finalize + + CMP.b #$AD : BNE + + LDA.l Follower_OldMan : BRA .finalize + + CMP.b #$B6 : BNE + + LDA.l Follower_Kiki : BRA .finalize + + CMP.b #$B7 : BNE + + LDA.l Follower_Maiden : BRA .finalize + + CMP.b #$76 : BNE + + LDA.l Follower_Zelda : BRA .finalize + + CMP.b #$B4 : BNE + + LDA.l Follower_PurpleChest : BRA .finalize + + LDA.l Follower_SuperBomb +.finalize + PHA + CMP.b #$07 : BNE + + LDA.l CurrentWorld : BNE + + PLA : LDA.b #$08 : RTL + + + PLA + RTL + +SetAndLoadFollower: + LDA.l FollowerIndicator +.skip_current + PHA + LDA.b #$00 : STA.l FollowerDropped + JSL DetermineFollower : STA.l FollowerIndicator + CMP.b #$01 : BNE + + JSL DetermineFollower_skip_stored : CMP.b #$01 : BNE + + LDA.b #$02 : STA.l StartingEntrance + JSL SaveDeathCount + + CMP.b #$09 : BNE + + LDA.b #$40 : STA.w $02CD : STZ.w $02CE ; locksmith timed message + + + PHX + JSL Tagalong_LoadGfx + PLX + PLA : BNE + + JSL Follower_Initialize + JML Sprite_BecomeFollower + + + RTL + +StoreAndLoadFollower: + LDA.l FollowerDropped : BNE .no_storage + LDA.l FollowerIndicator : BEQ .no_storage + PHA + JSL SetAndLoadFollower_skip_current + PLA : STA.w SpriteAux, X + LDA.b #$13 : JSL Sound_SetSfx3PanLong + LDA.b #$01 : STA.w SprRedrawFlag, X + STZ.w SpriteActivity, X + LDA.b #$90 : STA.w SpriteTimerE, X + SEC : RTL +.no_storage + JSL SetAndLoadFollower_skip_current + CLC : RTL + +; return SEC if destination resolved +DetermineFollowerSpawn_locksmith_check: + ; locksmith location needs to spawn if purple chest reward not acquired + LDA.l FollowerIndicator : CMP.b #$0C : BEQ .always_spawn + JSL DetermineFollower_skip_stored : CMP.l FollowerIndicator : BEQ .matched_following + LDA.l NpcFlagsVanilla : AND.b #$10 : BEQ .always_spawn + BRA DetermineFollowerSpawn +.always_spawn + CLC : RTL +.matched_following + SEC : RTL + +DetermineFollowerSpawn_include_stored: + JSL DetermineFollower + BRA DetermineFollowerSpawn_byof +DetermineFollowerSpawn: + JSL DetermineFollower_skip_stored +.byof + CMP.l FollowerIndicator : BEQ .matched_following +.skip_match_check + PHA + ; despawn if pre-requisite not met + LDA.w SpriteTypeTable, X : CMP.b #$B4 : BNE + + LDA.l NpcFlagsVanilla : AND.b #$20 : EOR.b #$20 : CMP.b #$20 : PLA : RTL + + CMP.b #$B5 : BNE + + LDA.l CrystalsField : AND.b #$05 : CMP.b #$05 + LDA.b #$FF : ADC.b #$00 : ROR ; flip carry flag + PLA : RTL + + + PLA +.check_resolved + CMP.b #$01 : BNE + + LDA.l ProgressFlags : AND.b #$04 : CMP.b #$04 : RTL + + CMP.b #$04 : BNE + + JML ItemCheck_OldMan + + CMP.b #$06 : BNE + + LDA.l RoomDataWRAM[$AC].high : AND.b #$08 : CMP.b #$08 : BCS ++ + LDA.l EnemizerFlags_close_blind_door : CMP.b #$01 + ++ + RTL + + CMP.b #$09 : BCS + ; if frog or smith + LDA.l NpcFlagsVanilla : AND.b #$20 : CMP.b #$20 : RTL + + CMP.b #$0A : BNE + + LDA.l OverworldEventDataWRAM+$5E : AND.b #$20 : CMP.b #$20 : RTL + + CMP.b #$0C : BNE + + LDA.l NpcFlagsVanilla : AND.b #$10 : CMP.b #$10 + RTL + + +.always_spawn + CLC : RTL ; big bomb and locksmith have no completion condition in code +.matched_following + SEC : RTL + +Follower_CheckMessageCollision: + PHA + LDA.w SpriteTimerE, X : BNE .skip_collision_check + PLA + JML Sprite_ShowMessageFromPlayerContact ; what we wrote over +.skip_collision_check + PLA + CLC : RTL + +Follower_CheckTileCollision: + LDA.w SpriteTimerE, X : BNE .skip_collision_check + JML Sprite_CheckTileCollisionLong ; what we wrote over +.skip_collision_check + RTL + +Follower_CheckCollision: + LDA.w SpriteTimerE, X : BNE .skip_collision_check + JML Sprite_CheckDamageToPlayerSameLayerLong ; what we wrote over +.skip_collision_check + CLC : RTL + +SpritePrep_ZeldaFollower: + LDA.b RoomIndex : CMP.b #$12 : BEQ .no_follower_shuffle_sanc + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .no_follower_shuffle + JSL DetermineFollowerSpawn : BCC + : RTL : + + LDA.b #$01 : STA.w SprRedrawFlag, X + PLA : PLA : PEA.w $EC4B-1 ; return to spawn + RTL +.no_follower_shuffle + LDA.l FollowerIndicator : CMP.b #$01 + RTL +.no_follower_shuffle_sanc + LDA.l FollowerIndicator : CMP.b #$02 + RTL + +Zelda_WaitingInCell: + JSL Follower_CheckCollision ; what we wrote over, kinda + BCC .return + PHP + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE + + INC.w SpriteActivity, X + PLP + PLA : PLA : PEA.w $ECF9-1 : RTL ; skip sprite movement + + + PLP +.return + RTL + +Zelda_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + PLA : PLA + JSL StoreAndLoadFollower : BCC + + PEA.w $ED68-1 : RTL ; jump to avoid sprite despawn + + + PEA.w $ED60-1 ; jump to despawn + RTL + +.vanilla + LDA.b #$02 : STA.l StartingEntrance ; what we wrote over + RTL + +SpritePrep_BlindMaiden: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + JSL DetermineFollowerSpawn : BCC + + LDA.b #$01 : RTL + + + LDA.b #$01 : STA.w SprRedrawFlag, X + INC.w SpriteAncillaInteract, X + STZ.w FollowerNoDraw + PLA : PLA : PEA.w $89C8-1 ; return to spawn + RTL +.vanilla + LDA.l RoomDataWRAM[$AC].high : AND.b #$08 ; what we wrote over + RTL + +; Prevent followers from causing blind/maiden to despawn: +; Door rando: let zelda despawn the maiden. +BlindZeldaDespawnFix: + LDA.l FollowerIndicator ; what we wrote over + CMP.b #06 : BEQ + + LDA.w SpritePosYLow,X : BEQ + + LDA.b #$00 : RTL ; don't despawn follower if maiden isn't "present" + + + LDA.b #$01 : RTL + +SpriteDraw_ZeldaMaiden: + LDA.b RoomIndex : CMP.b #$12 : BEQ .vanilla + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.b #.oam_group>>16 : STA.b Scrap08 + LDA.w SpriteTypeTable, X : CMP.b #$76 : BNE + + REP #$20 + LDA.w #.oam_group : STA.b Scrap06 + LDA.w #0000 : STA.b Scrap09 + LDA.l Follower_Zelda_vram + BRA .transfer + + + REP #$20 + LDA.w #.oam_group : STA.b Scrap06 + LDA.w #.palette_data_maiden : STA.b Scrap09 + LDA.l Follower_Maiden_vram + .transfer + JML TransferAndDrawFollowerGfx +.skip_draw + RTL +.vanilla: + JML SpriteDraw_Maiden +.oam_group: +dw 1, -7 : db $20, $00, $00, $02 +dw 1, 3 : db $22, $00, $00, $02 +.palette_data_maiden +; 01 04 06 07 08 09 0A 0C 0D +db $02, $00, $00, $02, $00, $04, $02, $02, $04, $02, $00, $02, $02 + +BlindMaiden_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + PLA : PLA + JSL StoreAndLoadFollower : BCS .return + STZ.w SpriteAITable, X +.return + PEA.w $E8EA-1 ; jump ahead on return + RTL +.vanilla + STZ.w SpriteAITable, X : LDA.b #$06 ; what we wrote over + RTL + +SpritePrep_OldManFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .no_follower_shuffle + PLA : PLA + JSL DetermineFollowerSpawn : BCC + + PEA.w $E928-1 ; return to despawn + RTL + + + LDA.b #$01 : STA.w SprRedrawFlag, X + PEA.w $E927-1 ; return to spawn + RTL +.no_follower_shuffle + LDA.l FollowerIndicator : CMP.b #$04 + RTL + +SpriteDraw_OldManFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.w SpriteJumpIndex, X : CMP.b #$01 : BEQ .vanilla + LDA.b #.oam_group>>16 : STA.b Scrap08 + REP #$20 + LDA.w #.oam_group : STA.b Scrap06 + LDA.w #0000 : STA.b Scrap09 + PLA : PEA.w $FF45-1 ; skip vanilla draw + LDA.l Follower_OldMan_vram + JML TransferAndDrawFollowerGfx +.vanilla + LDA.b #$02 : STA.b Scrap06 ; what we wrote over + RTL +.oam_group +dw 0, 0 : db $AC, $00, $00, $02 +dw 0, 8 : db $AE, $00, $00, $02 + +OldMan_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BCC .set_follower_and_despawn + PLA : PLA + JSL StoreAndLoadFollower : BCC + + PEA.w $E9DF-1 : RTL ; jump to avoid sprite despawn + + + PEA.w $E9DC-1 ; jump to despawn + RTL +.set_follower_and_despawn + JSL SetAndLoadFollower + PLA : PLA : PEA.w $E9D6-1 + +SpritePrep_SmithyFrog: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .no_follower_shuffle + JSL DetermineFollowerSpawn : BCC + + LDA.b #$01 ; return to despawn + RTL + + + LDA.b #$01 : STA.w SprRedrawFlag, X + DEC ; return to spawn + RTL +.no_follower_shuffle + LDA.l FollowerIndicator : BNE + ; what we wrote over + LDA.l NpcFlagsVanilla : AND.b #$20 ; what we wrote over + + RTL + +SpriteDraw_FrogFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.b #.oam_group>>16 : STA.b Scrap08 + REP #$20 + LDA.w #.oam_group : STA.b Scrap06 + LDA.w #0000 : STA.b Scrap09 + PLA : PEA.w $DCD6-1 + LDA.l Follower_Frog_vram + JML TransferAndDrawFollowerGfx +.vanilla + LDA.b #$01 : STA.b Scrap06 ; what we wrote over + RTL +.oam_group: +dw 1, -8 : db $FF, $00, $00, $02 +dw 1, 0 : db $C8, $00, $00, $02 + +Frog_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BCC .set_follower_and_despawn + PLA : PLA + JSL StoreAndLoadFollower : BCC + + PEA.w $B2C7-1 : RTL ; jump to avoid sprite despawn + + + PEA.w $B2C4-1 ; jump to despawn + RTL +.set_follower_and_despawn + JSL SetAndLoadFollower + PLA : PLA : PEA.w $B2C4-1 ; jump to despawn + RTL + +SpritePrep_PurpleChest: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + JSL DetermineFollowerSpawn : BCC + + LDA.b #$00 ; return to despawn + RTL + + + PLA : PLA : PEA.w $8A69-1 ; return to spawn + LDA.b #$01 : STA.w SprRedrawFlag, X + RTL +.vanilla + LDA.l FollowerIndicator : CMP.b #$0C + RTL + +SpriteDraw_PurpleChest: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.b #.oam_group>>16 : STA.b Scrap08 + REP #$20 + LDA.w #.oam_group : STA.b Scrap06 + LDA.w #0000 : STA.b Scrap09 + LDA.l Follower_PurpleChest_vram + JML TransferAndDrawFollowerGfx +.vanilla + JML Sprite_PrepAndDrawSingleLargeLong ; what we wrote over +.oam_group: +dw 0, -8 : db $C8, $00, $00, $02 +dw 0, 0 : db $EE, $00, $00, $02 + +PurpleChest_FollowCheck: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.b #$00 + RTL +.vanilla + LDA.l FollowerIndicator ; what we wrote over + RTL + +PurpleChest_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + PLA : PLA + JSL StoreAndLoadFollower : BCS .return + STZ.w SpriteAITable, X +.return + PEA.w $E10A-1 ; jump ahead on return + RTL +.vanilla + STZ.w SpriteAITable, X : LDA.b #$0C ; what we wrote over + RTL + +SpritePrep_SuperBomb: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + JSL DetermineFollowerSpawn : BCC + + LDA.b #$00 ; despawn on exit + RTL + + + LDA.b #$05 + RTL +.vanilla + LDA.l CrystalsField ; what we wrote over + RTL + +SpriteDraw_SuperBomb: + LDA.w SpriteJumpIndex, X : CMP.b #$02 : BNE .vanilla + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.b #.oam_group>>16 : STA.b Scrap08 + REP #$20 + LDA.w #.oam_group : STA.b Scrap06 + LDA.w #.palette_data : STA.b Scrap09 + PLA : PEA.w $E2E2-1 ; skip vanilla draw + LDA.l Follower_SuperBomb_vram + JML TransferAndDrawFollowerGfx +.vanilla + LDA.b #$01 : STA.b Scrap06 ; what we wrote over + RTL +.oam_group: +dw 0, -8 : db $AE, $08, $00, $02 +dw 0, 0 : db $4E, $08, $00, $02 +.palette_data +; 01 04 06 07 08 09 0A 0C 0D +db $08, $00, $00, $08, $00, $06, $08, $08, $06, $08, $00, $08, $08 + +SuperBomb_FollowCheck: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.w SpriteTimerE, X : BNE .skip_follow + LDA.w SpriteAux, X : BEQ .vanilla + PLA : PLA : PEA.w $E1F1-1 ; jump to skip cost, no double charge + RTL +.skip_follow + PLA : PLA : PEA.w $E20C-1 ; jump to exit + RTL +.vanilla + LDA.b #$64 : LDY.b #$00 ; what we wrote over + RTL + +SuperBomb_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + PLA : PLA + JSL StoreAndLoadFollower : BCC + + PEA.w $E20C-1 : RTL ; jump to exit + + + PEA.w $E201-1 ; jump to despawn + RTL +.vanilla + LDA.b #$0D : STA.l FollowerIndicator ; what we wrote over + RTL + +pushpc +org $868A14 +NOP #3 ; fix bomb shop spawn for dwarfless big bomb +LDA.b #$B5 : JSL Sprite_SpawnDynamically +BMI SuperBomb_BecomeFollower_exit +LDA.b #$01 : STA.w SprRedrawFlag, Y ; force redraw for super bomb gfx +pullpc + +SpritePrep_Kiki: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + JSL DetermineFollowerSpawn : BCC + + LDA.b #$20 : RTL ; despawn on exit + + + LDA.b #$00 + RTL +.vanilla + LDX.b OverworldIndex : LDA.l OverworldEventDataWRAM,X ; what we wrote over + RTL + +Kiki_OfferToFollow: + PHA + LDA.w SpriteTimerE, X : BNE .skip_collision_check + PLA + JML Sprite_ShowMessageFromPlayerContact ; what we wrote over +.skip_collision_check + PLA + CLC : RTL + +Kiki_FollowCheck: + JSL DetermineFollowerSpawn_include_stored : BCS .skip_follow + LDA.w SpriteTimerE, X + RTL +.skip_follow + LDA.b #$20 + RTL + +Kiki_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .no_follower_shuffle + PLA : PLA : PEA.w $E4C2-1 ; jump to exit + STZ.w FollowerNoDraw + JML StoreAndLoadFollower +.no_follower_shuffle + LDA.b #$00 : STA.l FollowerDropped ; defuse bomb + LDA.b #$0A : STA.l FollowerIndicator +RTL + +SpritePrep_Locksmith: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + JSL DetermineFollowerSpawn_locksmith_check : BCS + + LDA.b #$01 : STA.w SprRedrawFlag, X + + + LDA.l FollowerIndicator + RTL +.vanilla + LDA.l FollowerIndicator : CMP.b #$09 ; what we wrote over + BEQ + + CLC : RTL + + + SEC : RTL + +SpriteDraw_LocksmithFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + LDA.b #.oam_group>>16 : STA.b Scrap08 + REP #$20 + LDA.w #.oam_group : STA.b Scrap06 + LDA.w #.palette_data : STA.b Scrap09 + PLA : PEA.w $DCD6-1 ; skip draw on exit + LDA.l Follower_Locksmith_vram + JML TransferAndDrawFollowerGfx +.vanilla + LDA.b #$02 : STA.b Scrap06 ; what we wrote over + RTL +.oam_group: +dw 0, -8 : db $EA, $00, $00, $02 +dw 0, 0 : db $EC, $00, $00, $02 +.palette_data +; 01 04 06 07 08 09 0A 0C 0D +db $00, $00, $00, $0E, $00, $00, $0E, $0E, $00, $0E, $00, $0E, $0E + +Locksmith_Chillin_PostMessage: + LDA.w SpritePosXLow, X : PHA + SEC : SBC.b #$0A : STA.w SpritePosXLow, X + LDA.w SpritePosYLow, X : PHA + SEC : SBC.b #$0A : STA.w SpritePosYLow, X + JSL Follower_CheckCollision : BCC .return + INC.w SpriteActivity, X ; award follower + LDA.l FollowerIndicator : CMP.b #$0C : BEQ .purple_chest_prize + LDA.l FollowerTravelAllowed : CMP.b #$02 : BEQ .return + LDA.l FollowerIndicator : CMP.b #$00 : BEQ .return + LDA.b #$05 : STA.w SpriteActivity, X ; forever do nothing + BRA .return +.purple_chest_prize + INC.w SpriteActivity, X ; prep for purple chest prize +.return + PLA : STA.w SpritePosYLow, X + PLA : STA.w SpritePosXLow, X + JML $86BD08 ; jump back to immediately RTS + +Locksmith_BecomeFollower: + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla + STZ.w FollowerNoDraw + PLA : PLA + JSL StoreAndLoadFollower : BCS + + LDA.l FollowerIndicator : CMP.b #$0C : BEQ + + PEA.w $BD24-1 : RTL ; jump to despawn + + + PEA.w $BD27-1 ; jump to exit + RTL +.vanilla + LDA.b #$09 : STA.l FollowerIndicator + RTL + +Locksmith_RespondToAnswer_PostItem: + STA.l FollowerIndicator ; what we wrote over + LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .no_despawn + LDA.w SpriteAux, X : BNE .no_despawn + LDA.l Follower_Locksmith : CMP.b #$0C : BNE .no_despawn + STZ.w SpriteAITable, X +.no_despawn + RTL diff --git a/framehook.asm b/framehook.asm index 40f82fb..126b2aa 100644 --- a/framehook.asm +++ b/framehook.asm @@ -48,7 +48,7 @@ JML NMIHookReturn ;-------------------------------------------------------------------------------- PostNMIHookAction: LDA.w NMIAux : BEQ + - PHK : PEA .return-1 ; push stack for RTL return + PHK : PEA.w .return-1 ; push stack for RTL return JMP.w [NMIAux] .return STZ.w NMIAux ; zero bank byte of NMI hook pointer diff --git a/hooks.asm b/hooks.asm index 0f5af4e..3198d28 100755 --- a/hooks.asm +++ b/hooks.asm @@ -407,6 +407,12 @@ STA.l StalfosBombDamage org $8AB76E ; <- 5376E - Bank0A.asm : 30 (JSL OverworldMap_InitGfx) JSL OnLoadDuckMap +;================================================================================ +; Fix Clobbered Gfx +;-------------------------------------------------------------------------------- +org $80E259 +JSL PostFixOAMGfx : NOP + ;================================================================================ ; Infinite Bombs / Arrows / Magic ;-------------------------------------------------------------------------------- @@ -555,12 +561,6 @@ JSL AgahnimAsksAboutPed org $9ED6E8 JSL CheckAgaForPed : NOP -;================================================================================ -; Zelda Sprite Fixes -;-------------------------------------------------------------------------------- -org $85EBCF ; <- 2EBCF - sprite_zelda.asm : 23 (LDA $7EF359 : CMP.b #$02 : BCS .hasMasterSword) -JSL SpawnZelda : NOP #2 - ;================================================================================ ; Alternate Goal ;-------------------------------------------------------------------------------- @@ -688,12 +688,6 @@ db $06, $1F, $40, $12, $01, $3F, $14, $01, $3F, $13, $1F, $42, $1A, $1F, $4B, $1 org $85DFB1 ; <- 2DFB1 - Bank05.asm : 2499 JSL SkipDrawEOR -;================================================================================ -; Kiki Big Bomb Fix -;-------------------------------------------------------------------------------- -org $9EE4AF ; <- f64af sprite_kiki.asm : 285 (LDA.b #$0A : STA $7EF3CC) -JSL AssignKiki : NOP #2 - ;================================================================================ ; Wallmaster camera fix ;-------------------------------------------------------------------------------- @@ -845,11 +839,6 @@ org $81E97E dw $0116 : db $08 dw $0116 : db $25 ;-------------------------------------------------------------------------------- -org $9EE16E ; <- F616E - sprite_bomb_shop_entity.asm : 73 -NOP #8 ; fix bomb shop dialog for dwarfless big bomb -org $868A14 ; <- 30A14 - sprite_prep.asm : 716 -NOP #8 ; fix bomb shop spawn for dwarfless big bomb -;-------------------------------------------------------------------------------- org $86B489 ; <- 33489 - sprite_smithy_bros.asm : 473 (LDA $7EF359 : CMP.b #$03 : BCS .tempered_sword_or_better) JML GetSmithSword : NOP #4 Smithy_DoesntHaveSword: @@ -1819,7 +1808,9 @@ Sprite_ShowMessageUnconditional_Rest: ;-------------------------------------------------------------------------------- ;-- Music restarting at zelda fix org $85ED10 ; <- 2ED10 - sprite_zelda.asm : 233 - (LDA.b #$19 : STA $012C) -NOP #5 +BRA + : NOP #3 : + +org $85ED63 +BRA + : NOP #3 : + ;-------------------------------------------------------------------------------- org $9ECE47 ; <- F4E47 - sprite_crystal_maiden.asm : 220 JML MaidenCrystalScript @@ -2344,24 +2335,6 @@ org $82A451 ; <- 12451 - Bank02.asm:6283 (LDA $F6 : AND.b #$40 : BEQ .xButtonNot JSL QuickSwap ;================================================================================ -;================================================================================ -; Tagalong Fixes -;-------------------------------------------------------------------------------- -org $8689AB ; <- 309AB - sprite_prep.asm: 647 (LDA $7EF3CC : CMP.b #$06 : BEQ .killSprite) -; Note: In JP 1.0 we have: (CMP.b #$00 : BNE .killSprite) appling US bugfix -; Prevent followers from causing blind/maiden to despawn: -; Door rando: let zelda despawn the maiden. -JSL BlindZeldaDespawnFix - -org $8689AF -SpritePrep_BlindMaiden_despawn_follower: ; this is the normal execution path - -org $8689C9 -SpritePrep_BlindMaiden_kill_the_girl: ; not the follower -;-------------------------------------------------------------------------------- -; Fix old man purple chest issues using the same method as above -org $9EE906 ; <- F6906 - sprite_old_mountain_man.asm : 31 (LDA $7EF3CC : CMP.b #$00 : BNE .already_have_tagalong) -CMP.b #$04 : db $F0 ; BEQ ;-------------------------------------------------------------------------------- ;Control which doors frog/smith can enter org $9BBCF0 ; <- DBCF0 - Bank1B.asm: 248 (LDA $04B8 : BNE BRANCH_MU) diff --git a/initsramtable.asm b/initsramtable.asm index 908ee85..5f7d7e4 100644 --- a/initsramtable.asm +++ b/initsramtable.asm @@ -123,8 +123,8 @@ InitNpcFlagsVanilla: skip 1 ; PC 0x1833C9 InitCurrentWorld: skip 1 ; PC 0x1833CA skip 1 ; PC 0x1833CB InitFollowerIndicator: skip 1 ; PC 0x1833CC -InitFollowerXCoord: skip 2 ; PC 0x1833CD -InitFollowerYCoord: skip 2 ; PC 0x1833CF +InitFollowerYCoord: skip 2 ; PC 0x1833CD +InitFollowerXCoord: skip 2 ; PC 0x1833CF InitDroppedFollowerIndoors: skip 1 ; PC 0x1833D1 InitDroppedFollowerLayer: skip 1 ; PC 0x1833D2 InitFollowerDropped: skip 1 ; PC 0x1833D3 diff --git a/keydrop/dynamic_si_vram.asm b/keydrop/dynamic_si_vram.asm index d9d8251..6111e23 100644 --- a/keydrop/dynamic_si_vram.asm +++ b/keydrop/dynamic_si_vram.asm @@ -376,7 +376,7 @@ TransferCommonToVRAM: REP #$21 SEP #$10 - LDA.w #BigDecompressionBuffer+$2000 + LDA.w #BigDecompressionBuffer+$2400 LDX.b #BigDecompressionBuffer>>16 STA.w $4302 STX.w $4304 diff --git a/ram.asm b/ram.asm index 79a0dfc..43e6512 100644 --- a/ram.asm +++ b/ram.asm @@ -221,6 +221,7 @@ ItemReceiptMethod = $7E02E9 ; ; TileActBE = $7E02EF ; Bitfield used by breakables and entrances. b b b b d d d d ; b = Breakables | d = Entrances +FollowerNoDraw = $7E02F9 ; When set, prevents follower from drawing and forces a game mode check UseY1 = $7E0301 ; Bitfield for Y-item usage: b p - a x z h r ; b = Boomerang | p = Powder | a = Bow | x = Hammer (tested, never set) ; z = Rods (tested, never set) | h = Hammer | r = Rods @@ -841,6 +842,7 @@ endmacro %assertRAM(CutsceneFlag, $7E02E4) %assertRAM(ItemReceiptMethod, $7E02E9) %assertRAM(TileActBE, $7E02EF) +%assertRAM(FollowerNoDraw, $7E02F9) %assertRAM(UseY1, $7E0301) %assertRAM(CurrentYItem, $7E0303) %assertRAM(AButtonAct, $7E0308) diff --git a/sram.asm b/sram.asm index 23fc67d..0a2df8a 100644 --- a/sram.asm +++ b/sram.asm @@ -212,8 +212,8 @@ FollowerIndicator: skip 1 ; $00 = No Follower | $01 = Zelda | $04 = Ol ; $06 = Blind Maiden | $07 = Frog | $08 = Dwarf ; $09 = Locksmith | $0A = Kiki | $0C = Purple Chest ; $0D = Big Bomb -FollowerXCoord: skip 2 ; \ Cached X and Y overworld coordinates of dropped follower -FollowerYCoord: skip 2 ; / (16-bit integers) +FollowerYCoord: skip 2 ; \ Cached X and Y overworld coordinates of dropped follower +FollowerXCoord: skip 2 ; / (16-bit integers) DroppedFollowerIndoors: skip 1 ; $00 = Dropped follower outdoors | $01 = Dropped follower indoors DroppedFollowerLayer: skip 1 ; $00 = Upper layer | $01 =.lower layer FollowerDropped: skip 1 ; Set to $80 when a follower exists and has been dropped somewhere @@ -512,8 +512,8 @@ endmacro %assertSRAM(NpcFlagsVanilla, $7EF3C9) %assertSRAM(CurrentWorld, $7EF3CA) %assertSRAM(FollowerIndicator, $7EF3CC) -%assertSRAM(FollowerXCoord, $7EF3CD) -%assertSRAM(FollowerYCoord, $7EF3CF) +%assertSRAM(FollowerYCoord, $7EF3CD) +%assertSRAM(FollowerXCoord, $7EF3CF) %assertSRAM(DroppedFollowerIndoors, $7EF3D1) %assertSRAM(DroppedFollowerLayer, $7EF3D2) %assertSRAM(FollowerDropped, $7EF3D3) diff --git a/tables.asm b/tables.asm index d381a17..6842c23 100644 --- a/tables.asm +++ b/tables.asm @@ -190,8 +190,11 @@ QuickSwapFlag: db $00 ; #$00 = Off (default) - #$01 = On ;-------------------------------------------------------------------------------- org $B0804C ; PC 0x18004C -SmithTravelsFreely: -db $00 ; #$00 = Off (default) - #$01 = On (frog/smith can enter multi-entrance doors) +FollowerTravelAllowed: +db $00 +; #$00 = Off (default) +; #$01 = On (frog/smith can enter multi-entrance doors) +; #$02 = Follower Shuffle Enabled ;-------------------------------------------------------------------------------- org $B0804D ; PC 0x18004D EscapeAssist: ; ScrubMode: @@ -1011,14 +1014,14 @@ org $B08220 ; PC 0x180220 org $B08240 ; PC 0x180240 StartingAreaExitOffset: db $00, $00, $00, $00, $00, $00, $00 -;-------------------------------------------------------------------------------- +;------------------------------------------------------------------------------- org $B08247 ; PC 0x180247 ; For any starting areas in single entrance caves you can specify the overworld door here ; to enable drawing the doorframes These values should be the overworld door index+1. ; A value of zero will draw no door frame. StartingAreaOverworldDoor: db $00, $00, $00, $00, $00, $00, $00 -;-------------------------------------------------------------------------------- +;------------------------------------------------------------------------------- ; 0x18024E - 0x18024F (unused) ;------------------------------------------------------------------------------- ; $308250 (0x180250) - $30829F (0x18029F) @@ -1033,11 +1036,50 @@ dw $0000 : db $00 : dw $0000, $0000, $0000, $0000, $0000, $0000, $0000 : db $00, dw $0000 : db $00 : dw $0000, $0000, $0000, $0000, $0000, $0000, $0000 : db $00, $00, $00 ;-------------------------------------------------------------------------------- ; 0x1802A0 - 0x1802BF (unused) -;--------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +; $3082C0 (0x1802C0) - $3082D7 (0x1802D7) +org $B082C0 +; Follower data +; First byte is the Follower ID awarded at each of the locations +; Next 2 bytes are OAM address references to the head/body gfx +Follower_Zelda: ; PC 0x1802C0 +db $01 +.vram +dw $CCCE +Follower_OldMan: ; PC 0x1802C3 +db $04 +.vram +dw $ACAE +Follower_Maiden: ; PC 0x1802C6 +db $06 +.vram +dw $CCCE +Follower_Frog: ; PC 0x1802C9 +db $07 +.vram +dw $C8EE +Follower_Locksmith: ; PC 0x1802CC +db $09 +.vram +dw $EAEC +Follower_Kiki: ; PC 0x1802CF +db $0A +.vram +dw $C0C2 +Follower_PurpleChest: ; PC 0x1802D2 +db $0C +.vram +dw $C8EE +Follower_SuperBomb: ; PC 0x1802D5 +db $0D +.vram +dw $AE4E +;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- -; 0x1802C0 - 0x1802FF (unused) -;--------------------------------------------------------------------------------- +; 0x1802D8 - 0x1802FF (unused) +;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ; $308300 (0x180300) - $30834F (0x18034F) org $B08300 ; PC 0x180300 diff --git a/utilities.asm b/utilities.asm index 625c2ca..5a1414a 100644 --- a/utilities.asm +++ b/utilities.asm @@ -435,7 +435,7 @@ LoadItemPalette: ; Out: A - Sprite palette index PHX : PHY : PHB LDA.b #PalettesVanillaBank>>16 : STA.b Scrap0C - PEA $7E00 + PEA.w $7E00 PLB : PLB REP #$30 diff --git a/vanillalabels.asm b/vanillalabels.asm index f151050..621d399 100644 --- a/vanillalabels.asm +++ b/vanillalabels.asm @@ -37,6 +37,7 @@ CopyFontToVRAM = $80E596 LoadCommonSprites_in_file_select = $80E784 PaletteFilter_TheEndSprite = $80EC03 PrepDungeonExit = $80F945 +SaveDeathCount = $80F9DD Mirror_InitHdmaSettings = $80FDEE Dungeon_LoadRoom = $81873A Underworld_HandleRoomTags = $81C2FD @@ -73,12 +74,14 @@ SpritePrep_MagicShopAssistant = $85F521 Player_ApplyRumbleToSprites = $8680FA Sprite_Main = $868328 Utility_CheckIfHitBoxesOverlapLong = $8683E6 +Sprite_Get16BitCoords_long = $8684BD Sprite_TransmuteToBomb = $86AD58 Sprite_PrepAndDrawSingleLargeLong = $86DBF8 Sprite_PrepAndDrawSingleSmallLong = $86DC00 Sprite_DrawShadowLong = $86DC5C DashKey_Draw = $86DD40 Sprite_PrepOAMCoordLong = $86E41C +Sprite_CheckTileCollisionLong = $86E49C Sprite_ApplySpeedTowardsPlayerLong = $86EA18 Sprite_DirectionToFacePlayerLong = $86EAA6 Sprite_CheckDamageToPlayerSameLayerLong = $86F12F @@ -117,6 +120,8 @@ AncillaAdd_GTCutscene = $899B6F AddDoorDebris_spawn_failed = $899C39 AddAncillaLong = $899D04 Ancilla_CheckIfAlreadyExistsLong = $899D1A +Follower_Initialize = $899EE8 +Sprite_BecomeFollower = $899F25 Ancilla_TerminateSelectInteractives = $89AC57 GiveRupeeGift = $89AD58 Sprite_SetSpawnedCoords = $89AE64 @@ -141,6 +146,7 @@ Sound_SetSfxPanWithPlayerCoords = $8DBB67 Sound_SetSfx1PanLong = $8DBB6E Sound_SetSfx2PanLong = $8DBB7C Sound_SetSfx3PanLong = $8DBB8A +SpriteDraw_Maiden = $8DCE4F SpriteDraw_Stumpy = $8DD030 HUD_RefreshIconLong = $8DDB7F Equipment_UpdateEquippedItemLong = $8DDD32 diff --git a/zelda.asm b/zelda.asm index df4508c..1d7c9fd 100644 --- a/zelda.asm +++ b/zelda.asm @@ -1,12 +1,3 @@ -;================================================================================ -; Spawn Zelda (or not) -;-------------------------------------------------------------------------------- -SpawnZelda: - LDA.l FollowerIndicator : CMP.b #$08 : BEQ + ; don't spawn if dwarf is present - CMP.b #$07 : BEQ + ; don't spawn if frog is present - CMP.b #$0C : BEQ + ; don't spawn if purple chest is present - CLC - + RTL ;-------------------------------------------------------------------------------- EndRainState: LDA.l InitProgressIndicator : BIT.b #$80 : BNE + ; check for instant post-aga From ed7fb312d5844e720fa3d3260d6a0b762ab0c50e Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 30 Apr 2025 06:26:33 -0500 Subject: [PATCH 3/5] Fixed some incorrect bunny music behavior --- music.asm | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/music.asm b/music.asm index d69f1af..821970f 100644 --- a/music.asm +++ b/music.asm @@ -96,15 +96,14 @@ Overworld_DetermineMusic: CMP.b #$43 : BEQ .darkMountain CMP.b #$45 : BEQ .darkMountain CMP.b #$47 : BEQ .darkMountain + LDX.b #$09 ; default dark world theme + BRA .default_set + - LDX.b #$02 ; hyrule field theme - LDA.l CurrentWorld : BEQ + - LDX.b #$09 ; default dark world theme - + .default_set ; Check if we're entering the village - + LDA.b OverworldIndex : CMP.b #$18 : BNE + + LDA.b OverworldIndex : CMP.b #$18 : BNE + ; Check what phase we're in ; LDA ProgressIndicator : CMP.b #$03 : !BGE .bunny LDX.b #$07 ; Default village theme (phase <3) From 2d84f7431e99bdca805ef6786ae033c147e216ca Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 30 Apr 2025 06:48:54 -0500 Subject: [PATCH 4/5] Minor consistency --- follower.asm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/follower.asm b/follower.asm index 9d9727d..eb2f8e0 100644 --- a/follower.asm +++ b/follower.asm @@ -443,8 +443,7 @@ DetermineFollowerSpawn: + CMP.b #$0A : BNE + LDA.l OverworldEventDataWRAM+$5E : AND.b #$20 : CMP.b #$20 : RTL + CMP.b #$0C : BNE + - LDA.l NpcFlagsVanilla : AND.b #$10 : CMP.b #$10 - RTL + LDA.l NpcFlagsVanilla : AND.b #$10 : CMP.b #$10 : RTL + .always_spawn CLC : RTL ; big bomb and locksmith have no completion condition in code From 86efa741858f6fcf6cba06c612038ae0567995f2 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 4 May 2025 09:24:33 -0500 Subject: [PATCH 5/5] Various bug fixes for Follower Shuffle post-launch - Fix issue with infinite purple chest item get - Fix issue with Kiki running away on iframe ledge hops - Fix issue with bad follower gfx on screens with followers - Fix issue with Zelda appearing in conditional follower locations --- bugfixes.asm | 4 ++++ follower.asm | 29 ++++++++++++++++++++++++----- hooks.asm | 2 ++ ram.asm | 2 ++ vanillalabels.asm | 1 + 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/bugfixes.asm b/bugfixes.asm index fb2dc40..7a6d59a 100644 --- a/bugfixes.asm +++ b/bugfixes.asm @@ -180,6 +180,10 @@ LDA.b IndoorsFlag : BNE + + RTL +PostFixMirrorGfx: + JSL HandleFollowersAfterMirroring + JML FollowerGfxRedraw + PostFixOAMGfx: JSL FollowerGfxRedraw REP #$30 : LDA.w #$2000 ; what we wrote over diff --git a/follower.asm b/follower.asm index eb2f8e0..a296723 100644 --- a/follower.asm +++ b/follower.asm @@ -77,6 +77,8 @@ org $9EE495 JSL Kiki_FollowCheck : BRA + : NOP #12 : + org $9EE4AF JSL Kiki_BecomeFollower : NOP #2 +org $89A1B2 +JSL Kiki_DontScareTheMonke : NOP #3 org $868D63 JSL SpritePrep_Locksmith : NOP #2 : db $90 ; BCC @@ -84,13 +86,13 @@ org $868D7E db $80 ; BRA org $86BCD9 JML Locksmith_Chillin_PostMessage +org $86BD09 +JSL Locksmith_BecomeFollower : NOP #2 org $86BD7A ; allow follower pickup after purple chest item LDA.b #$00 : STA.w SpriteActivity, X JSL Locksmith_RespondToAnswer_PostItem org $86BDB4 JSL SpriteDraw_LocksmithFollower -org $86BD09 -JSL Locksmith_BecomeFollower : NOP #2 pullpc MaybeDeleteFollowersOnDeath: @@ -421,11 +423,14 @@ DetermineFollowerSpawn: PHA ; despawn if pre-requisite not met LDA.w SpriteTypeTable, X : CMP.b #$B4 : BNE + - LDA.l NpcFlagsVanilla : AND.b #$20 : EOR.b #$20 : CMP.b #$20 : PLA : RTL + LDA.l NpcFlagsVanilla : AND.b #$20 : EOR.b #$20 : CMP.b #$20 + BRA .prereq_check + CMP.b #$B5 : BNE + LDA.l CrystalsField : AND.b #$05 : CMP.b #$05 LDA.b #$FF : ADC.b #$00 : ROR ; flip carry flag - PLA : RTL + .prereq_check + PLA : BCC .check_resolved + RTL + PLA .check_resolved @@ -811,6 +816,18 @@ Kiki_BecomeFollower: LDA.b #$0A : STA.l FollowerIndicator RTL +; on return it checks BEQ and if non-zero, kiki get spook +Kiki_DontScareTheMonke: + LDA.b LinkJumping : BEQ .return + LDA.w NoDamage : BNE .no_spook + LDA.w LinkThud : BNE .no_spook +.spook + LDA.b #$01 : RTL +.no_spook + LDA.b #$00 +.return + RTL + SpritePrep_Locksmith: LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .vanilla JSL DetermineFollowerSpawn_locksmith_check : BCS + @@ -880,8 +897,10 @@ Locksmith_BecomeFollower: Locksmith_RespondToAnswer_PostItem: STA.l FollowerIndicator ; what we wrote over LDA.l FollowerTravelAllowed : CMP.b #$02 : BNE .no_despawn + LDA.l Follower_Locksmith : CMP.b #$0C : BEQ .despawn LDA.w SpriteAux, X : BNE .no_despawn LDA.l Follower_Locksmith : CMP.b #$0C : BNE .no_despawn - STZ.w SpriteAITable, X +.despawn + STZ.w SpriteAITable, X .no_despawn RTL diff --git a/hooks.asm b/hooks.asm index 3198d28..227003c 100755 --- a/hooks.asm +++ b/hooks.asm @@ -410,6 +410,8 @@ JSL OnLoadDuckMap ;================================================================================ ; Fix Clobbered Gfx ;-------------------------------------------------------------------------------- +org $80DB92 +JSL PostFixMirrorGfx org $80E259 JSL PostFixOAMGfx : NOP diff --git a/ram.asm b/ram.asm index 43e6512..b814b71 100644 --- a/ram.asm +++ b/ram.asm @@ -221,6 +221,7 @@ ItemReceiptMethod = $7E02E9 ; ; TileActBE = $7E02EF ; Bitfield used by breakables and entrances. b b b b d d d d ; b = Breakables | d = Entrances +LinkThud = $7E02F8 ; When set, guarantees a thud on landing FollowerNoDraw = $7E02F9 ; When set, prevents follower from drawing and forces a game mode check UseY1 = $7E0301 ; Bitfield for Y-item usage: b p - a x z h r ; b = Boomerang | p = Powder | a = Bow | x = Hammer (tested, never set) @@ -842,6 +843,7 @@ endmacro %assertRAM(CutsceneFlag, $7E02E4) %assertRAM(ItemReceiptMethod, $7E02E9) %assertRAM(TileActBE, $7E02EF) +%assertRAM(LinkThud, $7E02F8) %assertRAM(FollowerNoDraw, $7E02F9) %assertRAM(UseY1, $7E0301) %assertRAM(CurrentYItem, $7E0303) diff --git a/vanillalabels.asm b/vanillalabels.asm index 621d399..4a5d7eb 100644 --- a/vanillalabels.asm +++ b/vanillalabels.asm @@ -94,6 +94,7 @@ Player_HaltDashAttackLong = $8791B3 Link_ReceiveItem = $87999D Link_ReceiveItem_cool_pose = $8799EE Link_ReceiveItem_not_cool_pose = $8799F2 +HandleFollowersAfterMirroring = $87AA8B LinkHop_FindArbitraryLandingSpot = $87E359 Link_HandleMovingAnimation_FullLongEntry = $87E68F Link_CheckForEdgeScreenTransition = $87F413