]> git.sur5r.net Git - cc65/blob - libsrc/c64/tgi/c64-hi.s
Fixed _textcolor definition.
[cc65] / libsrc / c64 / tgi / c64-hi.s
1 ;
2 ; Graphics driver for the 320x200x2 mode on the C64.
3 ;
4 ; Based on Stephen L. Judd's GRLIB code.
5 ;
6 ; 2017-01-13, Greg King
7 ; 2018-03-13, Sven Klose
8 ;
9
10         .include        "zeropage.inc"
11
12         .include        "tgi-kernel.inc"
13         .include        "tgi-error.inc"
14
15         .macpack        generic
16         .macpack        module
17
18
19 ; ------------------------------------------------------------------------
20 ; Header. Includes jump table and constants.
21
22         module_header   _c64_hi_tgi
23
24 ; First part of the header is a structure that has a magic and defines the
25 ; capabilities of the driver
26
27         .byte   $74, $67, $69           ; "tgi"
28         .byte   TGI_API_VERSION         ; TGI API version number
29         .addr   $0000                   ; Library reference
30         .word   320                     ; X resolution
31         .word   200                     ; Y resolution
32         .byte   2                       ; Number of drawing colors
33         .byte   1                       ; Number of screens available
34         .byte   8                       ; System font X size
35         .byte   8                       ; System font Y size
36         .word   $00D4                   ; Aspect ratio (based on 4/3 display)
37         .byte   0                       ; TGI driver flags
38
39 ; Next comes the jump table. With the exception of IRQ, all entries must be
40 ; valid and may point to an RTS for test versions (function not implemented).
41
42         .addr   INSTALL
43         .addr   UNINSTALL
44         .addr   INIT
45         .addr   DONE
46         .addr   GETERROR
47         .addr   CONTROL
48         .addr   CLEAR
49         .addr   SETVIEWPAGE
50         .addr   SETDRAWPAGE
51         .addr   SETCOLOR
52         .addr   SETPALETTE
53         .addr   GETPALETTE
54         .addr   GETDEFPALETTE
55         .addr   SETPIXEL
56         .addr   GETPIXEL
57         .addr   LINE
58         .addr   BAR
59         .addr   TEXTSTYLE
60         .addr   OUTTEXT
61
62 ; ------------------------------------------------------------------------
63 ; Data.
64
65 ; Variables mapped to the zero page segment variables. Some of these are
66 ; used for passing parameters to the driver.
67
68 X1              := ptr1
69 Y1              := ptr2
70 X2              := ptr3
71 Y2              := ptr4
72 TEXT            := ptr3
73
74 TEMP            := tmp4
75 TEMP2           := sreg
76 POINT           := regsave
77
78 CHUNK           := X2           ; Used in the line routine
79 OLDCHUNK        := X2+1         ; Dito
80
81 ; Absolute variables used in the code
82
83 .bss
84
85 ERROR:          .res    1       ; Error code
86 PALETTE:        .res    2       ; The current palette
87
88 BITMASK:        .res    1       ; $00 = clear, $FF = set pixels
89
90 ; INIT/DONE
91 OLDD018:        .res    1       ; Old register value
92
93 ; Line routine stuff
94 DX:             .res    2
95 DY:             .res    2
96
97 ; BAR variables
98 X1SAVE:         .res    2
99 Y1SAVE:         .res    2
100 X2SAVE:         .res    2
101 Y2SAVE:         .res    2
102
103 ; Text output stuff
104 TEXTMAGX:       .res    1
105 TEXTMAGY:       .res    1
106 TEXTDIR:        .res    1
107
108 ; Constants and tables
109
110 .rodata
111
112 DEFPALETTE:     .byte   $00, $01        ; White on black
113 PALETTESIZE     = * - DEFPALETTE
114
115 BITTAB:         .byte   $80,$40,$20,$10,$08,$04,$02,$01
116 BITCHUNK:       .byte   $FF,$7F,$3F,$1F,$0F,$07,$03,$01
117
118 CHARROM         := $D000                ; Character rom base address
119 CBASE           := $D000                ; Color memory base address
120 VBASE           := $E000                ; Video memory base address
121
122
123 .code
124
125 ; ------------------------------------------------------------------------
126 ; INSTALL routine. Is called after the driver is loaded into memory. May
127 ; initialize anything that has to be done just once. Is probably empty
128 ; most of the time.
129 ;
130 ; Must set an error code: NO
131 ;
132
133 INSTALL:
134 ;       rts                     ; fall through
135
136
137 ; ------------------------------------------------------------------------
138 ; UNINSTALL routine. Is called before the driver is removed from memory. May
139 ; clean up anything done by INSTALL but is probably empty most of the time.
140 ;
141 ; Must set an error code: NO
142 ;
143
144 UNINSTALL:
145         rts
146
147
148 ; ------------------------------------------------------------------------
149 ; INIT: Changes an already installed device from text mode to graphics
150 ; mode.
151 ; Note that INIT/DONE may be called multiple times while the driver
152 ; is loaded, while INSTALL is only called once, so any code that is needed
153 ; to initializes variables and so on must go here. Setting palette and
154 ; clearing the screen is not needed because this is called by the graphics
155 ; kernel later.
156 ; The graphics kernel will never call INIT when a graphics mode is already
157 ; active, so there is no need to protect against that.
158 ;
159 ; Must set an error code: YES
160 ;
161
162 INIT:
163
164 ; Initialize variables
165
166         ldx     #$FF
167         stx     BITMASK
168
169 ; Switch into graphics mode
170
171         lda     $DD02           ; Set the data direction regs
172         ora     #3
173         sta     $DD02
174         lda     $DD00
175         and     #$FC            ; Switch to bank 3
176         sta     $DD00
177
178         lda     $D018
179         sta     OLDD018
180         lda     #$48            ; Set color map to $D000, screen to $E000
181         sta     $D018
182
183         lda     $D011           ; And turn on bitmap
184         ora     #$20
185 DONE1:  sta     $D011
186
187 ; Done, reset the error code
188
189         lda     #TGI_ERR_OK
190         sta     ERROR
191         rts
192
193 ; ------------------------------------------------------------------------
194 ; DONE: Will be called to switch the graphics device back into text mode.
195 ; The graphics kernel will never call DONE when no graphics mode is active,
196 ; so there is no need to protect against that.
197 ;
198 ; Must set an error code: NO
199 ;
200
201 DONE:   lda     $DD02           ; Set the data direction regs
202         ora     #3
203         sta     $DD02
204         lda     $DD00
205         ora     #$03            ; Bank 0
206         sta     $DD00
207
208         lda     OLDD018         ; Screen mem --> $0400
209         sta     $D018
210
211         lda     $D011
212         and     #<~$20
213         sta     $D011
214         rts
215
216 ; ------------------------------------------------------------------------
217 ; GETERROR: Return the error code in A and clear it.
218
219 GETERROR:
220         ldx     #TGI_ERR_OK
221         lda     ERROR
222         stx     ERROR
223         rts
224
225 ; ------------------------------------------------------------------------
226 ; CONTROL: Platform/driver specific entry point.
227 ;
228 ; Must set an error code: YES
229 ;
230
231 CONTROL:
232         lda     #TGI_ERR_INV_FUNC
233         sta     ERROR
234         rts
235
236 ; ------------------------------------------------------------------------
237 ; CLEAR: Clears the screen.
238 ;
239 ; Must set an error code: NO
240 ;
241
242 CLEAR:  ldy     #$00
243         tya
244 @L1:    sta     VBASE+$0000,y
245         sta     VBASE+$0100,y
246         sta     VBASE+$0200,y
247         sta     VBASE+$0300,y
248         sta     VBASE+$0400,y
249         sta     VBASE+$0500,y
250         sta     VBASE+$0600,y
251         sta     VBASE+$0700,y
252         sta     VBASE+$0800,y
253         sta     VBASE+$0900,y
254         sta     VBASE+$0A00,y
255         sta     VBASE+$0B00,y
256         sta     VBASE+$0C00,y
257         sta     VBASE+$0D00,y
258         sta     VBASE+$0E00,y
259         sta     VBASE+$0F00,y
260         sta     VBASE+$1000,y
261         sta     VBASE+$1100,y
262         sta     VBASE+$1200,y
263         sta     VBASE+$1300,y
264         sta     VBASE+$1400,y
265         sta     VBASE+$1500,y
266         sta     VBASE+$1600,y
267         sta     VBASE+$1700,y
268         sta     VBASE+$1800,y
269         sta     VBASE+$1900,y
270         sta     VBASE+$1A00,y
271         sta     VBASE+$1B00,y
272         sta     VBASE+$1C00,y
273         sta     VBASE+$1D00,y
274         sta     VBASE+$1E00,y
275         sta     VBASE+$1E40,y   ; preserve vectors
276         iny
277         bne     @L1
278         rts
279
280 ; ------------------------------------------------------------------------
281 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
282 ; The page number is already checked to be valid by the graphics kernel.
283 ;
284 ; Must set an error code: NO (will only be called if page ok)
285 ;
286
287 SETVIEWPAGE:
288 ;       rts                     ; fall through
289
290 ; ------------------------------------------------------------------------
291 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
292 ; The page number is already checked to be valid by the graphics kernel.
293 ;
294 ; Must set an error code: NO (will only be called if page ok)
295 ;
296
297 SETDRAWPAGE:
298         rts
299
300 ; ------------------------------------------------------------------------
301 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
302 ; to be in a valid range (0..maxcolor-1).
303 ;
304 ; Must set an error code: NO (will only be called if color ok)
305 ;
306
307 SETCOLOR:
308         tax
309         beq     @L1
310         lda     #$FF
311 @L1:    sta     BITMASK
312         rts
313
314 ; ------------------------------------------------------------------------
315 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
316 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
317 ; are not supported
318 ;
319 ; Must set an error code: YES
320 ;
321
322 SETPALETTE:
323         ldy     #PALETTESIZE - 1
324 @L1:    lda     (ptr1),y        ; Copy the palette
325         and     #$0F            ; Make a valid color
326         sta     PALETTE,y
327         dey
328         bpl     @L1
329
330 ; Get the color entries from the palette
331
332         lda     PALETTE+1       ; Foreground color
333         asl     a
334         asl     a
335         asl     a
336         asl     a
337         ora     PALETTE         ; Background color
338         tax
339
340 ; Initialize the color map with the new color settings (it is below the
341 ; I/O area)
342
343         ldy     #$00
344         sei
345         lda     $01             ; Get ROM config
346         pha                     ; Save it
347         and     #%11111100      ; Clear bit 0 and 1
348         sta     $01
349         txa                     ; Load color code
350 @L2:    sta     CBASE+$0000,y
351         sta     CBASE+$0100,y
352         sta     CBASE+$0200,y
353         sta     CBASE+$02e8,y
354         iny
355         bne     @L2
356         pla
357         sta     $01
358         cli
359
360 ; Done, reset the error code
361
362         lda     #TGI_ERR_OK
363         sta     ERROR
364         rts
365
366 ; ------------------------------------------------------------------------
367 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
368 ; set the palette should return the default palette here, so there's no
369 ; way for this function to fail.
370 ;
371 ; Must set an error code: NO
372 ;
373
374 GETPALETTE:
375         lda     #<PALETTE
376         ldx     #>PALETTE
377         rts
378
379 ; ------------------------------------------------------------------------
380 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
381 ; drivers should return something reasonable here, even drivers that don't
382 ; support palettes, otherwise the caller has no way to determine the colors
383 ; of the (not changeable) palette.
384 ;
385 ; Must set an error code: NO (all drivers must have a default palette)
386 ;
387
388 GETDEFPALETTE:
389         lda     #<DEFPALETTE
390         ldx     #>DEFPALETTE
391         rts
392
393 ; ------------------------------------------------------------------------
394 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
395 ; color. The coordinates passed to this function are never outside the
396 ; visible screen area, so there is no need for clipping inside this function.
397 ;
398 ; Must set an error code: NO
399 ;
400
401 SETPIXEL:
402         jsr     CALC            ; Calculate coordinates
403
404         sei                     ; Get underneath ROM
405         lda     $01
406         pha
407         lda     #$34
408         sta     $01
409
410         lda     (POINT),Y
411         eor     BITMASK
412         and     BITTAB,X
413         eor     (POINT),Y
414         sta     (POINT),Y
415
416         pla
417         sta     $01
418         cli
419
420 @L9:    rts
421
422 ; ------------------------------------------------------------------------
423 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
424 ; coordinates passed to this function are never outside the visible screen
425 ; area, so there is no need for clipping inside this function.
426
427
428 GETPIXEL:
429         jsr     CALC            ; Calculate coordinates
430
431         sei                     ; Get underneath ROM
432         lda     $01
433         pha
434         lda     #$34
435         sta     $01
436
437         lda     (POINT),Y
438         ldy     #$00
439         and     BITTAB,X
440         beq     @L1
441         iny
442
443 @L1:    pla
444         sta     $01
445         cli
446
447         tya                     ; Get color value into A
448         ldx     #$00            ; Clear high byte
449         rts
450
451 ; ------------------------------------------------------------------------
452 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
453 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
454 ;
455 ; X1,X2 etc. are set up above (x2=LINNUM in particular)
456 ; Format is LINE x2,y2,x1,y1
457 ;
458 ; Must set an error code: NO
459 ;
460
461 LINE:
462
463 @CHECK: lda     X2           ;Make sure x1<x2
464         sec
465         sbc     X1
466         tax
467         lda     X2+1
468         sbc     X1+1
469         bpl     @CONT
470         lda     Y2           ;If not, swap P1 and P2
471         ldy     Y1
472         sta     Y1
473         sty     Y2
474         lda     Y2+1
475         ldy     Y1+1
476         sta     Y1+1
477         sty     Y2+1
478         lda     X1
479         ldy     X2
480         sty     X1
481         sta     X2
482         lda     X2+1
483         ldy     X1+1
484         sta     X1+1
485         sty     X2+1
486         bcc     @CHECK
487
488 @CONT:  sta     DX+1
489         stx     DX
490
491         ldx     #$C8         ;INY
492         lda     Y2           ;Calculate dy
493         sec
494         sbc     Y1
495         tay
496         lda     Y2+1
497         sbc     Y1+1
498         bpl     @DYPOS       ;Is y2>=y1?
499         lda     Y1           ;Otherwise dy=y1-y2
500         sec
501         sbc     Y2
502         tay
503         ldx     #$88         ;DEY
504
505 @DYPOS: sty     DY              ; 8-bit DY -- FIX ME?
506         stx     YINCDEC
507         stx     XINCDEC
508
509         jsr     CALC            ; Set up .X, .Y, and POINT
510         lda     BITCHUNK,X
511         sta     OLDCHUNK
512         sta     CHUNK
513
514         sei                     ; Get underneath ROM
515         lda     #$34
516         sta     $01
517
518         ldx     DY
519         cpx     DX           ;Who's bigger: dy or dx?
520         bcc     STEPINX      ;If dx, then...
521         lda     DX+1
522         bne     STEPINX
523
524 ;
525 ; Big steps in Y
526 ;
527 ;   To simplify my life, just use PLOT to plot points.
528 ;
529 ;   No more!
530 ;   Added special plotting routine -- cool!
531 ;
532 ;   X is now counter, Y is y-coordinate
533 ;
534 ; On entry, X=DY=number of loop iterations, and Y=
535 ;   Y1 AND #$07
536 STEPINY:
537         lda     #00
538         sta     OLDCHUNK     ;So plotting routine will work right
539         lda     CHUNK
540         lsr                  ;Strip the bit
541         eor     CHUNK
542         sta     CHUNK
543         txa
544         beq     YCONT2       ;If dy=0, it's just a point
545 @CONT:  lsr                  ;Init counter to dy/2
546 ;
547 ; Main loop
548 ;
549 YLOOP:  sta     TEMP
550
551         lda     (POINT),y
552         eor     BITMASK
553         and     CHUNK
554         eor     (POINT),y
555         sta     (POINT),y
556 YINCDEC:
557         iny                  ;Advance Y coordinate
558         cpy     #8
559         bcc     @CONT        ;No prob if Y=0..7
560         jsr     FIXY
561 @CONT:  lda     TEMP         ;Restore A
562         sec
563         sbc     DX
564         bcc     YFIXX
565 YCONT:  dex                  ;X is counter
566         bne     YLOOP
567 YCONT2: lda     (POINT),y    ;Plot endpoint
568         eor     BITMASK
569         and     CHUNK
570         eor     (POINT),y
571         sta     (POINT),y
572         lda     #$36
573         sta     $01
574         cli
575         rts
576
577 YFIXX:                    ;x=x+1
578         adc     DY
579         lsr     CHUNK
580         bne     YCONT        ;If we pass a column boundary...
581         ror     CHUNK        ;then reset CHUNK to $80
582         sta     TEMP2
583         lda     POINT        ;And add 8 to POINT
584         adc     #8
585         sta     POINT
586         bcc     @CONT
587         inc     POINT+1
588 @CONT:  lda     TEMP2
589         dex
590         bne     YLOOP
591         beq     YCONT2
592
593 ;
594 ; Big steps in X direction
595 ;
596 ; On entry, X=DY=number of loop iterations, and Y=
597 ;   Y1 AND #$07
598
599 .bss
600 COUNTHI:
601         .byte   $00       ;Temporary counter
602                           ;only used once
603 .code
604 STEPINX:
605         ldx     DX
606         lda     DX+1
607         sta     COUNTHI
608         cmp     #$80
609         ror                  ;Need bit for initialization
610         sta     Y1           ;High byte of counter
611         txa
612         bne     @CONT        ;Could be $100
613         dec     COUNTHI
614 @CONT:  ror
615 ;
616 ; Main loop
617 ;
618 XLOOP:  lsr     CHUNK
619         beq     XFIXC        ;If we pass a column boundary...
620 XCONT1: sbc     DY
621         bcc     XFIXY        ;Time to step in Y?
622 XCONT2: dex
623         bne     XLOOP
624         dec     COUNTHI      ;High bits set?
625         bpl     XLOOP
626
627         lsr     CHUNK        ;Advance to last point
628         jsr     LINEPLOT     ;Plot the last chunk
629         lda     #$36
630         sta     $01
631         cli
632         rts
633 ;
634 ; CHUNK has passed a column, so plot and increment pointer
635 ; and fix up CHUNK, OLDCHUNK.
636 ;
637 XFIXC:  sta     TEMP
638         jsr     LINEPLOT
639         lda     #$FF
640         sta     CHUNK
641         sta     OLDCHUNK
642         lda     POINT
643         clc
644         adc     #8
645         sta     POINT
646         lda     TEMP
647         bcc     XCONT1
648         inc     POINT+1
649         jmp     XCONT1
650 ;
651 ; Check to make sure there isn't a high bit, plot chunk,
652 ; and update Y-coordinate.
653 ;
654 XFIXY:  dec     Y1           ;Maybe high bit set
655         bpl     XCONT2
656         adc     DX
657         sta     TEMP
658         lda     DX+1
659         adc     #$FF         ;Hi byte
660         sta     Y1
661
662         jsr     LINEPLOT     ;Plot chunk
663         lda     CHUNK
664         sta     OLDCHUNK
665
666         lda     TEMP
667 XINCDEC:
668         iny                  ;Y-coord
669         cpy     #8           ;0..7 is ok
670         bcc     XCONT2
671         sta     TEMP
672         jsr     FIXY
673         lda     TEMP
674         jmp     XCONT2
675
676 ;
677 ; Subroutine to plot chunks/points (to save a little
678 ; room, gray hair, etc.)
679 ;
680 LINEPLOT:                       ; Plot the line chunk
681         lda     (POINT),Y
682         eor     BITMASK
683         ora     CHUNK
684         and     OLDCHUNK
685         eor     CHUNK
686         eor     (POINT),Y
687         sta     (POINT),Y
688         rts
689
690 ;
691 ; Subroutine to fix up pointer when Y decreases through
692 ; zero or increases through 7.
693 ;
694 FIXY:   cpy     #255         ;Y=255 or Y=8
695         beq     @DECPTR
696
697 @INCPTR:                     ;Add 320 to pointer
698         ldy     #0           ;Y increased through 7
699         lda     POINT
700         adc     #<320
701         sta     POINT
702         lda     POINT+1
703         adc     #>320
704         sta     POINT+1
705         rts
706
707 @DECPTR:                     ;Okay, subtract 320 then
708         ldy     #7           ;Y decreased through 0
709         lda     POINT
710         sec
711         sbc     #<320
712         sta     POINT
713         lda     POINT+1
714         sbc     #>320
715         sta     POINT+1
716         rts
717
718 ; ------------------------------------------------------------------------
719 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
720 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
721 ; Contrary to most other functions, the graphics kernel will sort and clip
722 ; the coordinates before calling the driver, so on entry the following
723 ; conditions are valid:
724 ;       X1 <= X2
725 ;       Y1 <= Y2
726 ;       (X1 >= 0) && (X1 < XRES)
727 ;       (X2 >= 0) && (X2 < XRES)
728 ;       (Y1 >= 0) && (Y1 < YRES)
729 ;       (Y2 >= 0) && (Y2 < YRES)
730 ;
731 ; Must set an error code: NO
732 ;
733
734 ; Note: This function needs optimization. It's just a cheap translation of
735 ; the original C wrapper and could be written much smaller (besides that,
736 ; calling LINE is not a good idea either).
737
738 BAR:    lda     Y2
739         sta     Y2SAVE
740         lda     Y2+1
741         sta     Y2SAVE+1
742
743         lda     X2
744         sta     X2SAVE
745         lda     X2+1
746         sta     X2SAVE+1
747
748         lda     Y1
749         sta     Y1SAVE
750         lda     Y1+1
751         sta     Y1SAVE+1
752
753         lda     X1
754         sta     X1SAVE
755         lda     X1+1
756         sta     X1SAVE+1
757
758 @L1:    lda     Y1
759         sta     Y2
760         lda     Y1+1
761         sta     Y2+1
762         jsr     LINE
763
764         lda     Y1SAVE
765         cmp     Y2SAVE
766         bne     @L2
767         lda     Y1SAVE
768         cmp     Y2SAVE
769         beq     @L4
770
771 @L2:    inc     Y1SAVE
772         bne     @L3
773         inc     Y1SAVE+1
774
775 @L3:    lda     Y1SAVE
776         sta     Y1
777         lda     Y1SAVE+1
778         sta     Y1+1
779
780         lda     X1SAVE
781         sta     X1
782         lda     X1SAVE+1
783         sta     X1+1
784
785         lda     X2SAVE
786         sta     X2
787         lda     X2SAVE+1
788         sta     X2+1
789         jmp     @L1
790
791 @L4:    rts
792
793
794 ; ------------------------------------------------------------------------
795 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
796 ; direction is passend in X/Y, the text direction is passed in A.
797 ;
798 ; Must set an error code: NO
799 ;
800
801 TEXTSTYLE:
802         stx     TEXTMAGX
803         sty     TEXTMAGY
804         sta     TEXTDIR
805         rts
806
807
808 ; ------------------------------------------------------------------------
809 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
810 ; current text style. The text to output is given as a zero terminated
811 ; string with address in ptr3.
812 ;
813 ; Must set an error code: NO
814 ;
815
816 OUTTEXT:
817
818 ; Calculate a pointer to the representation of the character in the
819 ; character ROM
820
821         ldx     #((>(CHARROM + $0800)) >> 3)
822         ldy     #0
823         lda     (TEXT),y
824         bmi     @L1
825         ldx     #((>(CHARROM + $0000)) >> 3)
826 @L1:    stx     ptr4+1
827         asl     a
828         rol     ptr4+1
829         asl     a
830         rol     ptr4+1
831         asl     a
832         rol     ptr4+1
833         sta     ptr4
834
835
836
837
838
839         rts
840
841 ; ------------------------------------------------------------------------
842 ; Calculate all variables to plot the pixel at X1/Y1.
843
844 CALC:   lda     Y1
845         sta     TEMP2
846         and     #7
847         tay
848         lda     Y1+1
849         lsr                     ; Neg is possible
850         ror     TEMP2
851         lsr
852         ror     TEMP2
853         lsr
854         ror     TEMP2
855
856         lda     #00
857         sta     POINT
858         lda     TEMP2
859         cmp     #$80
860         ror
861         ror     POINT
862         cmp     #$80
863         ror
864         ror     POINT           ; row*64
865         adc     TEMP2           ; +row*256
866         clc
867         adc     #>VBASE         ; +bitmap base
868         sta     POINT+1
869
870         lda     X1
871         tax
872         and     #$F8
873         clc
874         adc     POINT           ; +(X AND #$F8)
875         sta     POINT
876         lda     X1+1
877         adc     POINT+1
878         sta     POINT+1
879         txa
880         and     #7
881         tax
882         rts