;*** renderer code ***

;was PUTTILE
.REND_DoScroll

	ld A,(FRAME)
	inc A
	ld (FRAME),A

	and 7
	
	ld (TILESCROLL),A
	jr nz,REND_DoScroll_Continue
	
	ld A,(TILEPOS)
	inc A
	and 3
	ld (TILEPOS),A
	jr nz,REND_DoScroll_Continue
	
	ld A,(TILENO)
	inc A
	ld (TILENO),A
	
.REND_DoScroll_Continue	

 	ld A,(NOSCROLL)
 	and A
 	ret nz
	
	ld A,(TILESCROLL)	;update only 1 on 2 frame
	and 1
	ret nz
	
	ld A,(TILENO)
	ld L,A
	ld H,0
	add HL,HL	;*2
	add HL,HL	;4
	add HL,HL	;*8
	add HL,HL	;*16
	ex DE,HL
	
	ld A,(TILEPOS)
	ld L,A
	ld H,0
	add HL,HL
	add HL,HL	;*4
	
	add HL,DE
	
	ld A,(TILESCROLL)
	srl A
	or L
	ld L,A
	
	ld A,(NOSCROLL)
	or A
	ret nz
	
	ld BC,#7FC4
	out (C),C
	call REND_SetScrollPos

	
	ret


;set scroll position
;
; HL = position in pixels
;
.REND_SetScrollPos

	ld A,L
	and 3	;get pix offset
	push HL
	call REND_SelectGroup
	pop HL
	ld A,L
	and %00001100
	sra A	;get tile offset
;break	
	push HL
	ld L,A
	ld H,0
	ld DE,SetScrollPosTable
	add HL,DE
	ld C,(HL)
	inc HL
	ld B,(HL)
	
	ld (REND_StepSelect0),BC
	ld (REND_StepSelect1),BC
	ld (REND_StepSelect2),BC
	ld (REND_StepSelect3),BC
	ld (REND_StepSelect4),BC
	
	pop HL
	
repeat 4
	sra H
	rr L
rend
	ld A,L

	call REND_PutMap	

	ret
.SetScrollPosTable
	dw REND_PutLine_step0
	dw REND_PutLine_step1
	dw REND_PutLine_step2
	dw REND_PutLine_step3

;select level map to use
; A = group
.REND_SelectGroup
	add A,A
	
	ld L,A
	ld H,0	
;get patterns	
	ld DE,#4002
	add HL,DE
	ld E,(HL)
	inc HL
	ld D,(HL)
	ld (REND_CurrentGroup),DE
	inc HL
;get map	
	ld L,A
	ld H,0
	ld DE,#400A
	add HL,DE
	ld E,(HL)
	inc HL
	ld D,(HL)
	ld (REND_CurrentMap),DE
	ret
	
.REND_CurrentMap
	dw 0

;transfert map into attribute array
; A = column
.REND_PutMap
;break
	ld IY,(REND_CurrentMap)
	
	ld L,A
	ld H,0
	ld E,A
	ld D,H
	
	add HL,HL
	add HL,HL
	add HL,DE
	
	ex DE,HL
	add IY,DE

	push IY
	ld BC,ATTR_Line_Base	
REND_StepSelect0 EQU $+1
	call REND_PutLine_step0
	pop IY
	inc IY
	
	push IY
	ld BC,ATTR_Line_Base+#80
REND_StepSelect1 EQU $+1
	call REND_PutLine_step0
	pop IY
	inc IY
	
	push IY
	ld BC,ATTR_Line_Base+#500
REND_StepSelect2 EQU $+1
	call REND_PutLine_step0
	pop IY
	inc IY
	
	push IY
	ld BC,ATTR_Line_Base+#580
REND_StepSelect3 EQU $+1
	call REND_PutLine_step0
	pop IY
	inc IY
	
	push IY
	ld BC,ATTR_Line_Base+#A00
REND_StepSelect4 EQU $+1
	call REND_PutLine_step0
	pop IY
	inc IY
	
	ret
	
.REND_PutLine_step2
	ld A,4
	ld (REND_BlocOffset),A
	ld A,2
	ld (REND_BlocWidth),A
	
	ld A,(IY)
	push BC
	push IY
	call REND_PutBloc
	pop IY
	
	ld BC,5
	add IY,BC
	pop BC
	ld A,2
	add C
	ld C,A
	
	xor A
	ld (REND_BlocOffset),A
	ld A,4
	ld (REND_BlocWidth),A
	
	ld D,7
	call REND_PutLine_loop

	xor A
	ld (REND_BlocOffset),A
	ld A,2
	ld (REND_BlocWidth),A	
	ld A,(IY)
	call REND_PutBloc
	
	ret
	
.REND_PutLine_step3
	ld A,6
	ld (REND_BlocOffset),A
	ld A,1
	ld (REND_BlocWidth),A
	
	ld A,(IY)
	push BC
	push IY
	call REND_PutBloc
	pop IY
	
	ld BC,5
	add IY,BC
	pop BC
	inc C
	
	xor A
	ld (REND_BlocOffset),A
	ld A,4
	ld (REND_BlocWidth),A
	
	ld D,7
	call REND_PutLine_loop

	xor A
	ld (REND_BlocOffset),A
	ld A,3
	ld (REND_BlocWidth),A	
	ld A,(IY)
	call REND_PutBloc
	
	ret
	
.REND_PutLine_step1
	ld A,2
	ld (REND_BlocOffset),A
	ld A,3
	ld (REND_BlocWidth),A
	
	ld A,(IY)
	push BC
	push IY
	call REND_PutBloc
	pop IY
	
	ld BC,5
	add IY,BC
	pop BC
	ld A,3
	add C
	ld C,A
	
	xor A
	ld (REND_BlocOffset),A
	ld A,4
	ld (REND_BlocWidth),A
	
	ld D,7
	call REND_PutLine_loop

	xor A
	ld (REND_BlocOffset),A
	ld A,1
	ld (REND_BlocWidth),A	
	ld A,(IY)
	call REND_PutBloc
	
	ret
	
	
.REND_PutLine_step0

	xor A
	ld (REND_BlocOffset),A
	ld A,4
	ld (REND_BlocWidth),A

	ld D,8

.REND_PutLine_loop	
	
	push DE
	push BC

	ld A,(IY)
	push IY
	call REND_PutBloc
	pop IY
	
	ld BC,5
	add IY,BC
	
	pop BC
	ld A,4
	add C
	ld C,A
	pop DE
	
	dec D
	jr nz,REND_PutLine_loop	
	ret
	
;transfert pattern to attribute array
;	BC = array address
;	A = bloc
;
.REND_PutBloc

	push BC		;keep target adress
	
	bit 7,A
	push AF
	;and 63
	and 127		;fixed bug here , changed to 127 max patterns, is a safe value ?

	ld L,A
	ld H,0
	
	add HL,HL	;2
	add HL,HL	;4
	add HL,HL	;8
	add HL,HL	;16
	add HL,HL	;32
	
	ld DE,(REND_CurrentGroup)
	add HL,DE
	
	pop AF
	jr z,REND_PutBlocPositiveWay
	
	ld A,-8
	ld (REND_PutBlock_Way),A
	ld A,16+3+128
	ld (REND_PutBloc_flags),A
	ld A,24
	add L
	ld L,A
	jr REND_PutBloc_WayDone
.REND_PutBlocPositiveWay	
	ld A,8
	ld (REND_PutBlock_Way),A
	ld A,3+128
	ld (REND_PutBloc_flags),A
.REND_PutBloc_WayDone

REND_BlocOffset	EQU $+1	
	ld A,0
	add L
	ld L,A
	
	push HL
	pop IX
	
	pop HL
	
; HL = screen address , IX = pattern address

REND_BlocWidth	EQU $+2
	ld BC,#0404

.REND_PutBloc_loop0
	push BC
	push HL
	push IX

.REND_PutBloc_loop1

	ld C,H

;check bank first
	ld A,(IX)
	and 15
	jr z,REND_PutBlocSkip
	
;flags
REND_PutBloc_flags EQU $+1
	ld (HL),128+3 ;is solid !
	inc H
	
	or #C0
	ld (HL),A
	inc H
;addr low	
	ld A,(IX)
	and %11110000
	ld (HL),A
	inc H
;addr high
	inc IXL
	ld A,(IX)
	ld (HL),A
	inc H
;master
	ld (HL),0	;level is always null
.REND_PutBlocSkipDone
	inc IXL
	inc L
	ld H,C

	djnz REND_PutBloc_loop1
	
	pop IX
REND_PutBlock_Way EQU $+1 
	ld A,8
	add IXL
	ld IXL,A
	
	pop HL
	ld A,#20
	add L
	ld L,A
	
	pop BC
	dec C
	jr nz,REND_PutBloc_loop0

	ret
.REND_PutBlocSkip
	bit 6,(HL)	;temp stuff for erasable stuff
	jr nz,REND_PutBlocSkip_NoErase
	
	bit 1,(HL)
	jr z,REND_PutBlocSkip_NoErase
	ld (HL),4
.REND_PutBlocSkip_NoErase	
	inc IXL
	jr REND_PutBlocSkipDone

.REND_CurrentGroup
	dw 0

;********************************
;*** RENDER ATTRIBUTE ARRAY ***
;********************************
	
.REND_Udpate

	ld H,rend_table_low
	ld A,(TILESCROLL)
	and 1
	ld B,A
	ld A,(NOSCROLL)
	or B
	add H
	ld H,A

	exx
	ld DE,#C000
	ld B,#7F
	ld IYL,20
	ld C,63
	
	ld IX,ATTR_Addr

.REND_Update_loop1
	push BC
	push DE

	ld L,(IX+0)
	ld H,(IX+1)
	inc IXL
	inc IXL
	
	ld IYH,32

.REND_Update_loop2
	ld A,(HL)		;2
	and C			;1
	jr z,REND_Done	;3/2	so no flags is 6 nops
	add A			;1
	exx				;1
	ld L,A			;1
	ld E,(HL)		;2
	inc L			;1
	ld D,(HL)		;2
	ex DE,HL		;1
	jp (HL)			;1	10 nops for all cases	

.REND_Error			;error ! unknown type
	break
	ex DE,HL		;1
	exx				;1
	ld (HL),4		;3	erase error !
	jr REND_Done	;3	18 nops = 12 nops penality for error
.REND_Ignore
	ex DE,HL		;1
	exx				;1	12 nops = 6 nops penality for ignore termination
	
.REND_Done
	inc E
	inc E
	inc L
	
	dec IYH
	jr nz,REND_Update_loop2
	
	pop HL
	ld BC,64
	add HL,BC
	ex DE,HL
	
	pop BC
	
	dec IYL
	jr nz,REND_Update_loop1

	ret
	
;*******************************
;** Draw a XY reversed sprite **
;*******************************	
.REND_Sprite_FlipXY
	ex DE,HL	;1
	exx			;1

	push BC
	push HL
		
	ld (HL),4	;auto erase
	
	inc H		;1
	ld A,(HL)	; 2 get bank
	out (C),A	;4

	inc H		;1 get address
	ld A,(HL)	;2
	inc H		;1
	ld H,(HL)	;2
	ld L,A		;1
	
	ld B,rev_table_high
	inc E
	
	ld A,%00111000
	or D
	ld D,A

	draw_char_revXY_opt
	
	pop HL
	pop BC

	jp REND_Done

;******************************
;** Draw a X reversed sprite **
;******************************
.REND_Sprite_FlipX
	ex DE,HL	;1
	exx			;1

	push BC
	push HL
		
	ld (HL),4	;auto erase
	
	inc H		;1
	ld A,(HL)	; 2 get bank
	out (C),A	;4

	inc H		;1 get address
	ld A,(HL)	;2
	inc H		;1
	ld H,(HL)	;2
	ld L,A		;1
	
	ld B,rev_table_high
	inc E
	
	draw_char_revX
	
	pop HL
	pop BC

	jp REND_Done
;****************************************
;** Draw a mirrored sprite with _alt feature **
;****************************************
.REND_Sprite_Mirror
	ex DE,HL	;1
	exx			;1
	ld (HL),4	;auto erase feature
	
	push BC
	push HL
	
	inc H		;1
	ld A,(HL)	; 2 get bank
	out (C),A	;4

	inc H		;1 get address
	ld A,(HL)	;2
	inc H		;1
	ld H,(HL)	;2
	ld L,A		;1
	
	ld BC,16
	add HL,BC
	
	draw_char_opt
	
	pop HL
	pop BC
	
	jp REND_Done
	
;********************************
;** Draw a normal sprite/block **
;********************************
.REND_Static
	ex DE,HL
	exx
	ld (HL),128+13	;will be ignored but solid
	jr REND_SpriteEntry	
.REND_Sprite
	ex DE,HL	;1
	exx			;1
	ld (HL),4	;auto erase feature
	jr REND_SpriteEntry	
	
.REND_Block
	ex DE,HL	;1
	exx			;1
.REND_SpriteEntry	
	push HL
	
	inc H		;1
	ld A,(HL)	; 2 get bank
	out (C),A	;4

	inc H		;1 get address
	ld A,(HL)	;2
	inc H		;1
	ld H,(HL)	;2
	ld L,A		;1
	
	draw_char_opt
	
	pop HL
	jp REND_Done
;**********************************
;*** Draw a Star from Starfield ***
;**********************************
.REND_Star
	ex DE,HL
	exx
	ld (HL),4	;auto erase
	
	push HL
	
	inc H ;skip attr
	inc H ;skip bank
	ld A,(HL)	;2
	inc H		;1
	ld H,(HL)	;2
	ld L,A
	
	draw_star
	
	pop HL
	jp REND_Done

;***************************************
;** Draw a Y reversed sprite or block **
;***************************************
.REND_Sprite_FlipY_Mirror
	ex DE,HL
	exx
	ld (HL),4 ;auto erase
	
	push BC
	push HL
	
	inc H		;1
	ld A,(HL)	; 2 get bank
	out (C),A	;4

	inc H		;1 get address
	ld A,(HL)	;2
	inc H		;1
	ld H,(HL)	;2
	
	ld L,A

	ld A,%00111000	;start line 7
	or D
	ld D,A
	
	
	ld BC,16
	add HL,BC
	
	draw_char_Yrev_opt
	
	pop HL
	pop BC
	
	jp REND_Done

.REND_StaticRev
	ex DE,HL
	exx
	ld (HL),128+13	;will be ignored but solid
	jr REND_SpriteFlipY_entry	
.REND_Sprite_FlipY
	ex DE,HL
	exx
	ld (HL),4 ;auto erase
	jr REND_SpriteFlipY_entry	
.REND_Block_FlipY
	ex DE,HL	;1
	exx			;1
.REND_SpriteFlipY_entry	
	push HL
	
	inc H		;1
	ld A,(HL)	; 2 get bank
	out (C),A	;4

	inc H		;1 get address
	ld A,(HL)	;2
	inc H		;1
	ld H,(HL)	;2
	
	ld L,A
	
	;break

	;start on line 7
	ld A,%00111000
	or D
	ld D,A
	
	
	draw_char_Yrev_opt
	
	pop HL
	
	jp REND_Done
	
;******************	
;** erase a char **
;******************
.REND_Erase
	ex DE,HL
	exx
	ld (HL),0
	
	erase_char
	
	jp REND_Done
	
;*********************
;*** COMPILED CHAR ***
;*********************
.REND_AutoBlockBankedStatic
	ex DE,HL
	exx
	push HL
	push BC
	
	ld (HL),128+13	;will be ignored but solid
	
	inc H	;skip flag
	ld C,(HL)	;get bank
	ld B,#7F
	out (C),C
	pop BC
	
	inc H	;skip bank
	ld A,(HL)
	inc H
	ld H,(HL)
	ld L,A		;get sprite adress

	jp (HL)
	


.REND_AutoBlock		;same as auto sprite except no auto erase
	ex DE,HL
	exx
	push HL
	
	inc H		;skip flag
	inc H		;skip bank
	ld A,(HL)
	inc H
	ld H,(HL)
	ld L,A		;get sprite adress

	jp (HL)
	
.REND_Auto
	ex DE,HL
	exx
	push HL
	
	ld (HL),4	;auto erase
	inc H		;skip flag
	inc H		;skip bank
	ld A,(HL)
	inc H
	ld H,(HL)
	ld L,A		;get sprite adress

	;break
	
	jp (HL)
	
.REND_AutoRet
	ex DE,HL
	;ld A,D
	;and %11000111
	;ld D,A	
	res 5,D
	pop HL
	jp REND_Done
	
;********************
;** INIT RENDERER **
;********************

REND_Init:

;cleanup attribut array
	ld DE,#C000	
	ld IX,ATTR_Addr
	ld C,20
	
.REND_InitLoop1
	ld B,32
	ld L,(IX+0)
	ld H,(IX+1)
	inc IX
	inc IX
.REND_InitLoop2
	ld (HL),4
	inc L
	djnz REND_InitLoop2
	
	dec C
	jr nz,REND_InitLoop1
	ret
	
	
	

	




	

		
