]> git.sur5r.net Git - cc65/blob - libsrc/lynx/lynx-160-102-16.s
Re-added cbm_dir which was acidently removed.
[cc65] / libsrc / lynx / lynx-160-102-16.s
1 ;
2 ; Graphics driver for the 160x102x16 mode on the Lynx.
3 ;
4 ; All the drawing functions are simply done by sprites as the sprite
5 ; engine is the only way to do fast graphics on a Lynx.
6 ;
7 ; So the code is not really based on any algorithms done by somebody.
8 ; I have looked at other routines in the cc65 libs to see what kind of
9 ; entry points we need. And I have looked at the old cc65 libs by
10 ; Bastian Schick to see how things worked in the past.
11 ;
12 ; This code is written by Karri Kaksonen, 2004 for the cc65 compiler.
13 ;
14
15         .include        "zeropage.inc"
16         .include        "extzp.inc"
17
18         .include        "tgi-kernel.inc"
19         .include        "tgi-mode.inc"
20         .include        "tgi-error.inc"
21
22         .include        "lynx.inc"
23
24         .macpack        generic
25
26 ; ------------------------------------------------------------------------
27 ; Header. Includes jump table and constants.
28
29 .segment        "JUMPTABLE"
30
31 ; First part of the header is a structure that has a magic and defines the
32 ; capabilities of the driver
33
34         .byte   $74, $67, $69           ; "tgi"
35         .byte   TGI_API_VERSION         ; TGI API version number
36         .word   160                     ; X resolution
37         .word   102                     ; Y resolution
38         .byte   16                      ; Number of drawing colors
39         .byte   2                       ; Number of screens available
40         .byte   8                       ; System font X size
41         .byte   8                       ; System font Y size
42         .res    4, $00                  ; Reserved for future extensions
43
44 ; Next comes the jump table. Currently all entries must be valid and may point
45 ; to an RTS for test versions (function not implemented). A future version may
46 ; allow for emulation: In this case the vector will be zero. Emulation means
47 ; that the graphics kernel will emulate the function by using lower level
48 ; primitives - for example ploting a line by using calls to SETPIXEL.
49
50         .addr   INSTALL
51         .addr   UNINSTALL
52         .addr   INIT
53         .addr   DONE
54         .addr   GETERROR
55         .addr   CONTROL
56         .addr   CLEAR
57         .addr   SETVIEWPAGE
58         .addr   SETDRAWPAGE
59         .addr   SETCOLOR
60         .addr   SETPALETTE
61         .addr   GETPALETTE
62         .addr   GETDEFPALETTE
63         .addr   SETPIXEL
64         .addr   GETPIXEL
65         .addr   LINE
66         .addr   BAR
67         .addr   CIRCLE
68         .addr   TEXTSTYLE
69         .addr   OUTTEXT
70         .addr   0                       ; IRQ entry is unused
71
72
73 ; ------------------------------------------------------------------------
74 ; Data.
75
76 ; Variables mapped to the zero page segment variables. Some of these are
77 ; used for passing parameters to the driver.
78
79 X1              := ptr1
80 Y1              := ptr2
81 X2              := ptr3
82 Y2              := ptr4
83
84 STRPTR          := ptr3
85 FONTOFF         := ptr4
86 STROFF          := tmp3
87 STRLEN          := tmp4
88
89 ; Absolute variables used in the code
90
91 .bss
92
93 ERROR:          .res    1       ; Error code
94
95 DRAWINDEX:      .res    1       ; Pen to use for drawing
96 VIEWPAGEL:      .res    1
97 VIEWPAGEH:      .res    1
98 DRAWPAGEL:      .res    1
99 DRAWPAGEH:      .res    1
100
101 ; Text output stuff
102 TEXTMAGX:       .res    1
103 TEXTMAGY:       .res    1
104 TEXTDIR:        .res    1
105 BGINDEX:        .res    1       ; Pen to use for text background
106
107 text_bitmap:    .res    8*(1+20+1)+1
108 ; 8 rows with (one offset-byte plus 20 character bytes plus one fill-byte) plus one 0-offset-byte
109
110 ; Constants and tables
111
112 .rodata
113
114 DEFPALETTE:     .byte   >$000
115                 .byte   >$007
116                 .byte   >$070
117                 .byte   >$700
118                 .byte   >$077
119                 .byte   >$770
120                 .byte   >$707
121                 .byte   >$777
122                 .byte   >$333
123                 .byte   >$00F
124                 .byte   >$0F0
125                 .byte   >$F00
126                 .byte   >$0FF
127                 .byte   >$FF0
128                 .byte   >$F0F
129                 .byte   >$FFF
130                 .byte   <$000
131                 .byte   <$007
132                 .byte   <$070
133                 .byte   <$700
134                 .byte   <$077
135                 .byte   <$770
136                 .byte   <$707
137                 .byte   <$777
138                 .byte   <$333
139                 .byte   <$00F
140                 .byte   <$0F0
141                 .byte   <$F00
142                 .byte   <$0FF
143                 .byte   <$FF0
144                 .byte   <$F0F
145                 .byte   <$FFF
146
147 PALETTESIZE     = * - DEFPALETTE
148
149 .code
150
151 ; ------------------------------------------------------------------------
152 ; INSTALL routine. Is called after the driver is loaded into memory. May
153 ; initialize anything that has to be done just once. Is probably empty
154 ; most of the time.
155 ;
156 ; Must set an error code: NO
157 ;
158
159 INSTALL:
160         lda     #1
161         sta     TEXTMAGX
162         sta     TEXTMAGY
163         stz     BGINDEX
164         rts
165
166
167 ; ------------------------------------------------------------------------
168 ; UNINSTALL routine. Is called before the driver is removed from memory. May
169 ; clean up anything done by INSTALL but is probably empty most of the time.
170 ;
171 ; Must set an error code: NO
172 ;
173
174 UNINSTALL:
175         rts
176
177
178 ; ------------------------------------------------------------------------
179 ; INIT: Changes an already installed device from text mode to graphics
180 ; mode.
181 ; Note that INIT/DONE may be called multiple times while the driver
182 ; is loaded, while INSTALL is only called once, so any code that is needed
183 ; to initializes variables and so on must go here. Setting palette and
184 ; clearing the screen is not needed because this is called by the graphics
185 ; kernel later.
186 ; The graphics kernel will never call INIT when a graphics mode is already
187 ; active, so there is no need to protect against that.
188 ;
189 ; Must set an error code: YES
190 ;
191
192 INIT:
193 ; Done, reset the error code
194         lda     #TGI_ERR_OK
195         sta     ERROR
196         rts
197
198 ; ------------------------------------------------------------------------
199 ; DONE: Will be called to switch the graphics device back into text mode.
200 ; The graphics kernel will never call DONE when no graphics mode is active,
201 ; so there is no need to protect against that.
202 ;
203 ; Must set an error code: NO
204 ;
205
206 DONE:
207         rts
208
209 ; ------------------------------------------------------------------------
210 ; GETERROR: Return the error code in A and clear it.
211
212 GETERROR:
213         ldx     #TGI_ERR_OK
214         lda     ERROR
215         stx     ERROR
216         rts
217
218 ; ------------------------------------------------------------------------
219 ; CONTROL: Platform/driver specific entry point.
220 ;
221 ; Must set an error code: YES
222 ;
223 ; The TGI lacks a way to draw sprites. As that functionality is vital to
224 ; Lynx games we borrow this CONTROL function to implement the still
225 ; missing tgi_draw_sprite funtion. To use this in your C-program
226 ; do a #define tgi_draw_sprite(spr) tgi_ioctl(0, spr)
227 ;
228 ; To do a flip-screen call tgi_ioctl(1, 0)
229 ;
230 ; To set the background index for text outputs call tgi_ioctl(2, bgindex)
231
232 CONTROL:
233         cmp     #2
234         bne     @L0
235         lda     ptr1
236         sta     BGINDEX
237         lda     #TGI_ERR_OK
238         sta     ERROR
239         rts
240 @L0:
241         cmp     #1
242         bne     @L2
243         lda     __sprsys
244         eor     #8
245         sta     __sprsys
246         sta     SPRSYS
247
248         lda     __viddma
249         eor     #2
250         sta     __viddma
251         sta     DISPCTL
252         ldy     VIEWPAGEL
253         ldx     VIEWPAGEH
254         and     #2
255         beq     @L1
256         clc
257         tya
258         adc     #<8159
259         tay
260         txa
261         adc     #>8159
262         tax
263 @L1:
264         sty     DISPADRL
265         stx     DISPADRH
266         lda     #TGI_ERR_OK
267         sta     ERROR
268         rts
269 @L2:
270         lda     ptr1            ; Get the sprite address
271         ldx     ptr1+1
272
273 draw_sprite:                    ; Draw it in render buffer
274         sta     SCBNEXTL
275         stx     SCBNEXTH
276         lda     DRAWPAGEL
277         ldx     DRAWPAGEH
278         sta     VIDBASL
279         stx     VIDBASH
280         lda     #1
281         sta     SPRGO
282         stz     SDONEACK
283 @L3:    stz     CPUSLEEP
284         lda     SPRSYS
285         lsr
286         bcs     @L3
287         stz     SDONEACK
288         lda     #TGI_ERR_OK
289         sta     ERROR
290         rts
291
292 ; ------------------------------------------------------------------------
293 ; CLEAR: Clears the screen.
294 ;
295 ; Must set an error code: NO
296 ;
297
298 .rodata
299 pixel_bitmap:
300         .byte   3,%10000100,%00000000, $0       ; A pixel bitmap
301 cls_sprite:
302         .byte   %00000001                       ; A pixel sprite
303         .byte   %00010000
304         .byte   %00100000
305         .addr   0,pixel_bitmap
306         .word   0
307         .word   0
308         .word   $a000                           ; 160
309         .word   $6600                           ; 102
310         .byte   $00
311
312 .code
313 CLEAR:  lda     #<cls_sprite
314         ldx     #>cls_sprite
315         bra     draw_sprite
316
317 ; ------------------------------------------------------------------------
318 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
319 ; The page number is already checked to be valid by the graphics kernel.
320 ;
321 ; Must set an error code: NO (will only be called if page ok)
322 ;
323 ; It is a good idea to call this function during the vertical blanking
324 ; period. If you call it in the middle of the screen update then half of
325 ; the drawn frame will be from the old buffer and the other half is
326 ; from the new buffer. This is usually noticed by the user.
327
328 SETVIEWPAGE:
329         cmp     #1
330         beq     @L1             ; page == maxpages-1
331         ldy     #<$de20         ; page 0
332         ldx     #>$de20
333         bra     @L2
334 @L1:
335         ldy     #<$be40         ; page 1
336         ldx     #>$be40
337 @L2:
338         sty     VIEWPAGEL       ; Save viewpage for getpixel
339         stx     VIEWPAGEH
340
341         lda     __viddma        ; Process flipped displays
342         and     #2
343         beq     @L3
344         clc
345         tya
346         adc     #<8159
347         tay
348         txa
349         adc     #>8159
350         tax
351 @L3:
352         sty     DISPADRL        ; $FD94
353         stx     DISPADRH        ; $FD95
354         rts
355
356 ; ------------------------------------------------------------------------
357 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
358 ; The page number is already checked to be valid by the graphics kernel.
359 ;
360 ; Must set an error code: NO (will only be called if page ok)
361 ;
362
363 SETDRAWPAGE:
364         cmp     #1
365         beq     @L1                 ; page == maxpages-1
366         lda     #<$de20             ; page 0
367         ldx     #>$de20
368         bra     @L2
369 @L1:
370         lda     #<$be40             ; page 1
371         ldx     #>$be40
372 @L2:
373         sta     DRAWPAGEL
374         stx     DRAWPAGEH
375         rts
376
377 ; ------------------------------------------------------------------------
378 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
379 ; to be in a valid range (0..maxcolor-1).
380 ;
381 ; Must set an error code: NO (will only be called if color ok)
382 ;
383
384 SETCOLOR:
385         sta     DRAWINDEX
386         rts
387
388 ; ------------------------------------------------------------------------
389 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
390 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
391 ; are not supported
392 ;
393 ; Must set an error code: YES
394 ;
395
396 SETPALETTE:
397         ldy     #31
398 @L1:    lda     (ptr1),y
399         sta     GCOLMAP,y   ; $FDA0
400         dey
401         bpl     @L1
402
403 ; Done, reset the error code
404
405         lda     #TGI_ERR_OK
406         sta     ERROR
407         rts
408
409 ; ------------------------------------------------------------------------
410 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
411 ; set the palette should return the default palette here, so there's no
412 ; way for this function to fail.
413 ;
414 ; Must set an error code: NO
415 ;
416
417 GETPALETTE:
418         lda     #<GCOLMAP       ; $FDA0
419         ldx     #>GCOLMAP
420         rts
421
422 ; ------------------------------------------------------------------------
423 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
424 ; drivers should return something reasonable here, even drivers that don't
425 ; support palettes, otherwise the caller has no way to determine the colors
426 ; of the (not changeable) palette.
427 ;
428 ; Must set an error code: NO (all drivers must have a default palette)
429 ;
430
431 GETDEFPALETTE:
432         lda     #<DEFPALETTE
433         ldx     #>DEFPALETTE
434         rts
435
436 ; ------------------------------------------------------------------------
437 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
438 ; color. The coordinates passed to this function are never outside the
439 ; visible screen area, so there is no need for clipping inside this function.
440 ;
441 ; Must set an error code: NO
442 ;
443
444 .data
445 pixel_sprite:
446         .byte   %00000001                       ; A pixel sprite
447         .byte   %00010000
448         .byte   %00100000
449         .addr   0,pixel_bitmap
450 pix_x:  .word   0
451 pix_y:  .word   0
452         .word   $100
453         .word   $100
454 pix_c:  .byte   $00
455
456 .code
457 SETPIXEL:
458         lda     X1
459         sta     pix_x
460         lda     Y1
461         sta     pix_y
462         lda     DRAWINDEX
463         sta     pix_c
464         lda     #<pixel_sprite
465         ldx     #>pixel_sprite
466         jmp     draw_sprite
467
468 ; ------------------------------------------------------------------------
469 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
470 ; coordinates passed to this function are never outside the visible screen
471 ; area, so there is no need for clipping inside this function.
472
473
474 GETPIXEL:
475         lda     Y1
476         sta     MATHD   ; Hardware multiply
477         stz     MATHC
478         lda     #80
479         sta     MATHB
480         stz     MATHA
481         lda     X1
482         lsr     A
483         php
484         tay
485
486         clc
487         lda     VIEWPAGEL
488         adc     MATHH
489         sta     ptr1
490         lda     VIEWPAGEH
491         adc     MATHG
492         sta     ptr1+1
493
494         ldx     #0
495         lda     #15
496         sta     MAPCTL
497         lda     (ptr1),y
498         tay
499         lda     #$0c
500         sta     MAPCTL
501         tya
502         plp
503         bcc     @L1
504         and     #$f
505         rts
506
507 @L1:    lsr     A
508         lsr     A
509         lsr     A
510         lsr     A
511         rts
512
513 ; ------------------------------------------------------------------------
514 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
515 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
516 ;
517 ; Must set an error code: NO
518 ;
519
520 .data
521 line_sprite:
522         .byte   0               ; Will be replaced by the code
523         .byte   %00110000
524         .byte   %00100000
525         .word   0,pixel_bitmap
526 line_x:
527         .word    0
528 line_y:
529         .word    0
530 line_sx:
531         .word    $100
532 line_sy:
533         .word    $100
534         .word    0
535 line_tilt:
536         .word    0
537 line_c:
538         .byte    $e
539
540 .code
541 LINE:
542         lda     DRAWINDEX
543         sta     line_c
544         stz     line_sx
545         stz     line_sy
546
547         sec
548         lda     X2
549         sbc     X1
550         lda     X2+1
551         sbc     X1+1
552         bpl     @L1
553         lda     X1
554         ldx     X2
555         sta     X2
556         stx     X1
557         lda     X1+1
558         ldx     X2+1
559         sta     X2+1
560         stx     X1+1
561         lda     Y1
562         ldx     Y2
563         sta     Y2
564         stx     Y1
565         lda     Y1+1
566         ldx     Y2+1
567         sta     Y2+1
568         stx     Y1+1
569 @L1:
570         lda     #%00000000      ; Not flipped
571         sta     line_sprite
572
573         sec
574         lda     Y2
575         sbc     Y1
576         sta     Y2
577         lda     Y2+1
578         sbc     Y1+1
579         sta     Y2+1
580         bpl     @L2
581         sec
582         lda     #0
583         sbc     Y2
584         sta     Y2
585         lda     #0
586         sbc     Y2+1
587         sta     Y2+1
588         lda     #%00010000      ; Vertical flip
589         sta     line_sprite
590 @L2:
591         lda     X1
592         sta     line_x
593         lda     X1+1
594         sta     line_x+1
595         lda     Y1
596         sta     line_y
597         lda     Y1+1
598         sta     line_y+1
599
600         lda     Y2
601         ina
602         sta     line_sy+1
603         sta     MATHP           ; hardware divide
604         stz     MATHN
605
606         stz     MATHH
607         stz     MATHG
608         sec
609         lda     X2
610         sbc     X1
611         ina
612         sta     MATHF
613         stz     MATHE
614 @L3:
615         lda     SPRSYS
616         bmi     @L3             ; wait for math done (bit 7 of sprsys)
617         lda     MATHC
618         sta     line_tilt
619         lda     MATHB
620         sta     line_tilt+1
621         bne     @L4
622         lda     #1
623         sta     line_sx+1
624         bra     @L6
625 @L4:
626         bit     line_tilt
627         bpl     @L5
628         ina
629 @L5:
630         sta     line_sx+1
631 @L6:
632         lda     #<line_sprite
633         ldx     #>line_sprite
634         jmp     draw_sprite
635
636 ; ------------------------------------------------------------------------
637 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
638 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
639 ; Contrary to most other functions, the graphics kernel will sort and clip
640 ; the coordinates before calling the driver, so on entry the following
641 ; conditions are valid:
642 ;       X1 <= X2
643 ;       Y1 <= Y2
644 ;       (X1 >= 0) && (X1 < XRES)
645 ;       (X2 >= 0) && (X2 < XRES)
646 ;       (Y1 >= 0) && (Y1 < YRES)
647 ;       (Y2 >= 0) && (Y2 < YRES)
648 ;
649 ; Must set an error code: NO
650 ;
651
652 .data
653 bar_sprite:
654         .byte   %00000001                       ; A pixel sprite
655         .byte   %00010000
656         .byte   %00100000
657         .addr   0,pixel_bitmap
658 bar_x:  .word   0
659 bar_y:  .word   0
660 bar_sx: .word   $0100
661 bar_sy: .word   $0100
662 bar_c:  .byte   $00
663
664 .code
665 BAR:    lda     X1
666         sta     bar_x
667         lda     Y1
668         sta     bar_y
669         lda     X2
670         sec
671         sbc     X1
672         ina
673         sta     bar_sx+1
674         lda     Y2
675         sec
676         sbc     Y1
677         ina
678         sta     bar_sy+1
679         lda     DRAWINDEX
680         sta     bar_c
681         lda     #<bar_sprite
682         ldx     #>bar_sprite
683         jmp     draw_sprite
684
685 ; ------------------------------------------------------------------------
686 ; CIRCLE: Draw a circle around the center X1/Y1 (= ptr1/ptr2) with the
687 ; radius in tmp1 and the current drawing color.
688 ;
689 ; Must set an error code: NO
690 ;
691 ; There is no sensible way of drawing a circle on a Lynx. As I would
692 ; have to use line elements to do the circle I rather do it in C than
693 ; create it here in the driver.
694
695 ; To do a circle please add this to your C program
696
697 ;int sintbl[9] = {
698 ;       0,     //  0    degrees
699 ;       3196,  // 11.25 degrees
700 ;       6270,  // 22.5  degrees
701 ;       9102,  // 33.75 degrees
702 ;       11585, // 45    degrees
703 ;       13623, // 56.25 degrees
704 ;       15137, // 67.5  degrees
705 ;       16069, // 78.75 degrees
706 ;       16384  // 90    degrees
707 ;};
708
709 ;int sin(char d)
710 ;{
711 ;    char neg;
712 ;    d = d & 31;
713 ;    neg = d > 16;
714 ;    d = d & 15;
715 ;    if (d > 8)
716 ;        d = 16 - d;
717 ;    if (neg)
718 ;       return -sintbl[d];
719 ;    else
720 ;       return sintbl[d];
721 ;}
722
723 ;void tgi_Circle(int x0, int y0, unsigned char r)
724 ;{
725 ;       char i;
726 ;       int x1, y1, x2, y2;
727 ;
728 ;       x1 = ((long)sin(0) * r + 8192) / 16384 + x0;
729 ;       y1 = ((long)sin(8) * r + 8192) / 16384 + y0;
730 ;       for (i = 1; i <= 32; i++) {
731 ;               x2 = ((long)sin(i) * r + 8192) / 16384 + x0;
732 ;               y2 = ((long)sin(i+8) * r + 8192) / 16384 + y0;
733 ;               tgi_line(x1, y1, x2, y2);
734 ;               x1 = x2;
735 ;               y1 = y2;
736 ;       }
737 ;}
738
739 ;#define tgi_circle tgi_Circle
740
741 CIRCLE:
742         rts
743
744 ; ------------------------------------------------------------------------
745 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
746 ; direction is passend in X/Y, the text direction is passed in A.
747 ;
748 ; Must set an error code: NO
749 ;
750
751 TEXTSTYLE:
752         stx     TEXTMAGX
753         sty     TEXTMAGY
754         sta     TEXTDIR
755         rts
756
757 ; ------------------------------------------------------------------------
758 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
759 ; current text style. The text to output is given as a zero terminated
760 ; string with address in ptr3.
761 ;
762 ; Must set an error code: NO
763 ;
764
765 OUTTEXT:
766         lda     TEXTMAGX        ; Scale sprite
767         sta     text_sx+1
768         lda     TEXTMAGY
769         sta     text_sy+1
770
771         stz     text_sprite     ; Set normal sprite
772         lda     BGINDEX
773         bne     @L1
774         lda     #4
775         sta     text_sprite     ; Set opaque sprite
776 @L1:
777         lda     DRAWINDEX       ; Set color
778         asl
779         asl
780         asl
781         asl
782         ora     BGINDEX
783         sta     text_c
784
785         lda     X1              ; Set start position
786         sta     text_x
787         lda     X1+1
788         sta     text_x+1
789         lda     Y1
790         sta     text_y
791         lda     Y1+1
792         sta     text_y+1
793
794         ldy     #-1             ; Calculate string length
795 @L2:
796         iny
797         lda     (STRPTR),y
798         bne     @L2
799         cpy     #20
800         bmi     @L3
801         ldy     #20
802 @L3:
803         sty     STRLEN
804         bne     @L4
805         rts                     ; Zero length string
806 @L4:
807         iny                     ; Prepare text_bitmap
808         iny
809         sty     STROFF
810
811         ldy     #8-1            ; 8 pixel lines per character
812         ldx     #0
813         clc
814 @L5:
815         lda     STROFF
816         sta     text_bitmap,x
817         txa
818         adc     STROFF
819         tax
820         lda     #$ff
821         sta     text_bitmap-1,x
822         dey
823         bpl     @L5
824         stz     text_bitmap,x
825
826         stz     tmp2
827         iny
828 @L6:
829         lda     (STRPTR),y
830         sty     tmp1
831
832         sec                     ; (ch-' ') * 8
833         sbc     #32
834         stz     FONTOFF
835         stz     FONTOFF+1
836         asl
837         asl
838         rol     FONTOFF+1
839         asl
840         rol     FONTOFF+1
841         clc                     ; Choose font
842         adc     #<font
843         sta     FONTOFF
844         lda     FONTOFF+1
845         adc     #>font
846         sta     FONTOFF+1
847
848 ; and now copy the 8 bytes of that char
849
850         ldx     tmp2
851         inx
852         stx     tmp2
853
854 ; draw char from top to bottom, reading char-data from offset 8-1 to offset 0
855         ldy     #8-1
856 @L7:
857         lda     (FONTOFF),y         ; *chptr
858         sta     text_bitmap,x    ;textbuf[y*(1+len+1)+1+x]
859
860         txa
861         adc     STROFF
862         tax
863
864         dey
865         bpl     @L7
866
867         ; goto next char
868         ldy     tmp1
869         iny
870         dec     STRLEN
871         bne     @L6
872
873         lda     #<text_sprite
874         ldx     #>text_sprite
875         jmp     draw_sprite
876
877 .data
878 text_sprite:
879         .byte $00,$90,$20
880         .addr 0, text_bitmap
881 text_x:
882         .word 0
883 text_y:
884         .word 0
885 text_sx:
886         .word $100
887 text_sy:
888         .word $100
889 text_c:
890         .byte 0
891
892 .rodata
893 ; The Font
894 ; 96 characters from ASCII 32 to 127
895 ; 8 pixels wide, 8 pixels high
896 ; bit value 0 = foreground, bit value 1 = background / transparent 
897 font:
898 ; VERSAIL
899         .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF  ;32
900         .byte $FF, $E7, $FF, $FF, $E7, $E7, $E7, $E7  ;33
901         .byte $FF, $FF, $FF, $FF, $FF, $99, $99, $99  ;34
902         .byte $FF, $99, $99, $00, $99, $00, $99, $99  ;35
903         .byte $FF, $E7, $83, $F9, $C3, $9F, $C1, $E7  ;36
904         .byte $FF, $B9, $99, $CF, $E7, $F3, $99, $9D  ;37
905         .byte $FF, $C0, $99, $98, $C7, $C3, $99, $C3  ;38
906         .byte $FF, $FF, $FF, $FF, $FF, $E7, $F3, $F9  ;39
907         .byte $FF, $F3, $E7, $CF, $CF, $CF, $E7, $F3  ;40
908         .byte $FF, $CF, $E7, $F3, $F3, $F3, $E7, $CF  ;41
909         .byte $FF, $FF, $99, $C3, $00, $C3, $99, $FF  ;42
910         .byte $FF, $FF, $E7, $E7, $81, $E7, $E7, $FF  ;43
911         .byte $CF, $E7, $E7, $FF, $FF, $FF, $FF, $FF  ;44
912         .byte $FF, $FF, $FF, $FF, $81, $FF, $FF, $FF  ;45
913         .byte $FF, $E7, $E7, $FF, $FF, $FF, $FF, $FF  ;46
914         .byte $FF, $9F, $CF, $E7, $F3, $F9, $FC, $FF  ;47
915         .byte $FF, $C3, $99, $99, $89, $91, $99, $C3  ;48
916         .byte $FF, $81, $E7, $E7, $E7, $C7, $E7, $E7  ;49
917         .byte $FF, $81, $9F, $CF, $F3, $F9, $99, $C3  ;50
918         .byte $FF, $C3, $99, $F9, $E3, $F9, $99, $C3  ;51
919         .byte $FF, $F9, $F9, $80, $99, $E1, $F1, $F9  ;52
920         .byte $FF, $C3, $99, $F9, $F9, $83, $9F, $81  ;53
921         .byte $FF, $C3, $99, $99, $83, $9F, $99, $C3  ;54
922         .byte $FF, $E7, $E7, $E7, $E7, $F3, $99, $81  ;55
923         .byte $FF, $C3, $99, $99, $C3, $99, $99, $C3  ;56
924         .byte $FF, $C3, $99, $F9, $C1, $99, $99, $C3  ;57
925         .byte $FF, $FF, $E7, $FF, $FF, $E7, $FF, $FF  ;58
926         .byte $CF, $E7, $E7, $FF, $FF, $E7, $FF, $FF  ;59
927         .byte $FF, $F1, $E7, $CF, $9F, $CF, $E7, $F1  ;60
928         .byte $FF, $FF, $FF, $81, $FF, $81, $FF, $FF  ;61
929         .byte $FF, $8F, $E7, $F3, $F9, $F3, $E7, $8F  ;62
930         .byte $FF, $E7, $FF, $E7, $F3, $F9, $99, $C3  ;63
931
932
933         .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3  ;0
934         .byte $FF, $99, $99, $99, $81, $99, $C3, $E7  ;1
935         .byte $FF, $83, $99, $99, $83, $99, $99, $83  ;2
936         .byte $FF, $C3, $99, $9F, $9F, $9F, $99, $C3  ;3
937         .byte $FF, $87, $93, $99, $99, $99, $93, $87  ;4
938         .byte $FF, $81, $9F, $9F, $87, $9F, $9F, $81  ;5
939         .byte $FF, $9F, $9F, $9F, $87, $9F, $9F, $81  ;6
940         .byte $FF, $C3, $99, $99, $91, $9F, $99, $C3  ;7
941         .byte $FF, $99, $99, $99, $81, $99, $99, $99  ;8
942         .byte $FF, $C3, $E7, $E7, $E7, $E7, $E7, $C3  ;9
943         .byte $FF, $C7, $93, $F3, $F3, $F3, $F3, $E1  ;10
944         .byte $FF, $99, $93, $87, $8F, $87, $93, $99  ;11
945         .byte $FF, $81, $9F, $9F, $9F, $9F, $9F, $9F  ;12
946         .byte $FF, $9C, $9C, $9C, $94, $80, $88, $9C  ;13
947         .byte $FF, $99, $99, $91, $81, $81, $89, $99  ;14
948         .byte $FF, $C3, $99, $99, $99, $99, $99, $C3  ;15
949         .byte $FF, $9F, $9F, $9F, $83, $99, $99, $83  ;16
950         .byte $FF, $F1, $C3, $99, $99, $99, $99, $C3  ;17
951         .byte $FF, $99, $93, $87, $83, $99, $99, $83  ;18
952         .byte $FF, $C3, $99, $F9, $C3, $9F, $99, $C3  ;19
953         .byte $FF, $E7, $E7, $E7, $E7, $E7, $E7, $81  ;20
954         .byte $FF, $C3, $99, $99, $99, $99, $99, $99  ;21
955         .byte $FF, $E7, $C3, $99, $99, $99, $99, $99  ;22
956         .byte $FF, $9C, $88, $80, $94, $9C, $9C, $9C  ;23
957         .byte $FF, $99, $99, $C3, $E7, $C3, $99, $99  ;24
958         .byte $FF, $E7, $E7, $E7, $C3, $99, $99, $99  ;25
959         .byte $FF, $81, $9F, $CF, $E7, $F3, $F9, $81  ;26
960         .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3  ;27
961         .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3  ;28
962         .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3  ;29
963         .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF  ;30
964         .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF  ;31
965
966
967 ; gemena
968         .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3  ;224
969         .byte $FF, $C1, $99, $C1, $F9, $C3, $FF, $FF  ;225
970         .byte $FF, $83, $99, $99, $83, $9F, $9F, $FF  ;226
971         .byte $FF, $C3, $9F, $9F, $9F, $C3, $FF, $FF  ;227
972         .byte $FF, $C1, $99, $99, $C1, $F9, $F9, $FF  ;228
973         .byte $FF, $C3, $9F, $81, $99, $C3, $FF, $FF  ;229
974         .byte $FF, $E7, $E7, $E7, $C1, $E7, $F1, $FF  ;230
975         .byte $83, $F9, $C1, $99, $99, $C1, $FF, $FF  ;231
976         .byte $FF, $99, $99, $99, $83, $9F, $9F, $FF  ;232
977         .byte $FF, $C3, $E7, $E7, $C7, $FF, $E7, $FF  ;233
978         .byte $C3, $F9, $F9, $F9, $F9, $FF, $F9, $FF  ;234
979         .byte $FF, $99, $93, $87, $93, $9F, $9F, $FF  ;235
980         .byte $FF, $C3, $E7, $E7, $E7, $E7, $C7, $FF  ;236
981         .byte $FF, $9C, $94, $80, $80, $99, $FF, $FF  ;237
982         .byte $FF, $99, $99, $99, $99, $83, $FF, $FF  ;238
983         .byte $FF, $C3, $99, $99, $99, $C3, $FF, $FF  ;239
984         .byte $9F, $9F, $83, $99, $99, $83, $FF, $FF  ;240
985         .byte $F9, $F9, $C1, $99, $99, $C1, $FF, $FF  ;241
986         .byte $FF, $9F, $9F, $9F, $99, $83, $FF, $FF  ;242
987         .byte $FF, $83, $F9, $C3, $9F, $C1, $FF, $FF  ;243
988         .byte $FF, $F1, $E7, $E7, $E7, $81, $E7, $FF  ;244
989         .byte $FF, $C1, $99, $99, $99, $99, $FF, $FF  ;245
990         .byte $FF, $E7, $C3, $99, $99, $99, $FF, $FF  ;246
991         .byte $FF, $C9, $C1, $80, $94, $9C, $FF, $FF  ;247
992         .byte $FF, $99, $C3, $E7, $C3, $99, $FF, $FF  ;248
993         .byte $87, $F3, $C1, $99, $99, $99, $FF, $FF  ;249
994         .byte $FF, $81, $CF, $E7, $F3, $81, $FF, $FF  ;250
995         .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3  ;251
996         .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3  ;252
997         .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3  ;253
998         .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF  ;254
999         .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF  ;255