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