LOG_XOR 	  equ %00000011

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
	
	call Cls
	
	
	ld hl,SprChibiko
	ld a,(hl)		;First byte of sprite data
	inc hl
	push hl
		ld ix,0	;Xpos
		ld iy,256	;Ypos
		ld hl,48	;Width
		ld de,48	;Height
		call VDP_HMMC_Generated_ViaStack
	pop hl
	
	ld bc,SprChibiko_End-SprChibiko-1	;Length of prite	
	call SendSprite
	
	
	ld hl,SprCursor
	ld a,(hl)		;First byte of sprite data
	inc hl
	push hl
		ld ix,50	;Xpos
		ld iy,256	;Ypos
		ld hl,8	;Width
		ld de,8	;Height
		call VDP_HMMC_Generated_ViaStack
	pop hl
	
	ld bc,SprCursor_End-SprCursor-1	;Length of prite	
	call SendSprite
	

	ld hl,SprDrag
	ld a,(hl)		;First byte of sprite data
	inc hl
	push hl
		ld ix,60	;Xpos
		ld iy,256	;Ypos
		ld hl,8	;Width
		ld de,8	;Height
		call VDP_HMMC_Generated_ViaStack
	pop hl
	
	ld bc,SprDrag_End-SprDrag-1	;Length of prite	
	call SendSprite
	
	
	ld a,(NewPosX+1)
	ld b,a
	ld a,(NewPosY+1)
	ld c,a
	

	call DrawCursor	;Show the Cursor to the scree

ShowAgain:	
	push bc
		call ReadMouse
	pop bc

	ld a,(FireDown)
	or a
	jr z,NoFire
	
;Fire is down - show our test sprite at current location	

	call DrawChibiko

	xor a
	ld (FireDown),a		;Clear Fire
NoFire:

;Update the Cursor

	ld a,(OldPosX+1)	;Last Joystick pos
	ld b,a
	ld a,(OldPosY+1)
	ld c,a

	ld a,(NewPosX+1)	;New Joystick pos
	ld h,a
	ld a,(NewPosY+1)
	ld l,a

	or a
	sbc hl,bc			;See if Cursor pos changed
	jr z,ShowAgain
	
	ld a,(OldPosX+1)
	ld b,a
	ld a,(OldPosY+1)
	ld c,a

	call DrawCursor		;Remove old cursor

	ld hl,(NewPosX)		;Update Cursor pos
	ld de,(NewPosY)
	ld (OldPosX),hl
	ld (OldPosY),de

	ld b,h
	ld c,d
	push bc
		call DrawCursor	;Show New Cursor
	pop bc
	
	
	ld a,(FireHeld)
	or a
	jr z,MoFireHeld		;Check if fire is still down

;Fire is Held - show our test sprite at current location	
	call DrawDrag	
MoFireHeld:

	jp ShowAgain
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ReadMouse:	
	call GetMouse
	and %00010000			;See if fire is pressed
	jr nz,JoyNotFire
	
	ld a,(FireHeld)
	or a
	jr nz,JoyNotFireB
	ld a,1
	ld (FireDown),a			;Set FireDown/Held
	ld (FireHeld),a
	jr JoyNotFireB
JoyNotFire:
	xor a		
	ld (FireHeld),a			;Release Fire Held
JoyNotFireB:

	ex de,hl				;XY mousepos into DE
	ld bc,0
	ld b,d
	ld hl,(NewPosX)
	
	ld a,d					;Xmove
	or a
	jp m,MouseLeft
;MouseRight
	add hl,bc
	jr c,MouseUPDOWN
	ld a,h
	cp 256-7
	jr nc,MouseUPDOWN		;Off Right of screen
	
	ld (NewPosX),hl
	jr MouseUPDOWN
	
MouseLeft:	
	add hl,bc
	jr nc,MouseUPDOWN		;Off Left of screen
	ld (NewPosX),hl
		
MouseUPDOWN:			
	ld b,e
	ld hl,(NewPosY)
	
	ld a,e					;Ymove
	or a
	jp m,MouseUp
	
;MouseDown
	add hl,bc
	ret c
	ld a,h
	cp 192-7				;Off Bottom of screen
	ret nc
	ld (NewPosY),hl
	ret
	
MouseUp:	
	add hl,bc
	ret nc					;Off Top of screen
	ld (NewPosY),hl
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

OldPosX equ &D000		;Last Mouse position
OldPosY equ &D002
NewPosX equ &D004		;Current Mouse position
NewPosY equ &D006

FireHeld equ &D008		;Mouse Left is Held
FireDown equ &D009		;Mouse Left was pressed
							;(not processed yet)




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
	
	
	
	
	
	
	
	
	
	
	
	
	
SendSprite:
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
	ret
	
DrawChibiko:
	ld h,0
	ld l,b
	ld d,0
	ld e,c
	exx
		ld c,LOG_XOR
		ld ix,0				;XSource
		ld iy,256			;YSource
		ld hl,48			;Width
		ld de,48			;Height
	call VDP_LMMM_ViaStack	;Fast Copy Vram->Vram
	ret
	

DrawCursor:
	ld h,0
	ld l,b
	ld d,0
	ld e,c
	exx
		ld c,LOG_XOR
		ld ix,50				;XSource
		ld iy,256			;YSource
		ld hl,8			;Width
		ld de,8			;Height
	call VDP_LMMM_ViaStack	;Fast Copy Vram->Vram
	ret
	
DrawDrag:
	;ld hl,100	;Xdest
	;ld de,100	;YDest	
	ld h,0
	ld l,b
	ld d,0
	ld e,c
	exx
		ld c,LOG_XOR
		ld ix,60				;XSource
		ld iy,256			;YSource
		ld hl,8			;Width
		ld de,8			;Height
	call VDP_LMMM_ViaStack	;Fast Copy Vram->Vram
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
SprChibiko:	
	incbin "\ResALL\Sprites\RawMSX.RAW"
SprChibiko_End:

SprCursor:
	db &00,&03,&30,&00
	db &00,&03,&30,&00
	db &00,&03,&30,&00
	db &33,&30,&03,&33
	db &33,&30,&03,&33
	db &00,&03,&30,&00
	db &00,&03,&30,&00
	db &00,&03,&30,&00
SprCursor_End:

SprDrag:
	db &00,&00,&00,&00
	db &00,&00,&00,&00
	db &00,&03,&30,&00
	db &00,&33,&33,&00
	db &00,&33,&33,&00
	db &00,&03,&30,&00
	db &00,&00,&00,&00
	db &00,&00,&00,&00
SprDrag_End:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	;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:	
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


		
		
GetMouse: 
		call GetMouseAxis
        ld h,a			;Save both nibbles
		
        call GetMouseAxis
        ld l,a			;Save both nibbles
				
		ld a,b
		or %11001111	;Set Unused bits of buttons
        ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		
GetMouseAxis:

		 ;KJ212211			;K=Kana light J= Port 21
	ld d,%11101100			;For Mouse 2
	;ld d,%10010011 		;For Mouse 1 
	
	CALL  GetMouseNibble   	;Get Top Nibble (Bit 8 ON)
	and %00001111
    rlca
    rlca
    rlca
    rlca
    ld c,a					;Save top nibble
	
	ld d,%11001100			;For Mouse 2
	;ld d,%10000011 		;For Mouse 1
    CALL  GetMouseNibble   	;Get Bottom Nibble (Bit 8 OFF)
	ld b,a 					;Bits 56 are Buttons
    and %00001111
    or c					;Or in top nibble
	
	neg						;Flip the axis
	ret
		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GetMouseNibble: 	
		ld a,15			;Write Reg 15 (Port B)
		out (&a0),a
		ld a,d
		out (&a1),a
		
		ld b,10			;Wait for Mouse
MouseWait:  
		djnz MouseWait

        ld a,14			;Read Reg 14 (Port A)
        out (&a0),a	
        in a,(&a2)		;Read from hardware
        ret

		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;		
	
	
Cls:		
	di
	ld ix,0			;XDest
	ld iy,0			;YDest
	ld hl,256		;Width
	ld de,192		;Height
	ld a,&00		;Colors (&LR)
	call VDP_HMMV_ViaStack		;Fast Copy Vram->Vram
	ret

;Fill area - used by CLS
VDP_HMMV_ViaStack:
		ld bc,&00C0		;Command Byte (don't change)
		push bc
		ld c,a			;Color / Direction (UNUSED)
		push bc			
		push de			;Height
		push hl			;Width
		push IY			;DestY
		push IX			;DestX
		
		ld hl,0
		add hl,sp		;Load Stack into HL
		
		push hl
			call VDP_FirmwareSafeWait	;Wait for VDP to be ready
			call VDP_HMMV
		pop hl
		
		ld bc,12		;Skip 8 pairs of vars pushed onto the stack
		add hl,bc
		ld sp,hl
		ret
				
VDP_HMMV:				;Fast copy from VRAM to VRAM
	ld a,36				;AutoInc From 36
	call SetIndirect
;These Bytes are a sequence of OUTI Commands 	
	defb &ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3,&ED,&A3
	defb &ED,&A3,&ED,&A3,&ED,&A3						 ;outi x 11
	ret											
	
	
		
		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;		
	
	
	
	
VDP_LMMM_ViaStack:		;Fast copy from VRAM to VRAM		
		ld a,&90		;Command Byte (don't change)
		or c			;or in Logical Operation
		ld c,a	
		push bc
		ld b,&00		;Direction
		push bc
		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_LMMM
		pop hl
		
		ld bc,16		;Skip 8 pairs of vars pushed onto the stack
		add hl,bc
		ld sp,hl
		ret		
VDP_LMMM:				;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


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
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_FirmwareSafeWait
			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