font.s (12820B)
1; font.ms 2; 3; Michael Hope, 1999 4; michaelh@earthling.net 5; Distrubuted under the Artistic License - see www.opensource.org 6; 7 .include "global.s" 8 9 .globl .cr_curs 10 .globl .adv_curs 11 .globl .cury, .curx 12 .globl .display_off 13 14 ; Structure offsets 15 sfont_handle_sizeof = 3 16 sfont_handle_font = 1 17 sfont_handle_first_tile = 0 18 19 ; Encoding types - lower 2 bits of font 20 FONT_256ENCODING = 0 21 FONT_128ENCODING = 1 22 FONT_NOENCODING = 2 23 24 ; Other bits 25 FONT_BCOMPRESSED = 2 26 27 .CR = 0x0A ; Unix 28 .SPACE = 0x00 29 30 ; Maximum number of fonts 31 .MAX_FONTS = 6 32 33 .area _FONT_HEADER (ABS) 34 35 .org .MODE_TABLE+4*.T_MODE 36 JP .tmode 37 38 .module font.ms 39 40 .globl .fg_colour, .bg_colour 41 42 .globl .drawing_vbl, .drawing_lcd 43 .globl .int_0x40, .int_0x48 44 .globl .remove_int 45 .globl _set_bkg_1bpp_data, _set_bkg_data 46 47 .area _INITIALIZED 48.curx:: ; Cursor position 49 .ds 0x01 50.cury:: 51 .ds 0x01 52 53 .area _INITIALIZER 54 .db 0x00 ; .curx 55 .db 0x00 ; .cury 56 57 .area _DATA 58 ; The current font 59 60font_current:: 61 .ds sfont_handle_sizeof 62 ; Cached copy of the first free tile 63font_first_free_tile:: 64 .ds 1 65 ; Table containing descriptors for all of the fonts 66font_table:: 67 .ds sfont_handle_sizeof*.MAX_FONTS 68 69 .area _HOME 70 71_font_load_ibm:: 72 ld hl,#_font_ibm 73 call font_load 74 ret 75 76; Load the font HL 77font_load:: 78 call .display_off 79 push hl 80 81 ; Find the first free font entry 82 ld hl,#font_table+sfont_handle_font 83 ld b,#.MAX_FONTS 84font_load_find_slot: 85 ld a,(hl) ; Check to see if this entry is free 86 inc hl ; Free is 0000 for the font pointer 87 or (hl) 88 cp #0 89 jr z,font_load_found 90 91 inc hl 92 inc hl 93 dec b 94 jr nz,font_load_find_slot 95 pop hl 96 ld hl,#0 97 jr font_load_exit ; Couldn't find a free space 98font_load_found: 99 ; HL points to the end of the free font table entry 100 pop de 101 ld (hl),d ; Copy across the font struct pointer 102 dec hl 103 ld (hl),e 104 105 ld a,(font_first_free_tile) 106 dec hl 107 ld (hl),a 108 109 push hl 110 call font_set ; Set this new font to be the default 111 112 ; Only copy the tiles in if were in text mode 113 ld a,(.mode) 114 and #.T_MODE 115 116 call nz,font_copy_current 117 118 ; Increase the 'first free tile' counter 119 ld hl,#font_current+sfont_handle_font 120 ld a,(hl+) 121 ld h,(hl) 122 ld l,a 123 124 inc hl ; Number of tiles used 125 ld a,(font_first_free_tile) 126 add a,(hl) 127 ld (font_first_free_tile),a 128 129 pop hl ; Return font setup in HL 130font_load_exit: 131 ;; Turn the screen on 132 LDH A,(.LCDC) 133 OR #(LCDCF_ON | LCDCF_BGON) 134 AND #~(LCDCF_BG9C00 | LCDCF_BG8000) 135 LDH (.LCDC),A 136 137 RET 138 139 ; Copy the tiles from the current font into VRAM 140font_copy_current:: 141 ; Find the current font data 142 ld hl,#font_current+sfont_handle_font 143 ld a,(hl+) 144 ld h,(hl) 145 ld l,a 146 147 ld a, (hl+) 148 ld e, a 149 ld a, (hl+) 150 ld d, a 151 152 ld a, e 153 ld c, #128 154 and #3 155 cp #FONT_128ENCODING 156 jr z, 1$ 157 cp #FONT_NOENCODING 158 jr z, 2$ 159 inc h 160 jr 2$ 1611$: 162 ld a, c 163 add l 164 ld l, a 165 adc h 166 sub l 167 ld h, a 1682$: 169 push hl 170 ld c, e 171 ld a, (font_current+sfont_handle_first_tile) 172 ld e, a 173 push de 174 bit FONT_BCOMPRESSED, c 175 jr nz, 3$ 176 call _set_bkg_data 177 jr 4$ 1783$: 179 call _set_bkg_1bpp_data 1804$: 181 add sp, #4 182 ret 183 184 ; Set the current font to HL 185font_set:: 186 ld a,(hl+) 187 ld (font_current),a 188 ld a,(hl+) 189 ld (font_current+1),a 190 ld a,(hl+) 191 ld (font_current+2),a 192 ret 193 194 ;; Print a character with interpretation 195.put_char:: 196 ; See if it's a special char 197 cp #.CR 198 jr nz,1$ 199 200 ; Now see if were checking special chars 201 push af 202 ld a,(.mode) 203 and #.M_NO_INTERP 204 jr nz,2$ 205 call .cr_curs 206 pop af 207 ret 2082$: 209 pop af 2101$: 211 call .set_char 212 jp .adv_curs 213 214 ;; Print a character without interpretation 215.out_char:: 216 call .set_char 217 jp .adv_curs 218 219 ;; Delete a character 220.del_char:: 221 call .rew_curs 222 ld a,#.SPACE 223 jp .set_char 224 225 ;; Print the character in A 226.set_char: 227 push af 228 ld a,(font_current+2) 229 ; Must be non-zero if the font system is setup (cant have a font in page zero) 230 or a 231 jr nz,3$ 232 233 ; Font system is not yet setup - init it and copy in the ibm font 234 ; Kind of a compatibility mode 235 call _font_init 236 237 ; Need all of the tiles 238 xor a 239 ld (font_first_free_tile),a 240 241 call _font_load_ibm 2423$: 243 pop af 244 push bc 245 push de 246 push hl 247 ; Compute which tile maps to this character 248 ld e,a 249 ld hl,#font_current+sfont_handle_font 250 ld a,(hl+) 251 ld h,(hl) 252 ld l,a 253 ld a,(hl+) 254 and #3 255 cp #FONT_NOENCODING 256 jr z,set_char_no_encoding 257 inc hl 258 ; Now at the base of the encoding table 259 ; E is set above 260 ld d,#0 261 add hl,de 262 ld e,(hl) ; That's the tile! 263set_char_no_encoding: 264 ld a,(font_current+0) 265 add a,e 266 ld e,a 267 268 LD A,(.cury) ; Y coordinate 269 LD L,A 270 LD H,#0x00 271 ADD HL,HL 272 ADD HL,HL 273 ADD HL,HL 274 ADD HL,HL 275 ADD HL,HL 276 LD A,(.curx) ; X coordinate 277 LD C,A 278 LD B,#0x00 279 ADD HL,BC 280 LD BC,#0x9800 281 ADD HL,BC 282 283 WAIT_STAT 284 285 LD (HL),E 286 POP HL 287 POP DE 288 POP BC 289 RET 290 291_putchar:: 292 PUSH BC 293 LDA HL,4(SP) ; Skip return address 294 LD A,(HL) ; A = c 295 CALL .put_char 296 POP BC 297 RET 298 299_setchar:: 300 PUSH BC 301 LDA HL,4(SP) ; Skip return address 302 LD A,(HL) ; A = c 303 CALL .set_char 304 POP BC 305 RET 306 307_font_load:: 308 push bc 309 LDA HL,4(SP) ; Skip return address and bc 310 LD A,(HL) ; A = c 311 inc hl 312 ld h,(hl) 313 ld l,a 314 call font_load 315 push hl 316 pop de ; Return in DE 317 pop bc 318 ret 319 320_font_set:: 321 push bc 322 LDA HL,4(SP) ; Skip return address 323 LD A,(HL) ; A = c 324 inc hl 325 ld h,(hl) 326 ld l,a 327 call font_set 328 pop bc 329 ld de,#0 ; Always good... 330 ret 331 332_font_init:: 333 push bc 334 .globl .tmode 335 336 call .tmode 337 338 xor a 339 ld (font_first_free_tile),a 340 341 ; Clear the font table 342 ld hl,#font_table 343 ld b,#sfont_handle_sizeof*.MAX_FONTS 3441$: 345 ld (hl+),a 346 dec b 347 jr nz,1$ 348 ld a,#3 349 ld (.fg_colour),a 350 xor a 351 ld (.bg_colour),a 352 353 call .cls_no_reset_pos 354 pop bc 355 ret 356 357_cls:: 358.cls:: 359 XOR A 360 LD (.curx), A 361 LD (.cury), A 362.cls_no_reset_pos: 363 PUSH DE 364 PUSH HL 365 LD HL,#0x9800 366 LD E,#0x20 ; E = height 3671$: 368 LD D,#0x20 ; D = width 3692$: 370 WAIT_STAT 371 372 LD (HL),#.SPACE ; Always clear 373 INC HL 374 DEC D 375 JR NZ,2$ 376 DEC E 377 JR NZ,1$ 378 POP HL 379 POP DE 380 RET 381 382 ; Support routines 383_gotoxy:: 384 lda hl,2(sp) 385 ld a,(hl+) 386 ld (.curx),a 387 ld a,(hl) 388 ld (.cury),a 389 ret 390 391_posx:: 392 LD A,(.mode) 393 AND #.T_MODE 394 JR NZ,1$ 395 PUSH BC 396 CALL .tmode 397 POP BC 3981$: 399 LD A,(.curx) 400 LD E,A 401 RET 402 403_posy:: 404 LD A,(.mode) 405 AND #.T_MODE 406 JR NZ,1$ 407 PUSH BC 408 CALL .tmode 409 POP BC 4101$: 411 LD A,(.cury) 412 LD E,A 413 RET 414 415 ;; Rewind the cursor 416.rew_curs: 417 PUSH HL 418 LD HL,#.curx ; X coordinate 419 XOR A 420 CP (HL) 421 JR Z,1$ 422 DEC (HL) 423 JR 99$ 4241$: 425 LD (HL),#.MAXCURSPOSX 426 LD HL,#.cury ; Y coordinate 427 XOR A 428 CP (HL) 429 JR Z,99$ 430 DEC (HL) 43199$: 432 POP HL 433 RET 434 435.cr_curs:: 436 PUSH HL 437 XOR A 438 LD (.curx),A 439 LD HL,#.cury ; Y coordinate 440 LD A,#.MAXCURSPOSY 441 CP (HL) 442 JR Z,2$ 443 INC (HL) 444 JR 99$ 4452$: 446 CALL .scroll 44799$: 448 POP HL 449 RET 450 451.adv_curs:: 452 PUSH HL 453 LD HL,#.curx ; X coordinate 454 LD A,#.MAXCURSPOSX 455 CP (HL) 456 JR Z,1$ 457 INC (HL) 458 JR 99$ 4591$: 460 LD (HL),#0x00 461 LD HL,#.cury ; Y coordinate 462 LD A,#.MAXCURSPOSY 463 CP (HL) 464 JR Z,2$ 465 INC (HL) 466 JR 99$ 4672$: 468 ;; See if scrolling is disabled 469 LD A,(.mode) 470 AND #.M_NO_SCROLL 471 JR Z,3$ 472 ;; Nope - reset the cursor to (0,0) 473 XOR A 474 LD (.cury),A 475 LD (.curx),A 476 JR 99$ 4773$: 478 CALL .scroll 47999$: 480 POP HL 481 RET 482 483 ;; Scroll the whole screen 484.scroll: 485 PUSH BC 486 PUSH DE 487 PUSH HL 488 LD HL,#0x9800 489 LD BC,#0x9800+0x20 ; BC = next line 490 LD E,#0x20-0x01 ; E = height - 1 4911$: 492 LD D,#0x20 ; D = width 4932$: 494 WAIT_STAT 495 LD A,(BC) 496 LD (HL+),A 497 INC BC 498 499 DEC D 500 JR NZ,2$ 501 DEC E 502 JR NZ,1$ 503 504 LD D,#0x20 5053$: 506 WAIT_STAT 507 LD A,#.SPACE 508 LD (HL+),A 509 DEC D 510 JR NZ,3$ 511 512 POP HL 513 POP DE 514 POP BC 515 RET 516 517 ;; Enter text mode 518.tmode:: 519 DI ; Disable interrupts 520 521 ;; Turn the screen off 522 LDH A,(.LCDC) 523 AND #LCDCF_ON 524 JR Z,1$ 525 526 ;; Turn the screen off 527 CALL .display_off 528 529 ;; Remove any interrupts setup by the drawing routine 530 LD BC,#.drawing_vbl 531 LD HL,#.int_0x40 532 CALL .remove_int 533 LD BC,#.drawing_lcd 534 LD HL,#.int_0x48 535 CALL .remove_int 5361$: 537 538 CALL .tmode_out 539 540 ;; Turn the screen on 541 LDH A,(.LCDC) 542 OR #(LCDCF_ON | LCDCF_BGON) 543 AND #~(LCDCF_BG9C00 | LCDCF_BG8000) 544 LDH (.LCDC),A 545 546 EI ; Enable interrupts 547 548 RET 549 550 ;; Text mode (out only) 551.tmode_out:: 552 ;; Clear screen 553 CALL .cls_no_reset_pos 554 555 LD A,#.T_MODE 556 LD (.mode),A 557 558 RET