;**************************************************************************
;*
;* move four player sprite
;*
;**************************************************************************

	;.define	DEBUG

	org $2000			   ;prg start
	
	icl "custom.i"
	
start	;

	sei				  ;disable irqs
	lda	#$00
	sta	NMIEN			  ;NMIEN all off 
	sta	DMACTL			  ;DMACTL all off

	;set display list (use shadow regs)
	
	lda	#<displayList
	sta	DLISTL	
	lda	#>displayList
	sta	DLISTH
	
	;set display list interrupt
	  
	lda	#<dli_irq
        sta	VDSLSTL           
        lda	#>dli_irq
        sta	VDSLSTH    
	
	;vertical blank interrupt 
	
	lda 	#>vbi_irq
	sta	VVBLKIH	
	lda 	#<vbi_irq
	sta	VVBLKIL	
	
	;set Timer-1 vector

	lda	#<timerIrq
        sta	VTIMR1L        
        lda	#>timerIrq
        sta	VTIMR1H 
	
	;chbase
	
	lda	#$e0	
	sta	CHBASE
	
	;color setup
	
	lda	#$0	;black
	sta	COLBK
	lda	#$34	;red		
	sta	COLPF0
	lda	#$b6	;green	
	sta	COLPF1
	lda	#$1a	;yellow		
	sta	COLPF2
	lda	#$70	;blue (usable width GTIA mode 2)			
	sta	COLPF3
	
	;color player/missile
	
	lda 	#$1F
        sta 	COLPM0
        lda 	#$2F
        sta 	COLPM1
        lda 	#$3F
        sta 	COLPM2
        lda 	#$70
        sta 	COLPM3
        
        ;hpos players
        lda	#100
        sta	HPOSP0
        lda	#00
        sta	HPOSP1
        lda	#0
        sta	HPOSP2
        lda	#0
        sta	HPOSP3
        
        ;hpos missile
        
	lda	#0
        sta	HPOSM0
        lda	#0
        sta	HPOSM1
        lda	#0
        sta	HPOSM2
        lda	#0
        sta	HPOSM3
                
        ;width/size play 0
        lda	#0		;x1 player
        sta	SIZEP0
        sta	SIZEP1
        sta	SIZEP2
	sta	SIZEP3
	
	lda	#0		;x1 missile
	sta	SIZEM
        
        ;pmbase
        
        lda	#>playerMissleBlock
        sta	PMBASE
		
	;enable player & missile

	lda	#GRACTL_PLAYERS|GRACTL_MISSILES
	sta	GRACTL
	
	;
	
	lda	#1		;player forground
	sta	PRIOR
	
	;setup displays
	   	
	lda	#DMACTL_DL|DMACTL_X1_PM|DMACTL_PLAYER|DMACTL_MISSILE|DMACTL_PF_NORMAL
		
		;enable display list dma 
		;player dma (1 line)
		;missile dma
		;playfield normal display (40)
		
			
	sta	DMACTL	;DMACTL
	
	lda	#$0
	sta	HSCROL
	
	;enable dli
	
	lda	#0	;NMIEN_VBI|NMIEN_DLI
	sta	NMIEN	;VBI + DLI enbable
	
	;config timer
	
	lda	#1	      
        sta	AUDCTL        ;15 kHz frequency 
	
        lda	#15		
        sta	AUDF1         ;~1 kHz
        lda	#0
        sta	AUDC1         ;no sound
	
	;enable timer irq
	
	lda	#1
        sta	POKMSK
        sta	IRQEN
	
	;start timer
	
        lda	#0
        sta	STIMER		;start time (strobe)
	
	;irq enable	
	
	cli

	;main loop
	
loop
	;Wait VBlank

?WaitVC0
        lda	VCOUNT		
        beq	?WaitVC0   	
?WaitVCnot0
        lda	VCOUNT		
        bne	?WaitVCnot0   	                
	
	;draw mouse poitner
	
	lda	#<spriteConfig1
	sta	za0
	lda	#>spriteConfig1
	sta	za0+1
	jsr	drawSprite
		
	;check keyboard
	
	lda	SKSTAT
	and	#$04
	bne	?noKey  ; wenn 1 -> keine Taste gedrückt
	
	lda	KBCODE
	and	#$3f
	
	;            W [2E]
	;A [3F]      S [3E]      D [3A]	
	
	cmp	#$2e
	bne	@+
	dec	mouseY
@	cmp	#$3e
	bne	@+
	inc	mouseY
@	cmp	#$3a
	bne	@+
	inc	mouseX
@	cmp	#$3f
	bne	@+
	dec	mouseX
@
	
?noKey

	;update sprite data

	ldy	#spriteConfig_s.xpos
	lda	mouseX		;x
	sta	(za0),y
	
	ldy	#spriteConfig_s.ypos
	lda	mouseY		;y
	sta	(za0),y

	;check SELECT
		
	lda	CONSOL   ;console keys (SELECT/START/OPTION bit 0..2)
	lsr		 ;select to carry
	rol	selectStream	
	
	;check OPTION
	
	lda	CONSOL   ;console keys (SELECT/START/OPTION bit 0..2)
	lsr		 ;select to carry
	lsr		 ;start to carry
	lsr		 ;option to carry
	rol	optionStream
	
	;process selectStream and optionStream
	
	lda	selectStream
	and	#$3
	cmp	#%10	;last was up now its down
	bne	@+
	
	inc	portSelection
	lda	portSelection
	and	#1
	sta	portSelection	
@
	lda	optionStream
	and	#$3
	cmp	#%10	;last was up now its down
	bne	@+
	
	inc	mouseTypeSelection
	lda	mouseTypeSelection
	and	#1
	sta	mouseTypeSelection	
@
	
	;update text
	
	jsr	updatePortMouseText
	
	jmp loop			;end
		
mouseX	.byte	50
mouseY	.byte	50

mouseXRaw	.byte	0
mouseYRaw	.byte	0
	
;************************************************
;*
;* timerIrq (1khz)
;*
;************************************************

timerIrq

        ;don't do pha, already pushed by OS!
        txa
        pha
        tya
        pha

	;move xold,yold
	
	lda	mouseXRaw
	asl
	asl
	and	#$0f
	sta	mouseXRaw
	
	lda	mouseYRaw
	asl
	asl
	and	#$0f
	sta	mouseYRaw

	;process
		
	lda	PORTA
	ldx	portSelection
	beq	@+
	lsr
	lsr
	lsr
	lsr	
@
	and	#$0f
	tax
	
	;get xnew,ynew

	lda	mouseTypeSelection
	beq	updateQuadAmiga
	bne	updateQuadAtari
	
updateQuadReturn

	;update mouse x,y

	ldx	mouseXRaw
	lda	quadTable,x
	clc	
	adc	mouseX
	sta	mouseX
	
	ldx	mouseYRaw
	lda	quadTable,x
	ldy     mouseTypeSelection
        bne	?yNormal

        eor	#$ff		;neg
        clc	
        adc	#1		

?yNormal
	
	
	clc	
	adc	mouseY
	sta	mouseY
		
	;
      
        lda	POKMSK
	sta	IRQEN

        pla
        tay
        pla
        tax
        pla
        rti

;quadTable
;old state [32] new state [10]

quadTable
        .byte   0,  -1, 1,  0	
        .byte  1,  0,  0,  -1
        .byte   -1,  0,  0, 1
        .byte   0, 1,  -1,  0

;************************************************************
;* 	
;* getQuadAmiga
;*
;* x = 4 bit port data
;* 
;************************************************************

updateQuadAmiga
	
	;X = bits 1/3 = pins 2/4 = H/HQ
	;Y = bits 0/2 = pins 1/3 = V/VQ
	
	lda	amigaBitSwap,x
	tax
	and	#$3
	ora	mouseYRaw
	sta	mouseYRaw
	txa
	lsr
	lsr
	and	#$3
	ora	mouseXRaw
	sta	mouseXRaw
	
	jmp	updateQuadReturn
	
	;HQ VQ H V -> XxYy
	
amigaBitSwap	
	.byte   %0000   ;0000
        .byte   %0001   ;0001
        .byte   %1000   ;0010
        .byte   %1001   ;0011
        .byte   %0010   ;0100
        .byte   %0011   ;0101
        .byte   %1010   ;0110
        .byte   %1011   ;0111
        .byte   %0100   ;1000
        .byte   %0101   ;1001
        .byte   %1100   ;1010
        .byte   %1101   ;1011
        .byte   %0110   ;1100
        .byte   %0111   ;1101
        .byte   %1110   ;1110
        .byte   %1111   ;1111
	
;************************************************************
;* 	
;* getQuadAtari
;*
;* x = 4 bit port data
;* 
;************************************************************	
	
updateQuadAtari

	;X = bits 0/1 = pins 1/2 = XB/XA
	;Y = bits 2/3 = pins 3/4 = YA/YB
	
	txa
	and	#$3
	ora	mouseXRaw
	sta	mouseXRaw
	
	txa
	lsr
	lsr
	and	#$3
	ora	mouseYRaw
	sta	mouseYRaw
	
	jmp	updateQuadReturn
		
;************************************************************
;* 	
;* updatePortMouseText
;* 
;************************************************************

updatePortMouseText

	;port
	
	ldx	#"1"
	lda	portSelection
	beq	@+
	ldx	#"2"
@	stx	charData+20*5+14

	;mouse type
	
	ldy	#0
	lda	mouseTypeSelection
	beq	@+
	ldy	#5
@

	.rept	5
	lda	mouseTypeText+#,y
	sta	charData+20*6+10+#
	.endr

	rts
	
mouseTypeText	.byte	"amiga"
		.byte	"atari"
	

	;
	
selectStream	.byte		0
optionStream	.byte		0

portSelection		.byte		0	;0 or 1 (port1 port2)
mouseTypeSelection	.byte		1	;0 or 1 (amiga atari)


	;struct and data for sprite operation
		
	.struct	spriteConfig_s
		gfxPrg		.word
		gfxClr		.word
		dest		.word
		xpos		.byte
		ypos		.byte
		ypos_old	.byte
		hposOffset	.byte
	.ends

spriteConfig1	.word	mousePointerGfx			;gfx copy programm
		.word	clearGfx			;gfx clear programm
		.word	playerMissleBlock+1024+8	;destination in PGM
		.byte	80				;xpos
		.byte	100				;ypos
		.byte	1				;ypos_old
		.byte	0				;hpos reg offset
	
;************************************************************
;* 	
;* drawSprite
;* 
;* ZA0 = playerConfig
;*
;* trash y, ZA1-ZA3
;*
;************************************************************
	
drawSprite
			
	;get xpos and set to HPOS P0
	
	lda	#<HPOSP0
	sta	ZA1
	lda	#>HPOSP0
	sta	ZA1+1
	
	;
	
	ldy	#spriteConfig_s.hposOffset
	lda	(ZA0),y
	sta	ZA2		;hposOffset
	ldy	#spriteConfig_s.xpos
	lda	(ZA0),y		;y
	ldy	ZA2
	sta	(ZA1),y
	
	;get and check y pos and y pos old
	
	ldy	#spriteConfig_s.ypos
	lda	(ZA0),y
	ldy	#spriteConfig_s.ypos_old
	cmp	(ZA0),y
	bne	?yChanged
	
	;not changed so no copy gfx
	
	rts
	
?yChanged
	
	;get dest -> ZA3, ZA2
 	
	ldy	#spriteConfig_s.dest
	lda	(ZA0),y
	sta	ZA3
	sta	ZA2
	iny
	lda	(ZA0),y
	sta	ZA3+1
	sta	ZA2+1
	
 	;add y_old to ZA3
 	
 	clc 
	ldy	#spriteConfig_s.ypos_old
	lda 	(ZA0),y	
        add 	ZA3
	sta	ZA3
 	
        lda 	ZA3+1
        adc 	#0     
        sta 	ZA3+1
 	
 	;get clear programm and execute
 	
 	ldy	#spriteConfig_s.gfxClr
 	lda	(ZA0),y
 	sta	ZA1
 	iny
 	lda	(ZA0),y
 	sta	ZA1+1
 
 	lda	#>?clrReturn	;return to ?clrReturn
 	pha
 	lda	#<?clrReturn
 	pha
 	jmp	(ZA1)
?clrReturn	
	
	;add y to ZA2 (stored deset) -> ZA3
	
	clc        
	ldy	#spriteConfig_s.ypos
        lda 	(ZA0),y
	add 	ZA2
        sta	ZA3

        lda 	ZA2+1
        adc 	#0     
        sta 	ZA3+1
	
	;y_old = ypos
	
	ldy	#spriteConfig_s.ypos
	lda 	(ZA0),y	
	ldy	#spriteConfig_s.ypos_old
	sta 	(ZA0),y
	
	;get gfx programm and execute (will rts, so jump)
	
	ldy	#spriteConfig_s.gfxPrg
	lda	(ZA0),y
	sta	ZA1
	iny
	lda	(ZA0),y
	sta	ZA1+1	
	jmp	(ZA1)
		
	;gfx as programm ZA3 is dest
	
mousePointerGfx
	
	ldy	#0
	lda	#%10000000
	sta	(ZA3),y	;M = (ZA3)+y ; M = A
	iny
        lda	#%11000000
	sta	(ZA3),y	;M = (ZA3)+y ; M = A
	iny
        lda	#%11100000
	sta	(ZA3),y
	iny
        lda	#%11110000
	sta	(ZA3),y
	iny
        lda	#%11111000
	sta	(ZA3),y
	iny
        lda	#%11111100
	sta	(ZA3),y
	iny
        lda	#%11111110
	sta	(ZA3),y
	iny
        lda	#%11111111
	sta	(ZA3),y
	iny
        lda	#%11111000
	sta	(ZA3),y
	iny
	lda	#%11111000
	sta	(ZA3),y
	iny
	lda	#%11011000
	sta	(ZA3),y
	iny
	lda	#%10001100
	sta	(ZA3),y
	iny
	lda	#%00001100
	sta	(ZA3),y
	iny
	;lda	#%00001100
	sta	(ZA3),y
	rts

	
	;clear program ZA3 is dest
	
clearGfx
	lda	#0
	ldy	#0
	.rept	15
	sta	(ZA3),y
	iny
	.endr
	rts
	
	

;************************************************
;*
;* vertical blank interrupt (immidiate, x,y regs save bei os rom)
;*
;************************************************

vbi_irq

	
	
	;prolog (like XITVBL)
	
	pla					  
	tay
	pla					  
	tax
	pla					  
	rti
		
;************************************************
;*
;* display list interrupt
;*
;************************************************

dli_irq

	;prolog

        pha 
	txa	
	pha
	tya	
	pha
	
	;
	
	;epilog
	
        pla					  
	tay
	pla					  
	tax
	pla
        rti   	;direct (no stack used)
        
	
; display list

	;7	6	5	4	3	2	1	0
	;DLI	LMS	VSCROLL	HSCOLL	Mode
	;
	;Mode 0 Blank lines 7..4 is count+1 of blank lines
	;Mode 1 JMP (use with LMS to set destination)
	;Mode $2-$f is ANTIC mode
		
	 .align $400
	 
displayList	 
	.byte 0			   ; Mode 0
	.byte $70,$70,$70  ; 8 blank lines (mode 0) * 3
	.byte $47,<charData,>charData  ; Mode 7 + LMS, setting screen memory to $4000
	.byte $7 ;1
	.byte $7 ;2
	.byte $7 ;3
	.byte $7 ;4
	.byte $7 ;5
	.byte $7 ;6
	.byte $7 ;7
	.byte $7 ;8 
	.byte $7 ;9 
	.byte $7 ;10
	.byte $7 ;11
	.byte $41,<displayList,>displayList ; wait vblank, restart same display list on next frame	
	
	
	org	$4000
	 
	;note here its a 8x16 pixel mode
	
charData

	;20 chars per screen width (20*8 = 160Pixel)
	;12 char height (12*16 = 192 (/2))

	;        --------------------
	.byte	"--------------------" ;0
	.byte	">                  <" ;1
	.byte	"> MOVE             <" ;2
	.byte	"> MOUSE POINTER    <" ;3
	.byte	">                  <" ;4
	.byte	"> select [port1]   <" ;5
	.byte	"> option [amiga]   <" ;6
	.byte	">                  <" ;7
	.byte	"> or use  w        <" ;8
	.byte	">        asd       <" ;9
	.byte	">                  <" ;10
	.byte	"--------------------" ;11        
        
	
	;there are 4 player and 4 missile "sprites"
	;player width is 8 pixel
	;missile width is 2 pixels
	;player missile pair have unique color (0,1,2,3)
	;height is 128 or 256 lines
	
	org	$4800
	
;+--------+--------------------+--------------------+
;| Offset | Double Line        | Single Line        |
;+--------+--------------------+--------------------+
;| +128   | unused             | unused             |
;+--------+--------------------+--------------------+
;| +256   |                    |                    |
;+--------+--------------------+--------------------+
;| +384   | M3   M2   M1   M0  |                    |
;+--------+--------------------+--------------------+
;| +512   | Player 0           |                    |
;+--------+--------------------+--------------------+
;| +640   | Player 1           |                    |
;+--------+--------------------+--------------------+
;| +768   | Player 2           | M3   M2   M1   M0  |
;+--------+--------------------|                    |
;| +896   | Player 3           |                    |
;+--------+--------------------+--------------------+
;| +1024  |                    | Player 0           |
;|        |                    |                    |
;+--------+--------------------+--------------------+
;| +1280  |                    | Player 1           |
;|        |                    |                    |
;+--------+--------------------+--------------------+
;| +1536  |                    | Player 2           |
;|        |                    |                    |
;+--------+--------------------+--------------------+
;| +1792  |                    | Player 3           |
;|        |                    |                    |
;+--------+--------------------+--------------------+

playerMissleBlock
