;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pile Driver Micro Goomba (Jumping Brick), by SMWEdit
;;
;; Uses first extra bit: NO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

incsrc subroutinedefs_trasm.asm

		ACTSTATUS = $1528	; 0=waiting for mario ; 1=preparing to jump ; 2=jumping
		PREPTIME = $163E	; decremental timer address used for preparing to jump
		TIME_UNTIL_JUMP = $27	; amount to set in timer while brick springs
		JUMP_SPEED = $9F	; jumping speed, works best with an F at the end (originally $AF)
		DISABLEJUMP = $1558	; time after landing to disable jumping
		DISABLEDFOR = $30	; amount of frames to disable brick after landing
		JUMPMAXDIST = $30	; how close mario needs to be to make the brick jump
		

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; INIT and MAIN JSL targets
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		dcb "INIT"
		LDA #$0F		; \ set goomba to be sprite's
		STA $C2,x		; / death frame.
		STZ ACTSTATUS,x		; \  reset timers and
		STZ PREPTIME,x		;  | address used for
		STZ DISABLEJUMP,x	; /  sprite's action

		LDA $E4,x
		STA $1504,x
		RTL		

		dcb "MAIN"			
		PHB
		PHK				
		PLB				
		JSR SPRITE_ROUTINE	
		PLB
		RTL     


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SPRITE_ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

X_SPEED_TABLE	dcb $10,$F0			    ; speeds (right, left)

RETURN1		RTS

SPRITE_ROUTINE	JSR SUB_GFX
		LDA $14C8,x		; \  don't execute main
		CMP #$08		;  | sprite code unless
		BNE RETURN1		; /  status is "normal" (8)
		LDA $9D			; \ return if sprites locked
		BNE RETURN1		; /
		JSL SubOffscreenX0	; only process sprite while on screen             

		LDA $1588,x		; \ check if sprite is touching object side
		AND #%00000011		; /
		BEQ DONT_CHANGE_DIR	; don't change direction if not touching side
		LDA $157C,x		; \
		EOR #$01		;  | flip sprite direction
		STA $157C,x		; /
DONT_CHANGE_DIR

		STZ $B6,x		; set X speed to zero (as a default)
		LDA ACTSTATUS,x		; \ brick is jumping?
		CMP #$02		; /
		BNE NOT_IN_JUMP_MODE	; if not, don't execute following code
		LDY $157C,x		; \  set X speed
		LDA X_SPEED_TABLE,y	;  | depending on
		STA $B6,x		; /  direction.
		LDA $1588,x		; \ check to see
		AND #%00000100		; / if brick has landed
		BEQ NOT_LANDED		; if not, don't execute folling code
		LDA #$00		; \ set status for brick waiting
		STA ACTSTATUS,x		; / for mario to come near
		LDA #$09		; \ play sound effect
		STA $1DFC		; / for brick landing
		LDA #DISABLEDFOR	; \ prevent brick from executing
		STA DISABLEJUMP,x	; / for a set amount of frames
NOT_LANDED
NOT_IN_JUMP_MODE

		LDA ACTSTATUS,x		; \ brick is preparing to jump?
		CMP #$01		; /
		BNE NOT_IN_PREP_MODE	; if not, don't execute following code
		LDA PREPTIME,x		; \  check timer for block to start jumping,
		;CMP #$00		;  | timer is also used as pointer to brick
		BNE NO_START_JUMP	; /  tile Y offsets in the "springing" action
		LDA #$02		; \ set status to jumping
		STA ACTSTATUS,x		; /
		LDA #JUMP_SPEED		; \ make brick jump
		STA $AA,x		; /
		JSL SubHorizPos        ; \
		TYA			;  | go toward mario
		STA $157C,x		; /
NO_START_JUMP
NOT_IN_PREP_MODE

		LDA $1588,x		; \ on ground?
		AND #%00000100		; /
		BEQ NOT_IN_WAIT_MODE	; if not, don't execute following code
		LDA DISABLEJUMP,x	; jump disabled?
		BNE NOT_IN_WAIT_MODE	; if so, don't execute following code
		LDA ACTSTATUS,x		; \ status = waiting for mario?
		;CMP #$00		; /
		BNE NOT_IN_WAIT_MODE	; if not, don't execute following code
DISTCHECK	LDA $E4,x		; \  put low and high byte of
		STA $04			;  | sprite X position in order
		LDA $14E0,x		;  | so that 16 bit mode can
		STA $05			; /  work with the X position
		JSL SubHorizPos	; \ check which side mario is on
		CPY #$00		; /
		BNE RCHECK		; check right side if on right
		BRA LCHECK		; else check left side
RCHECK		PHP			; \
		REP #%00100000		;  | get the distance between
		LDA $04			;  | the sprite and mario
		SEC			;  | assuming mario is on
		SBC $94			;  | the RIGHT side of
		STA $06			;  | the sprite
		PLP			; /
		BRA COMPARE		; branch to check distance
LCHECK		PHP			; \
		REP #%00100000		;  | get the distance between
		LDA $94			;  | the sprite and mario
		SEC			;  | assuming mario is on
		SBC $04			;  | the LEFT side of
		STA $06			;  | the sprite
		PLP			; /
COMPARE		LDA $06			; load distance (difference)
		CMP #JUMPMAXDIST	; compare to maximum distance
		BCS NO_SET_PREP_MODE	; if too far, don't jump
		LDA $07			; \  don't jump if 100 or
		;CMP #$00		;  | greater, which would
		BNE NO_SET_PREP_MODE	; /  mean there is a high byte
		LDA #$01		; \ set status for doing spring
		STA ACTSTATUS,x		; / action before jumping
		LDA #TIME_UNTIL_JUMP	; \ set jump timer
		STA PREPTIME,x		; /
NO_SET_PREP_MODE
NOT_IN_WAIT_MODE

		LDA $1588,x		; \ check if hitting ceiling
		AND #%00001000		; / 
		BEQ NO_BOUNCE_DOWN	; if not, don't execute following code
		LDA $AA,x		; \ check if going up
		CMP #$7D		; /
		BCC NO_BOUNCE_DOWN	; if not, don't execute following code
		LDA #$FF		; \  bounce brick down
		SEC			;  | by subtracting from
		SBC $AA,x		;  | $FF (255)
		STA $AA,x		; /
NO_BOUNCE_DOWN

RETURN		JSL $81802A             ; update position based on speed values
		JSL $818032             ; interact with other sprites
		JSL $81A7DC             ; check for mario/sprite contact
		RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GRAPHICS ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BLOCK_OFFSET	dcb $01,$01,$01,$01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$02
		dcb $02,$02,$02,$02,$02,$02,$02,$04,$04,$04,$04,$04,$04,$04,$04,$05
		dcb $05,$05,$05,$05,$05,$05,$05,$02

SUB_GFX		JSL GetDrawInfo	; after: Y = index to sprite OAM ($300)
				   	;      $00 = sprite x position relative to screen boarder 
				   	;      $01 = sprite y position relative to screen boarder  

		LDA PREPTIME,x		; \ store timer into $02
		STA $02			; / for future reference
		STZ $03			; zero out $03 in case of no value being set
		LDA ACTSTATUS,x		; \ check if in springing (jump prep) mode
		CMP #$01		; /
		BNE NOT_IN_PREP_MODE_2	; if not, don't execute following code
		PHX			; \
		LDX $02			;  | store current offset
		LDA BLOCK_OFFSET,x	;  | for springing action
		STA $03			;  | into $03
		PLX			; /
NOT_IN_PREP_MODE_2

		LDA ACTSTATUS,x		; \ check if in jumping mode
		CMP #$02		; /
		BNE NOT_IN_JUMP_MODE_2	; if not, don't execute following code
		LDA $AA,x		; \ check if going up
		CMP #$7D		; /
		BCC NOT_2_HIGH		; if not, don't execute following code
		LDA #$02		; \ set it to be two tiles high
		STA $03			; / to expose goomba's "feet"
NOT_2_HIGH
NOT_IN_JUMP_MODE_2

		LDA $00                 ; \ set X position of brick
		STA $0300,y		; /

		LDA $01                 ; get Y position of brick
		SEC			; \ subtract 1 to compensate for
		SBC #$01		; / always being 1 pixel lower
		SEC			; \ subtract offset
		SBC $03			; /
		STA $0301,y		; set Y position

		LDA $7FAB10,x
		AND #$04
		BNE GEM_TYPE
		LDA #$C6                ; \ set tile number to [2]A8	
		STA $0302,y		; /
		BRA DONE_BRICK_TILE
GEM_TYPE	LDA #$C4
		STA $0302,y
DONE_BRICK_TILE

		LDA $15F6,x             ; get sprite palette info
		ORA $64                 ; add in the priority bits from the level settings
		STA $0303,y             ; set properties

		LDA $7FAB10,x
		AND #$04
		BEQ DONE_PALETTE_CHANGE
		LDA $1504,x
		LSR
		LSR
		LSR
		LSR
		AND #$03
		BEQ PALETTE_A
		CMP #$01
		BEQ PALETTE_B
		CMP #$02
		BEQ PALETTE_C
		LDA $0303,y
		AND #%11110001
		ORA #%00001010
		STA $0303,y
		BRA DONE_PALETTE_CHANGE
PALETTE_C
		LDA $0303,y
		AND #%11110001
		ORA #%00001000
		STA $0303,y
		BRA DONE_PALETTE_CHANGE
PALETTE_B
		LDA $0303,y
		AND #%11110001
		ORA #%00000110
		STA $0303,y
		BRA DONE_PALETTE_CHANGE
PALETTE_A

		LDA $0303,y
		AND #%11110001
		ORA #%00000100
		STA $0303,y
DONE_PALETTE_CHANGE

		INY			; \  get the index
		INY			;  | to the next slot
		INY			;  | of the OAM by
		INY			; /  incrementing by 4

		LDA $00                 ; \ set X position of microgoomba
		STA $0300,y		; /

		LDA $01                 ; get Y position of the tile
		SEC			; \ subtract 1 to compensate for
		SBC #$01		; / always being 1 pixel lower
		STA $0301,y		; set Y position

		LDA #$E4                ; \ set tile number to [2]AA		
		STA $0302,y		; /

		LDA $15F6,x             ; get sprite palette info
		ORA $64                 ; add in the priority bits from the level settings
		PHA			; \
		LDA $14			;  |
		AND #%00001000		;  |
		STA $02			;  | flip the
		PLA			;  | micro goomba
		PHX			;  | every 8
		LDX $02			;  | frames
		BNE NO_FLIP		;  |
		ORA #%01000000		;  |
NO_FLIP		PLX			; /
		STA $0303,y             ; set properties

		LDY #$02                ; tiles are 16x16 (02 = 16x16, 00 = 8x8)
		LDA #$01		; it's two tiles (# - 1)
		JSL $81B7B3		; jump to routine to reserve spaces
		RTS

