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