; Atari 7800 sprite sample
; Written by Daniel Boris (dboris@comcast.net)
;

	icl '..\maria.h'

	opt f+h-

;******* Variables ********************************

	org $40

xpos	.ds	1	      	;X Position of sprite
ypos    .ds	1            	;Y Position of sprite
temp    .ds	1		
dlpnt	.ds	2
dlend	.ds	12		;Index of end of each DL

;**********************************************************
 	
        org     $8000           ;Start of code
START
	sei                     ;Disable interrupts
	cld                     ;Clear decimal mode
	

;******** Atari recommended startup procedure

	lda     #$07
	sta     INPTCTRL        ;Lock into 7800 mode
	lda     #$7F
	sta     CTRL            ;Disable DMA
	lda     #$00            
	sta     OFFSET
	sta     INPTCTRL
	ldx     #$FF            ;Reset stack pointer
	txs
	
;************** Clear zero page and hardware ******

	ldx     #$40
	lda     #$00
crloop1    
	sta     $00,x           ;Clear zero page
	sta	$100,x		;Clear page 1
	inx
	bne     crloop1

;************* Clear RAM **************************

        ldy     #$00            ;Clear Ram
        lda     #$18            ;Start at $1800
        sta     $81             
        lda     #$00
        sta     $80
crloop3
        lda     #$00
        sta     ($80),y         ;Store data
        iny                     ;Next byte
        bne     crloop3         ;Branch if not done page
        inc     $81             ;Next page
        lda     $81
        cmp     #$20            ;End at $1FFF
        bne     crloop3         ;Branch if not

        ldy     #$00            ;Clear Ram
        lda     #$22            ;Start at $2200
        sta     $81             
        lda     #$00
        sta     $80
crloop4
        lda     #$00
        sta     ($80),y         ;Store data
        iny                     ;Next byte
        bne     crloop4         ;Branch if not done page
        inc     $81             ;Next page
        lda     $81
        cmp     #$27            ;End at $27FF
        bne     crloop4         ;Branch if not

        ldx     #$00
        lda     #$00
crloop5                         ;Clear 2100-213F
        sta     $2100,x
        inx
        cpx     #$40
        bne     crloop5
        
;************* Build DLL *******************

; 20 blank lines

       	ldx	#$00                   
        lda     #$4F            ;16 lines
        sta     $1800,x  	      
        inx
        lda     #$21		;$2100 = blank DL
        sta	$1800,x
        inx
        lda     #$00
    	sta	$1800,x
    	inx                   
	lda     #$44            ;4 lines
	sta     $1800,x        
	inx
	lda     #$21
	sta	$1800,x
	inx
	lda     #$00
	sta	$1800,x
    	inx
        
; 192 mode lines divided into 12 regions

        ldy     #$00
DLLloop2                         
        lda     #$4F            ;16 lines
        sta     $1800,x        
        inx
        lda     DLPOINTH,y
        sta	$1800,x
        inx
        lda     DLPOINTL,y
    	sta	$1800,x
    	inx
        iny
        cpy     #$0D            ;12 DLL entries
        bne     DLLloop2


; 26 blank lines
                 
        lda     #$4F            ;16 lines
        sta     $1800,x  	      
        inx
        lda     #$21		;$2100 = blank DL
        sta	$1800,x
        inx
        lda     #$00
    	sta	$1800,x
    	inx                   
	lda     #$4A            ;10 lines
	sta     $1800,x        
	inx
	lda     #$21
	sta	$1800,x
	inx
	lda     #$00
	sta	$1800,x

    	
;***************** Setup Maria Registers ****************
	
        lda     #$18            ;DLL at $1800
	sta	DPPH
	lda	#$00
	sta	DPPL
	lda	#$18		;Setup Palette 0
	sta	P0C1
	lda	#$38
	sta	P0C2
	lda	#$58
	sta	P0C3
	lda	#$43		;Enable DMA
	sta	CTRL
	lda	#$00		;Setup ports to read mode
	sta	CTLSWA
	sta	CTLSWB
	
	lda	#$40		;Set initial X position of sprite
	sta	xpos
        
mainloop
	lda	MSTAT		;Wait for VBLANK
	and	#$80
	beq 	mainloop
	
	lda	SWCHA		;Read stick
	and	#$80		;Pushed Right?
	bne	skip1
	ldx	xpos		;Move sprite to right
	inx
	stx	xpos
skip1
	lda	SWCHA		;Read stick
	and 	#$40		;Pushed Left?
	bne 	skip2
	ldx 	xpos		;Move sprite to left
	dex
	stx 	xpos
skip2
        lda     SWCHA		;Read stick
        and     #$20		;Pushed Down?
        bne     skip3		
        ldx     ypos		;Move sprite down
        cpx	#176	
        beq	skip3		;Don't move if we are at the bottom
        inx
        stx     ypos	
skip3
        lda     SWCHA		;Read stick
        and     #$10		;Pushed Up?
        bne     skip4		
        ldx     ypos		;Move sprite up
        beq	skip4		;Don't move if we are at the top
        dex			
        stx     ypos
skip4

;********************** reset DL ends ******************
	
	ldx 	#$0C
	lda	#$00
dlclearloop
	dex
	sta	dlend,x
	bne	dlclearloop
	
	
;******************** build DL entries *********************

        lda     ypos		;Get Y position
   	and	#$F0		
   	lsr 			;Divide by 16
   	lsr	
   	lsr	
   	lsr	
   	tax
   	lda	DLPOINTL,x	;Get pointer to DL that this sprite starts in
   	sta	dlpnt
   	lda	DLPOINTH,x
   	sta	dlpnt+1
   	
   	;Create DL entry for upper part of sprite
   	
   	ldy	dlend,x		;Get the index to the end of this DL
   	lda	#$00				
	sta     (dlpnt),y	;Low byte of data address
	iny
	lda	#$40		;Mode 320x1
	sta     (dlpnt),y
	iny 
	lda	ypos		
	and	#$0F		
	ora	#$a0
	sta     (dlpnt),y
	iny
	lda	#$1F		;Palette 0, 1 byte wide
	sta     (dlpnt),y
	iny
	lda	xpos		;Horizontal position
        sta     (dlpnt),y
        sty	dlend,x
        
        lda	ypos
        and	#$0F		;See if sprite is entirely within this region
        beq	doneDL		;branch if it is
        
        ;Create DL entry for lower part of sprite 
        
        inx			;Next region
        lda	DLPOINTL,x	;Get pointer to next DL
   	sta	dlpnt
   	lda	DLPOINTH,x
   	sta	dlpnt+1
        ldy	dlend,x		;Get the index to the end of this DL
	lda	#$00				
	sta     (dlpnt),y
	iny
	lda	#$40		;Mode 320x1
	sta     (dlpnt),y
	iny 
	lda	ypos
	and	#$0F
	eor	#$0F
	sta	temp
	lda	#$a0
	clc
	sbc 	temp
	sta     (dlpnt),y
	iny
	lda	#$1F		;Palette 0, 1 byte wide
	sta     (dlpnt),y
	iny
	lda	xpos		;Horizontal position
	sta     (dlpnt),y
	sty	dlend,x
doneDL

;************** add DL end entry on each DL *****************************

	ldx	#$0C
dlendloop
	dex
	lda	DLPOINTL,x
	sta	dlpnt
	lda	DLPOINTH,x
   	sta	dlpnt+1
   	ldy 	dlend,x
   	iny
   	lda	#$00
   	sta	(dlpnt),y
   	txa
	bne 	dlendloop   	
   	
vbloop
	lda	MSTAT		;Wait for VBLANK to end
	and	#$80
	bne 	vbloop
	
	jmp     mainloop	;Loop

redraw
      

NMI
	RTI
	
IRQ
	RTI
	

;Pointers to the DLs

DLPOINTH
        .byte   $22,$22,$22,$22,$23,$23,$23,$23,$24,$24,$24,$24
DLPOINTL
        .byte   $00,$40,$80,$C0,$00,$40,$80,$C0,$00,$40,$80,$C0




;************** Graphic Data *****************************
        org $a000
        .byte     %00111100
        org $a100
        .byte     %00111100
        org $a200
        .byte     %01000010 
        org $a300
        .byte     %01000010 
        org $a400
        .byte     %10011001
        org $a500
        .byte     %10011001
        org $a600
        .byte     %10100101
        org $a700
        .byte     %10100101
        org $a800
        .byte     %10000001
        org $a900
        .byte     %10000001
        org $aA00
        .byte     %10100101
        org $aB00
        .byte     %10100101
        org $aC00
        .byte     %01000010
        org $aD00
        .byte     %01000010
        org $aE00
        .byte     %00111100
        org $aF00
        .byte     %00111100


;************** Cart reset vector **************************

	 org     $fff8
	.byte   $FF         ;Region verification
	.byte   $47         ;ROM start $4000
	.word   NMI
	.word   START
	.word   IRQ

