zIXH equ r_iyh
zIXL equ r_iyl

Color4 equ 1			;Map of logical to sys colors
Color3 equ 3			;CPC only has 3 colors
Color2 equ 2			;Game can use up to 4
Color1 equ 1

ScreenWidth20 equ 1
ScreenWidth equ 160		;Define 20x18 Screen
ScreenHeight equ 144	;(360 of 448 possible tiles)


UserRam Equ &D000		;Game Vars
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	ifdef vasm
		include "\SrcALL\VasmBuildCompat.asm"
	else
		read "\SrcALL\WinApeBuildCompat.asm"
	endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	read "\SrcALL\CPU_Compatability.asm"


;"The eight gameboy buttons/direction keys are arranged in form of a 2x4 matrix. Select either button or direction keys by writing to this register, then read-out bit 0-3.
  ;Bit 7 - Not used
  ;Bit 6 - Not used
  ;Bit 5 - P15 Select Button Keys      (0=Select)
  ;Bit 4 - P14 Select Direction Keys   (0=Select)
  ;Bit 3 - P13 Input Down  or Start    (0=Pressed) (Read Only)
  ;Bit 2 - P12 Input Up    or Select   (0=Pressed) (Read Only)
;  Bit 1 - P11 Input Left  or Button B (0=Pressed) (Read Only)
 ; Bit 0 - P10 Input Right or Button A (0=Pressed) (Read Only)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;										Header												
	org &0000				;RST 0-7
	org &0040				;Interrupt: Vblank
		jp VblankInterruptHandler
	org &0048				;Interrupt:	LCD-Stat
		jp LcdStatInterruptHandler
	org &0050				;Interrupt: Timer
		reti
	org &0058				;Interrupt: Serial
		reti
	org &0060				;Interrupt: Joypad
		reti
	org &0100
	nop				;0100-0103	Entry point (start of program)
	jp	begin
					;0104-0133	Nintendo logo (Must match ROM logo)	
	db &CE,&ED,&66,&66,&CC,&0D,&00,&0B,&03,&73,&00,&83,&00,&0C,&00,&0D
	db &00,&08,&11,&1F,&88,&89,&00,&0E,&DC,&CC,&6E,&E6,&DD,&DD,&D9,&99
	db &BB,&BB,&67,&63,&6E,&0E,&EC,&CC,&DD,&DC,&99,&9F,&BB,&B9,&33,&3E
	db "YQUEST         " ;0134-0142	Game Name (UCASE)
	ifdef BuildGBC 
		db &80		;0143 		Color gameboy flag (&80 = GB+CGB,&C0 = CGB only)
	else 
		db &00
	endif
	db 0,0       	;0144-0145	Game Manufacturer code
	db 0         	;0146		Super GameBoy flag (&00=normal, &03=SGB)
	db 2	  	  	;0147		Cartridge type (special upgrade hardware) 
	db 2        	;0148		Rom size (0=32k, 1=64k,2=128k etc)
	db 3         	;0149		Cart Ram size (0=none,1=2k 2=8k, 3=32k)
	db 1         	;014A		Destination Code (0=JPN 1=EU/US)
	db &33       	;014B		Old Licensee code (must be &33 for SGB)
	db 0         	;014C		Rom Version Number (usually 0)
	db 0         	;014D		Header Checksum - ‘ones complement' checksum of bytes 0134-014C… (not needed for emulators)
	dw 0         	;014E-014F	Global Checksum – 16 bit sum of all rom bytes (except 014E-014F)… unused by gameboy

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;										Start of code												
	 
begin:
	nop						;No-op for safety!
	di
	ld	sp, &ffff			; set the stack pointer to highest mem location + 1
	
	xor a					;We're going to reset the tilemap pos	
	ld hl,&FF42				
	ldi	(hl), a				;FF42: SCY - Tile Scroll Y
	ld	(hl), a				;FF43: SCX - Tile Scroll X
	
	call ScreenOff
	
	;Define palette
	ifdef BuildGBC
		ld c,0*8		;palette no 0 (back)
		call SetGBCPalettes
	else
		ld a,%00011011		;DDCCBBAA .... A=Background 3=Black, =White
		ld hl,&FF47
		ldi (hl),a			;FF47 	BGP	BG & Window Palette Data  (R/W)	= &FC
		ldi (hl),a			;FF48  	OBP0	Object Palette 0 Data (R/W)	= &FF
		cpl					;Set sprite Palette 2 to the opposite
		ldi (hl),a			;FF49  	OBP1	Object Palette 1 Data (R/W)	= &FF
	endif
	call ScreenOn
    
	
	
	
	;1st tile bank (Lines 0-95) (&8000 Tiles 0-239)
	ld bc,&0000 ;xy pos
	ld hl,&140C ;WH
	ld de,0		;Tile
	call FillAreaWithTiles		;Fill a grid area 
	
	;2nd tile bank (Lines 96-144) (&8800 Tiles 0-119)
	ld bc,&000C ;xy pos
	ld hl,&1406 ;WH
	ld de,0		;Tile
	call FillAreaWithTiles		;Fill a grid area 
	
	
		; ---JSTLV	J=Joypad / S=Serial / T=Timer / L=Lcd stat / V=vblank
	ld a,%00000011	;VBlank On / LCD Stat On (LYC)
	ld (&FFFF),a	;IE - Interrupt Enable (R/W)
	
	ld a,95			;Line 96 (12 tiles down... 12x20=240 Tiles)
	ld (&FF45),a	;LYC - LY Compare Line number
	
		; -LOVHCMM
	ld a,%01000000
	ld (&FF41),a	;Turn on LYC
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	ld hl,UserRam			;Clear Game Ram
	ld de,UserRam+1
	ld bc,256
	ld (hl),0
	z_ldir
	
	
	ei
	
	
	call MainMenu			;Show Main Menu

infloop:					;Main Loop
	ld a,(Tick)
	inc a
	and %00000001
	ld (Tick),a

	ld bc,350				;Slow Down Delay

	ld a,(boost)			;Check if boost is on
	or a
	jr nz,BoostOff
	ld bc,1		;Boost - no delay (compensate for font draw)
BoostOff:

	ld d,%00111111			;Key buffer
PauseBC:
	push bc
		push de
			call ReadJoystick
		pop de
		and %00111111
		cp %00111111		;Keypressed?
		jr z,PauseNoKey
		ld d,a				;Store any pressed joystick buttons
		jr KeysDown
PauseNoKey:
	ld a,0
	ld (KeyTimeout),a		;Released - nuke key, and relese keypress
	ld d,%00111111
KeysDown:
	pop bc
	dec bc
	ld a,b
	or c
	jr nz,PauseBC

StartDraw:
	ld a,(KeyTimeout)		;Keytimeout 
	or a
	jr nz,JoySkip			;Yes, skip keypresses

	ld a,1
	ld (boost),a			;Boost Off

ProcessKeys:
	ld hl,PlayerDirection
	z_ld_ix PlayerXacc		;Point IX to player Accelerations 
	bit 2,d					;L
	jr nz,JoyNotLeft	
	dec (hl)
	call SetPlayerDirection
	ld a,1
	ld (KeyTimeout),a		;Ignore keypresses
JoyNotLeft:
	bit 3,d					;R
	jr nz,JoyNotRight	
	inc (hl)
	call SetPlayerDirection
	ld a,1
	ld (KeyTimeout),a		;Ignore keypresses
JoyNotRight: 
	bit 4,d					;Fire
	jr nz,JoyNotFire
	ld a,(BoostPower)		;Check if boost power remains
	or a
	jr z,JoyNotFire
	ld a,0
	ld (boost),a			;Turn on Boost
JoyNotFire:
JoySkip:
	call HandlePlayer		;Draw and update player
	
	call HandleCPU			;Draw and update CPU
	
	jp InfLoop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


VblankInterruptHandler:
	push hl
		ld hl,&FF40		;DwWBbOoC	B=Background Tile Patterns
		set 4,(hl)		;Background Tiles @ &8000
	pop hl
	reti
	
LcdStatInterruptHandler:	
	push hl
		ld hl,&FF40		;DwWBbOoC	B=Background Tile Patterns
		res 4,(hl) 		;Background Tiles @ &8800
	pop hl
	reti
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PsetHLDE:	;DE=Xpos HL=Ypos A=Color
	push hl
	push bc	
	push de
		push af
			ld a,d	;XH
			ld b,e	;XL
			ld c,l	;YL
		pop de
		call Pset
	pop de
	pop bc
	pop hl
	ret
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	
PSET:		;BC=XYpos  D=Color
	ld a,b
	cp 24*8	;Don't try to draw offscreen!
	ret nc
	push bc
		push de
			ld hl,PixelMask
			ld a,b
			and %00000111		;Pixel within byte
			add l
			ld l,a
			ld a,(hl)
			ld d,a
			cpl 
			ld e,a
			push de
				call CalcVramAddr		;Get Vram Addr
			pop bc			
			call LCDWaitRead
		pop de
		and c
		rr d
		jr nc,Pset1
		or b					;Set Bitplane 0
Pset1:
		call LCDWaitWrite
		
		inc hl
		
		call LCDWaitRead
		and c
		rr d
		jr nc,Pset2
		or b					;Set Bitplane 1
Pset2:
		call LCDWaitWrite
	pop bc
	ret
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Point:			;Test XY pos BC - returns pixel A
	ld hl,PixelMask
	ld a,b
	and %00000111		;Pixel within byte
	add l
	ld l,a
	ld a,(hl)
	ld d,a
	push de
		call CalcVramAddr
	pop de
	ld c,0
	ld b,2
PointAgain:
	srl c				;Shift bits right
	
	call LCDWaitRead	;Get a bitplane
	inc hl
	
	and d
	jr z,Point0
	set 1,c				;<-1 into byte
	jr PointDone
Point0:
	res 1,c				;<-0 into byte
PointDone:
	dec b
	jr nz,PointAgain	;Next Bitplane
	ld a,c
	ret
	
	align 4
PixelMask:
	db %10000000,%01000000,%00100000,%00010000
	db %00001000,%00000100,%00000010,%00000001
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
CalcVramAddr:	;B=Xpos C=Ypos
	ld d,0
	
	ld a,b
	and %11111000	;Xpos 
	sla a 
	rl d
	ld e,a			;Tile Xpos*8*2 (16 bytes per tile)
	ld h,d
	ld l,e
	
	ld d,&80		;&8000 Vram Tile pattern base
	
	ld a,c			;Calculate line in pattern
	and %00000111	;Yline*2 (2 bitplanes per line)
	rlca
	ld e,a
	add hl,de

	ld a,c
	and %11111000	;20*8*2 (20 tiles wide)
	ld d,a
	xor a
	srl d
	rra
	srl d
	rra
	srl d
	rra
	ld e,a			;Tile Ypos *16
	add hl,de		;Add it 
	
	srl d
	rra
	srl d			;Tile Ypos *4
	rra
	ld e,a	
	add hl,de		;Add it
	
	ld a,c
	cp 96			;Are we over first tilemap range?
	ret c			;16 unused tiles in first bank = 16*8*2=256
	inc h			;Step into Second tile map (+256)
	ret
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	

Palette:
	;   -grb
	dw &0000	;0 - Background
	dw &0099	;1
	dw &0E0F	;2
	dw &0FFF	;3 - Last color in 4 color modes
	dw &000F	;4
	dw &004F	;5
	dw &008F	;6
	dw &00AF	;7
	dw &00FF	;8
	dw &04FF	;9
	dw &08FF	;10
	dw &0AFF	;11
	dw &0CCC	;12
	dw &0AAA	;13
	dw &0888	;14
	dw &0444	;15
	dw &0000	;Border


	;Sprite Data of our Chibiko character, this needs to be in the native format of the graphics system we're working with
SpriteData2:
		incbin "\ResALL\sprites\GBTileScreen2.raw"  
SpriteData2End:
SpriteData1:
		incbin "\ResALL\sprites\GBTileScreen1.raw"  
SpriteData1End:

	;2 bit bitmap font, this is generic for all systems
BitmapFont:
	db 0
BitmapFontEnd:



SetGBCPalettes:
	ifdef BuildGBC
		ld hl,GBPal		
SetGBCPalettesb:
		ldi a,(hl)  	;GGGRRRRR
		ld e,a
		ldi a,(hl)  	;xBBBBBGG
		ld d,a
		inc a 			;cp 255
		ret z
		push hl
			call lcdwait ;Wait for VDP Sync
			ld hl,&ff68	
			ld (hl),c	;FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index
			inc hl			
			ld (hl),e	;FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data
			dec hl		
			inc	c		;Increase palette address
			ld (hl),c	;FF68 - BCPS/BGPI - CGB Mode Only - Background Palette Index
			inc hl		
			ld (hl),d	;FF69 - BCPD/BGPD - CGB Mode Only - Background Palette Data
			inc c		;Increase palette address
		pop hl
		jr SetGBCPalettesb
	endif
	

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

FillAreaWithTiles:
	;BC = X,Y)
	;HL = W,H)
	;DE = Start Tile

	ld a,h
	add b
	ld (zIXH),a
	ld a,l
	add c
	ld (zIXL),a
FillAreaWithTiles_Yagain:
	push bc
		
		push bc
			ld a,c
			ld c,b
			ld b,a
			ld	hl, $9800		;Get the position of the line
			xor a
			rr b
			rra
			rr b
			rra
			rr b
			rra
			or c
			ld c,a
			add hl,bc
		pop bc
		
FillAreaWithTiles_Xagain:
		ld a,e
		call LCDWait	;Wait for VDP Sync
		ldi (hl),a			;Write each line's bytes
		inc de
		inc b
		ld a,(zIXH)
		cp b
		jr nz,FillAreaWithTiles_Xagain
	pop bc
	inc c
	ld a,(zIXL)
	cp c
	jr nz,FillAreaWithTiles_Yagain
	ret
DefineTiles:	;Write BC bytes from HL to DE for tile definition
	call LCDWait	;Wait for VDP Sync
	ldi a,(hl)		;LD a,(hl), inc HL
	ld (de),a			
	inc de
	dec bc
	ld a,b
	or c
	jr nz,DefineTiles
	ret

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

GetVDPScreenPos:;Set HL to tilepos B=Xpos, C=Ypos
	xor a
	ld h,c		;Ypos*32
	rr h		;Each line is 32 tiles
	rra			;and each tile is 1 byte
	rr h
	rra
	rr h
	rra
	or b		;Add XPOS
	ld l,a
	ld a,h
	add &98		;The tilemap starts at &9800
	ld h,a
	ret
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


LCDWait:	;Wait for Vblanks so we can write to VRAM
	push af
LCDWaitAgain
        ld a,(&FF41)  	;STAT - LCD Status (R/W)
			;-LOVHCMM
        and %00000010	;MM=video mode (0/1 =Vram available)  		
        jr nz,LCDWaitAgain 
    pop af	
	ret
	
	
	
LCDWaitWrite:
	push bc
		ld b,a
LCDWaitWriteA	
;Wait for Vblanks so we can write to VRAM	
		ld a,(&FF41)  	;STAT - LCD Status (R/W)
		and %00000010	;MM=video mode (0/1 =Vram available)  		
		jr nz,LCDWaitWriteA
	
		ld (hl),b
;If Vblank occurred while we wrote - try again!
		ld a,(&FF41)  	;STAT - LCD Status (R/W)
		and %00000010	;MM=video mode (0/1 =Vram available)  		
		jr nz,LCDWaitWriteA	
	pop bc
	ret	
	
	
LCDWaitRead:	;Wait for Vblanks so we can write to VRAM
	push bc
LCDWaitReadA
;Wait for Vblanks so we can read to VRAM	
		ld a,(&FF41)  	;STAT - LCD Status (R/W)
		and %00000010	;MM=video mode (0/1 =Vram available)  		
		jr nz,LCDWaitReadA
	
		ld b,(hl)
;If Vblank occurred while we read - try again!	
		ld a,(&FF41)  	;STAT - LCD Status (R/W)
		and %00000010	;MM=video mode (0/1 =Vram available)  		
		jr nz,LCDWaitReadA	
		ld a,b
	pop bc
	ret	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CLS:
	call ScreenOff
	
	ld hl,&8000
	ld de,&8001
	ld bc,&1800
	ld (hl),0
	z_ldir
	
	call ScreenOn
	ret	
	

ReadJoystick:
	ld a,%11101111 	;Select UDLR
	ld (&FF00),a
	
	ld a,(&FF00)	;Read in Keys
;We Need to swap position of RL and UD 
	rra				;Store R into L
	rl l			
	rra				;Store L into L
	rl l
	
	rra
	rr h			;Put U into H
	rra
	rr h			;Put D into H
		
	ld a,%11011111		;Select Fire/SelectStart
	ld (&FF00),a
	
	rr l			;Put LR into H
	rr h
	rr l
	rr h
	
	ld a,(&FF00)	;Read in the Fire Buttons
	rra			;	A
	rr h
	rra			;	B
	rr h
	rra			;Select
	rr h
	rra			;Start
	rr h
	ld a,h
	ret
	
WaitForFire:
	call DoRandom		;Randomize seed
	call ReadJoystick 	
	and %00010000
	jr nz,WaitForFire

WaitForFireB:
	call DoRandom		;Randomize seed
	call ReadJoystick 	
	and %00010000
	jr z,WaitForFireB
	ret
	
ScreenOff:

StopLCD_wait:				;Turn off the screen so we can define our patterns
	ld      a,(&FF44)		;Loop until we are in VBlank
	cp      145             ;Is display on scan line 145 yet?
	jr      nz,StopLCD_wait ;no? keep waiting!
	ld      hl,&FF40		;LCDC - LCD Control (R/W)
	res     7,(hl)      	;Turn off the screen
	ret

ScreenOn:
	ld      hl,&FF40		;LCDC - LCD Control (R/W)	EWwBbOoC 
	set     7,(hl)          ;Turn on the screen
	ret

	

;		 	xBBBBBGGGGGRRRRR
GBPal:	dw %0000000000000000	;col 0
		dw %0111111111100000	;col 1
		dw %0111110000011111	;col 2
		dw %0000001111100000	;col 3	
	
		db 255
		
	read "\SrcGB\MultiPlatform_MultDiv.asm"
	read "\ResALL\Vector\VectorFont.asm"
	read "\Sources\Photon\PH_Title.asm"
	
	
	read "\SrcALL\MultiPlatform_ShowDecimal.asm"
	read "PH_VectorGB.asm"
	read "PH_MultiplatformGB.asm"
	read "PH_DataDefs.asm"
	read "PH_RamDefs.asm"
