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