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