]> git.sur5r.net Git - cc65/blob - libsrc/lynx/lynx-160-102-16.s
Sqeeze out two bytes of the code.
[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         beq     IRQEND          ; Exit if not a VBL interrupt
470
471         lda     SWAPREQUEST
472         beq     @L0
473         lda     DRAWPAGE
474         jsr     SETVIEWPAGE
475         lda     DRAWPAGE
476         eor     #1
477         sta     DRAWPAGE
478         jsr     SETDRAWPAGE
479         stz     SWAPREQUEST
480 @L0:
481         jsr     VBLHOOK
482 IRQEND:
483         clc
484         rts
485
486 ; ------------------------------------------------------------------------
487 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
488 ; to be in a valid range (0..maxcolor-1).
489 ;
490 ; Must set an error code: NO (will only be called if color ok)
491 ;
492
493 SETCOLOR:
494         sta     DRAWINDEX
495         rts
496
497 ; ------------------------------------------------------------------------
498 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
499 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
500 ; are not supported
501 ;
502 ; Must set an error code: YES
503 ;
504
505 SETPALETTE:
506         ldy     #31
507 @L1:    lda     (ptr1),y
508         sta     GCOLMAP,y   ; $FDA0
509         dey
510         bpl     @L1
511
512 ; Done, reset the error code
513
514         lda     #TGI_ERR_OK
515         sta     ERROR
516         rts
517
518 ; ------------------------------------------------------------------------
519 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
520 ; set the palette should return the default palette here, so there's no
521 ; way for this function to fail.
522 ;
523 ; Must set an error code: NO
524 ;
525
526 GETPALETTE:
527         lda     #<GCOLMAP       ; $FDA0
528         ldx     #>GCOLMAP
529         rts
530
531 ; ------------------------------------------------------------------------
532 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
533 ; drivers should return something reasonable here, even drivers that don't
534 ; support palettes, otherwise the caller has no way to determine the colors
535 ; of the (not changeable) palette.
536 ;
537 ; Must set an error code: NO (all drivers must have a default palette)
538 ;
539
540 GETDEFPALETTE:
541         lda     #<DEFPALETTE
542         ldx     #>DEFPALETTE
543         rts
544
545 ; ------------------------------------------------------------------------
546 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
547 ; color. The coordinates passed to this function are never outside the
548 ; visible screen area, so there is no need for clipping inside this function.
549 ;
550 ; Must set an error code: NO
551 ;
552
553 .data
554 pixel_sprite:
555         .byte   %00000001                       ; A pixel sprite
556         .byte   %00010000
557         .byte   %00100000
558         .addr   0,pixel_bitmap
559 pix_x:  .word   0
560 pix_y:  .word   0
561         .word   $100
562         .word   $100
563 pix_c:  .byte   $00
564
565 .code
566 SETPIXEL:
567         lda     X1
568         sta     pix_x
569         lda     Y1
570         sta     pix_y
571         lda     DRAWINDEX
572         sta     pix_c
573         lda     #<pixel_sprite
574         ldx     #>pixel_sprite
575         jmp     draw_sprite
576
577 ; ------------------------------------------------------------------------
578 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
579 ; coordinates passed to this function are never outside the visible screen
580 ; area, so there is no need for clipping inside this function.
581
582
583 GETPIXEL:
584         lda     Y1
585         sta     MATHD   ; Hardware multiply
586         stz     MATHC
587         lda     #80
588         sta     MATHB
589         stz     MATHA
590         lda     X1
591         lsr     A
592         php
593         tay
594
595         clc
596         lda     VIEWPAGEL
597         adc     MATHH
598         sta     ptr1
599         lda     VIEWPAGEH
600         adc     MATHG
601         sta     ptr1+1
602
603         ldx     #0
604         lda     #15
605         sta     MAPCTL
606         lda     (ptr1),y
607         tay
608         lda     #$0c
609         sta     MAPCTL
610         tya
611         plp
612         bcc     @L1
613         and     #$f
614         rts
615
616 @L1:    lsr     A
617         lsr     A
618         lsr     A
619         lsr     A
620         rts
621
622 ; ------------------------------------------------------------------------
623 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
624 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
625 ;
626 ; Must set an error code: NO
627 ;
628
629 .data
630 line_sprite:
631         .byte   0               ; Will be replaced by the code
632         .byte   %00110000
633         .byte   %00100000
634         .word   0,pixel_bitmap
635 line_x:
636         .word    0
637 line_y:
638         .word    0
639 line_sx:
640         .word    $100
641 line_sy:
642         .word    $100
643         .word    0
644 line_tilt:
645         .word    0
646 line_c:
647         .byte    $e
648
649 .code
650 LINE:
651         lda     DRAWINDEX
652         sta     line_c
653         stz     line_sx
654         stz     line_sy
655
656         sec
657         lda     X2
658         sbc     X1
659         lda     X2+1
660         sbc     X1+1
661         bpl     @L1
662         lda     X1
663         ldx     X2
664         sta     X2
665         stx     X1
666         lda     X1+1
667         ldx     X2+1
668         sta     X2+1
669         stx     X1+1
670         lda     Y1
671         ldx     Y2
672         sta     Y2
673         stx     Y1
674         lda     Y1+1
675         ldx     Y2+1
676         sta     Y2+1
677         stx     Y1+1
678 @L1:
679         lda     #%00000000      ; Not flipped
680         sta     line_sprite
681
682         sec
683         lda     Y2
684         sbc     Y1
685         sta     Y2
686         lda     Y2+1
687         sbc     Y1+1
688         sta     Y2+1
689         bpl     @L2
690         sec
691         lda     #0
692         sbc     Y2
693         sta     Y2
694         lda     #0
695         sbc     Y2+1
696         sta     Y2+1
697         lda     #%00010000      ; Vertical flip
698         sta     line_sprite
699 @L2:
700         lda     X1
701         sta     line_x
702         lda     X1+1
703         sta     line_x+1
704         lda     Y1
705         sta     line_y
706         lda     Y1+1
707         sta     line_y+1
708
709         lda     Y2
710         ina
711         sta     line_sy+1
712         sta     MATHP           ; hardware divide
713         stz     MATHN
714
715         stz     MATHH
716         stz     MATHG
717         sec
718         lda     X2
719         sbc     X1
720         ina
721         sta     MATHF
722         stz     MATHE
723 @L3:
724         lda     SPRSYS
725         bmi     @L3             ; wait for math done (bit 7 of sprsys)
726         lda     MATHC
727         sta     line_tilt
728         lda     MATHB
729         sta     line_tilt+1
730         bne     @L4
731         lda     #1
732         sta     line_sx+1
733         bra     @L6
734 @L4:
735         bit     line_tilt
736         bpl     @L5
737         ina
738 @L5:
739         sta     line_sx+1
740 @L6:
741         lda     #<line_sprite
742         ldx     #>line_sprite
743         jmp     draw_sprite
744
745 ; ------------------------------------------------------------------------
746 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
747 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
748 ; Contrary to most other functions, the graphics kernel will sort and clip
749 ; the coordinates before calling the driver, so on entry the following
750 ; conditions are valid:
751 ;       X1 <= X2
752 ;       Y1 <= Y2
753 ;       (X1 >= 0) && (X1 < XRES)
754 ;       (X2 >= 0) && (X2 < XRES)
755 ;       (Y1 >= 0) && (Y1 < YRES)
756 ;       (Y2 >= 0) && (Y2 < YRES)
757 ;
758 ; Must set an error code: NO
759 ;
760
761 .data
762 bar_sprite:
763         .byte   %00000001                       ; A pixel sprite
764         .byte   %00010000
765         .byte   %00100000
766         .addr   0,pixel_bitmap
767 bar_x:  .word   0
768 bar_y:  .word   0
769 bar_sx: .word   $0100
770 bar_sy: .word   $0100
771 bar_c:  .byte   $00
772
773 .code
774 BAR:    lda     X1
775         sta     bar_x
776         lda     Y1
777         sta     bar_y
778         lda     X2
779         sec
780         sbc     X1
781         ina
782         sta     bar_sx+1
783         lda     Y2
784         sec
785         sbc     Y1
786         ina
787         sta     bar_sy+1
788         lda     DRAWINDEX
789         sta     bar_c
790         lda     #<bar_sprite
791         ldx     #>bar_sprite
792         jmp     draw_sprite
793
794 ; ------------------------------------------------------------------------
795 ; CIRCLE: Draw a circle around the center X1/Y1 (= ptr1/ptr2) with the
796 ; radius in tmp1 and the current drawing color.
797 ;
798 ; Must set an error code: NO
799 ;
800 ; There is no sensible way of drawing a circle on a Lynx. As I would
801 ; have to use line elements to do the circle I rather do it in C than
802 ; create it here in the driver.
803
804 ; To do a circle please add this to your C program
805
806 ;int sintbl[9] = {
807 ;       0,     //  0    degrees
808 ;       3196,  // 11.25 degrees
809 ;       6270,  // 22.5  degrees
810 ;       9102,  // 33.75 degrees
811 ;       11585, // 45    degrees
812 ;       13623, // 56.25 degrees
813 ;       15137, // 67.5  degrees
814 ;       16069, // 78.75 degrees
815 ;       16384  // 90    degrees
816 ;};
817
818 ;int sin(char d)
819 ;{
820 ;    char neg;
821 ;    d = d & 31;
822 ;    neg = d > 16;
823 ;    d = d & 15;
824 ;    if (d > 8)
825 ;        d = 16 - d;
826 ;    if (neg)
827 ;       return -sintbl[d];
828 ;    else
829 ;       return sintbl[d];
830 ;}
831
832 ;void tgi_Circle(int x0, int y0, unsigned char r)
833 ;{
834 ;       char i;
835 ;       int x1, y1, x2, y2;
836 ;
837 ;       x1 = ((long)sin(0) * r + 8192) / 16384 + x0;
838 ;       y1 = ((long)sin(8) * r + 8192) / 16384 + y0;
839 ;       for (i = 1; i <= 32; i++) {
840 ;               x2 = ((long)sin(i) * r + 8192) / 16384 + x0;
841 ;               y2 = ((long)sin(i+8) * r + 8192) / 16384 + y0;
842 ;               tgi_line(x1, y1, x2, y2);
843 ;               x1 = x2;
844 ;               y1 = y2;
845 ;       }
846 ;}
847
848 ;#define tgi_circle tgi_Circle
849
850 CIRCLE:
851         rts
852
853 ; ------------------------------------------------------------------------
854 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
855 ; direction is passend in X/Y, the text direction is passed in A.
856 ;
857 ; Must set an error code: NO
858 ;
859
860 TEXTSTYLE:
861         stx     TEXTMAGX
862         sty     TEXTMAGY
863         sta     TEXTDIR
864         rts
865
866 ; ------------------------------------------------------------------------
867 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
868 ; current text style. The text to output is given as a zero terminated
869 ; string with address in ptr3.
870 ;
871 ; Must set an error code: NO
872 ;
873
874 OUTTEXT:
875         lda     TEXTMAGX        ; Scale sprite
876         sta     text_sx+1
877         lda     TEXTMAGY
878         sta     text_sy+1
879
880         stz     text_sprite     ; Set normal sprite
881         lda     BGINDEX
882         bne     @L1
883         lda     #4
884         sta     text_sprite     ; Set opaque sprite
885 @L1:
886         lda     DRAWINDEX       ; Set color
887         asl
888         asl
889         asl
890         asl
891         ora     BGINDEX
892         sta     text_c
893
894         lda     X1              ; Set start position
895         sta     text_x
896         lda     X1+1
897         sta     text_x+1
898         lda     Y1
899         sta     text_y
900         lda     Y1+1
901         sta     text_y+1
902
903         ldy     #-1             ; Calculate string length
904 @L2:
905         iny
906         lda     (STRPTR),y
907         bne     @L2
908         cpy     #20
909         bmi     @L3
910         ldy     #20
911 @L3:
912         sty     STRLEN
913         bne     @L4
914         rts                     ; Zero length string
915 @L4:
916         iny                     ; Prepare text_bitmap
917         iny
918         sty     STROFF
919
920         ldy     #8-1            ; 8 pixel lines per character
921         ldx     #0
922         clc
923 @L5:
924         lda     STROFF
925         sta     text_bitmap,x
926         txa
927         adc     STROFF
928         tax
929         lda     #$ff
930         sta     text_bitmap-1,x
931         dey
932         bpl     @L5
933         stz     text_bitmap,x
934
935         stz     tmp2
936         iny
937 @L6:
938         lda     (STRPTR),y
939         sty     tmp1
940
941         sec                     ; (ch-' ') * 8
942         sbc     #32
943         stz     FONTOFF
944         stz     FONTOFF+1
945         asl
946         asl
947         rol     FONTOFF+1
948         asl
949         rol     FONTOFF+1
950         clc                     ; Choose font
951         adc     #<font
952         sta     FONTOFF
953         lda     FONTOFF+1
954         adc     #>font
955         sta     FONTOFF+1
956
957 ; and now copy the 8 bytes of that char
958
959         ldx     tmp2
960         inx
961         stx     tmp2
962
963 ; draw char from top to bottom, reading char-data from offset 8-1 to offset 0
964         ldy     #8-1
965 @L7:
966         lda     (FONTOFF),y         ; *chptr
967         sta     text_bitmap,x    ;textbuf[y*(1+len+1)+1+x]
968
969         txa
970         adc     STROFF
971         tax
972
973         dey
974         bpl     @L7
975
976         ; goto next char
977         ldy     tmp1
978         iny
979         dec     STRLEN
980         bne     @L6
981
982         lda     #<text_sprite
983         ldx     #>text_sprite
984         jmp     draw_sprite
985
986 .data
987 text_sprite:
988         .byte $00,$90,$20
989         .addr 0, text_bitmap
990 text_x:
991         .word 0
992 text_y:
993         .word 0
994 text_sx:
995         .word $100
996 text_sy:
997         .word $100
998 text_c:
999         .byte 0
1000
1001 .rodata
1002 ; The Font
1003 ; 96 characters from ASCII 32 to 127
1004 ; 8 pixels wide, 8 pixels high
1005 ; bit value 0 = foreground, bit value 1 = background / transparent
1006 font:
1007 ; VERSAIL
1008         .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF  ;32
1009         .byte $FF, $E7, $FF, $FF, $E7, $E7, $E7, $E7  ;33
1010         .byte $FF, $FF, $FF, $FF, $FF, $99, $99, $99  ;34
1011         .byte $FF, $99, $99, $00, $99, $00, $99, $99  ;35
1012         .byte $FF, $E7, $83, $F9, $C3, $9F, $C1, $E7  ;36
1013         .byte $FF, $B9, $99, $CF, $E7, $F3, $99, $9D  ;37
1014         .byte $FF, $C0, $99, $98, $C7, $C3, $99, $C3  ;38
1015         .byte $FF, $FF, $FF, $FF, $FF, $E7, $F3, $F9  ;39
1016         .byte $FF, $F3, $E7, $CF, $CF, $CF, $E7, $F3  ;40
1017         .byte $FF, $CF, $E7, $F3, $F3, $F3, $E7, $CF  ;41
1018         .byte $FF, $FF, $99, $C3, $00, $C3, $99, $FF  ;42
1019         .byte $FF, $FF, $E7, $E7, $81, $E7, $E7, $FF  ;43
1020         .byte $CF, $E7, $E7, $FF, $FF, $FF, $FF, $FF  ;44
1021         .byte $FF, $FF, $FF, $FF, $81, $FF, $FF, $FF  ;45
1022         .byte $FF, $E7, $E7, $FF, $FF, $FF, $FF, $FF  ;46
1023         .byte $FF, $9F, $CF, $E7, $F3, $F9, $FC, $FF  ;47
1024         .byte $FF, $C3, $99, $99, $89, $91, $99, $C3  ;48
1025         .byte $FF, $81, $E7, $E7, $E7, $C7, $E7, $E7  ;49
1026         .byte $FF, $81, $9F, $CF, $F3, $F9, $99, $C3  ;50
1027         .byte $FF, $C3, $99, $F9, $E3, $F9, $99, $C3  ;51
1028         .byte $FF, $F9, $F9, $80, $99, $E1, $F1, $F9  ;52
1029         .byte $FF, $C3, $99, $F9, $F9, $83, $9F, $81  ;53
1030         .byte $FF, $C3, $99, $99, $83, $9F, $99, $C3  ;54
1031         .byte $FF, $E7, $E7, $E7, $E7, $F3, $99, $81  ;55
1032         .byte $FF, $C3, $99, $99, $C3, $99, $99, $C3  ;56
1033         .byte $FF, $C3, $99, $F9, $C1, $99, $99, $C3  ;57
1034         .byte $FF, $FF, $E7, $FF, $FF, $E7, $FF, $FF  ;58
1035         .byte $CF, $E7, $E7, $FF, $FF, $E7, $FF, $FF  ;59
1036         .byte $FF, $F1, $E7, $CF, $9F, $CF, $E7, $F1  ;60
1037         .byte $FF, $FF, $FF, $81, $FF, $81, $FF, $FF  ;61
1038         .byte $FF, $8F, $E7, $F3, $F9, $F3, $E7, $8F  ;62
1039         .byte $FF, $E7, $FF, $E7, $F3, $F9, $99, $C3  ;63
1040
1041
1042         .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3  ;0
1043         .byte $FF, $99, $99, $99, $81, $99, $C3, $E7  ;1
1044         .byte $FF, $83, $99, $99, $83, $99, $99, $83  ;2
1045         .byte $FF, $C3, $99, $9F, $9F, $9F, $99, $C3  ;3
1046         .byte $FF, $87, $93, $99, $99, $99, $93, $87  ;4
1047         .byte $FF, $81, $9F, $9F, $87, $9F, $9F, $81  ;5
1048         .byte $FF, $9F, $9F, $9F, $87, $9F, $9F, $81  ;6
1049         .byte $FF, $C3, $99, $99, $91, $9F, $99, $C3  ;7
1050         .byte $FF, $99, $99, $99, $81, $99, $99, $99  ;8
1051         .byte $FF, $C3, $E7, $E7, $E7, $E7, $E7, $C3  ;9
1052         .byte $FF, $C7, $93, $F3, $F3, $F3, $F3, $E1  ;10
1053         .byte $FF, $99, $93, $87, $8F, $87, $93, $99  ;11
1054         .byte $FF, $81, $9F, $9F, $9F, $9F, $9F, $9F  ;12
1055         .byte $FF, $9C, $9C, $9C, $94, $80, $88, $9C  ;13
1056         .byte $FF, $99, $99, $91, $81, $81, $89, $99  ;14
1057         .byte $FF, $C3, $99, $99, $99, $99, $99, $C3  ;15
1058         .byte $FF, $9F, $9F, $9F, $83, $99, $99, $83  ;16
1059         .byte $FF, $F1, $C3, $99, $99, $99, $99, $C3  ;17
1060         .byte $FF, $99, $93, $87, $83, $99, $99, $83  ;18
1061         .byte $FF, $C3, $99, $F9, $C3, $9F, $99, $C3  ;19
1062         .byte $FF, $E7, $E7, $E7, $E7, $E7, $E7, $81  ;20
1063         .byte $FF, $C3, $99, $99, $99, $99, $99, $99  ;21
1064         .byte $FF, $E7, $C3, $99, $99, $99, $99, $99  ;22
1065         .byte $FF, $9C, $88, $80, $94, $9C, $9C, $9C  ;23
1066         .byte $FF, $99, $99, $C3, $E7, $C3, $99, $99  ;24
1067         .byte $FF, $E7, $E7, $E7, $C3, $99, $99, $99  ;25
1068         .byte $FF, $81, $9F, $CF, $E7, $F3, $F9, $81  ;26
1069         .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3  ;27
1070         .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3  ;28
1071         .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3  ;29
1072         .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF  ;30
1073         .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF  ;31
1074
1075
1076 ; gemena
1077         .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3  ;224
1078         .byte $FF, $C1, $99, $C1, $F9, $C3, $FF, $FF  ;225
1079         .byte $FF, $83, $99, $99, $83, $9F, $9F, $FF  ;226
1080         .byte $FF, $C3, $9F, $9F, $9F, $C3, $FF, $FF  ;227
1081         .byte $FF, $C1, $99, $99, $C1, $F9, $F9, $FF  ;228
1082         .byte $FF, $C3, $9F, $81, $99, $C3, $FF, $FF  ;229
1083         .byte $FF, $E7, $E7, $E7, $C1, $E7, $F1, $FF  ;230
1084         .byte $83, $F9, $C1, $99, $99, $C1, $FF, $FF  ;231
1085         .byte $FF, $99, $99, $99, $83, $9F, $9F, $FF  ;232
1086         .byte $FF, $C3, $E7, $E7, $C7, $FF, $E7, $FF  ;233
1087         .byte $C3, $F9, $F9, $F9, $F9, $FF, $F9, $FF  ;234
1088         .byte $FF, $99, $93, $87, $93, $9F, $9F, $FF  ;235
1089         .byte $FF, $C3, $E7, $E7, $E7, $E7, $C7, $FF  ;236
1090         .byte $FF, $9C, $94, $80, $80, $99, $FF, $FF  ;237
1091         .byte $FF, $99, $99, $99, $99, $83, $FF, $FF  ;238
1092         .byte $FF, $C3, $99, $99, $99, $C3, $FF, $FF  ;239
1093         .byte $9F, $9F, $83, $99, $99, $83, $FF, $FF  ;240
1094         .byte $F9, $F9, $C1, $99, $99, $C1, $FF, $FF  ;241
1095         .byte $FF, $9F, $9F, $9F, $99, $83, $FF, $FF  ;242
1096         .byte $FF, $83, $F9, $C3, $9F, $C1, $FF, $FF  ;243
1097         .byte $FF, $F1, $E7, $E7, $E7, $81, $E7, $FF  ;244
1098         .byte $FF, $C1, $99, $99, $99, $99, $FF, $FF  ;245
1099         .byte $FF, $E7, $C3, $99, $99, $99, $FF, $FF  ;246
1100         .byte $FF, $C9, $C1, $80, $94, $9C, $FF, $FF  ;247
1101         .byte $FF, $99, $C3, $E7, $C3, $99, $FF, $FF  ;248
1102         .byte $87, $F3, $C1, $99, $99, $99, $FF, $FF  ;249
1103         .byte $FF, $81, $CF, $E7, $F3, $81, $FF, $FF  ;250
1104         .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3  ;251
1105         .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3  ;252
1106         .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3  ;253
1107         .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF  ;254
1108         .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF  ;255