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

UserRam Equ &8000				;System Memory

ScreenWidth40 equ 1
ScreenWidth equ 320
ScreenHeight equ 200

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


	ORG &00F0
	
	DB 0,5			;type 5 = machine code application program
	DW FileEnd-FileStart	;16 bit lenght
	DB 0,0,0,0,0,0,0,0,0,0,0,0 ;not used bytes
;Program starts at ORG &0100

FileStart:			
	LD SP,&100			;Set up a base stack pointer
	call ScreenINIT
	
;Connect to Joystick/Keys
	ld de,ENT_Keboardname
	ld a,11					;Open the keyboard as stream 11
	rst 48					;EXOS
	db 1 					;Open stream	

;Turn off Keyclick
	ld c,7	;Var 7 - CLICK_KEY 
	ld d,1	;1=NoClick
	ld b,1	;0=Read 1=Write 2=Toggle
	rst 48
	db 16		; Read, Write or Toggle EXOS Variable 

	call MainMenu

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

	ld bc,15				;Slow Down Delay

	ld a,(boost)
	or a
	jr nz,BoostOff
	ld bc,1
BoostOff:

	ld d,0
PauseBC:
	push bc
		push de
			call ReadJoystick
		pop de
		or a
		jr z,PauseNoKey
		ld d,a					;Store any pressed joystick buttons
		jr KeysDown
PauseNoKey:
	ld a,(KeyTimeout)
	or a
	jr z,KeysDown
	ld a,0
	ld (KeyTimeout),a
	ld d,0
KeysDown:
	pop bc

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


StartDraw:


	ld a,(KeyTimeout)
	or a
	jr nz,JoySkip

	ld a,1
	ld (boost),a


ProcessKeys:
	ld hl,PlayerDirection
	ld ix,PlayerXacc

	ld a,d
	cp &b8
	jr nz,JoyNotLeft	
	dec (hl)
	call SetPlayerDirection
	ld a,5
	ld (KeyTimeout),a
JoyNotLeft:
	ld a,d
	cp &bc
	jr nz,JoyNotRight	
	inc (hl)
	call SetPlayerDirection
	ld a,5
	ld (KeyTimeout),a
JoyNotRight: 
	ld a,d
	cp ' '
	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

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

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:		;X=AB Y=C color=D
	push de
		call GetPixelMask ;Get HL=Address E=Background Mask D=Pixel mask
	pop af
	call GetColorMaskNum

	and e		;Mask pixel color
	ld e,a
	ld a,(hl)
	and d		;Keep background pixels
	or e		;Or in New Pixel
	ld (hl),a
	ret


Point:
	push bc
		call GetPixelMask ;Get HL=Address E=Background Mask D=Pixel mask
		ld a,(hl)
		and e		;Mask pixel color
	pop bc
	call ByteToColorMask	;Fill all pixels with same color

	ld hl,ColorLookup	;Look up color 
	ld b,0
PointAgain:
	cp (hl)		
	jr z,PointDone
	inc hl
	inc b
	jr PointAgain
PointDone:
	ld a,b	
	ret

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

ByteToColorMask: ;Fill whole byte with color - eg %00000001 to %00001111
		 ;A=Color pixel... B=pixel pos (Xpos)
	ld c,a
	ld a,b
	and %00000011	;4 pixels per byte in Mode 1
	jr z,ByteToColorMaskNoShift ;Zero pos=no shift
	ld b,a
ByteToColorMaskLeftShift:
	sla c			;Shift C B times (color to far right
	djnz ByteToColorMaskLeftShift
ByteToColorMaskNoShift:
	ld a,c
	rrca		;Fill all the pixels with the same color
	or c
	rrca
	or c
	rrca
	or c
	ret			;All pixels in A now the same color


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

GetColorMaskNum:
	and %00000011	;4 pixels per byte in Mode 1
	ld bc,ColorLookup ;Get Color from LUT
	add c
	ld c,a 
	ld a,(bc)
	ret
	
GetPixelMask:	;(AB,C) = (X,Y)
;Returns HL=Mempos... D=Mask to keep background - E= pixel to select
	push bc	
		rra		;2 pixels per byte in mode 0
		rr b
		rra	;4 pixels per byte in mode 1
		rr b	
		call GetScreenPos ;Get Byte Position
	pop af
	and %00000011 ;4 pixels per byte in Mode 1
	ld bc,PixelBitLookup
	add c
	ld c,a 
	ld a,(bc)	;Get Pixel Mask for X position
	ld e,a
	cpl
	ld d,a	
	ret 

GetScreenPos:	;return memory pos in HL of screen co-ord B,C (X,Y)
				;Input  BC= XY (x=bytes - so 80 across)
				;Output HL= screen mem pos
	push de
;screen is 80 wide = 00000000 01010000
		ld h,C		;YYYYYYYY 00000000
		xor a
		
		srl h
		rra			;0YYYYYYY Y0000000
		srl h
		rra 		;00YYYYYY YY000000
		
		ld d,h
		ld e,a		;Store first part for later
		
		srl h
		rra			;000YYYYY YYY00000
		srl h
		rra			;0000YYYY YYYY0000
		
		add e		
		jr nc,GetScreenPos_NoOverflow
		inc h
GetScreenPos_NoOverflow:
		add B		;Add the X pos 
		ld l,a
		
		ld a,h
		adc d
		add &C0		;Add screen Base &C000
		ld h,a	
	pop de
	ret 			;return memory location in hl



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

WaitForFire:
	call DoRandom		;Reseed Random Numbers
	call ReadJoystick
	cp ' '
	jr nz,WaitForFire

WaitForFireB:
	call DoRandom		;Reseed Random Numbers
	call ReadJoystick
	cp ' '
	jr z,WaitForFireB
	ret
	 
ReadJoystick:
	push bc
		ld a,11 			;Keyboard is channel 11
		rst 48				;EXOS call
		db 9 				;Channel Read Status
		;Result in C (0=Byte waiting / 1=no byte / FF=StreamEnd)
			
		ld a,c				
		or a				;0=ready
		ld a,0				;return zero if z flag not set
		jr nz,TestChar_NoCharWaiting
		
		;Get the waiting character
		ld a,11 			;Keyboard is channel 11
		rst 48				;EXOS call
		db 5 				;Read from channel - result in b
		ld a,b
TestChar_NoCharWaiting:
	pop bc
	ret

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


	include "\SrcAll\MultiPlatform_MultDiv.asm"
	include "\ResALL\Vector\VectorFont.asm"
	include "\Sources\Photon\PH_Title.asm"
	include "\SrcALL\MultiPlatform_ShowDecimal.asm"
	include "PH_Vector.asm"
	include "PH_Multiplatform.asm"
	include "PH_DataDefs.asm"
	include "PH_RamDefs.asm"
	
Palette:
	db 0,23,8,18			;Palette in native format

	Align 4	
PixelBitLookup:	;Pixel positions
	db %10001000,%01000100,%00100010,%00010001
ColorLookup:	;Colors (all pixels one color)
	db %00000000,%11110000,%00001111,%11111111


cls:
	ld hl,&C000
	ld de,&C001
	ld bc,&3E80
	ld (hl),0
	ldir
	ret

	;The code below was based on an example from the Enterprise forever forum
ScreenINIT:
	di
	LD A,12		;disable memory wait states
	OUT (191),A	

	;setting the Border color to black

	LD BC,&100+27	;B=1 write
	;C=27 number of system variable (BORDER)	
	LD D,0			;new value
	rst 6*8
	db 16			;handling EXOS variable

	CALL BankSwitch_RequestVidBank	;get a free Video segment
	Jr NZ,VideoFail	;if not available then exit
	LD A,C		
	LD (VIDS),A		;store segment number page to the page 3.
	OUT (&B3),A		

	LD DE,0			;segment number low two bits
	RRA				;will be the top two bits of the video address
	RR D			
	RRA				
	RR D			
	LD (VIDADR1),DE ;this is the start of pixel data in the video memory

	LD HL,&3F00		;after the pixel bytes starting the Line Parameter Table (LPT)
	ADD HL,DE	
	LD (LPTADR),HL	
		
	LD HL,LPT		;Line Parameter Table copy to the end of video segment
	LD DE,&FF00	
	LD BC,LPTH	
	LDIR		
VidAgain:		
	LD HL,(LPTADR)	;LPT video address
	LD B,4			;4 bit rotate
LPTA:           SRL H
	RR L
	DJNZ LPTA
	LD A,L			;low byte send to Nick
	OUT (&82),A	
	LD A,H			;high 4 bits enable Nick running
	OR &C0		
	
	;switch to the new LPT at the end of current frame send to Nick
	OUT (&83),A	
			
VideoFail:
	ret



BankSwitch_RequestVidBank:           
	LD HL,FileEnd		;buffer area
	LD (HL),0			;start of the list
GetSegment:	
	rst 6*8				;get a free segment
	db 24			
	RET NZ				;if error then return
	LD A,C				;segment number
	CP &FC				;<0FCh?, no video segment?
	JR NC,ENDGET		;exit cycle if video
	INC HL				;next buffer address
	LD (HL),C			;store segment number
	JR GetSegment		;get next segment
ENDGET: 
	PUSH BC				;store segment number
FREES:	LD C,(HL)		;deallocate onwanted

		rst 6 *8
		db 25			;free non video segments

		DEC HL			;previoud buffer address
		JR Z,FREES		;continue deallocating when call the EXOS 25 function with
		;c=0 which is stored at the start of list, then got a error, flag is NZ
		
	POP BC				;get back the video segment number
	XOR A				;Z = no error
	ret

ENT_Keboardname: db 9,'KEYBOARD:'


;NICK Line Parameter Table (LPT)

LPT: DB 256-200		;Screen Size: 200 lines.... 
					;Two's complement of the number of scanlines in this mode line.
	   ;ICCRMMML
	db %00110010   		;I   VINT=0, no IRQ
						;CC  Colour Mode=01, 4 colours mode (2/4/16/256)
						;R   VRES=1, full vertical resolution (full/half)
						;MMM Video Mode=001, pixel graphics mode
						;L   Reload=0, LPT will continue
	
	DB 11   		;left margin=11
	DB 51  			;right margin=51
VIDADR1:  DW 0    	;primary video address, address of pixel data
	DW 0  			;secondary vide0 address, not used in pixel graphics mode
ENT_PALETTE:	
	; 	GRBGRBGR  	;g0 | r0 | b0 | g1 | r1 | b1 | g2 | r2 | - x0 = lsb 
	db %00000000	;Color 0: Black
	db %10110110	;Color 1: Cyan
	db %01101101	;Color 2: Magenta
	db %10010010	;Color 3: Green
	
	db 0,0,0,0 		;Colors 4-7 (unused)

;Line definitions			
	DB -50,&12,63,0,0,0,0,0,0,0,0,0,0,0,0,0	;50 lines of border, this is the bottom margin,
	DB -3,16,63,0,0,0,0,0,0,0,0,0,0,0,0,0	;3 black lines, syncronization off
	DB -4,16,6,63,0,0,0,0,0,0,0,0,0,0,0,0	;4 lines, syncronization on
	DB -1,&90,63,32,0,0,0,0,0,0,0,0,0,0,0,0	;1 line, syncronization will switch off at half of line
												;the NICK chip generate video IRQ at this line
	DB 252,&12,6,63,0,0,0,0,0,0,0,0,0,0,0,0 ;4 black lines
	DB -50,&13,63,0,0,0,0,0,0,0,0,0,0,0,0,0 ;50 lines of border, this is the top margin,
LPTEnd:              
LPTH equ LPTEnd-LPT ;length of LPT
	
VIDS:		DB 0	;variables for storing allocated memory
LPTADR:     DW 0		
	
FileEnd:
		
	