; (values for this mode based on Fred Bowen's document)
; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
; 23.12.2002
+; 2004-04-04, Greg King
;
; NOTES:
-; For any smart monkey that will try to optimize this: PLEASE do tests on
+; 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
+; 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
+; 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
+; Register 25 ($19) is said to require different value for VDC v1, but I
; couldn't find what it should be.
.include "zeropage.inc"
pages: .byte 0 ; 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).
- .word INSTALL
- .word UNINSTALL
- .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
+ .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.
Y1 = ptr2
X2 = ptr3
Y2 = ptr4
-RADIUS = tmp1
ADDR = tmp1 ; (2) CALC
TEMP = tmp3 ; CALC icmp
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
; Line routine stuff (combined with CIRCLE to save space)
-OGora:
COUNT: .res 2
-OUkos:
NY: .res 2
-Y3:
DX: .res 1
DY: .res 1
+AX: .res 1
AY: .res 1
; Text output stuff
.byte 27, $00
.byte $ff
-SCN80CLR: .byte 27,88,147,27,88,0
+SCN80CLR: .byte 27,88,147,27,88,0
.code
INIT:
lda pages ; is there enough memory?
bne @L11 ; Jump if there is one screen
- lda #TGI_ERR_INV_MODE ; ## Error
+ lda #TGI_ERR_INV_MODE ; Error
bne @L9
; Initialize variables
; 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
- stx TEMP
- lda ADDR
- ldy ADDR+1
- jsr VDCSetSourceAddr
- jsr VDCReadByte
- ldx TEMP
+ stx TEMP
+ lda ADDR
+ ldy ADDR+1
+ jsr VDCSetSourceAddr
+ jsr VDCReadByte
+ ldx TEMP
- sta TEMP
+ sta TEMP
eor BITMASK
and BITTAB,X
- eor TEMP
- pha
- lda ADDR
- ldy ADDR+1
- jsr VDCSetSourceAddr
- pla
- jsr VDCWriteByte
+ eor TEMP
+ pha
+ lda ADDR
+ ldy ADDR+1
+ jsr VDCSetSourceAddr
+ pla
+ jsr VDCWriteByte
@L9: rts
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.
jsr abs
sta NY
sty NY+1
- ; if (x2>x1)
+ ; if (x2>=x1)
ldx #X2
lda X1
ldy X1+1
jsr icmp
bcc @L0243
- beq @L0243
; dx = 1;
lda #1
bne @L0244
; dx = -1;
@L0243: lda #$ff
@L0244: sta DX
- ; if (y2>y1)
+ ; if (y2>=y1)
ldx #Y2
lda Y1
ldy Y1+1
jsr icmp
bcc @L024A
- beq @L024A
; dy = 1;
lda #1
bne @L024B
; dy = -1;
@L024A: lda #$ff
@L024B: sta DY
- ; err = ay = 0;
+ ; err = ax = ay = 0;
lda #0
sta ERR
sta ERR+1
+ sta AX
sta AY
; if (nx<ny) {
ldx NY+1
sta NY+1
stx NX+1
- ; ay = dx
+ ; ax = dx
lda DX
+ sta AX
+ ; ay = dy
+ lda DY
sta AY
; dx = dy = 0;
lda #0
bne @L0167
rts
; setpixel(X1,Y1)
-@L0167: jsr SETPIXELCLIP
+@L0167: jsr SETPIXEL
; pb = err + ny
lda ERR
clc
lda PB
ldx PB+1
jmp @L0312
- ; } else { x1 = x1 + ay
+ ; } else { x1 = x1 + ax
@L027F:
ldx #0
- lda AY
+ lda AX
bpl @L0288
dex
@L0288: clc
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
-;
-CIRCLE:
- lda RADIUS
- bne @L1
- jmp SETPIXELCLIP ; Plot as a point
+; Original code for a horizontal line
-@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
+HORLINE:
+ lda X1
pha
- lda YS+1
- adc YY+1
- sta Y1+1 ; (stack)=ys+y, y1=(stack)
+ lda X1+1
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)
+ 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 Y1+1
+ sta X1 ; put left address into X1
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)
- 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)
+ 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
- jsr SETPIXELCLIP ; plot(xs+y,ys+x)
- lda YS
- 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)
+ lda X1
+ ldy X1+1
+ jsr VDCSetSourceAddr
pla
- sta Y1+1
+ 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
- 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)
+ jsr VDCWriteByte
- ; 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;
+@L2: ; do the fill in the middle
+ lda ADDR ; calculate offset in full bytes
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
+ 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
+
+; 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
abs:
; a/y := abs(a/y)
- dey
- iny
+ cpy #$00
bpl absend
; negay
-neg: clc
- eor #$ff
- adc #1
+neg: eor #$ff
+ add #1
pha
tya
eor #$ff