[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Line drawing code
Albert Chin-A-Young asked me to post this, so here it is.
;
; Arc3D line-drawing code
; By Andy McFadden
; Adapted from code by the FTA.
;
; Draws from (clpx0,clpy0) to (clpx1,clpy1) (output of a clipping routine).
;
penColor equ $70 ;0 - 15
clpx0 equ $72
clpy0 equ $74
clpx1 equ $76
clpy1 equ $78
x0 equ $80
y0 equ $82
x1 equ $84
y1 equ $86
offset equ $88
deltax equ $8a
deltay equ $8c
diff equ $8e
even_c equ $90
odd_c equ $92
_DrawLine ENTRY
DoDrawLine ANOP
lda <clpy1 ;4 is y1 < y0?
cmp <clpy0 ;4
blt in_order ;2/3 yes, so leave alone
; lda <clpy1 ;we want y0 to be the largest,
sta y0 ; so switch
lda <clpx1
sta x0
lda <clpy0
sta y1
lda <clpx0
sta x1
bra copy_done
in_order ANOP
; lda <clpy1
sta y1
lda <clpx1
sta x1
lda <clpy0
sta y0
lda <clpx0
sta x0
; 39/41 cycles to here
; setup offset and deltas
copy_done ANOP
lda y1
asl A
asl A
adc y1
asl A
asl A
asl A
asl A
asl A
asl A
adc x1
sta offset ;16+16=32
; penColor must be between 0 and 15
lda <penColor ;setup pixel images
sta even_c ;0x000f
xba
asl A
asl A
asl A
asl A
and #$f000
sta odd_c ;0xf000
lda y0
sec
sbc y1
sta deltay ;we know y0 is larger...
beq Horizontal ;+2 do as special case
lda x1
cmp x0
beq Vertical ;+2 do as special case
; bcc Rev ;x1 is smaller; go other way
bcs Forw
brl Rev
Forw ANOP
sbc x0
sta deltax
cmp deltay
bcc Forw_bigy_j
brl Forw_bigx
Forw_bigy_j brl Forw_bigy
;
; Handle special cases (horizontal/vertical/point)
;
; handle vertical (deltax=0) lines
Vertical ANOP
lda deltay
tay ;count down
lda offset
lsr A
tax
bcc vf_odd2
clc
; bra vf_even2
; loop below
vf_even2 lda $2000,x
and #$fff0
ora even_c
sta $2000,x
txa
adc #160
tax
dey
bpl vf_even2
bra vf_done
vf_odd2 lda $1fff,x
and #$0fff
ora odd_c
sta $1fff,x
txa
adc #160
tax
dey
bpl vf_odd2
; bra vf_done
vf_done brl Exit
; handle horizontal (deltay=0) lines
Horizontal ANOP
lda x1
cmp x0
bcc h_rev ;x1 is smaller; go other way
sbc x0
sta deltax
; horizontal, moving forward
h_forw ANOP
lda deltax
tay ;count down
lda offset
lsr A
tax
bcc hf_odd2
clc
; bra hf_even2
; loop below
hf_even2 lda $2000,x
and #$fff0
ora even_c
sta $2000,x
dey
bmi hf_done
hf_odd2 lda $1fff,x
and #$0fff
ora odd_c
sta $1fff,x
dex
dey
bpl hf_even2
hf_done brl Exit
; horizontal, reverse direction
h_rev ANOP
sec
lda x0
sbc x1
sta deltax
lda deltax
tay ;count down
lda offset
lsr A
tax
bcc hr_odd2
clc
; bra hr_even2
; loop below
hr_even2 lda $2000,x
and #$fff0
ora even_c
sta $2000,x
dey
bmi hr_done
inx
hr_odd2 lda $1fff,x
and #$0fff
ora odd_c
sta $1fff,x
dey
bpl hr_even2
; bra hr_done
hr_done brl Exit
;
; Standard cases
;
; forward direction, deltay is bigger than deltax
Forw_bigy ANOP
lda deltay
tay ;count down
lsr A
eor #$ffff
inc A
sta diff
lda offset
lsr A
tax
bcc fy_odd2
clc
bra fy_even2
; loop below
fy_even1 sta diff
fy_even2 lda $2000,x
and #$fff0
ora even_c
sta $2000,x
dey
bmi fy_done
txa
adc #160
tax
lda deltax
adc diff
bmi fy_even1
sbc deltay
fy_odd1 sta diff
fy_odd2 lda $1fff,x
and #$0fff
ora odd_c
sta $1fff,x
dey
bmi fy_done
txa
adc #160
tax
lda deltax
adc diff
bmi fy_odd1
sbc deltay
dex
bra fy_even1
fy_done brl Exit
; reverse direction
Rev ANOP
sec
lda x0
sbc x1
sta deltax
cmp deltay
bcs Rev_bigx
; reverse direction, deltay is bigger than deltax
Rev_bigy ANOP
lda deltay
tay ;count down
inc A
lsr A
eor #$ffff
inc A
sta diff
lda offset
lsr A
tax
bcc ry_odd2
clc
bra ry_even2
; loop below
ry_even1 sta diff
ry_even2 lda $2000,x
and #$fff0
ora even_c
sta $2000,x
dey
bmi ry_done
txa
adc #160
tax
lda deltax
adc diff
bmi ry_even1
sbc deltay
inx
ry_odd1 sta diff
ry_odd2 lda $1fff,x
and #$0fff
ora odd_c
sta $1fff,x
dey
bmi ry_done
txa
adc #160
tax
lda deltax
adc diff
bmi ry_odd1
sbc deltay
bra ry_even1
ry_done brl Exit
; reverse direction, deltax is bigger than deltay
Rev_bigx ANOP
lda deltax
tay ;count down
lsr A
eor #$ffff
inc A
sta diff
lda offset
lsr A
tax
bcc rx_odd2
clc
bra rx_even2
; loop below
rx_even1 sta diff
rx_even2 lda $2000,x
and #$fff0
ora even_c
sta $2000,x
dey
bmi rx_done
inx
lda deltay
adc diff
bmi rx_odd1
sbc deltax
sta diff
txa
adc #160
tax
bra rx_odd2
rx_odd1 sta diff
rx_odd2 lda $1fff,x
and #$0fff
ora odd_c
sta $1fff,x
dey
bmi rx_done
lda deltay
adc diff
bmi rx_even1
sbc deltax
sta diff
txa
adc #160
tax
bra rx_even2
rx_done brl Exit
; forward direction, deltax is bigger than deltay
Forw_bigx ANOP
lda deltax
tay ;count down
lsr A
eor #$ffff
inc A
sta diff
lda offset
lsr A
tax
bcc fx_odd2
clc
bra fx_even2
; loop below
fx_even1 sta diff
fx_even2 lda $2000,x
and #$fff0
ora even_c
sta $2000,x
dey
bmi fx_done
lda deltay
adc diff
bmi fx_odd1
sbc deltax
sta diff
txa
adc #160
tax
bra fx_odd2
fx_odd1 sta diff
fx_odd2 lda $1fff,x
and #$0fff
ora odd_c
sta $1fff,x
dey
bmi fx_done
dex
lda deltay
adc diff
bmi fx_even1
sbc deltax
sta diff
txa
adc #160
tax
bra fx_even2
fx_done brl Exit
;
; common exit point
;
Exit ANOP
rtl
--
fadden@uts.amdahl.com (Andy McFadden)
[ Above opinions are mine, Amdahl has nothing to do with them, etc, etc. ]