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