]> git.sur5r.net Git - cc65/blob - libsrc/c128/c128-640-200-2.s
removed some duplicated GEOS conio stuff
[cc65] / libsrc / c128 / c128-640-200-2.s
1 ;
2 ; Graphics driver for the 640x200x2 mode on the C128 VDC
3 ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
4 ; 23.12.2002
5 ;
6 ; NOTES:
7 ; For any smart monkey that will try to optimize this: PLEASE do tests on real VDC,
8 ; not only VICE.
9 ;
10 ; Only DONE routine contains C128-mode specific stuff, everything else will work in
11 ; C64-mode of C128 (C64 needs full VDC init then).
12 ;
13 ; With special initialization and CALC we can get 320x200 double-pixel mode.
14 ;
15 ; Color translation values for BROWN and GRAY3 are obviously wrong, they could
16 ; be replaced by equiv. of ORANGE and GRAY2 but this would give only 14 of 16 colors available.
17 ;
18 ; Register 25 ($19) is said to require different value for VDC v1, but I couldn't find what
19 ; it should be.
20
21         .include        "zeropage.inc"
22
23         .include        "tgi-kernel.inc"
24         .include        "tgi-mode.inc"
25         .include        "tgi-error.inc"
26
27
28         .macpack        generic
29
30 ; ------------------------------------------------------------------------
31 ; Constants
32
33 VDC_ADDR_REG      = $D600                 ; VDC address
34 VDC_DATA_REG      = $D601                 ; VDC data
35
36 VDC_DSP_HI        = 12                    ; registers used
37 VDC_DSP_LO        = 13
38 VDC_DATA_HI       = 18
39 VDC_DATA_LO       = 19
40 VDC_VSCROLL       = 24
41 VDC_HSCROLL       = 25
42 VDC_COLORS        = 26
43 VDC_CSET          = 28
44 VDC_COUNT         = 30
45 VDC_DATA          = 31
46
47 ; ------------------------------------------------------------------------
48 ; Header. Includes jump table and constants.
49
50 .segment        "JUMPTABLE"
51
52 ; First part of the header is a structure that has a magic and defines the
53 ; capabilities of the driver
54
55         .byte   $74, $67, $69           ; "tgi"
56         .byte   $00                     ; TGI version number
57 xres:   .word   640                     ; X resolution
58 yres:   .word   200                     ; Y resolution
59         .byte   2                       ; Number of drawing colors
60 pages:  .byte   1                       ; Number of screens available
61         .byte   8                       ; System font X size
62         .byte   8                       ; System font Y size
63         .res    4, $00                  ; Reserved for future extensions
64
65 ; Next comes the jump table. Currently all entries must be valid and may point
66 ; to an RTS for test versions (function not implemented). A future version may
67 ; allow for emulation: In this case the vector will be zero. Emulation means
68 ; that the graphics kernel will emulate the function by using lower level
69 ; primitives - for example ploting a line by using calls to SETPIXEL.
70
71         .word   INSTALL
72         .word   UNINSTALL
73         .word   INIT
74         .word   DONE
75         .word   GETERROR
76         .word   CONTROL
77         .word   CLEAR
78         .word   SETVIEWPAGE
79         .word   SETDRAWPAGE
80         .word   SETCOLOR
81         .word   SETPALETTE
82         .word   GETPALETTE
83         .word   GETDEFPALETTE
84         .word   SETPIXEL
85         .word   GETPIXEL
86         .word   HORLINE
87         .word   LINE
88         .word   BAR
89         .word   CIRCLE
90         .word   TEXTSTYLE
91         .word   OUTTEXT
92
93 ; ------------------------------------------------------------------------
94 ; Data.
95
96 ; Variables mapped to the zero page segment variables. Some of these are
97 ; used for passing parameters to the driver.
98
99 X1              = ptr1
100 Y1              = ptr2
101 X2              = ptr3
102 Y2              = ptr4
103 RADIUS          = tmp1
104
105 ADDR            = tmp1          ; (2)   CALC
106 TEMP            = tmp3          ;       CALC icmp
107 TEMP2           = tmp4          ;       icmp
108 TEMP3           = sreg          ;       LINE
109 TEMP4           = sreg+1        ;       LINE
110
111 ; Line routine stuff (must be on zpage)
112 PB              = ptr3          ; (2)   LINE
113 UB              = ptr4          ; (2)   LINE
114 ERR             = regsave       ; (2)   LINE
115 NX              = regsave+2     ; (2)   LINE
116 ; Circle stuff
117 XX              = ptr3          ; (2)   CIRCLE
118 YY              = ptr4          ; (2)   CIRCLE
119 MaxO            = sreg          ; (overwritten by TEMP3+TEMP4, but restored from OG/OU anyway)
120 XS              = regsave       ; (2)   CIRCLE
121 YS              = regsave+2     ; (2)   CIRCLE
122
123 ; Absolute variables used in the code
124
125 .bss
126
127 SCRBASE:        .res    1       ; High byte of screen base
128
129 ERROR:          .res    1       ; Error code
130 PALETTE:        .res    2       ; The current palette
131
132 BITMASK:        .res    1       ; $00 = clear, $FF = set pixels
133
134 OLDCOLOR:       .res    1       ; colors before entering gfx mode
135
136 ; Line routine stuff (combined with CIRCLE to save space)
137
138 OGora:
139 COUNT:           .res   2
140 OUkos:
141 NY:              .res   2
142 Y3:
143 DX:              .res   1
144 DY:              .res   1
145 AY:              .res   1
146
147 ; Text output stuff
148 TEXTMAGX:       .res    1
149 TEXTMAGY:       .res    1
150 TEXTDIR:        .res    1
151
152 ; Constants and tables
153
154 .rodata
155
156 DEFPALETTE:     .byte   $00, $0f        ; White on black
157 PALETTESIZE     = * - DEFPALETTE
158
159 BITTAB:         .byte   $80,$40,$20,$10,$08,$04,$02,$01
160
161 BITMASKL:       .byte   %11111111, %01111111, %00111111, %00011111
162                 .byte   %00001111, %00000111, %00000011, %00000001
163
164 BITMASKR:       .byte   %10000000, %11000000, %11100000, %11110000
165                 .byte   %11111000, %11111100, %11111110, %11111111
166
167 ; color translation table (indexed by VIC color)
168 COLTRANS:       .byte $00, $0f, $08, $06, $0a, $04, $02, $0c
169                 .byte $0d, $0b, $09, $01, $0e, $05, $03, $07
170                 ; colors BROWN and GRAY3 are wrong
171
172 ; VDC initialization table (reg),(val),...,$ff
173 InitVDCTab:
174                 .byte VDC_DSP_HI, 0             ; viewpage 0 as default
175                 .byte VDC_DSP_LO, 0
176                 .byte VDC_HSCROLL, $87
177                 .byte $ff
178
179 SCN80CLR:       .byte 27,88,147,27,88,0
180
181 .code
182
183 ; ------------------------------------------------------------------------
184 ; INSTALL routine. Is called after the driver is loaded into memory. May
185 ; initialize anything that has to be done just once. Is probably empty
186 ; most of the time.
187 ;
188 ; Must set an error code: NO
189 ;
190
191 INSTALL:
192         ; check for VDC version and update register $19 value
193
194         ; check for VDC ram size and update number of available screens
195
196         ldx     #VDC_CSET       ; determine size of RAM...
197         jsr     VDCReadReg
198         sta     tmp1
199         ora     #%00010000
200         jsr     VDCWriteReg     ; turn on 64k
201
202         jsr     settestadr1     ; save original value of test byte
203         jsr     VDCReadByte
204         sta     tmp2
205
206         lda     #$55            ; write $55 here
207         ldy     #ptr1
208         jsr     test64k         ; read it here and there
209         lda     #$aa            ; write $aa here
210         ldy     #ptr2
211         jsr     test64k         ; read it here and there
212
213         jsr     settestadr1
214         lda     tmp2
215         jsr     VDCWriteByte    ; restore original value of test byte
216
217         lda     ptr1            ; do bytes match?
218         cmp     ptr1+1
219         bne     @have64k
220         lda     ptr2
221         cmp     ptr2+1
222         bne     @have64k
223
224         ldx     #VDC_CSET
225         lda     tmp1
226         jsr     VDCWriteReg     ; restore 16/64k flag
227         jmp     @endok          ; and leave default values for 16k
228
229 @have64k:
230         lda     #4
231         sta     pages
232 @endok:
233         lda     #0
234         sta     SCRBASE         ; draw page 0 as default
235         rts
236
237 test64k:
238         sta     tmp1
239         sty     ptr3
240         lda     #0
241         sta     ptr3+1
242         jsr     settestadr1
243         lda     tmp1
244         jsr     VDCWriteByte            ; write $55
245         jsr     settestadr1
246         jsr     VDCReadByte             ; read here
247         pha
248         jsr     settestadr2
249         jsr     VDCReadByte             ; and there
250         ldy     #1
251         sta     (ptr3),y
252         pla
253         dey
254         sta     (ptr3),y
255         rts
256
257 settestadr1:
258         ldy     #$02                    ; test page 2 (here)
259         .byte   $2c
260 settestadr2:
261         ldy     #$42                    ; or page 64+2 (there)
262         lda     #0
263         jmp     VDCSetSourceAddr
264
265 ; ------------------------------------------------------------------------
266 ; UNINSTALL routine. Is called before the driver is removed from memory. May
267 ; clean up anything done by INSTALL but is probably empty most of the time.
268 ;
269 ; Must set an error code: NO
270 ;
271
272 UNINSTALL:
273         rts
274
275
276 ; ------------------------------------------------------------------------
277 ; INIT: Changes an already installed device from text mode to graphics
278 ; mode.
279 ; Note that INIT/DONE may be called multiple times while the driver
280 ; is loaded, while INSTALL is only called once, so any code that is needed
281 ; to initializes variables and so on must go here. Setting palette and
282 ; clearing the screen is not needed because this is called by the graphics
283 ; kernel later.
284 ; The graphics kernel will never call INIT when a graphics mode is already
285 ; active, so there is no need to protect against that.
286 ;
287 ; Must set an error code: YES
288 ;
289
290 INIT:
291
292 ; Initialize variables
293
294 @L1:    ldx     #$FF
295         stx     BITMASK
296
297 ; Remeber current color value
298         ldx     #VDC_COLORS
299         jsr     VDCReadReg
300         sta     OLDCOLOR
301
302 ; Switch into graphics mode (set view page 0)
303
304         ldy     #0
305 @L2:    ldx     InitVDCTab,y
306         bmi     @L3
307         iny
308         lda     InitVDCTab,y
309         jsr     VDCWriteReg
310         iny
311         bne     @L2
312 @L3:
313
314 ; Done, reset the error code
315
316         lda     #TGI_ERR_OK
317         sta     ERROR
318         rts
319
320 ; ------------------------------------------------------------------------
321 ; DONE: Will be called to switch the graphics device back into text mode.
322 ; The graphics kernel will never call DONE when no graphics mode is active,
323 ; so there is no need to protect against that.
324 ;
325 ; Must set an error code: YES
326 ;
327
328 DONE:
329         ; This part is C128-mode specific
330         jsr $e179               ; reload character set and setup VDC
331         jsr $ff62
332         lda $d7                 ; in 80-columns?
333         bne @L01
334 @L0:    lda SCN80CLR,y
335         beq @L1
336         jsr $ffd2               ; print \xe,clr,\xe
337         iny
338         bne @L0
339 @L01:   lda #147
340         jsr $ffd2               ; print clr
341 @L1:    lda #0                  ; restore view page
342         ldx #VDC_DSP_HI
343         jsr VDCWriteReg
344         lda OLDCOLOR
345         ldx #VDC_COLORS
346         jsr VDCWriteReg         ; restore color (background)
347         lda #$47
348         ldx #VDC_HSCROLL
349         jsr VDCWriteReg         ; switch to text screen
350 ; fall through to GETERROR in order to clear ERROR status
351
352 ; ------------------------------------------------------------------------
353 ; GETERROR: Return the error code in A and clear it.
354
355 GETERROR:
356         ldx     #TGI_ERR_OK
357         lda     ERROR
358         stx     ERROR
359         rts
360
361 ; ------------------------------------------------------------------------
362 ; CONTROL: Platform/driver specific entry point.
363 ;
364 ; Must set an error code: YES
365 ;
366
367 CONTROL:
368         lda     #TGI_ERR_INV_FUNC
369         sta     ERROR
370         rts
371
372 ; ------------------------------------------------------------------------
373 ; CLEAR: Clears the screen.
374 ;
375 ; Must set an error code: NO
376 ;
377
378 CLEAR:
379         lda     #0
380         ldy     SCRBASE
381         jsr     VDCSetSourceAddr
382         lda     #0
383         ldx     #VDC_VSCROLL
384         jsr     VDCWriteReg                     ; set fill mode
385         lda     #0
386         jsr     VDCWriteByte                    ; put 1rst byte (fill value)
387         ldy     #62                             ; 62 times
388         lda     #0                              ; 256 bytes
389         ldx     #VDC_COUNT
390 @L1:    jsr     VDCWriteReg
391         dey
392         bne     @L1
393         lda     #127
394         jmp     VDCWriteReg                     ; 1+62*256+127=16000=(640*256)/8
395
396 ; ------------------------------------------------------------------------
397 ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n).
398 ; The page number is already checked to be valid by the graphics kernel.
399 ;
400 ; Must set an error code: NO (will only be called if page ok)
401 ;
402
403 SETVIEWPAGE:
404         clc
405         ror
406         ror
407         ror
408         ldx     #VDC_DSP_HI
409         jmp     VDCWriteReg
410
411 ; ------------------------------------------------------------------------
412 ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n).
413 ; The page number is already checked to be valid by the graphics kernel.
414 ;
415 ; Must set an error code: NO (will only be called if page ok)
416 ;
417
418 SETDRAWPAGE:
419         clc
420         ror
421         ror
422         ror
423         sta     SCRBASE
424         rts
425
426 ; ------------------------------------------------------------------------
427 ; SETCOLOR: Set the drawing color (in A). The new color is already checked
428 ; to be in a valid range (0..maxcolor-1).
429 ;
430 ; Must set an error code: NO (will only be called if color ok)
431 ;
432
433 SETCOLOR:
434         tax
435         beq     @L1
436         lda     #$FF
437 @L1:    sta     BITMASK
438         rts
439
440 ; ------------------------------------------------------------------------
441 ; SETPALETTE: Set the palette (not available with all drivers/hardware).
442 ; A pointer to the palette is passed in ptr1. Must set an error if palettes
443 ; are not supported
444 ;
445 ; Must set an error code: YES
446 ;
447
448 SETPALETTE:
449         ldy     #PALETTESIZE - 1
450 @L1:    lda     (ptr1),y        ; Copy the palette
451         and     #$0F            ; Make a valid color
452         sta     PALETTE,y
453         dey
454         bpl     @L1
455
456 ; Get the color entries from the palette
457
458         ldy     PALETTE+1       ; Foreground color
459         lda     COLTRANS,y
460         asl     a
461         asl     a
462         asl     a
463         asl     a
464         ldy     PALETTE         ; Background color
465         ora     COLTRANS,y
466
467         ldx     #VDC_COLORS
468         jmp     VDCWriteReg
469
470 ; ------------------------------------------------------------------------
471 ; GETPALETTE: Return the current palette in A/X. Must return NULL and set an
472 ; error if palettes are not supported.
473 ;
474 ; Must set an error code: YES
475 ;
476
477 GETPALETTE:
478         lda     #<PALETTE
479         ldx     #>PALETTE
480         rts
481
482 ; ------------------------------------------------------------------------
483 ; GETDEFPALETTE: Return the default palette for the driver in A/X. Must
484 ; return NULL and set an error of palettes are not supported.
485 ;
486 ; Must set an error code: YES
487 ;
488
489 GETDEFPALETTE:
490         lda     #<DEFPALETTE
491         ldx     #>DEFPALETTE
492         rts
493
494 ; ------------------------------------------------------------------------
495 ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing
496 ; color. The coordinates passed to this function are never outside the
497 ; visible screen area, so there is no need for clipping inside this function.
498 ;
499 ; Must set an error code: NO
500 ;
501
502 SETPIXELCLIP:
503         lda     Y1+1
504         bmi     @finito         ; y<0
505         lda     X1+1
506         bmi     @finito         ; x<0
507         lda     xres
508         ldx     xres+1
509         sta     ADDR
510         stx     ADDR+1
511         ldx     #ADDR
512         lda     X1
513         ldy     X1+1
514         jsr     icmp            ; if (xres<x1)
515         bcs     @cont           ; !(xres<x1)
516 @finito:rts
517 @cont:  lda     yres
518         ldx     yres+1
519         sta     ADDR
520         stx     ADDR+1
521         ldx     #ADDR
522         lda     Y1
523         ldy     Y1+1
524         jsr     icmp            ; if (yres<y1)
525         bcc     @finito
526
527 SETPIXEL:
528         jsr     CALC            ; Calculate coordinates
529
530         stx     TEMP
531         lda     ADDR
532         ldy     ADDR+1
533         jsr     VDCSetSourceAddr
534         jsr     VDCReadByte
535         ldx     TEMP
536
537         sta     TEMP
538         eor     BITMASK
539         and     BITTAB,X
540         eor     TEMP
541         pha
542         lda     ADDR
543         ldy     ADDR+1
544         jsr     VDCSetSourceAddr
545         pla
546         jsr     VDCWriteByte
547
548 @L9:    rts
549
550 ; ------------------------------------------------------------------------
551 ; GETPIXEL: Read the color value of a pixel and return it in A/X. The
552 ; coordinates passed to this function are never outside the visible screen
553 ; area, so there is no need for clipping inside this function.
554
555
556 GETPIXEL:
557         jsr     CALC            ; Calculate coordinates
558
559         stx     TEMP            ; preserve X
560         lda     ADDR
561         ldy     ADDR+1
562         jsr     VDCSetSourceAddr
563         jsr     VDCReadByte
564         ldx     TEMP
565
566         ldy     #$00
567         and     BITTAB,X
568         beq     @L1
569         iny
570
571 @L1:    tya                     ; Get color value into A
572         ldx     #$00            ; Clear high byte
573         rts
574
575 ; ------------------------------------------------------------------------
576 ; HORLINE: Draw a horizontal line from X1/Y to X2/Y, where X1 = ptr1,
577 ; Y = ptr2 and X2 = ptr3, using the current drawing color.
578 ;
579 ; This is a special line drawing entry used when the line is know to be
580 ; horizontal, for example by the BAR emulation routine. If the driver does
581 ; not have special code for horizontal lines, it may just copy Y to Y2 and
582 ; proceed with the generic line drawing code.
583 ;
584 ; Note: Line coordinates will always be sorted (Y1 <= X2) and clipped.
585 ;
586 ; Must set an error code: NO
587 ;
588
589 HORLINE:
590         lda X1
591         pha
592         lda X1+1
593         pha
594         jsr CALC                ; get data for LEFT
595         lda BITMASKL,x          ; remember left address and bitmask
596         pha
597         lda ADDR
598         pha
599         lda ADDR+1
600         pha
601
602         lda X2
603         sta X1
604         lda X2+1
605         sta X1+1
606         jsr CALC                ; get data for RIGHT
607         lda BITMASKR,x
608         sta TEMP3
609
610         pla                     ; recall data for LEFT
611         sta X1+1
612         pla
613         sta X1                  ; put left address into X1
614         pla
615
616         cmp #%11111111          ; if left bit <> 0
617         beq @L1
618         sta TEMP2               ; do left byte only...
619         lda X1
620         ldy X1+1
621         jsr VDCSetSourceAddr
622         jsr VDCReadByte
623         sta TEMP
624         eor BITMASK
625         and TEMP2
626         eor TEMP
627         pha
628         lda X1
629         ldy X1+1
630         jsr VDCSetSourceAddr
631         pla
632         jsr VDCWriteByte
633         inc X1                  ; ... and proceed
634         bne @L1
635         inc X1+1
636
637         ; do right byte (if Y2=0 ++ADDR and skip)
638 @L1:    lda TEMP3
639         cmp #%11111111          ; if right bit <> 7
640         bne @L11
641         inc ADDR                ; right bit = 7 - the next one is the last
642         bne @L10
643         inc ADDR+1
644 @L10:   bne @L2
645
646 @L11:   lda ADDR                ; do right byte only...
647         ldy ADDR+1
648         jsr VDCSetSourceAddr
649         jsr VDCReadByte
650         sta TEMP
651         eor BITMASK
652         and TEMP3
653         eor TEMP
654         pha
655         lda ADDR
656         ldy ADDR+1
657         jsr VDCSetSourceAddr
658         pla
659         jsr VDCWriteByte
660
661 @L2:                            ; do the fill in the middle
662         lda ADDR                ; calculate offset in full bytes
663         sec
664         sbc X1
665         beq @L3                 ; if equal - there are no more bytes
666         sta ADDR
667
668         lda X1                  ; setup for the left side
669         ldy X1+1
670         jsr VDCSetSourceAddr
671         lda BITMASK             ; get color
672         jsr VDCWriteByte        ; put 1st value
673         ldx ADDR
674         dex
675         beq @L3                 ; 1 byte already written
676
677         stx ADDR                ; if there are more bytes - fill them...
678         ldx #VDC_VSCROLL
679         lda #0
680         jsr VDCWriteReg         ; setup for fill
681         ldx #VDC_COUNT
682         lda ADDR
683         jsr VDCWriteReg         ; ... fill them NOW!
684
685 @L3:    pla
686         sta X1+1
687         pla
688         sta X1
689         rts
690
691 ; ------------------------------------------------------------------------
692 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
693 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
694 ;
695 ; Must set an error code: NO
696 ;
697
698 LINE:
699         ; if (x2>x1) {
700         ldx     #X1
701         lda     X2
702         ldy     X2+1
703         jsr     icmp
704         bcc     @L0137
705         beq     @L0137
706         ;  x2<->x1 }
707         lda     X1
708         ldx     X2
709         sta     X2
710         stx     X1
711         lda     X1+1
712         ldx     X2+1
713         sta     X2+1
714         stx     X1+1
715 @L0137: ; if (y2>y1) {
716         ldx     #Y1
717         lda     Y2
718         ldy     Y2+1
719         jsr     icmp
720         bcc     @L013F
721         bne     @nequal
722         jmp     HORLINE         ; x1/x2 are sorted, y1==y2 - do faster horizontal line draw
723 @nequal:
724         ; y2<->y1 }
725         lda     Y1
726         ldx     Y2
727         sta     Y2
728         stx     Y1
729         lda     Y1+1
730         ldx     Y2+1
731         sta     Y2+1
732         stx     Y1+1
733 @L013F:
734         ; nx = x2 - x1
735         lda     X2
736         sec
737         sbc     X1
738         sta     NX
739         lda     X2+1
740         sbc     X1+1
741         sta     NX+1
742         ; ny = y2 - y1
743         lda     Y2
744         sec
745         sbc     Y1
746         sta     NY
747         lda     Y2+1
748         sbc     Y1+1
749         sta     NY+1
750         ; if (nx<ny) {
751         ldx     #NX
752         lda     NY
753         ldy     NY+1
754         jsr     icmp
755         bcs     @L041B
756         ;  nx <-> ny
757         lda     NX
758         ldx     NY
759         sta     NY
760         stx     NX
761         lda     NX+1
762         ldx     NY+1
763         sta     NY+1
764         stx     NX+1
765         ; dx = dy = 0; ax = ay = 1 }
766         ldy     #1
767         sty     AY
768         dey
769         beq     @L025A
770         ; else { dx = dy = 1; ax = ay = 0 }
771 @L041B: ldy     #0
772         sty     AY
773         iny
774 @L025A: sty     DX
775         sty     DY
776         ; err = 0
777         lda     #0
778         sta     ERR
779         sta     ERR+1
780         ; for (count=nx;count>0;--count) {
781         lda     NX
782         ldx     NX+1
783         sta     COUNT
784         stx     COUNT+1
785 @L0166: lda     COUNT           ; count>0
786         ora     COUNT+1
787         bne     @L0167
788         rts
789         ;    setpixel(X1,Y1)
790 @L0167: jsr     SETPIXELCLIP
791         ;    pb = err - ny
792         lda     ERR
793         sec
794         sbc     NY
795         sta     PB
796         lda     ERR+1
797         sbc     NY+1
798         sta     PB+1
799         tax
800         ;    ub = pb + nx
801         lda     PB
802         clc
803         adc     NX
804         sta     UB
805         txa
806         adc     NX+1
807         sta     UB+1
808         ;    x1 = x1 + dx
809         lda     X1
810         clc
811         adc     DX
812         sta     X1
813         bcc     @L0254
814         inc     X1+1
815         ;   y1 = y1 + ay
816 @L0254:
817         lda     Y1
818         clc
819         adc     AY
820         sta     Y1
821         bcc     @L0255
822         inc     Y1+1
823 @L0255:
824         ; if (abs(pb)<abs(ub)) {
825         lda     PB
826         ldy     PB+1
827         jsr     abs
828         sta     TEMP3
829         sty     TEMP4
830         lda     UB
831         ldy     UB+1
832         jsr     abs
833         ldx     #TEMP3
834         jsr     icmp
835         bpl     @L017B
836         ;   err = pb
837         lda     PB
838         ldx     PB+1
839         jmp     @L025B
840         ; } else { x1 = x1 + ay
841 @L017B:
842         lda     X1
843         clc
844         adc     AY
845         sta     X1
846         bcc     @L0256
847         inc     X1+1
848         ;       y1 = y1 + dy
849 @L0256:
850         lda     Y1
851         clc
852         adc     DY
853         sta     Y1
854         bcc     @L0257
855         inc     Y1+1
856         ;       err = ub }
857 @L0257:
858         lda     UB
859         ldx     UB+1
860 @L025B:
861         sta     ERR
862         stx     ERR+1
863         ; } (--count)
864         sec
865         lda     COUNT
866         sbc     #1
867         sta     COUNT
868         bcc     @L0260
869         jmp     @L0166
870 @L0260: dec     COUNT+1
871         jmp     @L0166
872
873 ; ------------------------------------------------------------------------
874 ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where
875 ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color.
876 ; Contrary to most other functions, the graphics kernel will sort and clip
877 ; the coordinates before calling the driver, so on entry the following
878 ; conditions are valid:
879 ;       X1 <= X2
880 ;       Y1 <= Y2
881 ;       (X1 >= 0) && (X1 < XRES)
882 ;       (X2 >= 0) && (X2 < XRES)
883 ;       (Y1 >= 0) && (Y1 < YRES)
884 ;       (Y2 >= 0) && (Y2 < YRES)
885 ;
886 ; Must set an error code: NO
887 ;
888
889 BAR:
890         inc     Y2
891         bne     @L0
892         inc     Y2+1
893 @L0:    jsr     HORLINE
894         inc     Y1
895         bne     @L1
896         inc     Y1+1
897 @L1:    lda     Y1
898         cmp     Y2
899         bne     @L0
900         lda     Y1+1
901         cmp     Y2+1
902         bne     @L0
903         rts
904
905 ; ------------------------------------------------------------------------
906 ; CIRCLE: Draw a circle around the center X1/Y1 (= ptr1/ptr2) with the
907 ; radius in tmp1 and the current drawing color.
908 ;
909 ; Must set an error code: NO
910 ;
911
912 CIRCLE:
913         lda     RADIUS
914         bne     @L1
915         jmp     SETPIXELCLIP    ; Plot as a point
916
917 @L1:    sta     XX
918         ; x = r;
919         lda     #0
920         sta     XX+1
921         sta     YY
922         sta     YY+1
923         sta     MaxO
924         sta     MaxO+1
925         ; y =0; mo=0;
926         lda     X1
927         ldx     X1+1
928         sta     XS
929         stx     XS+1
930         lda     Y1
931         ldx     Y1+1
932         sta     YS
933         stx     YS+1            ; XS/YS to remember the center
934
935         ; while (y<x) {
936 @L013B: ldx     #YY
937         lda     XX
938         ldy     XX+1
939         jsr     icmp
940         bcc     @L12
941         rts
942 @L12:   ; plot points in 8 slices...
943         lda     XS
944         clc
945         adc     XX
946         sta     X1
947         lda     XS+1
948         adc     XX+1
949         sta     X1+1            ; x1 = xs+x
950         lda     YS
951         clc
952         adc     YY
953         sta     Y1
954         pha
955         lda     YS+1
956         adc     YY+1
957         sta     Y1+1            ; (stack)=ys+y, y1=(stack)
958         pha
959         jsr     SETPIXELCLIP    ; plot(xs+x,ys+y)
960         lda     YS
961         sec
962         sbc     YY
963         sta     Y1
964         sta     Y3
965         lda     YS+1
966         sbc     YY+1
967         sta     Y1+1            ; y3 = y1 = ys-y
968         sta     Y3+1
969         jsr     SETPIXELCLIP    ; plot(xs+x,ys-y)
970         pla
971         sta     Y1+1
972         pla
973         sta     Y1              ; y1 = ys+y
974         lda     XS
975         sec
976         sbc     XX
977         sta     X1
978         lda     XS+1
979         sbc     XX+1
980         sta     X1+1
981         jsr     SETPIXELCLIP    ; plot (xs-x,ys+y)
982         lda     Y3
983         sta     Y1
984         lda     Y3+1
985         sta     Y1+1
986         jsr     SETPIXELCLIP    ; plot (xs-x,ys-y)
987
988         lda     XS
989         clc
990         adc     YY
991         sta     X1
992         lda     XS+1
993         adc     YY+1
994         sta     X1+1            ; x1 = xs+y
995         lda     YS
996         clc
997         adc     XX
998         sta     Y1
999         pha
1000         lda     YS+1
1001         adc     XX+1
1002         sta     Y1+1            ; (stack)=ys+x, y1=(stack)
1003         pha
1004         jsr     SETPIXELCLIP    ; plot(xs+y,ys+x)
1005         lda     YS
1006         sec
1007         sbc     XX
1008         sta     Y1
1009         sta     Y3
1010         lda     YS+1
1011         sbc     XX+1
1012         sta     Y1+1            ; y3 = y1 = ys-x
1013         sta     Y3+1
1014         jsr     SETPIXELCLIP    ; plot(xs+y,ys-x)
1015         pla
1016         sta     Y1+1
1017         pla
1018         sta     Y1              ; y1 = ys+x(stack)
1019         lda     XS
1020         sec
1021         sbc     YY
1022         sta     X1
1023         lda     XS+1
1024         sbc     YY+1
1025         sta     X1+1
1026         jsr     SETPIXELCLIP    ; plot (xs-y,ys+x)
1027         lda     Y3
1028         sta     Y1
1029         lda     Y3+1
1030         sta     Y1+1
1031         jsr     SETPIXELCLIP    ; plot (xs-y,ys-x)
1032
1033         ; og = mo+y+y+1
1034         lda     MaxO
1035         ldx     MaxO+1
1036         clc
1037         adc     YY
1038         tay
1039         txa
1040         adc     YY+1
1041         tax
1042         tya
1043         clc
1044         adc     YY
1045         tay
1046         txa
1047         adc     YY+1
1048         tax
1049         tya
1050         clc
1051         adc     #1
1052         bcc     @L0143
1053         inx
1054 @L0143: sta     OGora
1055         stx     OGora+1
1056         ; ou = og-x-x+1
1057         sec
1058         sbc     XX
1059         tay
1060         txa
1061         sbc     XX+1
1062         tax
1063         tya
1064         sec
1065         sbc     XX
1066         tay
1067         txa
1068         sbc     XX+1
1069         tax
1070         tya
1071         clc
1072         adc     #1
1073         bcc     @L0146
1074         inx
1075 @L0146: sta     OUkos
1076         stx     OUkos+1
1077         ; ++y
1078         inc     YY
1079         bne     @L0148
1080         inc     YY+1
1081 @L0148: ; if (abs(ou)<abs(og))
1082         lda     OUkos
1083         ldy     OUkos+1
1084         jsr     abs
1085         sta     TEMP3
1086         sty     TEMP4
1087         lda     OGora
1088         ldy     OGora+1
1089         jsr     abs
1090         ldx     #TEMP3
1091         jsr     icmp
1092         bpl     @L0149
1093         ; { --x;
1094         sec
1095         lda     XX
1096         sbc     #1
1097         sta     XX
1098         bcs     @L014E
1099         dec     XX+1
1100 @L014E: ; mo = ou; }
1101         lda     OUkos
1102         ldx     OUkos+1
1103         jmp     @L014G
1104         ; else { mo = og }
1105 @L0149: lda     OGora
1106         ldx     OGora+1
1107 @L014G: sta     MaxO
1108         stx     MaxO+1
1109         ; }
1110         jmp     @L013B
1111
1112 ; ------------------------------------------------------------------------
1113 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
1114 ; direction is passend in X/Y, the text direction is passed in A.
1115 ;
1116 ; Must set an error code: NO
1117 ;
1118
1119 TEXTSTYLE:
1120         stx     TEXTMAGX
1121         sty     TEXTMAGY
1122         sta     TEXTDIR
1123         rts
1124
1125
1126 ; ------------------------------------------------------------------------
1127 ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the
1128 ; current text style. The text to output is given as a zero terminated
1129 ; string with address in ptr3.
1130 ;
1131 ; Must set an error code: NO
1132 ;
1133
1134 OUTTEXT:
1135         rts
1136
1137 ; ------------------------------------------------------------------------
1138 ; Calculate all variables to plot the pixel at X1/Y1.
1139 ;------------------------
1140 ;< X1,Y1 - pixel
1141 ;> ADDR - address of card
1142 ;> X - bit number (X1 & 7)
1143 CALC:
1144         lda     Y1+1
1145         sta     ADDR+1
1146         lda     Y1
1147         asl
1148         rol     ADDR+1
1149         asl
1150         rol     ADDR+1          ; Y*4
1151         clc
1152         adc     Y1
1153         sta     ADDR
1154         lda     Y1+1
1155         adc     ADDR+1
1156         sta     ADDR+1          ; Y*4+Y=Y*5
1157         lda     ADDR
1158         asl
1159         rol     ADDR+1
1160         asl
1161         rol     ADDR+1
1162         asl
1163         rol     ADDR+1
1164         asl
1165         rol     ADDR+1
1166         sta     ADDR            ; Y*5*16=Y*80
1167         lda     X1+1
1168         sta     TEMP
1169         lda     X1
1170         lsr     TEMP
1171         ror
1172         lsr     TEMP
1173         ror
1174         lsr     TEMP
1175         ror
1176         clc
1177         adc     ADDR
1178         sta     ADDR
1179         lda     ADDR+1          ; ADDR = Y*80+x/8
1180         adc     TEMP
1181         sta     ADDR+1
1182         lda     ADDR+1
1183         adc     SCRBASE
1184         sta     ADDR+1
1185         lda     X1
1186         and     #7
1187         tax
1188         rts
1189
1190 ;-------------
1191 ; copies of some runtime routines
1192
1193 abs:
1194         ; a/y := abs(a/y)
1195         dey
1196         iny
1197         bpl     @L1
1198         ; negay
1199         clc
1200         eor     #$ff
1201         adc     #1
1202         pha
1203         tya
1204         eor     #$ff
1205         adc     #0
1206         tay
1207         pla
1208 @L1:    rts
1209
1210 icmp:
1211         ; compare a/y to zp,x
1212         sta     TEMP            ; TEMP/TEMP2 - arg2
1213         sty     TEMP2
1214         lda     $0,x
1215         pha
1216         lda     $1,x
1217         tay
1218         pla
1219         tax
1220         tya                     ; x/a - arg1 (a=high)
1221
1222         sec
1223         sbc     TEMP2
1224         bne     @L4
1225         cpx     TEMP
1226         beq     @L3
1227         adc     #$ff
1228         ora     #$01
1229 @L3:    rts
1230 @L4:    bvc     @L3
1231         eor     #$ff
1232         ora     #$01
1233         rts
1234
1235 ;-------------
1236 ; VDC helpers
1237
1238 VDCSetSourceAddr:
1239         pha
1240         tya
1241         ldx     #VDC_DATA_HI
1242         jsr     VDCWriteReg
1243         pla
1244         ldx     #VDC_DATA_LO
1245         bne     VDCWriteReg
1246
1247 VDCReadByte:
1248         ldx     #VDC_DATA
1249 VDCReadReg:
1250         stx     VDC_ADDR_REG
1251 @L0:    bit     VDC_ADDR_REG
1252         bpl     @L0
1253         lda     VDC_DATA_REG
1254         rts
1255
1256 VDCWriteByte:
1257         ldx     #VDC_DATA
1258 VDCWriteReg:
1259         stx     VDC_ADDR_REG
1260 @L0:    bit     VDC_ADDR_REG
1261         bpl     @L0
1262         sta     VDC_DATA_REG
1263         rts
1264