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