
;Photon... battle of the Chibi Photonic hunters!

UserRam Equ &C000				;System Memory

Color1 equ &1
Color2 equ &2
Color3 equ &3
Color4 equ &4

	ifdef BuildSMS
ScreenWidth20 equ 1
ScreenWidth equ 192		;Define 24x18 Screen 
ScreenHeight equ 144	;(432 of 448 possible tiles)*
	else
ScreenWidth20 equ 1
ScreenWidth equ 160		;Define 20x18 Screen
ScreenHeight equ 144	;(360 of 448 possible tiles)
	endif
	
;* Theoretical limit is 512 tiles, but top 2k of VRAM is tilemap	
	
vdpOUT_Control equ &BF
vdpOUT_Data    equ &BE

	;Unrem this if building with vasm
	include "\SrcALL\VasmBuildCompat.asm"

	org &0000
	jr ProgramStart		;&0000 - RST 0
	ds 6,&C9			;&0002 - RST 0
	ds 8,&C9			;&0008 - RST 1
	ds 8,&C9			;&0010 - RST 2
	ds 8,&C9			;&0018 - RST 3
	ds 8,&C9			;&0020 - RST 4
	ds 8,&C9			;&0028 - RST 5
	ds 8,&C9			;&0030 - RST 6
	ds 8,&C9			;&0038 - RST 7
	ds 38,&C9			;&0066 - NMI
	ds 26,&C9			;&0080
						
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	; effective Start address &0080
ProgramStart:	
	di
    im 1    			;Interrupt mode 1
    ld sp, &dff0		;Default stack pointer

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
;									Init the screen 												

	ld hl,VdpInitData	;Source of data
    ld b,VdpInitDataEnd-VdpInitData		;Byte count
    ld c,vdpOUT_Control		;Destination port
    otir				;Out (c),(hl).. inc HL... dec B, djnz 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
;				Define Palette 												
	
    ld hl, &c000	    ; set VRAM write address to CRAM (palette) address 0
		; note &C0-- is a set palette command... it's not a literal memory address 
    call VDP_SetWriteAddress

    ld hl,PaletteData	;Source of data
	ifdef BuildSGG
		ld b,16*2 		;Byte count (32 on SGG)
	else
		ld b,16			;Byte count (16 on SMS)
	endif
	ld c,vdpOUT_Data		;Destination port
	otir				;Out (c),(hl).. inc HL... dec B, djnz  

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;				Fill the Tilemap												

	
	ifdef BuildSMS
		call ClearTilemap	;Fill Border with tile 447
	;Define 24x18 Screen (432 of 448 possible tiles)
		ld bc,&0403		;Start Position in BC
		ld hl,&1812		;Width/Height of the area to fill with tiles in HL
		;We have 16 tiles free! (for some kind of border?)
	else
	;Define 20x18 Screen
		ld bc,&0000		;Start Position in BC
		ld hl,&1412		;Width/Height of the area to fill with tiles in HL
	endif
						;We need to load DE with the first tile number we want 
						;to fill the area with.
	ld de,0			
	
	call FillAreaWithTiles		;Fill a grid area with consecutive tiles 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	ld hl,UserRam			;Clear Game Ram
	ld de,UserRam+1
	ld bc,256
	ld (hl),0
	ldir

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

ReadJoystick:
		in a,(&DC)	;UD are in Player1's port	---FRLDU 0=Down 1=up
	ret
	
WaitForFire:
	call DoRandom
	call ReadJoystick 			; KM Get Joystick... Returns ---FRLDU
	and %00010000
	jr nz,WaitForFire

WaitForFireB:
	call DoRandom
	call ReadJoystick 			; KM Get Joystick... Returns ---FRLDU
	and %00010000
	jr z,WaitForFireB
	ret


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

	
	
	
	
	
PSET:		;BC=XYpos  D=Color
	ld a,b
	cp 24*8	;Don't try to draw offscreen!
	ret nc
	push ix
	push iy
	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
				call VDP_SetReadAddress
			pop bc			
			in a,(VdpOut_Data)
			and c
			ld ixh,a			;Read Bitplane 0
			in a,(VdpOut_Data)
			and c
			ld ixl,a			;Read Bitplane 1
			in a,(VdpOut_Data)
			and c
			ld iyh,a			;Read Bitplane 2
			in a,(VdpOut_Data)
			and c
			ld iyl,a			;Read Bitplane 3
			call VDP_SetWriteAddress
		pop de
		ld a,ixh
		rr d
		jr nc,Pset1
		or b					;Set Bitplane 0
Pset1:
		out (VdpOut_Data),a
		ld a,ixl
		rr d
		jr nc,Pset2
		or b					;Set Bitplane 1
Pset2:
		out (VdpOut_Data),a
		ld a,iyh
		rr d
		jr nc,Pset3
		or b					;Set Bitplane 2
Pset3:
		out (VdpOut_Data),a
		ld a,iyl
		rr d
		jr nc,Pset4
		or b					;Set Bitplane 3
Pset4:
		out (VdpOut_Data),a
	pop bc
	pop iy
	pop ix
	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
		call VDP_SetReadAddress
	pop de
	ld c,0
	ld b,4
PointAgain:
	srl c				;Shift bits right
	in a,(VdpOut_Data)
	and d
	jr z,Point0
	set 3,c				;<-1 into byte
	jr PointDone
Point0:
	res 3,c				;<-0 into byte
PointDone:
	djnz PointAgain
	ld a,c
	ret
	
	align 4
PixelMask:
	db %10000000,%01000000,%00100000,%00010000,%00001000,%00000100,%00000010,%00000001
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
CalcVramAddr:	;B=Xpos C=Ypos
	ld d,0
	
	ld a,b
	and %11111000	;Xpos 
	sla a 
	rl d
	sla a
	rl d
	ld e,a			;Tile Xpos*8*4 (32 bytes per tile)
	ld h,d
	ld l,e
	
	ld d,0
	ld a,c
	and %00000111	;Yline*4 (4 bitplanes per line)
	rlca
	rlca
	ld e,a
	add hl,de

	ld a,c
	and %11111000	;20*8*4 / 24*8*4
	ld d,a
	xor a
	srl d
	rra
	srl d
	rra
	ld e,a			;Tile Ypos *16
	add hl,de
	
	srl d			;Tile Ypos *8
	rra
	ifdef BuildSGG
		srl d		;Tile Ypos *4
		rra
	endif
	ld e,a
	add hl,de		;Add *8 / 4
	ret

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

FillAreaWithTiles:	;BC = X,Y	HL = W,H 	DE = Start Tile
	ld a,h				;Calculate End Xpos
	add b
	ld h,a
	ld a,l				;Calculate End Ypos
	add c
	ld l,a
FillAreaWithTiles_Yagain:
	push bc
		push hl
			call GetVDPScreenPos	;Move to the correcr VDP location
		pop hl	
FillAreaWithTiles_Xagain:;Tilemap takes two bytes, ---pcvhn nnnnnnnn
		ld a,e			;nnnnnnnn - Tile number
		out (VdpOut_Data),a	
		ld a,d			;---pcvhn - p=Priority (1=Sprites behind) C=color palette 
		out (VdpOut_Data),a	;(0=back 1=sprite), V=Vert Flip, H=Horiz Flip, N=Tilenum (0-511)
		inc de
		inc b			;Increase Xpos
		ld a,b
		cp h			;Are we at the end of the X-line?
		jr nz,FillAreaWithTiles_Xagain
	pop bc
	inc c				;Increase Ypos
	ld a,c
	cp l				;Are we at the end of the height Y-line?
	jr nz,FillAreaWithTiles_Yagain
	ret
	

	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					VDP Register settings (needed to turn on screen)							

VdpInitData:
	db %00000110,128+0 ; reg. 0, display and interrupt mode.
	db %11100001,128+1 ; reg. 1, display and interrupt mode.
	db &ff		,128+2 ; reg. 2, name table address. &ff = name table at &3800
	db &ff		,128+3 ; reg. 3, Name Table Base Address  (no function) &0000
	db &ff 		,128+4 ; reg. 4, Color Table Base Address (no function) &0000
	db &ff		,128+5 ; reg. 5, sprite attribute table. -DCBA98- = bits of address $3f00
	db &00		,128+6 ; reg. 6, sprite tile address. -----D-- = bit 13 of address $2000
	db &00		,128+7 ; reg. 7, border color. 			----CCCC = Color
	db &00 		,128+8 ; reg. 8, horizontal scroll value = 0.
	db &00		,128+9 ; reg. 9, vertical scroll value = 0.
	db &ff 		,128+10; reg. 10, raster line interrupt. Turn off line int. requests.
VdpInitDataEnd:	
	ret

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

GetVDPScreenPos:	;Move to a memory address in VDP by BC cursor pos
	push bc				;B=Xpos, C=Ypos
		ifdef BuildSGG
			ld a,c
			add 3		;Need add 3 on Ypos for GG to reposition screen
			ld h,a
		else 
			ld h,c
		endif
		xor a			
		rr h			;Multiply Y*64
		rra
		rr h
		rra
		rlc b			;Multiply X*2 (Two byte per tile)
		or b
		ifdef BuildSGG
			add 6*2		;Need add 6 on Xpos for GG to reposition screen
		endif
		ld l,a
		ld a,h
		add &38			;Address of TileMap &3800 
		ld h,a				;(32x28 - 2 bytes per cell = &700 bytes)
		call VDP_SetWriteAddress
	pop bc
	ret
	
		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

VDP_SetReadAddress:				;Set VRAM address next write will occur
	ld a, l
    out (VdpOut_Control), a		;Send L byte
    ld a, h
    out (VdpOut_Control), a		;Send H  byte	
	ret     
	
VDP_SetWriteAddress:			;Set VRAM address next write will occur
	ld a, l
    out (VdpOut_Control), a		;Send L byte
    ld a, h
    or %01000000				;Set WRITE (0=read)
    out (VdpOut_Control), a		;Send H  byte
	
	ret            
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Clear entire tilemap to tile 447 (Unused areas on SMS)
ClearTilemap:
	ld hl,&3800
	call VDP_SetWriteAddress	;Set VRAM address we want to write to
	
	ld bc,32*24
	ld de,447	;Tilenum
ClearTilemapAgain:	
	ld a,e
	out (VdpOut_Data),a	
	ld a,d
	out (VdpOut_Data),a	
	dec bc
	ld a,b 
	or c
	jr nz,ClearTilemapAgain
	ret	
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cls:
	ld hl,&0000
	call VDP_SetWriteAddress	;Set VRAM address we want to write to
	ifdef BuildSMS
		ld bc,8*4*24*18			;Bytes to zero
	else
		ld bc,8*4*20*18
	endif
clsAgain:
	xor a
	out (VdpOut_Data),a			;Zero byte of Vram
	dec bc
	ld a,b 
	or c
	jr nz,clsAgain
	ret	

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

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
	

	read "\SrcAll\MultiPlatform_MultDiv.asm"
	read "\ResALL\Vector\VectorFont.asm"
	read "\Sources\Photon\PH_Title.asm"
	
	
	read "\SrcALL\MultiPlatform_ShowDecimal.asm"
	read "PH_Vector.asm"
	read "PH_Multiplatform.asm"
	read "PH_DataDefs.asm"
	read "PH_RamDefs.asm"


PaletteData:
	ifdef BuildSGG					;SGG
		   ;GGGGRRRR, ----BBBB
		db %00000000,%00000000;0
		db %11110000,%00001111;1
		db %00001111,%00001111;2
		db %11110000,%00000000;3
		db %11111111,%00000000;4
		db %00001111,%00001111;5
		db %00001111,%00001111;6
		db %00001111,%00001111;7
		db %00001111,%00001111;8
		db %00001111,%00001111;9
		db %00001111,%00001111;10
		db %00001111,%00001111;11
		db %00001111,%00001111;12
		db %00001111,%00001111;13
		db %00001111,%00001111;14
		db %11111111,%00000000;15
	else 							;SMS
		;   --BBGGRR
		db %00000000	;0
		db %00111100	;1
		db %00110011	;2
		db %00001100	;3
		db %00001111	;4
		db %00001111	;5
		db %00001111	;6
		db %00001111	;7
		db %00001111	;8
		db %00001111	;9
		db %00001111	;A
		db %00001111	;B
		db %00001111	;C
		db %00001111	;D
		db %00001111	;E
		db %00001111	;F
	endif
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;										Footer													

	
	org &7FF0
	db "TMR SEGA"	;Fixed data (needed by some SGG)
	db 0,0			;Reserved
	db &69,&69		;16 bit Checksum (sum of bytes $0000-$7FEF... Little endian)
					;Only needed for 'Export SMS', not checked by emulator without bios
	db 0,0,0 		;BCD Product Code & Version
	
	ifdef BuildSGG	;Region & Rom size (see below) - only checked by SMS export bios
		db &6C		;GG Export - 32k
	else
		db &4C		;SMS Export - 32k
	endif

;&3- SMS Japan 
;&4- SMS Export 
;&5- GG 	Japan 
;&6- GG 	Export 
;&7- GG 	International 
;&-C 32KB   
;&-F 128KB   
;&-0 256KB   
;&-1 512KB

 