; tab-8

; -------------------------------
; Data

print_first_data	data	0
print_hl		data	2
print_c			data	1
print_attr		data	1
print_flags		data	1
print_scrollcount	data	1
print_logptr		data	2
print_pending_ctl	data	2
print_last_data		data	0

; print_flags:
pbit_narrow		equ	0 ; bit in print_flags: narrow spacing: omit first spacing column
pbit_inverse		equ	1 ; bit in print_flags: print inverse:  set pixels for 0-bits in glyph
pbit_bold		equ	2 ; bit in print_flags: print inverse:  set pixels for 0-bits in glyph
pbit_log		equ	3 ; bit in print_flags: log all printing (print_logptr)++
pbit_pending_ctl	equ	4 ; bit in print_flags: control code pending, awaiting argument byte


; Attribute:

black		equ	0
blue		equ	1
red		equ	2
magenta		equ	3
green		equ	4
cyan		equ	5
yellow		equ	6
white		equ	7

pen		equ	1
paper		equ	8
bright		equ	$40
flashing	equ	$80

black_paper	equ	black * paper
blue_paper	equ	blue  * paper
red_paper	equ	red   * paper
magenta_paper	equ	magenta*paper
green_paper	equ	green * paper
cyan_paper	equ	cyan  * paper
yellow_paper	equ	yellow* paper
white_paper	equ	white * paper



; Control Codes:
; note: must match pc_jumpblock!

ctl_eot		equ	0	; end of text
ctl_home	equ	1	; locate 0,0
ctl_cls		equ	2	; clear screen mit print_attr, set border, home cursor
ctl_locate	equ	3	; set cursor to row, col (req. 2 argument characters)
ctl_setcol	equ	4	; set cursor to col (req. 1 argument character)
ctl_setrow	equ	5	; set cursor to row (req. 1 argument character)
ctl_setattr	equ	6	; set paper, pen, bright + flashing (req. 1 argument character)
ctl_setpen	equ	7	; set pen (req. 1 argument character)
ctl_setpaper	equ	8	; set paper (req. 1 argument character)
ctl_tab		equ	9	; set cursor to next tab position (n*8*8 pixel)
;		equ	10,11,12
ctl_newline	equ	13	; set cursor to start of next line (may scroll)
ctl_inverse	equ	14;15	; +0/+1: reset/set bright attr
ctl_narrow	equ	16;17	; +0/+1: reset/set bright attr
ctl_bold	equ	18;19	; +0/+1: reset/set bold attr
ctl_log		equ	20;21	; +0/+1: reset/set log-to-mem flag
ctl_flash	equ	22;23	; +0/+1: reset/set flash attr
ctl_bright	equ	24;25	; +0/+1: reset/set bright attr
;		equ	26,27,28,29,30,31


print_bset	data	2	; -> ins Ram kopierte Plot-A-Byte-Routine



; ----------------------------------------------------
; Initialize Text VDU
;
; in:	--
; out:	--
; mod:	af bc de hl iy

init_print:

; Selbst-modifizierenden Code ins Ram kopieren:
	ld	hl,print_bset_source
	ld	bc,print_bset_size
	call	mem_push_data
	call	mem_top_get_addr	; -> hl
	ld	(print_bset),hl

; Reset internal state:
	;call	print_reset			; z.Zt. ein Nop.

; clear screen, home cursor and set color attributes:
	rst	print_msg
	defb	ctl_home			; init print_hl & print_c
	defb	ctl_setattr, white_paper+black	; init print_attr
	defb	0
	ret



; ----------------------------------------
; Reset Text VDU
;
; reset flags, discard pending ctl code waiting for argument.
; does not clear screen, home cursor or set color attributes.
;
; in:	--
; out:	--
; mod:	af

print_reset_no_exx:
print_reset:
	sub	a
	ld	(print_flags),a		; switch off special modes, kill pending ctl arg
	ld	(print_scrollcount),a	; "scroll?" count
	ret



; ----------------------------------------
; push text vdu state on heap
; restore: with mem_pop_data
;
; in:	--
; out:	--
; mod:	af

print_push_state:
	exx
	ld	hl,print_first_data			; Q
	ld	bc,print_last_data-print_first_data	; size
	call	mem_push_data_no_exx
	exx
	ret



; ------------------------------------------------------------
; print "yes" or "no" depending on cy-flag:
;
; cy -> print "yes"
; nc -> print "no"
;
; in:	cy-flag
; out:	cy-flag 
; mod:	--

print_yes_no:
	jr	c,print_yes
	;jr	nc,print_no

	

; ------------------------------------------------------------
; print "no" & ret nc
;
; in:	--
; out:	f: cy = nc
; mod:	f

print_no:
	rst	print_msg
	defm	"no",$00
	and	a		; enforce nc
	ret



; ------------------------------------------------------------
; print "yes" & ret c
;
; in:	--
; out:	f:  cy = c
; mod:	f

print_yes:
	rst	print_msg
	defm	"yes",$00
	scf			; enforce cy
	ret



; ------------------------------------------------------------
; print unsigned decimal number 
;
; print_dec:		print hl with auto-sized field width
; print_dec_a:		print a  auto-sized
; print_dec[1..5]:	print hl with fixed field width 1..5 digits
;
; in:	hl = number
; out:	--
; mod:	af, de, hl

print_dec_a:
	ld	l,a
	ld	h,0

print_dec:
	ld	de,10000          ; print auto-sized 1-5 characters
	and	a
	sbc	hl,de
	add	hl,de
	jr	nc,print_dec5

	ld	de,1000
	and	a
	sbc	hl,de
	add	hl,de
	jr	nc,print_dec4

pd1	ld	de,100
	and	a
	sbc	hl,de
	add	hl,de
	jr	nc,print_dec3

	ld	de,10
	and	a
	sbc	hl,de
	add	hl,de
	jr	nc,print_dec2
	jr	print_dec1

print_dec5
	ld	de,10000          ; print 5 characters wide
	call	pdx
print_dec4
	ld	de,1000           ; print 4 characters wide
	call	pdx
print_dec3
	ld	de,100            ; print 3 characters wide
	call	pdx
print_dec2
	ld	de,10             ; print 2 characters wide
	call	pdx
print_dec1
	ld	de,1              ; print 1 character wide

pdx	ld	a,'0'
	and	a
pdx1	inc	a
	sbc	hl,de
	jr	nc,pdx1
	add	hl,de
	dec	a
	jp	print_char


		
; ------------------------------------------------------------
; print word as 4 hex chars
;
; in:	hl = number
; out:	--
; mod:	af

print_hex4:
	push	hl
	ld	a,h
	call	print_hex2
	pop	hl
	ld	a,l
	;jr	print_hex2   



; ------------------------------------------------------------
; print byte as 2 hex chars
;
; in:	a = number
; out:	--
; mod:	af

print_hex2:
	push	af
	rra
	rra
	rra
	rra
	call	print_hex1
	pop	af          
	;jr	print_hex1



; ------------------------------------------------------------
; print hex char
;
; in:	a = number (lower nibble only)
; out:	--
; mod:	af

print_hex1:
	and	$0f
	add	'0'
	cp	'9'+1
	jr	c,print_char
	add	7
	jr	print_char



; ------------------------------------------------------------
; print word as 16 binary chars
;
; in:	hl = number
; out:	--
; mod:	af

print_bin16:
	push	hl
	ld	a,h
	call	print_bin8
	pop	hl
	ld	a,l
	;jr	print_bin8   



; ------------------------------------------------------------
; print byte as 8 binary chars
;
; in:	a = number
; out:	--
; mod:	af

print_bin8:
	push	bc
	ld	b,8
pb0	ld	c,a
pb1	ld	a,'0'/2
	rl	c
	adc	a,a
	call	print_char
	djnz	pb1
	pop	bc
	ret



; ------------------------------------------------------------
; print nibble as 4 binary chars
;
; in:	a = number (lower nibble only)
; out:	--
; mod:	af

print_bin4:
	push	bc
	ld	b,4
	jr	pb0

	
	
; ------------------------------------------------------------
; print number as 4 hex chars + 1 space
;
; in:	hl = number
; out:	--
; mod:	af

print_hex4s;
	call	print_hex4
	;jr	print_space



; ------------------------------------------------------------
; print single space
;
; in:	--
; out:	--
; mod:	--

print_space:
	rst	print_msg
	defb	' ',0
	ret



; ------------------------------------------------------------
; print newline
;
; in:	--
; out:	--
; mod:	--

print_nl:
	rst	print_msg
	defb	13,0
	ret



; -------------------------------------------
; print single character
;
; in:	a = char
; out:	--
; mod:	IY

print_char_no_exx:
print_char:
	rst	save_registers
	push	af
	
	ld	b,a
	ld	hl,(print_hl)
	ld	a,(print_c)
	ld	c,a
	ld	a,b
	call	up_print_char_a_at_hl_bit_c
	ld	a,c
	ld	(print_c),a
	ld	(print_hl),hl

	pop	af
	ret
	


; ---------------------------------------------
; print text 
;
; --> Restart-Vektor: RST print_msg
;
; in:	mit 0-Byte abgeschlossener Text folgt inline
; out:	--
; mod:	iy

#if 0		
print_msg_no_exx:
print_msg:	
	ex	hl,(sp)
	call	print_text_hl_no_exx
	ex	hl,(sp)
	ret
#endif
	


; ----------------------------------------------
; print text 
;
; in:	hl -> 0-terminierter Text
; out:	hl incremented -> hinter $00
; mod:	hl, iy

print_text_hl_no_exx:
print_text_hl:
	push	af
	push	de
	push	bc
	ex	hl,de

	ld	hl,(print_hl)
	ld	a,(print_c)
	ld	c,a
		
pm_1	ld	a,(de)
	inc	de
	and	a
	jr	z,pm_x
	push	de
	call	up_print_char_a_at_hl_bit_c
	pop	de
	jr	pm_1

pm_x	ld	a,c
	ld	(print_c),a
	ld	(print_hl),hl

	ex	hl,de	
	pop	bc
	pop	de
	pop	af
	ret
	


; ------------------------------------------------------------
; Locate Textcursor at Row B, Column C
; Setup print_hl and print_c
;
; if row B >= 24, then the screen is scrolled 
; until row fits in screen
;
; in:	B = row [0..23]
;	C = col [0..255]
; out:	--
; mod:	AF, IY

print_locate_no_exx:
print_locate:
	rst	save_registers

pc_l2	ld	a,b
	cp	24
	jr	c,pc_l1
	call	scroll_screen_save_exx
	dec	b
	jr	pc_l2	

pc_l1	call	calc_hlc_from_row_b_col_c
	ld	a,c
	ld	(print_c),a
	ld	(print_hl),hl

	ret



; ------------------------------------------------------------
; Scroll screen up 
;
; scrolls screen up by 1 character row
; scrolls 23 rows and clears bottom row with print_attr
; scrolls pixels and attributes 
; printing position etc. are not updated
;
; in:	--
; out:	--
; mod:	AF, IY

scroll_screen_save_exx:	
	rst	save_exx_registers
	
scroll_screen:
	ld	a,(print_scrollcount)
	dec	a
	jp	p,ss1

	call	show_scroll_and_wait_for_key
	ld	a,24 -1	

ss1	ld	(print_scrollcount),a

scroll_screen_up:
	rst	save_registers
	ld	hl,$4000			; screen start
	ld	bc,24*256+32			; 24 rows, 32 columns
	jp	scroll_cbox_up_quick






; ------------------------------------------------------------
; Display "scroll?" and wait for key
;
; in:	--
; out:	--
; mod:	AF, IY

show_scroll_and_wait_for_key_save_exx:
	rst	save_exx_registers

show_scroll_and_wait_for_key:	
	rst	save_registers
			
	ld	bc,1*256 + 6		; rows = 1; cols = 6
	ld	hl,$5000+8*32 -6	; HL -> screen
	call	mem_push_data
	call	clear_pixels
	call	calc_hl_attr_from_pixel
	call	mem_push_data
	call	clear_attributes

	call	print_push_state
	call	print_reset
	rst	print_msg
	defb	ctl_locate, 23, 256-6*8
	defb	ctl_setattr, white + red_paper
	defm	"scroll?",$00

	call	wait_newkey
	call	mem_pop_data		; state

	call	mem_pop_data		; attr
	jp	mem_pop_data		; pixels
	
		
	
; ------------------------------------------------------------
; ------------------------------------------------------------
;	Internal Routines
; ------------------------------------------------------------
; ------------------------------------------------------------



; ------------------------------------------------------------
; render byte b at address hl bit c/8
; using routine via iy
; mod:	af,h		(only bits 0..2 of h are modified)

set_iy_and_print_byte_b_at_hl_bit_c:	

	ld	iy,(print_bset)

print_byte_b_at_hl_bit_c:	

	ld	a,b
	and	a
	ret	z

; schnelleinstieg: 
;	iy muss gesetzt sein 
;	c muss != 0 sein sonst kein Abbruch...

pc_c	ld	a,h
	or	7
	ld	h,a
	inc	h

	ld	a,c
	or	$c6			; SET 0,(hl)
	ld	(IY+prt_b-prt_a+1),a	; Selbst-modifizierender Code!

	ld	a,b			; a = byte
	jp	(iy)		

; der folgende Codeschnippel wird in 'init_print' ins RAM kopiert:

print_bset_source:
prt_a:	dec	h			; pixel werden von untennach oben geplottet
	rla				; <- req. cy=0 !
	jr	nc,prt_a		; bit=0 -> next bit
prt_b:	set	0,(hl)			; <- Selbst-modifizierender Code
	and	a
	ret	z
	jr	nz,prt_a
prt_e:	ret

print_bset_size	equ	prt_e - prt_a +1





; ------------------------------------------------------------
; Print char a at address hl using bit c/8
;
; in:  HL,C = Printposition
;      A    = Char
; out: HL,C = Printposition, aktualisiert
; mod: AF, BC, DE, HL

up_print_char_a_at_hl_bit_c:
	ex	hl,de		
	ld	hl,print_flags		; log printing ?
	bit	pbit_log,(hl)
	jr	z,pc_aa
	ld	hl,(print_logptr)
	ld	(hl),a
	inc	hl
	ld	(print_logptr),hl
	ld	hl,print_flags

pc_aa	bit	pbit_pending_ctl,(hl)	; hl = print_flags
	jr	z,pc_ab
	res	pbit_pending_ctl,(hl)
	ld	hl,(print_pending_ctl)
	jp	(hl)
pc_ab	ex	hl,de

	add	a,a
	sub	33*2
	jr	c,pc_d			; space or control

	push	hl
	ld	hl,charset_ptr		; hl -> glyph pointer table
	add	a,l
	ld	l,a
	jr	nc,$+3
	inc	h
	
	ld	e,(hl)
	inc	hl
	ld	d,(hl)			; de -> glyph
	pop	hl
	
; print char de at address hl using bit c/8
; increments hl and c 

print_char_de_at_hl_bit_c:

	ld	a,(print_flags)
	bit	pbit_narrow,a
	call	z,print_add_spacing

	ld	a,(de)			; 1st glyph col w/o own start-marker
	and	$FE			; remove bit 0 = start-of-glyph marker

pc_ba	ld	iy,(print_bset)		; für pc_c  =>  print_byte_b_at_hl_bit_c 

	push	hl
	ld	b,a
	call	calc_hl_attr_from_pixel	; set attribute
	ld	a,(print_attr)
	ld	(hl),a
	ld	a,b
	pop	hl

pc_b	ld	b,a
	rrc	a	
	jr	c,print_add_spacing	; bit 0 set => next char
	
	call	nz,pc_c			; paint col	(note: iy muss gesetzt sein)

	ld	a,c
	sub	8		
	ld	c,a

	inc	de		; next glyph col
	ld	a,(de)
	jr	nc,pc_b		; cy flag von: 'sub 8'

; next screen byte	
	ld	c,7*8
	inc	l
	jr	nz,pc_ba

; next line && next block	
	call	pc_e
	ld	a,(de)
	jr	pc_ba


print_add_spacing:		; add character spacing to hl/c
	ld	a,c
	sub	8
	ld	c,a
	ret	nc

print_advance_hl:
	ld	c,7*8
	inc	l
	ret	nz
	
; next line && next block
pc_e	ld	a,h
	add	8
	ld	h,a
	cp	$58
	ret	c
; end of screen
	ld	hl,$50E0
	jp	scroll_screen_save_exx


; space or control code
; TODO: Space sollte normal gedruckt werden, z.B. wg. Setzen von Attributen 

pc_d	rra			; undo *2 (note: cy must be set, cy is moved to bit 7)
	inc	a
	jr	nz,pc_f		; control code
	
; space
	ld	a,c
	sub	4*8		; 4 pixel spacing
	ld	c,a
	ret	nc		; still in same byte
	add	8*8
	ld	c,a
	inc	l
	ret	nz		; still in same block
	jr	pc_e		; next line && next block

; control code

pc_f	and	a,31		; a := code [0 ... 31]
	add	a,a		; a := code*2
	ex	hl,de
	ld	hl,pc_jumpblock
	add	l
	ld	l,a
	jr	nc,$+3
	inc	h
	ld	a,(hl)
	inc	hl
	ld	h,(hl)
	ld	l,a
	jp	(hl)
	
; Jumpblock für Controlcodes [0 .. 31]	
; in:  Printposition in dec (nicht hlc)
; out: Printposition in hlc
pc_jumpblock:
	defw	pc_eot			; $00 End of text
	defw	pc_home			; $01 Locate 0,0
	defw	pc_cls			; $02 Clear screen & home cursor
	defw	pc_locate		; $03 Argumente: row,col
	defw	pc_setcol		; $04 Argument:  col [0..255]
	defw	pc_setrow		; $05 Argument:  row [0..23]  ((größere Werte scrollen Screen))
	defw	pc_setattr		; $06 Argument:  pen_ink+paper_ink+bright+flashing
	defw	pc_setpen		; $07 Argument: pen color black ... white
	defw	pc_setpaper		; $08 Argument: paper color black_paper ... white_paper
	defw	pc_tab			; $09
	defw	pc_10,pc_11,pc_12
	defw	pc_newline		; $0D
	defw	pc_inverse_off,pc_inverse_on
	defw	pc_narrow_off, pc_narrow_on
	defw	pc_bold_off,   pc_bold_on
	defw	pc_log_on,     pc_log_off
	defw	pc_flash_off,  pc_flash_on
	defw	pc_bright_off, pc_bright_on
	defw	pc_26,pc_27,pc_28,pc_29,pc_30,pc_31


; unknown ctrl codes:
pc_10:
pc_11:
pc_12:
pc_26:			
pc_27:
pc_28:
pc_29:
pc_30:
pc_31:
	;di		; debug
	;halt
	;jr	pc_eot

; end of text: char(0) 
; sollte eigentlich nicht vorkommen
pc_eot:
	ex	hl,de		
	ret

pc_flash_off:
	ld	hl,print_attr
	res	7,(hl)
	ex	hl,de
	ret
	
pc_flash_on:
	ld	hl,print_attr
	set	7,(hl)
	ex	hl,de
	ret

pc_bright_off:
	ld	hl,print_attr
	res	6,(hl)
	ex	hl,de
	ret

pc_bright_on:
	ld	hl,print_attr
	set	6,(hl)
	ex	hl,de
	ret

pc_inverse_off:	
	ld	hl,print_flags
	res	pbit_inverse,(hl)
	ex	hl,de
	ret
	
pc_inverse_on:
	ld	hl,print_flags
	set	pbit_inverse,(hl)
	ex	hl,de
	ret

pc_narrow_off:
	ld	hl,print_flags
	res	pbit_narrow,(hl)
	ex	hl,de
	ret
	
pc_narrow_on:
	ld	hl,print_flags
	set	pbit_narrow,(hl)
	ex	hl,de
	ret

pc_bold_off:
	ld	hl,print_flags
	res	pbit_bold,(hl)
	ex	hl,de
	ret

pc_bold_on:
	ld	hl,print_flags
	set	pbit_bold,(hl)
	ex	hl,de
	ret

pc_log_off:
	ld	hl,print_flags
	res	pbit_log,(hl)
	ex	hl,de
	ret

pc_log_on:
	ld	hl,print_flags
	set	pbit_log,(hl)
	ex	hl,de
	ret

; cls, set border, home cursor, reset scroll count
pc_cls:				
	ld	a,(print_attr)
	call	clear_screen_no_exx	; clear screen with current attr
	;jr	pc_home

; home cursor, reset scroll count
pc_home:
	sub	a		; reset "Scroll?" message count down
	ld	(print_scrollcount),a
	ld	c,7*8		; home cursor == locate 0,0
	ld	hl,$4000	
	ret

; tab => alle 4 Byte (etwa 6 Buchstaben)
; TODO: Attribute setzen?
pc_tab:
	ld	a,3		; mask
	jr	pc_nl

pc_newline:
	ld	a,$1f		; mask
pc_nl	ld	c,8*7		; c := bit 7  ((leftmost bit))
	ex	hl,de		; hl := screenbyte addr
	or	l
	inc	a		
	ld	l,a
	ret	nz		; kein Übertrag über Blockgrenze (Zeilengrenze egal!)
	jp	pc_e		; nächster Block, evtl. Screenende => scrollen
	
pc_setpen:			; Argument: pen color black ... white
	ld	hl,pc_setpen_resume
	jr	pc_argx

pc_setpaper:			; Argument: paper color black ... white
	ld	hl,pc_setpaper_resume
	jr	pc_argx

pc_locate:			; Arguments: row [-128.. [0..23] ..127], col [0..255]
	ld	hl,pc_locate_resume
	jr	pc_argx

pc_locate_resume:	
	call	pc_setrow_resume
	ex	hl,de
	;jr	pc_setcol
	
pc_setcol:			; Argument: col [0..255]
	ld	hl,pc_setcol_resume
	jr	pc_argx

pc_setrow:			; Argument: row [0..23] bzw. [-128 .. +127] may scroll
	ld	hl,pc_setrow_resume
	jr	pc_argx

pc_setattr:			; Argument: attribute %FBPapPen (Flash, Bright, Paper, Pen)
	ld	hl,pc_setattr_resume
	;jr	pc_argx
		
pc_argx	ld	(print_pending_ctl),hl
	ld	hl,print_flags
	set	pbit_pending_ctl,(hl)
	ex	hl,de
	ret

	
	
pc_setpen_resume:
	and	a,$07		; force legal
	ld	b,a		; b := new val.
	ld	a,$F8		; other bits mask
	jr	pc_sp_r

pc_setpaper_resume:
	rlca
	rlca
	rlca
	and	a,$38		; force legal
	ld	b,a		; b := new val.
	ld	a,$C7		; other bits mask
pc_sp_r	ld	hl,print_attr
	and	a,(hl)		; a := other bits
	or	b		; a := new attr
	ld	(hl),a		; store new attr
	ex	hl,de
	ret

pc_setattr_resume:
	ld	(print_attr),a	; store new attr
	ex	hl,de
	ret

pc_setcol_resume:
	ex	hl,de		; => wieder hlc
	push	af		; new col [0..255]
	call	calc_row_b_col_c_from_hlc
	pop	af
	ld	c,a		; new col
	jp	calc_hlc_from_row_b_col_c

pc_setrow_resume:
	ex	hl,de
	cp	a,24		; force legal (TODO: evtl. scroll up/down)
	jr	c,pc_sr1	; [0 .. a .. 23]
	add	a		; mi -> cy
	ld	a,23
	jr	nc,$+3		; a>23  =>  a:=23
	sub	a		; a<0   =>  a:= 0

pc_sr1	push	af
	call	calc_row_b_col_c_from_hlc
	sub	a
	ld	(print_scrollcount),a		; reset scroll count
	pop	af
	ld	b,a
	jp	calc_hlc_from_row_b_col_c



; ------------------------------------------------------------
; UP: Berechne Row B und Col C
; zu Byteadresse HL und Bitadresse C 
;
; in:	HL = Byteadresse [$4000..$57FF]
;	C  = Bitadresse*8 [7..0]*8  (7=leftmost, 0=rightmost)
; out:	B  = row [0..23]
;	C  = col [0..255]
;	A  = B
; mod:	AF, BC

calc_row_b_col_c_from_hlc:
	ld	a,c		; [7..0]*8  (7=leftmost, 0=rightmost)
	rrca
	rrca
	rrca
	cpl			; [0..7]  (0=leftmost, 7=rightmost)
	and	$07		; force legal
	ld	c,a		; C = Spalte Bits 2..0

	ld	a,l		;     bit 7..5  =  Zeile in Screen Block [0..7]*32
	rlca			;     bit 4..0  =  Spalte in Zeile (Byte)
	rlca			; --> bit 2..0  =  Zeile in Screen Block [0..7]
	rlca			;     bit 7..3  =  Spalte (Byte) *8
	ld	b,a		; temp

	and	$F8		; Spalte Bits 7..3
	or	c		
	ld	c,a		; Spalte [0..255]
	
	ld	a,b
	and	$07		; Zeile Bits 2..0
	ld	b,a		; b = Zeile im Screen Block Bits 2..0

	ld	a,h
	and	$18		; 0,8,16[,24]  =  screen block  = Zeile Bits 4..3
	or	b
	ld	b,a		; Zeile [0..23] [..31]
	ret
	




	
; ------------------------------------------------------------
; UP: Berechne Byteadresse HL und Bitadresse C 
; zu Row B [0..23] und Col C [0..255]
;
; in:	B  = row [0..23]
;	C  = col [0..255]
; out:	HL = Byteadresse [$4000..$58FF]
;	C  = Bitadresse*8 [7..0]*8  (7=leftmost, 0=rightmost)
;	A  = C
; mod:	HL, AF, BC

calc_hlc_from_row_b_col_c:
	ld	a,b			; row
	and	$18
	or	$40			; screen base
	ld	h,a			; h = high byte screen address = [$40,$48,$50]

	ld	a,c			; col
	rr	b
	rra
	rr	b
	rra
	rr	b
	rra
	ld	l,a			; l = low byte screen address

	ld	a,c			; col
	cpl
	and	7
	rlca
	rlca
	rlca		
	ld	c,a			; bitnr * 8
	ret




#if 0

new_calc_row_b_col_c_from_hlc:
	
; konvertiere pixelmaske in c in spaltenzahl 0 (ganz links) ... 7 (ganz rechts)	
; Diese Routine braucht im Mittel 78.0 Taktzyklen.
; Eine Schleife mit rlca/inc r/jr nz bräuchte ~ 100 Takte.

	ld	a,$0F		; Maske: ____XXXX  hier dabei? => col+4
	and	c
	ld	b,a		; b := 0 wenn a=0
	jr	z,$+4
	ld	b,4		; b := 4 wenn a!=0

	ld	a,$33		; Maske: __XX__XX  hier dabei? => col+2
	and	c
	jr	z,$+4
	set	1,b

	ld	a,$55		; Maske: _X_X_X_X  hier dabei? => col+1
	and	c
	jr	z,$+3
	inc	b		
	ld	c,b		; c = %00000bbb = col inside char [0..7]
	
; l = %rrrccccc		wobei rrr = row inside char  und ccccc = char col
; l rotieren, dass es so aussieht:
; l = %cccccrrr		damit stehen rrr und ccccc auf den positionen, 
;			die ihrer Wertigkeit entspricht

	ld	a,l		
	rla
	rla
	rla			
	ld	b,a		; b = a = %cccccrrr

	and	$F8		; a = %ccccc000
	or	c		; a = %cccccbbb  
	ld	c,a		; c = pixelspalte = fertig

	ld	a,b		 
	and	7		
	ld	b,a		; b = %00000rrr

; h = %010bbzzz		wobei bb = 8-Textzeilen-Block  und zzz = pixelzeile innerhalb eines Zeichens
	
	ld	a,h	
	and	$18		; a = %000bb000		
	or	b		; a = %000bbrrr
	ld	b,a		; b = character row = fertig
	
	ret


new_calc_hlc_from_row_b_col_c:

;	hl := %010bb000.rrrccccc	bb=block, rr=row inside block, ccccc=char col
;	c = %10000000 >> (c&7)

	ld	a,b
	and	$18		; a = %000bb000
	or	$40
	ld	h,a		; h = %010bb000 = fertig
	
	ld	a,b
	and	7
	ld	b,a		; b = %00000rrr
	
	ld	a,c
	and	$E0		; a = %ccccc000
	or	b		; a = %cccccrrr
	rrca
	rrca
	rrca			; a = %rrrccccc
	ld	l,a		; l = %rrrccccc = fertig
	
	ld	a,c		; a = pixel col
	and	7		; a = pixel col inside byte
	add	pmasks%256
	ld	c,a
	ld	b,pmasks/256
	ld	a,(bc)
	ld	c,a

	ret
	
#if $/256 != ($+8-1)/256
	defs	256 - $%256
#endif

pmasks	defb	$80, $40, $20, $10, $08, $04, $02, $01


#endif






