;; This code shows how to draw a message using characters that are 6x8 pixels in size.
;;
;; This example doesn't use the firmware.
;;
;; The pixel data is defined in mode 2 (2 colours, 1 bit per pixel)
;; This is converted at runtime to mode 1 format (4 colours, 2 bits per pixel)
;; And then drawn to the screen
;;
;; The code does some screen pixel manipulate to draw and mask the chars onto the screen.
;;
;; 
org &4000
nolist

;; nibbles swapped!
pen0 equ %00000000
pen1 equ %00001000
pen2 equ %10000000
pen3 equ %10001000

;; aaaa aabb bbbb cccc ccdd dddd eeee eeff ffff
;;  0    1    2    3     4    5   6    7   8

;; 0->0
;; 1->1
;; 2->3
;; 3->4
;; 4->6
;; 5->7
;; 6->9


start:
call make_scr_table

ld h,0
ld l,1
call set_txt_coord

ld h,pen0
ld l,pen1
call set_txt_colours

ld hl,message
call display_message
l1:
jp l1

display_message:
ld a,(hl)
inc hl
or a
ret z
call display_char
jr display_message

message: defb "THIS IS A TEST",0	



;; each char is 6 mode 1 pixels wide and 8 mode 1 pixels tall
;; in mode 1, each byte uses 4 pixels
;; so this means that each char uses 2 bytes, with the last 2 pixels of each line are unused.
;; this is done for simplicity.
;;
;; this means each char is 2 bytes wide and 8 bytes tall


;; to work out screen address to draw char to
;; 
;; byte 0  byte 2   byte 3    byte 4        byte 5
;; 0 1 2 3 4 5 6 7  8 9 10 11 12 13 14 15   16 17 18 19

;; first char uses pixels 0,1,2,3,4,5
;; second char uses pixels 6,7,8,9,10,11
;; third char uses 12,13,14,15, 16, 17

;; even/odd x coord

display_char:
push hl
push de
push bc

;; work out location of pixel data
;; 1 bit per pixel font used here
sub ' '
ld l,a
ld h,0
add hl,hl
add hl,hl
add hl,hl
ld de,font
add hl,de
;; convert from 1 bit per pixel to 2 bit per pixel
call depack_char

;; x coord, remove bit 0, and multiply by 3
;; 0->0
;; 2->3
;; 4->6

ld a,(txt_x)
srl a
ld c,a
add a,a	;; x2
add a,c ;; x3
ld c,a
ld a,(txt_x)
and &1
add a,c
ld h,a
ld a,(txt_y)
add a,a
add a,a
add a,a
ld l,a

call get_scr_addr

;; now display char in appropiate location
ld de,char_depack_buffer
ex de,hl

call display_char2

;; increment text coord position
ld hl,txt_x
inc (hl)
pop bc
pop de
pop hl
ret

display_char2:
ld a,(txt_x)
and 1
jp nz,display_char_odd
jp display_char_even

;; H = x coord
;; L = y coord
set_txt_coord:
ld (txt_coords),hl
ret

;; set foreground and background colours
set_txt_colours:
ld a,h
ld (bk_color+1),a
ld a,l
ld (fg_color+1),a
ret

;; convert 1-bit per pixel into 2 bit per pixel
depack_char:
ld b,8
ld de,char_depack_buffer
depack_char2:
push bc
ld c,(hl)
call depack_byte
call depack_byte
inc hl
pop bc
djnz depack_char2
ret

;; take 4x 1 bit per pixel from one byte and write out 4 2-bit per pixels to one byte

depack_byte:
xor a
call depack_pixel
call depack_pixel
call depack_pixel
call depack_pixel
ld (de),a
inc de
ret

depack_pixel:
call depack_pix
or b
rlca
ret

depack_pix:
;; shift into carry
rlc c
bk_color:
ld b,0
ret nc
fg_color:
ld b,1
ret


scr_next_line:
ld a,h
add a,8
ld h,a
ret nc
ld a,l
add a,&50
ld l,a
ld a,h
adc a,&c0
ld h,a
ret

get_scr_addr:
push bc
push de
ld c,h
ld h,0
add hl,hl
ld de,scr_table
add hl,de
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
ld b,0
add hl,bc
pop de
pop bc
ret

make_scr_table:
ld ix,scr_table
ld hl,&c000
ld b,200
mst1:
ld (ix+0),l
ld (ix+1),h
inc ix
inc ix
call scr_next_line
djnz mst1
ret


scr_table:
defs 200*2


txt_coords:
txt_y:
defb 0
txt_x:
defb 0

;; in this example B is the odd char
;; on screen:
;;
;; aaaa aabb bbbb 
;;  0    1    2   
;;
;; pixels from char:
;; bbbb bb

display_char_odd:
ld b,8
dco1:
push bc
push de

;; read 4 pixels from screen
;; keep left 2 pixels
ld a,(de)
and %11001100
ld c,a
;; read font data
;; shift data two pixels to right
ld a,(hl)
rrca
rrca
and %00110011
;; combine with screen
or c
ld (de),a
inc de

ld a,(hl)
rlca
rlca
and %11001100
ld c,a
inc hl
ld a,(hl)
rrca
rrca
and %00110011
or c
ld (de),a
inc hl
pop de
ex de,hl
call scr_next_line
ex de,hl
pop bc
djnz dco1
ret


;; in this example A is the even char
;; on screen:
;;
;; aaaa aabb bbbb 
;;  0    1    2   
;;
;; pixels from char:
;; aaaa aa

display_char_even:
ld b,8
dce1:
push bc
push de

;; read 4 pixels
ld a,(hl)
;; store to screen
ld (de),a
inc de
inc hl

;; read 4 pixels from screen
ld a,(de)
;; isolate the pixels we don't want to change
and %00110011
ld c,a

;; now read 4 pixels from font
ld a,(hl)
;; isolate pixels we want
and %11001100
;; combine with screen data
or c
;; write back to screen
ld (de),a
;;inc de
inc hl
pop de
ex de,hl
call scr_next_line
ex de,hl
pop bc
djnz dce1
ret


char_depack_buffer: defs 16

font:
defb &00
defb &00,&00,&00,&00,&00,&00,&00,&00,&10,&10,&10,&10,&00,&10,&00,&00 
defb &28,&28,&00,&00,&00,&00,&00,&00,&28,&7c,&28,&28,&7c,&28,&00,&00 
defb &10,&7c,&50,&7c,&14,&7c,&10,&60,&64,&08,&10,&20,&4c,&0c,&00,&10 
defb &28,&28,&30,&54,&48,&34,&00,&10,&10,&20,&00,&00,&00,&00,&00,&08 
defb &10,&20,&20,&20,&10,&08,&00,&20,&10,&08,&08,&08,&10,&20,&00,&00 
defb &00,&28,&10,&7c,&10,&28,&00,&00,&00,&10,&10,&7c,&10,&10,&00,&00 
defb &00,&00,&00,&00,&20,&20,&40,&00,&00,&00,&00,&7c,&00,&00,&00,&00 
defb &00,&00,&00,&00,&30,&30,&00,&00,&00,&04,&08,&10,&20,&40,&00,&00 
defb &38,&4c,&54,&54,&64,&38,&00,&00,&30,&50,&10,&10,&10,&7c,&00,&00 
defb &38,&44,&04,&38,&40,&7c,&00,&00,&38,&44,&18,&04,&44,&38,&00,&00 
defb &08,&18,&28,&48,&7c,&08,&00,&00,&7c,&40,&78,&04,&44,&38,&00,&00 
defb &38,&40,&78,&44,&44,&38,&00,&00,&7c,&04,&08,&10,&20,&20,&00,&00 
defb &38,&44,&38,&44,&44,&38,&00,&00,&38,&44,&44,&3c,&04,&38,&00,&00 
defb &00,&00,&20,&00,&00,&20,&00,&00,&00,&10,&00,&00,&10,&10,&20,&00 
defb &00,&08,&10,&20,&10,&08,&00,&00,&00,&00,&7c,&00,&7c,&00,&00,&00 
defb &00,&20,&10,&08,&10,&20,&00,&00,&38,&44,&08,&10,&00,&10,&00,&70 
defb &00,&70,&48,&48,&48,&48,&00,&00,&38,&44,&44,&7c,&44,&44,&00,&00 
defb &78,&44,&78,&44,&44,&78,&00,&00,&38,&44,&40,&40,&44,&38,&00,&00 
defb &78,&24,&24,&24,&24,&78,&00,&00,&7c,&40,&78,&40,&40,&7c,&00,&00 
defb &7c,&40,&78,&40,&40,&40,&00,&00,&38,&44,&40,&4c,&44,&38,&00,&00 
defb &44,&44,&7c,&44,&44,&44,&00,&00,&38,&10,&10,&10,&10,&38,&00,&00 
defb &04,&04,&04,&44,&44,&38,&00,&00,&48,&50,&60,&50,&48,&44,&00,&00 
defb &40,&40,&40,&40,&40,&7c,&00,&00,&44,&6c,&54,&44,&44,&44,&00,&00 
defb &44,&64,&54,&4c,&44,&44,&00,&00,&38,&44,&44,&44,&44,&38,&00,&00 
defb &78,&44,&44,&78,&40,&40,&00,&00,&38,&44,&44,&54,&48,&34,&00,&00 
defb &78,&44,&44,&78,&48,&44,&00,&00,&38,&40,&38,&04,&44,&38,&00,&00 
defb &7c,&10,&10,&10,&10,&10,&00,&00,&44,&44,&44,&44,&44,&38,&00,&00 
defb &44,&44,&44,&44,&28,&10,&00,&00,&44,&44,&44,&44,&54,&28,&00,&00 
defb &44,&28,&10,&10,&28,&44,&00,&00,&44,&44,&28,&10,&10,&10,&00,&00 
defb &7c,&08,&10,&20,&40,&7c,&00,&00
list