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