;
; Graphics driver for the 640x200x2 mode on the C128 VDC
-; Maciej 'YTM/Elysium' Witkowiak <ytm@friko.onet.pl>
-; 22.12.2002
+; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
+; 23.12.2002
;
; NOTES:
+; 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.
-;
-; All Y-axis calculations are 16-bit, so this driver will support 640x400 (interlaced)
-; mode only with gfx-mode initialization changed.
-; (is the above true? I can't remember if interlace skips lines or takes them from two
-; different places (same offset, different base))
-;
-; 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.
+; C64-mode of C128 (C64 needs full VDC init then).
;
; With special initialization and CALC we can get 320x200 double-pixel mode.
;
; primitives - for example ploting a line by using calls to SETPIXEL.
.word INSTALL
- .word DEINSTALL
+ .word UNINSTALL
.word INIT
.word DONE
.word GETERROR
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
; 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
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
; ------------------------------------------------------------------------
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
jsr VDCWriteReg ; restore color (background)
lda #$47
ldx #VDC_HSCROLL
- jmp VDCWriteReg ; switch to text screen
+ jsr VDCWriteReg ; switch to text screen
+; fall through to GETERROR in order to clear ERROR status
; ------------------------------------------------------------------------
; GETERROR: Return the error code in A and clear it.
; Must set an error code: NO
;
-CLEAR:
+CLEAR:
lda #0
ldy SCRBASE
jsr VDCSetSourceAddr
ror
ror
sta SCRBASE
- rts
+ rts
; ------------------------------------------------------------------------
; SETCOLOR: Set the drawing color (in A). The new color is already checked
;
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
+ beq @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
+ beq @L024A
+ ; dy = 1;
+ lda #1
+ bne @L024B
+ ; else
+ ; dy = -1;
+@L024A: lda #$ff
+@L024B: sta DY
+ ; err = ay = 0;
+ lda #0
+ sta ERR
+ sta ERR+1
+ sta AY
+
; if (nx<ny) {
ldx #NX
lda NY
ldy NY+1
jsr icmp
- bcs @L041B
+ bcs @L0255
; nx <-> ny
lda NX
ldx NY
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
+ ; ay = dx
+ lda DX
+ 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
rts
; setpixel(X1,Y1)
@L0167: jsr SETPIXELCLIP
- ; pb = err - ny
+ ; 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
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
jsr abs
ldx #TEMP3
jsr icmp
- bpl @L017B
+ bpl @L027F
; err = pb
lda PB
ldx PB+1
- jmp @L025B
+ jmp @L0312
; } else { x1 = x1 + ay
-@L017B:
- lda X1
- clc
- adc AY
+@L027F:
+ ldx #0
+ lda AY
+ 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)
; Must set an error code: NO
;
-CIRCLE:
+CIRCLE:
lda RADIUS
bne @L1
jmp SETPIXELCLIP ; Plot as a point
rts
; ------------------------------------------------------------------------
-; Calculate all variables to plot the pixel at X1/Y1. If the point is out
-; of range, a carry is returned and INRANGE is set to a value !0 zero. If
-; the coordinates are valid, INRANGE is zero and the carry clear.
-
+; Calculate all variables to plot the pixel at X1/Y1.
;------------------------
;< X1,Y1 - pixel
-;> ADDR - address of card, INRANGE
+;> ADDR - address of card
;> X - bit number (X1 & 7)
CALC:
lda Y1+1
; a/y := abs(a/y)
dey
iny
- bpl @L1
+ bpl absend
; negay
- clc
+neg: clc
eor #$ff
adc #1
pha
adc #0
tay
pla
-@L1: rts
+absend: rts
icmp:
; compare a/y to zp,x
; 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
- 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