;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Elite Goomba, by Buster Beetle
;;   based upon
;; Classic Goomba, by mikeyk
;;
;; Description: A classic squashable goomba. or so you'll be wishing
;;
;; Uses first extra bit: NO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

incsrc subroutinedefs_trasm.asm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; goomba init JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    
                    dcb "INIT"
                    PHY
                    JSL SubHorizPos
                    TYA
                    STA $157C,x
                    PLY
                    STZ $15AC,x
					LDA #$25
					STA $163E,x
                    RTL


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; goomba main JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; goomba main code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


X_SPEED             dcb $08,$F8 
KILLED_X_SPEED      dcb $F0,$10

GOOMB_CODE_START    JSR GOOMB_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              ; /
                    LDA $1558,x             ; \ if sprite not defeated (timer to show remains > 0)...
                    BEQ ALIVE               ; /    ... goto ALIVE
                    STA $15D0,x             ; \ 
                    DEC A                   ;  }   if sprite remains don't disappear next frame...
                    BNE RETURN              ; /    ... return
					LDA #$23
					STA $1DF9
					LDA #$02
                    STA $14C8,x             ; this is the last frame to show remains, so set sprite status = 0 (not alive)
RETURN              RTS                     ; return                    
ALIVE               LDA $1588,x             ;A:0100 X:0007 Y:0001 D:0000 DB:03 S:01EF P:envMXdiZCHC:0276 VC:077 00 FL:623
                    AND #$04                ;A:0100 X:0007 Y:0001 D:0000 DB:03 S:01EF P:envMXdiZCHC:0308 VC:077 00 FL:623
                    PHA                     ;A:0100 X:0007 Y:0001 D:0000 DB:03 S:01EF P:envMXdiZCHC:0324 VC:077 00 FL:623
                    JSL $81802A             ; update position based on speed values
                    JSL $818032             ; interact with other sprites
					LDA $163E,x
					BNE TURN_CONT
					JSL SubHorizPos
					PHY
					PLA
					STA $157C,x
					LDA #$25
					STA $163E,x

TURN_CONT				
				
                    LDA $1588,x             ;A:254B X:0007 Y:0007 D:0000 DB:03 S:01EE P:envMXdizcHC:0684 VC:085 00 FL:623
                    AND #$04                ;A:2504 X:0007 Y:0007 D:0000 DB:03 S:01EE P:envMXdizcHC:0716 VC:085 00 FL:623
                    BEQ IN_AIR              ;A:2504 X:0007 Y:0007 D:0000 DB:03 S:01EE P:envMXdizcHC:0732 VC:085 00 FL:623
                    STZ $AA,x               ;A:2504 X:0007 Y:0007 D:0000 DB:03 S:01EE P:envMXdizcHC:0748 VC:085 00 FL:623
                    PLA                     ;A:2504 X:0007 Y:0007 D:0000 DB:03 S:01EE P:envMXdizcHC:0778 VC:085 00 FL:623
                    BRA ON_GROUND           ;A:2500 X:0007 Y:0007 D:0000 DB:03 S:01EF P:envMXdiZcHC:0806 VC:085 00 FL:623
IN_AIR              PLA                     ;A:2500 X:0007 Y:0006 D:0000 DB:03 S:01EB P:envMXdiZcHC:0316 VC:085 00 FL:4955
                    BEQ WAS_IN_AIR          ;A:2504 X:0007 Y:0006 D:0000 DB:03 S:01EC P:envMXdizcHC:0344 VC:085 00 FL:4955
                    LDA #$0A                ;A:2504 X:0007 Y:0006 D:0000 DB:03 S:01EC P:envMXdizcHC:0360 VC:085 00 FL:4955
                    STA $1540,x             ;A:25FF X:0007 Y:0006 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0376 VC:085 00 FL:4955
WAS_IN_AIR          LDA $1540,x             ;A:25FF X:0007 Y:0006 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0408 VC:085 00 FL:4955
                    BEQ ON_GROUND           ;A:25FF X:0007 Y:0006 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0440 VC:085 00 FL:4955
;                    STZ $AA,x               ;A:25FF X:0007 Y:0006 D:0000 DB:03 S:01EC P:eNvMXdizcHC:0456 VC:085 00 FL:4955
NO_GROUND			LDA #$05
					STA $163E,x
					LDA $1588,x
					AND #$08
					BEQ HEAD_BONK
					LDA #$B8
					EOR #$FF
					STA $AA,x
HEAD_BONK
					BRA NO_TOUCH
					
ON_GROUND           LDA $77
					AND #$04
					BEQ NO_TOUCH
					LDA $1588,x
					AND #$04
					BEQ NO_GROUND
					LDA $16
					AND #$80
					BEQ NO_TOUCH
					LDA #$20
					STA $1DF9
					LDA #$B4
					STA $AA,x
NO_TOUCH
					LDY $15AC,x             ; \
                    LDA $1588,x             ; | if sprite is in contact with an object...
                    AND #$03                ; |
                    BEQ DONT_UPDATE         ; |
                    LDA $157C,x             ; | flip the direction status
                    EOR #$01                ; |
                    STA $157C,x             ; /

DONT_UPDATE         JSL $81A7DC             ; check for mario/sprite contact
                    BCC RETURN_24           ; (carry set = contact)
                    LDA $1490               ; \ if mario star timer > 0 ...
                    BNE HAS_STAR            ; /    ... goto HAS_STAR
                    LDA $7D                 ; \  if mario's y speed < 10 ...
                    CMP #$10                ;  }   ... sprite will hurt mario
                    BMI GOOB_WINS           ; /                       
                    
MARIO_WINS          JSL $81AA33             ; set mario speed
                    JSL $81AB99             ; display contact graphic
                    LDA $140D               ; \  if mario is spin jumping...
                    ORA $187A               ;  }    ... or on yoshi ...
                    BNE SPIN_KILL           ; /     ... goto SPIN_KILL
                    LDA #$20                ; \     ... time to show defeated sprite = $20
                    STA $1558,x             ; / 
RETURN_24           RTS                     ; return 

GOOB_WINS           LDA $1497               ; \ if mario is invincible...
                    ORA $187A               ;  }  ... or mario on yoshi...
                    ORA $15D0,x             ; |   ...or sprite being eaten...
                    BNE RETURN2             ; /   ... return
                    JSL SubHorizPos         ; \  set new sprite direction
                    TYA                     ;  }  
                    STA $157C,x             ; /
                    JSL $80F5B7             ; hurt mario
RETURN2             RTS                     ; return
					
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; spin and star kill (still part of above routine)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FLIP				dcb $00,$FF
STAR_SOUNDS         dcb $00,$13,$14,$15,$16,$17,$18,$19

SPIN_KILL           LDA #$FF
					STA $163E,x
					LDA #$E0
					STA $AA,x
					LDY $76
					LDA #$37

					EOR FLIP,y
					STA $7B
					EOR #$FF
					STA $B6,x
					LDA #$BD
					STA $7D
					LDA #$05
					STA $1497
					LDA #$08
					STA $1DFC
                    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


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; graphics routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                    ;frame 1, frame 2, squashed, star killed (2 bytes each)
TILE_SIZE           dcb $02,$02,$02,$02,$02,$02,$02,$02
GOOMB_HORIZ_DISP    dcb $00,$00,$00,$00,$00,$00,$00,$00
GOOMB_VERT_DISP     dcb $00,$00,$00,$00,$00,$00,$00,$00
GOOMB_TILEMAP       dcb $A8,$A8,$AA,$AA,$AA,$AA,$AA,$AA
FLIP 				dcb $40,$00

GOOMB_GRAPHICS      JSL GetDrawInfo      
                    LDA $157C,x             ; \ $02 = direction
                    STA $02                 ; / 
                    
                    LDA $14                 ;\ 
                    LSR A                   ; |
                    LSR A                   ; |
                    LSR A                   ; |
                    CLC                     ; |
                    ADC $15E9               ; |
                    AND #$01                ; |
                    ASL A
                    STA $03                 ; | $03 = index to frame start (0 or 2)
                    PHX                     ; /

                    LDA $14C8,x
                    CMP #$02
                    BNE NO_STAR
                    LDA #$06
                    STA $03    

NO_STAR             LDA $1558,x             ; \ if time to show sprite remains > 0...
                    BEQ NOT_DEAD            ; |
                    LDA #$04                ; |  $03 = 4
                    STA $03                 ; /
                    STX $15E9
NOT_DEAD
                    
                    LDX #$01                ; run loop 4 times, cuz 4 tiles per frame
LOOP_START_2        PHX                     ; push, current tile

                    TXA                     ; \ X = index of frame start + current tile
                    CLC                     ;  |
                    ADC $03                 ;  |
                    TAX                     ; /

                    PHY                     ; set tile to be 8x8 or 16x16
                    TYA                     ;
                    LSR A                   ;
                    LSR A                   ;
                    TAY                     ;
                    LDA TILE_SIZE,x         ; 
                    STA $0460,y             ;
                    PLY                     ;
                    
                    LDA $00                 ; \ tile x position = sprite x location ($00) + tile displacement
                    CLC                     ; |
                    ADC GOOMB_HORIZ_DISP,x  ; |
                    STA $0300,y             ; /
                    
                    LDA $01                 ; |
                    CLC                     ; | tile y position = sprite y location ($01) + tile displacement
                    ADC GOOMB_VERT_DISP,x   ; |
                    STA $0301,y             ; /

                    LDA GOOMB_TILEMAP,x     ; \ store tile
                    STA $0302,y             ; /

                    PHX                     ;
                    LDX $15E9               ;
                    LDA $15F6,x             ; get palette info
                    PLX                     ;
					LDX $02
					ORA FLIP,x  ; flip tile if necessary
                    ORA $64                 ; add in tile priority of level
                    STA $0303,y             ; store tile properties

                    PLX                     ; \ pull, current tile
                    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 #$FF                ; \ we've already set 460 so use FF
                    LDA #$01                ; | A = number of tiles drawn - 1
                    JSL $81B7B3             ; / don't draw if offscreen
                    RTS                     ; return
                    
                    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; points routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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                     ;                  
                    LDA #$02       	    ; \ 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



