Added clipping for lines.
git-svn-id: svn://svn.cc65.org/cc65/trunk@4452 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -33,13 +33,13 @@ C_OBJS = tgi_arc.o \
|
|||||||
tgi_load.o \
|
tgi_load.o \
|
||||||
tgi_load_driver.o \
|
tgi_load_driver.o \
|
||||||
tgi_load_vectorfont.o \
|
tgi_load_vectorfont.o \
|
||||||
tgi_pieslice.o
|
tgi_pieslice.o
|
||||||
|
|
||||||
S_OBJS = tgi-kernel.o \
|
S_OBJS = tgi-kernel.o \
|
||||||
tgi_bar.o \
|
tgi_bar.o \
|
||||||
tgi_circle.o \
|
tgi_circle.o \
|
||||||
tgi_clear.o \
|
tgi_clear.o \
|
||||||
tgi_clipline.o \
|
tgi_clippedline.o \
|
||||||
tgi_curtoxy.o \
|
tgi_curtoxy.o \
|
||||||
tgi_done.o \
|
tgi_done.o \
|
||||||
tgi_ellipse.o \
|
tgi_ellipse.o \
|
||||||
|
|||||||
@@ -1,494 +0,0 @@
|
|||||||
;
|
|
||||||
; Ullrich von Bassewitz, 2009-10-25
|
|
||||||
;
|
|
||||||
; Clips the line in ptr1/ptr2/ptr3/ptr4 to the screen coordinates
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
.export _tgi_clipline
|
|
||||||
.export _tgi_clip_x1, _tgi_clip_y1, _tgi_clip_x2, _tgi_clip_y2
|
|
||||||
.export _tgi_clip_o1, _tgi_clip_o2 ; Debugging!
|
|
||||||
.export _tgi_clip_dx, _tgi_clip_dy
|
|
||||||
.export _tgi_xmax, _tgi_ymax
|
|
||||||
|
|
||||||
.import negax, pushax
|
|
||||||
.import imul16x16r32, idiv32by16r16
|
|
||||||
.import return0, return1
|
|
||||||
|
|
||||||
.include "tgi-kernel.inc"
|
|
||||||
.include "zeropage.inc"
|
|
||||||
|
|
||||||
.macpack longbranch
|
|
||||||
|
|
||||||
.code
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; outcode constants. These aren't really used because most stuff is done by
|
|
||||||
; shifting the values, but they're here for documentation.
|
|
||||||
|
|
||||||
CLIP_NONE = $00
|
|
||||||
CLIP_LEFT = $01
|
|
||||||
CLIP_RIGHT = $02
|
|
||||||
CLIP_BOTTOM = $04
|
|
||||||
CLIP_TOP = $08
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; Generate a Cohen Sutherland outcode for tgi_clip_x1/tgi_clip_y1 in _tgi_clip_o1
|
|
||||||
;
|
|
||||||
; void outcode1 ()
|
|
||||||
; {
|
|
||||||
; _tgi_clip_o1 = 0;
|
|
||||||
; if (Y1 < 0) {
|
|
||||||
; _tgi_clip_o1 = CLIP_BOTTOM;
|
|
||||||
; } else if (Y1 >= yres) {
|
|
||||||
; _tgi_clip_o1 = CLIP_TOP;
|
|
||||||
; }
|
|
||||||
; if (X1 < 0) {
|
|
||||||
; _tgi_clip_o1 |= CLIP_LEFT;
|
|
||||||
; } else if (X1 >= xres) {
|
|
||||||
; _tgi_clip_o1 |= CLIP_RIGHT;
|
|
||||||
; }
|
|
||||||
; }
|
|
||||||
|
|
||||||
.proc outcode1
|
|
||||||
|
|
||||||
ldy #CLIP_BOTTOM ; Assume line needs bottom clip
|
|
||||||
|
|
||||||
; Check Y coordinate
|
|
||||||
|
|
||||||
lda _tgi_clip_y1+1 ; High byte of Y1
|
|
||||||
bmi L2 ; Jump if bottom clip
|
|
||||||
|
|
||||||
ldy #CLIP_TOP ; Assume line needs top clip
|
|
||||||
ldx _tgi_clip_y1 ; Low byte of Y1
|
|
||||||
cpx _tgi_yres
|
|
||||||
sbc _tgi_yres+1
|
|
||||||
bvs L1
|
|
||||||
eor #$80
|
|
||||||
L1: bmi L2
|
|
||||||
|
|
||||||
ldy #CLIP_NONE ; No clipping actually
|
|
||||||
|
|
||||||
L2: sty _tgi_clip_o1
|
|
||||||
|
|
||||||
|
|
||||||
; Check X coordinate
|
|
||||||
|
|
||||||
ldy #CLIP_LEFT ; Assume line needs left clip
|
|
||||||
|
|
||||||
lda _tgi_clip_x1+1 ; High byte of X1
|
|
||||||
bmi L4 ; Jump if left clip
|
|
||||||
|
|
||||||
ldy #CLIP_RIGHT ; Assume line needs right clip
|
|
||||||
|
|
||||||
ldx _tgi_clip_x1 ; Low byte of X1
|
|
||||||
cpx _tgi_xres
|
|
||||||
sbc _tgi_xres+1
|
|
||||||
bvs L3
|
|
||||||
eor #$80
|
|
||||||
L3: bmi L4
|
|
||||||
|
|
||||||
ldy #CLIP_NONE ; No clipping actually
|
|
||||||
|
|
||||||
L4: tya
|
|
||||||
ora _tgi_clip_o1
|
|
||||||
sta _tgi_clip_o1
|
|
||||||
|
|
||||||
rts
|
|
||||||
|
|
||||||
.endproc
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; Generate a Cohen Sutherland outcode for tgi_clip_x2/tgi_clip_y2 in _tgi_clip_o2
|
|
||||||
;
|
|
||||||
; void outcode2 ()
|
|
||||||
; {
|
|
||||||
; _tgi_clip_o2 = 0;
|
|
||||||
; if (Y2 < 0) {
|
|
||||||
; _tgi_clip_o2 = CLIP_BOTTOM;
|
|
||||||
; } else if (Y2 >= yres) {
|
|
||||||
; _tgi_clip_o2 = CLIP_TOP;
|
|
||||||
; }
|
|
||||||
; if (X2 < 0) {
|
|
||||||
; _tgi_clip_o2 |= CLIP_LEFT;
|
|
||||||
; } else if (X2 >= xres) {
|
|
||||||
; _tgi_clip_o2 |= CLIP_RIGHT;
|
|
||||||
; }
|
|
||||||
; }
|
|
||||||
|
|
||||||
.proc outcode2
|
|
||||||
|
|
||||||
ldy #CLIP_BOTTOM ; Assume line needs bottom clip
|
|
||||||
|
|
||||||
; Check Y coordinate
|
|
||||||
|
|
||||||
lda _tgi_clip_y2+1 ; High byte of Y2
|
|
||||||
bmi L2 ; Jump if bottom clip
|
|
||||||
|
|
||||||
ldy #CLIP_TOP ; Assume line needs top clip
|
|
||||||
ldx _tgi_clip_y2 ; Low byte of Y4
|
|
||||||
cpx _tgi_yres
|
|
||||||
sbc _tgi_yres+1
|
|
||||||
bvs L1
|
|
||||||
eor #$80
|
|
||||||
L1: bmi L2
|
|
||||||
|
|
||||||
ldy #CLIP_NONE ; No clipping actually
|
|
||||||
|
|
||||||
L2: sty _tgi_clip_o2
|
|
||||||
|
|
||||||
|
|
||||||
; Check X coordinate
|
|
||||||
|
|
||||||
ldy #CLIP_LEFT ; Assume line needs left clip
|
|
||||||
|
|
||||||
lda _tgi_clip_x2+1 ; High byte of X2
|
|
||||||
bmi L4 ; Jump if left clip
|
|
||||||
|
|
||||||
ldy #CLIP_RIGHT ; Assume line needs right clip
|
|
||||||
|
|
||||||
ldx _tgi_clip_x2 ; Low byte of X2
|
|
||||||
cpx _tgi_xres
|
|
||||||
sbc _tgi_xres+1
|
|
||||||
bvs L3
|
|
||||||
eor #$80
|
|
||||||
L3: bmi L4
|
|
||||||
|
|
||||||
ldy #CLIP_NONE ; No clipping actually
|
|
||||||
|
|
||||||
L4: tya
|
|
||||||
ora _tgi_clip_o2
|
|
||||||
sta _tgi_clip_o2
|
|
||||||
|
|
||||||
rts
|
|
||||||
|
|
||||||
.endproc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; Calculate dx and dy
|
|
||||||
;
|
|
||||||
|
|
||||||
.proc calcdeltas
|
|
||||||
|
|
||||||
lda _tgi_clip_x2
|
|
||||||
sec
|
|
||||||
sbc _tgi_clip_x1
|
|
||||||
sta _tgi_clip_dx
|
|
||||||
lda _tgi_clip_x2+1
|
|
||||||
sbc _tgi_clip_x1+1
|
|
||||||
sta _tgi_clip_dx+1
|
|
||||||
|
|
||||||
lda _tgi_clip_y2
|
|
||||||
sec
|
|
||||||
sbc _tgi_clip_y1
|
|
||||||
sta _tgi_clip_dy
|
|
||||||
lda _tgi_clip_y2+1
|
|
||||||
sbc _tgi_clip_y1+1
|
|
||||||
sta _tgi_clip_dy+1
|
|
||||||
|
|
||||||
rts
|
|
||||||
|
|
||||||
.endproc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; Multiplicate value in y/a by dy, then divide by dx.
|
|
||||||
;
|
|
||||||
|
|
||||||
.proc muldiv_dydx
|
|
||||||
|
|
||||||
sty ptr1 ; lhs
|
|
||||||
sta ptr1+1
|
|
||||||
lda _tgi_clip_dy
|
|
||||||
ldx _tgi_clip_dy+1 ; rhs
|
|
||||||
jsr imul16x16r32 ; Multiplicate
|
|
||||||
|
|
||||||
; Move the result of the multiplication into ptr1:ptr2
|
|
||||||
|
|
||||||
sta ptr1
|
|
||||||
stx ptr1+1
|
|
||||||
ldy sreg
|
|
||||||
sty ptr2
|
|
||||||
ldy sreg+1
|
|
||||||
sty ptr2+1
|
|
||||||
|
|
||||||
; Load divisor and divide
|
|
||||||
|
|
||||||
lda _tgi_clip_dx
|
|
||||||
ldx _tgi_clip_dx+1
|
|
||||||
jmp idiv32by16r16
|
|
||||||
|
|
||||||
.endproc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; Multiplicate value in y/a by dx, then divide by dy.
|
|
||||||
;
|
|
||||||
|
|
||||||
.proc muldiv_dxdy
|
|
||||||
|
|
||||||
sty ptr1 ; lhs
|
|
||||||
sta ptr1+1
|
|
||||||
lda _tgi_clip_dx
|
|
||||||
ldx _tgi_clip_dx+1 ; rhs
|
|
||||||
jsr imul16x16r32 ; Multiplicate
|
|
||||||
|
|
||||||
; Move the result of the multiplication into ptr1:ptr2
|
|
||||||
|
|
||||||
sta ptr1
|
|
||||||
stx ptr1+1
|
|
||||||
ldy sreg
|
|
||||||
sty ptr2
|
|
||||||
ldy sreg+1
|
|
||||||
sty ptr2+1
|
|
||||||
|
|
||||||
; Load divisor and divide
|
|
||||||
|
|
||||||
lda _tgi_clip_dy
|
|
||||||
ldx _tgi_clip_dy+1
|
|
||||||
jmp idiv32by16r16
|
|
||||||
|
|
||||||
.endproc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; Clip a line using Cohen Sutherland
|
|
||||||
;
|
|
||||||
|
|
||||||
.proc _tgi_clipline
|
|
||||||
|
|
||||||
; Generate outcodes
|
|
||||||
|
|
||||||
jsr outcode1
|
|
||||||
jsr outcode2
|
|
||||||
jsr calcdeltas
|
|
||||||
|
|
||||||
; if ((_tgi_clip_o1 | _tgi_clip_o2) == 0) accept;
|
|
||||||
|
|
||||||
Loop: lda _tgi_clip_o1
|
|
||||||
ora _tgi_clip_o2
|
|
||||||
bne L1
|
|
||||||
jmp return0
|
|
||||||
|
|
||||||
; if ((_tgi_clip_o1 & _tgi_clip_o2) != 0) reject;
|
|
||||||
|
|
||||||
L1: lda _tgi_clip_o1
|
|
||||||
and _tgi_clip_o2
|
|
||||||
beq L2
|
|
||||||
jmp return1
|
|
||||||
|
|
||||||
; Check if X1/Y1 needs clipping
|
|
||||||
|
|
||||||
L2: lda _tgi_clip_o1
|
|
||||||
jeq L10
|
|
||||||
|
|
||||||
; Need to clip X1/Y1
|
|
||||||
|
|
||||||
lsr a ; Check for CLIP_LEFT
|
|
||||||
bcc L3
|
|
||||||
|
|
||||||
; tgi_clip_y1 += (0 - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
|
|
||||||
; tgi_clip_x1 = 0;
|
|
||||||
|
|
||||||
lda #$00
|
|
||||||
tax
|
|
||||||
beq L4
|
|
||||||
|
|
||||||
L3: lsr a ; Check for CLIP_RIGHT
|
|
||||||
bcc L5
|
|
||||||
|
|
||||||
; tgi_clip_y1 += (tgi_xmax - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
|
|
||||||
; tgi_clip_x1 = tgi_xmax;
|
|
||||||
|
|
||||||
lda _tgi_xmax
|
|
||||||
ldx _tgi_xmax+1
|
|
||||||
|
|
||||||
L4: tay
|
|
||||||
sec
|
|
||||||
sbc _tgi_clip_x1
|
|
||||||
sty _tgi_clip_x1
|
|
||||||
tay
|
|
||||||
txa
|
|
||||||
sbc _tgi_clip_x1+1
|
|
||||||
stx _tgi_clip_x1+1
|
|
||||||
|
|
||||||
jsr muldiv_dydx
|
|
||||||
|
|
||||||
clc
|
|
||||||
adc _tgi_clip_y1
|
|
||||||
sta _tgi_clip_y1
|
|
||||||
txa
|
|
||||||
adc _tgi_clip_y1+1
|
|
||||||
sta _tgi_clip_y1+1
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
lda _tgi_clip_o1
|
|
||||||
lsr a
|
|
||||||
lsr a
|
|
||||||
L5: lsr a ; Check for CLIP_BOTTOM
|
|
||||||
bcc L6
|
|
||||||
|
|
||||||
; tgi_clip_x1 = (0 - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
|
|
||||||
; tgi_clip_y1 = 0;
|
|
||||||
|
|
||||||
lda #$00
|
|
||||||
tax
|
|
||||||
beq L7
|
|
||||||
|
|
||||||
L6: lsr a ; Check for CLIP_TOP
|
|
||||||
bcc L8
|
|
||||||
|
|
||||||
; tgi_clip_x1 += (tgi_ymax - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
|
|
||||||
; tgi_clip_y1 = ymax;
|
|
||||||
|
|
||||||
lda _tgi_ymax
|
|
||||||
ldx _tgi_ymax+1
|
|
||||||
|
|
||||||
L7: tay
|
|
||||||
sec
|
|
||||||
sbc _tgi_clip_y1
|
|
||||||
sty _tgi_clip_y1
|
|
||||||
tay
|
|
||||||
txa
|
|
||||||
sbc _tgi_clip_y1+1
|
|
||||||
stx _tgi_clip_y1+1
|
|
||||||
|
|
||||||
jsr muldiv_dxdy
|
|
||||||
|
|
||||||
clc
|
|
||||||
adc _tgi_clip_x1
|
|
||||||
sta _tgi_clip_x1
|
|
||||||
txa
|
|
||||||
adc _tgi_clip_x1+1
|
|
||||||
sta _tgi_clip_x1+1
|
|
||||||
|
|
||||||
; We need to recalculate outcode1 in this case
|
|
||||||
|
|
||||||
L8: jsr outcode1
|
|
||||||
|
|
||||||
; Check if X2/Y2 needs clipping
|
|
||||||
|
|
||||||
L10: lda _tgi_clip_o2
|
|
||||||
jeq Loop
|
|
||||||
|
|
||||||
; Need to clip X2/Y2
|
|
||||||
|
|
||||||
lsr a ; Check for CLIP_LEFT
|
|
||||||
bcc L11
|
|
||||||
|
|
||||||
; tgi_clip_y2 += (0 - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
|
|
||||||
; tgi_clip_x2 = 0;
|
|
||||||
|
|
||||||
lda #$00
|
|
||||||
tax
|
|
||||||
beq L12
|
|
||||||
|
|
||||||
L11: lsr a ; Check for CLIP_RIGHT
|
|
||||||
bcc L13
|
|
||||||
|
|
||||||
; tgi_clip_y2 += (tgi_xmax - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
|
|
||||||
; tgi_clip_x2 = tgi_xmax;
|
|
||||||
|
|
||||||
lda _tgi_xmax
|
|
||||||
ldx _tgi_xmax+1
|
|
||||||
|
|
||||||
L12: tay
|
|
||||||
sec
|
|
||||||
sbc _tgi_clip_x2
|
|
||||||
sty _tgi_clip_x2
|
|
||||||
tay
|
|
||||||
txa
|
|
||||||
sbc _tgi_clip_x2+1
|
|
||||||
stx _tgi_clip_x2+1
|
|
||||||
|
|
||||||
jsr muldiv_dydx
|
|
||||||
|
|
||||||
clc
|
|
||||||
adc _tgi_clip_y2
|
|
||||||
sta _tgi_clip_y2
|
|
||||||
txa
|
|
||||||
adc _tgi_clip_y2+1
|
|
||||||
sta _tgi_clip_y2+1
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
lda _tgi_clip_o2
|
|
||||||
lsr a
|
|
||||||
lsr a
|
|
||||||
L13: lsr a ; Check for CLIP_BOTTOM
|
|
||||||
bcc L14
|
|
||||||
|
|
||||||
; tgi_clip_x2 += (0 - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
|
|
||||||
; tgi_clip_y2 = 0;
|
|
||||||
|
|
||||||
lda #$00
|
|
||||||
tax
|
|
||||||
beq L15
|
|
||||||
|
|
||||||
L14: lsr a ; Check for CLIP_TOP
|
|
||||||
bcc L16
|
|
||||||
|
|
||||||
; tgi_clip_x2 += (tgi_ymax - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
|
|
||||||
; tgi_clip_y2 = tgi_ymax;
|
|
||||||
|
|
||||||
lda _tgi_ymax
|
|
||||||
ldx _tgi_ymax+1
|
|
||||||
|
|
||||||
L15: tay
|
|
||||||
sec
|
|
||||||
sbc _tgi_clip_y2
|
|
||||||
sty _tgi_clip_y2
|
|
||||||
tay
|
|
||||||
txa
|
|
||||||
sbc _tgi_clip_y2+1
|
|
||||||
stx _tgi_clip_y2+1
|
|
||||||
|
|
||||||
jsr muldiv_dxdy
|
|
||||||
|
|
||||||
clc
|
|
||||||
adc _tgi_clip_x2
|
|
||||||
sta _tgi_clip_x2
|
|
||||||
txa
|
|
||||||
adc _tgi_clip_x2+1
|
|
||||||
sta _tgi_clip_x2+1
|
|
||||||
|
|
||||||
; We need to recalculate outcode2 in this case
|
|
||||||
|
|
||||||
L16: jsr outcode2
|
|
||||||
|
|
||||||
; Try again
|
|
||||||
|
|
||||||
jmp Loop
|
|
||||||
|
|
||||||
.endproc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
|
||||||
; Data
|
|
||||||
|
|
||||||
.bss
|
|
||||||
|
|
||||||
_tgi_clip_x1: .res 2
|
|
||||||
_tgi_clip_y1: .res 2
|
|
||||||
_tgi_clip_x2: .res 2
|
|
||||||
_tgi_clip_y2: .res 2
|
|
||||||
|
|
||||||
_tgi_clip_o1: .res 1
|
|
||||||
_tgi_clip_o2: .res 1
|
|
||||||
|
|
||||||
_tgi_clip_dx: .res 2
|
|
||||||
_tgi_clip_dy: .res 2
|
|
||||||
|
|
||||||
_tgi_xmax: .res 2
|
|
||||||
_tgi_ymax: .res 2
|
|
||||||
565
libsrc/tgi/tgi_clippedline.s
Normal file
565
libsrc/tgi/tgi_clippedline.s
Normal file
@@ -0,0 +1,565 @@
|
|||||||
|
;
|
||||||
|
; Ullrich von Bassewitz, 2009-10-25
|
||||||
|
;
|
||||||
|
; Clips line coordinates to the screen coordinates and calls tgi_line
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
.import umul16x16r32, udiv32by16r16
|
||||||
|
.import negax
|
||||||
|
|
||||||
|
.include "tgi-kernel.inc"
|
||||||
|
.include "zeropage.inc"
|
||||||
|
|
||||||
|
.macpack longbranch
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Data
|
||||||
|
|
||||||
|
.bss
|
||||||
|
|
||||||
|
; Line coordinates. Must be set before calling tgi_clippedline
|
||||||
|
tgi_clip_x1: .res 2
|
||||||
|
tgi_clip_y1: .res 2
|
||||||
|
tgi_clip_x2: .res 2
|
||||||
|
tgi_clip_y2: .res 2
|
||||||
|
|
||||||
|
tgi_clip_o1: .res 1
|
||||||
|
tgi_clip_o2: .res 1
|
||||||
|
|
||||||
|
tgi_clip_d: .res 1
|
||||||
|
tgi_clip_dx: .res 2
|
||||||
|
tgi_clip_dy: .res 2
|
||||||
|
|
||||||
|
tgi_clip_sign: .res 1
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; outcode constants.
|
||||||
|
|
||||||
|
CLIP_NONE = $00
|
||||||
|
CLIP_LEFT = $01
|
||||||
|
CLIP_RIGHT = $02
|
||||||
|
CLIP_BOTTOM = $04
|
||||||
|
CLIP_TOP = $08
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Generate a Cohen Sutherland outcode
|
||||||
|
;
|
||||||
|
; void outcode ()
|
||||||
|
; {
|
||||||
|
; unsigned char o = 0;
|
||||||
|
; if (Y < 0) {
|
||||||
|
; o = CLIP_BOTTOM;
|
||||||
|
; } else if (Y >= yres) {
|
||||||
|
; o = CLIP_TOP;
|
||||||
|
; }
|
||||||
|
; if (X < 0) {
|
||||||
|
; o |= CLIP_LEFT;
|
||||||
|
; } else if (X >= xres) {
|
||||||
|
; o |= CLIP_RIGHT;
|
||||||
|
; }
|
||||||
|
; return o;
|
||||||
|
; }
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc outcode
|
||||||
|
|
||||||
|
lda #CLIP_NONE
|
||||||
|
sta tmp1
|
||||||
|
|
||||||
|
; Check Y coordinate
|
||||||
|
|
||||||
|
lda tgi_clip_y1+1,y ; High byte of Y1
|
||||||
|
bmi L2 ; Jump if bottom clip
|
||||||
|
|
||||||
|
ldx tgi_clip_y1,y ; Low byte of Y1
|
||||||
|
cpx _tgi_yres
|
||||||
|
sbc _tgi_yres+1
|
||||||
|
bvs L1
|
||||||
|
eor #$80
|
||||||
|
L1: bpl L4
|
||||||
|
lda #CLIP_TOP ; Top clipping necessary
|
||||||
|
bne L3
|
||||||
|
L2: lda #CLIP_BOTTOM
|
||||||
|
L3: sta tmp1 ; Save temp outcode
|
||||||
|
|
||||||
|
|
||||||
|
; Check X coordinate
|
||||||
|
|
||||||
|
L4: lda tgi_clip_x1+1,y ; High byte of X1
|
||||||
|
bmi L7 ; Jump if left clip
|
||||||
|
|
||||||
|
ldx tgi_clip_x1,y ; Low byte of X1
|
||||||
|
cpx _tgi_xres
|
||||||
|
sbc _tgi_xres+1
|
||||||
|
bvs L5
|
||||||
|
eor #$80
|
||||||
|
L5: bmi L6
|
||||||
|
|
||||||
|
; No right or left clipping necessary
|
||||||
|
|
||||||
|
lda tmp1
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Need right clipping
|
||||||
|
|
||||||
|
L6: lda #CLIP_RIGHT
|
||||||
|
ora tmp1
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Need left clipping
|
||||||
|
|
||||||
|
L7: lda #CLIP_LEFT
|
||||||
|
ora tmp1
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Calculate outcodes for both ends of the line
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc outcode1
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
jsr outcode
|
||||||
|
sta tgi_clip_o1
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc outcode2
|
||||||
|
|
||||||
|
ldy #(tgi_clip_y2 - tgi_clip_y1)
|
||||||
|
jsr outcode
|
||||||
|
sta tgi_clip_o2
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Negate tgi_clip_dxy
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc negate
|
||||||
|
|
||||||
|
lda tgi_clip_dx,y
|
||||||
|
eor #$FF
|
||||||
|
clc
|
||||||
|
adc #1
|
||||||
|
sta tgi_clip_dx,y
|
||||||
|
lda tgi_clip_dx+1,y
|
||||||
|
eor #$FF
|
||||||
|
adc #$00
|
||||||
|
sta tgi_clip_dx+1,y
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Calculate the absolute values of dx and dy and store the combined sign in
|
||||||
|
; tgi_clip_sign
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc calcdeltas
|
||||||
|
|
||||||
|
lda tgi_clip_x2
|
||||||
|
sec
|
||||||
|
sbc tgi_clip_x1
|
||||||
|
sta tgi_clip_dx
|
||||||
|
lda tgi_clip_x2+1
|
||||||
|
sbc tgi_clip_x1+1
|
||||||
|
sta tgi_clip_dx+1
|
||||||
|
sta tgi_clip_sign
|
||||||
|
bpl @L1
|
||||||
|
ldy #0
|
||||||
|
jsr negate
|
||||||
|
|
||||||
|
@L1: lda tgi_clip_y2
|
||||||
|
sec
|
||||||
|
sbc tgi_clip_y1
|
||||||
|
sta tgi_clip_dy
|
||||||
|
lda tgi_clip_y2+1
|
||||||
|
sbc tgi_clip_y1+1
|
||||||
|
sta tgi_clip_dy+1
|
||||||
|
|
||||||
|
eor tgi_clip_sign
|
||||||
|
sta tgi_clip_sign
|
||||||
|
|
||||||
|
bit tgi_clip_dy+1
|
||||||
|
bpl @L9
|
||||||
|
|
||||||
|
ldy #(tgi_clip_dy - tgi_clip_dx)
|
||||||
|
jmp negate
|
||||||
|
|
||||||
|
@L9: rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Helper routine. Generate the absolute value of y/a and calculate the sign
|
||||||
|
; of the final result
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc prepare_coord
|
||||||
|
|
||||||
|
tax ; Remember high byte
|
||||||
|
eor tgi_clip_sign
|
||||||
|
sta tmp1 ; Sign of result
|
||||||
|
tya
|
||||||
|
cpx #0 ; Check sign
|
||||||
|
bpl @L1
|
||||||
|
jsr negax
|
||||||
|
@L1: sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Helper routine. Move the value in eax to ptr1:ptr2
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc move_intermediate_result
|
||||||
|
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
ldy sreg
|
||||||
|
sty ptr2
|
||||||
|
ldy sreg+1
|
||||||
|
sty ptr2+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Multiplicate value in y/a by dy, then divide by dx.
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc muldiv_dydx
|
||||||
|
|
||||||
|
; Generate the absolute value of y/a and calculate the sign of the final
|
||||||
|
; result
|
||||||
|
|
||||||
|
jsr prepare_coord
|
||||||
|
|
||||||
|
; All values are positive now (dx/dy have been made positive in calcdeltas)
|
||||||
|
; and the sign of the final result is on tmp1, so we can use unsigned
|
||||||
|
; operations and apply the final result later, after rounding.
|
||||||
|
|
||||||
|
lda tgi_clip_dy
|
||||||
|
ldx tgi_clip_dy+1 ; rhs
|
||||||
|
jsr umul16x16r32 ; Multiplicate
|
||||||
|
|
||||||
|
; Move the result of the multiplication into ptr1:ptr2
|
||||||
|
|
||||||
|
jsr move_intermediate_result
|
||||||
|
|
||||||
|
; Load divisor and divide
|
||||||
|
|
||||||
|
lda tgi_clip_dx
|
||||||
|
ldx tgi_clip_dx+1
|
||||||
|
jsr udiv32by16r16
|
||||||
|
|
||||||
|
; Check the sign of the final result and negate it if nessary
|
||||||
|
|
||||||
|
done: bit tmp1
|
||||||
|
jmi negax
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Multiplicate value in y/a by dx, then divide by dy.
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc muldiv_dxdy
|
||||||
|
|
||||||
|
; Generate the absolute value of y/a and calculate the sign of the final
|
||||||
|
; result
|
||||||
|
|
||||||
|
jsr prepare_coord
|
||||||
|
|
||||||
|
; All values are positive now (dx/dy have been made positive in calcdeltas)
|
||||||
|
; and the sign of the final result is on tmp1, so we can use unsigned
|
||||||
|
; operations and apply the final result later, after rounding.
|
||||||
|
|
||||||
|
lda tgi_clip_dx
|
||||||
|
ldx tgi_clip_dx+1 ; rhs
|
||||||
|
jsr umul16x16r32 ; Multiplicate
|
||||||
|
|
||||||
|
; Move the result of the multiplication into ptr1:ptr2
|
||||||
|
|
||||||
|
jsr move_intermediate_result
|
||||||
|
|
||||||
|
; Load divisor and divide
|
||||||
|
|
||||||
|
lda tgi_clip_dy
|
||||||
|
ldx tgi_clip_dy+1
|
||||||
|
jsr udiv32by16r16
|
||||||
|
|
||||||
|
; Check the sign of the final result and negate it if nessary
|
||||||
|
|
||||||
|
jmp muldiv_dydx::done
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Clip a line using Cohen Sutherland
|
||||||
|
;
|
||||||
|
|
||||||
|
.code
|
||||||
|
.proc tgi_clippedline
|
||||||
|
|
||||||
|
; Set a flag that we have no deltas calculated
|
||||||
|
|
||||||
|
lda #0
|
||||||
|
sta tgi_clip_d
|
||||||
|
|
||||||
|
; Generate outcodes
|
||||||
|
|
||||||
|
jsr outcode1
|
||||||
|
jsr outcode2
|
||||||
|
|
||||||
|
; if ((tgi_clip_o1 | tgi_clip_o2) == 0) {
|
||||||
|
; tgi_line (x1, y1, x2, y2);
|
||||||
|
; }
|
||||||
|
|
||||||
|
Loop: lda tgi_clip_o1
|
||||||
|
ora tgi_clip_o2
|
||||||
|
bne L1
|
||||||
|
|
||||||
|
; Copy the coordinates into ptr1-4 and draw the line
|
||||||
|
|
||||||
|
ldx #7
|
||||||
|
L0: lda tgi_clip_x1,x
|
||||||
|
sta ptr1,x
|
||||||
|
dex
|
||||||
|
bpl L0
|
||||||
|
jmp tgi_line
|
||||||
|
|
||||||
|
; if ((tgi_clip_o1 & tgi_clip_o2) != 0) reject;
|
||||||
|
|
||||||
|
L1: lda tgi_clip_o1
|
||||||
|
and tgi_clip_o2
|
||||||
|
beq L2
|
||||||
|
rts ; Nothing to draw
|
||||||
|
|
||||||
|
; We must clip. If we haven't already done so, calculate dx/dy.
|
||||||
|
|
||||||
|
L2: lda tgi_clip_d ; Deltas alreay calculated?
|
||||||
|
bne HaveDeltas ; Jump if yes
|
||||||
|
inc tgi_clip_d
|
||||||
|
jsr calcdeltas
|
||||||
|
|
||||||
|
; Check if X1/Y1 needs clipping
|
||||||
|
|
||||||
|
HaveDeltas:
|
||||||
|
lda tgi_clip_o1
|
||||||
|
jeq L10
|
||||||
|
|
||||||
|
; Need to clip X1/Y1
|
||||||
|
|
||||||
|
lsr a ; Check for CLIP_LEFT
|
||||||
|
bcc L3
|
||||||
|
|
||||||
|
; tgi_clip_y1 += (0 - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
|
||||||
|
; tgi_clip_x1 = 0;
|
||||||
|
|
||||||
|
lda #$00
|
||||||
|
tax
|
||||||
|
beq L4
|
||||||
|
|
||||||
|
L3: lsr a ; Check for CLIP_RIGHT
|
||||||
|
bcc L5
|
||||||
|
|
||||||
|
; tgi_clip_y1 += (tgi_xmax - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
|
||||||
|
; tgi_clip_x1 = tgi_xmax;
|
||||||
|
|
||||||
|
lda _tgi_xmax
|
||||||
|
ldx _tgi_xmax+1
|
||||||
|
|
||||||
|
L4: tay
|
||||||
|
sec
|
||||||
|
sbc tgi_clip_x1
|
||||||
|
sty tgi_clip_x1
|
||||||
|
tay
|
||||||
|
txa
|
||||||
|
sbc tgi_clip_x1+1
|
||||||
|
stx tgi_clip_x1+1
|
||||||
|
|
||||||
|
jsr muldiv_dydx
|
||||||
|
|
||||||
|
clc
|
||||||
|
adc tgi_clip_y1
|
||||||
|
sta tgi_clip_y1
|
||||||
|
txa
|
||||||
|
adc tgi_clip_y1+1
|
||||||
|
sta tgi_clip_y1+1
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
lda tgi_clip_o1
|
||||||
|
lsr a
|
||||||
|
lsr a
|
||||||
|
L5: lsr a ; Check for CLIP_BOTTOM
|
||||||
|
bcc L6
|
||||||
|
|
||||||
|
; tgi_clip_x1 = (0 - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
|
||||||
|
; tgi_clip_y1 = 0;
|
||||||
|
|
||||||
|
lda #$00
|
||||||
|
tax
|
||||||
|
beq L7
|
||||||
|
|
||||||
|
L6: lsr a ; Check for CLIP_TOP
|
||||||
|
bcc L8
|
||||||
|
|
||||||
|
; tgi_clip_x1 += (tgi_ymax - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
|
||||||
|
; tgi_clip_y1 = ymax;
|
||||||
|
|
||||||
|
lda _tgi_ymax
|
||||||
|
ldx _tgi_ymax+1
|
||||||
|
|
||||||
|
L7: tay
|
||||||
|
sec
|
||||||
|
sbc tgi_clip_y1
|
||||||
|
sty tgi_clip_y1
|
||||||
|
tay
|
||||||
|
txa
|
||||||
|
sbc tgi_clip_y1+1
|
||||||
|
stx tgi_clip_y1+1
|
||||||
|
|
||||||
|
jsr muldiv_dxdy
|
||||||
|
|
||||||
|
clc
|
||||||
|
adc tgi_clip_x1
|
||||||
|
sta tgi_clip_x1
|
||||||
|
txa
|
||||||
|
adc tgi_clip_x1+1
|
||||||
|
sta tgi_clip_x1+1
|
||||||
|
|
||||||
|
; We need to recalculate outcode1 in this case
|
||||||
|
|
||||||
|
L8: jsr outcode1
|
||||||
|
|
||||||
|
; Check if X2/Y2 needs clipping
|
||||||
|
|
||||||
|
L10: lda tgi_clip_o2
|
||||||
|
jeq Loop
|
||||||
|
|
||||||
|
; Need to clip X2/Y2
|
||||||
|
|
||||||
|
lsr a ; Check for CLIP_LEFT
|
||||||
|
bcc L11
|
||||||
|
|
||||||
|
; tgi_clip_y2 += (0 - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
|
||||||
|
; tgi_clip_x2 = 0;
|
||||||
|
|
||||||
|
lda #$00
|
||||||
|
tax
|
||||||
|
beq L12
|
||||||
|
|
||||||
|
L11: lsr a ; Check for CLIP_RIGHT
|
||||||
|
bcc L13
|
||||||
|
|
||||||
|
; tgi_clip_y2 += (tgi_xmax - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
|
||||||
|
; tgi_clip_x2 = tgi_xmax;
|
||||||
|
|
||||||
|
lda _tgi_xmax
|
||||||
|
ldx _tgi_xmax+1
|
||||||
|
|
||||||
|
L12: tay
|
||||||
|
sec
|
||||||
|
sbc tgi_clip_x2
|
||||||
|
sty tgi_clip_x2
|
||||||
|
tay
|
||||||
|
txa
|
||||||
|
sbc tgi_clip_x2+1
|
||||||
|
stx tgi_clip_x2+1
|
||||||
|
|
||||||
|
jsr muldiv_dydx
|
||||||
|
|
||||||
|
clc
|
||||||
|
adc tgi_clip_y2
|
||||||
|
sta tgi_clip_y2
|
||||||
|
txa
|
||||||
|
adc tgi_clip_y2+1
|
||||||
|
sta tgi_clip_y2+1
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
lda tgi_clip_o2
|
||||||
|
lsr a
|
||||||
|
lsr a
|
||||||
|
L13: lsr a ; Check for CLIP_BOTTOM
|
||||||
|
bcc L14
|
||||||
|
|
||||||
|
; tgi_clip_x2 += (0 - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
|
||||||
|
; tgi_clip_y2 = 0;
|
||||||
|
|
||||||
|
lda #$00
|
||||||
|
tax
|
||||||
|
beq L15
|
||||||
|
|
||||||
|
L14: lsr a ; Check for CLIP_TOP
|
||||||
|
bcc L16
|
||||||
|
|
||||||
|
; tgi_clip_x2 += (tgi_ymax - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
|
||||||
|
; tgi_clip_y2 = tgi_ymax;
|
||||||
|
|
||||||
|
lda _tgi_ymax
|
||||||
|
ldx _tgi_ymax+1
|
||||||
|
|
||||||
|
L15: tay
|
||||||
|
sec
|
||||||
|
sbc tgi_clip_y2
|
||||||
|
sty tgi_clip_y2
|
||||||
|
tay
|
||||||
|
txa
|
||||||
|
sbc tgi_clip_y2+1
|
||||||
|
stx tgi_clip_y2+1
|
||||||
|
|
||||||
|
jsr muldiv_dxdy
|
||||||
|
|
||||||
|
clc
|
||||||
|
adc tgi_clip_x2
|
||||||
|
sta tgi_clip_x2
|
||||||
|
txa
|
||||||
|
adc tgi_clip_x2+1
|
||||||
|
sta tgi_clip_x2+1
|
||||||
|
|
||||||
|
; We need to recalculate outcode2 in this case
|
||||||
|
|
||||||
|
L16: jsr outcode2
|
||||||
|
|
||||||
|
; Try again
|
||||||
|
|
||||||
|
jmp Loop
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,10 +11,14 @@
|
|||||||
|
|
||||||
.proc _tgi_line
|
.proc _tgi_line
|
||||||
|
|
||||||
jsr tgi_linepop ; Pop/store Y2/X2
|
jsr tgi_linepop ; Pop/store Y2/X2
|
||||||
jsr popax
|
jsr popax ; Y1
|
||||||
jsr tgi_popxy ; Pop/store X1/Y1 into ptr1/ptr2
|
sta tgi_clip_y1
|
||||||
jmp tgi_line ; Call the driver
|
stx tgi_clip_y1+1
|
||||||
|
jsr popax ; X1
|
||||||
|
sta tgi_clip_x1
|
||||||
|
stx tgi_clip_x1+1
|
||||||
|
jmp tgi_clippedline ; Call the line clipper
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|||||||
@@ -7,17 +7,18 @@
|
|||||||
.include "tgi-kernel.inc"
|
.include "tgi-kernel.inc"
|
||||||
|
|
||||||
.import popax
|
.import popax
|
||||||
.importzp ptr3, ptr4
|
|
||||||
|
|
||||||
.proc tgi_linepop
|
.proc tgi_linepop
|
||||||
|
|
||||||
sta ptr4 ; Y2
|
sta tgi_clip_y2 ; Y2
|
||||||
stx ptr4+1
|
stx tgi_clip_y2+1
|
||||||
sta _tgi_cury
|
sta _tgi_cury
|
||||||
stx _tgi_cury+1
|
stx _tgi_cury+1
|
||||||
|
|
||||||
jsr popax
|
jsr popax
|
||||||
sta ptr3 ; X2
|
|
||||||
stx ptr3+1
|
sta tgi_clip_x2 ; X2
|
||||||
|
stx tgi_clip_x2+1
|
||||||
sta _tgi_curx
|
sta _tgi_curx
|
||||||
stx _tgi_curx+1
|
stx _tgi_curx+1
|
||||||
rts
|
rts
|
||||||
|
|||||||
@@ -12,9 +12,15 @@
|
|||||||
|
|
||||||
.proc _tgi_lineto
|
.proc _tgi_lineto
|
||||||
|
|
||||||
jsr tgi_curtoxy ; Copy curx/cury into ptr1/ptr2
|
pha
|
||||||
jsr tgi_linepop ; Pop x2/y2 into ptr3/ptr4 and curx/cury
|
ldy #3 ; Copy curx/cury to tgi_clip_x1/tgi_clip_y1
|
||||||
jmp tgi_line ; Call the driver
|
@L1: lda _tgi_curx,y
|
||||||
|
sta tgi_clip_x1,y
|
||||||
|
dey
|
||||||
|
bpl @L1
|
||||||
|
pla
|
||||||
|
jsr tgi_linepop ; Pop x2/y2
|
||||||
|
jmp tgi_clippedline ; Call the line clipper
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user