1; font.ms
2;
3;	Michael Hope, 1999
4;	michaelh@earthling.net
5;	Distrubuted under the Artistic License - see www.opensource.org
6;
7
8
9    INCLUDE "target/gb/def/gb_globals.def"
10
11
12    PUBLIC	tmode_out
13    PUBLIC	tmode
14    PUBLIC	asm_setchar
15    PUBLIC  asm_font_load
16    PUBLIC  asm_font_set
17    PUBLIC  asm_load_z88dk_font
18    PUBLIC  asm_load_z88dk_udg
19
20    GLOBAL	display_off
21
22
23    GLOBAL	__console_y, __console_x
24
25    EXTERN	asm_cls
26    EXTERN	asm_adv_curs
27    EXTERN	__mode
28    EXTERN	generic_console_font32
29
30    ; Structure offsets
31    defc sfont_handle_sizeof    =	3
32    defc sfont_handle_font      =	1
33    defc sfont_handle_first_tile	=	0
34
35    ; Other bits
36    defc FONT_BCOMPRESSED	=	2
37
38    defc CR     		= 	0x0A          ; Unix
39    defc SPACE			=	0x00
40
41    ; Maximum number of fonts
42    defc MAX_FONTS		= 	6
43
44    ; Globals from drawing.s
45    ; FIXME: Hmmm... check the linkage of these
46    GLOBAL	__fgcolour
47    GLOBAL	__bgcolour
48
49	SECTION	bss_driver
50	; The current font
51font_current:
52	defs	sfont_handle_sizeof
53	; +0 =
54	; +1 = font address low
55	; +2 = font address high
56	; Cached copy of the first free tile
57font_first_free_tile:
58	defs	1
59	; Table containing descriptors for all of the fonts
60font_table:
61	defs	sfont_handle_sizeof*MAX_FONTS
62
63	SECTION	code_driver
64	; Copy uncompressed 16 byte tiles from (BC) to (HL), length = DE*2
65	; Note: HL must be aligned on a UWORD boundry
66font_copy_uncompressed:
67    ld      a,d
68    or      e
69    ret     z
70    ld      a,h
71    cp      0x98
72    jr      c,fc_4
73    sub     0x98-0x88
74    ld      h,a
75fc_4:
76    xor     a
77    cp      e		; Special for when e=0 you will get another loop
78    jr      nz,fc_1
79    dec     d
80fc_1:
81    ldh     a,(STAT)
82    bit     1,a
83    jr      nz,fc_1
84    ld      a,(bc)
85    ld	    (hl+),a
86    inc	    bc
87stat_1:
88    ldh     a,(STAT)
89    bit     1,a
90    jr      nz,stat_1
91    ld      a,(bc)
92    ld      (hl),a
93    inc     bc
94    inc	    l
95    jr      nz,fc_2
96    inc     h
97    ld      a,h		; Special wrap-around
98    cp      0x98
99    jr      nz,fc_2
100    ld      h,0x88
101fc_2:
102    dec     e
103    jr      nz,fc_1
104    dec     d
105    bit     7,d		; -1?
106    jr      z,fc_1
107    ret
108
109    ; Copy a set of compressed (8 bytes/cell) tiles to VRAM
110    ; Sets the foreground and background colours based on the current
111    ; font colours
112    ; Entry:
113    ;	From (BC) to (HL), length (DE) where DE = #cells * 8
114    ;	Uses the current __fgcolour and __bgcolour fiedefs
115font_copy_compressed:
116    ld      a,d
117    or      e
118    ret     z		; Do nothing
119
120    ld      a,h
121    cp      0x98		; Take care of the 97FF -> 8800 wrap around
122    jr      c,font_copy_compressed_loop
123    sub     0x98-0x88
124    ld      h,a
125font_copy_compressed_loop:
126    push    de
127    ld      a,(bc)
128    ld      e,a
129    inc     bc
130    push    bc
131
132    ld      bc,0
133        ; Do the background colour first
134    ld      a,(__bgcolour)
135    bit     0,a
136    jr      z,font_copy_compressed_bg_grey1
137    ld      b,0xFF
138font_copy_compressed_bg_grey1:
139    bit     1,a
140    jr      z,font_copy_compressed_bg_grey2
141    ld      c,0xFF
142font_copy_compressed_bg_grey2:
143    ; BC contains the background colour
144    ; Compute what xoring we need to do to get the correct fg colour
145    ld      d,a
146    ld      a,(__fgcolour)
147    xor     d
148    ld      d,a
149
150    bit     0,d
151    jr      z,font_copy_compressed_grey1
152    ld      a,e
153    xor     b
154    ld      b,a
155font_copy_compressed_grey1:
156    bit     1,d
157    jr      z,font_copy_compressed_grey2
158    ld      a,e
159    xor     c
160    ld      c,a
161font_copy_compressed_grey2:
162    ldh     a,(STAT)
163    bit     1,a
164    jr      nz,font_copy_compressed_grey2
165    ld      (hl),b
166    inc     hl
167stat_2:
168    ldh     a,(STAT)
169    bit     1,a
170    jr      nz,stat_2
171    ld      (hl),c
172    inc     hl
173    ld      a,h		; Take care of the 97FFF -> 8800 wrap around
174    cp      0x98
175    jr      nz,fcc_1
176    ld      h,0x88
177fcc_1:
178    pop     bc
179    pop     de
180    dec     de
181    ld      a,d
182    or      e
183    jr      nz,font_copy_compressed_loop
184    ret
185
186; Load the font HL
187asm_font_load:
188    call    display_off
189    push    hl
190
191    ; Find the first free font entry
192    ld      hl,font_table+sfont_handle_font
193    ld      b,MAX_FONTS
194font_load_find_slot:
195    ld      a,(hl)		; Check to see if this entry is free
196    inc     hl		; Free is 0000 for the font pointer
197    or      (hl)
198    jr      z,font_load_found
199
200    inc     hl
201    inc     hl
202    dec     b
203    jr      nz,font_load_find_slot
204    pop     hl
205    ld      hl,0
206    jr      font_load_exit	; Couldn't find a free space
207font_load_found:
208    ; HL points to the end of the free font table entry
209    pop     de
210    ld      (hl),d		; Copy across the font struct pointer
211    dec     hl
212    ld      (hl),e
213
214    ld      a,(font_first_free_tile)
215    dec     hl
216    ld      (hl),a
217
218    push    hl
219    call    asm_font_set	; Set this new font to be the default
220
221    ; Only copy the tiles in if were in text mode
222    ld      a,(__mode)
223    and     T_MODE
224
225    call    nz,font_copy_current
226
227    ; Increase the 'first free tile' counter
228    ld      hl,font_current+sfont_handle_font
229    ld      a,(hl+)
230    ld      h,(hl)
231    ld      l,a
232
233    inc     hl		; Number of tiles used
234    ld      a,(font_first_free_tile)
235    add     a,(hl)
236    ld      (font_first_free_tile),a
237
238    pop     hl		; Return font setup in HL
239font_load_exit:
240    ;; Turn the screen on
241    LDH     A,(LCDC)
242    OR      @10000001       ; LCD           = On
243                            ; BG            = On
244    AND     @11100111       ; BG Chr        = 0x8800
245                            ; BG Bank       = 0x9800
246    LDH     (LCDC),A
247
248    RET
249
250	; Copy the tiles from the current font into VRAM
251font_copy_current:
252    ; Find the current font data
253    ld      hl,font_current+sfont_handle_font
254    ld      a,(hl+)
255    ld      h,(hl)
256    ld      l,a     ;hl = font address
257
258    inc     hl      ; Points to the 'tiles required' entry
259    ld      e,(hl)
260    ld      d,0
261    rl      e       ; Multiple DE by 8
262    rl      d
263    rl      e
264    rl      d
265    rl      e
266    rl      d       ; DE has the length of the tile data
267    dec     hl
268
269    ld      a,(hl)  ; Get the flags
270    push    af
271    and     3       ; Only lower 2 bits set encoding table size
272
273    ld      bc,128
274    cp      FONT_128ENCODING    ; 0 for 256 char encoding table, 1 for 128 char
275    jr      z,font_copy_current_copy
276
277    ld      bc,0
278    cp      FONT_NOENCODING
279    jr      z,font_copy_current_copy
280
281    ld      bc,256  ; Must be 256 element encoding
282font_copy_current_copy:
283    inc     hl
284    inc     hl      ; Points to the start of the encoding table
285    add     hl,bc
286    ld      c,l
287    ld      b,h     ; BC points to the start of the tile data
288
289    ; Find the offset in VRAM for this font
290    ld      a,(font_current+sfont_handle_first_tile)	; First tile used for this font
291    ld      l,a
292    ld      h,0
293    add     hl,hl
294    add     hl,hl
295    add     hl,hl
296    add     hl,hl
297
298    ld      a,0x90  ; Tile 0 is at 9000h
299    add     a,h
300    ld      h,a
301    ; Is this font compressed?
302    pop	    af      ; Recover flags
303    bit     FONT_BCOMPRESSED,a
304    ; Do the jump in a mildly different way
305    jp	    z,font_copy_uncompressed
306    jp	    font_copy_compressed
307
308; Set the current font to HL
309asm_font_set:
310    ld      a,(hl+)
311    ld      (font_current),a
312    ld      a,(hl+)
313    ld      (font_current+1),a
314    ld      a,(hl+)
315    ld      (font_current+2),a
316    ret
317
318
319	;; Print a character without interpretation
320out_char:
321    call    asm_setchar
322    call    asm_adv_curs
323    ret
324
325
326;; Print the character in A
327; C =x, B=y
328asm_setchar:
329    push    af
330    ld      a,(font_current+2)
331    ; Must be non-zero if the font system is setup (cant have a font in page zero)
332    or      a
333    jr      nz,asm_setchar_3
334
335    push    bc
336    ; Font system is not yet setup - init it and copy in the default font
337    ; Kind of a compatibility mode
338    call    _font_init
339
340    ; Need all of the tiles
341    xor     a
342    ld      (font_first_free_tile),a
343
344    ld      hl,generic_console_font32
345    ld      a,(hl+)
346    ld      h,(hl)
347    ld      l,a
348    call    asm_font_load
349    pop     bc
350asm_setchar_3:
351    pop     af
352    push    de
353    push    hl
354    push    bc      ;Save coordinates
355    ; Compute which tile maps to this character
356    ld      e,a
357    ld      hl,font_current+sfont_handle_font
358    ld      a,(hl+)
359    ld      h,(hl)
360    ld      l,a     ;hl = address of font
361    ld      a,(hl+) ;font encoding
362    and     3
363    cp      FONT_NOENCODING
364    jr      z,asm_setchar_no_encoding
365    inc     hl
366    ; Now at the base of the encoding table
367    ; E is set above
368    ld      d,0
369    add     hl,de
370    ld      e,(hl)  ; That's the tile!
371asm_setchar_no_encoding:
372    ld      a,(font_current+0)  ;first tile
373    add     a,e
374    ld      e,a     ;e = tile to use
375
376    pop     bc      ;c = x, b = y
377    push    bc
378
379    LD      L,B
380    LD      H,0x00
381    ADD     HL,HL
382    ADD     HL,HL
383    ADD     HL,HL
384    ADD     HL,HL
385    ADD     HL,HL
386    LD      B,0x00  ;Add on x coordinate now
387    ADD     HL,BC
388    LD      BC,0x9800
389    ADD     HL,BC
390
391stat_4:
392    ldh     a,(STAT)
393    bit     1,a
394    jr      nz,stat_4
395
396    LD      (HL),E
397    POP     BC
398    POP     HL
399    POP     DE
400    RET
401
402
403_font_init:
404    push    bc
405    call    tmode
406    xor     a       ; We use the first tile as a space _always_
407    ld      (font_first_free_tile),a
408
409    ; Clear the font table
410    ld      hl,font_table
411    ld      b,sfont_handle_sizeof*MAX_FONTS
412init_1:
413    ld      (hl+),a
414    dec     b
415    jr      nz,init_1
416    ld      (__bgcolour),a	;a = 0
417    ld      a,3
418    ld      (__fgcolour),a
419    call    asm_cls
420    pop     bc
421    ret
422
423
424
425    SECTION code_driver
426    GLOBAL  vbl
427    GLOBAL  lcd
428    GLOBAL  int_0x40
429    GLOBAL  int_0x48
430    GLOBAL  remove_int
431
432	;; Enter text mode
433tmode:
434    DI          ; Disable interrupts
435
436    ;; Turn the screen off
437    LDH     A,(LCDC)
438    BIT     7,A
439    JR      Z,tmode_1
440
441    ;; Turn the screen off
442    CALL    display_off
443
444    ;; Remove any interrupts setup by the drawing routine
445
446    ;	LD	BC,vbl
447    ;	LD	HL,int_0x40
448    ;	CALL	remove_int
449    ;	LD	BC,lcd
450    ;	LD	HL,int_0x48
451    ;	CALL	remove_int
452tmode_1:
453
454    CALL    tmode_out
455
456    ;; Turn the screen on
457    LDH     A,(LCDC)
458    OR      @10000001   ; LCD		= On
459                        ; BG		= On
460    AND     @11100111   ; BG Chr	= 0x8800
461                        ; BG Bank	= 0x9800
462    LDH     (LCDC),A
463    EI                  ; Enable interrupts
464    RET
465
466;; Text mode (out only)
467tmode_out:
468    XOR     A
469    LD      (__console_x),A
470    LD      (__console_y),A
471    ;; Clear screen
472    CALL    asm_cls
473    LD      A,T_MODE
474    LD      (__mode),A
475    RET
476
477
478
479; Entry: bc = address of font (with gb header)
480asm_load_z88dk_font:
481    push    bc
482    ld      a,(font_current+2)
483    ; Must be non-zero if the font system is setup (cant have a font in page zero)
484    and     a
485    call    z,_font_init
486    xor     a
487    ld      (font_first_free_tile),a
488    ld      c,l
489    ld      b,h
490    call    asm_font_load
491    pop     bc
492    ret
493
494; Entry: bc = address of UDG bitmaps
495asm_load_z88dk_udg:
496    ld      a,(font_current+2)
497    ; Must be non-zero if the font system is setup (cant have a font in page zero)
498    and     a
499    jr      nz,set_udgs
500    push    bc
501    ld      hl,generic_console_font32
502    ld      c,(hl)
503    inc     hl
504    ld      b,(hl)
505    call    asm_load_z88dk_font
506    pop     bc
507set_udgs:
508    ld      hl,$8800    ;Tile 128 is the first UDG
509    ld      de,64 * 8
510    call    font_copy_compressed
511    ret
512
513