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