]> git.sur5r.net Git - cc65/blobdiff - libsrc/c128/c128-640-200-2.s
poor man's _toascii routine, contributed by Fatih Aygun
[cc65] / libsrc / c128 / c128-640-200-2.s
index 26ab0b9d16ad4f0dc44f85c3e4db7077b4901cd5..1a51eb903dad9e64f03974c5759ccb42c06c9618 100644 (file)
@@ -2,28 +2,27 @@
 ; Graphics driver for the 640x200x2 mode on the C128 VDC
 ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
 ; 23.12.2002
+; 2004-04-04, Greg King
 ;
 ; NOTES:
-; On the real machine there are some additional pixels appearing (probably bad reads)
-; VICE emulator does not show them. Needs further investigation.
+; For any smart monkey that will try to optimize this: PLEASE do tests on
+; real VDC, not only VICE.
 ;
-; Only DONE routine contains C128-mode specific stuff, everything else will work in
-; C64-mode of C128 (C64 needs full VDC init then).
-;
-; X-axis resolution can be changed by manipulating xres header field so
-; any resolution 8..708 is possible only with gfx-mode initialization and CALC changed.
+; Only DONE routine contains C128-mode specific stuff, everything else will
+; work in C64-mode of C128 (C64 needs full VDC init then).
 ;
 ; With special initialization and CALC we can get 320x200 double-pixel mode.
 ;
-; Color translation values for BROWN and GRAY3 are obviously wrong, they could
-; be replaced by equiv. of ORANGE and GRAY2 but this would give only 14 of 16 colors available.
+; Color translation values for BROWN and GRAY3 are obviously wrong, they
+; could be replaced by equiv. of ORANGE and GRAY2 but this would give only
+; 14 of 16 colors available.
 ;
-; Register 25 ($19) is said to require different value for VDC v1, but I couldn't find what
-; it should be.
+; Register 25 ($19) is said to require different value for VDC v1, but I
+; couldn't find what it should be.
 
-       .include        "zeropage.inc"
+       .include        "zeropage.inc"
 
-       .include        "tgi-kernel.inc"
+       .include        "tgi-kernel.inc"
         .include        "tgi-mode.inc"
         .include        "tgi-error.inc"
 
@@ -56,42 +55,38 @@ VDC_DATA      = 31
 ; capabilities of the driver
 
         .byte   $74, $67, $69           ; "tgi"
-        .byte   $00                     ; TGI version number
+        .byte   TGI_API_VERSION         ; TGI API version number
 xres:   .word   640                     ; X resolution
 yres:   .word   200                     ; Y resolution
         .byte   2                       ; Number of drawing colors
 pages: .byte   1                       ; Number of screens available
         .byte   8                       ; System font X size
         .byte   8                       ; System font Y size
-        .res    4, $00                  ; Reserved for future extensions
+        .word   $100                    ; Aspect ratio
 
 ; Next comes the jump table. Currently all entries must be valid and may point
-; to an RTS for test versions (function not implemented). A future version may
-; allow for emulation: In this case the vector will be zero. Emulation means
-; that the graphics kernel will emulate the function by using lower level
-; primitives - for example ploting a line by using calls to SETPIXEL.
-
-        .word   INSTALL
-        .word   DEINSTALL
-        .word   INIT
-        .word   DONE
-       .word   GETERROR
-        .word   CONTROL
-        .word   CLEAR
-        .word   SETVIEWPAGE
-        .word   SETDRAWPAGE
-        .word   SETCOLOR
-        .word   SETPALETTE
-        .word   GETPALETTE
-        .word   GETDEFPALETTE
-        .word   SETPIXEL
-        .word   GETPIXEL
-        .word   HORLINE
-        .word   LINE
-        .word   BAR
-        .word   CIRCLE
-        .word   TEXTSTYLE
-        .word   OUTTEXT
+; to an RTS for test versions (function not implemented).
+
+        .addr   INSTALL
+        .addr   UNINSTALL
+        .addr   INIT
+        .addr   DONE
+               .addr   GETERROR
+        .addr   CONTROL
+        .addr   CLEAR
+        .addr   SETVIEWPAGE
+        .addr   SETDRAWPAGE
+        .addr   SETCOLOR
+        .addr   SETPALETTE
+        .addr   GETPALETTE
+        .addr   GETDEFPALETTE
+        .addr   SETPIXEL
+        .addr   GETPIXEL
+        .addr   LINE
+        .addr   BAR
+        .addr   TEXTSTYLE
+        .addr   OUTTEXT
+        .addr   0                       ; IRQ entry is unused
 
 ; ------------------------------------------------------------------------
 ; Data.
@@ -103,7 +98,6 @@ X1              = ptr1
 Y1              = ptr2
 X2              = ptr3
 Y2              = ptr4
-RADIUS         = tmp1
 
 ADDR           = tmp1          ; (2)   CALC
 TEMP           = tmp3          ;       CALC icmp
@@ -116,12 +110,6 @@ PB                 = ptr3          ; (2)   LINE
 UB             = ptr4          ; (2)   LINE
 ERR            = regsave       ; (2)   LINE
 NX             = regsave+2     ; (2)   LINE
-; Circle stuff
-XX             = ptr3          ; (2)   CIRCLE
-YY             = ptr4          ; (2)   CIRCLE
-MaxO           = sreg          ; (overwritten by TEMP3+TEMP4, but restored from OG/OU anyway)
-XS             = regsave       ; (2)   CIRCLE
-YS             = regsave+2     ; (2)   CIRCLE
 
 ; Absolute variables used in the code
 
@@ -136,15 +124,13 @@ BITMASK:        .res    1       ; $00 = clear, $FF = set pixels
 
 OLDCOLOR:      .res    1       ; colors before entering gfx mode
 
-; Line routine stuff (combined with CIRCLE to save space)
+; Line routine stuff
 
-OGora:
 COUNT:          .res   2
-OUkos:
 NY:             .res   2
-Y3:
 DX:             .res   1
 DY:             .res   1
+AX:             .res   1
 AY:             .res   1
 
 ; Text output stuff
@@ -266,19 +252,19 @@ settestadr2:
        jmp     VDCSetSourceAddr
 
 ; ------------------------------------------------------------------------
-; DEINSTALL routine. Is called before the driver is removed from memory. May
+; UNINSTALL routine. Is called before the driver is removed from memory. May
 ; clean up anything done by INSTALL but is probably empty most of the time.
 ;
 ; Must set an error code: NO
 ;
 
-DEINSTALL:
+UNINSTALL:
         rts
 
 
 ; ------------------------------------------------------------------------
 ; INIT: Changes an already installed device from text mode to graphics
-; mode. The number of the graphics mode is passed to the function in A.
+; mode.
 ; Note that INIT/DONE may be called multiple times while the driver
 ; is loaded, while INSTALL is only called once, so any code that is needed
 ; to initializes variables and so on must go here. Setting palette and
@@ -290,16 +276,18 @@ DEINSTALL:
 ; Must set an error code: YES
 ;
 
-INIT:   cmp     #TGI_MODE_640_200_2     ; Correct mode?
-        beq     @L1                     ; Jump if yes
-        lda     #TGI_ERR_INV_MODE       ; ## Error
-        bne     @L9
+INIT:
 
 ; Initialize variables
 
 @L1:    ldx     #$FF
         stx     BITMASK
 
+; Remeber current color value
+       ldx     #VDC_COLORS
+       jsr     VDCReadReg
+       sta     OLDCOLOR
+
 ; Switch into graphics mode (set view page 0)
 
        ldy     #0
@@ -312,15 +300,10 @@ INIT:   cmp     #TGI_MODE_640_200_2     ; Correct mode?
        bne     @L2
 @L3:
 
-; Remeber current color value
-       ldx     #VDC_COLORS
-       jsr     VDCReadReg
-       sta     OLDCOLOR
-
 ; Done, reset the error code
 
         lda     #TGI_ERR_OK
-@L9:    sta     ERROR
+        sta     ERROR
         rts
 
 ; ------------------------------------------------------------------------
@@ -328,12 +311,13 @@ INIT:   cmp     #TGI_MODE_640_200_2     ; Correct mode?
 ; The graphics kernel will never call DONE when no graphics mode is active,
 ; so there is no need to protect against that.
 ;
-; Must set an error code: YES
+; Must set an error code: NO
 ;
 
 DONE:
        ; This part is C128-mode specific
-       jsr $ce0c               ; reload character set
+       jsr $e179               ; reload character set and setup VDC
+       jsr $ff62
        lda $d7                 ; in 80-columns?
        bne @L01
 @L0:   lda SCN80CLR,y
@@ -351,7 +335,7 @@ DONE:
        jsr VDCWriteReg         ; restore color (background)
        lda #$47
        ldx #VDC_HSCROLL
-       jmp VDCWriteReg         ; switch to text screen
+               jmp VDCWriteReg         ; switch to text screen
 
 ; ------------------------------------------------------------------------
 ; GETERROR: Return the error code in A and clear it.
@@ -379,7 +363,7 @@ CONTROL:
 ; Must set an error code: NO
 ;
 
-CLEAR:  
+CLEAR:
        lda     #0
        ldy     SCRBASE
        jsr     VDCSetSourceAddr
@@ -469,13 +453,17 @@ SETPALETTE:
        ora     COLTRANS,y
 
        ldx     #VDC_COLORS
-       jmp     VDCWriteReg
+               jsr     VDCWriteReg     ; Clear error code
+        lda     #TGI_ERR_OK
+        sta     ERROR
+        rts
 
 ; ------------------------------------------------------------------------
-; GETPALETTE: Return the current palette in A/X. Must return NULL and set an
-; error if palettes are not supported.
+; GETPALETTE: Return the current palette in A/X. Even drivers that cannot
+; set the palette should return the default palette here, so there's no
+; way for this function to fail.
 ;
-; Must set an error code: YES
+; Must set an error code: NO
 ;
 
 GETPALETTE:
@@ -484,10 +472,12 @@ GETPALETTE:
         rts
 
 ; ------------------------------------------------------------------------
-; GETDEFPALETTE: Return the default palette for the driver in A/X. Must
-; return NULL and set an error of palettes are not supported.
+; GETDEFPALETTE: Return the default palette for the driver in A/X. All
+; drivers should return something reasonable here, even drivers that don't
+; support palettes, otherwise the caller has no way to determine the colors
+; of the (not changeable) palette.
 ;
-; Must set an error code: YES
+; Must set an error code: NO (all drivers must have a default palette)
 ;
 
 GETDEFPALETTE:
@@ -503,31 +493,6 @@ GETDEFPALETTE:
 ; Must set an error code: NO
 ;
 
-SETPIXELCLIP:
-       lda     Y1+1
-       bmi     @finito         ; y<0
-       lda     X1+1
-       bmi     @finito         ; x<0
-       lda     xres
-       ldx     xres+1
-       sta     ADDR
-       stx     ADDR+1
-       ldx     #ADDR
-       lda     X1
-       ldy     X1+1
-       jsr     icmp            ; if (xres<x1)
-       bcs     @cont           ; !(xres<x1)
-@finito:rts
-@cont: lda     yres
-       ldx     yres+1
-       sta     ADDR
-       stx     ADDR+1
-       ldx     #ADDR
-       lda     Y1
-       ldy     Y1+1
-       jsr     icmp            ; if (yres<y1)
-       bcc     @finito
-
 SETPIXEL:
         jsr     CALC            ; Calculate coordinates
 
@@ -576,122 +541,6 @@ GETPIXEL:
         ldx     #$00            ; Clear high byte
         rts
 
-; ------------------------------------------------------------------------
-; HORLINE: Draw a horizontal line from X1/Y to X2/Y, where X1 = ptr1,
-; Y = ptr2 and X2 = ptr3, using the current drawing color.
-;
-; This is a special line drawing entry used when the line is know to be
-; horizontal, for example by the BAR emulation routine. If the driver does
-; not have special code for horizontal lines, it may just copy Y to Y2 and
-; proceed with the generic line drawing code.
-;
-; Note: Line coordinates will always be sorted (Y1 <= X2) and clipped.
-;
-; Must set an error code: NO
-;
-
-HORLINE:
-       lda X1
-       pha
-       lda X1+1
-       pha
-       jsr CALC                ; get data for LEFT
-       lda BITMASKL,x          ; remember left address and bitmask
-       pha
-       lda ADDR
-       pha
-       lda ADDR+1
-       pha
-
-       lda X2
-       sta X1
-       lda X2+1
-       sta X1+1
-       jsr CALC                ; get data for RIGHT
-       lda BITMASKR,x
-       sta TEMP3
-
-       pla                     ; recall data for LEFT
-       sta X1+1
-       pla
-       sta X1                  ; put left address into X1
-       pla
-
-       cmp #%11111111          ; if left bit <> 0
-       beq @L1
-       sta TEMP2               ; do left byte only...
-       lda X1
-       ldy X1+1
-       jsr VDCSetSourceAddr
-       jsr VDCReadByte
-       sta TEMP
-       eor BITMASK
-       and TEMP2
-       eor TEMP
-       pha
-       lda X1
-       ldy X1+1
-       jsr VDCSetSourceAddr
-       pla
-       jsr VDCWriteByte
-       inc X1                  ; ... and proceed
-       bne @L1
-       inc X1+1
-
-       ; do right byte (if Y2=0 ++ADDR and skip)
-@L1:   lda TEMP3
-       cmp #%11111111          ; if right bit <> 7
-       bne @L11
-       inc ADDR                ; right bit = 7 - the next one is the last
-       bne @L10
-       inc ADDR+1
-@L10:  bne @L2
-
-@L11:  lda ADDR                ; do right byte only...
-       ldy ADDR+1
-       jsr VDCSetSourceAddr
-       jsr VDCReadByte
-       sta TEMP
-       eor BITMASK
-       and TEMP3
-       eor TEMP
-       pha
-       lda ADDR
-       ldy ADDR+1
-       jsr VDCSetSourceAddr
-       pla
-       jsr VDCWriteByte
-
-@L2:                           ; do the fill in the middle
-       lda ADDR                ; calculate offset in full bytes
-       sec
-       sbc X1
-       beq @L3                 ; if equal - there are no more bytes
-       sta ADDR
-
-       lda X1                  ; setup for the left side
-       ldy X1+1
-       jsr VDCSetSourceAddr
-       lda BITMASK             ; get color
-       jsr VDCWriteByte        ; put 1st value
-       ldx ADDR
-       dex
-       beq @L3                 ; 1 byte already written
-
-       stx ADDR                ; if there are more bytes - fill them...
-       ldx #VDC_VSCROLL
-       lda #0
-       jsr VDCWriteReg         ; setup for fill
-       ldx #VDC_COUNT
-       lda ADDR
-       jsr VDCWriteReg         ; ... fill them NOW!
-
-@L3:   pla
-       sta X1+1
-       pla
-       sta X1
-       rts
-
 ; ------------------------------------------------------------------------
 ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and
 ; X2/Y2 = ptr3/ptr4 using the current drawing color.
@@ -700,63 +549,69 @@ HORLINE:
 ;
 
 LINE:
-       ; if (x2>x1) {
-       ldx     #X1
-       lda     X2
-       ldy     X2+1
-       jsr     icmp
-       bcc     @L0137
-       beq     @L0137
-       ;  x2<->x1 }
-       lda     X1
-       ldx     X2
-       sta     X2
-       stx     X1
-       lda     X1+1
-       ldx     X2+1
-       sta     X2+1
-       stx     X1+1
-@L0137:        ; if (y2>y1) {
-       ldx     #Y1
-       lda     Y2
-       ldy     Y2+1
-       jsr     icmp
-       bcc     @L013F
-       bne     @nequal
-       jmp     HORLINE         ; x1/x2 are sorted, y1==y2 - do faster horizontal line draw
-@nequal:
-       ; y2<->y1 }
-       lda     Y1
-       ldx     Y2
-       sta     Y2
-       stx     Y1
-       lda     Y1+1
-       ldx     Y2+1
-       sta     Y2+1
-       stx     Y1+1
-@L013F:
-       ; nx = x2 - x1
+       ; nx = abs(x2 - x1)
        lda     X2
        sec
        sbc     X1
        sta     NX
        lda     X2+1
        sbc     X1+1
-       sta     NX+1
-       ; ny = y2 - y1
+       tay
+       lda     NX
+       jsr     abs
+       sta     NX
+       sty     NX+1
+       ; ny = abs(y2 - y1)
        lda     Y2
        sec
        sbc     Y1
        sta     NY
        lda     Y2+1
        sbc     Y1+1
-       sta     NY+1
+       tay
+       lda     NY
+       jsr     abs
+       sta     NY
+       sty     NY+1
+       ; if (x2>=x1)
+       ldx     #X2
+       lda     X1
+       ldy     X1+1
+       jsr     icmp
+       bcc     @L0243
+       ; dx = 1;
+       lda     #1
+       bne     @L0244
+       ; else
+       ; dx = -1;
+@L0243:        lda     #$ff
+@L0244:        sta     DX
+       ; if (y2>=y1)
+       ldx     #Y2
+       lda     Y1
+       ldy     Y1+1
+       jsr     icmp
+       bcc     @L024A
+       ; dy = 1;
+       lda     #1
+       bne     @L024B
+       ; else
+       ; dy = -1;
+@L024A:        lda     #$ff
+@L024B:        sta     DY
+       ; err = ax = ay = 0;
+       lda     #0
+       sta     ERR
+       sta     ERR+1
+       sta     AX
+       sta     AY
+
        ; if (nx<ny) {
        ldx     #NX
        lda     NY
        ldy     NY+1
        jsr     icmp
-       bcs     @L041B
+       bcs     @L0255
        ;  nx <-> ny
        lda     NX
        ldx     NY
@@ -766,21 +621,22 @@ LINE:
        ldx     NY+1
        sta     NY+1
        stx     NX+1
-       ; dx = dy = 0; ax = ay = 1 }
-       ldy     #1
-       sty     AY
-       dey
-       beq     @L025A
-       ; else { dx = dy = 1; ax = ay = 0 }
-@L041B:        ldy     #0
-       sty     AY
-       iny
-@L025A:        sty     DX
-       sty     DY
-       ; err = 0
+       ; ax = dx
+       lda     DX
+       sta     AX
+       ; ay = dy
+       lda     DY
+       sta     AY
+       ; dx = dy = 0;
        lda     #0
-       sta     ERR
-       sta     ERR+1
+       sta     DX
+       sta     DY
+       ; ny = - ny;
+@L0255:        lda     NY
+       ldy     NY+1
+       jsr     neg
+       sta     NY
+       sty     NY+1
        ; for (count=nx;count>0;--count) {
        lda     NX
        ldx     NX+1
@@ -791,14 +647,14 @@ LINE:
        bne     @L0167
        rts
        ;    setpixel(X1,Y1)
-@L0167:        jsr     SETPIXELCLIP
-       ;    pb = err - ny
+@L0167:        jsr     SETPIXEL
+       ;    pb = err + ny
        lda     ERR
-       sec
-       sbc     NY
+       clc
+       adc     NY
        sta     PB
        lda     ERR+1
-       sbc     NY+1
+       adc     NY+1
        sta     PB+1
        tax
        ;    ub = pb + nx
@@ -810,21 +666,27 @@ LINE:
        adc     NX+1
        sta     UB+1
        ;    x1 = x1 + dx
-       lda     X1
-       clc
-       adc     DX
+       ldx     #0
+       lda     DX
+       bpl     @L027B
+       dex
+@L027B:        clc
+       adc     X1
        sta     X1
-       bcc     @L0254
-       inc     X1+1
+       txa
+       adc     X1+1
+       sta     X1+1
        ;   y1 = y1 + ay
-@L0254:
-       lda     Y1
-       clc
-       adc     AY
+       ldx     #0
+       lda     AY
+       bpl     @L027E
+       dex
+@L027E:        clc
+       adc     Y1
        sta     Y1
-       bcc     @L0255
-       inc     Y1+1
-@L0255:
+       txa
+       adc     Y1+1
+       sta     Y1+1
        ; if (abs(pb)<abs(ub)) {
        lda     PB
        ldy     PB+1
@@ -836,32 +698,38 @@ LINE:
        jsr     abs
        ldx     #TEMP3
        jsr     icmp
-       bpl     @L017B
+       bpl     @L027F
        ;   err = pb
        lda     PB
        ldx     PB+1
-       jmp     @L025B
-       ; } else { x1 = x1 + ay
-@L017B:        
-       lda     X1
-       clc
-       adc     AY
+       jmp     @L0312
+       ; } else { x1 = x1 + ax
+@L027F:
+       ldx     #0
+       lda     AX
+       bpl     @L0288
+       dex
+@L0288:        clc
+       adc     X1
        sta     X1
-       bcc     @L0256
-       inc     X1+1
+       txa
+       adc     X1+1
+       sta     X1+1
        ;       y1 = y1 + dy
-@L0256:
-       lda     Y1
-       clc
-       adc     DY
+       ldx     #0
+       lda     DY
+       bpl     @L028B
+       dex
+@L028B:        clc
+       adc     Y1
        sta     Y1
-       bcc     @L0257
-       inc     Y1+1
+       txa
+       adc     Y1+1
+       sta     Y1+1
        ;       err = ub }
-@L0257:
        lda     UB
        ldx     UB+1
-@L025B:
+@L0312:
        sta     ERR
        stx     ERR+1
        ; } (--count)
@@ -892,226 +760,126 @@ LINE:
 
 BAR:
        inc     Y2
-       bne     @L0
+       bne     HORLINE
        inc     Y2+1
-@L0:   jsr     HORLINE
-       inc     Y1
-       bne     @L1
-       inc     Y1+1
-@L1:   lda     Y1
-       cmp     Y2
-       bne     @L0
-       lda     Y1+1
-       cmp     Y2+1
-       bne     @L0
-       rts
 
-; ------------------------------------------------------------------------
-; CIRCLE: Draw a circle around the center X1/Y1 (= ptr1/ptr2) with the
-; radius in tmp1 and the current drawing color.
-;
-; Must set an error code: NO
-;
+; Original code for a horizontal line
 
-CIRCLE: 
-       lda     RADIUS
-        bne     @L1
-        jmp     SETPIXELCLIP    ; Plot as a point
+HORLINE:
+       lda X1
+       pha
+       lda X1+1
+       pha
+       jsr CALC                ; get data for LEFT
+       lda BITMASKL,x          ; remember left address and bitmask
+       pha
+       lda ADDR
+       pha
+       lda ADDR+1
+       pha
+
+       lda X2
+       sta X1
+       lda X2+1
+       sta X1+1
+       jsr CALC                ; get data for RIGHT
+       lda BITMASKR,x
+       sta TEMP3
+
+       pla                     ; recall data for LEFT
+       sta X1+1
+       pla
+       sta X1                  ; put left address into X1
+       pla
+
+       cmp #%11111111          ; if left bit <> 0
+       beq @L1
+       sta TEMP2               ; do left byte only...
+       lda X1
+       ldy X1+1
+       jsr VDCSetSourceAddr
+       jsr VDCReadByte
+       sta TEMP
+       eor BITMASK
+       and TEMP2
+       eor TEMP
+       pha
+       lda X1
+       ldy X1+1
+       jsr VDCSetSourceAddr
+       pla
+       jsr VDCWriteByte
+       inc X1                  ; ... and proceed
+       bne @L1
+       inc X1+1
+
+       ; do right byte (if Y2=0 ++ADDR and skip)
+@L1:   lda TEMP3
+       cmp #%11111111          ; if right bit <> 7
+       bne @L11
+       inc ADDR                ; right bit = 7 - the next one is the last
+       bne @L10
+       inc ADDR+1
+@L10:  bne @L2
 
-@L1:   sta     XX
-       ; x = r;
-       lda     #0
-       sta     XX+1
-       sta     YY
-       sta     YY+1
-       sta     MaxO
-       sta     MaxO+1
-       ; y =0; mo=0;
-       lda     X1
-       ldx     X1+1
-       sta     XS
-       stx     XS+1
-       lda     Y1
-       ldx     Y1+1
-       sta     YS
-       stx     YS+1            ; XS/YS to remember the center
-
-       ; while (y<x) {
-@L013B:        ldx     #YY
-       lda     XX
-       ldy     XX+1
-       jsr     icmp
-       bcc     @L12
-       rts
-@L12:  ; plot points in 8 slices...
-       lda     XS
-       clc
-       adc     XX
-       sta     X1
-       lda     XS+1
-       adc     XX+1
-       sta     X1+1            ; x1 = xs+x
-       lda     YS
-       clc
-       adc     YY
-       sta     Y1
-       pha
-       lda     YS+1
-       adc     YY+1
-       sta     Y1+1            ; (stack)=ys+y, y1=(stack)
+@L11:  lda ADDR                ; do right byte only...
+       ldy ADDR+1
+       jsr VDCSetSourceAddr
+       jsr VDCReadByte
+       sta TEMP
+       eor BITMASK
+       and TEMP3
+       eor TEMP
        pha
-       jsr     SETPIXELCLIP    ; plot(xs+x,ys+y)
-       lda     YS
-       sec
-       sbc     YY
-       sta     Y1
-       sta     Y3
-       lda     YS+1
-       sbc     YY+1
-       sta     Y1+1            ; y3 = y1 = ys-y
-       sta     Y3+1
-       jsr     SETPIXELCLIP    ; plot(xs+x,ys-y)
-       pla
-       sta     Y1+1
+       lda ADDR
+       ldy ADDR+1
+       jsr VDCSetSourceAddr
        pla
-       sta     Y1              ; y1 = ys+y
-       lda     XS
-       sec
-       sbc     XX
-       sta     X1
-       lda     XS+1
-       sbc     XX+1
-       sta     X1+1
-       jsr     SETPIXELCLIP    ; plot (xs-x,ys+y)
-       lda     Y3
-       sta     Y1
-       lda     Y3+1
-       sta     Y1+1
-       jsr     SETPIXELCLIP    ; plot (xs-x,ys-y)
+       jsr VDCWriteByte
 
-       lda     XS
-       clc
-       adc     YY
-       sta     X1
-       lda     XS+1
-       adc     YY+1
-       sta     X1+1            ; x1 = xs+y
-       lda     YS
-       clc
-       adc     XX
-       sta     Y1
-       pha
-       lda     YS+1
-       adc     XX+1
-       sta     Y1+1            ; (stack)=ys+x, y1=(stack)
-       pha
-       jsr     SETPIXELCLIP    ; plot(xs+y,ys+x)
-       lda     YS
+@L2:                           ; do the fill in the middle
+       lda ADDR                ; calculate offset in full bytes
        sec
-       sbc     XX
-       sta     Y1
-       sta     Y3
-       lda     YS+1
-       sbc     XX+1
-       sta     Y1+1            ; y3 = y1 = ys-x
-       sta     Y3+1
-       jsr     SETPIXELCLIP    ; plot(xs+y,ys-x)
-       pla
-       sta     Y1+1
+       sbc X1
+       beq @L3                 ; if equal - there are no more bytes
+       sta ADDR
+
+       lda X1                  ; setup for the left side
+       ldy X1+1
+       jsr VDCSetSourceAddr
+       lda BITMASK             ; get color
+       jsr VDCWriteByte        ; put 1st value
+       ldx ADDR
+       dex
+       beq @L3                 ; 1 byte already written
+
+       stx ADDR                ; if there are more bytes - fill them...
+       ldx #VDC_VSCROLL
+       lda #0
+       jsr VDCWriteReg         ; setup for fill
+       ldx #VDC_COUNT
+       lda ADDR
+       jsr VDCWriteReg         ; ... fill them NOW!
+
+@L3:   pla
+       sta X1+1
        pla
-       sta     Y1              ; y1 = ys+x(stack)
-       lda     XS
-       sec
-       sbc     YY
-       sta     X1
-       lda     XS+1
-       sbc     YY+1
-       sta     X1+1
-       jsr     SETPIXELCLIP    ; plot (xs-y,ys+x)
-       lda     Y3
-       sta     Y1
-       lda     Y3+1
-       sta     Y1+1
-       jsr     SETPIXELCLIP    ; plot (xs-y,ys-x)
+       sta X1
 
-       ; og = mo+y+y+1
-       lda     MaxO
-       ldx     MaxO+1
-       clc
-       adc     YY
-       tay
-       txa
-       adc     YY+1
-       tax
-       tya
-       clc
-       adc     YY
-       tay
-       txa
-       adc     YY+1
-       tax
-       tya
-       clc
-       adc     #1
-       bcc     @L0143
-       inx
-@L0143:        sta     OGora
-       stx     OGora+1
-       ; ou = og-x-x+1
-       sec
-       sbc     XX
-       tay
-       txa
-       sbc     XX+1
-       tax
-       tya
-       sec
-       sbc     XX
-       tay
-       txa
-       sbc     XX+1
-       tax
-       tya
-       clc
-       adc     #1
-       bcc     @L0146
-       inx
-@L0146:        sta     OUkos
-       stx     OUkos+1
-       ; ++y
-       inc     YY
-       bne     @L0148
-       inc     YY+1
-@L0148:        ; if (abs(ou)<abs(og))
-       lda     OUkos
-       ldy     OUkos+1
-       jsr     abs
-       sta     TEMP3
-       sty     TEMP4
-       lda     OGora
-       ldy     OGora+1
-       jsr     abs
-       ldx     #TEMP3
-       jsr     icmp
-       bpl     @L0149
-       ; { --x;
-       sec
-       lda     XX
-       sbc     #1
-       sta     XX
-       bcs     @L014E
-       dec     XX+1
-@L014E:        ; mo = ou; }
-       lda     OUkos
-       ldx     OUkos+1
-       jmp     @L014G
-       ; else { mo = og }
-@L0149:        lda     OGora
-       ldx     OGora+1
-@L014G:        sta     MaxO
-       stx     MaxO+1
-       ; }
-        jmp    @L013B
+; End of horizontal line code
+
+       inc     Y1
+       bne     @L4
+       inc     Y1+1
+@L4:   lda     Y1
+       cmp     Y2
+       bne     @L5
+       lda     Y1+1
+       cmp     Y2+1
+       bne     @L5
+       rts
+
+@L5:   jmp     HORLINE
 
 ; ------------------------------------------------------------------------
 ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y
@@ -1196,20 +964,18 @@ CALC:
 
 abs:
        ; a/y := abs(a/y)
-       dey
-       iny
-       bpl     @L1
+       cpy     #$00
+       bpl     absend
        ; negay
-       clc
-       eor     #$ff
-       adc     #1
+neg:   eor     #$ff
+       add     #1
        pha
        tya
        eor     #$ff
        adc     #0
        tay
        pla
-@L1:   rts
+absend:        rts
 
 icmp:
        ; compare a/y to zp,x
@@ -1240,18 +1006,13 @@ icmp:
 ; VDC helpers
 
 VDCSetSourceAddr:
-       ldx     #VDC_DATA_LO
-       stx     VDC_ADDR_REG
-@L0:   bit     VDC_ADDR_REG
-       bpl     @L0
-       sta     VDC_DATA_REG
-       dex
+       pha
        tya
-@L1:   bit     VDC_ADDR_REG
-       bpl     @L1
-       stx     VDC_ADDR_REG
-       sta     VDC_DATA_REG
-       rts
+       ldx     #VDC_DATA_HI
+       jsr     VDCWriteReg
+       pla
+       ldx     #VDC_DATA_LO
+       bne     VDCWriteReg
 
 VDCReadByte:
        ldx     #VDC_DATA