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