

PlayerX 	equ &C010	;Current player pos
PlayerY 	equ &C011

PlayerX2 	equ &C012	;Last player pos 
PlayerY2	equ &C013		;(For clearing sprite)

;GTSTCK
; Address  : #00D5
; Function : Returns the joystick status
; Input    : A  - Joystick number to test (0 = cursors, 1 = port 1, 2 = port 2)
; Output   : A  - Direction
; Registers: All
;  \U/
;  L+R
;  /D\
;

; GTTRIG
; Address  : #00D8
; Function : Returns current trigger status
; Input    : A  - trigger button to test
           ; 0 = spacebar
           ; 1 = port 1, button A
           ; 2 = port 2, button A
           ; 3 = port 1, button B
           ; 4 = port 2, button B
; Output   : A  - #00 trigger button not pressed
                ; #FF trigger button pressed
; Registers: AF



VdpIn_Status 	equ &99
VdpOut_Control 	equ &99
VdpOut_Indirect equ &9B
Vdp_SendByteData equ &9B	

;For Cartridge	
	org &4000				;Base Cart Address
	db "AB"					;Fixed Header
	dw ProgramStart 		;Pointer to start of program
	db 00,00,00,00,00,00	;Unused

	;;;Effectively Code starts at address &400A

ProgramStart:				;Program Code Starts Here
	
	;Initialize screen
	ld c,VdpOut_Control	
	ld b,VDPScreenInitData_End-VDPScreenInitData
	ld hl,VDPScreenInitData
	otir
	
	;Clear Screen
	ld hl,sprite
	ld a,(hl)				;First byte of sprite data
	inc hl
	push hl
		ld ix,0				;Xpos
		ld iy,0				;Ypos
		ld hl,256			;Width
		ld de,192			;Height
		call VDP_HMMC_Generated_ViaStack
	pop hl
	
	ld bc,128*192			;Screen Size
NextByteCLS:
	xor a					;0
	out (Vdp_SendByteData),a;Send next byte to vdp
	dec bc
	inc hl
	ld a,b
	or c
	jr nz,NextByteCLS
	
	;Send Sprite data from CPU to VRAM
	ld hl,sprite
	ld a,(hl)				;First byte of sprite data
	inc hl
	push hl
		ld ix,0				;Xpos
		ld iy,256			;Ypos
		ld hl,8				;Width
		ld de,16			;Height (2 x 8 line sprites)
		call VDP_HMMC_Generated_ViaStack
	pop hl
	
	ld bc,SpriteEnd-Sprite-1;Length of prite	
NextByte:
	ld a,(hl)				;Read next byte of sprite
	out (Vdp_SendByteData),a;Send next byte to vdp
	dec bc
	inc hl
	ld a,b
	or c
	jr nz,NextByte

	ld a,0					;Clear Player Pos
	ld (PlayerX),a
	ld (PlayerY),a
	
	JR StartDraw			;Need A=0
	
infloop:
	ld a,1				;Joystick 1 (0=keyboard 1=joy1 2=joy2)
	call &00D5			;GTSTCK - Get Keypress
	or a			
	jr z,infloop		;See if no keys are pressed
StartDraw:
	push af
		ld a,(PlayerX)	;Back up X
		ld b,a
		ld (PlayerX2),a

		ld a,(PlayerY)	;Back up Y
		ld c,a
		ld (PlayerY2),a

		push bc
			call BlankPlayer ;Remove old player sprite
		pop bc
	pop af
	
	ld d,a
	cp 1
	jr nz,JoyNotUp		;Jump if UP not presesd
	dec c				;Move Y Up the screen
JoyNotUp:
	ld a,d
	cp 5
	jr nz,JoyNotDown		;Jump if DOWN not presesd
	inc c				;Move Y Down the screen
JoyNotDown:
	ld a,d
	cp 7
	jr nz,JoyNotLeft 	;Jump if LEFT not presesd
	dec b				;Move X Left 
JoyNotLeft:
	ld a,d
	cp 3
	jr nz,JoyNotRight	;Jump if RIGHT not presesd
	inc b				;Move X Right
JoyNotRight: 

	ld a,b
	ld (PlayerX),a		;Update X
	ld a,c
	ld (PlayerY),a		;Update Y
	
	;X Boundary Check - if we go <0 we will end up back at &FFFF
	
	ld a,b
	cp 32 		
	jr c,PlayerPosXOk
	jr PlayerReset		;Player out of bounds - Reset!
PlayerPosXOk

	;Y Boundary Check - only need to check 1 byte
	ld a,c
	cp 24
	jr c,PlayerPosYOk	;Not Out of bounds
	
PlayerReset:
	ld a,(PlayerX2) 	;Reset Xpos	
	ld b,a
	ld (PlayerX),a	

	ld a,(PlayerY2) 	;Reset Ypos
	ld c,a
	ld (PlayerY),a
	
PlayerPosYOk:
	call DrawPlayer		;Draw Player Sprite

	ld bc,5000
	call PauseBC		;Wait a bit!

	jp infloop

PauseBC:
	dec bc
	ld a,b
	or c
	jr nz,PauseBC
	ret

	
	
	
BlankPlayer:
	ld iy,256+8		;YSource (Blank Sprite)
	jr DrawBoth
DrawPlayer:
	ld iy,256		;YSource (Face Sprite)
DrawBoth:
	ld ix,0			;XSource
	ld a,b
	rlca
	rlca
	rlca
	exx
		
		ld h,0		;Xdest
		ld l,a
	exx
	ld a,c
	rlca
	rlca
	rlca
	exx
		ld d,0		;YDest
		ld e,a
	exx
	ld hl,8			;Width
	ld de,8			;Height
	
	call VDP_HMMM_ViaStack		;Fast Copy Vram->Vram
	
	
	ret
	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
Sprite:	;Smiley face - one nibble per color
        DB &00,&44,&44,&00
        DB &04,&44,&44,&40
        DB &44,&34,&43,&44
        DB &44,&44,&44,&44
        DB &44,&44,&44,&44
        DB &44,&24,&42,&44
        DB &04,&42,&24,&40
        DB &00,&44,&44,&00
SpriteBlank:	
		DB &00,&00,&00,&00
		DB &00,&00,&00,&00
		DB &00,&00,&00,&00
		DB &00,&00,&00,&00
		DB &00,&00,&00,&00
		DB &00,&00,&00,&00
		DB &00,&00,&00,&00
		DB &00,&00,&00,&00
SpriteEnd:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	;Settings to define our graphics screen

VDPScreenInitData:	
	db %00000110,128+0		;mode register #0
	db %01100000,128+1		;mode register #1
	db 31		,128+2		;pattern name table
	db 239		,128+5		;sprite attribute table (LOW)
	db %11110000,128+7		;border colour/character colour at text mode
	db %00001010,128+8		;mode register #2
	db %00000000,128+9	 	;mode register #3
	db 128		,128+10		;colour table (HIGH)
VDPScreenInitData_End:	
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
VDP_HMMM_ViaStack:		;Fast copy from VRAM to VRAM

		ld bc,&00D0		;Command Byte (don't change)
		push bc
		push bc			;unused
		push de			;Height
		push hl			;Width
		exx
			push de		;DestY
			push hl		;DestX
		exx
		push iy			;SourceY
		push ix			;SourceX
		
		ld hl,0
		add hl,sp		;Load Stack into HL
		
		push hl
			call VDP_FirmwareSafeWait	;Wait for VDP to be ready
			call VDP_HMMM
		pop hl
		
		ld bc,16		;Skip 8 pairs of vars pushed onto the stack
		add hl,bc
		ld sp,hl
		ret
				
VDP_HMMM:				;Fast copy from VRAM to VRAM

	ld a,32				;AutoInc From 32
	call SetIndirect
	
	defb &ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3
	defb &ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3	
	ret														  ;outi x 15
	

; MyHMMM:						;Tile Copy command Vars 	
; MyHMMM_SX:	defw &0000 		;SY 32,33	;Destination Xpos
; MyHMMM_SY:	defw &0200 		;SY 34,35	;Tiles start 512 pixels down
; MyHMMM_DX:	defw &0000 		;DX 36,37	;Destination X
; MyHMMM_DY:	defw &0000 		;DY 38,39	;Destination Y
; MyHMMM_NX:	defw &0008 		;NX 40,41 	;Width=8px
; MyHMMM_NY:	defw &0008 		;NY 42,43	;Height=8px
				; defb 0     		;Color 44 	;unused
; MyHMMM_MV:	defb 0     		;Move 45	;Unused
				; defb %11010000 	;Command 46	;HMMM command - Don't mess with this 
; T_TemplateCommands_End	
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
		
VDP_HMMC_Generated_ViaStack:	;Fill ram from calculated values (first in A)

		ld bc,&00F0		;Command Byte (don't change)
		push bc
		ld c,a			;First Pixel (B unused)
		push bc
		push de			;Height
		push hl			;Width
		push iy			;Ypos
		push ix			;Xpos
		
		ld hl,0
		add hl,sp
		push hl
			call VDP_HMMC_Generated
		pop hl
		
		ld bc,12	;Skip 8 pairs of vars pushed onto the stack
		add hl,bc
		ld sp,hl
		ret
		
VDP_HMMC_Generated:		;Fill ram from calculated values (first in A)

	;Set the autoinc for more data
	ld a,36				;AutoInc From 36
	call SetIndirect
	defb &ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3
	defb &ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3			; 11 outis
	
	ld a,128+44			;128 = NO Increment ;R#44    Color byte (from CPU->VDP)
SetIndirect:
	out (VdpOut_Control),a		
	ld a,128+17			;R#17 -	Indirect Register 128=no inc  [AII] [ 0 ] [R5 ] [R4 ] [R3 ] [R2 ] [R1 ] [R0 ] 	
	out (VdpOut_Control),a
	ld c,VdpOut_Indirect	
	ret

;MyHMMC:								:HMMC Command looks like this
;MyHMMC_DX:	defw &0000 ;DX 36,37
;MyHMMC_DY:	defw &0000 ;DY 38,39
;MyHMMC_NX:	defw &0032 ;NX 40,41
;MyHMMC_NY:	defw &0032 ;NY 42,43
;MyHMMCByte:	defb 255   ;Color 44
;				defb 0     ;Move 45
;				defb %11110000 ;Command 46	


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	;Wait for VDP to be ready
VDP_FirmwareSafeWait:
	di
	call VDP_Wait						;Wait for the VDP to be available
	call VDP_GetStatusFirwareDefault	;Reset selected Status register to 0 for the firmware
	ret

VDP_Wait: 			;Get The status register - Disable interrupts, 
						;as they require status register 0 to be selected!

	call VDP_GetStatusRegister
VDP_DoWait:
	in a,(VdpIn_Status)	;Status register 2	- S#2  [TR ] [VR ] [HR ] [BD ] [ 1 ] [ 1 ] [EO ] [CE ] 
	rra
	ret nc
	jr VDP_DoWait




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;Set Status Reg

VDP_GetStatusFirwareDefault:
	xor a
	jr VDP_GetStatusRegisterB
VDP_GetStatusRegister:		;Get The status register - Disable interrupts!
	ld a,2					;S#2  [TR ] [VR ] [HR ] [BD ] [ 1 ] [ 1 ] [EO ] [CE ] - Status register 2
VDP_GetStatusRegisterB:
	out (VdpOut_Control),a
	ld a,128+15				;R#15  [ 0 ] [ 0 ] [ 0 ] [ 0 ] [S3 ] [S2 ] [S1 ] [S0 ] - Set Stat Reg to read
	out (VdpOut_Control),a
	ret
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
	org &C000		;Pad to 32k