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