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