;================================================================================ ; Utility Functions ;================================================================================ ; GetSpriteTile ; in: A - Loot ID ; out: A - Sprite GFX ID ;-------------------------------------------------------------------------------- GetSpriteID: JSL AttemptItemSubstitution JSR ResolveLootID CMP.b #$6D : BEQ .server_F0 ; Server Request F0 CMP.b #$6E : BEQ .server_F1 ; Server Request F1 CMP.b #$6F : BEQ .server_F2 ; Server Request F2 BRA .normal .server_F0 JSL ItemVisualServiceRequest_F0 BRA .normal .server_F1 JSL ItemVisualServiceRequest_F1 BRA .normal .server_F2 JSL ItemVisualServiceRequest_F2 .normal PHX TAX : LDA.l ItemReceipts_graphics, X ; look up item gfx PLX RTL ;-------------------------------------------------------------------------------- ; GetSpritePalette ; in: A - Loot ID ; out: A - Palette ;-------------------------------------------------------------------------------- GetSpritePalette: JSL AttemptItemSubstitution JSR ResolveLootID .resolved TAX LDA.l SpriteProperties_standing_palette, X : BIT #$80 : BNE .load_palette ASL RTL .load_palette JSL LoadItemPalette ASL RTL ;-------------------------------------------------------------------------------- ; PrepDynamicTile ;-------------------------------------------------------------------------------- 20/8477 PrepDynamicTile: PHX : PHY : PHB LDA.l RemoteItems : BEQ .notRemote LDA.w SprItemReceipt, X : CMP.l !MULTIWORLD_SCOUTREPLY_LOCATION : BNE ++ LDA.l !MULTIWORLD_SCOUTREPLY_PLAYER : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID LDA.l !MULTIWORLD_SCOUTREPLY_ITEM STA.w SprItemReceipt, X BRA .notRemote ++ STA.l !MULTIWORLD_SCOUT_LOCATION LDA.b #$00 : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID LDA.b #$6B : STA.w SprItemReceipt, X ; make it a power star, I guess .notRemote JSR ResolveLootID - JSR ResolveBeeTrap JSR LoadDynamicTileOAMTable CMP.b #$34 : BCC + : CMP.b #$36+1 : BCS + : BRA ++ ; if rupees, don't draw to OAM + JSL TransferItemReceiptToBuffer_using_ReceiptID SEP #$30 ++ LDA.b #$00 : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID ; clear player id PLB : PLY : PLX RTL .loot_resolved PHX : PHY : PHB BRA - ;-------------------------------------------------------------------------------- ; ResolveBeeTrap ; In: A - Loot ID ; Out: A - Resolved Loot ID ;-------------------------------------------------------------------------------- ResolveBeeTrap: PHA LDA.b #$00 : STA.l BeeTrapDisguise ; clear it LDA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID : BNE .skip LDA.w SkipBeeTrapDisguise : BEQ + .skip STZ.w SkipBeeTrapDisguise PLA : RTS + PLA CMP.b #$D0 : BNE + JSL GetRandomInt : AND.b #$3F BNE ++ : LDA.b #$49 : ++ CMP.b #$26 : BNE ++ : LDA.b #$6A : ++ STA.l BeeTrapDisguise + RTS ResolveBeeTrapLong: JSR ResolveBeeTrap RTL ;-------------------------------------------------------------------------------- ; LoadDynamicTileOAMTable ; in: SprItemReceipt,X - Loot ID ; out: A - Loot ID ;-------------------------------------------------------------------------------- 20/847B LoadDynamicTileOAMTable: PHP REP #$30 LDA.w #$0000 : STA.l SpriteOAM : STA.l SpriteOAM+2 LDA.w #$0200 : STA.l SpriteOAM+6 LDA.l BeeTrapDisguise : AND.w #$00FF : BNE + LDA.w SprItemReceipt,X : AND.w #$00FF + LDY.w #$0024 PHX : ASL : TAX LDA.l InventoryTable_properties, X : BIT.w #$8000 : BEQ + LDA.l VRAMAddressOffset, X : TAY + TYA : STA.l SpriteOAM+4 PLX SEP #$30 LDA.l BeeTrapDisguise : BNE + LDA.w SprItemReceipt,X + JSL GetSpritePalette_resolved STA.l SpriteOAM+5 : STA.l SpriteOAM+13 PHX LDA.l SpriteProperties_standing_width,X : BEQ .narrow BRA .done .narrow REP #$20 LDA.w #$0400 : STA.l SpriteOAM+7 : STA.l SpriteOAM+14 LDA.w #$0000 : STA.l SpriteOAM+14 LDA.w #$0800 : STA.l SpriteOAM+9 TYA : XBA : AND.w #$FF00 : ADC.w #$1000 : STA.l SpriteOAM+11 SEP #$20 LDA.b #$04 : STA.l SpriteOAM .done TXA PLX PLP RTS ;-------------------------------------------------------------------------------- ; DrawDynamicTile ; in: A - Loot ID ; out: A - OAM Slots Taken ;-------------------------------------------------------------------------------- ; This wastes two OAM slots if you don't want a shadow - fix later - I wrote "fix later" over a year ago and it's still not fixed (Aug 6, 2017) - lol (May 25th, 2019) ;-------------------------------------------------------------------------------- 2084B8 DrawDynamicTile: JSR PrepDrawRemoteItemSprite PHX TAX LDA.l BeeTrapDisguise : BEQ + TAX + LDA.l SpriteProperties_standing_width,X : BEQ .narrow .full PLX LDA.b #$01 : STA.b Scrap06 LDA.b #$0C : JSL OAM_AllocateFromRegionC LDA.b #$02 : PHA BRA .draw .narrow PLX LDA.b #$02 : STA.b Scrap06 LDA.b #$10 : JSL OAM_AllocateFromRegionC LDA.b #$03 : PHA .draw LDA.b #SpriteOAM>>0 : STA.b Scrap08 LDA.b #SpriteOAM>>8 : STA.b Scrap09 STZ.b Scrap07 LDA.b #$7E : PHB : PHA : PLB LDA.b #$01 : STA.l SpriteSkipEOR JSL Sprite_DrawMultiple_quantity_preset LDA.b #$00 : STA.l SpriteSkipEOR PLB LDA.b OAMPtr : !ADD.b #$08 : STA.b OAMPtr ; leave the pointer in the right spot to draw the shadow, if desired LDA.b OAMPtr+2 : INC #2 : STA.b OAMPtr+2 PLA RTL ;-------------------------------------------------------------------------------- DrawDynamicTileNoShadow: JSR PrepDrawRemoteItemSprite PHX TAX LDA.l SpriteProperties_standing_width,X : BEQ .narrow .full PLX LDA.b #$01 : STA.b Scrap06 LDA.b #$04 : JSL OAM_AllocateFromRegionC BRA .draw .narrow PLX LDA.b #$02 : STA.b Scrap06 LDA.b #$08 : JSL OAM_AllocateFromRegionC .draw LDA.b #SpriteOAM>>0 : STA.b Scrap08 LDA.b #SpriteOAM>>8 : STA.b Scrap09 STZ.b Scrap07 LDA.b #$7E : PHB : PHA : PLB LDA.b #$01 : STA.l SpriteSkipEOR JSL Sprite_DrawMultiple_quantity_preset LDA.l Bob : BNE + : LDA.b #$00 : STA.l SpriteSkipEOR : + ; Bob fix is conditional PLB LDA.b OAMPtr : !ADD.b #$08 : STA.b OAMPtr LDA.b OAMPtr+2 : INC #2 : STA.b OAMPtr+2 RTL ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- PrepDrawRemoteItemSprite: PHA LDA.l RemoteItems : BEQ + PLA CMP.l !MULTIWORLD_SCOUTREPLY_LOCATION : BNE ++ LDA.l !MULTIWORLD_SCOUT_LOCATION : BEQ +++ LDA.l !MULTIWORLD_SCOUTREPLY_LOCATION STA.l SprItemReceipt, X JSL PrepDynamicTile LDA.b #$00 BRA ++ +++ LDA.l !MULTIWORLD_SCOUTREPLY_PLAYER : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID LDA.l !MULTIWORLD_SCOUTREPLY_ITEM RTS ++ STA.l !MULTIWORLD_SCOUT_LOCATION LDA.b #$00 : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID LDA.b #$6B RTS + PLA RTS ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- LoadModifiedTileBufferAddress: PHA LDA.l TileUploadOffsetOverride : BEQ + TAX LDY.w #$0002 LDA.w #$0000 : STA.l TileUploadOffsetOverride BRA .done + LDX.w #$2D40 LDY.w #$0002 .done PLA RTL ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ; Sprite_IsOnscreen ; in: X - Sprite Slot ; out: Carry - 1 = On Screen, 0 = Off Screen ;-------------------------------------------------------------------------------- Sprite_IsOnscreen: JSR .check_sprite BCS + REP #$20 LDA.b BG2H : PHA : !SUB.w #$0F : STA.b BG2H LDA.b BG2V : PHA : !SUB.w #$0F : STA.b BG2V SEP #$20 JSR .check_sprite REP #$20 PLA : STA.b BG2V PLA : STA.b BG2H SEP #$20 + RTL .check_sprite LDA.w SpritePosXLow, X : CMP.b BG2H LDA.w SpritePosXHigh, X : SBC.b BG2H+1 : BNE .offscreen LDA.w SpritePosYLow, X : CMP.b BG2V LDA.w SpritePosYHigh, X : SBC.b BG2V+1 : BNE .offscreen SEC RTS .offscreen CLC RTS ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ; Sprite_GetScreenRelativeCoords: ; out: $00.w Sprite Y ; out: $02.w Sprite X ; out: $06.b Sprite Y Relative ; out: $07.b Sprite X Relative ;-------------------------------------------------------------------------------- ; Copied from bank $06 ;-------------------------------------------------------------------------------- Sprite_GetScreenRelativeCoords: STY.b Scrap0B STA.b Scrap08 LDA.w SpritePosYLow, X : STA.b Scrap00 !SUB.b BG2V : STA.b Scrap06 LDA.w SpritePosYHigh, X : STA.b Scrap01 LDA.w SpritePosXLow, X : STA.b Scrap02 !SUB.b BG2H : STA.b Scrap07 LDA.w SpritePosXHigh, X : STA.b Scrap03 RTL ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ; SkipDrawEOR - Shims in Bank05.asm : 2499 ;-------------------------------------------------------------------------------- SkipDrawEOR: LDA.l SpriteSkipEOR : BEQ .normal LDA.w #$0000 : STA.l SpriteSkipEOR LDA.w #$0F00 : TRB.b Scrap04 .normal LDA.b (Scrap08), Y : EOR.w Scrap04 ; thing we wrote over RTL ;-------------------------------------------------------------------------------- ; WriteVRAMStripe ; in: A(w) - VRAM Destination ; in: X(w) - Length in Tiles ; in: Y(w) - Word to Write ;-------------------------------------------------------------------------------- WriteVRAMStripe: PHX LDX.w GFXStripes ; get pointer AND.w #$7F : STA.w GFXStripes+2, X : INX #2 ; set destination PLA : ASL : AND.w #$7FFF : ORA.w #$7000 : STA.w GFXStripes+2, X : INX #2 ; set length and enable RLE TYA : STA.w GFXStripes+2, X : INX #2 ; set tile SEP #$20 ; set 8-bit accumulator LDA.b #$FF : STA.w GFXStripes+2, X STX.w GFXStripes LDA.b #01 : STA.b NMISTRIPES REP #$20 ; set 16-bit accumulator RTL ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ; WriteVRAMBlock ; in: A(w) - VRAM Destination ; in: X(w) - Length in Tiles ; in: Y(w) - Address of Data to Copy ;-------------------------------------------------------------------------------- WriteVRAMBlock: PHX LDX.w GFXStripes ; get pointer AND.w #$7F : STA.w GFXStripes+2, X : INX #2 ; set destination PLA : ASL : AND.w #$3FFF : STA.w GFXStripes+2, X : INX #2 ; set length PHX TYX ; set X to source PHA TXA : !ADD.w #$1002 : TAY ; set Y to dest PLA ;A is already the value we need for mvn MVN $7F7E ; currently we transfer from our buffers in 7F to the vram buffer in 7E !ADD 1, s ; add the length in A to the stack pointer on the top of the stack PLX : TAX ; pull and promptly ignore, copying the value we just got over it SEP #$20 ; set 8-bit accumulator LDA.b #$FF : STA.w GFXStripes+$02, X STX.w GFXStripes LDA.b #01 : STA.w NMISTRIPES REP #$20 ; set 16-bit accumulator RTL ;-------------------------------------------------------------------------------- ;Byte 1 byte 2 Byte 3 byte 4 ;Evvvvvvv vvvvvvv DRllllll llllllll ; ;E if set indicates that this is not a header, but instead is the terminator byte. Only the topmost bit matters in that case. ;The v's form a vram address. ;if D is set, the dma will increment the vram address by a row per word, instead of incrementing by a column (1). ;R if set enables a run length encoding feature ;the l's are the number of bytes to upload minus 1 (don't forget this -1, it is important) ; ;This is then followed by the bytes to upload, in normal format. ;RLE feature: ;This feature makes it easy to draw the same tile repeatedly. If this bit is set, the length bits should be set to 2 times the number of copies of the tile to upload. (Without subtracting 1!) ;It is followed by a single tile (word). Combining this this with the D bit makes it easy to draw large horizontal or vertical runs of a tile without using much space. Geat for erasing or drawing horizontal or verical box edges. ;================================================================================ DynamicDrawCleanup: PHA REP #$20 LDA.w #$F000 STA.w OAMBuffer STA.w OAMBuffer+$04 STA.w OAMBuffer+$08 STA.w OAMBuffer+$0C STZ.w OAMBuffer+$02 STZ.w OAMBuffer+$06 STZ.w OAMBuffer+$0A STZ.w OAMBuffer+$0E SEP #$20 PLA RTL ;------------------------------------------------------------------------------ CheckReceivedItemPropertiesBeforeLoad: PHX LDX.w CurrentSpriteSlot LDA.w AncillaID,X : CMP.b #$29 : BEQ .falling_sprite PLX LDA.b RoomIndex : BEQ .normalCode CMP.b #$09 : BNE + ; potion shop to skip RoomFade check to avoid bad palette issue LDA.b RoomIndex+1 : CMP.b #$01 : BEQ .normalCode + LDA.l RoomFade : BNE .load_palette .normalCode LDA.l SpriteProperties_chest_palette,X : BIT #$80 : BNE .load_palette RTL .load_palette JSL LoadItemPalette RTL .falling_sprite PLX LDA.l SpriteProperties_standing_palette,X : BIT #$80 : BNE .load_palette RTL ;------------------------------------------------------------------------------ LoadItemPalette: ; In: X - Loot ID ; Out: A - Sprite palette index PHX : PHY : PHB LDA.b #PalettesVanillaBank>>16 : STA.b Scrap0C PEA.w $7E00 PLB : PLB REP #$30 TXA : ASL : TAX LDA.l SpriteProperties_palette_addr,X : STA.b Scrap0A LDY.w #$000E JSR AuxPaletteCheck : BCS .aux LDA.w TransparencyFlag : BNE .SP05 - LDA.b [Scrap0A], Y STA.w PaletteBuffer+$0170,Y DEY #2 BPL - LDA.w #$0003 BRA .done .SP05 - LDA.b [Scrap0A], Y STA.w PaletteBuffer+$01B0,Y DEY #2 BPL - LDA.w #$0005 .done SEP #$30 PLB : PLY : PLX INC.b NMICGRAM RTL .aux LDA.w TransparencyFlag : BNE .SP05_aux - LDA.b [Scrap0A], Y STA.w PaletteBufferAux+$0170,Y DEY #2 BPL - LDA.w #$0003 BRA .done .SP05_aux - LDA.b [Scrap0A], Y STA.w PaletteBufferAux+$01B0,Y DEY #2 BPL - LDA.w #$0005 BRA .done TransferVRAMStripes: JSL TransferNewNameStripes JSL DoDungeonMapBossIcon LDA.b NMISTRIPES : CMP.b #$01 ; What we wrote over RTL ItemReceiptWidthCheck: PHX LDX.w CurrentSpriteSlot LDA.w AncillaID,X : CMP.b #$29 : BEQ .falling_sprite PLX LDA.l SpriteProperties_chest_width, X RTL .falling_sprite PLX LDA.l SpriteProperties_standing_width, X RTL AuxPaletteCheck: ; Out: c - write to aux palette buffer if set, main buffer if unset. ; ; We have to put an item's palette in the aux buffer in rooms where standing ; item gfx are loaded in the middle of a fade-in/out such as the spiral staircase ; fade for GT torch room and the Hera cage. PHX SEP #$30 LDA.w ItemReceiptMethod : BNE .main_buffer ; Never use aux if we're actually receiving an item LDA.b RoomIndex : CMP.b #$8C : BEQ .aux_buffer ; GT torch/Hope room CMP.b #$87 : BEQ .aux_buffer ; Hera cage/basement .main_buffer REP #$31 PLX RTS .aux_buffer SEC REP #$30 PLX RTS CountBits: ; In: A - value to count bits set in ; Out: A - number of bits set ; Flexible to use with 8 or 16-bit mode PHX : TAX PHY : PHP SEP #$20 LDA.b 1,S : BIT.b #$20 : BNE + PLP : TXA : LDX.w #$000F : LDY.w #$0000 BRA ++ + PLP : TXA : LDX.b #$07 : LDY.b #$00 ++ - LSR : BCC + INY + DEX : BPL - TYA : PLY : PLX RTL