;================================================================================ ; New Item Handlers ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ; Service Indexes ; 0x00 - 0x04 - chests ; 0xF0 - freestanding heart / powder / mushroom / bonkable ; 0xF1 - freestanding heart 2 / boss heart / npc ; 0xF3 - tablet/pedestal ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- GetAnimatedSpriteGfxFile: CMP.b #$0C : BNE + LDY.b #$5C : JML GetAnimatedSpriteGfxFile_return + CMP.b #$23 : BNE + LDY.b #$5D : JML GetAnimatedSpriteGfxFile_return + CMP.b #$48 : BNE + LDY.b #$60 : JML GetAnimatedSpriteGfxFile_return + CMP.b #$4B : BNE + LDY.b #$50 : JML GetAnimatedSpriteGfxFile_return + CMP.b #$4C : BNE + LDY.b #$5E : JML GetAnimatedSpriteGfxFile_return + CMP.b #$24 : !BGE + LDY.b #$5B : JML GetAnimatedSpriteGfxFile_return + CMP.b #$37 : !BGE + LDY.b #$5C : JML GetAnimatedSpriteGfxFile_return + CMP.b #$39 : !BGE + LDY.b #$5D : JML GetAnimatedSpriteGfxFile_return + LDY.b #$32 JML GetAnimatedSpriteGfxFile_return GetAnimatedSpriteBufferPointer_table: ; Original data: dw $09C0, $0030, $0060, $0090, $00C0, $0300, $0318, $0330 dw $0348, $0360, $0378, $0390, $0930, $03F0, $0420, $0450 dw $0468, $0600, $0630, $0660, $0690, $06C0, $06F0, $0720 ; disassembly (incorrectly?) says this is $0270 dw $0750, $0768, $0900, $0930, $0960, $0990, $09F0, $0000 dw $00F0, $0A20, $0A50, $0660, $0600, $0618, $0630, $0648 dw $0678, $06D8, $06A8, $0708, $0738, $0768, $0960, $0900 dw $03C0, $0990, $09A8, $09C0, $09D8, $0A08, $0A38, $0600 dw $0630 ; New data: dw $0600, $0630, $0660, $0690 ; 50 Bombs / 70 Arrows / Half Magic / Quarter Magic dw $06C0, $06F0, $8520 ; +5/+10 Bomb Arrows ;#$4x dw $0750 ; +10 Arrows dw $0900 ; Upgrade-Only Silver Arrows dw $09D8 ; Unused dw $0930, $0960, $0990, $09C0 ; Lvl 1/2/3/4 Sword (Freestanding) dw $09F0 ; Null-Item dw $09C0 ; Clock dw $0A20 ; Triforce dw $0A50 ; Power Star dw $09F0 ; Chicken dw $09C0 ; Fairy ($09F0 if using uncompressed version) dw $0988 ; Apple GetAnimatedSpriteBufferPointer: ;PHB : PHK : PLB LDA.b Scrap00 : ADC.l GetAnimatedSpriteBufferPointer_table, X ;PLB RTL macro ProgrammableItemLogic(index) LDA.l ProgrammableItemLogicPointer_ : BNE ?jump LDA.l ProgrammableItemLogicPointer_+1 : BNE ?jump LDA.l ProgrammableItemLogicPointer_+2 : BNE ?jump BRA ?end ?jump: JSL ProgrammableItemLogicJump_ ?end: endmacro ;-------------------------------------------------------------------------------- ;carry clear if pass ;carry set if caught ;incsrc eventdata.asm ProcessEventItems: LDA.b Scrap00 : PHA LDA.b Scrap01 : PHA LDA.b Scrap02 : PHA PHY : PHP PHB : LDA.b #$AF : PHA : PLB LDA.w ItemReceiptID CMP.b #$E0 : BNE + REP #$30 ; set 16-bit accumulator & index registers LDA.l RNGItem : ASL : TAX LDA.l EventDataOffsets, X : !ADD.l #EventDataTable : STA.b Scrap00 SEP #$20 ; set 8-bit accumulator LDA.b #$AF : STA.b Scrap02 JSL LoadDialogAddressIndirect LDA.l RNGItem : INC : STA.l RNGItem SEP #$10 ; set 8-bit index registers REP #$20 ; set 16-bit accumulator LDA.l GoalItemRequirement : BEQ ++ LDA.l GoalCounter : INC : STA.l GoalCounter CMP.l GoalItemRequirement : BCC ++ LDA.l TurnInGoalItems : AND.w #$00FF : BNE ++ SEP #$20 ; set 8-bit accumulator LDA.b OverworldIndex : CMP.b #$80 : BNE +++ LDA.b LinkPosX+1 : BNE +++ JSL ActivateGoal +++ ++ SEP #$20 ; set 8-bit accumulator LDX.b #$01 : BRA .done + LDX.b #$00 .done PLB PLP : PLY PLA : STA.b Scrap02 PLA : STA.b Scrap01 PLA : STA.b Scrap00 RTS ;-------------------------------------------------------------------------------- AddReceivedItemExpanded: PHA : PHX LDA.l RemoteItems : BEQ + : LDA.l !MULTIWORLD_ITEM_PLAYER_ID : BEQ + LDA.w ItemReceiptMethod : BEQ ++ : CMP.b #$03 : BNE +++ : ++ ; fromTextOrObject LDA.w $0345 : BEQ ++ : LDA.b #$04 : ++ : STA.b LinkState ; Restore Link to his swimming state STZ.w ItemReceiptPose : STZ.w NoDamage : STZ.w CutsceneFlag LDA.b #$0E : STA.w SFX3 +++ STZ.w ItemReceiptID : STZ.w ItemReceiptID+1 : STZ.w ItemReceiptMethod PHY : LDY.b #$00 : JSL AddInventory : PLY PLX : PLA : RTL + PLX : PLA JSR ResolveReceipt PHB : PHK JML AddReceivedItem+2 AddReceivedItemExpandedGetItem: PHX : PHB LDA.w ItemReceiptID JSL FreeDungeonItemNotice PHA : LDA.l !MULTIWORLD_ITEM_PLAYER_ID : BEQ + PLA : BRA .done + PLA JSR ItemBehavior SEP #$30 .done PLB : PLX LDA.w ItemReceiptMethod : CMP.b #$01 ; thing we wrote over RTL ItemBehavior: REP #$30 AND.w #$00FF : ASL : TAX SEP #$20 JMP (ItemReceipts_behavior,X) .skip RTS .blue_boomerang LDA.l InventoryTracking : ORA.b #$80 BRA .store_inventory_tracking .red_boomerang LDA.l InventoryTracking : ORA.b #$40 BRA .store_inventory_tracking .mushroom LDA.l InventoryTracking : ORA.b #$28 BRA .store_inventory_tracking .powder LDA.l InventoryTracking : ORA.b #$10 BRA .store_inventory_tracking .flute_inactive LDA.b #$00 : STA.l FluteBitfield LDA.l InventoryTracking : ORA.b #$02 BRA .store_inventory_tracking .flute_active LDA.b #$00 : STA.l FluteBitfield LDA.l InventoryTracking : ORA.b #$01 BRA .store_inventory_tracking .shovel LDA.l InventoryTracking : ORA.b #$04 .store_inventory_tracking STA.l InventoryTracking RTS .sword_shield SEP #$10 LDX.b #$01 JSR .increment_sword JSR .increment_shield RTS .master_sword SEP #$10 LDX.b #$02 JSR .increment_sword RTS .tempered_sword SEP #$10 LDX.b #$03 JSR .increment_sword RTS .gold_sword SEP #$10 LDX.b #$04 JSR .increment_sword RTS .fighter_shield .red_shield .mirror_shield SEP #$10 LDA.l ProgressiveFlag : BEQ + LDA.l HighestShield : INC : TAX JSR .increment_shield + RTS .blue_mail SEP #$10 LDX.b #$01 JSR .increment_mail REP #$10 RTS .red_mail SEP #$10 LDX.b #$02 JSR .increment_mail REP #$10 RTS .fighter_sword SEP #$10 LDX.b #$01 JSR .increment_sword REP #$10 RTS .prog_sword SEP #$10 LDA.l SwordEquipment : INC : TAX JSR .increment_sword REP #$10 RTS .prog_shield SEP #$10 LDA.l HighestShield : INC : TAX JSR .increment_shield REP #$10 RTS .prog_mail SEP #$10 LDA.l ArmorEquipment : INC : TAX JSR .increment_mail REP #$10 RTS .bow BIT.b #$40 : BNE .silversbow LDA.b #$01 : STA.l BowEquipment RTS .silversbow LDA.l BowTracking : ORA.b #$40 : STA.l BowTracking LDA.l SilverArrowsUseRestriction : BNE + LDA.b #03 : STA.l BowEquipment ; set bow to silver + LDA.b #$01 : STA.l BowEquipment RTS .dungeon_compass REP #$20 LDA.w DungeonID : CMP.w #$0003 : BCC ..hc_sewers TAX LDA.l DungeonItemMasks,X : TAY ORA.l CompassField : STA.l CompassField JMP .increment_compass ..hc_sewers LDA.w #$C000 : TAY ORA.l CompassField : STA.l CompassField JMP .increment_compass .dungeon_bigkey REP #$20 LDA.w DungeonID : CMP.w #$0003 : BCC ..hc_sewers TAX LDA.l DungeonItemMasks,X : ORA.l BigKeyField : STA.l BigKeyField JMP .increment_bigkey ..hc_sewers LDA.w #$C000 : ORA.l BigKeyField : STA.l BigKeyField JMP .increment_bigkey .dungeon_map REP #$20 LDA.w DungeonID : CMP.w #$0003 : BCC ..hc_sewers TAX LDA.l DungeonItemMasks,X : TAY ORA.l MapField : STA.l MapField JMP .increment_map ..hc_sewers LDA.w #$C000 : TAY ORA.l MapField : STA.l MapField JMP .increment_map .bow_and_arrows LDA.l BowTracking : BIT.b #$40 : BEQ .no_silvers LDA.l SilverArrowsUseRestriction : BNE .no_silvers LDA.l CurrentArrows : BEQ + LDA.b #04 : STA.l BowEquipment BRA .store_bow + LDA.b #$03 BRA .store_bow .no_silvers LDA.l CurrentArrows : BEQ + LDA.b #02 BRA .store_bow + LDA.b #$01 .store_bow STA.l BowEquipment RTS .silver_bow LDA.b #$40 : ORA.l BowTracking : STA.l BowTracking LDA.l SilverArrowsUseRestriction : BNE .noequip LDA.l SilverArrowsAutoEquip : AND.b #$01 : BEQ .noequip LDA.l CurrentArrows : BNE + ; check arrows LDA.b #$03 : BRA ++ ; bow without arrow + LDA.b #$04 ; bow with arrow ++ STA.l BowEquipment .noequip RTS .bombs_50 LDA.b #50 : STA.l BombCapacity ; upgrade bombs LDA.b #50 : STA.l BombsFiller ; fill bombs RTS .arrows_70 LDA.b #70 : STA.l ArrowCapacity ; upgrade arrows LDA.b #70 : STA.l ArrowsFiller ; fill arrows RTS .magic_2 LDA.l MagicConsumption : CMP.b #$02 : !BGE + INC : STA.l MagicConsumption ; upgrade magic + LDA.b #$80 : STA.l MagicFiller ; fill magic RTS .magic_4 LDA.b #$02 : STA.l MagicConsumption ; upgrade magic LDA.b #$80 : STA.l MagicFiller ; fill magic RTS .master_sword_safe SEP #$10 LDA.l SwordEquipment : CMP.b #$02 : !BGE + ; skip if we have a better sword LDA.b #$02 : STA.l SwordEquipment ; set master sword + LDX.b #$02 JSR .increment_sword RTS .bombs_5 LDA.l BombCapacity : !ADD.b #$05 : STA.l BombCapacity ; upgrade bombs +5 LDA.l Upgrade5BombsRefill : STA.l BombsFiller ; fill bombs RTS .bombs_10 LDA.l BombCapacity : !ADD.b #$0A : STA.l BombCapacity ; upgrade bombs +10 LDA.l Upgrade10BombsRefill : STA.l BombsFiller ; fill bombs RTS .arrows_5 LDA.l ArrowCapacity : !ADD.b #$05 : STA.l ArrowCapacity ; upgrade arrows +5 LDA.l Upgrade5ArrowsRefill : STA.l ArrowsFiller ; fill arrows RTS .arrows_10 LDA.l ArrowCapacity : !ADD.b #$0A : STA.l ArrowCapacity ; upgrade arrows +10 LDA.l Upgrade10ArrowsRefill : STA.l ArrowsFiller ; fill arrows RTS .programmable_1 %ProgrammableItemLogic(1) RTS .programmable_2 %ProgrammableItemLogic(2) RTS .programmable_3 %ProgrammableItemLogic(3) RTS .silver_arrows LDA.l BowTracking : ORA.b #$40 : STA.l BowTracking LDA.l SilverArrowsUseRestriction : BNE ++ LDA.l SilverArrowsAutoEquip : AND.b #$01 : BEQ ++ LDA.l BowEquipment : BEQ ++ : CMP.b #$03 : !BGE + !ADD.b #$02 : STA.l BowEquipment ; switch to silver bow + ++ LDA.l ArrowMode : BEQ + LDA.b #$01 : STA.l ArrowsFiller + RTS .single_arrow LDA.l ArrowMode : BEQ + LDA.l CurrentArrows : INC : STA.l CurrentArrows ; Should be sole write to this address LDA.b #$01 : STA.l UpdateHUDFlag ; in retro/rupee bow mode. + RTS .rupoor REP #$20 : LDA.l CurrentRupees : !SUB.l RupoorDeduction : STA.l CurrentRupees : SEP #$20 ; Take 1 rupee RTS .null RTS .red_clock REP #$20 ; set 16-bit accumulator LDA.l ChallengeTimer : !ADD.l RedClockAmount : STA.l ChallengeTimer LDA.l ChallengeTimer+2 : ADC.l RedClockAmount+2 : STA.l ChallengeTimer+2 SEP #$20 ; set 8-bit accumulator RTS .blue_clock REP #$20 ; set 16-bit accumulator LDA.l ChallengeTimer : !ADD.l BlueClockAmount : STA.l ChallengeTimer LDA.l ChallengeTimer+2 : ADC.l BlueClockAmount+2 : STA.l ChallengeTimer+2 SEP #$20 ; set 8-bit accumulator RTS .green_clock REP #$20 ; set 16-bit accumulator LDA.l ChallengeTimer : !ADD.l GreenClockAmount : STA.l ChallengeTimer LDA.l ChallengeTimer+2 : ADC.l GreenClockAmount+2 : STA.l ChallengeTimer+2 SEP #$20 ; set 8-bit accumulator RTS .triforce LDA.b OverworldIndex : CMP.b #$80 : BNE + LDA.b LinkPosX+1 : BNE + JSL ActivateGoal + RTS .goal_item REP #$20 ; set 16-bit accumulator LDA.l GoalItemRequirement : BEQ + LDA.l GoalCounter : INC : STA.l GoalCounter CMP.w GoalItemRequirement : BCC + LDA.l TurnInGoalItems : AND.w #$00FF : BNE + SEP #$20 ; set 8-bit accumulator LDA.b OverworldIndex : CMP.b #$80 : BNE + LDA.b LinkPosX+1 : BNE + JSL ActivateGoal + SEP #$20 ; set 8-bit accumulator RTS .request_F0 JSL ItemGetServiceRequest_F0 RTS .request_F1 JSL ItemGetServiceRequest_F1 RTS .request_F2 JSL ItemGetServiceRequest_F2 RTS .request_async ; JSL ItemGetServiceRequest RTS .free_map REP #$20 LSR AND.w #$000F : ASL : TAX LDA.w DungeonItemIDMap,X : TAX LDA.l DungeonItemMasks,X : TAY ORA.l MapField : STA.l MapField SEP #$20 JMP .increment_map .hc_map REP #$20 LDA.w #$C000 : TAY ORA.l MapField : STA.l MapField JMP .increment_map .free_compass REP #$20 LSR AND.w #$000F : ASL : TAX LDA.w DungeonItemIDMap,X : TAX LDA.l DungeonItemMasks,X : TAY ORA.l CompassField : STA.l CompassField SEP #$20 JMP .increment_compass .hc_compass REP #$20 LDA.w #$C000 : TAY ORA.l CompassField : STA.l CompassField SEP #$20 JMP .increment_compass .free_bigkey REP #$20 LSR AND.w #$000F : ASL : TAX LDA.w DungeonItemIDMap,X : TAX LDA.l DungeonItemMasks,X : ORA.l BigKeyField : STA.l BigKeyField SEP #$20 JMP .increment_bigkey .hc_bigkey LDA.b #$C0 : ORA.l BigKeyField+1 : STA.l BigKeyField+1 JMP .increment_bigkey .free_smallkey REP #$20 LSR AND.w #$000F : TAX ASL : CMP.w DungeonID : BEQ .same_dungeon LDA.l DungeonKeys,X : INC : STA.l DungeonKeys,X RTS .same_dungeon SEP #$20 LDA.l CurrentSmallKeys : INC : STA.l CurrentSmallKeys : STA.l DungeonKeys,X RTS .same_dungeon_hc SEP #$20 LDA.l CurrentSmallKeys : INC : STA.l CurrentSmallKeys LDA.l SewerKeys : INC STA.l SewerKeys : STA.l HyruleCastleKeys RTS .hc_smallkey LDA.w DungeonID : CMP.b #$03 : BCC .same_dungeon_hc LDA.l HyruleCastleKeys : INC : STA.l HyruleCastleKeys LDA.l SewerKeys : INC : STA.l SewerKeys RTS .generic_smallkey LDA.l GenericKeys : BEQ .normal LDA.l CurrentSmallKeys : INC STA.l CurrentGenericKeys : STA.l CurrentSmallKeys RTS .normal LDA.w DungeonID : BMI + LDA.l CurrentSmallKeys : INC : STA.l CurrentSmallKeys RTS + RTS .increment_sword LDA.l HighestSword INC : STA.b Scrap04 : CPX.b Scrap04 : BCC + ; don't increment unless we're getting a better sword TXA : STA.l HighestSword + RTS .increment_shield LDA.l HighestShield INC : STA.b Scrap04 : CPX.b Scrap04 : BCC + ; don't increment unless we're getting a better shield TXA : STA.l HighestShield + RTS .increment_mail LDA.l HighestMail INC : STA.b Scrap04 : CPX.b Scrap04 : BCC + ; don't increment unless we're getting a better mail TXA : STA.l HighestMail + RTS .increment_bigkey SEP #$20 LDA.l StatsLocked : BNE + LDA.l BigKeysBigChests CLC : ADC.b #$10 STA.l BigKeysBigChests + RTS .increment_map SEP #$20 LDA.l StatsLocked : BNE + LDA.l MapsCompasses CLC : ADC.b #$10 STA.l MapsCompasses JSL MaybeFlagMapTotalPickup + RTS .increment_compass SEP #$20 LDA.l StatsLocked : BNE + LDA.l MapsCompasses : INC : AND.b #$0F : TAX LDA.l MapsCompasses : AND.b #$F0 : STA.l MapsCompasses TXA : ORA.l MapsCompasses : STA.l MapsCompasses JSL MaybeFlagCompassTotalPickup + RTS .pendant SEP #$20 LSR SEC : SBC.b #$37 TAX LDA.w PendantMasks,X : AND.l PendantsField : BNE + LDA.l PendantCounter : INC : STA.l PendantCounter + RTS .dungeon_crystal SEP #$20 LDA.l CrystalCounter : INC : STA.l CrystalCounter RTS .free_crystal REP #$20 LSR AND.w #$000F : TAX LDA.w #$0000 SEC - ROL DEX BPL - SEP #$20 TAX AND.l CrystalsField : BNE + TXA ORA.l CrystalsField : STA.l CrystalsField LDA.l CrystalCounter : INC : STA.l CrystalCounter + .done RTS .refill_magic SEP #$30 : LDA.b #$80 : STA.l MagicFiller : RTS .bee_trap SEP #$30 LDA.b #$79 : JSL Sprite_SpawnDynamically : BMI + ; DashBeeHive_SpawnBee LDA.b LinkPosX : CLC : ADC.b #$03 : AND.b #$F8 : STA.w SpritePosXLow,Y LDA.b LinkPosX+1 : ADC.b #$00 : STA.w SpritePosXHigh,Y ; round X to nearest 8 LDA.b LinkPosY : STA.w SpritePosYLow, Y : LDA.b LinkPosY+1 : STA.w SpritePosYHigh, Y LDA.b LinkLayer : STA.w SpriteLayer,Y ; spawns on same layer as link + RTS .good_bee SEP #$30 LDA.b #$79 : JSL Sprite_SpawnDynamically : BMI + ; DashBeeHive_SpawnBee LDA.b LinkPosX : CLC : ADC.b #$03 : AND.b #$F8 : STA.w SpritePosXLow,Y LDA.b LinkPosX+1 : ADC.b #$00 : STA.w SpritePosXHigh,Y ; round X to nearest 8 LDA.b LinkPosY : STA.w SpritePosYLow, Y : LDA.b LinkPosY+1 : STA.w SpritePosYHigh, Y LDA.b LinkLayer : STA.w SpriteLayer,Y ; spawns on same layer as link JSL GoldBee_SpawnSelf_SetProperties + RTS .apples SEP #$30 LDA.b #$AC : JSL Sprite_SpawnDynamically : BMI + LDA.b LinkPosX : CLC : ADC.b #$03 : AND.b #$F8 : STA.w SpritePosXLow,Y LDA.b LinkPosX+1 : ADC.b #$00 : STA.w SpritePosXHigh,Y ; round X to nearest 8 LDA.b LinkPosY : SEC : SBC.b #$10 : STA.w SpritePosYLow,Y LDA.b LinkPosY+1 : SBC.b #$00 : STA.w SpritePosYHigh,Y ; move up 16 pixels LDA.b LinkLayer : STA.w SpriteLayer,Y ; spawns on same layer as link LDA.b #$FF : STA.w EnemyStunTimer,Y ; allows them to expire + RTS .fairy SEP #$30 LDA.b #$E3 : JSL Sprite_SpawnDynamically : BMI + LDA.b LinkPosX : CLC : ADC.b #$03 : AND.b #$F8 : STA.w SpritePosXLow,Y LDA.b LinkPosX+1 : ADC.b #$00 : STA.w SpritePosXHigh,Y ; round X to nearest 8 LDA.b LinkPosY : SEC : SBC.b #$10 : STA.w SpritePosYLow,Y LDA.b LinkPosY+1 : SBC.b #$00 : STA.w SpritePosYHigh,Y ; move up 16 pixels LDA.b LinkLayer : STA.w SpriteLayer,Y ; spawns on same layer as link LDA.b #$FF : STA.w EnemyStunTimer,Y ; allows them to expire + RTS .chicken SEP #$30 LDA.b #$0B : JSL Sprite_SpawnDynamically : BMI + LDA.b LinkPosX : CLC : ADC.b #$03 : AND.b #$F8 : STA.w SpritePosXLow,Y LDA.b LinkPosX+1 : ADC.b #$00 : STA.w SpritePosXHigh,Y ; round X to nearest 8 LDA.b LinkPosY : SEC : SBC.b #$08 : STA.w SpritePosYLow,Y LDA.b LinkPosY+1 : SBC.b #$00 : STA.w SpritePosYHigh,Y ; move up 8 pixels LDA.b LinkLayer : STA.w SpriteLayer,Y ; spawns on same layer as link + RTS ResolveReceipt: PHA : PHX PHK : PLB JSL PreItemGet LDA.l !MULTIWORLD_ITEM_PLAYER_ID : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID LDA.w ItemReceiptID : STA.l !MULTIWORLD_ITEM_ID JSL AttemptItemSubstitution JSR HandleBowTracking JSR ResolveLootID STA.w ItemReceiptID LDA.l !MULTIWORLD_ITEM_PLAYER_ID : BNE + LDA.w ItemReceiptID JSR IncrementItemCounters + PLX : PLA RTS ResolveLootIDLong: PHY JSR ResolveLootID PLY RTL ResolveLootID: ; In: A - Loot ID ; Out: A - Resolved Loot ID ; Caller is responsible for running AttemptItemSubstitution prior if applicable. PHX : PHB PHK : PLB .get_item TAY REP #$30 AND.w #$00FF : ASL : TAX TYA JMP (ItemReceipts_resolution,X) .have_item SEP #$30 PLB : PLX RTS .skip JMP .have_item .bottles SEP #$30 JSR CountBottles : CMP.l BottleLimit : BCC + LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE + LDA.l BottleLimitReplacement JMP .get_item + TYA JMP .have_item .magic SEP #$20 LDA.l MagicConsumption : TAX LDA.w .magic_ids,X JMP .have_item ..ids db $4E, $4F, $4F .prog_sword SEP #$20 LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE ++ LDA.l HighestSword CMP.l ProgressiveSwordLimit : BCC + LDA.l ProgressiveSwordReplacement JMP .get_item ++ LDA.l SwordEquipment + TAX LDA.w .prog_sword_ids,X JMP .have_item ..ids db $49, $50, $02, $03, $03 .shields SEP #$20 LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE ++ LDA.b #$01 : STA.l ProgressiveFlag LDA.l HighestShield CMP.l ProgressiveShieldLimit : BCC + LDA.l ProgressiveShieldReplacement JMP .get_item ++ LDA.l HighestShield + TAX LDA.w .shields_ids,X JMP .have_item ..ids db $04, $05, $06, $06 .armor SEP #$20 LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE ++ LDA.l HighestMail CMP.l ProgressiveArmorLimit : BCC + LDA.l ProgressiveArmorReplacement JMP .get_item + ++ LDA.l ArmorEquipment TAX LDA.w .armor_ids,X JMP .have_item ..ids db $22, $23, $23 .gloves SEP #$20 LDA.l GloveEquipment : TAX LDA.w .gloves_ids,X JMP .have_item ..ids db $1B, $1C, $1C .progressive_bow ; For non-chest progressive bows we assign the tracking bits to SpriteMetaData,X ; (where X is that sprite's slot) so the bit can be set on pickup. SEP #$30 LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE .skipbowlimit LDA.l BowEquipment : INC : LSR : CMP.l ProgressiveBowLimit : BCC + LDA.l ProgressiveBowReplacement JMP .get_item + LDA.w ItemReceiptMethod : CMP.b #$01 : BEQ + LDX.w CurrentSpriteSlot LDA.b #$10 : STA.w SpriteMetaData,X + .skipbowlimit LDA.l BowEquipment : TAX LDA.w ResolveLootID_bows_ids,X JMP .get_item .progressive_bow_2 SEP #$30 LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE .skipbowlimit_2 LDA.l BowEquipment : INC : LSR : CMP.l ProgressiveBowLimit : BCC + LDA.l ProgressiveBowReplacement JMP .get_item + LDA.w ItemReceiptMethod : CMP.b #$01 : BEQ + LDX.w CurrentSpriteSlot LDA.b #$20 : STA.w SpriteMetaData,X .skipbowlimit_2 + LDA.l BowEquipment : TAX LDA.w ResolveLootID_bows_ids,X JMP .get_item .bows ..ids db $3A, $3B, $3B, $3B, $3B .null_chest ; JSL ChestItemServiceRequest JMP .have_item .rng_single JSL GetRNGItemSingle : STA.l ScratchBufferV+6 XBA : JSR MarkRNGItemSingle LDA.b #$FF : STA.l RNGLockIn ; clear lock-in LDA.l ScratchBufferV+6 : JMP .get_item .rng_multi JSL GetRNGItemMulti : STA.l ScratchBufferV+6 LDA.b #$FF : STA.l RNGLockIn ; clear lock-in LDA.l ScratchBufferV+6 : JMP .get_item ;-------------------------------------------------------------------------------- DungeonItemMasks: ; these are dungeon correlations to $7EF364 - $7EF369 so it knows where to store compasses, etc ; sewers and castle get 2 bits active so that they can share their items elegantly dw $C000, $C000, $2000, $1000, $0800, $0400, $0200, $0100 dw $0080, $0040, $0020, $0010, $0008, $0004, $4B8B, $20AB ; last two can be re-used ; caves dw $9CCE, $0390, $2F82, $AD03, $02E9, $01C9, $06D0, $72A5 dw $A548, $4873, $01A0, $D8AD, $C902, $D020, $A002, $9802 dw $E48D, $DA02, $D8AC, $D002, $A215, $BD08, $84E2, $0085 dw $E3BD, $8584, $A901, $857E, $B902, $857A, $0087, $0A98 dw $BDAA, $84E2, $0085, $E3BD, $8584, $A901, $857E, $B902 dw $857A, $0230, $0087, $1FC0, $02D0, $5664, $04A9, $4BC0 dw $06F0, $1EC0, $0AD0, $02A9, $790F, $7EF3, $798F, $7EF3 dw $1BC0, $04F0, $1CC0, $07D0, $1B22, $1BEE, $0182, $A201 dw $C004, $F037, $A20C, $C001, $F038, $A206, $C002, $D039 dw $8A14, $0007, $0087, $00EE, $2902, $C907, $D007, $A906 dw $8F04, $F3C7, $C07E, $D022, $A70A, $D000, $A904, $8701 dw $8000, $C0C9, $F025, $C008, $F032, $C004, $D033, $AE11 dw $040C, $20C2, $C6BD, $0785, $8700, $E200, $8220, $00B0 dw $3EC0, $0AD0, $082C, $1003, $A905, $8D02, $0309, $20C0 dw $44D0 ;-------------------------------------------------------------------------------- BottleListExpanded: db $16, $2B, $2C, $2D, $3D, $3C, $48 PotionListExpanded: db $2E, $2F, $30, $FF, $0E ;-------------------------------------------------------------------------------- HandleBowTracking: ; In: A - Item Receipt ID PHA CMP.b #$64 : BEQ .prog_one CMP.b #$65 : BEQ .prog_two CMP.b #$0B : BEQ .vanilla_bow CMP.b #$3A : BEQ .vanilla_bow CMP.b #$3B : BEQ .vanilla_bow PLA RTS .prog_one LDA.b #$10 BRA .done .prog_two LDA.b #$20 BRA .done .vanilla_bow ; A non-chest progressive bow will always have been resolved to a vanilla bow ID ; at this point. LDA.w ItemReceiptMethod : CMP.b #$01 : BEQ + LDX.w CurrentSpriteSlot LDA.w SpriteMetaData,X : BEQ .done BRA .done + LDA.b #$00 .done ORA.b #$80 : ORA.l BowTracking STA.l BowTracking PLA RTS ;-------------------------------------------------------------------------------- ;Return BowEquipment but also draw silver arrows if you have the upgrade even if you don't have the bow CheckHUDSilverArrows: LDA.l ArrowMode : BNE .rupee_bow LDA.l BowEquipment : TAX : BEQ .nobow JSL DrawHUDArrows_normal TXA RTL .rupee_bow LDA.l BowEquipment : TAX JSL DrawHUDArrows_rupee_arrows TXA RTL .nobow JSL DrawHUDArrows_silverscheck TXA RTL ;-------------------------------------------------------------------------------- DrawHUDArrows: .rupee_arrows LDA.l CurrentArrows : BEQ .none ; assuming silvers will increment this. if we go with something else, reorder these checks TXA : BNE + .silverscheck LDA.l BowTracking : AND.b #$40 : BNE .silver BRA .wooden + CMP.b #03 : !BGE .silver .wooden LDA.b #$A7 : STA.l HUDTileMapBuffer+$20 ; draw wooden arrow marker LDA.b #$20 : STA.l HUDTileMapBuffer+$21 LDA.b #$A9 : STA.l HUDTileMapBuffer+$22 LDA.b #$20 : STA.l HUDTileMapBuffer+$23 .skip RTL .normal TXA CMP.b #$03 : BCS .silver BRA .wooden .silver LDA.b #$86 : STA.l HUDTileMapBuffer+$20 ; draw silver arrow marker LDA.b #$24 : STA.l HUDTileMapBuffer+$21 LDA.b #$87 : STA.l HUDTileMapBuffer+$22 LDA.b #$24 : STA.l HUDTileMapBuffer+$23 RTL .none LDA.b #$7F : STA.l HUDTileMapBuffer+$20 ; draw no arrow marker LDA.b #$24 : STA.l HUDTileMapBuffer+$21 LDA.b #$7F : STA.l HUDTileMapBuffer+$22 LDA.b #$24 : STA.l HUDTileMapBuffer+$23 RTL ;-------------------------------------------------------------------------------- GetRNGItemSingle: PHY LDA.l RNGLockIn : CMP.b #$FF : BEQ + : TAX : XBA : LDA.l RNGSingleItemTable, X : RTL : + LDX.b #$00 .single_reroll JSL GetRandomInt : AND.b #$7F ; select random value INX : CPX.b #$7F : BCC + : LDA.b #$00 : BRA +++ : + ; default to 0 if too many attempts CMP.l RNGSingleTableSize : !BGE .single_reroll +++ STA.l ScratchBufferV ; put our index value here LDX.b #$00 TAY .recheck TYA JSR CheckSingleItem : BEQ .single_unused ; already used LDA.l ScratchBufferV : INC ; increment index CMP.l RNGSingleTableSize : BCC +++ : LDA.b #$00 : +++ ; rollover index if needed STA.l ScratchBufferV ; store index INX : TAY : TXA : CMP.l RNGSingleTableSize : BCC .recheck LDA.b #$5A ; everything is gone, default to null item - MAKE THIS AN OPTION FOR THIS AND THE OTHER ONE BRA .single_done .single_unused LDA.l ScratchBufferV .single_done TAX : LDA.l RNGSingleItemTable, X XBA : LDA.l ScratchBufferV : STA.l RNGLockIn : XBA PLY RTL ;-------------------------------------------------------------------------------- CheckSingleItem: LSR #3 : TAX LDA.l RNGItem, X : STA.l ScratchBufferV+2 ; load value to temporary PHX LDA.l ScratchBufferV : AND.b #$07 : TAX ; load 0-7 part into X LDA.l ScratchBufferV+2 --- CPX.b #$00 : BEQ +++ LSR DEX BRA --- +++ PLX AND.b #$01 RTS ;-------------------------------------------------------------------------------- MarkRNGItemSingle: LSR #3 : STA.l ScratchBufferV+1 : TAX LDA.l RNGItem, X STA.l ScratchBufferV+2 LDA.l ScratchBufferV : AND.b #$07 : TAX ; load 0-7 part into X LDA.b #01 --- CPX.b #$00 : BEQ +++ ASL DEX BRA --- +++ PHA LDA.l ScratchBufferV+1 : TAX PLA ORA.l ScratchBufferV+2 STA.l RNGItem, X RTS ;-------------------------------------------------------------------------------- GetRNGItemMulti: LDA.l RNGLockIn : CMP.b #$FF : BEQ + : TAX : XBA : LDA.l RNGMultiItemTable, X : RTL : + LDX.b #$00 - ; reroll JSL GetRandomInt : AND.b #$7F ; select random value INX : CPX.b #$7F : BCC + : LDA.b 00 : BRA .done : + ; default to 0 if too many attempts CMP.l RNGMultiTableSize : !BGE - .done STA.l RNGLockIn TAX : XBA : LDA.l RNGMultiItemTable, X RTL ;-------------------------------------------------------------------------------- IncrementItemCounters: PHX : PHA LDX.b #$00 - LDA.l ItemSubstitutionRules, X CMP.b #$FF : BEQ .exit CMP.b 1,s : BNE .noMatch .match PHX TXA : LSR #2 : TAX LDA.l ItemLimitCounts, X : INC : STA.l ItemLimitCounts, X PLX BEQ .exit .noMatch INX #4 BRA - .exit PLA : PLX RTS ;-------------------------------------------------------------------------------- AttemptItemSubstitution: PHX : PHA LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE .exit LDX.b #$00 - LDA.l ItemSubstitutionRules, X CMP.b #$FF : BEQ .exit CMP.b 1,S : BNE .noMatch .match PHX TXA : LSR #2 : TAX LDA.l ItemLimitCounts, X PLX CMP.l ItemSubstitutionRules+1, X : BCC + LDA.l ItemSubstitutionRules+2, X : STA.b 1,S + BEQ .exit .noMatch INX #4 BRA - .exit PLA : PLX RTL ;-------------------------------------------------------------------------------- CountBottles: PHX LDX.b #$00 LDA.l BottleContentsOne : BEQ + : INX + : LDA.l BottleContentsTwo : BEQ + : INX + : LDA.l BottleContentsThree : BEQ + : INX + : LDA.l BottleContentsFour : BEQ + : INX + TXA PLX RTS ;-------------------------------------------------------------------------------- ActivateGoal: STZ.b GameSubMode STZ.b SubSubModule JML StatsFinalPrep ;-------------------------------------------------------------------------------- ChestPrep: LDA.b #$01 : STA.w ItemReceiptMethod JSL IncrementChestCounter LDA.l ServerRequestMode : BEQ + JSL ChestItemServiceRequest RTL + LDY.b Scrap0C ; get item value SEC RTL ;-------------------------------------------------------------------------------- Ancilla22_ItemReceipt_ContinueB: CMP.b #$6A : BNE .return JSL ActivateTriforceCutscene .return STZ.w AncillaID,X : STZ.w FreezeSprites ; what we wrote over RTL ;-------------------------------------------------------------------------------- MaybeFlagCompassTotalPickup: LDA.l CompassMode : AND.b #$0F : BEQ .done LDA.w DungeonID : BMI .done LDA.w ItemReceiptID : CMP.b #$25 : BEQ .set_flag REP #$20 AND.w #$000F : ASL : TAX LDA.w DungeonItemIDMap,X : CMP.w DungeonID : BNE .done .set_flag REP #$20 TYA : ORA.l CompassCountDisplay : STA.l CompassCountDisplay .done RTL MaybeFlagMapTotalPickup: ; LDA.l MapHUDMode : AND.b #$0F : BEQ .done LDA.w DungeonID : BMI .done LDA.w ItemReceiptID : CMP.b #$33 : BEQ .set_flag REP #$20 AND.w #$000F : ASL : TAX LDA.w DungeonItemIDMap,X : CMP.w DungeonID : BNE .done .set_flag REP #$20 TYA : ORA.l MapCountDisplay : STA.l MapCountDisplay .done RTL ;-------------------------------------------------------------------------------- ; Set the dungeon item count display flags if we're entering a dungeon and have the ; corresponding dungeon item MaybeFlagDungeonTotalsEntrance: LDX.w DungeonID : BMI .done ; Skip if we're not entering dungeon REP #$10 LDA.l DungeonItemMasks,X : TAY LDA.l CompassMode : AND.w #$000F : BEQ .maps ; Skip if we're not showing compass counts JSR FlagCompassCount .maps LDA.l MapHUDMode : AND.w #$000F LDX.w DungeonID JSR FlagMapCount .done RTL ;-------------------------------------------------------------------------------- FlagCompassCount: CMP.w #$0002 : BEQ .compass_shown LDA.l CompassField : AND.l DungeonItemMasks, X : BEQ .done ; skip if we don't have compass .compass_shown TYA : ORA.l CompassCountDisplay : STA.l CompassCountDisplay .done RTS ;-------------------------------------------------------------------------------- FlagMapCount: CMP.w #$0002 : BEQ .mapShown LDA.l MapMode : AND.w #$00FF : BEQ .mapShown LDA.l MapField : AND.l DungeonItemMasks, X : BEQ .done ; skip if we don't have map .mapShown TYA : ORA.l MapCountDisplay : STA.l MapCountDisplay .done RTS ;-------------------------------------------------------------------------------- DungeonItemIDMap: ; Maps lower four bits of our new dungeon items to DungeonID dw $FFFF dw $FFFF dw $001A ; GT dw $0018 ; TR dw $0016 ; TT dw $0014 ; TH dw $0012 ; IP dw $0010 ; SW dw $000E ; MM dw $000C ; PD dw $000A ; SP dw $0008 ; CT dw $0006 ; DP dw $0004 ; EP dw $0002 ; HC dw $0000 ; Sewers PendantMasks: db $04, 01, 02