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