]> git.sur5r.net Git - cc65/blob - libsrc/c64/tgi/c64-hi.s
Removed unused label
[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         bne     @CONT        ;If dy=0 it's just a point
545         inx
546 @CONT:  lsr                  ;Init counter to dy/2
547 ;
548 ; Main loop
549 ;
550 YLOOP:  sta     TEMP
551
552         lda     (POINT),y
553         eor     BITMASK
554         and     CHUNK
555         eor     (POINT),y
556         sta     (POINT),y
557 YINCDEC:
558         iny                  ;Advance Y coordinate
559         cpy     #8
560         bcc     @CONT        ;No prob if Y=0..7
561         jsr     FIXY
562 @CONT:  lda     TEMP         ;Restore A
563         sec
564         sbc     DX
565         bcc     YFIXX
566 YCONT:  dex                  ;X is counter
567         bne     YLOOP
568 YCONT2: lda     (POINT),y    ;Plot endpoint
569         eor     BITMASK
570         and     CHUNK
571         eor     (POINT),y
572         sta     (POINT),y
573         lda     #$36
574         sta     $01
575         cli
576         rts
577
578 YFIXX:                    ;x=x+1
579         adc     DY
580         lsr     CHUNK
581         bne     YCONT        ;If we pass a column boundary...
582         ror     CHUNK        ;then reset CHUNK to $80
583         sta     TEMP2
584         lda     POINT        ;And add 8 to POINT
585         adc     #8
586         sta     POINT
587         bcc     @CONT
588         inc     POINT+1
589 @CONT:  lda     TEMP2
590         dex
591         bne     YLOOP
592         beq     YCONT2
593
594 ;
595 ; Big steps in X direction
596 ;
597 ; On entry, X=DY=number of loop iterations, and Y=
598 ;   Y1 AND #$07
599
600 .bss
601 COUNTHI:
602         .byte   $00       ;Temporary counter
603                           ;only used once
604 .code
605 STEPINX:
606         ldx     DX
607         lda     DX+1
608         sta     COUNTHI
609         cmp     #$80
610         ror                  ;Need bit for initialization
611         sta     Y1           ;High byte of counter
612         txa
613         bne     @CONT        ;Could be $100
614         dec     COUNTHI
615 @CONT:  ror
616 ;
617 ; Main loop
618 ;
619 XLOOP:  lsr     CHUNK
620         beq     XFIXC        ;If we pass a column boundary...
621 XCONT1: sbc     DY
622         bcc     XFIXY        ;Time to step in Y?
623 XCONT2: dex
624         bne     XLOOP
625         dec     COUNTHI      ;High bits set?
626         bpl     XLOOP
627
628         lsr     CHUNK        ;Advance to last point
629         jsr     LINEPLOT     ;Plot the last chunk
630         lda     #$36
631         sta     $01
632         cli
633         rts
634 ;
635 ; CHUNK has passed a column, so plot and increment pointer
636 ; and fix up CHUNK, OLDCHUNK.
637 ;
638 XFIXC:  sta     TEMP
639         jsr     LINEPLOT
640         lda     #$FF
641         sta     CHUNK
642         sta     OLDCHUNK
643         lda     POINT
644         clc
645         adc     #8
646         sta     POINT
647         lda     TEMP
648         bcc     XCONT1
649         inc     POINT+1
650         jmp     XCONT1
651 ;
652 ; Check to make sure there isn't a high bit, plot chunk,
653 ; and update Y-coordinate.
654 ;
655 XFIXY:  dec     Y1           ;Maybe high bit set
656         bpl     XCONT2
657         adc     DX
658         sta     TEMP
659         lda     DX+1
660         adc     #$FF         ;Hi byte
661         sta     Y1
662
663         jsr     LINEPLOT     ;Plot chunk
664         lda     CHUNK
665         sta     OLDCHUNK
666
667         lda     TEMP
668 XINCDEC:
669         iny                  ;Y-coord
670         cpy     #8           ;0..7 is ok
671         bcc     XCONT2
672         sta     TEMP
673         jsr     FIXY
674         lda     TEMP
675         jmp     XCONT2
676
677 ;
678 ; Subroutine to plot chunks/points (to save a little
679 ; room, gray hair, etc.)
680 ;
681 LINEPLOT:                       ; Plot the line chunk
682         lda     (POINT),Y
683         eor     BITMASK
684         ora     CHUNK
685         and     OLDCHUNK
686         eor     CHUNK
687         eor     (POINT),Y
688         sta     (POINT),Y
689         rts
690
691 ;
692 ; Subroutine to fix up pointer when Y decreases through
693 ; zero or increases through 7.
694 ;
695 FIXY:   cpy     #255         ;Y=255 or Y=8
696         beq     @DECPTR
697
698 @INCPTR:                     ;Add 320 to pointer
699         ldy     #0           ;Y increased through 7
700         lda     POINT
701         adc     #<320
702         sta     POINT
703         lda     POINT+1
704         adc     #>320
705         sta     POINT+1
706         rts
707
708 @DECPTR:                     ;Okay, subtract 320 then
709         ldy     #7           ;Y decreased through 0
710         lda     POINT
711         sec
712         sbc     #<320
713         sta     POINT
714         lda     POINT+1
715         sbc     #>320
716         sta     POINT+1
717         rts
718
719 ; ------------------------------------------------------------------------
720 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
721 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
722 ; Contrary to most other functions, the graphics kernel will sort and clip
723 ; the coordinates before calling the driver, so on entry the following
724 ; conditions are valid:
725 ;       X1 <= X2
726 ;       Y1 <= Y2
727 ;       (X1 >= 0) && (X1 < XRES)
728 ;       (X2 >= 0) && (X2 < XRES)
729 ;       (Y1 >= 0) && (Y1 < YRES)
730 ;       (Y2 >= 0) && (Y2 < YRES)
731 ;
732 ; Must set an error code: NO
733 ;
734
735 ; Note: This function needs optimization. It's just a cheap translation of
736 ; the original C wrapper and could be written much smaller (besides that,
737 ; calling LINE is not a good idea either).
738
739 BAR:    lda     Y2
740         sta     Y2SAVE
741         lda     Y2+1
742         sta     Y2SAVE+1
743
744         lda     X2
745         sta     X2SAVE
746         lda     X2+1
747         sta     X2SAVE+1
748
749         lda     Y1
750         sta     Y1SAVE
751         lda     Y1+1
752         sta     Y1SAVE+1
753
754         lda     X1
755         sta     X1SAVE
756         lda     X1+1
757         sta     X1SAVE+1
758
759 @L1:    lda     Y1
760         sta     Y2
761         lda     Y1+1
762         sta     Y2+1
763         jsr     LINE
764
765         lda     Y1SAVE
766         cmp     Y2SAVE
767         bne     @L2
768         lda     Y1SAVE
769         cmp     Y2SAVE
770         beq     @L4
771
772 @L2:    inc     Y1SAVE
773         bne     @L3
774         inc     Y1SAVE+1
775
776 @L3:    lda     Y1SAVE
777         sta     Y1
778         lda     Y1SAVE+1
779         sta     Y1+1
780
781         lda     X1SAVE
782         sta     X1
783         lda     X1SAVE+1
784         sta     X1+1
785
786         lda     X2SAVE
787         sta     X2
788         lda     X2SAVE+1
789         sta     X2+1
790         jmp     @L1
791
792 @L4:    rts
793
794
795 ; ------------------------------------------------------------------------
796 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
797 ; direction is passend in X/Y, the text direction is passed in A.
798 ;
799 ; Must set an error code: NO
800 ;
801
802 TEXTSTYLE:
803         stx     TEXTMAGX
804         sty     TEXTMAGY
805         sta     TEXTDIR
806         rts
807
808
809 ; ------------------------------------------------------------------------
810 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
811 ; current text style. The text to output is given as a zero terminated
812 ; string with address in ptr3.
813 ;
814 ; Must set an error code: NO
815 ;
816
817 OUTTEXT:
818
819 ; Calculate a pointer to the representation of the character in the
820 ; character ROM
821
822         ldx     #((>(CHARROM + $0800)) >> 3)
823         ldy     #0
824         lda     (TEXT),y
825         bmi     @L1
826         ldx     #((>(CHARROM + $0000)) >> 3)
827 @L1:    stx     ptr4+1
828         asl     a
829         rol     ptr4+1
830         asl     a
831         rol     ptr4+1
832         asl     a
833         rol     ptr4+1
834         sta     ptr4
835
836
837
838
839
840         rts
841
842 ; ------------------------------------------------------------------------
843 ; Calculate all variables to plot the pixel at X1/Y1.
844
845 CALC:   lda     Y1
846         sta     TEMP2
847         and     #7
848         tay
849         lda     Y1+1
850         lsr                     ; Neg is possible
851         ror     TEMP2
852         lsr
853         ror     TEMP2
854         lsr
855         ror     TEMP2
856
857         lda     #00
858         sta     POINT
859         lda     TEMP2
860         cmp     #$80
861         ror
862         ror     POINT
863         cmp     #$80
864         ror
865         ror     POINT           ; row*64
866         adc     TEMP2           ; +row*256
867         clc
868         adc     #>VBASE         ; +bitmap base
869         sta     POINT+1
870
871         lda     X1
872         tax
873         and     #$F8
874         clc
875         adc     POINT           ; +(X AND #$F8)
876         sta     POINT
877         lda     X1+1
878         adc     POINT+1
879         sta     POINT+1
880         txa
881         and     #7
882         tax
883         rts