]> git.sur5r.net Git - cc65/blob - libsrc/atari/atari_tgi_common.inc
879bda51c4cc8043405f2e5b05288b0e3257cdb4
[cc65] / libsrc / atari / atari_tgi_common.inc
1 ;
2 ; Generic Atari graphics driver
3 ;
4
5 ; ******************************************************************************
6
7         ; ----------------------------------------------------------------------
8         ;
9         ; Header. Includes jump table and constants.
10         ;
11         ; ----------------------------------------------------------------------
12
13 .segment        "JUMPTABLE"
14
15 ; Header
16
17         .byte   $74, $67, $69           ; "tgi"
18         .byte   TGI_API_VERSION         ; TGI API version number
19         .word   x_res                   ; X resolution
20         .word   y_res                   ; Y resolution
21         .byte   colors                  ; Number of drawing colors
22         .byte   pages                   ; Number of screens available
23         .byte   8                       ; System font X size
24         .byte   8                       ; System font Y size
25         .word   aspect                  ; Aspect ratio
26
27 ; Function table
28
29         .addr   INSTALL
30         .addr   UNINSTALL
31         .addr   INIT
32         .addr   DONE
33         .addr   GETERROR
34         .addr   CONTROL
35         .addr   CLEAR
36         .addr   SETVIEWPAGE
37         .addr   SETDRAWPAGE
38         .addr   SETCOLOR
39         .addr   SETPALETTE
40         .addr   GETPALETTE
41         .addr   GETDEFPALETTE
42         .addr   SETPIXEL
43         .addr   GETPIXEL
44         .addr   LINE
45         .addr   BAR
46         .addr   TEXTSTYLE
47         .addr   OUTTEXT
48         .addr   0                       ; IRQ entry is unused
49
50 ; ******************************************************************************
51
52         ; ----------------------------------------------------------------------
53         ;
54         ; Parameters
55         ;
56         ; ----------------------------------------------------------------------
57
58         x1      := ptr1
59         y1      := ptr2
60         x2      := ptr3
61         y2      := ptr4
62         radius  := tmp1
63
64 ; ******************************************************************************
65
66         ; ----------------------------------------------------------------------
67         ;
68         ; Global variables
69         ;
70         ; ----------------------------------------------------------------------
71
72         sptr    := regsave + 2
73
74 .bss
75         error:
76                 .res    1       ; Error code
77         .if grmode = 9 || grmode = 11
78         palette = default_palette
79         .else
80         palette:
81                 .res    colors  ; The current palette
82         .endif
83         mask:
84                 .res    1       ; Current pixel mask
85         griocb:
86                 .res    1       ; IOCB channel number for graphics
87
88 .if pages = 2
89         p0scr:
90                 .res    1       ; High byte of screen address for screen page 0
91         p0dls:
92                 .res    1       ; High byte of display list address for screen page 0
93                                 ; Page 1's addresses are 8K higher
94 .endif
95
96 .data
97         mag_x:
98                 .byte   1       ; Horizontal text scaling factor
99         mag_y:
100                 .byte   1       ; Vertical text scaling factor
101         mag_x8:
102                 .word   8       ; Horizontal text scaling factor * 8
103         mag_y8:
104                 .word   8       ; Vertical text scaling factor * 8
105         text_dir:
106                 .byte   0       ; Text direction,
107
108 .code
109
110 ; ******************************************************************************
111
112 .macro  put_pixel
113
114         ; ----------------------------------------------------------------------
115         ;
116         ; Put a pixel at (sptr),y using x as the bit mask offset
117         ;
118         ; ----------------------------------------------------------------------
119
120         lda     (sptr),y
121         eor     mask
122         and     mask_table,x
123         eor     (sptr),y
124         sta     (sptr),y
125 .endmacro
126
127 ; ******************************************************************************
128
129 .rodata
130 screen_device:
131         .byte "S:",$9B          ; Device code for screen
132 screen_device_length := * - screen_device
133
134 .code
135
136 .proc INIT
137
138         ; ----------------------------------------------------------------------
139         ;
140         ; INIT: Switch to graphics mode
141         ;
142         ; ----------------------------------------------------------------------
143
144
145 .code
146         ; Initialize drawing color
147         ldx     #$FF
148         stx     mask
149
150         ; Find a free IOCB
151         clc
152         lda     #$70
153 search: tax
154         ldy     ICHID,x
155         cpy     #$FF
156         beq     found
157         sbc     #$10
158         bcs     search
159
160         ; Out of resources
161 nores:  lda     #TGI_ERR_NO_RES
162         sta     error
163         rts
164
165 found:  ; Check if enough RAM is available
166         lda     #0
167         sub     #<mem_needed
168         tay
169         lda     RAMTOP
170         sbc     #>mem_needed
171         cmp     APPMHI + 1
172         bcc     nores
173         bne     switch
174         cpy     APPMHI
175         bcc     nores
176
177         ; Switch into graphics mode
178 switch: lda     #OPEN
179         sta     ICCOM,x
180         lda     #OPNIN | OPNOT
181         sta     ICAX1,x
182         lda     #grmode
183         sta     ICAX2,x
184         lda     #<screen_device
185         sta     ICBAL,x
186         lda     #>screen_device
187         sta     ICBAH,x
188         lda     #<screen_device_length
189         sta     ICBLL,x
190         lda     #>screen_device_length
191         sta     ICBLH,x
192         jsr     CIOV
193
194         .if pages = 2
195         ; Reserve 8K of high memory
196         lda     RAMTOP
197         sub     #32
198         sta     RAMTOP
199         ; Close and reopen graphics
200         lda     #CLOSE
201         sta     ICCOM,x
202         jsr     CIOV
203         ; Reopen graphics
204         lda     #OPEN
205         sta     ICCOM,x
206         lda     #OPNIN | OPNOT
207         sta     ICAX1,x
208         lda     #grmode
209         sta     ICAX2,x
210         lda     #<screen_device
211         sta     ICBAL,x
212         lda     #>screen_device
213         sta     ICBAH,x
214         lda     #<screen_device_length
215         sta     ICBLL,x
216         lda     #>screen_device_length
217         sta     ICBLH,x
218         jsr     CIOV
219         ; Save screen poniters
220         lda     SAVMSC + 1
221         sta     p0scr
222         lda     SDLSTH
223         sta     p0dls
224         .endif
225
226         stx     griocb
227         ; Reset the error code and return
228         lda     #TGI_ERR_OK
229         sta     error
230         rts
231 .endproc
232
233 ; ******************************************************************************
234
235 .proc DONE
236
237         ; ----------------------------------------------------------------------
238         ;
239         ; DONE: Switch back to text mode
240         ;
241         ; ----------------------------------------------------------------------
242
243 .code
244         .if pages = 2
245         ; Free 8K of high memory
246         lda     RAMTOP
247         add     #32
248         sta     RAMTOP
249         .endif
250
251         ; Clear griocb
252         lda     #$FF
253         ldx     griocb
254         sta     griocb
255
256         ; Close the S: device
257         lda     #CLOSE
258         sta     ICCOM,x
259         jsr     CIOV
260
261         ; Reopen it in Graphics 0
262         lda     #OPEN
263         sta     ICCOM,x
264         lda     #OPNIN | OPNOT
265         sta     ICAX1,x
266         lda     #0
267         sta     ICAX2,x
268         lda     #<screen_device
269         sta     ICBAL,x
270         lda     #>screen_device
271         sta     ICBAH,x
272         lda     #<screen_device_length
273         sta     ICBLL,x
274         lda     #>screen_device_length
275         sta     ICBLH,x
276         jsr     CIOV
277
278         ; Now close it again; we don't need it anymore
279         lda     #CLOSE
280         sta     ICCOM,x
281         jmp     CIOV
282 .endproc
283
284 ; ******************************************************************************
285
286 .proc GETERROR
287
288         ; ----------------------------------------------------------------------
289         ;
290         ; GETERROR: Return the error code in A and clear it
291         ;
292         ; ----------------------------------------------------------------------
293
294 .code
295         ldx     #TGI_ERR_OK
296         lda     error
297         stx     error
298         rts
299 .endproc
300
301 ; ******************************************************************************
302
303 .proc CLEAR
304
305         ; ----------------------------------------------------------------------
306         ;
307         ; CLEAR: Clear the screen
308         ;
309         ; ----------------------------------------------------------------------
310
311 .code
312         ; Load the screen address in sptr
313         lda     SAVMSC
314         sta     sptr
315         lda     SAVMSC + 1
316         sta     sptr + 1
317
318         ; Fill with zero
319         lda     #0
320         tay
321
322         ; Clear full pages if any
323         .if >(scrsize) > 0
324         ldx     #>(scrsize)
325 loop1:  sta     (sptr),y
326         iny
327         bne     loop1
328         inc     sptr + 1
329         dex
330         bne     loop1
331         .endif
332
333         ; Clear the rest, if any
334         .if <(scrsize) > 0
335 loop2:  sta     (sptr),y
336         iny
337         cpy     #<(scrsize)
338         bne     loop2
339         .endif
340
341         rts
342 .endproc
343
344 ; ******************************************************************************
345
346 .proc GETPALETTE
347
348         ; ----------------------------------------------------------------------
349         ;
350         ; GETPALETTE: Return the current palette in A/X
351         ;
352         ; ----------------------------------------------------------------------
353
354 .code
355         lda     #<palette
356         ldx     #>palette
357         rts
358 .endproc
359
360 ; ******************************************************************************
361
362 .proc GETDEFPALETTE
363
364         ; ----------------------------------------------------------------------
365         ;
366         ; GETDEFPALETTE: Return the default palette in A/X
367         ;
368         ; ----------------------------------------------------------------------
369
370 .code
371         lda     #<default_palette
372         ldx     #>default_palette
373         rts
374 .endproc
375
376 ; ******************************************************************************
377
378 .proc SETCOLOR
379
380         ; ----------------------------------------------------------------------
381         ;
382         ; SETCOLOR: Set the drawing color (in A)
383         ;
384         ; ----------------------------------------------------------------------
385
386 .code
387         tax
388         .if grmode = 9
389         ; Map colors like this: 0 -> 0, 1 -> 15, 2 -> 1, 3 -> 2 etc.
390         beq     @cont
391         cpx     #1
392         bne     @map
393         ldx     #16
394 @map:   dex
395 @cont:  .endif
396         lda     masks,x
397         sta     mask
398         rts
399 .endproc
400
401 ; ******************************************************************************
402
403 .proc CALC
404
405         ; ----------------------------------------------------------------------
406         ;
407         ; CALC: Calculate the screen address
408         ;       in
409         ;               x1 (ptr1)       x coordinate
410         ;               y1 (ptr2)       y coordinate
411         ;       out
412         ;               sptr + y        screen address
413         ;               x               bit mask index
414         ;
415         ; ----------------------------------------------------------------------
416
417 .bss
418         temp:   .res    1
419 .code
420         ; calculate line offset
421         lda     y1 + 1
422         sta     temp
423         lda     y1
424
425         .if x_res / ppb = 40
426         .define yrep 3
427         .elseif x_res / ppb = 20
428         .define yrep 2
429         .elseif x_res / ppb = 10
430         .define yrep 1
431         .endif
432
433         .repeat yrep
434           asl   a
435           rol   temp
436         .endrepeat
437         sta     sptr
438         ldx     temp
439         stx     sptr + 1
440         .repeat 2
441           asl   a
442           rol   temp
443         .endrepeat
444         add     sptr
445         sta     sptr
446         lda     temp
447         adc     sptr + 1
448         sta     sptr + 1
449
450         ; calculate bit mask offset
451         lda     x1
452         and     #ppb - 1
453         tax
454
455         ; calculate row offset
456         lda     x1 + 1
457         sta     temp
458         lda     x1
459
460         .if ppb = 8
461         .define xrep 3
462         .elseif ppb = 4
463         .define xrep 2
464         .elseif ppb = 2
465         .define xrep 1
466         .endif
467         .repeat xrep
468         lsr     temp
469         ror     a
470         .endrepeat
471         tay
472
473         ; sptr += SAVMSC
474         lda     SAVMSC
475         add     sptr
476         sta     sptr
477         lda     SAVMSC + 1
478         adc     sptr + 1
479         sta     sptr + 1
480
481         ; We're done!
482         rts
483 .endproc
484
485 ; ******************************************************************************
486
487 .proc SETPIXEL
488
489         ; ----------------------------------------------------------------------
490         ;
491         ; Draw one pixel at x1, y1
492         ;
493         ; ----------------------------------------------------------------------
494
495 .code
496         jsr     CALC
497         put_pixel
498         rts
499 .endproc
500
501 ; ******************************************************************************
502
503 .proc GETPIXEL
504
505         ; ----------------------------------------------------------------------
506         ;
507         ; GETPIXEL: Read the color value of a pixel and return it in A/X
508         ;
509         ; ----------------------------------------------------------------------
510
511 .code
512         jsr     CALC
513         lda     (sptr),y
514         and     mask_table,x
515         .if ppb = 8
516         beq     zero
517         lda     #1
518 zero:   ldx     #0
519         rts
520         .elseif ppb = 4
521 loop:   cpx     #3
522         beq     cont
523         lsr     a
524         lsr     a
525         inx
526         bne     loop
527 cont:   and     #$03
528         rts
529         .elseif ppb = 2
530         dex
531         bne     shift
532         and     #$0F
533         jmp     exit
534 shift:  ldx     #0
535         lsr     a
536         lsr     a
537         lsr     a
538         lsr     a
539
540         ; Mode 9 mapping
541 exit:   .if grmode = 9
542         ; Map colors like this: 0 -> 0, 15 -> 1, 2 -> 3, 3 -> 4 etc.
543         beq     @cont
544         cmp     #15
545         bne     @map
546         lda     #0
547 @map:   add     #1
548 @cont:  .endif
549
550         ; Mode 10 mapping
551         .if grmode = 10
552         ; Map out-of-range colors like this:
553         ;  9 -> 8
554         ; 10 -> 8
555         ; 11 -> 8
556         ; 12 -> 0
557         ; 13 -> 1
558         ; 14 -> 2
559         ; 15 -> 3
560         cmp     #9
561         bcc     @cont
562         sub     #12
563         bcs     @cont
564         lda     #8
565 @cont:  .endif
566
567         ; Done!
568         rts
569         .endif
570 .endproc
571
572 ; ******************************************************************************
573
574 .proc LINE
575
576         ; ----------------------------------------------------------------------
577         ;
578         ; LINE: Draw a line from x1,y1 to x2,y2
579         ;
580         ; ----------------------------------------------------------------------
581
582 ; locals
583
584         dx      :=      sreg
585         dy      :=      y1
586         dx2     :=      x2
587         dy2     :=      y2
588         iy      :=      tmp1
589         err     :=      tmp3
590
591 .code
592         ; dx = x2 - x1
593         lda     x2
594         sub     x1
595         sta     dx
596         lda     x2 + 1
597         sbc     x1 + 1
598         sta     dx + 1
599         ; if dx is positive, no problem
600         bcs     dx_positive
601
602         ; if dx is negative, swap x1,y1 with x2,y2
603         lda     x1      ; x1 <-> x2, low byte
604         ldx     x2
605         sta     x2
606         stx     x1
607         lda     x1 + 1  ; x1 <-> x2, high byte
608         ldx     x2 + 1
609         sta     x2 + 1
610         stx     x1 + 1
611         lda     y1      ; y1 <-> y2, low byte
612         ldx     y2
613         sta     y2
614         stx     y1
615         lda     y1 + 1  ; y1 <-> y2, high byte
616         ldx     y2 + 1
617         sta     y2 + 1
618         stx     y1 + 1
619         ; Calculate again
620         jmp     LINE
621
622 dx_positive:
623         ; Calculate coords
624         jsr     CALC
625
626         ; dy = y2 - y1
627         lda     y2
628         sub     y1
629         sta     dy
630         lda     y2 + 1
631         sbc     y1 + 1
632         sta     dy + 1
633
634         ; if dy is negative
635         bcs     dy_positive
636         ; dy = -dy
637         lda     #0
638         sub     dy
639         sta     dy
640         lda     #0
641         sbc     dy + 1
642         sta     dy + 1
643         ; iy = -row_size
644         lda     #<(65536 - x_res / ppb)
645         sta     iy
646         lda     #>(65536 - x_res / ppb)
647         sta     iy + 1
648         bne     skip_iy_1               ; always
649
650 dy_positive:
651         ; iy = row_size
652         lda     #<(x_res / ppb)
653         sta     iy
654         lda     #>(x_res / ppb)
655         sta     iy + 1
656 skip_iy_1:
657
658         ; dx2 = dx * 2
659         lda     dx
660         asl     a
661         sta     dx2
662         lda     dx + 1
663         rol     a
664         sta     dx2 + 1
665
666         ; dy2 = dy * 2
667         lda     dy
668         asl     a
669         sta     dy2
670         lda     dy + 1
671         rol     a
672         sta     dy2 + 1
673
674         ; if dx >= dy
675         lda     dx
676         cmp     dy
677         lda     dx + 1
678         sbc     dy + 1
679         bcc     dy_major
680
681         ; dx is the major axis
682
683         ; err = dy2 - dx
684         lda     dy2
685         sub     dx
686         sta     err
687         lda     dy2 + 1
688         sbc     dx + 1
689         sta     err + 1
690
691         .scope
692 loop:   ; main loop
693         put_pixel
694         ; if err >= 0
695         lda     err + 1
696         bmi     err_neg
697         ; err -= dx2
698         lda     err
699         sub     dx2
700         sta     err
701         lda     err + 1
702         sbc     dx2 + 1
703         sta     err + 1
704         ; move_vertical (iy)
705         lda     sptr
706         add     iy
707         sta     sptr
708         lda     sptr + 1
709         adc     iy + 1
710         sta     sptr + 1
711 err_neg:
712         ; err += dy2
713         lda     err
714         add     dy2
715         sta     err
716         lda     err + 1
717         adc     dy2 + 1
718         sta     err + 1
719         ; move_right
720         inx
721         cpx     #ppb
722         bne     end_move
723         ldx     #0
724         iny
725         bne     end_move
726         inc     sptr + 1
727 end_move:
728         ; loop while dx-- >= 0
729         lda     dx
730         ora     dx + 1
731         beq     exit
732         dec     dx
733         lda     dx
734         cmp     #$FF
735         bne     loop
736         dec     dx + 1
737         jmp     loop
738 exit:   rts
739         .endscope
740
741 dy_major:
742         ; dy is the major axis
743
744         ; err = dx2 - dy;
745         lda     dx2
746         sub     dy
747         sta     err
748         lda     dx2 + 1
749         sbc     dy + 1
750         sta     err + 1
751
752         .scope
753 loop:   ; main loop
754         put_pixel
755         ; if err >= 0
756         lda     err + 1
757         bmi     end_move
758         ; err -= dy2
759         lda     err
760         sub     dy2
761         sta     err
762         lda     err + 1
763         sbc     dy2 + 1
764         sta     err + 1
765         ; move_right
766         inx
767         cpx     #ppb
768         bne     end_move
769         ldx     #0
770         iny
771         bne     end_move
772         inc     sptr + 1
773 end_move:
774         ; err += dx2
775         lda     err
776         add     dx2
777         sta     err
778         lda     err + 1
779         adc     dx2 + 1
780         sta     err + 1
781         ; move_vertical(iy)
782         lda     sptr
783         add     iy
784         sta     sptr
785         lda     sptr + 1
786         adc     iy + 1
787         sta     sptr + 1
788         ; loop while dy-- >= 0
789         lda     dy
790         ora     dy + 1
791         beq     exit
792         dec     dy
793         lda     dy
794         cmp     #$FF
795         bne     loop
796         dec     dy + 1
797         jmp     loop
798 exit:   rts
799         .endscope
800 .endproc
801
802 ; ******************************************************************************
803
804 .proc clipped_bar
805
806         ; ----------------------------------------------------------------------
807         ;
808         ; Clip and draw bar
809         ;
810         ; ----------------------------------------------------------------------
811
812 .code
813         lda     y1 + 1
814         bne     off
815         lda     y1
816         cmp     #y_res
817         bcs     off
818
819         lda     x1 + 1
820         .if >(x_res - 1) > 0
821         cmp     #>x_res
822         bcc     check2
823         .endif
824         bne     off
825         lda     x1
826         cmp     #<x_res
827         bcc     check2
828 off:    rts
829
830 check2: lda     y2 + 1
831         bne     off
832         lda     y2
833         cmp     #y_res
834         bcs     off
835
836         lda     x2 + 1
837         .if >(x_res - 1) > 0
838         cmp     #>x_res
839         bcc     BAR
840         .endif
841         bne     off
842         lda     x2
843         cmp     #<x_res
844         bcs     off
845 .endproc
846
847 ; ******************************************************************************
848
849 .proc BAR
850
851         ; ----------------------------------------------------------------------
852         ;
853         ; BAR: Draw a filled rectangle with the corners at x1,y1,x2,y2
854         ;
855         ; ----------------------------------------------------------------------
856
857 ; locals
858         lmem    := sreg
859 .bss
860         lmask:  .res 1
861         rmask:  .res 1
862         dy:     .res 1
863         dx:     .res 1
864         fmask:  .res 1
865 .code
866         ; dy = y2 - y1 + 1
867         lda     y2
868         sub     y1
869         sta     dy
870         inc     dy
871         ; Calculate upper left corner
872         jsr     CALC
873         ; Save the values
874         tya
875         add     sptr
876         sta     lmem
877         lda     sptr + 1
878         adc     #0
879         sta     lmem + 1
880         lda     bar_table,x
881         sta     lmask
882         ; Calculate upper right corner
883         lda     x2
884         sta     x1
885         .if >(x_res - 1) > 0
886         lda     x2 + 1
887         sta     x1 + 1
888         .endif
889         jsr     CALC
890         ; Save the values
891         tya
892         add     sptr
893         sta     sptr
894         bcc     skips
895         inc     sptr + 1
896 skips:  inx
897         lda     bar_table,x
898         eor     #$FF
899         sta     rmask
900         ; Calculate memory difference between x1 and x2
901         lda     sptr
902         sub     lmem
903         sta     dx
904 loop:   ; Main loop
905         ldy     #0
906         ldx     dx
907         beq     same
908         ; Left
909         lda     (lmem),y
910         eor     mask
911         and     lmask
912         eor     (lmem),y
913         sta     (lmem),y
914         iny
915         ; Between
916         lda     mask
917         jmp     next
918 btwn:   sta     (lmem),y
919         iny
920 next:   dex
921         bne     btwn
922         ; Right
923         lda     (lmem),y
924         eor     mask
925         and     rmask
926         eor     (lmem),y
927         sta     (lmem),y
928         jmp     cont
929 same:   ; Same byte
930         lda     lmask
931         and     rmask
932         sta     fmask
933         lda     (lmem),y
934         eor     mask
935         and     fmask
936         eor     (lmem),y
937         sta     (lmem),y
938 cont:   ; Go to next row
939         lda     lmem
940         add     #<(x_res / ppb)
941         sta     lmem
942         bcc     skipm
943         inc     lmem + 1
944 skipm:  ; Loop while --dy > 0
945         dec     dy
946         bne     loop
947
948         rts
949
950 .endproc
951
952 ; ******************************************************************************
953
954 .proc TEXTSTYLE
955
956         ; ----------------------------------------------------------------------
957         ;
958         ; TEXTSTYLE: Set text style. Scale factors in X and Y and direction in A
959         ;
960         ; ----------------------------------------------------------------------
961
962 .code
963         stx     mag_x
964         sty     mag_y
965         ; Save text direction in bit 8 so that we can use BIT instruction later
966         lsr     a
967         ror     a
968         sta     text_dir
969         ; Save 8 * scaling factors
970         lda     #0
971         sta     mag_x8 + 1
972         sta     mag_y8 + 1
973         ; Save 8 * mag_x
974         txa
975         .repeat 3
976         asl     a
977         rol     mag_x8 + 1
978         .endrepeat
979         sta     mag_x8
980         ; Save 8 * mag_y
981         tya
982         .repeat 3
983         asl     a
984         rol     mag_y8 + 1
985         .endrepeat
986         sta     mag_y8
987         ; Done!
988         rts
989 .endproc
990
991 ; ******************************************************************************
992
993 .proc OUTTEXT
994
995         ; ----------------------------------------------------------------------
996         ;
997         ; OUTTEXT: Draw text at x1, y1. String is in ptr3
998         ;
999         ; ----------------------------------------------------------------------
1000
1001 ; locals
1002         string  := tmp1
1003         cols    := tmp3
1004         pixels  := tmp4
1005         font    := regsave
1006 .rodata
1007         ataint: .byte   64,0,32,96
1008 .bss
1009         rows:   .res    1
1010         .if >(x_res - 1) > 0
1011         oldx1:  .res    2
1012         oldx2:  .res    2
1013         .else
1014         oldx1:  .res    1
1015         oldx2:  .res    1
1016         .endif
1017         oldy1:  .res    1
1018         oldy2:  .res    1
1019         inv:    .res    1
1020 .code
1021         ; Don't draw zero sized characters
1022         lda     mag_x
1023         beq     @exit
1024         lda     mag_y
1025         bne     @cont
1026 @exit:  rts
1027 @cont:  ; Save string address, ptr3 is needed by BAR
1028         lda     ptr3
1029         sta     string
1030         lda     ptr3 + 1
1031         sta     string + 1
1032
1033         bit     text_dir
1034         bmi     vert
1035
1036         ; Calculate x2
1037         lda     mag_x
1038         sub     #1
1039         add     x1
1040         sta     x2
1041         .if >(x_res - 1) > 0
1042         lda     x1 + 1
1043         adc     #0
1044         sta     x2 + 1
1045         .else
1046         lda     #0
1047         sta     x2 + 1
1048         .endif
1049
1050         ; Calculate y2 and adjust y1
1051         dec     y1
1052         lda     y1
1053         sta     y2
1054         sub     mag_y
1055         add     #1
1056         sta     y1
1057         lda     #0
1058         sta     y2 + 1
1059
1060         jmp     while
1061
1062         ; Calculate for vertical text
1063 vert:   lda     x1
1064         sub     #1
1065         sta     x2
1066         lda     x1 + 1
1067         sbc     #0
1068         sta     x2 + 1
1069         lda     x1
1070         sub     mag_y
1071         sta     x1
1072         lda     x1 + 1
1073         sbc     #0
1074         sta     x1 + 1
1075
1076         lda     mag_x
1077         sub     #1
1078         add     y1
1079         sta     y2
1080         lda     #0
1081         sta     y2 + 1
1082         beq     while           ; Always
1083
1084         ; Main loop
1085 loop:   inc     string
1086         bne     skiph
1087         inc     string + 1
1088 skiph:  ; Save coords
1089         jsr     save_text_y
1090         ; Draw one character
1091         jsr     outchar
1092         ; Restore coords
1093         jsr     restore_text_y
1094         ; End of loop
1095 while:  ldy     #0
1096         lda     (string),y
1097         bne     loop            ; Check for null character
1098         rts
1099
1100         ; --------------------
1101         ; Output one character
1102 outchar:
1103         ; Convert to ANTIC code
1104         tay
1105         rol     a
1106         rol     a
1107         rol     a
1108         rol     a
1109         and     #3
1110         tax
1111         tya
1112         and     #$9f
1113         ora     ataint,x
1114         ; Save and clear inverse video bit
1115         sta     inv
1116         and     #$7F
1117         ; Calculate font data address
1118         sta     font
1119         lda     #0
1120         sta     font + 1
1121         .repeat 3
1122         asl     font
1123         rol     a
1124         .endrepeat
1125         adc     CHBAS
1126         sta     font + 1
1127         ; Save old coords
1128         bit     text_dir
1129         bpl     @hor
1130         lda     y1
1131         sta     oldy1
1132         lda     y2
1133         sta     oldy2
1134         jmp     @cont
1135 @hor:   lda     x1
1136         sta     oldx1
1137         lda     x2
1138         sta     oldx2
1139         .if >(x_res - 1) > 0
1140         lda     x1 + 1
1141         sta     oldx1 + 1
1142         lda     x2 + 1
1143         sta     oldx2 + 1
1144         .endif
1145         ; Get glyph pixels
1146 @cont:  ldy     #7
1147         ; Put one row of the glyph
1148 putrow: sty     rows
1149         lda     (font),y
1150         bit     inv
1151         bpl     noinv
1152         eor     #$FF
1153 noinv:  sta     pixels
1154         lda     #7
1155         sta     cols
1156         ; Put one column of the row
1157 putcol: asl     pixels
1158         bcc     next_col
1159         lda     x1
1160         pha
1161         lda     x1 + 1
1162         pha
1163         jsr     clipped_bar
1164         pla
1165         sta     x1 + 1
1166         pla
1167         sta     x1
1168 next_col:
1169         ; Go to next column
1170         jsr     inc_x
1171         dec     cols
1172         bpl     putcol
1173 next_row:
1174         ; Go to next row
1175         jsr     dec_y
1176         ; Restore old values
1177         bit     text_dir
1178         bpl     @hor
1179         lda     oldy1
1180         sta     y1
1181         lda     oldy2
1182         sta     y2
1183         jmp     @cont
1184 @hor:   lda     oldx1
1185         sta     x1
1186         lda     oldx2
1187         sta     x2
1188         .if >(x_res - 1) > 0
1189         lda     oldx1 + 1
1190         sta     x1 + 1
1191         lda     oldx2 + 1
1192         sta     x2 + 1
1193         .endif
1194         ; Next row
1195 @cont:  ldy     rows
1196         dey
1197         bpl     putrow
1198
1199         ; We're done!
1200         rts
1201
1202
1203 ; -------------------------
1204 inc_x:  ; increase x coords
1205         bit     text_dir
1206         bmi     @vert
1207
1208         lda     mag_x
1209         add     x1
1210         sta     x1
1211         bcc     @1
1212         inc     x1 + 1
1213 @1:     lda     mag_x
1214         add     x2
1215         sta     x2
1216         bcc     @2
1217         inc     x2 + 1
1218 @2:     rts
1219
1220 @vert:  lda     y1
1221         sub     mag_x
1222         sta     y1
1223         lda     y2
1224         sub     mag_x
1225         sta     y2
1226         rts
1227
1228 ; -------------------------
1229 dec_y:  ; decrease y coords
1230         bit     text_dir
1231         bmi     @vert
1232
1233         lda     y1
1234         sub     mag_y
1235         sta     y1
1236         bcs     @1
1237         dec     y1 + 1
1238 @1:     lda     y2
1239         sub     mag_y
1240         sta     y2
1241         bcs     @2
1242         dec     y2 + 1
1243 @2:     rts
1244
1245 @vert:  lda     x1
1246         sub     mag_y
1247         sta     x1
1248         bcs     @3
1249         dec     x1 + 1
1250 @3:     lda     x2
1251         sub     mag_y
1252         sta     x2
1253         bcs     @4
1254         dec     x2 + 1
1255 @4:     rts
1256
1257 ; -------------------------
1258 save_text_y: ; Save text's height coords
1259         bit     text_dir
1260         bmi     @vert
1261         ldx     y1
1262         stx     oldy1
1263         ldx     y2
1264         stx     oldy2
1265         rts
1266 @vert:  ldx     x1
1267         stx     oldx1
1268         ldx     x2
1269         stx     oldx2
1270         .if >(x_res - 1) > 0
1271         ldx     x1 + 1
1272         stx     oldx1 + 1
1273         ldx     x2 + 1
1274         stx     oldx2 + 1
1275         .endif
1276         rts
1277
1278 ; -------------------------
1279 restore_text_y: ; Position to next char
1280         bit     text_dir
1281         bmi     @vert
1282
1283         ldx     oldy1
1284         stx     y1
1285         ldx     oldy2
1286         stx     y2
1287         ldx     #0
1288         stx     y1 + 1
1289         stx     y2 + 1
1290
1291         lda     mag_x8
1292         add     x1
1293         sta     x1
1294         lda     mag_x8 + 1
1295         adc     x1 + 1
1296         sta     x1 + 1
1297         lda     mag_x8
1298         add     x2
1299         sta     x2
1300         lda     mag_x8 + 1
1301         adc     x2 + 1
1302         sta     x2 + 1
1303
1304         rts
1305
1306 @vert:  ldx     oldx1
1307         stx     x1
1308         ldx     oldx2
1309         stx     x2
1310         .if >(x_res - 1) > 0
1311         ldx     oldx1 + 1
1312         stx     x1 + 1
1313         ldx     oldx2 + 1
1314         stx     x2 + 1
1315         .endif
1316
1317         lda     y1
1318         sub     mag_x8
1319         sta     y1
1320         lda     y1 +1
1321         sbc     mag_x8 + 1
1322         sta     y1 + 1
1323         lda     y2
1324         sub     mag_x8
1325         sta     y2
1326         lda     y2 +1
1327         sbc     mag_x8 + 1
1328         sta     y2 + 1
1329
1330         rts
1331
1332 .endproc
1333
1334 .if pages = 2
1335 ; ******************************************************************************
1336
1337 .proc SETVIEWPAGE
1338
1339         ; ----------------------------------------------------------------------
1340         ;
1341         ; SETVIEWPAGE, page in A
1342         ;
1343         ; ----------------------------------------------------------------------
1344
1345 .code
1346         tax
1347         beq     cont
1348         lda     #32
1349
1350 cont:   add     p0dls
1351         cmp     SDLSTH
1352         beq     done            ; We're already in the desired page
1353
1354         ldx     RTCLOK + 2
1355         sta     SDLSTH
1356
1357         ; Wait until next VBLANK
1358 wait:   cpx     RTCLOK + 2
1359         beq     wait
1360
1361         ; Done
1362 done:   rts
1363 .endproc
1364
1365 ; ******************************************************************************
1366
1367 .proc SETDRAWPAGE
1368
1369         ; ----------------------------------------------------------------------
1370         ;
1371         ; SETDRAWPAGE, page in A
1372         ;
1373         ; ----------------------------------------------------------------------
1374
1375 .code
1376         tax
1377         beq     @cont
1378         lda     #32
1379 @cont:  add     p0scr
1380         sta     SAVMSC + 1
1381         rts
1382 .endproc
1383 .endif
1384
1385 ; ******************************************************************************
1386
1387         ; ----------------------------------------------------------------------
1388         ;
1389         ; Unimplemented functions that require an error code
1390         ;
1391         ; ----------------------------------------------------------------------
1392
1393 CONTROL:
1394         lda     #TGI_ERR_INV_FUNC
1395         sta     error
1396         ; fall through
1397
1398 ; ******************************************************************************
1399
1400         ; ----------------------------------------------------------------------
1401         ;
1402         ; Unimplemented functions that don't require an error code
1403         ;
1404         ; ----------------------------------------------------------------------
1405
1406 INSTALL:
1407 UNINSTALL:
1408 .if pages = 1
1409 SETVIEWPAGE:
1410 SETDRAWPAGE:
1411 .endif
1412         rts