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