
dcb "INIT"
JSR SUB_HORZ_POS
TYA
STA $157C,x
RTL

dcb "MAIN"
PHB		;\
PHK		; | Change the data bank to the one our code is running from.
PLB		; | This is a good practice.
JSR SpriteCode	; | Jump to the sprite's function.
PLB		; | Restore old data bank.
RTL		;/ And return.

;===================================
;Sprite Function
;===================================
RETURN: RTS

SpriteCode:
	JSR Graphics
	LDA $14C8,x			;\
	CMP #$08			; | If sprite dead,
	BNE RETURN			;/ Return.
	LDA $9D				;\
	BNE RETURN			;/ If locked, return.
	JSL $01A7DC
	JSR BLOCKCHECK
	LDA [$05]
	XBA
	INC $07
	LDA [$05]
	XBA
	REP #$20
	CMP #$015B
	BEQ HITONLEFT
	CMP #$015C
	BEQ HITONRIGHT
	SEP #$20
	JSR NoContact
	RTS
	
	HITONLEFT:
	SEP #$20
	LDA $1528,x
	CMP #$01
	BCS INVIN
	BRA CHECKDEAD
	HITONRIGHT:
	SEP #$20
	LDA $1528,x
	CMP #$01
	BCS INVIN
	BRA CHECKDEAD
	CHECKDEAD:
	LDA #$28
	STA $1DFC
	INC $1534,x
	LDA $1534,x
	CMP #$05
	BEQ DEAD
	LDA #$01
	STA $1528,x
	JSR WAVESTART
	RTS
	DEAD:
	LDA #$02
	STA $14C8,x
	LDA #$FF
	STA $1493
	DEC $13C6 
	LDA #$0B
	STA $1DFB ; Store sound and exit level.
	JSL $07FC3B   
	LDX #$0B 
	Loop: 
	STZ $14C8,x 
	DEX 
	BPL Loop
	RTS
	
	INVIN:
	JSR UPDATE
	RTS
	
	WAVEDOWNSTART
	LDA $1510,x
	CMP #$00
	BNE UPWAVESTART
	LDA #$00
	STA $D8,x
	BRA SKIPG
	UPWAVESTART:
	LDA #$D0
	STA $D8,x
	SKIPG:
	LDA #$00 
	STA $14D4,x
	LDA #$80
	STA $E4,x 
	LDA #$01
	STA $1504,x
	WAVEDOWN:
	LDA #$07
	STA $1594,x
	INC $1602,x
	LDA $1602,x
	CMP #$35
	BEQ ENDYAY
	LDA $1510,x
	CMP #$00
	BNE UPWAVERAWRG
	LDA #$30
	STA $AA,x
	BRA SKIPH
	UPWAVERAWRG:
	LDA #$D0
	STA $AA,x
	SKIPH:
	LDA $1504,x
	CMP #$01
 	BNE NORIGHT
	INC $B6,x
	LDA $B6,x
	CMP #$10
	BNE DONTFLIP
	LDA #$00
	STA $1504,x
	NORIGHT:
	DEC $B6,x
	LDA $B6,x
	CMP #$E0
	BNE DONTFLIP
	LDA #$01
	STA $1504,x
	DONTFLIP:
	JSR UPDATE
	RTS
	ENDYAY:
	STZ $1504,x
	JSR ENDWIPE
	RTS
	
	WAVE:
	LDA $13
	AND #$01
	STA $1510,x
	BRA WAVEDOWNSTART
	RTS
	ENDYAY:
	JSR ENDWIPE
	RTS
	WAVESTART:
	LDA #$06
	STA $1594,x
	LDA $D8,x
	CMP #$05
	BCC WAVE
	LDA #$D0
	STA $AA,x	
	LDA #$00	
	STA $B6,x
	JSR UPDATE
	RTS
	
	NoContact:
	LDA $1594,x
	CMP #$09
	BEQ SPAWN
	LDA $1594,x
	CMP #$07
	BEQ WAVEDOWN
	LDA $1594,x
	CMP #$06
	BEQ WAVESTART
	LDA $1594,x
	CMP #$02
	BEQ TRANSFER12
	LDA $1594,x
	CMP #$03
	BEQ TRANSFER22
	LDA $1594,x
	CMP #$04
	BEQ TRANSFER32
	LDA $1594,x
	CMP #$05
	BEQ TRANSFER42
	LDA $1594,x
	CMP #$01
	BEQ WIPEWARP
	LDA $151C,x
	CMP #$FF
	BNE FLOAT
	STZ $151C,x
	ADC $14;frame counter
ADC $13;another frame counter
EOR $7D;mario yspeed
EOR $7B;mario xspeed
SBC $D1;mario x position
SBC $D3;mario y position
ADC $D8,x;own ypos
ADC $E4,x;own xpos
	AND #$05
	CMP #$03
	BCS SPAWN
	CMP #$01
	BEQ WAVESTART
	CMP #$00
	BEQ WIPEWARP
	BRA FLOAT
	SPAWN:
	LDA #$09
	STA $1594,x
	LDA #$01
	STA $1528,x
	LDA $1602,x
	CMP #$20
	BEQ MEH
	INC $1602,x
	RTS
	TRANSFER12:
	BRA TRANSFER1
	TRANSFER22:
	BRA TRANSFER2
	TRANSFER32:
	BRA TRANSFER3
	TRANSFER42:
	BRA TRANSFER4
	MEH:
	STZ $1602,x
	STZ $1594,x
	STZ $1528,x
	JSR ME
	RTS
	WIPEWARP:
	JSR WIPE
	RTS
	FLOAT:
	INC $151C,x
	LDA $14
	AND #$03
	BEQ CONTINUE
	RTS
	CONTINUE:
	LDA $94
	CMP $E4,x
	BCS RIGHT
	BRA LEFT
	RTS
	RIGHT:
	LDA $B6,x
	BPL GOOD
	INC $B6,x
	INC $B6,x
	INC $B6,x
	GOOD:
	INC $B6,x
	BRA Y
	LEFT:	
	LDA $B6,x
	BPL RURO
	BRA BAHHUMBUG
	RURO:
	DEC $B6,x
	DEC $B6,x
	DEC $B6,x
	BAHHUMBUG:
	DEC $B6,x
	BRA Y
	Y:
	LDA $96
	CMP $D8,x
	BCS WTF
	BRA WTFER
	RTS
	TRANSFER1:
	BRA WIPE2
	TRANSFER2:
	BRA WIPE3
	TRANSFER3:
	JSR WIPE4
	RTS
	TRANSFER4:
	JSR WIPE5
	RTS
	
	

	WTF:
	LDA $AA,x
	BPL GOODER
	INC $AA,x
	INC $AA,x
	INC $AA,x
	GOODER:
	INC $AA,x
	BRA UGH
	
	

	WTFER:
	LDA $AA,x
	BPL EH
	BRA BAH
	EH:
	DEC $AA,x
	DEC $AA,x
	DEC $AA,x
	BAH:
	DEC $AA,x
	BRA UGH

	WIPE:
	INC $1602,x
	LDA #$01
	STA $1594,x
	LDA $D8,x
	CMP #$05
	BCC WIPE2START
	LDA #$D0
	STA $AA,x	
	LDA #$00	
	STA $B6,x
	
	UGH:
	JSR UPDATE
	RTS
	
	WIPE2START:
	STZ $1602,x
	LDA #$02
	STA $1594,x
	STZ $D8,x 
	LDA #$00 
	STA $14D4,x
	WIPE2:
	INC $1602,x
	LDA $1602,x
	CMP #$50
	BCS WIPE3START
	LDA #$30
	STA $AA,x	
	LDA #$48
	STA $E4,x
	BRA UPDATE
	
	WIPE3START:
	STZ $1602,x
	LDA #$03
	STA $1594,x
	WIPE3:
	INC $1602,x
	LDA $1602,x
	CMP #$50
	BCS WIPE4START
	LDA #$D0
	STA $AA,x	
	LDA #$75
	STA $E4,x
	BRA UPDATE

	WIPE4START:
	STZ $1602,x
	LDA #$04
	STA $1594,x
	WIPE4:
	INC $1602,x
	LDA $1602,x
	CMP #$50
	BCS WIPE5START
	LDA #$30
	STA $AA,x	
	LDA #$A0
	STA $E4,x
	BRA UPDATE
	
	WIPE5START:
	STZ $1602,x
	LDA #$05
	STA $1594,x
	WIPE5:
	INC $1602,x
	LDA $1602,x
	CMP #$30
	BCS ENDWIPE
	LDA #$D0
	STA $AA,x	
	LDA #$C5
	STA $E4,x
	BRA UPDATE
	
	ENDWIPE:
	STZ $1528,x
	STZ $1602,x
	STZ $1594,x

	UPDATE:
	LDA $14E0,x
	CMP #$00
	BNE GRRRRR
	JSL $01801A
	JSL $018022
	RTS
	GRRRRR:
	LDA #$00
	STA $14E0,x
	BRA UPDATE
	ME:
JSL $02A9DE
BMI SlotsFull ; If sprite slots are full, don't generate.
LDA #$06
STA $1DFC
;After this, the sprite to generate is in the Y register.

PHX ; NOTE: We need to use the X register for the generated sprite.
TYX ; So we preserve the current sprites data.

LDA #$06
STA $7FAB9E,x ; The sprite number is stored to the custom sprite RAM Address. STA $7FAB9E,y doesn't exist, that's why we transfered X to Y.

JSL $07F7D2 ; Reset sprite tables, to generate this one.
JSL $0187A7 ; Reset custom sprite tables, too.

LDA #$08
STA $7FAB10,x ; Setting this to 08 means we are generating a custom sprite.

TXY ; Transfer sprite to spawn back to Y.
PLX ; Restore X.

LDA #$01
STA $14C8,y ; Run sprite's INIT code first.

LDA $E4,x
STA $00E4,y ; X position.
LDA $14E0,x
STA $14E0,y ; X position high.
LDA $D8,x
STA $00D8,y ; Y position.
LDA $14D4,x
STA $14D4,y ; Y position high.
LDA #$30
STA $B6,y ; Y position high.

PHX ; Push current sprite.
TYX ; Get sprite to generate into X.
PLX ; Restore previous sprite.
BRA SPARK2
SLOTSFULL:
RTS
SPARK2:
JSL $02A9DE
BMI SlotsFull ; If sprite slots are full, don't generate.

;After this, the sprite to generate is in the Y register.

PHX ; NOTE: We need to use the X register for the generated sprite.
TYX ; So we preserve the current sprites data.

LDA #$B1
STA $7FAB9E,x ; The sprite number is stored to the custom sprite RAM Address. STA $7FAB9E,y doesn't exist, that's why we transfered X to Y.

JSL $07F7D2 ; Reset sprite tables, to generate this one.
JSL $0187A7 ; Reset custom sprite tables, too.

LDA #$08
STA $7FAB10,x ; Setting this to 08 means we are generating a custom sprite.

TXY ; Transfer sprite to spawn back to Y.
PLX ; Restore X.

LDA #$01
STA $14C8,y ; Run sprite's INIT code first.

LDA $E4,x
STA $00E4,y ; X position.
LDA $14E0,x
STA $14E0,y ; X position high.
LDA $D8,x
STA $00D8,y ; Y position.
LDA $14D4,x
STA $14D4,y ; Y position high.
LDA #$D0
STA $B6,y ; Y position high.

PHX ; Push current sprite.
TYX ; Get sprite to generate into X.
PLX ; Restore previous sprite.
RTS


;===================================
;Block Check
;===================================
BLOCKCHECK:
PHX
LDA $E4,x           ; Get X low position of sprite
STA $02             ; store into $02
LDA $14E0,X         ;
STA $03	
LDA $D8,x           ; Get y low position of sprite
STA $00             ; Store into $00
LDA $14D4,x         ; Get y hi
STA $01             ; Store into $01
LDA $00                   
AND #$F0                
STA $06                   
LDA $02                   
LSR                       
LSR                       
LSR                       
LSR                                              
ORA $06                   
PHA                      
LDA $5A     
AND #$01                
BEQ CODE_01D977           
PLA                       
LDX $01                   
CLC                       
ADC $00BA80,X       
STA $05                   
LDA $00BABC,X       
ADC $03                   
STA $06                   
BRA CODE_01D989           

CODE_01D977
PLA                       
LDX $03                   
CLC                       
ADC.l $00BA60,X       
STA $05                   
LDA.l $00BA9C,x       
ADC $01                   
STA $06                   

CODE_01D989
LDA.b #$7E                
STA $07                   
LDX $15E9
PLX
RTS

;===================================
;Graphics Code
;===================================


TILEMAP1: 
dcb $20,$22,$00,$02

TILEMAP2:
dcb $24,$26,$04,$06

FLASH:
dcb $47,$43,$4F,$45

YDISP: dcb $10,$10,$00,$00
XDISP: dcb $10,$00,$10,$00

Graphics:
	JSR GET_DRAW_INFO 
	
	LDA $14
	LSR A
	LSR A
	AND #$01
	STA $03

	PHX
	LDX #$03
Loop:
	LDA $00			;\
	CLC			; | Apply X displacement of the sprite.
	ADC XDISP,x		; |
	STA $0300,y		;/ 

	LDA $01			;\
	CLC			; | Y displacement is added for the Y position, so one tile is higher than the other.
	ADC YDISP,x		; | Otherwise, both tiles would have been drawn to the same position!
	STA $0301,y		; | If X is 00, i.e. first tile, then load the first value from the table and apply that
				;/ as the displacement. For the second tile, F0 is added to make it higher than the first.

	LDA $03
	BNE FRAME2
	LDA TILEMAP1,x		; X still contains index for the tile to draw. If it's the first tile, draw first tile in
	BRA A
FRAME2:
	LDA TILEMAP2,x
A:
	STA $0302,y		; the table. If X = 01, i.e. second tile, draw second tile in the table.
	PHX
	LDX $15E9
	LDA $1528,x
	PLX
	CMP #$01
	BEQ FLASHY
	LDA #$47	; | Set properties based on direction.
	STA $0303,y	
	BRA SADFACE
	FLASHY:
	PHX			; Push number of times to go through loop (01), because we're using it for a table 
	LDA $14
	LSR A
	LSR A
	AND #$03
	TAX
	LDA FLASH,x	; | Set properties based on direction.
	STA $0303,y		;/
	PLX			; Pull number of times to go through loop.
	SADFACE:

	INY			;\
	INY			; | The OAM is 8x8, but our sprite is 16x16 ..
	INY			; | So increment it 4 times.
	INY			;/
	
	DEX			; After drawing this tile, decrease number of tiles to go through loop. If the second tile
				; is drawn, then loop again to draw the first tile.

	BPL Loop		; Loop until X becomes negative (FF).
	
	PLX			; Pull back the sprite index! We pushed it at the beginning of the routine.

	LDY #$02		; Y ends with the tile size .. 02 means it's 16x16
	LDA #$03		; A -> number of tiles drawn - 1.
				; I drew 2 tiles, so 2-1 = 1. A = 01.

	JSL $01B7B3		; Call the routine that draws the sprite.
	RTS			; Never forget this!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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            ;  | IF YOU READ THIS, YOU WIN A COOKIE! PM ME AND I'LL GIVE YOU A FREE ASM HACK WOOHOO!
	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 HORZ POS
;
; $B817 - horizontal mario/sprite check - shared
; Y = 1 if mario left of sprite??
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                    ;org $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 LABEL16             ;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
LABEL16:             RTS                     ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642