
Mode0 equ 1		;Screen mode of test 1/0

	nolist
	org &100

	ifdef Mode0
		ld a,0
	else
		ld a,1
	endif
	call &BC0E	;Change Screen mode	


	call BuildLUTs	;Build Lookup tables

	ld bc,&0000
	call GetScreenPos	;DE=Screen Mem pos

;1x Scale
	ld hl,Image	;Screen Source
	ld ixl,48	;Sprite Heigh
	ld iyl,12	;Sprite Width (Byte)
	call DoScale1x	
	
	ld bc,&0B00
	call GetScreenPos	;DE=Screen Mem pos

;2x Scale
	ld hl,Image	;Screen Source
	ld ixl,48	;Sprite Heigh
	ld iyl,12	;Sprite Width (Byte)
	call DoScale2x

	ld bc,&2000
	call GetScreenPos	;DE=Screen Mem pos
;4x Scale
	ld hl,Image	;Screen Source
	ld ixl,48	;Sprite Heigh
	ld iyl,12	;Sprite Width (Byte)
	call DoScale4x

	di
	halt
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;HL=Sprite Source, DE=Dest VRAM Address, IXL/IYL = Width/Height
DoScale1x:			
	ld b,ixl
SpriteNextLine:
	push de
		ld a,iyl
		ld c,a		;Bytes per line (Width)
SpriteNextByte:
		ld a,(hl)	;Source Byte
		ld (de),a	;Screen Destination

		inc de		;INC Source (Sprite) Address
		inc hl		;INC Dest (Screen) Address

		dec c 		;Repeat for next byte
		jr nz,SpriteNextByte
	pop de
	call GetNextLineDE	;Scr Next Line (Alter HL to move down a line)
	djnz SpriteNextLine	;Repeat for next line
	ret

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

;HL=Sprite Source, DE=Dest VRAM Address, IXL/IYL = Width/Height
DoScale2x:
	ld bc,LUT2x	
SpriteNextLine2x:
	push hl
		ld iyh,2	;Duplicate lines
SpriteNextLineCopy:
	pop hl
	push hl
	push de
		ld a,iyl
		ld ixh,a	;Bytes per line (Width)
SpriteNextByte2x:
;Source Byte
		ld c,(hl)	;Source Byte
;Dest Byte 1
		ld a,(bc)	;Convert via LUT	
		ld (de),a	;Screen Destination
		inc de		;INC Dest (Screen) Address
		inc b
;Dest Byte 2
		ld a,(bc)
		ld (de),a	;Screen Destination
		inc de		;INC Dest (Screen) Address
;Next Source Byte
		dec b		;Reet LUT address
		inc hl		;INC Source (Sprite) Address
		dec ixh 	;Repeat for next byte
		jr nz,SpriteNextByte2x
	pop de
	call GetNextLineDE

	dec iyh
	jr nz,SpriteNextLineCopy	
	inc sp			;Skip over backed up H
	inc sp

	dec ixl
	jr nz,SpriteNextLine2x	;Repeat for next line
	ret	
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;HL=Sprite Source, DE=Dest VRAM Address, IXL/IYL = Width/Height
DoScale4x:
	ifdef Mode0
		ld bc,LUT2x	;We can use 2x LUT for mode 0
	else
		ld bc,LUT4x
	endif
SpriteNextLine4x:
	push hl
		ld iyh,4	;Duplicate lines
SpriteNextLineCopy4x:
	pop hl
	push hl
	push de
		ld a,iyl	
		ld ixh,a	;Bytes per line (Width)
SpriteNextByte4x
		ld c,(hl)	;Source Byte	
;Dest Byte 1
		ld a,(bc)
		ld (de),a	;Screen Destination
		inc de		;INC Dest (Screen) Address
;Dest Byte 2
		ifndef Mode0
			inc b	
			ld a,(bc)
		endif
		ld (de),a	;Screen Destination
		inc de		;INC Dest (Screen) Address
		inc b
;Dest Byte 3
		ld a,(bc)
		ld (de),a	;Screen Destination
		inc de		;INC Dest (Screen) Address
;Dest Byte 4
		ifndef Mode0
			inc b	
			ld a,(bc)
		endif
		ld (de),a	;Screen Destination
		inc de		;INC Dest (Screen) Address
;Next Source Byte
		dec b		;Reset LUT address
		ifndef Mode0
			dec b
			dec b
		endif
		inc hl		;INC Source (Sprite) Address
		dec ixh 	;Repeat for next byte
		jr nz,SpriteNextByte4x
	pop de
	call GetNextLineDE

	dec iyh
	jr nz,SpriteNextLineCopy4x	
	inc sp			;Skip over backed up H
	inc sp
	
	dec ixl
	jr nz,SpriteNextLine4x	;Repeat for next line
	ret

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



GetScreenPos:	;return memory pos in HL of screen co-ord B,C (X,Y)
;	; Input  BC= XY (x=bytes - so 80 across)
;	; output DE= screen mem pos

;

;Looking at Y line (in C) - we need to take each set of bits, and work with them separately:
;YYYYYYYY	Y line number (0-200)
;-----YYY	(0-7)  - this part needs to be multiplied by &0800 and added to the total
;YYYYY---	(0-31) - This part needs to be multiplied by 80 (&50)



;YYYYY---	(0-31) - This part needs to be multiplied by 80 (&50)
	push hl
		;screen is 80 bytes wide = -------- %01010000
		ld a,C		; 00000000 01010000
		and %11111000 	; -------- -YYYY---
		ld h,0
		ld l,a
				; 00000000 01010000
		
		sla l		; -------- YYYY----
		rl h
		
		ld d,h		;value is in first bit position -add it
		ld e,l	
				; 00000000 01010000
		sla e		; -------Y YYY-----
		rl d		;	    
		sla e		; ------YY YY------
		rl d
		
		add hl,de	;value is in 2nd bit position - add it
		;We've now effectively multiplied by 80 (&50)

	;-----YYY	(0-7)  - this part needs to be multiplied by &0800 and added to the total
		ld a,C
		and %00000111	
		
		rlca		;X8
		rlca
		rlca

		ld d,a		;Load into top byte, and add as 16 bit
		ld e,0

		add hl,de
		;We've now effectively multiplied by 8

	;Screen Base
		ld a,&C0	;Add the screen Base &C000
		ld d,a

	;X position
		ld e,B		;Add the X pos 
		add hl,de
		ex de,hl
	pop hl

	ret 		;return memory location in de
	
GetNextLineDE:

		ld a,d		;Add &08 to H (each CPC line is &0800 bytes below the last
		add &08
		ld d,a
			;Every 8 lines we need to jump back to the top of the memory range to get the correct line
			;The code below will check if we need to do this - yes it's annoying but that's just the way the CPC screen is!
		bit 7,d		;Change this to bit 6,h if your screen is at &8000!
		ret nz
		push hl
			ld hl,&c050	;if we got here we need to jump back to the top of the screen - the command here will do that
			add hl,de
			ex de,hl
		pop hl
	ret
	

	ifndef Mode0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Mode 1 LUTS

BuildLUTs:

;Build 2x Scaled sprite lut

	ld hl,LUT2X		;Lookup Table for 2x zoom... 2 bytes per entry
	ld b,0			;256 bytes
FillLutAgain:
	ld a,b
	and %10001000	;Convert pixels AB-- to AABB
	ld c,a
	ld a,b
	and %01000100
	rrca
	or c
	ld c,a
	rrca
	or c	
	ld (hl),a

	inc h			;Next Dest Byte

	ld a,b
	and %00100010	;Convert pixels --CD to CCDD
	rlca
	ld c,a
	ld a,b
	and %00010001
	or c
 	ld c,a
	rlca
	or c
	ld (hl),a

	dec h
	inc l
	inc b
	jr nz,FillLutAgain ;Next Source Byte

;Build 4x Scaled Sprite LUT:

	ld hl,LUT4x		;4 Bytes per Entry
	ld b,0			;256 bytes
FillLutAgain4x:
	ld a,b
	and %10001000	;Convert pixels A--- to AAAA
	ld c,a
	rrca
	or c
	rrca
	or c
	rrca
	or c
	ld (hl),a
	inc h

	ld a,b
	and %01000100	;Convert pixels -B-- to BBBB
	rlca
 	ld c,a
	rrca
	or c
	rrca
	or c
	rrca
	or c
	ld (hl),a
	inc h

	ld a,b
	and %00100010	;Convert pixels --C- to CCCC
	rrca
	ld c,a
	rlca
	or c
	rlca
	or c
	rlca
	or c
	ld (hl),a
	inc h	

	ld a,b
	and %00010001	;Convert pixels ---D to DDDD
	ld c,a
	rlca
	or c
	rlca
	or c
	rlca
	or c
	ld (hl),a

	dec h
	dec h
	dec h
	inc l
	inc b
	jr nz,FillLutAgain4x
	ret

	else

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Mode 0 LUTS

BuildLUTs:

;Build 2x Scaled sprite lut

	ld hl,LUT2X		;Lookup Table for 2x zoom
	ld b,0			;256 bytes
FillLutAgain:
	ld a,b
	and %10101010	;Convert pixels A-- to AA
	ld c,a
	rrca
	or c
	ld (hl),a

	inc h

	ld a,b
	and %01010101	;Convert pixels A-- to AA
	ld c,a
	rlca
	or c
	ld (hl),a

	dec h
	inc l
	inc b
	jr nz,FillLutAgain

;Build 4x Scaled Sprite LUT not needed for mode 0
	
	endif

Image:
	ifdef Mode0
		incbin "\ResALL\Sprites\RawCPC16.RAW"
	else
		incbin "\ResALL\Sprites\SpriteCPC.raw"
	endif


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

	ifdef VASM
		align 8			;use whole byte eg: &10xx
	else
		align 256
	endif
	
LUT2x:
	ds 512	;Lookup table for 2x scale (2 bytes per input byte)

	ifndef Mode0	;Don't need 2nd LUT for mode 0
LUT4x:
		ds 1024	;Lookup table for 4x scale (4 bytes per input byte)
	endif
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


