	nolist

	; Program that receives 10/11 bytes from the CPCBooster to be decoded before sending to the PSG.
	; We use a compressed buffer. We have to decode the 10 or 11 incoming bytes into a PSG stream.

	; For CPC only fitted with CPC Booster. Source compatible with Winape/Maxam.


Buffer equ #6000
Adr_Fonte equ #7000
CRTC_Reg1 equ 40


	org #4000			;>#3fff as the lower ROM is opened to get the system font.
	limit Buffer
	run $



	ld a,2
	call #bc0e


Test_CPCBooster
	di
	call CPCB_Init
	ei
	jp nc,CPCBooster_NotDetected



	di
	ld hl,#c9fb
	ld (#38),hl




	call VSync

	ld bc,#7f54
	ld a,#10
PaletteLoop
	out (c),a
	out (c),c
	sub 1
	jr nc,PaletteLoop



	ld bc,#7f8a			;Open lower ROM to get the system font.
	out (c),c
	ld hl,#3900
	ld de,Adr_Fonte
	ld bc,127-32*8
	ldir
	ld bc,#7f8e
	out (c),c


	ld hl,TXT_Main
	call LD_Affiche_Page

	ld bc,#7f01
	out (c),c
	ld a,#4b
	out (c),a
	ld c,#10
	out (c),c





	ld bc,#7f10
	out (c),c

	;call Vsync
	;ei



Mainloop
	ld bc,#ff1c
	ld hl,Stream
	call CPCB_GetByteFastInMemory
		ld bc,#7f44
		out (c),c
		ld bc,#ff1c
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory
	call CPCB_GetByteFastInMemory	;9
	and %11000000			;new R13 or new Replay Frequency ?
	jr z,LastByteReached
	call CPCB_GetByteFastInMemory
LastByteReached
		ld bc,#7f55
		out (c),c

	;Play the stream, after having decoded it.
	ld hl,Stream
	call PSG_DecodeStream
	ld hl,PSG_DecodedStream
	call Play_PSGRegisters

		ld bc,#7f54
		out (c),c
	call Keyboard


	jr Mainloop







;Keyboard management.
Keyboard
	ld a,8 + 64
	call Routouch
	cp %11111011
	jp z,0

	ld a,5 + 64
	call Routouch
	cp %01111111
	jr nz,WaitKB_NoSpace

Keyboard_Pushed ld a,0
	or a
	ret nz
	;Change the raster color.
ColorSwitch ld hl,#0210
	ld a,l
	ld (Keyboard_Pushed + 1),a
	ld l,h
	ld h,a
	ld (ColorSwitch + 1),hl
	ld bc,#7f54
	out (c),h
	out (c),c
	out (c),l
	out (c),c
	ret
WaitKB_NoSpace
	xor a
	ld (Keyboard_Pushed + 1),a
	ret






;Value list to send to the PSG to stop the sound.
PSG_NoSoundValues
	db 0,0,0,0,0,0,0,%00111111,0,0,0,0,0,0
PSG_NoSoundValues_End


Stream_NoSoundValues
	db 0,0,0,0,0,0,0,0,0,%00111111
Stream_NoSoundValues_End

;Where the encoded stream is written.
Stream	db 0,0,0,0,0,0,0,0,0,%00111111,0,0

;Stream actually decoded and sent to the PSG (R13 is #FFable).
PSG_DecodedStream db 0,0,0,0,0,0,0,0,0,%00111111

CPCBooster_NotDetected
	ld hl,TXT_CPCBooster_NotDetected
	call WriteSystem
	call #bb18
	jp Test_CPCBooster





;Write a sentence with the system.
WriteSystem
	ld a,(hl)
	or a
	ret z
	call #bb5a
	inc hl
	jr WriteSystem




VSync	ld b,#f5
	in a,(c)
	rra
	jr nc,VSync + 2
	ret


;Display a text page. Continues after each sentence, unless #ff is found.
;HL=Text to display.
LD_Affiche_Page
	call LD_Writter
	ld a,(hl)
	cp #ff
	ret z
	jr LD_Affiche_Page

;Writter.
;HL=Sentence to display.
;Format = No line Y (in caracters), text ending with 0.
;RET=HL=Points after the 0 at the end.
LD_Writter
	ld a,(hl)
	inc hl
	ld (LD_Writter_PtTexte + 1),hl

	ld hl,#c000
	or a
	jr z,LD_Writter_YFound
	ld de,CRTC_Reg1 * 2
LD_Writter_YFindLoop
	add hl,de
	dec a
	jr nz,LD_Writter_YFindLoop

LD_Writter_YFound
	ld (LD_Writter_AdEcrY + 1),hl


;Find the sentence to find its length.
	ld hl,(LD_Writter_PtTexte + 1)
	ld e,0				;Length.

LD_Writter_FindSize
	ld a,(hl)
	inc hl
	or a
	jr z,LD_Writter_SizeFound
	inc e
	jr LD_Writter_FindSize

LD_Writter_SizeFound

;Calcul the X of the text. X=(width screen - width text) /2
	ld a,CRTC_Reg1 * 2
	sub e
	srl a
	ld e,a
	ld d,0
LD_Writter_AdEcrY ld hl,0
	add hl,de
	ld (LD_Writter_PosEcr + 1),hl

;Text display
LD_Writter_PtTexte ld hl,0
	ld a,(hl)
	inc hl
	ld (LD_Writter_PtTexte + 1),hl
	or a
	ret z

	sub 32
	add a,a
	ld l,a
	ld h,0
	add hl,hl
	add hl,hl
	ld de,Adr_Fonte
	add hl,de
LD_Writter_PosEcr ld de,0
	ld bc,#808

LD_Writter_AffLoop
	ld a,(hl)
	ld (de),a
	inc hl

	ld a,d
	add a,c
	ld d,a
	djnz LD_Writter_AffLoop

	ld hl,(LD_Writter_PosEcr + 1)
	inc hl
	ld (LD_Writter_PosEcr + 1),hl
	jr LD_Writter_PtTexte



Routouch		;58 cycles with the RET.
	LD BC,#F782
	OUT (C),C
	LD BC,#F40E
	OUT (C),C
	LD BC,#F6C0
	OUT (C),C
	DEFB #ed,#71
	LD BC,#F792
	OUT (C),C
	DEC B
	OUT (C),A
	LD B,#F4
	IN A,(C)
	LD BC,#F782
	OUT (C),C
	DEC B
	DEFB #ed,#71
	RET




TXT_CPCBooster_NotDetected defb "CPCBooster not detected !",13,10,0

TXT_Main
 	defb 1, "Arkos Tracker - Client V1.0",0
	defb 8, "Ready to receive PSG values from server...",0

	defb 11, "Press Space to switch on/off the border flickering.",0
	defb 12, "Press Esc to quit.",0
	defb 23, "(c) Arkos 2010",0

	defb #ff





Play_PSGRegisters
	exx
	ld de,#c080
	ld b,#f6
	out (c),d	;#f6c0
	exx
	ld e,#f6
	ld bc,#f401

;Register 0
	defb #ed,#71	;#f400+Register
	ld b,e
	defb #ed,#71	;#f600
	dec b
	outi		;#f400+value
	exx
	out (c),e	;#f680
	out (c),d	;#f6c0
	exx

;Register 1
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 2
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 3
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 4
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 5
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 6
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 7
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 8
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	
	outi
	endif
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 9
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	
	outi
	endif
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 10
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	
	outi
	endif
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 11
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 12
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	inc c

;Register 13
	ld a,(hl)
	cp 255			;Don't send the value if =#ff.
	ret z
	out (c),c
	ld b,e
	defb #ed,#71
	dec b
	outi
	exx
	out (c),e
	out (c),d
	exx
	ret








;Decode a stream from the buffer into a decoded stream, ready to be sent to the PSG.
;R13 remains "#ff"able.
;HL=Buffer
;RET=PSG_DecodedStream ready.
PSG_DecodeStream
	ld ix,PSG_DecodedStream

	;By default, R13 is the same.
	ld (ix + 13),#ff

	;Low Freq1 (8bits)
	ld a,(hl)
	ld (ix+0),a
	inc hl

	;Low Freq2 (8bits)
	ld a,(hl)
	ld (ix+2),a
	inc hl

	;Low Freq3 (8bits)
	ld a,(hl)
	ld (ix+4),a
	inc hl
	
	;Low HardFreq (8bits)
	ld a,(hl)
	ld (ix+11),a
	inc hl

	;High HardFreq (8bits)
	ld a,(hl)
	ld (ix+12),a
	inc hl

	;HighFreq2 (7,6,5,4) + High Freq1 (3,2,1,0)
	ld a,(hl)
	and %1111			;Useless.
	ld (ix+1),a
	ld a,(hl)
	rra
	rra
	rra
	rra
	and %1111			;Useless.
	ld (ix+3),a
	inc hl

	;HighFreq3 (7,6,5,4) + Vol1 (3,2,1,0)
	ld a,(hl)
	rra
	rra
	rra
	rra
	and %1111			;Useless.
	ld (ix+5),a
	ld a,(hl)
	and %1111
	ld d,a				;D=Vol1 without hardware bit.
	inc hl

	;Vol3 (7,6,5,4) + Vol2 (3,2,1,0)
	ld a,(hl)
	and %1111
	ld e,a				;E=Vol2 without hardware bit.
	ld a,(hl)
	rra
	rra
	rra
	rra
	and %1111
	ld c,a				;C=Vol3 without hardware bit.
	inc hl

	;HVol3 (b7) + Hvol2 (b6) + Hvol1 (b5) + Noise (4,3,2,1,0)
	ld a,(hl)
	and %11111			;Useless.
	ld (ix + 6),a
	ld a,(hl)			;Mix HVol1 with Vol1.
	rra
	and %00010000
	or d
	ld (ix + 8),a

	ld a,(hl)			;Mix HVol2 with Vol2.
	rra
	rra
	and %00010000
	or e
	ld (ix + 9),a

	ld a,(hl)			;Mix HVol3 with Vol3.
	rra
	rra
	rra
	and %00010000
	or c
	ld (ix + 10),a
	inc hl

	;NewR13? (b7) + Mix (5,4,3,2,1,0)
	ld a,(hl)
	and %00111111
	ld (ix + 7),a
	ld a,(hl)
	ld c,a				;C = NewR13? (b7) and NewRFreq? (b6)
	and %11000000			;If both = 0, there is no other byte.
	ret z
	inc hl

	;11th byte.
	rl c				;NewR13?
	ret nc

	ld a,(hl)
	and %1111
	ld (ix + 13),a
	
	ret





	read "CPCBooster.asm"


	