]> git.sur5r.net Git - cc65/blob - libsrc/c64/tgi/c64-hi.s
NMI friendly c64-hi
[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         iny
276         bne     @L1
277 @L2:    sta     VBASE+$1F00,y
278         iny
279         cpy     #$40
280         bne     @L2
281         rts
282
283 ; ------------------------------------------------------------------------
284 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
285 ; The page number is already checked to be valid by the graphics kernel.
286 ;
287 ; Must set an error code: NO (will only be called if page ok)
288 ;
289
290 SETVIEWPAGE:
291 ;       rts                     ; fall through
292
293 ; ------------------------------------------------------------------------
294 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
295 ; The page number is already checked to be valid by the graphics kernel.
296 ;
297 ; Must set an error code: NO (will only be called if page ok)
298 ;
299
300 SETDRAWPAGE:
301         rts
302
303 ; ------------------------------------------------------------------------
304 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
305 ; to be in a valid range (0..maxcolor-1).
306 ;
307 ; Must set an error code: NO (will only be called if color ok)
308 ;
309
310 SETCOLOR:
311         tax
312         beq     @L1
313         lda     #$FF
314 @L1:    sta     BITMASK
315         rts
316
317 ; ------------------------------------------------------------------------
318 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
319 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
320 ; are not supported
321 ;
322 ; Must set an error code: YES
323 ;
324
325 SETPALETTE:
326         ldy     #PALETTESIZE - 1
327 @L1:    lda     (ptr1),y        ; Copy the palette
328         and     #$0F            ; Make a valid color
329         sta     PALETTE,y
330         dey
331         bpl     @L1
332
333 ; Get the color entries from the palette
334
335         lda     PALETTE+1       ; Foreground color
336         asl     a
337         asl     a
338         asl     a
339         asl     a
340         ora     PALETTE         ; Background color
341         tax
342
343 ; Initialize the color map with the new color settings (it is below the
344 ; I/O area)
345
346         ldy     #$00
347         sei
348         lda     $01             ; Get ROM config
349         pha                     ; Save it
350         and     #%11111100      ; Clear bit 0 and 1
351         sta     $01
352         txa                     ; Load color code
353 @L2:    sta     CBASE+$0000,y
354         sta     CBASE+$0100,y
355         sta     CBASE+$0200,y
356         sta     CBASE+$02e8,y
357         iny
358         bne     @L2
359         pla
360         sta     $01
361         cli
362
363 ; Done, reset the error code
364
365         lda     #TGI_ERR_OK
366         sta     ERROR
367         rts
368
369 ; ------------------------------------------------------------------------
370 ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
371 ; set the palette should return the default palette here, so there's no
372 ; way for this function to fail.
373 ;
374 ; Must set an error code: NO
375 ;
376
377 GETPALETTE:
378         lda     #<PALETTE
379         ldx     #>PALETTE
380         rts
381
382 ; ------------------------------------------------------------------------
383 ; GETDEFPALETTE: Return the default palette for the driver in A/X. All
384 ; drivers should return something reasonable here, even drivers that don't
385 ; support palettes, otherwise the caller has no way to determine the colors
386 ; of the (not changeable) palette.
387 ;
388 ; Must set an error code: NO (all drivers must have a default palette)
389 ;
390
391 GETDEFPALETTE:
392         lda     #<DEFPALETTE
393         ldx     #>DEFPALETTE
394         rts
395
396 ; ------------------------------------------------------------------------
397 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
398 ; color. The coordinates passed to this function are never outside the
399 ; visible screen area, so there is no need for clipping inside this function.
400 ;
401 ; Must set an error code: NO
402 ;
403
404 SETPIXEL:
405         jsr     CALC            ; Calculate coordinates
406
407         sei                     ; Get underneath ROM
408         lda     $01
409         pha
410         lda     #$34
411         sta     $01
412
413         lda     (POINT),Y
414         eor     BITMASK
415         and     BITTAB,X
416         eor     (POINT),Y
417         sta     (POINT),Y
418
419         pla
420         sta     $01
421         cli
422
423 @L9:    rts
424
425 ; ------------------------------------------------------------------------
426 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
427 ; coordinates passed to this function are never outside the visible screen
428 ; area, so there is no need for clipping inside this function.
429
430
431 GETPIXEL:
432         jsr     CALC            ; Calculate coordinates
433
434         sei                     ; Get underneath ROM
435         lda     $01
436         pha
437         lda     #$34
438         sta     $01
439
440         lda     (POINT),Y
441         ldy     #$00
442         and     BITTAB,X
443         beq     @L1
444         iny
445
446 @L1:    pla
447         sta     $01
448         cli
449
450         tya                     ; Get color value into A
451         ldx     #$00            ; Clear high byte
452         rts
453
454 ; ------------------------------------------------------------------------
455 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
456 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
457 ;
458 ; X1,X2 etc. are set up above (x2=LINNUM in particular)
459 ; Format is LINE x2,y2,x1,y1
460 ;
461 ; Must set an error code: NO
462 ;
463
464 LINE:
465
466 @CHECK: lda     X2           ;Make sure x1<x2
467         sec
468         sbc     X1
469         tax
470         lda     X2+1
471         sbc     X1+1
472         bpl     @CONT
473         lda     Y2           ;If not, swap P1 and P2
474         ldy     Y1
475         sta     Y1
476         sty     Y2
477         lda     Y2+1
478         ldy     Y1+1
479         sta     Y1+1
480         sty     Y2+1
481         lda     X1
482         ldy     X2
483         sty     X1
484         sta     X2
485         lda     X2+1
486         ldy     X1+1
487         sta     X1+1
488         sty     X2+1
489         bcc     @CHECK
490
491 @CONT:  sta     DX+1
492         stx     DX
493
494         ldx     #$C8         ;INY
495         lda     Y2           ;Calculate dy
496         sec
497         sbc     Y1
498         tay
499         lda     Y2+1
500         sbc     Y1+1
501         bpl     @DYPOS       ;Is y2>=y1?
502         lda     Y1           ;Otherwise dy=y1-y2
503         sec
504         sbc     Y2
505         tay
506         ldx     #$88         ;DEY
507
508 @DYPOS: sty     DY              ; 8-bit DY -- FIX ME?
509         stx     YINCDEC
510         stx     XINCDEC
511
512         jsr     CALC            ; Set up .X, .Y, and POINT
513         lda     BITCHUNK,X
514         sta     OLDCHUNK
515         sta     CHUNK
516
517         sei                     ; Get underneath ROM
518         lda     #$34
519         sta     $01
520
521         ldx     DY
522         cpx     DX           ;Who's bigger: dy or dx?
523         bcc     STEPINX      ;If dx, then...
524         lda     DX+1
525         bne     STEPINX
526
527 ;
528 ; Big steps in Y
529 ;
530 ;   To simplify my life, just use PLOT to plot points.
531 ;
532 ;   No more!
533 ;   Added special plotting routine -- cool!
534 ;
535 ;   X is now counter, Y is y-coordinate
536 ;
537 ; On entry, X=DY=number of loop iterations, and Y=
538 ;   Y1 AND #$07
539 STEPINY:
540         lda     #00
541         sta     OLDCHUNK     ;So plotting routine will work right
542         lda     CHUNK
543         lsr                  ;Strip the bit
544         eor     CHUNK
545         sta     CHUNK
546         txa
547         bne     @CONT        ;If dy=0 it's just a point
548         inx
549 @CONT:  lsr                  ;Init counter to dy/2
550 ;
551 ; Main loop
552 ;
553 YLOOP:  sta     TEMP
554
555         lda     (POINT),y
556         eor     BITMASK
557         and     CHUNK
558         eor     (POINT),y
559         sta     (POINT),y
560 YINCDEC:
561         iny                  ;Advance Y coordinate
562         cpy     #8
563         bcc     @CONT        ;No prob if Y=0..7
564         jsr     FIXY
565 @CONT:  lda     TEMP         ;Restore A
566         sec
567         sbc     DX
568         bcc     YFIXX
569 YCONT:  dex                  ;X is counter
570         bne     YLOOP
571 YCONT2: lda     (POINT),y    ;Plot endpoint
572         eor     BITMASK
573         and     CHUNK
574         eor     (POINT),y
575         sta     (POINT),y
576         lda     #$36
577         sta     $01
578         cli
579         rts
580
581 YFIXX:                    ;x=x+1
582         adc     DY
583         lsr     CHUNK
584         bne     YCONT        ;If we pass a column boundary...
585         ror     CHUNK        ;then reset CHUNK to $80
586         sta     TEMP2
587         lda     POINT        ;And add 8 to POINT
588         adc     #8
589         sta     POINT
590         bcc     @CONT
591         inc     POINT+1
592 @CONT:  lda     TEMP2
593         dex
594         bne     YLOOP
595         beq     YCONT2
596
597 ;
598 ; Big steps in X direction
599 ;
600 ; On entry, X=DY=number of loop iterations, and Y=
601 ;   Y1 AND #$07
602
603 .bss
604 COUNTHI:
605         .byte   $00       ;Temporary counter
606                           ;only used once
607 .code
608 STEPINX:
609         ldx     DX
610         lda     DX+1
611         sta     COUNTHI
612         cmp     #$80
613         ror                  ;Need bit for initialization
614         sta     Y1           ;High byte of counter
615         txa
616         bne     @CONT        ;Could be $100
617         dec     COUNTHI
618 @CONT:  ror
619 ;
620 ; Main loop
621 ;
622 XLOOP:  lsr     CHUNK
623         beq     XFIXC        ;If we pass a column boundary...
624 XCONT1: sbc     DY
625         bcc     XFIXY        ;Time to step in Y?
626 XCONT2: dex
627         bne     XLOOP
628         dec     COUNTHI      ;High bits set?
629         bpl     XLOOP
630
631         lsr     CHUNK        ;Advance to last point
632         jsr     LINEPLOT     ;Plot the last chunk
633 EXIT:   lda     #$36
634         sta     $01
635         cli
636         rts
637 ;
638 ; CHUNK has passed a column, so plot and increment pointer
639 ; and fix up CHUNK, OLDCHUNK.
640 ;
641 XFIXC:  sta     TEMP
642         jsr     LINEPLOT
643         lda     #$FF
644         sta     CHUNK
645         sta     OLDCHUNK
646         lda     POINT
647         clc
648         adc     #8
649         sta     POINT
650         lda     TEMP
651         bcc     XCONT1
652         inc     POINT+1
653         jmp     XCONT1
654 ;
655 ; Check to make sure there isn't a high bit, plot chunk,
656 ; and update Y-coordinate.
657 ;
658 XFIXY:  dec     Y1           ;Maybe high bit set
659         bpl     XCONT2
660         adc     DX
661         sta     TEMP
662         lda     DX+1
663         adc     #$FF         ;Hi byte
664         sta     Y1
665
666         jsr     LINEPLOT     ;Plot chunk
667         lda     CHUNK
668         sta     OLDCHUNK
669
670         lda     TEMP
671 XINCDEC:
672         iny                  ;Y-coord
673         cpy     #8           ;0..7 is ok
674         bcc     XCONT2
675         sta     TEMP
676         jsr     FIXY
677         lda     TEMP
678         jmp     XCONT2
679
680 ;
681 ; Subroutine to plot chunks/points (to save a little
682 ; room, gray hair, etc.)
683 ;
684 LINEPLOT:                       ; Plot the line chunk
685         lda     (POINT),Y
686         eor     BITMASK
687         ora     CHUNK
688         and     OLDCHUNK
689         eor     CHUNK
690         eor     (POINT),Y
691         sta     (POINT),Y
692         rts
693
694 ;
695 ; Subroutine to fix up pointer when Y decreases through
696 ; zero or increases through 7.
697 ;
698 FIXY:   cpy     #255         ;Y=255 or Y=8
699         beq     @DECPTR
700
701 @INCPTR:                     ;Add 320 to pointer
702         ldy     #0           ;Y increased through 7
703         lda     POINT
704         adc     #<320
705         sta     POINT
706         lda     POINT+1
707         adc     #>320
708         sta     POINT+1
709         rts
710
711 @DECPTR:                     ;Okay, subtract 320 then
712         ldy     #7           ;Y decreased through 0
713         lda     POINT
714         sec
715         sbc     #<320
716         sta     POINT
717         lda     POINT+1
718         sbc     #>320
719         sta     POINT+1
720         rts
721
722 ; ------------------------------------------------------------------------
723 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
724 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
725 ; Contrary to most other functions, the graphics kernel will sort and clip
726 ; the coordinates before calling the driver, so on entry the following
727 ; conditions are valid:
728 ;       X1 <= X2
729 ;       Y1 <= Y2
730 ;       (X1 >= 0) && (X1 < XRES)
731 ;       (X2 >= 0) && (X2 < XRES)
732 ;       (Y1 >= 0) && (Y1 < YRES)
733 ;       (Y2 >= 0) && (Y2 < YRES)
734 ;
735 ; Must set an error code: NO
736 ;
737
738 ; Note: This function needs optimization. It's just a cheap translation of
739 ; the original C wrapper and could be written much smaller (besides that,
740 ; calling LINE is not a good idea either).
741
742 BAR:    lda     Y2
743         sta     Y2SAVE
744         lda     Y2+1
745         sta     Y2SAVE+1
746
747         lda     X2
748         sta     X2SAVE
749         lda     X2+1
750         sta     X2SAVE+1
751
752         lda     Y1
753         sta     Y1SAVE
754         lda     Y1+1
755         sta     Y1SAVE+1
756
757         lda     X1
758         sta     X1SAVE
759         lda     X1+1
760         sta     X1SAVE+1
761
762 @L1:    lda     Y1
763         sta     Y2
764         lda     Y1+1
765         sta     Y2+1
766         jsr     LINE
767
768         lda     Y1SAVE
769         cmp     Y2SAVE
770         bne     @L2
771         lda     Y1SAVE
772         cmp     Y2SAVE
773         beq     @L4
774
775 @L2:    inc     Y1SAVE
776         bne     @L3
777         inc     Y1SAVE+1
778
779 @L3:    lda     Y1SAVE
780         sta     Y1
781         lda     Y1SAVE+1
782         sta     Y1+1
783
784         lda     X1SAVE
785         sta     X1
786         lda     X1SAVE+1
787         sta     X1+1
788
789         lda     X2SAVE
790         sta     X2
791         lda     X2SAVE+1
792         sta     X2+1
793         jmp     @L1
794
795 @L4:    rts
796
797
798 ; ------------------------------------------------------------------------
799 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
800 ; direction is passend in X/Y, the text direction is passed in A.
801 ;
802 ; Must set an error code: NO
803 ;
804
805 TEXTSTYLE:
806         stx     TEXTMAGX
807         sty     TEXTMAGY
808         sta     TEXTDIR
809         rts
810
811
812 ; ------------------------------------------------------------------------
813 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
814 ; current text style. The text to output is given as a zero terminated
815 ; string with address in ptr3.
816 ;
817 ; Must set an error code: NO
818 ;
819
820 OUTTEXT:
821
822 ; Calculate a pointer to the representation of the character in the
823 ; character ROM
824
825         ldx     #((>(CHARROM + $0800)) >> 3)
826         ldy     #0
827         lda     (TEXT),y
828         bmi     @L1
829         ldx     #((>(CHARROM + $0000)) >> 3)
830 @L1:    stx     ptr4+1
831         asl     a
832         rol     ptr4+1
833         asl     a
834         rol     ptr4+1
835         asl     a
836         rol     ptr4+1
837         sta     ptr4
838
839
840
841
842
843         rts
844
845 ; ------------------------------------------------------------------------
846 ; Calculate all variables to plot the pixel at X1/Y1.
847
848 CALC:   lda     Y1
849         sta     TEMP2
850         and     #7
851         tay
852         lda     Y1+1
853         lsr                     ; Neg is possible
854         ror     TEMP2
855         lsr
856         ror     TEMP2
857         lsr
858         ror     TEMP2
859
860         lda     #00
861         sta     POINT
862         lda     TEMP2
863         cmp     #$80
864         ror
865         ror     POINT
866         cmp     #$80
867         ror
868         ror     POINT           ; row*64
869         adc     TEMP2           ; +row*256
870         clc
871         adc     #>VBASE         ; +bitmap base
872         sta     POINT+1
873
874         lda     X1
875         tax
876         and     #$F8
877         clc
878         adc     POINT           ; +(X AND #$F8)
879         sta     POINT
880         lda     X1+1
881         adc     POINT+1
882         sta     POINT+1
883         txa
884         and     #7
885         tax
886         rts