X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libsrc%2Flynx%2Flynx-160-102-16.s;h=83e0c10afd8d8a8f1e99cc154554223e3b19c7a1;hb=5f006333bf97d98099a4702320f60c3551a5bbe5;hp=d9899271f028f1316cd3f14dfbc056729fb114fd;hpb=4964382c67bb3cc2d74df95a39516ae8042d3fed;p=cc65 diff --git a/libsrc/lynx/lynx-160-102-16.s b/libsrc/lynx/lynx-160-102-16.s index d9899271f..83e0c10af 100644 --- a/libsrc/lynx/lynx-160-102-16.s +++ b/libsrc/lynx/lynx-160-102-16.s @@ -1,10 +1,19 @@ ; ; Graphics driver for the 160x102x16 mode on the Lynx. ; -; Based on Stephen L. Judds GRLIB code +; All the drawing functions are simply done by sprites as the sprite +; engine is the only way to do fast graphics on a Lynx. +; +; So the code is not really based on any algorithms done by somebody. +; I have looked at other routines in the cc65 libs to see what kind of +; entry points we need. And I have looked at the old cc65 libs by +; Bastian Schick to see how things worked in the past. +; +; This code is written by Karri Kaksonen, 2004 for the cc65 compiler. ; .include "zeropage.inc" + .include "extzp.inc" .include "tgi-kernel.inc" .include "tgi-mode.inc" @@ -14,7 +23,6 @@ .macpack generic - ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. @@ -28,7 +36,7 @@ .word 160 ; X resolution .word 102 ; Y resolution .byte 16 ; Number of drawing colors - .byte 1 ; Number of screens available + .byte 2 ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size .res 4, $00 ; Reserved for future extensions @@ -39,26 +47,28 @@ ; that the graphics kernel will emulate the function by using lower level ; primitives - for example ploting a line by using calls to SETPIXEL. - .word INSTALL - .word UNINSTALL - .word INIT - .word DONE - .word GETERROR - .word CONTROL - .word CLEAR - .word SETVIEWPAGE - .word SETDRAWPAGE - .word SETCOLOR - .word SETPALETTE - .word GETPALETTE - .word GETDEFPALETTE - .word SETPIXEL - .word GETPIXEL - .word LINE - .word BAR - .word CIRCLE - .word TEXTSTYLE - .word OUTTEXT + .addr INSTALL + .addr UNINSTALL + .addr INIT + .addr DONE + .addr GETERROR + .addr CONTROL + .addr CLEAR + .addr SETVIEWPAGE + .addr SETDRAWPAGE + .addr SETCOLOR + .addr SETPALETTE + .addr GETPALETTE + .addr GETDEFPALETTE + .addr SETPIXEL + .addr GETPIXEL + .addr LINE + .addr BAR + .addr CIRCLE + .addr TEXTSTYLE + .addr OUTTEXT + .addr IRQ + ; ------------------------------------------------------------------------ ; Data. @@ -70,17 +80,11 @@ X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 -RADIUS := tmp1 - -ROW := tmp2 ; Bitmap row... -COL := tmp3 ; ...and column, both set by PLOT -TEMP := tmp4 -TEMP2 := sreg -POINT := regsave -INRANGE := regsave+2 ; PLOT variable, $00 = coordinates in range -CHUNK := X2 ; Used in the line routine -OLDCHUNK := X2+1 ; Dito +STRPTR := ptr3 +FONTOFF := ptr4 +STROFF := tmp3 +STRLEN := tmp4 ; Absolute variables used in the code @@ -91,34 +95,21 @@ ERROR: .res 1 ; Error code DRAWINDEX: .res 1 ; Pen to use for drawing VIEWPAGEL: .res 1 VIEWPAGEH: .res 1 - -; INIT/DONE -OLDD018: .res 1 ; Old register value - -; Line routine stuff -DX: .res 2 -DY: .res 2 - -; Circle routine stuff, overlaid by BAR variables -X1SAVE: -CURX: .res 1 -CURY: .res 1 -Y1SAVE: -BROW: .res 1 ; Bottom row -TROW: .res 1 ; Top row -X2SAVE: -LCOL: .res 1 ; Left column -RCOL: .res 1 ; Right column -Y2SAVE: -CHUNK1: .res 1 -OLDCH1: .res 1 -CHUNK2: .res 1 -OLDCH2: .res 1 +DRAWPAGEL: .res 1 +DRAWPAGEH: .res 1 ; Text output stuff TEXTMAGX: .res 1 TEXTMAGY: .res 1 TEXTDIR: .res 1 +BGINDEX: .res 1 ; Pen to use for text background + +; Double buffer IRQ stuff +DRAWPAGE: .res 1 +SWAPREQUEST: .res 1 + +text_bitmap: .res 8*(1+20+1)+1 +; 8 rows with (one offset-byte plus 20 character bytes plus one fill-byte) plus one 0-offset-byte ; Constants and tables @@ -159,13 +150,6 @@ DEFPALETTE: .byte >$000 PALETTESIZE = * - DEFPALETTE -BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01 -BITCHUNK: .byte $FF,$7F,$3F,$1F,$0F,$07,$03,$01 - -VBASE = $E000 ; Video memory base address -CBASE = $D000 ; Color memory base address - - .code ; ------------------------------------------------------------------------ @@ -177,6 +161,12 @@ CBASE = $D000 ; Color memory base address ; INSTALL: + lda #1 + sta TEXTMAGX + sta TEXTMAGY + stz BGINDEX + stz DRAWPAGE + stz SWAPREQUEST rts @@ -206,8 +196,20 @@ UNINSTALL: ; INIT: +; Enable interrupts for VBL + lda #$80 + tsb VTIMCTLA +; Set up collision buffer to $A058 + lda #$58 + sta COLLBASL + lda #$A0 + sta COLLBASH +; Put collision index before sprite data + lda #$FE + sta COLLOFFL + lda #$FF + sta COLLOFFH ; Done, reset the error code - lda #TGI_ERR_OK sta ERROR rts @@ -237,9 +239,138 @@ GETERROR: ; ; Must set an error code: YES ; +; The TGI lacks a way to draw sprites. As that functionality is vital to +; Lynx games we borrow this CONTROL function to implement the still +; missing tgi_draw_sprite funtion. To use this in your C-program +; do a #define tgi_draw_sprite(spr) tgi_ioctl(0, spr) +; +; To do a flip-screen call tgi_ioctl(1, 0) +; +; To set the background index for text outputs call tgi_ioctl(2, bgindex) +; +; To set the frame rate for the display hardware call tgi_ioctl(3, rate) +; +; To check if the drawing engine is busy with the previous swap you can +; call tgi_ioctl(4, 0). It returns 0 if idle and 1 if busy +; +; To update displays you can call tgi_ioctl(4, 1) it will wait for the +; next VBL interrupt and swap draw and view buffers. +; +; Activate or deactivate collision detection by calling tgi_ioctl(5, 0/1). CONTROL: - lda #TGI_ERR_INV_FUNC + pha ; Almost all control routines succeed + lda #TGI_ERR_OK + sta ERROR + pla + + cmp #5 + bne ControlSwap + lda ptr1 + bne @L0 + lda __sprsys + ora #$20 + bra @L1 +@L0: lda __sprsys + and #$df +@L1: sta __sprsys + sta SPRSYS + rts + +ControlSwap: + cmp #4 + bne ControlFramerate + + lda ptr1 ; Swap request + bne @L0 + lda SWAPREQUEST + rts +@L0: sta SWAPREQUEST + rts + +ControlFramerate: + cmp #3 + bne ControlTextBG + + lda ptr1 + cmp #75 ; Set framerate + beq rate75 + cmp #60 + beq rate60 + cmp #50 + beq rate50 + lda #TGI_ERR_INV_ARG + sta ERROR + rts +rate50: lda #$bd ; 50 Hz + ldx #$31 + bra setRate +rate60: lda #$9e ; 60 Hz + ldx #$29 + bra setRate +rate75: lda #$7e ; 75 Hz + ldx #$20 +setRate: + sta HTIMBKUP + stx PBKUP + rts + +ControlTextBG: + cmp #2 + bne ControlFlipScreen + + lda ptr1 ; Set text background color + sta BGINDEX + rts + +ControlFlipScreen: + cmp #1 + bne ControlDrawSprite + + lda __sprsys ; Flip screen + eor #8 + sta __sprsys + sta SPRSYS + lda __viddma + eor #2 + sta __viddma + sta DISPCTL + ldy VIEWPAGEL + ldx VIEWPAGEH + and #2 + beq NotFlipped + clc + tya + adc #<8159 + tay + txa + adc #>8159 + tax +NotFlipped: + sty DISPADRL + stx DISPADRH + rts + +ControlDrawSprite: + lda ptr1 ; Get the sprite address + ldx ptr1+1 + +draw_sprite: ; Draw it in render buffer + sta SCBNEXTL + stx SCBNEXTH + lda DRAWPAGEL + ldx DRAWPAGEH + sta VIDBASL + stx VIDBASH + lda #1 + sta SPRGO + stz SDONEACK +@L0: stz CPUSLEEP + lda SPRSYS + lsr + bcs @L0 + stz SDONEACK + lda #TGI_ERR_OK sta ERROR rts @@ -266,18 +397,7 @@ cls_sprite: .code CLEAR: lda #cls_sprite -draw_sprite: - sta $fc10 - stx $fc11 - lda #1 - sta $fc91 - stz $fd90 -@L3: stz CPUSLEEP - lda $fc92 - lsr - bcs @L3 - stz $fd90 - rts + bra draw_sprite ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). @@ -285,18 +405,37 @@ draw_sprite: ; ; Must set an error code: NO (will only be called if page ok) ; +; It is a good idea to call this function during the vertical blanking +; period. If you call it in the middle of the screen update then half of +; the drawn frame will be from the old buffer and the other half is +; from the new buffer. This is usually noticed by the user. SETVIEWPAGE: - beq @L1 - lda #<$fe00-8160-8160 - ldx #>$fe00-8160-8160 + cmp #1 + beq @L1 ; page == maxpages-1 + ldy #<$e018 ; page 0 + ldx #>$e018 bra @L2 -@L1: lda #<$fe00-8160 - ldx #>$fe00-8160 -@L2: sta DISPADRL ; $FD94 - sta VIEWPAGEL - stx DISPADRH ; $FD95 - sta VIEWPAGEH +@L1: + ldy #<$c038 ; page 1 + ldx #>$c038 +@L2: + sty VIEWPAGEL ; Save viewpage for getpixel + stx VIEWPAGEH + + lda __viddma ; Process flipped displays + and #2 + beq @L3 + clc + tya + adc #<8159 + tay + txa + adc #>8159 + tax +@L3: + sty DISPADRL ; $FD94 + stx DISPADRH ; $FD95 rts ; ------------------------------------------------------------------------ @@ -307,16 +446,42 @@ SETVIEWPAGE: ; SETDRAWPAGE: - beq @L1 - lda #<$fe00-8160-8160 - ldx #>$fe00-8160-8160 + cmp #1 + beq @L1 ; page == maxpages-1 + lda #<$e018 ; page 0 + ldx #>$e018 bra @L2 -@L1: lda #<$fe00-8160 - ldx #>$fe00-8160 -@L2: sta VIDBASL ; $FD94 - stx VIDBASH ; $FD95 +@L1: + lda #<$c038 ; page 1 + ldx #>$c038 +@L2: + sta DRAWPAGEL + stx DRAWPAGEH rts +; ------------------------------------------------------------------------ +; IRQ: VBL interrupt handler +; + +IRQ: + lda INTSET ; Poll all pending interrupts + and #VBL_INTERRUPT + beq IRQEND ; Exit if not a VBL interrupt + + lda SWAPREQUEST + beq @L0 + lda DRAWPAGE + jsr SETVIEWPAGE + lda DRAWPAGE + eor #1 + sta DRAWPAGE + jsr SETDRAWPAGE + stz SWAPREQUEST +@L0: +IRQEND: + clc + rts + ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). @@ -383,7 +548,7 @@ GETDEFPALETTE: ; ; Must set an error code: NO ; - + .data pixel_sprite: .byte %00000001 ; A pixel sprite @@ -392,10 +557,10 @@ pixel_sprite: .addr 0,pixel_bitmap pix_x: .word 0 pix_y: .word 0 - .word $0100 - .word $0100 + .word $100 + .word $100 pix_c: .byte $00 - + .code SETPIXEL: lda X1 @@ -435,7 +600,13 @@ GETPIXEL: sta ptr1+1 ldx #0 + lda #15 + sta MAPCTL lda (ptr1),y + tay + lda #$0c + sta MAPCTL + tya plp bcc @L1 and #$f @@ -451,19 +622,124 @@ GETPIXEL: ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; -; To deal with off-screen coordinates, the current row -; and column (40x25) is kept track of. These are set -; negative when the point is off the screen, and made -; positive when the point is within the visible screen. -; -; X1,X2 etc. are set up above (x2=LINNUM in particular) -; Format is LINE x2,y2,x1,y1 -; ; Must set an error code: NO ; +.data +line_sprite: + .byte 0 ; Will be replaced by the code + .byte %00110000 + .byte %00100000 + .word 0,pixel_bitmap +line_x: + .word 0 +line_y: + .word 0 +line_sx: + .word $100 +line_sy: + .word $100 + .word 0 +line_tilt: + .word 0 +line_c: + .byte $e + +.code LINE: - rts + lda DRAWINDEX + sta line_c + stz line_sx + stz line_sy + + sec + lda X2 + sbc X1 + lda X2+1 + sbc X1+1 + bpl @L1 + lda X1 + ldx X2 + sta X2 + stx X1 + lda X1+1 + ldx X2+1 + sta X2+1 + stx X1+1 + lda Y1 + ldx Y2 + sta Y2 + stx Y1 + lda Y1+1 + ldx Y2+1 + sta Y2+1 + stx Y1+1 +@L1: + lda #%00000000 ; Not flipped + sta line_sprite + + sec + lda Y2 + sbc Y1 + sta Y2 + lda Y2+1 + sbc Y1+1 + sta Y2+1 + bpl @L2 + sec + lda #0 + sbc Y2 + sta Y2 + lda #0 + sbc Y2+1 + sta Y2+1 + lda #%00010000 ; Vertical flip + sta line_sprite +@L2: + lda X1 + sta line_x + lda X1+1 + sta line_x+1 + lda Y1 + sta line_y + lda Y1+1 + sta line_y+1 + + lda Y2 + ina + sta line_sy+1 + sta MATHP ; hardware divide + stz MATHN + + stz MATHH + stz MATHG + sec + lda X2 + sbc X1 + ina + sta MATHF + stz MATHE +@L3: + lda SPRSYS + bmi @L3 ; wait for math done (bit 7 of sprsys) + lda MATHC + sta line_tilt + lda MATHB + sta line_tilt+1 + bne @L4 + lda #1 + sta line_sx+1 + bra @L6 +@L4: + bit line_tilt + bpl @L5 + ina +@L5: + sta line_sx+1 +@L6: + lda #line_sprite + jmp draw_sprite ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where @@ -501,10 +777,12 @@ BAR: lda X1 lda X2 sec sbc X1 + ina sta bar_sx+1 lda Y2 sec sbc Y1 + ina sta bar_sy+1 lda DRAWINDEX sta bar_c @@ -518,9 +796,58 @@ BAR: lda X1 ; ; Must set an error code: NO ; +; There is no sensible way of drawing a circle on a Lynx. As I would +; have to use line elements to do the circle I rather do it in C than +; create it here in the driver. + +; To do a circle please add this to your C program + +;int sintbl[9] = { +; 0, // 0 degrees +; 3196, // 11.25 degrees +; 6270, // 22.5 degrees +; 9102, // 33.75 degrees +; 11585, // 45 degrees +; 13623, // 56.25 degrees +; 15137, // 67.5 degrees +; 16069, // 78.75 degrees +; 16384 // 90 degrees +;}; + +;int sin(char d) +;{ +; char neg; +; d = d & 31; +; neg = d > 16; +; d = d & 15; +; if (d > 8) +; d = 16 - d; +; if (neg) +; return -sintbl[d]; +; else +; return sintbl[d]; +;} + +;void tgi_Circle(int x0, int y0, unsigned char r) +;{ +; char i; +; int x1, y1, x2, y2; +; +; x1 = ((long)sin(0) * r + 8192) / 16384 + x0; +; y1 = ((long)sin(8) * r + 8192) / 16384 + y0; +; for (i = 1; i <= 32; i++) { +; x2 = ((long)sin(i) * r + 8192) / 16384 + x0; +; y2 = ((long)sin(i+8) * r + 8192) / 16384 + y0; +; tgi_line(x1, y1, x2, y2); +; x1 = x2; +; y1 = y2; +; } +;} + +;#define tgi_circle tgi_Circle CIRCLE: - rts + rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y @@ -535,7 +862,6 @@ TEXTSTYLE: sta TEXTDIR rts - ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated @@ -545,5 +871,237 @@ TEXTSTYLE: ; OUTTEXT: - rts + lda TEXTMAGX ; Scale sprite + sta text_sx+1 + lda TEXTMAGY + sta text_sy+1 + + stz text_sprite ; Set normal sprite + lda BGINDEX + bne @L1 + lda #4 + sta text_sprite ; Set opaque sprite +@L1: + lda DRAWINDEX ; Set color + asl + asl + asl + asl + ora BGINDEX + sta text_c + + lda X1 ; Set start position + sta text_x + lda X1+1 + sta text_x+1 + lda Y1 + sta text_y + lda Y1+1 + sta text_y+1 + + ldy #-1 ; Calculate string length +@L2: + iny + lda (STRPTR),y + bne @L2 + cpy #20 + bmi @L3 + ldy #20 +@L3: + sty STRLEN + bne @L4 + rts ; Zero length string +@L4: + iny ; Prepare text_bitmap + iny + sty STROFF + + ldy #8-1 ; 8 pixel lines per character + ldx #0 + clc +@L5: + lda STROFF + sta text_bitmap,x + txa + adc STROFF + tax + lda #$ff + sta text_bitmap-1,x + dey + bpl @L5 + stz text_bitmap,x + + stz tmp2 + iny +@L6: + lda (STRPTR),y + sty tmp1 + + sec ; (ch-' ') * 8 + sbc #32 + stz FONTOFF + stz FONTOFF+1 + asl + asl + rol FONTOFF+1 + asl + rol FONTOFF+1 + clc ; Choose font + adc #font + sta FONTOFF+1 + +; and now copy the 8 bytes of that char + + ldx tmp2 + inx + stx tmp2 + +; draw char from top to bottom, reading char-data from offset 8-1 to offset 0 + ldy #8-1 +@L7: + lda (FONTOFF),y ; *chptr + sta text_bitmap,x ;textbuf[y*(1+len+1)+1+x] + + txa + adc STROFF + tax + + dey + bpl @L7 + + ; goto next char + ldy tmp1 + iny + dec STRLEN + bne @L6 + + lda #text_sprite + jmp draw_sprite + +.data +text_sprite: + .byte $00,$90,$20 + .addr 0, text_bitmap +text_x: + .word 0 +text_y: + .word 0 +text_sx: + .word $100 +text_sy: + .word $100 +text_c: + .byte 0 +.rodata +; The Font +; 96 characters from ASCII 32 to 127 +; 8 pixels wide, 8 pixels high +; bit value 0 = foreground, bit value 1 = background / transparent +font: +; VERSAIL + .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ;32 + .byte $FF, $E7, $FF, $FF, $E7, $E7, $E7, $E7 ;33 + .byte $FF, $FF, $FF, $FF, $FF, $99, $99, $99 ;34 + .byte $FF, $99, $99, $00, $99, $00, $99, $99 ;35 + .byte $FF, $E7, $83, $F9, $C3, $9F, $C1, $E7 ;36 + .byte $FF, $B9, $99, $CF, $E7, $F3, $99, $9D ;37 + .byte $FF, $C0, $99, $98, $C7, $C3, $99, $C3 ;38 + .byte $FF, $FF, $FF, $FF, $FF, $E7, $F3, $F9 ;39 + .byte $FF, $F3, $E7, $CF, $CF, $CF, $E7, $F3 ;40 + .byte $FF, $CF, $E7, $F3, $F3, $F3, $E7, $CF ;41 + .byte $FF, $FF, $99, $C3, $00, $C3, $99, $FF ;42 + .byte $FF, $FF, $E7, $E7, $81, $E7, $E7, $FF ;43 + .byte $CF, $E7, $E7, $FF, $FF, $FF, $FF, $FF ;44 + .byte $FF, $FF, $FF, $FF, $81, $FF, $FF, $FF ;45 + .byte $FF, $E7, $E7, $FF, $FF, $FF, $FF, $FF ;46 + .byte $FF, $9F, $CF, $E7, $F3, $F9, $FC, $FF ;47 + .byte $FF, $C3, $99, $99, $89, $91, $99, $C3 ;48 + .byte $FF, $81, $E7, $E7, $E7, $C7, $E7, $E7 ;49 + .byte $FF, $81, $9F, $CF, $F3, $F9, $99, $C3 ;50 + .byte $FF, $C3, $99, $F9, $E3, $F9, $99, $C3 ;51 + .byte $FF, $F9, $F9, $80, $99, $E1, $F1, $F9 ;52 + .byte $FF, $C3, $99, $F9, $F9, $83, $9F, $81 ;53 + .byte $FF, $C3, $99, $99, $83, $9F, $99, $C3 ;54 + .byte $FF, $E7, $E7, $E7, $E7, $F3, $99, $81 ;55 + .byte $FF, $C3, $99, $99, $C3, $99, $99, $C3 ;56 + .byte $FF, $C3, $99, $F9, $C1, $99, $99, $C3 ;57 + .byte $FF, $FF, $E7, $FF, $FF, $E7, $FF, $FF ;58 + .byte $CF, $E7, $E7, $FF, $FF, $E7, $FF, $FF ;59 + .byte $FF, $F1, $E7, $CF, $9F, $CF, $E7, $F1 ;60 + .byte $FF, $FF, $FF, $81, $FF, $81, $FF, $FF ;61 + .byte $FF, $8F, $E7, $F3, $F9, $F3, $E7, $8F ;62 + .byte $FF, $E7, $FF, $E7, $F3, $F9, $99, $C3 ;63 + + + .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3 ;0 + .byte $FF, $99, $99, $99, $81, $99, $C3, $E7 ;1 + .byte $FF, $83, $99, $99, $83, $99, $99, $83 ;2 + .byte $FF, $C3, $99, $9F, $9F, $9F, $99, $C3 ;3 + .byte $FF, $87, $93, $99, $99, $99, $93, $87 ;4 + .byte $FF, $81, $9F, $9F, $87, $9F, $9F, $81 ;5 + .byte $FF, $9F, $9F, $9F, $87, $9F, $9F, $81 ;6 + .byte $FF, $C3, $99, $99, $91, $9F, $99, $C3 ;7 + .byte $FF, $99, $99, $99, $81, $99, $99, $99 ;8 + .byte $FF, $C3, $E7, $E7, $E7, $E7, $E7, $C3 ;9 + .byte $FF, $C7, $93, $F3, $F3, $F3, $F3, $E1 ;10 + .byte $FF, $99, $93, $87, $8F, $87, $93, $99 ;11 + .byte $FF, $81, $9F, $9F, $9F, $9F, $9F, $9F ;12 + .byte $FF, $9C, $9C, $9C, $94, $80, $88, $9C ;13 + .byte $FF, $99, $99, $91, $81, $81, $89, $99 ;14 + .byte $FF, $C3, $99, $99, $99, $99, $99, $C3 ;15 + .byte $FF, $9F, $9F, $9F, $83, $99, $99, $83 ;16 + .byte $FF, $F1, $C3, $99, $99, $99, $99, $C3 ;17 + .byte $FF, $99, $93, $87, $83, $99, $99, $83 ;18 + .byte $FF, $C3, $99, $F9, $C3, $9F, $99, $C3 ;19 + .byte $FF, $E7, $E7, $E7, $E7, $E7, $E7, $81 ;20 + .byte $FF, $C3, $99, $99, $99, $99, $99, $99 ;21 + .byte $FF, $E7, $C3, $99, $99, $99, $99, $99 ;22 + .byte $FF, $9C, $88, $80, $94, $9C, $9C, $9C ;23 + .byte $FF, $99, $99, $C3, $E7, $C3, $99, $99 ;24 + .byte $FF, $E7, $E7, $E7, $C3, $99, $99, $99 ;25 + .byte $FF, $81, $9F, $CF, $E7, $F3, $F9, $81 ;26 + .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3 ;27 + .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3 ;28 + .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3 ;29 + .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF ;30 + .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF ;31 + + +; gemena + .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3 ;224 + .byte $FF, $C1, $99, $C1, $F9, $C3, $FF, $FF ;225 + .byte $FF, $83, $99, $99, $83, $9F, $9F, $FF ;226 + .byte $FF, $C3, $9F, $9F, $9F, $C3, $FF, $FF ;227 + .byte $FF, $C1, $99, $99, $C1, $F9, $F9, $FF ;228 + .byte $FF, $C3, $9F, $81, $99, $C3, $FF, $FF ;229 + .byte $FF, $E7, $E7, $E7, $C1, $E7, $F1, $FF ;230 + .byte $83, $F9, $C1, $99, $99, $C1, $FF, $FF ;231 + .byte $FF, $99, $99, $99, $83, $9F, $9F, $FF ;232 + .byte $FF, $C3, $E7, $E7, $C7, $FF, $E7, $FF ;233 + .byte $C3, $F9, $F9, $F9, $F9, $FF, $F9, $FF ;234 + .byte $FF, $99, $93, $87, $93, $9F, $9F, $FF ;235 + .byte $FF, $C3, $E7, $E7, $E7, $E7, $C7, $FF ;236 + .byte $FF, $9C, $94, $80, $80, $99, $FF, $FF ;237 + .byte $FF, $99, $99, $99, $99, $83, $FF, $FF ;238 + .byte $FF, $C3, $99, $99, $99, $C3, $FF, $FF ;239 + .byte $9F, $9F, $83, $99, $99, $83, $FF, $FF ;240 + .byte $F9, $F9, $C1, $99, $99, $C1, $FF, $FF ;241 + .byte $FF, $9F, $9F, $9F, $99, $83, $FF, $FF ;242 + .byte $FF, $83, $F9, $C3, $9F, $C1, $FF, $FF ;243 + .byte $FF, $F1, $E7, $E7, $E7, $81, $E7, $FF ;244 + .byte $FF, $C1, $99, $99, $99, $99, $FF, $FF ;245 + .byte $FF, $E7, $C3, $99, $99, $99, $FF, $FF ;246 + .byte $FF, $C9, $C1, $80, $94, $9C, $FF, $FF ;247 + .byte $FF, $99, $C3, $E7, $C3, $99, $FF, $FF ;248 + .byte $87, $F3, $C1, $99, $99, $99, $FF, $FF ;249 + .byte $FF, $81, $CF, $E7, $F3, $81, $FF, $FF ;250 + .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3 ;251 + .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3 ;252 + .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3 ;253 + .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF ;254 + .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF ;255