Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Adapted from Yoshi's Island Chomp Rock (NON DYNAMIC VERSION)
- ; Programmed by SMWEdit, modified by ICB. Give credit to both if used, please.
- ;
- ;This is a wooden crate that Mario can push left or right and then stand on top
- ;of to get an extra boost. It also goes up hills and kills sprites while it's
- ;moving. It moves a couple of tiles before stopping and repeats
- ;after a few seconds, mimicking the giant pushable blocks in Zelda:OOT, MM,
- ;and Wind Waker. Comes with ExGFX image which you will want to paste into your
- ;SP4 file if you are using other SP4 sprites for a particular level, or just use the
- ;SP4 by itself if you want.
- ;
- ; Uses first extra bit: NO
- ;
- ; uses SP4
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- SPRITEKILLSND = $37
- OFFSET = $1528
- STARTOFFSET = $1504
- FLIPXY = $151C
- STANDINGLASTFRAME = $1626
- LASTXLO = $1534
- LASTXHI = $1570
- LASTYLO = $1594
- LASTYHI = $1602
- SPRXTMP = $04
- SPRYTMP = $06
- SPRXTMP2 = $08
- SPRYTMP2 = $0A
- GENERICTMP = $0C
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; INIT and MAIN JSL targets
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- dcb "INIT"
- LDA $E4,x
- STA STARTOFFSET,x
- JSR STORE_POS
- RTL
- dcb "MAIN"
- PHB
- PHK
- PLB
- JSR SPRITE_ROUTINE
- LDA $1588,x
- AND #$04
- BNE a
- STZ $B6,x
- a:
- PLB
- RTL
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; SPRITE_ROUTINE
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- STAND_YPOS = $FFD0 ; Y position of platform relative to sprite
- STAND_XMIN = $FFEC ; Left X boundary
- STAND_XMAX = $0012 ; Right X boundary
- LPUSH_YMIN = $FFD8 ; Y position of top of left push area
- LPUSH_YMAX = $0000 ; Y position of bottom of left push area
- LPUSH_XMIN = $FFE1 ; X position for pushing
- LPUSH_XMAX = $0000 ; extent (forward) of interaction field
- RPUSH_YMIN = $FFD8 ; Y position of top of left push area
- RPUSH_YMAX = $0000 ; Y position of bottom of left push area
- RPUSH_XMIN = $000F ; X position for pushing
- RPUSH_XMAX = $0001 ; extent (backward) of interaction field
- LROLL_XMAX = $FFEA ; max for standing and making rock roll left
- RROLL_XMAX = $0015 ; max for standing and making rock roll right
- STORE_POS LDA $E4,x ; \
- STA LASTXLO,x ; | store current position
- LDA $14E0,x ; | to sprite tables for
- STA LASTXHI,x ; | use next time sprite
- LDA $D8,x ; | routine is called.
- STA LASTYLO,x ; | It's used for moving mario
- LDA $14D4,x ; | while he's standing on it
- STA LASTYHI,x ; /
- RETURN1 RTS
- SPRITE_ROUTINE JSR SUB_GFX
- LDA $14C8,x ; \ return if
- CMP #$08 ; | sprite
- BNE RETURN1 ; / status != 8
- LDA $9D ; \ return if
- BNE RETURN1 ; / sprites locked
- LDA $13F9
- BNE RETURN1
- JSR SUB_OFF_SCREEN_X0 ; only process sprite while on screen
- JSR POSOFFSETSTART ; interaction improvement offset
- LDA $187A ; \ don't shift
- BEQ NOYOSHI ; / if not on Yoshi
- LDA $96 ; \
- CLC ; | offset Y
- ADC #$10 ; | by #$10
- STA $96 ; | again to
- LDA $97 ; | compensate
- ADC #$00 ; | for yoshi
- STA $97 ; /
- NOYOSHI
- LDA LASTXLO,x ; \
- STA SPRXTMP2 ; | store sprite's old
- LDA LASTXHI,x ; | X and Y positions
- STA SPRXTMP2+1 ; | into scratch
- LDA LASTYLO,x ; | RAM for use
- STA SPRYTMP2 ; | in some of the
- LDA LASTYHI,x ; | following code
- STA SPRYTMP2+1 ; /
- LDA $E4,x ; \
- STA SPRXTMP ; | store sprite X
- LDA $14E0,x ; | and Y position
- STA SPRXTMP+1 ; | into scratch
- LDA $D8,x ; | RAM for use
- STA SPRYTMP ; | in some of the
- LDA $14D4,x ; | following code
- STA SPRYTMP+1 ; /
- LDA $E4,x ; \
- SEC ; | set offsets
- SBC STARTOFFSET,x ; | for rotation
- PHA ; |
- AND #%00001111 ; |
- STA OFFSET,x ; |
- PLA ; |
- AND #%00000000 ; |
- STA FLIPXY,x ; /
- LDA STANDINGLASTFRAME,x ; \ check if mario was
- BEQ NOT_STANDING_LAST_FRAME ; / standing last frame
- LDA $77 ; \ don't move mario if
- AND #%00000011 ; | he is hitting the side
- BNE NO_MOVE_MARIO ; / of an object
- PHP ; \
- REP #%00100000 ; | move mario
- LDA SPRXTMP ; | 2 pixels for
- SEC ; | every pixel
- SBC SPRXTMP2 ; | the sprite
- ASL A ; | moves
- CLC ; |
- ADC $94 ; |
- STA $94 ; |
- PLP ; /
- NO_MOVE_MARIO
- STZ STANDINGLASTFRAME,x ; zero this in case it won't be set this frame
- NOT_STANDING_LAST_FRAME
- BRA NO_NO_STAND_JMP ; \ this is used when a standard
- NO_STAND_JMP JMP NO_STAND ; / branch is out of range
- NO_NO_STAND_JMP
- LDA $7D ; \ don't stand on if
- BMI NO_STAND_JMP ; / mario not moving down
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRYTMP ; get sprite's Y position
- CLC ; \ offset to get minimum
- ADC.w #STAND_YPOS-1 ; / Y area for standing
- CMP $96 ; compare with mario's Y position
- BCS NO_STAND_1 ; don't execute next command if area is under mario
- LDY #$01 ; set Y register = 1
- NO_STAND_1 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set
- BEQ NO_STAND_JMP ; / then don't stand
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRYTMP ; get sprite's Y position
- CLC ; \ offset to get maximum
- ADC.w #STAND_YPOS+5 ; / Y area for standing
- CMP $96 ; compare with mario's Y position
- BCC NO_STAND_2 ; don't execute next command if area is over mario
- LDY #$01 ; set Y register = 1
- NO_STAND_2 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set
- BEQ NO_STAND_JMP ; / then don't stand
- PHP ; back up processor bits
- REP #%00100000 ; 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get minimum
- ADC.w #STAND_XMIN ; / X area for standing
- BPL CMP1 ; \ if area goes backward past
- LDA.w #$0000 ; / level start then assume zero
- CMP1 CMP $94 ; compare with mario's X position
- BCS NO_STAND_3 ; don't execute next command if area is after mario
- LDY #$01 ; set Y register = 1
- NO_STAND_3 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set
- BEQ NO_STAND_JMP ; / then don't stand
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get maximum
- ADC.w #STAND_XMAX ; / X area for standing
- BPL CMP2 ; \ if X area goes backward past
- LDA.w #$0000 ; / level start then assume zero
- CMP2 CMP $94 ; compare with mario's X position
- BCC NO_STAND_4 ; don't execute next command if area is before mario
- LDY #$01 ; set Y register = 1
- NO_STAND_4 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set
- BEQ NO_STAND_JMP ; / then don't stand
- PHP ; \
- REP #%00100000 ; | offset mario's
- LDA SPRYTMP ; | Y position so
- CLC ; | that he is
- ADC.w #STAND_YPOS ; | standing at
- STA $96 ; | specified offset
- PLP ; /
- LDA #$01 ; \ set standing
- STA $1471 ; / mode
- PHP ; back up processor bits
- REP #%00100000 ; 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get maximum X
- ADC.w #LROLL_XMAX ; / area for left stand-rolling
- BPL CMP7 ; \ if area goes backward past
- LDA.w #$0000 ; / level start then assume zero
- CMP7 CMP $94 ; compare with mario's X position
- BCC NO_LROLL_1 ; don't execute next command if area is after mario
- LDY #$01 ; set Y register = 1
- NO_LROLL_1 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set
- BEQ NO_LROLL ; / then don't stand
- LDA $14 ; \
- AND #%00000011 ; | "slowly" increase
- BNE NO_LROLL ; | speed of rock
- DEC $B6,x ; |
- NO_LROLL ; /
- PHP ; back up processor bits
- REP #%00100000 ; 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get maximum X
- ADC.w #RROLL_XMAX+1 ; / area for left stand-rolling
- BPL CMP8 ; \ if area goes backward past
- LDA.w #$0000 ; / level start then assume zero
- CMP8 CMP $94 ; compare with mario's X position
- BCS NO_RROLL_1 ; don't execute next command if area is after mario
- LDY #$01 ; set Y register = 1
- NO_RROLL_1 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set
- BEQ NO_RROLL ; / then don't stand
- LDA $14 ; \
- AND #%00000011 ; | "slowly" increase
- BNE NO_RROLL ; | speed of rock
- INC $B6,x ; |
- NO_RROLL ; /
- LDA #$01 ; \ for the next frame, indicate mario
- STA STANDINGLASTFRAME,x ; / was standing during this frame
- NO_STAND
- BRA NO_NO_LPUSH_JMP ; \ this is used when a standard
- NO_LPUSH_JMP JMP NO_LPUSH ; / branch is out of range
- NO_NO_LPUSH_JMP
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRYTMP ; get sprite's Y position
- CLC ; \ offset to get top
- ADC.w #LPUSH_YMIN-1 ; / boundary for pushing
- CMP $96 ; compare with mario's Y position
- BCS NO_LPUSH_1 ; don't execute next command if area is under mario
- LDY #$01 ; set Y register = 1
- NO_LPUSH_1 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set
- BEQ NO_LPUSH_JMP ; / then don't stand
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRYTMP ; get sprite's Y position
- CLC ; \ offset to get bottom
- ADC.w #LPUSH_YMAX ; / boundary for pushing
- PHY ; back up Y
- LDY $187A ; \
- BEQ NOT_YOSHI1 ; | boundary is lower
- CLC ; | if mario is on Yoshi
- ADC.w #$0010 ; /
- NOT_YOSHI1 LDY $73 ; \
- BNE NOT_BIG1 ; | boundary is lower
- LDY $19 ; | if mario is ducking
- BEQ NOT_BIG1 ; | or if he is not big
- CLC ; |
- ADC.w #$0008 ; /
- NOT_BIG1 PLY ; load backed up Y
- CMP $96 ; compare low boundary with mario's Y position
- BCC NO_LPUSH_2 ; don't execute next command if area is above mario
- LDY #$01 ; set Y register = 1
- NO_LPUSH_2 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set then
- BEQ NO_LPUSH ; / don't push from left
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get left
- ADC.w #LPUSH_XMIN-1 ; / boundary for pushing
- BPL CMP3 ; \ if area goes backwards past
- LDA.w #$0000 ; / level start then assume zero
- CMP3 CMP $94 ; compare with mario's X position
- BCS NO_LPUSH_3 ; don't execute next command if area is after mario
- LDY #$01 ; set Y register = 1
- NO_LPUSH_3 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set then
- BEQ NO_LPUSH ; / don't push from left
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get right
- ADC.w #LPUSH_XMAX ; / boundary for pushing
- BPL CMP4 ; \ if area goes backwards past
- LDA.w #$0000 ; / level start then assume zero
- CMP4 CMP $94 ; compare with mario's X position
- BCC NO_LPUSH_4 ; don't execute next command if area is before mario
- LDY #$01 ; set Y register = 1
- NO_LPUSH_4 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set then
- BEQ NO_LPUSH ; / don't push from left
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDA SPRXTMP ; \
- CLC ; | keep mario at
- ADC.w #LPUSH_XMIN ; | push offset position
- STA $94 ; /
- PLP ; load backed up processor bits
- LDA $14 ; \
- AND #%00010001 ; | "slowly" increase
- BNE NO_INC_SPD_L ; | speed of rock
- INC $B6,x ; |
- NO_INC_SPD_L ; /
- LDA $B6,x ; \
- CMP $7B ; | prevent mario's speed from
- BCS OKX1 ; | exceeding that of the rock
- STA $7B ; /
- OKX1
- LDA $B6,x ; \
- BPL NOT_HITTING_WALL_L ; | if mario is wedged
- LDA $77 ; | in between the rock
- AND #%00000010 ; | and the wall, then
- BEQ NOT_HITTING_WALL_L ; | bounce off of him
- JSR HIT_WALL ; | (so not to kill him)
- NOT_HITTING_WALL_L ; /
- NO_LPUSH
- BRA NO_NO_RPUSH_JMP ; \ this is used when a standard
- NO_RPUSH_JMP JMP NO_RPUSH ; / branch is out of range
- NO_NO_RPUSH_JMP
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRYTMP ; get sprite's Y position
- CLC ; \ offset to get top
- ADC.w #RPUSH_YMIN-1 ; / boundary for pushing
- CMP $96 ; compare with mario's Y position
- BCS NO_RPUSH_1 ; don't execute next command if area is below mario
- LDY #$01 ; set Y register = 1
- NO_RPUSH_1 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set then
- BEQ NO_RPUSH_JMP ; / don't push from right
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRYTMP ; get sprite's Y position
- CLC ; \ offset to get bottom
- ADC.w #RPUSH_YMAX ; / boundary for pushing
- PHY ; back up Y
- LDY $187A ; \
- BEQ NOT_YOSHI2 ; | boundary is lower
- CLC ; | if mario is on Yoshi
- ADC.w #$0010 ; /
- NOT_YOSHI2 LDY $73 ; \
- BNE NOT_BIG2 ; | boundary is lower
- LDY $19 ; | if mario is ducking
- BEQ NOT_BIG2 ; | or if he is not big
- CLC ; |
- ADC.w #$0008 ; /
- NOT_BIG2 PLY ; load backed up Y
- CMP $96 ; compare with mario's Y position
- BCC NO_RPUSH_2 ; don't execute next command if area is above mario
- LDY #$01 ; set Y register = 1
- NO_RPUSH_2 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set then
- BEQ NO_RPUSH ; / don't push from right
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get right
- ADC.w #RPUSH_XMIN ; / boundary for pushing
- BPL CMP5 ; \ if area goes backward past
- LDA.w #$0000 ; / level start then assume zero
- CMP5 CMP $94 ; compare with sprite's X position
- BCC NO_RPUSH_3 ; don't execute next command if area is before mario
- LDY #$01 ; set Y register = 1
- NO_RPUSH_3 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set then
- BEQ NO_RPUSH ; / don't push from right
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDY #$00 ; Y register = 0
- LDA SPRXTMP ; get sprite's X position
- CLC ; \ offset to get left
- ADC.w #RPUSH_XMAX ; / boundary for pushing
- BPL CMP6 ; \ if area goes backward past
- LDA.w #$0000 ; / level start the assume zero
- CMP6 CMP $94 ; compare with sprite's X position
- BCS NO_RPUSH_4 ; don't execute next command if area is before mario
- LDY #$01 ; set Y register = 1
- NO_RPUSH_4 PLP ; load backed up processor bits
- CPY #$00 ; \ if Y is not set then
- BEQ NO_RPUSH ; / don't push from right
- PHP ; back up processor bits
- REP #%00100000 ; set 16 bit A/math
- LDA SPRXTMP ; \
- CLC ; | keep mario at
- ADC.w #RPUSH_XMIN ; | push offset position
- STA $94 ; /
- PLP ; load backed up processor bits
- LDA $14 ; \
- AND #%00010001 ; | "slowly" increase
- BNE NO_INC_SPD_R ; | speed of rock
- DEC $B6,x ; |
- NO_INC_SPD_R ; /
- LDA $B6,x ; \
- CMP $7B ; | prevent mario's speed from
- BCC OKX2 ; | exceeding that of the rock
- STA $7B ; /
- OKX2
- LDA $B6,x ; \
- BMI NOT_HITTING_WALL_R ; | if mario is wedged
- LDA $77 ; | in between the rock
- AND #%00000001 ; | and the wall then
- BEQ NOT_HITTING_WALL_R ; | bounce off of him
- JSR HIT_WALL ; | (so not to kill him)
- NOT_HITTING_WALL_R ; /
- NO_RPUSH
- LDA $B6,x ; \ don't execute following
- BEQ NOT_ROLLING ; / code if rock is not rolling
- JSR POSOFFSETEND ; reverse interaction improvement offset
- JSR KILLSPRITES ; kill sprites
- JSR POSOFFSETSTART ; re-do interaction improvement offset
- LDA $14 ; \
- AND #%01000000 ; | make the rock
- BNE END_SLOWDOWN ; | slow down
- LDA $B6,x ; |
- BPL MINUS ; |
- PLUS INC $B6,x ; |
- BRA END_SLOWDOWN ; |
- MINUS DEC $B6,x ; /
- END_SLOWDOWN
- NOT_ROLLING
- LDA $1588,x ; \
- AND #%00000011 ; | bounce off of
- BEQ NOT_HITTING_WALL ; | walls
- JSR HIT_WALL ; /
- NOT_HITTING_WALL
- LDA $187A ; \ don't shift
- BEQ NOYOSHI2 ; / if not on Yoshi
- LDA $96 ; \ reverse
- SEC ; | offset Y
- SBC #$10 ; | by #$10
- STA $96 ; | again to
- LDA $97 ; | compensate
- SBC #$00 ; | for yoshi
- STA $97 ; /
- NOYOSHI2
- JSR STORE_POS ; store sprite's current position for reference in next frame
- JSR POSOFFSETEND ; reverse interaction improvement offset
- JSL $01802A ; update position based on speed values
- JSL $018032 ; interact with other sprites
- RETURN RTS
- ;; This temporarily offsets mario's and the sprite's
- ;; Y positions so rock doesn't have a push glitch
- ;; when it's at the top of the level
- PERCEPTIONOFFSET = $40
- POSOFFSETSTART LDA $96 ; \
- CLC ; | add specified
- ADC #PERCEPTIONOFFSET ; | offset to
- STA $96 ; | mario
- LDA $97 ; |
- ADC #$00 ; |
- STA $97 ; /
- LDA $D8,x ; \
- CLC ; | add specified
- ADC #PERCEPTIONOFFSET ; | offset to
- STA $D8,x ; | sprite
- LDA $14D4,x ; |
- ADC #$00 ; |
- STA $14D4,x ; /
- RTS ; \
- POSOFFSETEND LDA $96 ; | subtract
- SEC ; | specified
- SBC #PERCEPTIONOFFSET ; | offset from
- STA $96 ; | mario
- LDA $97 ; |
- SBC #$00 ; |
- STA $97 ; /
- LDA $D8,x ; \
- SEC ; | subtract
- SBC #PERCEPTIONOFFSET ; | specified
- STA $D8,x ; | offset from
- LDA $14D4,x ; | sprite
- SBC #$00 ; |
- STA $14D4,x ; /
- RTS
- ;; SPRITE KILLER - kills enemies
- ;; - important note: the reason I only check for "interact with stars/cape/fire/bricks"
- ;; is because some sprites with specially programmed shell interaction have this
- ;; as the only way to tell if they should be killed.
- KILLSPRITES
- LDY #$0C ; load number of times to go through loop
- KILL_LOOP CPY #$00 ; \ zero? if so,
- BEQ END_KILL_LOOP ; / end loop
- DEY ; decrease # of times left+get index
- STX $06 ; \ if sprite is
- CPY $06 ; | this sprite
- BEQ KILL_LOOP ; / then ignore it
- LDA $14C8,y ; \ if sprite is not
- CMP #$08 ; | in a "tangible"
- BCC KILL_LOOP ; / mode, don't kill
- LDA $167A,y ; \ if sprite doesn't
- AND #%00000010 ; | interact with stars/cape/fire/bricks
- BNE KILL_LOOP ; / don't continue
- JSL $03B69F ; \
- PHX ; | if sprite is
- TYX ; | not touching
- JSL $03B6E5 ; | this sprite
- PLX ; | don't continue
- JSL $03B72B ; |
- BCC KILL_LOOP ; /
- LDA #SPRITEKILLSND ; \ play kill
- STA $1DFC ; / sound
- LDA $1656,y ; \ force sprite
- ORA #%10000000 ; | to disappear
- STA $1656,y ; / in smoke
- LDA #$02 ; \ set sprite into
- STA $14C8,y ; / death mode (status=2)
- END_KILL_LOOP RTS
- ;; subroutine for bouncing
- ;; I put the code in a subroutine
- ;; because it is used more than once
- ;; throughout the main code
- HIT_WALL LDA $B6,x ; \ decide which way rock is going to
- BPL HIT_POS ; / determine which handler code to use
- HIT_NEG LDA #$00 ; \
- SEC ; | if speed is negative
- SBC $B6,x ; | (which means left movement)
- LSR A ; | then handle it properly
- STA $B6,x ; |
- INC STARTOFFSET,x ; | .. also alter base position for rock
- BRA END_HIT ; /
- HIT_POS LDA $B6,x ; \
- LSR A ; | if speed is positive
- STA $B6,x ; | (which means right movement)
- LDA #$00 ; | then handle it properly
- SEC ; |
- SBC $B6,x ; |
- STA $B6,x ; | .. also alter base position for rock
- DEC STARTOFFSET,x ; /
- END_HIT RTS
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; GRAPHICS ROUTINE
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ROCK_YOFF = $F8 ; shift for whole rock
- TILESDRAWN = $08 ; \ scratch RAM
- TEMP_FOR_TILE = $03 ; / addresses
- FRAMES dcb $00,$00,$00,$00
- dcb $00,$00,$00,$00
- dcb $00,$00,$00,$00
- dcb $00,$00,$00,$00
- ROCK_TILES dcb $CC,$CE,$EC,$EE ;$CC,$CE,$EC,$EE
- ROCK_XPOS dcb $F0,$00,$F0,$00
- ROCK_YPOS dcb $F8,$F8,$08,$08
- SUB_GFX JSR GET_DRAW_INFO ; get info to draw tiles
- LDA FLIPXY,x ; \ store flip
- STA $02 ; / to scratch RAM
- STZ TILESDRAWN ; zero tiles drawn
- JSR DRAW_ROCK ; draw rock
- JSR SETTILES ; set tiles / don't draw offscreen
- ENDSUB RTS
- DRAW_ROCK LDA OFFSET,x ; \
- PHY ; | set frame according
- TAY ; | to offset
- LDA FRAMES,y ; |
- PLY ; /
- STA TEMP_FOR_TILE ; store tile into scratch RAM
- PHX ; back up X
- LDX #$00 ; load X with zero
- TILELP CPX #$04 ; end of loop?
- BNE NORETFRML ; if not, then don't end
- BRA RETFRML ; if so, end
- NORETFRML
- LDA $00 ; get sprite's X position
- PHY ; \
- LDY $02 ; | offset by
- BEQ NO_FLIP_R ; | this tile's
- SEC ; | X position
- SBC ROCK_XPOS,x ; | (add or
- BRA END_FLIP_R ; | subtract
- NO_FLIP_R CLC ; | depending on
- ADC ROCK_XPOS,x ; | direction)
- END_FLIP_R PLY ; /
- STA $0300,y ; set tile's X position
- LDA $01 ; get sprite's Y position
- PHY ; \
- LDY $02 ; | offset by
- BEQ NO_FLIP_R2 ; | this tile's
- SEC ; | Y position
- SBC ROCK_YPOS,x ; | (add or
- BRA END_FLIP_R2 ; | subtract
- NO_FLIP_R2 CLC ; | depending on
- ADC ROCK_YPOS,x ; | direction)
- END_FLIP_R2 PLY ; /
- CLC ; \ rock Y
- ADC #ROCK_YOFF ; / offset
- STA $0301,y ; set tile's Y position
- LDA TEMP_FOR_TILE ; load tile # from scratch RAM
- CLC ; \ shift tile right/down
- ADC ROCK_TILES,x ; / according to which part
- STA $0302,y ; set tile #
- PHX ; back up X (index to tile data)
- LDX $15E9 ; load X with index to sprite
- LDA $15F6,x ; load palette info
- ORA $64 ; add in priority bits
- PHX ; \
- LDX $02 ; | flip the tile
- BEQ NO_FLIP_XY ; | X and Y if
- ORA #%11000000 ; | address set
- NO_FLIP_XY PLX ; /
- STA $0303,y ; set extra info
- PLX ; load backed up X
- INC TILESDRAWN ; another tile was drawn
- INY ; \
- INY ; | index to next slot
- INY ; |
- INY ; /
- INX ; next tile to draw
- JMP TILELP ; loop (BRA is out of range)
- RETFRML PLX ; load backed up X
- ENDROCK RTS
- SETTILES LDA TILESDRAWN ; \ don't do it
- BEQ NODRAW ; / if no tiles
- LDY #$02 ; #$02 means 16x16
- DEC A ; A = # tiles - 1
- JSL $01B7B3 ; don't draw if offscreen
- NODRAW RTS
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; ROUTINES FROM THE LIBRARY ARE PASTED BELOW
- ; You should never have to modify this code
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; GET_DRAW_INFO
- ; This is a helper for the graphics routine. It sets off screen flags, and sets up
- ; variables. It will return with the following:
- ;
- ; Y = index to sprite OAM ($300)
- ; $00 = sprite x position relative to screen boarder
- ; $01 = sprite y position relative to screen boarder
- ;
- ; It is adapted from the subroutine at $03B760
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- SPR_T1 dcb $0C,$1C
- SPR_T2 dcb $01,$02
- GET_DRAW_INFO STZ $186C,x ; reset sprite offscreen flag, vertical
- STZ $15A0,x ; reset sprite offscreen flag, horizontal
- LDA $E4,x ; \
- CMP $1A ; | set horizontal offscreen if necessary
- LDA $14E0,x ; |
- SBC $1B ; |
- BEQ ON_SCREEN_X ; |
- INC $15A0,x ; /
- ON_SCREEN_X LDA $14E0,x ; \
- XBA ; |
- LDA $E4,x ; |
- REP #$20 ; |
- SEC ; |
- SBC $1A ; | mark sprite invalid if far enough off screen
- CLC ; |
- ADC.W #$0040 ; |
- CMP.W #$0180 ; |
- SEP #$20 ; |
- ROL A ; |
- AND #$01 ; |
- STA $15C4,x ; /
- BNE INVALID ;
- LDY #$00 ; \ set up loop:
- LDA $1662,x ; |
- AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
- BEQ ON_SCREEN_LOOP ; | else, go through loop once
- INY ; /
- ON_SCREEN_LOOP LDA $D8,x ; \
- CLC ; | set vertical offscreen if necessary
- ADC SPR_T1,y ; |
- PHP ; |
- CMP $1C ; | (vert screen boundry)
- ROL $00 ; |
- PLP ; |
- LDA $14D4,x ; |
- ADC #$00 ; |
- LSR $00 ; |
- SBC $1D ; |
- BEQ ON_SCREEN_Y ; |
- LDA $186C,x ; | (vert offscreen)
- ORA SPR_T2,y ; |
- STA $186C,x ; |
- ON_SCREEN_Y DEY ; |
- BPL ON_SCREEN_LOOP ; /
- LDY $15EA,x ; get offset to sprite OAM
- LDA $E4,x ; \
- SEC ; |
- SBC $1A ; | $00 = sprite x position relative to screen boarder
- STA $00 ; /
- LDA $D8,x ; \
- SEC ; |
- SBC $1C ; | $01 = sprite y position relative to screen boarder
- STA $01 ; /
- RTS ; return
- INVALID PLA ; \ return from *main gfx routine* subroutine...
- PLA ; | ...(not just this subroutine)
- RTS ; /
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; SUB_OFF_SCREEN
- ; This subroutine deals with sprites that have moved off screen
- ; It is adapted from the subroutine at $01AC0D
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- SPR_T12 dcb $40,$B0
- SPR_T13 dcb $01,$FF
- SPR_T14 dcb $30,$C0,$A0,$C0,$A0,$F0,$60,$90 ;bank 1 sizes
- dcb $30,$C0,$A0,$80,$A0,$40,$60,$B0 ;bank 3 sizes
- SPR_T15 dcb $01,$FF,$01,$FF,$01,$FF,$01,$FF ;bank 1 sizes
- dcb $01,$FF,$01,$FF,$01,$00,$01,$FF ;bank 3 sizes
- SUB_OFF_SCREEN_X1 LDA #$02 ; \ entry point of routine determines value of $03
- BRA STORE_03 ; | (table entry to use on horizontal levels)
- SUB_OFF_SCREEN_X2 LDA #$04 ; |
- BRA STORE_03 ; |
- SUB_OFF_SCREEN_X3 LDA #$06 ; |
- BRA STORE_03 ; |
- SUB_OFF_SCREEN_X4 LDA #$08 ; |
- BRA STORE_03 ; |
- SUB_OFF_SCREEN_X5 LDA #$0A ; |
- BRA STORE_03 ; |
- SUB_OFF_SCREEN_X6 LDA #$0C ; |
- BRA STORE_03 ; |
- SUB_OFF_SCREEN_X7 LDA #$0E ; |
- STORE_03 STA $03 ; |
- BRA START_SUB ; |
- SUB_OFF_SCREEN_X0 STZ $03 ; /
- START_SUB JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return
- BEQ RETURN_35 ; /
- LDA $5B ; \ goto VERTICAL_LEVEL if vertical level
- AND #$01 ; |
- BNE VERTICAL_LEVEL ; /
- LDA $D8,x ; \
- CLC ; |
- ADC #$50 ; | if the sprite has gone off the bottom of the level...
- LDA $14D4,x ; | (if adding 0x50 to the sprite y position would make the high byte >= 2)
- ADC #$00 ; |
- CMP #$02 ; |
- BPL ERASE_SPRITE ; / ...erase the sprite
- LDA $167A,x ; \ if "process offscreen" flag is set, return
- AND #$04 ; |
- BNE RETURN_35 ; /
- LDA $13 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0756 VC:176 00 FL:205
- AND #$01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0780 VC:176 00 FL:205
- ORA $03 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0796 VC:176 00 FL:205
- STA $01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0820 VC:176 00 FL:205
- TAY ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0844 VC:176 00 FL:205
- LDA $1A ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0858 VC:176 00 FL:205
- CLC ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0882 VC:176 00 FL:205
- ADC SPR_T14,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0896 VC:176 00 FL:205
- ROL $00 ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizcHC:0928 VC:176 00 FL:205
- CMP $E4,x ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:0966 VC:176 00 FL:205
- PHP ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:0996 VC:176 00 FL:205
- LDA $1B ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizCHC:1018 VC:176 00 FL:205
- LSR $00 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdiZCHC:1042 VC:176 00 FL:205
- ADC SPR_T15,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizcHC:1080 VC:176 00 FL:205
- PLP ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F0 P:eNvMXdizcHC:1112 VC:176 00 FL:205
- SBC $14E0,x ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1140 VC:176 00 FL:205
- STA $00 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1172 VC:176 00 FL:205
- LSR $01 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1196 VC:176 00 FL:205
- BCC SPR_L31 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1234 VC:176 00 FL:205
- EOR #$80 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1250 VC:176 00 FL:205
- STA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1266 VC:176 00 FL:205
- SPR_L31 LDA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1290 VC:176 00 FL:205
- BPL RETURN_35 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1314 VC:176 00 FL:205
- ERASE_SPRITE LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite
- CMP #$08 ; |
- BCC KILL_SPRITE ; /
- LDY $161A,x ;A:FF08 X:0007 Y:0001 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1108 VC:059 00 FL:2878
- CPY #$FF ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1140 VC:059 00 FL:2878
- BEQ KILL_SPRITE ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1156 VC:059 00 FL:2878
- LDA #$00 ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1172 VC:059 00 FL:2878
- STA $1938,y ;A:FF00 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZcHC:1188 VC:059 00 FL:2878
- KILL_SPRITE STZ $14C8,x ; erase sprite
- RETURN_35 RTS ; return
- VERTICAL_LEVEL LDA $167A,x ; \ if "process offscreen" flag is set, return
- AND #$04 ; |
- BNE RETURN_35 ; /
- LDA $13 ; \
- LSR A ; |
- BCS RETURN_35 ; /
- LDA $E4,x ; \
- CMP #$00 ; | if the sprite has gone off the side of the level...
- LDA $14E0,x ; |
- SBC #$00 ; |
- CMP #$02 ; |
- BCS ERASE_SPRITE ; / ...erase the sprite
- LDA $13 ;A:0000 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:1218 VC:250 00 FL:5379
- LSR A ;A:0016 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1242 VC:250 00 FL:5379
- AND #$01 ;A:000B X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1256 VC:250 00 FL:5379
- STA $01 ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1272 VC:250 00 FL:5379
- TAY ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1296 VC:250 00 FL:5379
- LDA $1C ;A:001A X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0052 VC:251 00 FL:5379
- CLC ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0076 VC:251 00 FL:5379
- ADC SPR_T12,y ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0090 VC:251 00 FL:5379
- ROL $00 ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:enVMXdizCHC:0122 VC:251 00 FL:5379
- CMP $D8,x ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0160 VC:251 00 FL:5379
- PHP ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0190 VC:251 00 FL:5379
- LDA.W $001D ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F2 P:eNVMXdizcHC:0212 VC:251 00 FL:5379
- LSR $00 ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdiZcHC:0244 VC:251 00 FL:5379
- ADC SPR_T13,y ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdizCHC:0282 VC:251 00 FL:5379
- PLP ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:envMXdiZCHC:0314 VC:251 00 FL:5379
- SBC $14D4,x ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0342 VC:251 00 FL:5379
- STA $00 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0374 VC:251 00 FL:5379
- LDY $01 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0398 VC:251 00 FL:5379
- BEQ SPR_L38 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0422 VC:251 00 FL:5379
- EOR #$80 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0438 VC:251 00 FL:5379
- STA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0454 VC:251 00 FL:5379
- SPR_L38 LDA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0478 VC:251 00 FL:5379
- BPL RETURN_35 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0502 VC:251 00 FL:5379
- BMI ERASE_SPRITE ;A:8AFF X:0002 Y:0000 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0704 VC:184 00 FL:5490
- SUB_IS_OFF_SCREEN LDA $15A0,x ; \ if sprite is on screen, accumulator = 0
- ORA $186C,x ; |
- RTS ; / return
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; SUB_HORZ_POS
- ; This routine determines which side of the sprite Mario is on. It sets the Y register
- ; to the direction such that the sprite would face Mario
- ; It is ripped from $03B817
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- SUB_HORZ_POS LDY #$00 ;A:25D0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1020 VC:097 00 FL:31642
- LDA $94 ;A:25D0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZCHC:1036 VC:097 00 FL:31642
- SEC ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1060 VC:097 00 FL:31642
- SBC $E4,x ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1074 VC:097 00 FL:31642
- STA $0F ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1104 VC:097 00 FL:31642
- LDA $95 ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1128 VC:097 00 FL:31642
- SBC $14E0,x ;A:2500 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZcHC:1152 VC:097 00 FL:31642
- BPL SPR_L16 ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1184 VC:097 00 FL:31642
- INY ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1200 VC:097 00 FL:31642
- SPR_L16 RTS ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement