;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Giant Para Beetle, by Buu-Huu
;; original Para Beetle, by mikeyk
;;
;; Description: This sprite carries Mario upward if aboard.
;;
;; Note: When rideable, clipping tables values should be: 03 0A FE 0E
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;; Uses first extra bit: NO
;;
;; Extra Property Byte 1
;;    bit 0 - enable spin killing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

incsrc subroutinedefs_trasm.asm

                    EXTRA_PROP_1 = $7FAB28

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                
TILEMAP             dcb $E4,$E6
X_SPEED             dcb $0D,$F3
Y_SPEED             dcb $00,$08,$0B         ; mario not riding, mario getting on, mario riding
KILLED_X_SPEED      dcb $F0,$10
  
  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite init JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                    dcb "INIT"
                    PHY
                    JSL SubHorizPos
                    TYA
                    STA $157C,x
                    PLY
                    STZ $15AC,x
                    RTL
                    

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite code JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                    dcb "MAIN"                                    
                    PHB                     ; \
                    PHK                     ;  | main sprite function, just calls local subroutine
                    PLB                     ;  |
                    JSR SPRITE_CODE_START   ;  |
                    PLB                     ;  |
                    RTL                     ; /


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite main code 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

RETURN              RTS
SPRITE_CODE_START   JSR SPRITE_GRAPHICS       ; graphics routine
                    LDA $14C8,x             ; \ 
                    CMP #$08                ;  | if status != 8, return
                    BNE RETURN              ; /
                    JSL SubOffscreenX0  ; handle off screen situation
                    LDY $157C,x             ; \ set x speed based on direction
                    LDA X_SPEED,y           ;  |
                    STA $B6,x               ; /
                    LDA $9D                 ; \ if sprites locked, return
                    BNE RETURN              ; /
                    JSL $81802A             ; update position based on speed values
                    ;JSL $818032             ; interact with other sprites

                    PHY
                    LDA $154C,x             ; \
                    BNE GETSPEED            ;  |
                    STZ $1540,x             ;  | 
                    LDY #$00                ;  | y speed  ...
                    BRA SETSPEED            ;  |   ... depending if and how long mario has been riding
GETSPEED            LDA $1540,x             ;  |
                    INC A                   ;  |
                    INC A                   ;  |
                    STA $1540,x             ;  |
                    CMP #$14                ;  |
                    BCS MOVE_UP             ;  |
                    LDY #$01                ;  |
                    BRA SETSPEED            ;  |
MOVE_UP             LDA #$14                ;  |
                    STA $1540,x             ;  |
                    LDY #$02                ;  |
SETSPEED            LDA Y_SPEED,y           ;  |
                    STA $AA,x               ; /
                    PLY
         
                    LDY $15AC,x             ; \
                    LDA $1588,x             ;  | if sprite is in contact with an object...
                    AND #$03                ;  |
                    BEQ NO_CONTACT          ;  |
                    CPY #$00                ;  |    ... and timer hasn't been set (time until flip == 0)...
                    BNE DONT_SET_TIMER      ;  |
                    LDA #$10                ;  |    ... set time until flip
                    STA $15AC,x             ; /
DONT_SET_TIMER      LDA $157C,x             ; \ flip the temp direction status
                    EOR #$01                ;  |
                    STA $157C,x             ; /
NO_CONTACT          CPY #$00                ; \ if time until flip == 0...
                    BNE DONT_UPDATE         ;  |
                    LDA $157C,x             ;  |    ... update the direction status used by the gfx routine
                    STA $151C,x             ; /

DONT_UPDATE         JSL $81A7DC             ; check for mario/sprite contact (carry set = contact)
                    BCC RETURN_24           ; return if no contact
                    JSL SubVertPos        ; 
                    LDA $0E                 ; \ if mario isn't above sprite, and there's vertical contact...
                    CMP #$E6                ;  |     ... sprite wins
                    BPL SPRITE_WINS         ; /
                    LDA $7D                 ; \if mario speed is upward, return
                    BMI RETURN_24           ; /
                    LDA EXTRA_PROP_1,x
                    AND #$01
                    BEQ SPIN_KILL_DISABLED  ;
                    LDA $140D               ; \ if mario is spin jumping, goto SPIN_KILL
                    BNE SPIN_KILL           ; / 
SPIN_KILL_DISABLED  LDA #$01                ; \ set "on sprite" flag
                    STA $1471               ; /
                    LDA #$06                ; \ set riding sprite
                    STA $154C,x             ; / 
                    STZ $7D                 ; y speed = 0
                    LDA #$E1                ; \
                    LDY $187A               ;  | mario's y position += E1 or D1 depending if on yoshi
                    BEQ NO_YOSHI            ;  |
                    LDA #$D1                ;  |
NO_YOSHI            CLC                     ;  |
                    ADC $D8,x               ;  |
                    STA $96                 ;  |
                    LDA $14D4,x             ;  |
                    ADC #$FF                ;  |
                    STA $97                 ; /
                    LDY #$00                ; \ 
                    LDA $1491               ;  | $1491 == 01 or FF, depending on direction
                    BPL LABEL9              ;  | set mario's new x position
                    DEY                     ;  |
LABEL9              CLC                     ;  |
                    ADC $94                 ;  |
                    STA $94                 ;  |
                    TYA                     ;  |
                    ADC $95                 ;  |
                    STA $95                 ; /
RETURN_24B          RTS                     ;

SPRITE_WINS         LDA $154C,x             ; \ if riding sprite...
                    ORA $15D0,x             ;  |   ...or sprite being eaten...
                    BNE RETURN_24           ; /   ...return
                    LDA $1490               ; \ if mario star timer > 0, goto HAS_STAR 
                    BNE HAS_STAR            ; / NOTE: branch to RETURN_24 to disable star killing                  
                    JSL $80F5B7             ; hurt mario
RETURN_24           RTS                     ; final return

SPIN_KILL           JSR SUB_STOMP_PTS       ; give mario points
                    JSL $81AA33             ; set mario speed, NOTE: remove call to not bounce off sprite
                    JSL $81AB99             ; display contact graphic
                    LDA #$04                ; \ status = 4 (being killed by spin jump)
                    STA $14C8,x             ; /   
                    LDA #$1F                ; \ set spin jump animation timer
                    STA $1540,x             ; /
                    JSL $87FC3B             ; show star animation
                    LDA #$08                ; \ play sound effect
                    STA $1DF9               ; /
                    RTS                     ; return
HAS_STAR            LDA #$02                ; \ status = 2 (being killed by star)
                    STA $14C8,x             ; /
                    LDA #$D0                ; \ set y speed
                    STA $AA,x               ; /
                    JSL SubHorizPos        ; get new direction
                    LDA KILLED_X_SPEED,y    ; \ set x speed based on direction
                    STA $B6,x               ; /
                    INC $18D2               ; increment number consecutive enemies killed
                    LDA $18D2               ; \
                    CMP #$08                ;  | if consecutive enemies stomped >= 8, reset to 8
                    BCC NO_RESET2           ;  |
                    LDA #$08                ;  |
                    STA $18D2               ; /   
NO_RESET2           JSL $82ACE5             ; give mario points
                    LDY $18D2               ; \ 
                    CPY #$08                ;  | if consecutive enemies stomped < 8 ...
                    BCS NO_SOUND2           ;  |
                    LDA STAR_SOUNDS,y       ;  |    ... play sound effect
                    STA $1DF9               ; /
NO_SOUND2           RTS                     ; final return

       
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite graphics routine - specific 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TILEMAP             dcb $08,$0A,$28,$2A,$0C,$0E,$2C,$2E
                    dcb $08,$0A,$28,$2A,$0C,$0E,$2C,$2E
HORIZ_DISP          dcb $F8,$08,$F8,$08,$F8,$08,$F8,$08
                    dcb $08,$F8,$08,$F8,$08,$F8,$08,$F8
VERT_DISP           dcb $F0,$F0,$00,$00,$F0,$F0,$00,$00
                    dcb $F0,$F0,$00,$00,$F0,$F0,$00,$00
PROPERTIES          dcb $40,$00             ;xyppccct format

SPRITE_GRAPHICS     JSL GetDrawInfo       ; after: Y = index to sprite tile map ($300)
                                            ;      $00 = sprite x position relative to screen boarder 
                                            ;      $01 = sprite y position relative to screen boarder  
                   
                    LDA $1602,x
                    STA $03                 ; | $03 = index to frame start (0 or 4)
                    LDA $14 ; Frame Counter
                    LSR A  ;    \
                    LSR A  ; | Change every 8 frames
                    LSR A  ;  /
                    AND #$01  ; 2 walking "frames"
                    ASL A  ; x2
                    ASL A  ; x4
                    STA $03
                                       
                   
                    LDA $157C,x             ; \ $02 = sprite direction
                    STA $02                 ; /
                    BNE NO_ADD
                    LDA $03
                    CLC
                    ADC #$08
                    STA $03
NO_ADD              PHX                     ; push sprite index

                    LDX #$03                ; loop counter = (number of tiles per frame) - 1
LOOP_START_2        PHX                     ; push current tile number
                    TXA                     ; \ X = index to horizontal displacement
                    ORA $03                 ; / get index of tile (index to first tile of frame + current tile number)
FACING_LEFT         TAX                     ; \ 
                    
                    LDA $00                 ; \ tile x position = sprite x location ($00)
                    CLC                     ;  |
                    ADC HORIZ_DISP,x        ;  |
                    STA $0300,y             ; /
                    
                    LDA $01                 ; \ tile y position = sprite y location ($01) + tile displacement
                    CLC                     ;  |
                    ADC VERT_DISP,x         ;  |
                    STA $0301,y             ; /
                    
                    LDA TILEMAP,x           ; \ store tile
                    STA $0302,y             ; / 
        
                    LDX $02                 ; \
                    LDA PROPERTIES,x        ;  | get tile properties using sprite direction
                    LDX $15E9               ;  |
                    ORA $15F6,x             ;  | get palette info
                    ORA $64                 ;  | put in level properties
                    STA $0303,y             ; / store tile properties
                    
                    PLX                     ; \ pull, X = current tile of the frame we're drawing
                    INY                     ;  | increase index to sprite tile map ($300)...
                    INY                     ;  |    ...we wrote 1 16x16 tile...
                    INY                     ;  |    ...sprite OAM is 8x8...
                    INY                     ;  |    ...so increment 4 times
                    DEX                     ;  | go to next tile of frame and loop
                    BPL LOOP_START_2        ; / 

                    PLX                     ; pull, X = sprite index
                    LDY #$02                ; \ 02, because we didn't write to 460 yet
                    LDA #$03                ;  | A = number of tiles drawn - 1
                    JSL $81B7B3             ; / don't draw if offscreen
                    RTS                     ; return



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; routines below can be shared by all sprites.  they are ripped from original
; SMW and poorly documented
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; points routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

STAR_SOUNDS         dcb $00,$13,$14,$15,$16,$17,$18,$19

SUB_STOMP_PTS       PHY                     ; 
                    LDA $1697               ; \
                    CLC                     ;  | 
                    ADC $1626,x             ; / some enemies give higher pts/1ups quicker??
                    INC $1697               ; increase consecutive enemies stomped
                    TAY                     ;
                    INY                     ;
                    CPY #$08                ; \ if consecutive enemies stomped >= 8 ...
                    BCS NO_SOUND            ; /    ... don't play sound 
                    LDA STAR_SOUNDS,y       ; \ play sound effect
                    STA $1DF9               ; /   
NO_SOUND            TYA                     ; \
                    CMP #$08                ;  | if consecutive enemies stomped >= 8, reset to 8
                    BCC NO_RESET            ;  |
                    LDA #$08                ; /
NO_RESET            JSL $82ACE5             ; give mario points
                    PLY                     ;
                    RTS                     ; return
                

