
; --------------------------------------------------------
;		S C R E E N - U T I L I T I E S
; --------------------------------------------------------

; clear_32_bytes		IY DE E		--  DE++
; copy_32_bytes			IY HL DE BC	--  HL++ DE++ BC++
; calc_ix_for_clear_c		C		-- IX
; calc_ix_for_copy_c		C		-- IX

; clear_bc			HL BC		-- HL++
; clear_bc_a			HL BC A		-- HL++
; clear_bc_e			HL BC E		-- HL++

; clear_pixels			HL B C		--
; clear_attributes		HL B C A	--
; clear_attributes_with_e_quick	HL B C E	--
; clear_screen_with_attr	A		--
; clear_cbox_with_attr		HL B C A	--

; copy_bc			HL DE BC	-- HL++ DE++ BC=0
; copy_pixels_to_buffer		HL DE B C	-- 
; copy_buffer_to_pixels		HL DE B C	--
; copy_attributes_to_buffer	HL DE B C	--
; copy_buffer_to_attributes	HL DE B C	--

; scroll_cbox_up		HL B C		--

; calc_hl_for_next_pixel_row	HL		-- HL
; calc_de_for_next_pixel_row	DE		-- DE
; adjust_hl_for_next_row	HL		-- HL
; adjust_de_for_next_row	DE		-- DE
; calc_hl_down_8_pixel_rows	HL		-- HL

; calc_attr_hl_for_pixel_hl	HL		-- HL
; calc_pixel_hl_from_attr_hl	HL		-- HL
; calc_attr_hl_for_row_b_col_c	B C		-- HL
; calc_pixel_hl_for_row_b_col_c	B C		-- HL
; calc_row_b_col_c_for_pixel_hl	HL		-- BC
; calc_row_b_col_c_for_attr_hl	HL		-- BC



; --------------------------------------------------
; Lösche 32 Bytes im Bildschirm
; (HL)++ = E
;
; Der zu löschende Bereich muss vollständig in einem 256-Byte-Block liegen,
; was beim Bildschirm immer der Fall ist. H wird nicht incrementiert,
; und wenn der zu löschende Bereich an einer 256-Byte-Grenze endet, muss der
; Aufrufer H selbst incrementieren. Dazu kann er sofort das Z-Flag prüfen.
; Beim Bildschirm-Löschen ist es aber sehr günstig, dass H nicht verändert wird,
; da man beim Weiterschalten innerhalb einer Zeichenzeile dann immer L restauriert 
; und H incrementiert.
;
; Die verwendete Methode ist vermutlich die zweitschnellste nach 
; Löschen mit push dd. Hier muss aber nicht der Interrupt (immer wieder)
; ausgeschaltet werden und es kann auch eine ungerade Anzahl von Bytes leichter
; gelöscht werden. 
; Das Löschen von beliebigen Speicherbereichen ist allerding hiermit nicht ideal, 
; weil das Splitten an den 256-Byte-Grenzen unverhältnismäßig aufwendig ist.
;
; in:	IY: Rücksprungadresse
;	HL -> Ziel
;	E = Füllbyte
; out:	L++
;	F: Z: L overflowed -> H++ needed.
; mod:	F, L

clear_32_bytes:
	ld	(hl),e		; 7 T
	inc	l		; 4 T

clear_31_bytes:
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l
	ld	(hl),e
	inc	l		; <- der evtl. Übertrag muss vom Aufrufer behandelt werden.

clear_0_bytes:
	jp	(iy)



; --------------------------------------------------
; Kopiere 32 Bytes 
; (hl++) -> (de++) und bc--
;
; in:	iy: Rücksprungadresse
;	hl -> Quelle
;	de -> Ziel
;	bc = Zähler
; out:	hl++
;	de++
;	bc--
; mod:	f, bc, de, hl

copy_32_bytes:
	ldi			; 16 T

copy_31_bytes:
	ldi			; ld (de++),(hl++) 
	ldi			; bc--
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi

copy_0_bytes:
	jp	(iy)



; -------------------------------------------------
; Berechne Einsprungsadresse in clear_32_bytes
;
; in:	c = bytes  [0..c..32]
; out:	ix -> Einsprungsadresse für jp (ix)
; mod:	af, ix

calc_ix_for_clear_c:
	ld	ix,clear_32_bytes  
	jr	calc_ix



; -------------------------------------------------
; Berechne Einsprungsadresse in copy_32_bytes
;
; in:	c = bytes  [0..c..32]
; out:	ix -> Einsprungsadresse für jp (ix)
; mod:	af, ix

calc_ix_for_copy_c:
	ld	ix,copy_32_bytes  

calc_ix:
	ld	a,64
	sub	c
	sub	c
	add	xl
	ld	xl,a
	ret	nc
	inc	xh
	ret



; ------------------------------------------------
; Lösche BC Bytes mit $00.		
;
; in:	hl	dest
;	bc	count
; out:	hl++
; mod:	af, bc, de, hl

clear_bc:
	sub	a		
	;jr	clear_bc_a



; ------------------------------------------------
; Lösche BC Bytes.
;
; in:	hl	dest
;	bc	count
;	a	filler
; out:	hl++
; mod:	af, bc, de, hl

clear_bc_a:
	ld	e,a		; e = filler

clear_bc_e:
	inc	b		; b = outer loop counter
	ld	d,4		; d = 4
	ld	a,c		; a = inner loop counter; bits 0&1 = remainder
	jr	cbc4
	
cbc3	ld	(hl),e
	inc	hl
	ld	(hl),e
	inc	hl
	ld	(hl),e
	inc	hl
	ld	(hl),e
	inc	hl

cbc4	sub	d		; 4
	jr	nc,cbc3
	
	dec	b
	djnz	cbc3

; a = remainder

cbcx	rrca
	jr	nc,cbc5
	ld	(hl),e
	inc	hl

cbc5	rrca
	ret	nc
	ld	(hl),e
	inc	hl
	ld	(hl),e
	inc	hl
	ret



; ------------------------------------------------------------
; Lösche die Pixel ab HL für B x C Character Cells 
;
; in:	hl -> 1. screen byte
;	b = rows
;	c = columns
; out:	--
; mod:	AF, IY

clear_pixels_no_exx:
clear_pixels:
	rst	save_registers
	ld	a,h
	and	$F8		; %010bbzzz -> %010bb000
	ld	h,a		; force legal: hl -> top row of character cell

clear_pixels_quick:
	ld	e,0		; E = fill byte = 0
	push	ix
	call	calc_ix_for_clear_c
	ld	iy,clrret	; return address from jp(ix)
	ld	c,b		; C = rows = outer counter

; loop over B character rows:
cb80	ld	b,8		; b = counter = 8 pixel rows
	ld	a,l		; L retten

; loop over 8 pixel rows:
cb81	jp	(ix)		; clear pixel row (hl)++
clrret	ld	l,a		; L erneuern
	inc	h		; next pixel row
	djnz	cb81		; next row inside character row

	call	adjust_hl_for_next_row	; hl++
	dec	c
	jr	nz,cb80		; next character row

	pop	ix
	ret



; ------------------------------------------------------------
; Lösche die Attribute ab HL für B x C Character Cells
;
; in:	a = attribute byte
;	hl -> 1. attribute byte
;	b = rows
;	c = columns
; out:	--
; mod:	AF, IY

clear_attributes_no_exx:
clear_attributes:
	rst	save_registers

clear_attributes_quick:
	ld	e,a		; E = fill byte 

clear_attributes_with_e_quick:
	push	ix
	call	calc_ix_for_clear_c
	ld	iy,claret	; return address from jp(ix)
	ld	a,l		; A = L for restore & increment

; loop over B rows:
cb84	jp	(ix)
claret	add	32		
	ld	l,a		; hl++
	jr	nc,$+3
	inc	h
	
	djnz	cb84

	pop	ix
	ret



; ------------------------------------------------------------
; Clear screen
; Löscht Pixel mit 0x00 und Attribute mit dem Wert aus A.
; Setzt Border Color entsprechend der Paper Color.
; Um den Eindruck eines instantanen Löschens ohne pixel/attr out-of-sync-Blitzer
; zu erzeugen, werden die Attribute zunächst zusätzlich mit pen=paper color gelöscht.
;
; in:	A = new attribute
; out:	--
; mod:	AF, IY

clear_screen_with_attr_no_exx:
clear_screen_with_attr:
	rst	save_registers

	push	af		; attr retten

	and	$F8		
	ld	e,a		; e = attribut ohne pen bits
	rra
	rra
	rra
	and	7		; a = paper bits moved to pen position
	out	($fe),a		; set border
	or	e		; a = attr mit pen == paper

	ld	hl,$5800	; start of attr
	ld	bc,24*256+32	; 24 rows, 32 cols
	call	clear_attributes_quick	; quick => also no exx
	
	pop	af		; attr
	ld	hl,$4000
	ld	bc,24*256 + 32
	jr	clear_cbox_with_attr_quick		; quick -> also no exx
	


; ------------------------------------------------------------
; clear B rows á C character cells
;
; Löscht 8x pixel mit $00 + 1x attr je Feld mit print_attr
;
; in:	a = attribute
;	b = rows
;	c = columns
;	hl -> 1. screen byte
; out:	--
; mod:	AF, IY

clear_cbox_with_attr_no_exx:
clear_cbox_with_attr:
	rst	save_registers
	
clear_cbox_with_attr_quick:
	ld	e,a				; attr
	call	clear_pixels
	call	calc_attr_hl_for_pixel_hl
	jp	clear_attributes_with_e_quick	; quick => also no exx



; ------------------------------------------------
; slightly faster ldir.
; Beide Routinen lohnen sich erst ab 32 Bytes.
;
; copy_bc	kopiert bc Bytes von hl++ nach de++.
;
; in:	hl, de, bc
; out:	hl++, de++, bc=0
; mod:	af, bc, de, hl, iy
;
; copy_c	kopiert C Bytes, B wird erhalten.
;
; in:	hl, de, c
; out:	hl++, de++, c=0
; mod:	af, c, de, hl, iy

copy_bc_no_exx:
copy_bc:
	sub	a
	ld	iy,cpbc1
cpbc1	cp	b
	jp	c,copy_32_bytes		; while bc >= 256

copy_c	ld	a,32			; while c >= 33
	ld	iy,cpbc2
cpbc2	cp	c
	jp	c,copy_32_bytes 

; Die restl. 0..32 Bytes kopieren
; Berechneter Einsprung in die LDI-Routine

cpbc3	pop	iy		; eigene Return-Adresse		
	push	hl		; retten			
	sub	c		; 32-C				
	add	a		; 2* (32-C)			

	ld	hl,copy_32_bytes				
	add	l						
	ld	l,a						

#if copy_32_bytes/256 != copy_0_bytes/256
	jr	nc,$+3
	inc	h
#endif	
	ex	hl,(sp)	
	ret							 



; ------------------------------------------
; save screen pixels to buffer
;
; in:	hl -> 1st pixel byte
;	b  = rows  (characters)
;	c  = cols
; out:	hl = handle
; mod:	af,iy

scr_save_pixels_no_exx:
scr_save_pixels:
	push	bc
	push	de

; allocate buffer
	push	hl			; sp: -> source
	push	bc			; sp: b=rows and c=cols
	call	mult_bc			; hl = b x c
	add	hl,hl			; characters are 8 pixel rows each
	inc	hl			; +4 for source address, rows and cols
	add	hl,hl			; hl = size := hl*8
	add	hl,hl
	ld	bc,hl			; bc = size
	call	mem_alloc		; hl -> handle, de -> dest; bc=size
	pop	bc			; b=rows, c=cols
	ex	hl,(sp)			; sp: handle; hl->source; de->dest; bc=rows/cols

; store 1st pixel address, rows and cols in buffer:
	call	up_store_hlbc_to_de

; setup copy routine
	push	ix			
	call	calc_ix_for_copy_c	; setup IX from C
	ld	iy,pcp1ret		; ix = return address from ldi-routine

; copy B character rows:
pcp0	push	bc			; B = row count down, C = cols	
	ld	bc,9*256		; B: 8 rows; +1 because c will underflow 1x 
					; C: 0 => will 1x overflow and decr b
	ld	a,l			; save l to restore hl
	
; copy 8 pixel rows:
pcp1	jp	(ix)			; copy C bytes
pcp1ret	ld	l,a			; restore hl
	inc	h			; hl+=256 => skip over remainder of row
	djnz	pcp1

	call	adjust_hl_for_next_row	; adjust hl for next character row	
	pop	bc
	djnz	pcp0			; B runterzählen

	jr	pop_ixhldebc



; ------------------------------------------
; copy attributes to buffer
;
; in:	hl -> 1st attr byte
;	b  = rows  (characters)
;	c  = cols
; out:	handle
; mod:	af

scr_save_attributes_no_exx:
scr_save_attributes:
	push	bc
	push	de

; allocate buffer:
	push	hl			; sp: -> source
	push	bc			; sp: b=rows and c=cols
	call	mult_bc			; hl = b x c
	inc	hl			; add 2 bytes to store rows and cols
	inc	hl
	inc	hl			; add 2 bytes to store 1st attr byte address
	inc	hl
	ld	bc,hl			; bc = size
	call	mem_alloc		; hl -> handle, de -> dest; bc=size
	pop	bc			; b=rows, c=cols
	ex	hl,(sp)			; sp: handle; hl->source; de->dest; bc=rows/cols

; store source, rows and cols in buffer
	call	up_store_hlbc_to_de	; store hlbc via de++

; setup copy routine
	push	ix
	call	calc_ix_for_copy_c	; setup IX from C
	ld	iy,pca1ret		; iy = return address from ldi-routine	
	ld	a,b			; a = rows
	
; copy A attr rows:
pca0	ld	bc,32			; bc = offset of attribute rows
	jp	(ix)			; copy C bytes
pca1ret	add	hl,bc			; skip over remainder of row
	dec	a
	jr	nz,pca0

pop_ixhldebc:
	pop	ix		; ix
	pop	hl		; handle
	pop	de		; de
	pop	bc		; bc
	ret

up_store_hlbc_to_de:
	ex	hl,de
	ld	(hl),e			; store source address
	inc	hl
	ld	(hl),d
	inc	hl
	ld	(hl),b			; store rows
	inc	hl
	ld	(hl),c			; store cols
	inc	hl
	ex	hl,de
	ret
	


; ------------------------------------------
; copy buffer back to screen pixels
;
; in:	hl = handle
; out:	--
; mod:	af

scr_restore_pixels_no_exx:
scr_restore_pixels:
	push	bc
	push	de
	push	hl
	push	ix
	call	mem_get_address		; hl -> source data

; restore 1st pixel address, rows and cols in buffer:
	ld	e,(hl)			; 1st pixel address
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	b,(hl)			; rows
	inc	hl
	ld	c,(hl)			; cols
	inc	hl			; bc=rows/cols; hl->buffer; de->1st pixel

; setup copy routine:
	call	calc_ix_for_copy_c	; setup IX from C
	ld	iy,pp1ret		; iy = return address from ldi-routine

; copy B character rows:
pp0	push	bc			; B = row count down, C = cols	
	ld	bc,9*256		; B: 8 rows; (+1 because c will underflow 1x)
					; C: will underflow 1x and decr b
	ld	a,e			; a: save e for restore de
	
; copy 8 pixel rows:
pp1	jp	(ix)			; copy one row
pp1ret	ld	e,a			; restore de
	inc	d			; next pixel row: de += 256
	djnz	pp1

	call	adjust_de_for_next_row	; adjust hl for next character row	
	pop	bc
	djnz	pp0			; next row

pop_ixhldebc_dealloc:
	pop	ix
	pop	hl
	pop	de
	pop	bc
	jp	mem_dealloc




; ------------------------------------------
; copy buffer back to screen attributes
;
; in:	hl -> buffer
; out:	--
; mod:	af

scr_restore_attributes_no_exx:
scr_restore_attributes:
	push	bc
	push	de
	push	hl
	push	ix
	call	mem_get_address		; hl -> source data

; restore 1st attr address, rows and cols in buffer:
	ld	e,(hl)			; 1st attr address
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	b,(hl)			; rows
	inc	hl
	ld	c,(hl)			; cols
	inc	hl			; bc=rows/cols; hl->buffer; de->1st attr

; copy:
	call	calc_ix_for_copy_c	; setup IX from C
	ld	iy,ppa2ret		; iy = return address from ldi-routine
	ld	a,b			; a = rows

ppa3	ld	bc,32			; offset of attr rows
	jp	(ix)			; copy C bytes
ppa2ret	ex	hl,de
	add	hl,bc			; skip over remainder of row
	ex	hl,de
	dec	a
	jr	nz,ppa3			; B runterzählen, C bewahren!

	jr	pop_ixhldebc_dealloc
	


; ------------------------------------------------------------
; Scroll screen up: B rows, C cols
;
; scrolls C columns up by 1 character row
; scrolls B-1 rows and clears bottom row with print_attr
; scrolls pixels and attributes 
; printing position etc. are not updated
;
; in:	hl -> current screen byte
;	b = rows
;	c = cols
; out:	--
; mod:	AF, IY, exx

scroll_cbox_up_save_exx:
	rst	save_exx_registers
	
scroll_cbox_up:	
	rst	save_registers

	ld	a,b			; Security:
	or	c			; trap 0-wide or 0-high blocks
	ret	z
	ret	m

	ld	a,h			; Force legal:
	and	$F8			; hl -> top pixel row of character row
	ld	h,a

scroll_cbox_up_quick:
	push	ix
	call	calc_ix_for_copy_c	; setup IX
	
; prepare copy pixels:	
	push	hl			; hl für copy attr
	ld	de,hl			; de -> upper row = dest
	call	calc_hl_down_8_pixel_rows	; hl -> lower row = source

; prepare copy attributes:
	exx				; attr set
	pop	hl
	call	calc_attr_hl_for_pixel_hl
	ex	hl,de			; de -> upper row = dest
	ld	hl,32	
	add	hl,de			; hl -> lower row = source		
	exx				; pixel set
	
	jr	psb3			; copy b-1 rows; maybe 0
	
; --- main loop: copy B-1 character rows: ---

; copy 8 pixel rows:
psb0	ld	a,8			; 8 rows
	ld	iy,psb1ret

	push	bc			; B = row count down, C = cols	

psb1	ld	bc,256			; offset of pixel rows inside character rows
	jp	(ix)			; copy C bytes
psb1ret	add	hl,bc			; skip over remainder of row
	ex	hl,de		
	add	hl,bc		
	ex	hl,de
	dec	a
	jr	nz,psb1

	pop	bc

	call	adjust_hl_for_next_row	; adjust de and hl for next character row
	call	adjust_de_for_next_row
	
; copy 1 attribute row:
	exx				; attr set
	ld	iy,psa1ret	
psa1	ld	bc,32			; offset of attr rows
	jp	(ix)			; copy C bytes
psa1ret	add	hl,bc			; skip over remainder of row
	ex	hl,de		
	add	hl,bc		
	ex	hl,de
	exx				; pixel set

psb3	djnz	psb0			; B runterzählen, C bewahren!

; --- end of main loop ---

	pop	ix			; ix

	ex	hl,de			; hl -> pixels of the last character row
	;ld	c,c			; c = columns
	inc	b			; b = 1 row
	
	push	bc
	call	clear_pixels_quick
	pop	bc
	exx				; hl -> attr of the last character row
	jp	clear_attributes_quick
	
	



; ----------------------------------------
; advance hl vertically to next pixel row
;
; screen layout:
;
; %010ccaaa.bbbzzzzz
;
; zzzzz	= character column
; aaa   = row inside character row
; bbb   = character row inside screen block
; cc    = screen block
;
; in:	HL 
; out:	HL
; mod:	AF, HL

calc_hl_for_next_pixel_row:
	inc	h		; aaa += 1
	ld	a,h
	and	7
	ret	nz		; advance pixel row inside a character row

; aaa++ overflowed to cc
; => add the overflow to bbb

; this is also a good entry after incrementing H 8 times for a character row
; to adjust HL to the next pixel row, the first row of the next character row.

adjust_hl_for_next_row:
	ld	a,l
	add	32
	ld	l,a		; bbb++
	
; now undo the overflow to cc
; except if there was also an overflow from bbb++
; in which case the overflow to cc is fine (though it came from bbb++, not aaa++)	

	ret	c		; bbb++ did overflow => ok => exit
	
; undo the overflow to cc:

	ld	a,h
	sub	8
	ld	h,a		; cc--
	ret



; ----------------------------------------
; Advance de vertically to next pixel row.
; das selbe nur für DE:

calc_de_for_next_pixel_row:
	inc	d
	ld	a,d
	and	7
	ret	nz
adjust_de_for_next_row:
	ld	a,e
	add	32
	ld	e,a
	ret	c
	ld	a,d
	sub	8
	ld	d,a
	ret



; ----------------------------------------
; advance hl vertically to next character row
;
; column and pixel row inside character row 
; are preserved.
;
; in:	HL 
; out:	HL
; mod:	AF, HL

calc_hl_down_8_pixel_rows:
	ld	a,l
	add	32
	ld	l,a		; bbb++	
	ret	nc

; overflow to cc:
	ld	a,h
	add	8
	ld	h,a		; cc++
	ret



; ------------------------------------------------------------
; UP: Berechne Attribut-Addresse HL zu Pixel (Byte) Adresse HL
;
; in:	HL = Pixel-Adresse	[$4000..$57FF]	= %010bbzzz.rrrccccc
; out:	HL = Attribut-Adresse   [$5800..$5AFF]	= %010110bb.rrrccccc
; mod:	HL, AF

calc_attr_hl_for_pixel_hl:
	ld	a,h
	rrca
	rrca
	rrca
	and	$03
	or	$58
	ld	h,a
	ret



; ------------------------------------------------------------
; UP: Berechne Pixel-Addresse HL zu Attribut-Adresse HL
;     Berechnet die Adresse des obersten Pixelbytes: hl & $0007 = 0
;
; in:	HL = Attribut-Adresse   [$5800..$5AFF]	= %010110bb.rrrccccc
; out:	HL = Pixel-Byte-Adresse [$4000..$57FF]	= %010bb000.rrrccccc
; mod:	HL, AF

calc_pixel_hl_for_attr_hl:
	ld	a,h
	and	$0f
	rlca
	rlca
	rlca
	ld	h,a
	ret



; ------------------------------------------------------------
; Berechne Attribut-Adresse für Zeile B Spalte C:
;
; in:	B = character row	[0..23]		= %000bbrrr
;	C = character column	[0..31]		= %000ccccc
; out:	HL -> attribute byte			= %010110bb.rrrccccc
; mod:	AF, HL

calc_attr_hl_for_row_b_col_c:
	ld	a,b		; a = %000bbrrr
	ld	h,$58>>2	; h = %00010110;  $5800: Start of Attributes
	rlca			; a = %00101100; cy=0
	rla			; a = %01011000; cy=0
	rla			; a = %bbrrr000; cy=0
	rla			; a = %brrr0000; cy = b
	rl	h		; h = %0010110b; cy = 0
	rla			; a = %rrr00000; cy = b
	rl	h		; h = %010110bb = fertig
	or	c		; a = %rrrccccc
	ld	l,a		; l = %rrrccccc = fertig
	ret



; ------------------------------------------------------------
; Berechne Pixel-Adresse für Zeile B Spalte C:
; Berechnet die Adresse des obersten Pixelbytes: hl & $0007 = 0
;
; in:	B = character row	[0..23]		= %000bbrrr
;	C = character column	[0..31]		= %000ccccc
; out:	HL -> pixel byte			= %010bb000.rrrccccc
; mod:	AF, HL

calc_pixel_hl_for_row_b_col_c:
	ld	a,b
	rrca
	rrca
	rrca	
	and	$E0		; a = %rrr00000
	or	c		; a = %rrrccccc
	ld	l,a		; l = %rrrccccc = fertig	
	ld	a,b		; a = %000bbrrr
	and	$18		; a = %000bb000
	or	$40		; a = %010bb000
	ld	h,a		; h = %010bb000 = fertig
	ret



; ------------------------------------------------------------
; Berechne Zeile B und Spalte C zu einer Pixeladresse HL
;
; in:	HL -> pixel byte			= %010bbzzz.rrrccccc
; out:	B = character row	[0..23]		= %000bbrrr
;	C = character column	[0..31]		= %000ccccc
; mod:	AF, BC

calc_row_b_col_c_for_pixel_hl:
	ld	a,h		; a = %010bbzzz
	and	$18		; a = %000bb000
	ld	b,a		; b = %000bb000

	ld	a,l		; a = %rrrccccc
	and	$1f		; a = %000ccccc
	ld	c,a		; c = %000ccccc = feritg

	xor	l		; a = %rrr00000
	rlca
	rlca
	rlca			; a = %00000rrr
	or	b		; a = %000bbrrr
	ld	b,a		; b = %000bbrrr = fertig
	ret



; ------------------------------------------------------------
; Berechne Zeile B und Spalte C zu einer Attributadresse HL
;
; in:	HL -> attribute byte			= %010110bb.rrrccccc
; out:	B = character row	[0..23]		= %000bbrrr
;	C = character column	[0..31]		= %000ccccc
; mod:	AF, BC

calc_row_b_col_c_for_attr_hl:
	ld	a,h		; a = %010110bb
	and	3		; a = %000000bb
	ld	b,a		; b = %000000bb
	
	ld	a,l		; a = %rrrccccc
	and	$1f		; a = %000ccccc
	ld	c,a		; c = %000ccccc = fertig

	xor	l		; a = %rrr00000
	or	b		; a = %rrr000bb
	rlca
	rlca
	rlca			; a = %000bbrrr
	ld	b,a		; b = %000bbrrr = fertig
	ret
	







