;Acts like $25 (to prevent the coin from pushing (dropped) sprites outwards). !RAM_CUSTBLOCK = $7EC275 ; 10 bytes, free ram used for custom map16 changes ;options: !CoinBrick = 1 ;>Will switch between a coin and a block? 0 = no, 1 = yes. !Switch = $14AD ;>What ram address will switch this block. !invert = 0 ;>Invert flags, 0 = if ram is clear, then brick, otherwise coin, 1 = vice versa. !SpinShatter = 1 ;>Breakable from above? 0 = no, 1 = yes. db $42 JMP MarioBelow : JMP MarioAbove : JMP MarioSide : JMP SpriteV : JMP SpriteH JMP MarioCape : JMP MarioFireBall : JMP TopCorner : JMP HeadInside : JMP BodyInside BOUNCE: ; Code for spawning a bounce block sprite is here PHY ; save Y LDA #$0F ; Clear low nybble of these (so bounce block is positioned correctly) TRB $98 ; TRB $9A ; LDY #$03 ; find a free bounce sprite slot GET_FREE_SLOT: LDA $1699,y ; check status BEQ GOT_ONE ; if empty, we got one DEY BPL GET_FREE_SLOT DEC $18CD ; decrement counter used by SMW BPL BOUNCE_0 LDA #$03 ; reset it if needed STA $18CD ; BOUNCE_0: LDY $18CD JSR RESET_TURNBLOCK ; LDY $18CD ; $18CD holds the oldest bounce sprite index, in case more than 4 are running at one time GOT_ONE: LDA #$0C ; bounce block properties. YXPPCCCT STA $1901,Y ; set to palette E, first sprite page, no x/y flip LDA #$08 ; Set bounce block sprite number STA $1699,y ; 8+ = custom LDA #$00 ; make it run init routine STA $169D,Y ; 1-FF = no init routine LDA $9A ; X (low) STA $16A5,Y ; store to bounce sprite table LDA $9B ; X (high) STA $16AD,Y ; LDA $98 ; Y (low) STA $16A1,Y ; LDA $99 ; Y (high) STA $16A9,Y ; LDA $1933 ; layer being processed LSR ; Used in bounce sprite code ROR ; determines which layer to write the block to after done animating STA $08 ; store to scratch LDA #$00 ; set x speed STA $16B5,Y ; LDA #$C0 ; set y speed STA $16B1,Y ; LDA #$00 ; movement table index. 0 = up, 1 = right, 2 = left, 3 = down ORA $08 ; add in layer bit determined earlier STA $16C9,Y ; LDA #$1C ; set block to turn into = spawn block from table STA $16C1,Y ; 1C-FF will not use the regular table. Instead you must set it in a table later LDA #$08 ; set time to show block STA $16C5,Y ; PHX ; get table index for custom map16 changes TYA ; this allows your sprite to change the block back after it finishes animating ASL ; could also be used to change it to something else TAX ; REP #$20 ; 16 bit A LDA $03 ; map16 number STA !RAM_CUSTBLOCK,x ; store to custom table. Will change to this block after the bounce sprite finishes SEP #$20 ; 8 bit A PLX ; done with bounce sprite spawning PHK PER $0006 ; hit sprites above block PEA $94F3 JML $0286ED ;LDA #$09 ; Replace block with invisible solid block ;STA $9C ; ;JSL $00BEB0 ; ; | this works just as well as the code above, but used for example purposes ; | normally changing the map16 is limited to a small number of blocks defined within SMW ; | or inserting a huge chunk of code into your block ; v this allows for changing to any map16 without fuss LDA #$FF ; Replace block with map16 #152 (invisible solid block) for the duration of the bounce STA $9C ; FF = custom number LDA #$52 ; low byte of map16 STA !RAM_CUSTBLOCK+8 ; LDA #$01 ; high byte STA !RAM_CUSTBLOCK+9 ; LDX #$04 ; get custom block number set above JSL $00BEB0 ; MUST set x to 4 if you use this method. PLY ; restore y RETURN2: RTL SHATTER1: ; shatter routine for Mario hitting block. Standard stuff from now on... ; and badly written stuff too LDA #$0F TRB $98 TRB $9A PHY ;>don't act like 125 PHK PER $0006 ; hit sprites above block PEA $94F3 JML $0286ED PLY JMP SHATTER2 ;------------------------------------------------------------------------------------ MarioBelow: if !CoinBrick != 0 if !invert = 0 LDA !Switch ;\If switch is ON, then coin. BEQ + ;| JMP Coin ;/ + else LDA !Switch ;\If switch is OFF, then coin. BNE + ;| JMP Coin ;/ + endif endif LDY #$01 LDA #$30 STA $1693 LDA $19 ; powerup BNE SHATTER1 ; shatter block if not small JMP BOUNCE ; bounce if small ;------------------------------------------------------------------------------------ SpriteV: if !CoinBrick != 0 if !invert = 0 LDA !Switch ;\If switch is ON, then coin. BEQ + ;| JMP PassableCoin ;/ + else LDA !Switch ;\If switch is OFF, then coin. BNE + ;| JMP PassableCoin ;/ + endif endif LDY #$01 LDA #$30 STA $1693 LDA $AA,x ; if moving downwards, return BPL RETURN2 ; LDA $14C8,X ; make sure it's in state 9 or above CMP #$09 ; (^yes, its "dropped" if kicked upwards.) BCC RETURN2 ; shatter if movement upward and state 9-c LDA #$10 ; set y speed STA $AA,x ; LDA $0F ;\Prevent sprite from being shifted sideways. PHA ;/ LDA $98 PHA LDA $99 ; preserve these PHA LDA $9A PHA LDA $9B PHA PHY ; LDA $0A ; $0A-D hold the x/y of sprite contact ; AND #$F0 ; have to clear the low nybble much like $98-9B ; STA $9A ; LDA $0B ; STA $9B ; LDA $0C ; AND #$F0 ; SEC ; SBC #$08 ; STA $98 ; move y up for this (so sprites thrown below the block don't get hit) ; LDA $0D ; SBC #$00 ; STA $99 %sprite_block_position() PHK PER $0006 ; hit sprites above block PEA $94F3 JML $0286ED LDA $0C AND #$F0 ; get real y for everything else STA $98 LDA $0D STA $99 BRA SPRITE_SHATTER2 ;------------------------------------------------------------------------------------ SpriteH: if !CoinBrick != 0 if !invert = 0 LDA !Switch ;\If switch is ON, then coin. BEQ + ;| JMP PassableCoin ;/ + else LDA !Switch ;\If switch is OFF, then coin. BNE + ;| JMP PassableCoin ;/ + endif endif LDY #$01 LDA #$30 STA $1693 LDA $14C8,x ; sprite status CMP #$09 ; shatter if carriable BEQ SPRITEH_CONT CMP #$0A ; return if not "kicked" BEQ + RTL ; shatter if so (branch out of range) + BRA SPRITEH_1 SPRITEH_CONT: LDA $B6,x ; x speed. don't shatter if between -#$08 and #$08 BMI SPRITEH_0 CMP #$08 BCS SPRITEH_1 RTL SPRITEH_0: CMP #$F8 BCC SPRITEH_1 RTL SPRITEH_1: LDA $0F ;\Prevent sprite from being shifted sideways. PHA ;/ LDA $98 PHA LDA $99 ; preserve these PHA LDA $9A PHA LDA $9B PHA SPRITE_SHATTER: PHY ; LDA $0A ; $0A-D hold the x/y of sprite contact ; AND #$F0 ; have to clear the low nybble much like $98-9B ; STA $9A ; LDA $0B ; STA $9B ; LDA $0C ; AND #$F0 ; STA $98 ; LDA $0D ; STA $99 %sprite_block_position() SPRITE_SHATTER2: ; PHB ; LDA #$02 ; PHA ; PLB ; LDA #$00 ; set palette number ; JSR $028663 ; breaking effect ; PLB ; LDA #$02 ; Replace block with blank tile ; STA $9C ; JSL $00BEB0 %shatter_block() PLY PLA STA $9B PLA ;restore these STA $9a PLA STA $99 PLA STA $98 PLA STA $0F RTL ;------------------------------------------------------------------------------------ MarioCape: if !CoinBrick != 0 if !invert = 0 LDA !Switch ;\If switch is ON, then don't break the coin. BEQ + ;| JMP RETURN ;/ + else LDA !Switch ;\If switch is OFF, then don't break the coin. BNE + ;| JMP RETURN ;/ + endif endif ; PHY LDA #$0F TRB $98 TRB $9A SHATTER2: ; PHB ; LDA #$02 ; PHA ; PLB ; LDA #$00 ; set palette number to default (00). Anything else = rainbow ; JSL $028663 ; breaking effect ; PLB ; LDA #$02 ; Replace block with blank tile ; STA $9C ; JSL $00BEB0 %shatter_block() ; PLY RTL ;------------------------------------------------------------------------------------ MarioFireBall: ;>fireballs should go through coins! if !CoinBrick != 0 if !invert = 0 LDA !Switch ;\If switch is ON, then pass through coin. BEQ + ;| JMP PassableCoin ;/ + else LDA !Switch ;\If switch is OFF, then pass through coin. BNE + ;| JMP PassableCoin ;/ + endif endif ;------------------------------------------------------------------------------------ if !SpinShatter != 0 MarioAbove: TopCorner: if !CoinBrick != 0 if !invert = 0 LDA !Switch ;\If switch is ON, then coin. BEQ + ;| JMP Coin ;/ + else LDA !Switch ;\If switch is OFF, then coin. BNE + ;| JMP Coin ;/ + endif endif LDY #$01 LDA #$30 STA $1693 LDA $7D ;\If Y speed is negative (#$80~#$FF, going up) BMI RETURN ;/then return LDA $19 ;\If powerup status is small mario, then return. BEQ RETURN ;/ LDA $140D ;\If not spinjumping, return. BEQ RETURN ;/ LDA #$D0 ;\Bounce up like a turn block STA $7D ;/ JMP SHATTER1 ;>shatter the block. endif ;------------------------------------------------------------------------------------ BodyInside: HeadInside: MarioSide: if !SpinShatter == 0 MarioAbove: TopCorner: endif if !CoinBrick != 0 if !invert = 0 LDA !Switch ;\If switch is ON, then coin. BEQ + ;| JMP Coin ;/ + else LDA !Switch ;\If switch is OFF, then coin. BNE + ;| JMP Coin ;/ + endif endif LDY #$01 LDA #$30 STA $1693 RETURN: RTL RESET_TURNBLOCK: ; taken from $0287B0 LDA $9A PHA LDA $9B ; preserve some stuff PHA LDA $98 PHA LDA $99 PHA LDA $16A5,Y ; reset turnblock STA $9A LDA $16AD,Y STA $9B LDA $16A1,Y CLC ADC #$0C AND #$F0 STA $98 LDA $16A9,Y ADC #$00 STA $99 LDA $16C1,Y STA $9C LDA $03 PHA LDA $04 PHA LDA $05 PHA LDA $06 PHA LDA $07 PHA JSL $00BEB0 ; generate turnblock tile PLA STA $07 PLA STA $06 PLA ; restore crap STA $05 PLA STA $04 PLA STA $03 PLA STA $99 PLA STA $98 PLA STA $9B PLA STA $9A RTS ; return Coin: INC $13CC ;>in case the player grabs 2 coins simultaneously LDA #$01 ;\coin sfx STA $1DFC ;/ %erase_block() ;>delete block ;%give_points() ;>give player points (only happens if you get coins from ? and turn blocks) ;glitter PHY ;>protect tile behavor PHK ;\the JSL-RTS trick. PEA.w .jslrtsreturn-1 ;|Thanks LX5 and imamelia! PEA.w $84CF-1 ;/ JML $00FD5A ;>glitter subroutine .jslrtsreturn PLY ;>end protect to avoid stack overflow. PassableCoin: LDY #$00 ;\Become passable (coins need this). LDA #$25 ;| STA $1693 ;/ RTL print "A brick block."