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

!CarryingMario = $1510
!FrameNum = $00C2
!LastOAM = $1504
!CurrentCart = $151C
!CartWithMario = $1528
!TilesDrawn = $1534
!Carts = $1594
!InteractYOffLo = $1602
!InteractXOffLo = $1FD6
!InteractYOffHi = $7F9A7B
!InteractXOffHi = $7F9A87
!CartX = $7FB200			;\These should all be together
!CartY = $7FB206			;|
!CartYSpeed = $7FB20C		;|
!CartXSpeed = $7FB20F		;|
!CartFrame = $7FB212		;|
!CartJumpTimers = $7FB215	;|
!CartFractionX = $7FB218	;|
!CartFractionY = $7FB21B	;|
!CartOffscreen = $7FB21E	;|
!CartState = $7FB221		;/
;!CartInAir = $7FB224        ; Carries whether the cart Mario was previously in was in the air last frame
!DisableRAM = $79
!Direction = $157C
!TmpDirection = $7FB224

!JumpSoundEffect = #$2B
!JumpSoundEffectPort = $1DF9

;Ram for the baddy
!Enemy = $1510
!BaddyPalette = $151C
!BaddyPropertyRAM = $146C ;Some 4 bytes. Best to stay away.



                    print "INIT ",pc
					Init:
					lda $7FAB10,x
					and #$0C
					cmp #$0C
					bne .GoodCart
					STZ !FrameNum,x
					LDA #$00
					STA !Direction,x
					
					jsl $01ACF9
					
					lda $148D
					and #$03
					clc
					adc #$02
					asl
					ora #$01
					sta !BaddyPalette,x
					
					lda $148D
					and #$01
					sta !Enemy,x
					
					rtl
					.GoodCart
					lda #$01
					STA !Direction,x
					STZ !FrameNum,x
					STZ $1588,x
					STZ !CarryingMario,x
					STZ !CurrentCart,x
					STZ !CartWithMario,x
					LDA.b #%00000111
					STA !Carts,x
					LDA #$08
					STA !CartState
					STA !CartState+1
					STA !CartState+2
					LDA $14E0,x
					XBA
					LDA $E4,x
					REP #$20
					STA !CartX
					SEC
					SBC #$0020
					STA !CartX+2
					SEC
					SBC #$0020
					STA !CartX+4
					SEP #$20
					LDA $14D4,x
					XBA
					LDA $D8,x
					REP #$20
					STA !CartY
					STA !CartY+2
					STA !CartY+4
					SEP #$20
					PHX
					LDX #$14
					LDA #$00
					.loop
					STA !CartYSpeed,x
					DEX
					BPL .loop
					PLX
					RTL
					
	                print "MAIN ",pc			
                    PHB
                    PHK				
                    PLB
                    JSR SPRITE_ROUTINE			;Jump to the routine to keep organized
                    PLB
                    RTL     


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

XSpeeds:
db $F0,$10

BadXSpeeds:
db $E0,$20

SPRITE_ROUTINE:
					lda $7FAB10,x
					and #$0C
					cmp #$0C
					bne .GoodCart
						LDA $9D
						BNE .bad_return
						LDA $14C8,x
						CMP #$08
						BNE .bad_return
						JSL $01802A
						PHX
						LDA !Direction,x
						TAX
						LDA BadXSpeeds,x
						PLX
						STA $B6,x
						STZ !FrameNum,x
						LDA $15B8,x
						BEQ .NoSlope
						BPL .RightSlope
						LDA !Direction,x
						BNE +
						LDA #$04
						STA !FrameNum,x
						BRA .NoSlope
						+
						LDA #$02
						STA !FrameNum,x
						BRA .NoSlope
						.RightSlope
						LDA !Direction,x
						BNE +
						LDA #$02
						STA !FrameNum,x
						BRA .NoSlope
						+
						LDA #$04
						STA !FrameNum,x
						.NoSlope
						
						;LDA #$02
						;STA !FrameNum,x
						
						.bad_return
						JSL $25F9C0
						;LDY $15EA,x             ; get offset to sprite OAM
						;STY $04
						;JSR SUB_GFX_BAD					;Draw the graphics
						;JSR GET_DRAW_INFO
						;tya
						LDA $15EA,x
						sta !LastOAM,x
						jsr DrawKoopa
						JSR DrawGoodCart
						rts
					.GoodCart
					; The random number generator routine is a little deterministic.
					; Put this here because it will take the player  random amount of time to get in the cart.
					jsl $01ACF9
					LDA $15EA,x
					STA !LastOAM,x
					LDA #$FF
					STA !TilesDrawn,x
					LDA !Carts,x
					BIT #$01
					BEQ +
					JSR SPRITE_ROUTINE1
					+
					INC !CurrentCart,x
					LDA !Carts,x
					BIT #$02
					BEQ +
					JSR SPRITE_ROUTINE1
					+
					INC !CurrentCart,x
					LDA !Carts,x
					BIT #$04
					BEQ +
					JSR SPRITE_ROUTINE1
					+
					PHX
					TXY
					LDA !CartWithMario,y
					ASL
					TAX
					LDA !CartX,x
					STA $00E4,y
					LDA !CartX+1,x
					STA $14E0,y
					LDA !CartY,x
					STA $00D8,y
					LDA !CartY+1,x
					STA $14D4,y
					TXA
					LSR
					LDA !CartXSpeed,x
					STA $00B6,y
					LDA !CartYSpeed,x
					STA $00AA,y
					LDA !CartFrame,x
					STA !FrameNum,y
					PLX
					LDA #$08
					STA $14C8,x
					LDA !CartState
					BNE +
					LDA !CartState+1
					BNE +
					LDA !CartState+2
					BNE +
					STZ $14C8,x
					+
					STZ !CurrentCart,x
					;LDA !TilesDrawn,x
					;LDY #$FF
					;JSL $01B7B3					;Finish the graphics routine
					LDA !CartJumpTimers
					BEQ +
					DEC
					STA !CartJumpTimers
					+
					LDA !CartJumpTimers+1
					BEQ +
					DEC
					STA !CartJumpTimers+1
					+
					LDA !CartJumpTimers+2
					BEQ +
					DEC
					STA !CartJumpTimers+2
					+
					RTS

SendReturn:
JMP return

SPRITE_ROUTINE1:	  	
					PHX
					TXY
					LDA !CurrentCart,x
					TAX
					LDA !CartFractionX,x
					STA $14F8,y
					LDA !CartFractionY,x
					STA $14EC,y
					LDA !CartXSpeed,x
					STA $00B6,y
					LDA !CartYSpeed,x
					STA $00AA,y
					LDA !CartState,x
					STA $14C8,y
					LDA !CartOffscreen,x
					STA $15A0,y
					LDA !CartFrame,x
					STA !FrameNum,y
					TXA
					ASL
					TAX
					LDA !CartX,x
					STA $00E4,y
					LDA !CartX+1,x
					STA $14E0,y
					LDA !CartY,x
					STA $00D8,y
					LDA !CartY+1,x
					STA $14D4,y
					PLX
					LDA $9D
					BNE SendReturn
					LDA $14C8,x
					CMP #$02
					BNE +
					JMP Dying
					+
					CMP #$08
					BNE SendReturn
					JSL $01802A
					
					PHX
					TXY
					LDA !CurrentCart,x
					TAX
					LDA $00B6,y
					STA !CartXSpeed,x
					LDA $00AA,y
					STA !CartYSpeed,x
					LDA $14F8,y
					STA !CartFractionX,x
					LDA $14EC,y
					STA !CartFractionY,x
					TXA
					ASL
					TAX
					LDA $00E4,y
					STA !CartX,x
					LDA $14E0,y
					STA !CartX+1,x
					LDA $00D8,y
					STA !CartY,x
					LDA $14D4,y
					STA !CartY+1,x
					PLX
					LDA !CarryingMario,x
					BNE +
					JMP .NotCarryingMario
					+
					STZ $140D
					STZ $14A6
					STZ $13E2
					STZ $13E8
					LDA #$03
					STA !DisableRAM
					LDA #$FF
					STA $78
					PHY
					LDA #$40
					LDY $1528,x
					BEQ +
					-
					SEC
					SBC #$10
					DEY
					BPL -
					+
					PLY
					CMP $142A
					BCC .LessThan
					BEQ .ScrollCorrect
					INC $142A
					BRA .ScrollCorrect
					.LessThan
					DEC $142A
					.ScrollCorrect
					LDA #$29
					STA $B6,x
					PHX
					LDY !CurrentCart,x
					TYX
					STA !CartXSpeed,x
					PLX
					LDA !CurrentCart,x
					CMP !CartWithMario,x
					BEQ +
					JMP .CartNoMario
					+
					LDA !InteractXOffHi,x
					STA $01
					XBA
					LDA !InteractXOffLo,x
					STA $00
					REP #$20
					BEQ .NotOffX
					BPL .PlusX
					INC
					SEP #$20
					STA !InteractXOffLo,x
					XBA
					STA !InteractXOffHi,x
					BRA .NotOffX
					.PlusX
					DEC
					SEP #$20
					STA !InteractXOffLo,x
					XBA
					STA !InteractXOffHi,x
					.NotOffX
					SEP #$20
					LDA $14E0,x
					XBA
					LDA $E4,x
					REP #$20
					SEC
					SBC #$0004
					SEC
					SBC $00
					STA $94
					SEP #$20
					LDA !InteractYOffHi,x
					XBA
					LDA !InteractYOffLo,x
					REP #$20
					STA $00
					BEQ .NotOffY
					BPL .PlusY
					INC
					SEP #$20
					STA !InteractYOffLo,x
					XBA
					STA !InteractYOffHi,x
					BRA .NotOffY
					.PlusY
					DEC
					SEP #$20
					STA !InteractYOffLo,x
					XBA
					STA !InteractYOffHi,x
					.NotOffY
					SEP #$20
					LDA $19
					BNE +
					REP #$20
					LDA $00
					CLC
					ADC #$0007
					STA $00
					SEP #$20
					+
					LDA $14D4,x
					XBA
					LDA $D8,x
					REP #$20
					SEC
					SBC #$0014
					SEC
					SBC $00
					STA $96
					SEP #$20
					.CartNoMario
					STZ !FrameNum,x
					LDA $1588,x
					BIT #$03
					BEQ .NotHittingWall
					JSR KillCart
					.NotHittingWall
					LDA $1588,x
					BIT #$04
					BNE .OnGround
					;lda !CartWithMario,x
					;cmp !CurrentCart,x
					;bne +
					;LDA $15B8,x
					;bne +
					;lda #$01
					;sta !CartInAir
					;+
					LDA $AA,x
					BMI +
					JMP .NotOnGround
					+
					LDA !CartWithMario,x
					BEQ .First
					CMP #$02
					BEQ .Last
					JMP .NotOnGround
					.First
					LDA #$01
					STA !FrameNum,x
					JMP .NotOnGround
					.Last
					LDA #$03
					STA !FrameNum,x
					JMP .NotOnGround
					.OnGround
					;lda !CartWithMario,x
					;cmp !CurrentCart,x
					;bne ++
					;lda !CartInAir
					;beq +
					;lda #$37
					;sta $1DFC
					;+ 
					;lda #$00
					;sta !CartInAir
					;++
					PHX
					TXY
					LDA !CurrentCart,x
					TAX
					LDA !CartJumpTimers,x
					CMP #$01
					BNE ++
					PHX
					TYX
					LDA $15B8,x
					BEQ +
					BPL +
					PLX
					LDA #$B0
					STA $00AA,y
					STA !CartYSpeed,x
					BRA ++
					+
					PLX
					LDA #$C0
					STA $00AA,y
					STA !CartYSpeed,x
					++
					PLX
					LDA $16
					BIT #$80
					BEQ .NotOnGround
					LDA !CurrentCart,x
					CMP !CartWithMario,x
					BNE .NotOnGround
					lda !JumpSoundEffect
					sta !JumpSoundEffectPort
					LDA $15B8,x
					BEQ +
					BPL +
					LDA #$B0
					STA $AA,x
					BRA ++
					+
					LDA #$C0
					STA $AA,x
					++
					PHX
					LDY !CurrentCart,x
					TYX
					STA !CartYSpeed,x
					PLX
					LDA !CurrentCart,x
					CMP #$02
					BEQ .LastCartJump
					CMP #$01
					BEQ .SecondCartJump
					LDA #$08
					STA !CartJumpTimers+1
					LDA #$10
					STA !CartJumpTimers+2
					BRA .NotOnGround
					.SecondCartJump
					LDA #$04
					STA !CartJumpTimers
					LDA #$04
					STA !CartJumpTimers+2
					BRA .NotOnGround
					.LastCartJump
					LDA #$08
					STA !CartJumpTimers+1
					LDA #$10
					STA !CartJumpTimers
					.NotOnGround
					LDA $18
					BIT #$80
					BEQ .NotJumpOut
					STZ !DisableRAM
					LDA $15
					BIT #$01
					BEQ +
					LDA #$4C
					
					STA $7B
					BRA .Done
					+
					LDA $15
					BIT #$02
					BEQ +
					LDA #$30
					STA $7B
					BRA .Done
					+
					LDA #$20
					STA $7B
					.Done
					LDA #$C0
					STA $7D
					STZ !CarryingMario,x
					;STZ !CartWithMario,x
					LDA #$06
					STA $154C,x
					.NotJumpOut
					BRA return
					.NotCarryingMario
					JSL $01A7DC
					BCC return
					LDA $154C,x
					BNE return
					LDA #$01
					STA !CarryingMario,x
					LDA !CurrentCart,x
					STA !CartWithMario,x
					LDA $14E0,x
					XBA
					LDA $E4,x
					REP #$20
					SEC
					SBC $94
					SEP #$20
					STA !InteractXOffLo,x
					XBA
					STA !InteractXOffHi,x
					LDA $14D4,x
					XBA
					LDA $D8,x
					REP #$20
					SEC
					SBC #$0014
					SEC
					SBC $96
					SEP #$20
					STA !InteractYOffLo,x
					XBA
					STA !InteractYOffHi,x
					return:
					LDA $14C8,x
					CMP #$08
					BNE .Dead
					LDA $15B8,x
					BEQ .NoSlope
					BPL .RightSlope
					LDA #$02
					STA !FrameNum,x
					BRA .NoSlope
					.RightSlope
					LDA #$04
					STA !FrameNum,x
					.NoSlope
					JSR GetSprSprInt
					.Dead
					LDA $14D4,x
					XBA
					LDA $D8,x
					REP #$20
					CLC
					ADC #$0050
					CMP #$0200
					BCC +
					SEP #$20
					JSR RealKillCart
					+
					SEP #$20
					JSR SUB_OFF_SCREEN_X0
					;JSR GET_DRAW_INFO
					JSR DrawMarioNew
					JSR DrawGoodCart					;Draw the graphics	
                    RTS							;End the routine
Dying:
	LDA #$02
	STA !FrameNum,x
	JSL $01802A			
	PHX
	TXY
	LDA !CurrentCart,x
	TAX
	LDA $00B6,y
	STA !CartXSpeed,x
	LDA $00AA,y
	STA !CartYSpeed,x
	LDA $14F8,y
	STA !CartFractionX,x
	LDA $14EC,y
	STA !CartFractionY,x
	TXA
	ASL
	TAX
	LDA $00E4,y
	STA !CartX,x
	LDA $14E0,y
	STA !CartX+1,x
	LDA $00D8,y
	STA !CartY,x
	LDA $14D4,y
	STA !CartY+1,x
	PLX
	JMP return
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
;Other Routines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetSprSprInt:	
	LDY #$0B
INTLOOP:	
	CPY #$00
	BNE SPR_CON
	JMP NO_SPR_CON
	SPR_CON:
	DEY
	STX $06
	CPY $06
	BEQ INTLOOP
	LDA $14C8,y	; this just checks if
	CMP #$08	; the sprite touching this
	BCC INTLOOP	; is dead or not, if you want it to interact with dead sprites, remove 3 lines
	LDA $1686,y
	BIT #$08
	BNE INTLOOP
	JSL $03B69F
	PHX
	TYX
	JSL $03B6E5
	PLX
	JSL $03B72B
	BCC INTLOOP
	PHX
	TYX
	LDA $7FAB10,x
	BIT #$08
	BEQ Normal
	PLX
	LDA #$02
	STA $14C8,y
	STA $00C2,y
	LDA #$C0
	STA $00AA,y
	LDA #$10
	STA $00B6,y
	JSR KillCart

	BRA INTLOOP
	
	Normal:
	PLX
	
	LDA #$02
	STA $14C8,y
	JMP INTLOOP
NO_SPR_CON:
	RTS	
	
KillCart:
	PHY
	PHX
	LDA !CurrentCart,x
	TAX
	LDA #$02
	STA !CartState,x
	LDA #$C0
	STA !CartYSpeed,x
	LDA #$F0
	STA !CartXSpeed,x
	TXA
	TXY
	PLX
	CMP !CartWithMario,x
	BNE .NotWithMario
	LDA !CarryingMario,x
	BEQ .NotWithMario
	PHY
	JSL $00F5B7
	PLY
	LDA #$C0
	STA $7D
	STZ !CarryingMario,x
	;STZ !CartWithMario,x
	LDA #$08
	STA $154C,x
	.NotWithMario
	CPY #$01
	BNE .Done
	.MidCart
	LDA !CartWithMario,x
	CMP #$02
	BEQ .MarioInBack
	LDA !CurrentCart,x
	PHA
	LDA #$02
	STA !CurrentCart,x
	JSR KillCart
	PLA
	STA !CurrentCart,x
	BRA .Done
	.MarioInBack
	LDA !CurrentCart,x
	PHA
	LDA #$00
	STA !CurrentCart,x
	JSR KillCart
	PLA
	STA !CurrentCart,x
	BRA .Done
	.Done
	PLY
	RTS

RealKillCart:
	PHY
	PHX
	LDA !CurrentCart,x
	TAX
	LDA #$02
	STA !CartState,x
	TXA
	TXY
	PLX
	CPY #$02
	BEQ .BackCart
	CPY #$01
	BEQ .MidCart
	LDA !Carts,x
	STA $00
	LDA.b #%00000001
	TRB $00
	LDA $00
	STA !Carts,x
	BRA .Done
	.MidCart
	LDA !CartWithMario,x
	CMP #$02
	BEQ .MarioInBack
	LDA !Carts,x
	STA $00
	LDA.b #%00000110
	TRB $00
	LDA $00
	STA !Carts,x
	BRA .Done
	.MarioInBack
	LDA !Carts,x
	STA $00
	LDA.b #%00000011
	TRB $00
	LDA $00
	STA !Carts,x
	BRA .Done
	.BackCart
	LDA !Carts,x
	STA $00
	LDA.b #%00000100
	TRB $00
	LDA $00
	STA !Carts,x
	.Done
	PLY
	RTS
	
	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GRAPHICS ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TileSize:
db $02,$02,$02,$02,$00,$00

TileProperties:
db $07,$07,$07,$07,$07,$07

MarioTileProperties:
db $01,$01

TilePointers:
dw Straight
dw Up1
dw Up2
dw Down1
dw Down2
dw Straight
dw Up1
dw Up2
dw Down1
dw Down2

XOffPointers:
dw StraightX
dw Up1X
dw Up2X
dw Down1X
dw Down2X
dw StraightXLeft
dw Up1XLeft
dw Up2XLeft
dw Down1XLeft
dw Down2XLeft

YOffPointers:
dw StraightY
dw Up1Y
dw Up2Y
dw Down1Y
dw Down2Y
dw StraightY
dw Up1Y
dw Up2Y
dw Down1Y
dw Down2Y

LargeMarioTilePointers:
dw StraightLM
dw Up1LM
dw Up2LM
dw Down1LM
dw Down2LM

LargeMarioXOffPointers:
dw StraightXLM
dw Up1XLM
dw Up2XLM
dw Down1XLM
dw Down2XLM

LargeMarioYOffPointers:
dw StraightYLM
dw Up1YLM
dw Up2YLM
dw Down1YLM
dw Down2YLM

SmallMarioTilePointers:
dw StraightSM
dw Up1SM
dw Up2SM
dw Down1SM
dw Down2SM

SmallMarioXOffPointers:
dw StraightXSM
dw Up1XSM
dw Up2XSM
dw Down1XSM
dw Down2XSM

SmallMarioYOffPointers:
dw StraightYSM
dw Up1YSM
dw Up2YSM
dw Down1YSM
dw Down2YSM

Straight:
db $A0,$A2,$A0,$A2,$80,$80
Up1:
db $94,$96,$A4,$A6,$80,$80
Up2:
db $88,$8A,$A8,$AA,$80,$80
Down1:
db $C4,$C6,$E4,$E6,$80,$80
Down2:
db $C8,$CA,$E8,$EA,$80,$80

StraightLM:
db $8C,$81
Up1LM:
db $DE,$EE
Up2LM:
db $C2,$0E
Down1LM:
db $DC,$EC
Down2LM:
db $C0,$0E

StraightSM:
db $8E,$0E
Up1SM:
db $AE,$BE
Up2SM:
db $E2,$0E
Down1SM:
db $AC,$BC
Down2SM:
db $E0,$0E

StraightX:
db $F8,$08,$F8,$08,$04,$F8
Up1X:
db $F8,$08,$F8,$08,$00,$F4
Up2X:
db $F8,$08,$F8,$08,$FA,$F1
Down1X:
db $F8,$08,$F8,$08,$04,$F8
Down2X:
db $F8,$08,$F8,$08,$06,$FE

StraightXLeft:
db $F8,$08,$F8,$08,$0C,$00
Up1XLeft:
db $F8,$08,$F8,$08,$08,$FC
Up2XLeft:
db $F8,$08,$F8,$08,$02,$FA
Down1XLeft:
db $F8,$08,$F8,$08,$0C,$00
Down2XLeft:
db $F8,$08,$F8,$08,$0D,$06

StraightXLM:
db $08,$08
Up1XLM:
db $08,$08
Up2XLM:
db $0D,$80
Down1XLM:
db $03,$03
Down2XLM:
db $FE,$80

StraightXSM:
db $08,$08
Up1XSM:
db $08,$08
Up2XSM:
db $0D,$80
Down1XSM:
db $03,$03
Down2XSM:
db $FE,$80

StraightY:
db $FC,$FC,$80,$80,$08,$08
Up1Y:
db $F4,$F4,$FC,$FC,$08,$00
Up2Y:
db $EC,$EC,$FC,$FC,$06,$FE
Down1Y:
db $F4,$F4,$04,$04,$00,$08
Down2Y:
db $F0,$F0,$00,$00,$FC,$04

StraightYLM:
db $EE,$FE
Up1YLM:
db $EE,$F6
Up2YLM:
db $F3,$03
Down1YLM:
db $E8,$F0
Down2YLM:
db $EA,$FA

StraightYSM:
db $EF,$FF
Up1YSM:
db $EE,$F6
Up2YSM:
db $F3,$03
Down1YSM:
db $E8,$F0
Down2YSM:
db $EA,$FA

EnemyPointers:
dw GoombaTileCount
dw GoombaXOffPointers
dw GoombaYOffPointers
dw GoombaTilePointers

dw KoopaTileCount
dw KoopaXOffPointers
dw KoopaYOffPointers
dw KoopaTilePointers

GoombaTileCount:
db $01,$01,$01,$01,$01

GoombaXOffPointers:
dw StraightXGoomba
dw Up1XGoomba
dw Up2XGoomba
dw Down1XGoomba
dw Down2XGoomba

GoombaYOffPointers:
dw StraightYGoomba
dw Up1YGoomba
dw Up2YGoomba
dw Down1YGoomba
dw Down2YGoomba

GoombaTilePointers:
dw StraightGoomba
dw Up1Goomba
dw Up2Goomba
dw Down1Goomba
dw Down2Goomba

StraightYGoomba:
db $EF,$80
Up1YGoomba:
;db $EE,$F6
Up2YGoomba:
db $F5,$80
Down1YGoomba:
;db $E8,$F0
Down2YGoomba:
db $F0,$80

StraightXGoomba:
db $08,$08
Up1XGoomba:
;db $F8,$F8
Up2XGoomba:
db $0A,$0A
Down1XGoomba:
;db $FD,$FD
Down2XGoomba:
db $FB,$FB

StraightGoomba:
db $08,$08
Up1Goomba:
;db $AE,$BE
Up2Goomba:
db $0A,$0A
Down1Goomba:
;db $AC,$BC
Down2Goomba:
db $0C,$0C

KoopaTileCount:
db $01,$03,$03,$03,$03

KoopaXOffPointers:
dw StraightXKoopa
dw Up1XKoopa
dw Up2XKoopa
dw Down1XKoopa
dw Down2XKoopa

KoopaYOffPointers:
dw StraightYKoopa
dw Up1YKoopa
dw Up2YKoopa
dw Down1YKoopa
dw Down2YKoopa

KoopaTilePointers:
dw StraightKoopa
dw Up1Koopa
dw Up2Koopa
dw Down1Koopa
dw Down2Koopa


StraightYKoopa:
db $E9,$F1
Up1YKoopa:
;db $EE,$F6
Up2YKoopa:
db $EF,$EF,$F7,$F7
Down1YKoopa:
;db $E8,$F0
Down2YKoopa:
db $E6,$E6,$ED,$ED

StraightXKoopa:
db $08,$08
Up1XKoopa:
;db $F8,$F8
Up2XKoopa:
db $0B,$13,$0B,$13
Down1XKoopa:
;db $FD,$FD
Down2XKoopa:
db $FA,$02,$FA,$02

StraightKoopa:
db $00,$10
Up1Koopa:
;db $AE,$BE
Up2Koopa:
db $05,$06,$15,$16
Down1Koopa:
;db $AC,$BC
Down2Koopa:
db $02,$03,$12,$13

DrawKoopa:
    stz $0E
	LDA !Direction,x
	sta !TmpDirection
	lda !LastOAM,x
	tay
	PHY
	JSR GET_DRAW_INFO
	PLY
	LDA $15C4,x
	ora $186C,x
	BEQ +
	RTS
	+
	;Get whether the sprite is on the bottom of the screen or not
	lda $14D4,x
	xba
	lda $D8,x
	rep #$20
	sec
	sbc #$0078
	bpl +
	clc
	bra ++
	+
	cmp $1C
	++
	sep #$20
	rol $0E
	;Get whether the sprite is on the left side of the screen or not, if it is, we don't skip drawing on carry
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0080
	bcc + ;If we overflow back, then we are definitely on the left side
	bmi + ;And if it's negative
	cmp $1A
	+
	sep #$20
	rol $0E
	lda !BaddyPalette,x
	sta !BaddyPropertyRAM
	sta !BaddyPropertyRAM+1
	sta !BaddyPropertyRAM+2
	sta !BaddyPropertyRAM+3
	PHX
	
	lda !Enemy,x
	asl #3
	tax
	rep #$20
	lda EnemyPointers,x
	sta $03
	lda EnemyPointers+2,x
	sta $09
	lda EnemyPointers+4,x
	sta $0B
	lda EnemyPointers+6,x
	sta $05
	sep #$20
	
	plx
	phx
	phy
	
	lda !FrameNum,x
	tax
	tay
	lda ($03),y
	sta $0D
	txa
	ASL
	TAX
	tay
	REP #$20
	LDA ($05),y
	STA $05
	LDA ($09),y
	STA $09
	LDA ($0B),y
	STA $0B
	lda #TileSize
	sta $03
	LDA #!BaddyPropertyRAM
	STA $07
	SEP #$20
	ply
	plx
	jsr shared_gfx_routine

DrawMarioReturn:
	rts
	
DrawMarioNew:
	LDA !CarryingMario,x
	BEQ DrawMarioReturn
	LDA $71
	BNE DrawMarioReturn
	LDA !CartWithMario,x
	CMP !CurrentCart,x
	BNE DrawMarioReturn
	stz $0E
	LDA !Direction,x
	sta !TmpDirection
	lda !LastOAM,x
	tay
	PHY
	JSR GET_DRAW_INFO
	PLY
	LDA $15C4,x
	ora $186C,x
	BEQ +
	RTS
	+
	;Get whether the sprite is on the bottom of the screen or not
	lda $14D4,x
	xba
	lda $D8,x
	rep #$20
	sec
	sbc #$0078
	bpl +
	clc
	bra ++
	+
	cmp $1C
	++
	sep #$20
	rol $0E
	;Get whether the sprite is on the left side of the screen or not, if it is, we don't skip drawing on carry
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0080
	bcc + ;If we overflow back, then we are definitely on the left side
	cmp $1A
	+
	sep #$20
	rol $0E
	PHX
	lda !FrameNum,x
	tax
	lda #$01
	sta $0D
	txa
	ASL
	TAX
	LDA $19
	BNE .Large
	REP #$20
	LDA SmallMarioTilePointers,x
	STA $05
	LDA SmallMarioXOffPointers,x
	STA $09
	LDA SmallMarioYOffPointers,x
	STA $0B
	BRA .Small
	.Large
	REP #$20
	LDA LargeMarioTilePointers,x
	STA $05
	LDA LargeMarioXOffPointers,x
	STA $09
	LDA LargeMarioYOffPointers,x
	STA $0B
	.Small
	lda #TileSize
	sta $03
	LDA #MarioTileProperties
	STA $07
	SEP #$20
	plx
	jsr shared_gfx_routine
	
DrawGoodCart:
    stz $0E
	LDA $14
	LSR #2
	AND #$03
	ASL #6
	STA $0F
	LDA !Direction,x
	sta !TmpDirection
	lda !LastOAM,x
	tay
	PHY
	JSR GET_DRAW_INFO
	PLY
	LDA $15C4,x
	ora $186C,x
	BEQ +
	RTS
	+
	;Get whether the sprite is on the bottom of the screen or not
	lda $14D4,x
	xba
	lda $D8,x
	rep #$20
	sec
	sbc #$0078
	bpl +
	clc
	bra ++
	+
	cmp $1C
	++
	sep #$20
	rol $0E
	;Get whether the sprite is on the left side of the screen or not, if it is, we don't skip drawing on carry
	lda $14E0,x
	xba
	lda $E4,x
	rep #$20
	sec
	sbc #$0070
	bcc + ;If we overflow back, then we are definitely on the left side
	cmp $1A
	+
	sep #$20
	rol $0E
	PHX
	lda !FrameNum,x
	tax
	lda !TmpDirection
	bne +
	txa
	clc
	adc #$05
	tax
	+
	lda #$05
	sta $0D
	txa
	ASL
	TAX
	REP #$20
	LDA TilePointers,x
	STA $05
	LDA #TileProperties
	STA $07
	LDA XOffPointers,x
	sta $09
	lda YOffPointers,x
	sta $0B
	lda #TileSize
	sta $03
	SEP #$20
	plx
	
shared_gfx_routine:
	phx
	ldx $0D
	.GFXLoop
	stz $02
	lda $0E
	ror
	bcc .left
	.right
		lda !TmpDirection
		bne .right_facing_right
		.right_facing_left
			PHY
			TXY
			LDA ($09),y
			bpl .right_facing_left_positive
			.right_facing_left_negative
				PLY
				eor #$FF
				inc
				sta $0D
				lda $00
				sec
				sbc $0D
				rol
				eor #$01
				ror
				bra .right_finish_x
			.right_facing_left_positive
				PLY
				CLC
				ADC $00
				bra .right_finish_x
		.right_facing_right
			PHY
			TXY
			LDA ($09),y
			bpl .right_facing_right_positive
			.right_facing_right_negative
				PLY
				eor #$FF
				inc
				clc
				adc $00
				bra .right_finish_x
			.right_facing_right_positive
				PLY
				sta $0D
				lda $00
				sec
				sbc $0D
				rol
				eor #$01
				ror
				bra .right_finish_x
		.right_finish_x
		bcc +
		jmp .endofloop
		+
		bra .xdone
	.left
		lda !TmpDirection
		bne .left_facing_right
		.left_facing_left
			PHY
			TXY
			LDA ($09),y
			PLY
			CLC
			ADC $00
			bra .left_finish_x
		.left_facing_right
			lda $00
			sec
			PHY
			TXY
			sbc ($09),y
			PLY
		.left_finish_x
		cmp #$D0
		bcc .xdone
		;$02 = #$01, but preserve A, X, and Y
		sec
		rol $02
	.xdone
	STA $0300,y
	
	lda $0E
	ror #2
	bcc .top
	.bottomW
		PHY
		TXY
		LDA ($0B),y
		PLY
		;#$80 is a sentinal value to hide this tile.
		cmp #$80
		beq +
		CLC
		ADC $01
		cmp #$F0
		bcs +
		cmp #$50
		bcs .ydone
		+
		jmp .endofloop
		++
		bra .ydone
	.top
		PHY
		TXY
		LDA ($0B),y
		PLY
		;#$80 is a sentinal value to hide this tile
		cmp #$80
		beq +
		CLC
		ADC $01
		cmp #$F0
		bcs .ydone
		cmp #$B0
		bcc .ydone
		+
		jmp .endofloop
	.ydone
	STA $0301,y
	
	PHY
	TXY
	LDA ($05),y
	PLY
	STA $0302,y
	
	INC !TilesDrawn
	PHX
	LDX $15E9
	LDA $15F6,x
	PLX
	CPX #$04
	BCC +
	ORA $0F
	+
	ORA $64
	PHY
	TXY
	ora ($07),y
	PLY
	sta $0D
	lda !TmpDirection
	beq .prop_facing_left
	.prop_facing_right
		lda $0D
		ora #$40
		bra .prop_finish
	.prop_facing_left
		lda $0D
	.prop_finish
	STA $0303,y
	lda $0E
	ror
	bcs .overflow
	lda $0300,y
	bpl .notoverflow
	.overflow
		PHY
		TYA
		LSR #2
		TAY
		phy
		txy
		lda ($03),y
		ply
		PHX
		LDX $15E9
		ORA $15A0,x
		ORA $02
		PLX
		STA $0460,y	;
		PLY
		bra .overflowdone
	.notoverflow
		PHY
		TYA
		LSR #2
		TAY
		phy
		txy
		lda ($03),y
		ply
		STA $0460,y
		PLY
	.overflowdone
	
	INY
	INY
	INY
	INY
	.endofloop ;When we jump to the end, we don't want to take up this sprite slot.
	DEX
	bmi +
	jmp .GFXLoop
	+
	PLX	
	tya
	sta !LastOAM,x
	RTS
					
					
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUB_OFF_SCREEN
; This subroutine deals with sprites that have moved off screen
; It is adapted from the subroutine at $01AC0D
; DO NOT POINT THIS TO THE SHARED SUBROUTINES, IT IS CHANGED AND THE SPRITE WILL BREAK IF YOU DO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    
SPR_T12:             db $40,$B0
SPR_T13:             db $01,$FF
SPR_T14:             db $30,$C0,$A0,$C0,$A0,$F0,$60,$90		;bank 1 sizes
		            db $30,$C0,$A0,$80,$A0,$40,$60,$B0		;bank 3 sizes
SPR_T15:             db $01,$FF,$01,$FF,$01,$FF,$01,$FF		;bank 1 sizes
					db $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
                    AND #$01
                    ORA $03
                    STA $01
                    TAY
                    LDA $1A
                    CLC
                    ADC SPR_T14,y
                    ROL $00
                    CMP $E4,x
                    PHP
                    LDA $1B
                    LSR $00
                    ADC SPR_T15,y
                    PLP
                    SBC $14E0,x
                    STA $00
                    LSR $01
                    BCC SPR_L31
                    EOR #$80
                    STA $00
SPR_L31:             LDA $00
                    BPL RETURN_35
ERASE_SPRITE:        LDA $14C8,x             ; \ if sprite status < 8, permanently erase sprite
                    CMP #$08                ; |
                    BCC KILL_SPRITE         ; /    
                    LDY $161A,x
                    CPY #$FF
                    BEQ KILL_SPRITE
                    LDA #$00
                    STA $1938,y
KILL_SPRITE:         
					JMP RealKillCart
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
                    LSR A
                    AND #$01
                    STA $01
                    TAY
                    LDA $1C
                    CLC
                    ADC SPR_T12,y
                    ROL $00
                    CMP $D8,x
                    PHP
                    LDA.w $001D 
                    LSR $00
                    ADC SPR_T13,y
                    PLP
                    SBC $14D4,x
                    STA $00
                    LDY $01
                    BEQ SPR_L38
                    EOR #$80
                    STA $00
SPR_L38:             
					LDA $00
                    BPL RETURN_35
                    BMI ERASE_SPRITE

SUB_IS_OFF_SCREEN:   LDA $15A0,x             ; \ if sprite is on screen, accumulator = 0 
                    ORA $186C,x             ; |  
                    RTS                     ; / return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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
; DO NOT POINT THIS TO THE SHARED SUBROUTINES, IT IS CHANGED AND THE SPRITE WILL BREAK IF YOU DO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SPR_T1:              db $0C,$1C
SPR_T2:              db $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                 ; / 
INVALID:                     RTS                     ; return
