]> git.sur5r.net Git - cc65/commitdiff
Added clipping for lines.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 6 Nov 2009 15:26:46 +0000 (15:26 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 6 Nov 2009 15:26:46 +0000 (15:26 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4452 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/tgi/Makefile
libsrc/tgi/tgi_clipline.s [deleted file]
libsrc/tgi/tgi_clippedline.s [new file with mode: 0644]
libsrc/tgi/tgi_line.s
libsrc/tgi/tgi_linepop.s
libsrc/tgi/tgi_lineto.s

index f0721b0ea57f0fc11ba7fb88bf79db0532905bd1..1e0dc2bf9d274f4962407a48093f7cd9adbcc132 100644 (file)
@@ -33,13 +33,13 @@ C_OBJS =        tgi_arc.o               \
                 tgi_load.o              \
                 tgi_load_driver.o       \
                 tgi_load_vectorfont.o   \
-                tgi_pieslice.o  
+                tgi_pieslice.o
 
 S_OBJS =               tgi-kernel.o            \
                 tgi_bar.o               \
                 tgi_circle.o            \
                 tgi_clear.o             \
-                tgi_clipline.o          \
+                tgi_clippedline.o       \
                 tgi_curtoxy.o           \
                 tgi_done.o              \
                 tgi_ellipse.o           \
diff --git a/libsrc/tgi/tgi_clipline.s b/libsrc/tgi/tgi_clipline.s
deleted file mode 100644 (file)
index 96ef5b8..0000000
+++ /dev/null
@@ -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
diff --git a/libsrc/tgi/tgi_clippedline.s b/libsrc/tgi/tgi_clippedline.s
new file mode 100644 (file)
index 0000000..c4085c0
--- /dev/null
@@ -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
+
+
+
+
index d895dc533bcac46e456663d456e2ed5fc6f12958..36f63c8ff08a08ae2d094c4457f0db4f870162a5 100644 (file)
 
 .proc   _tgi_line
 
-        jsr     tgi_linepop     ; Pop/store Y2/X2
-        jsr     popax
-        jsr     tgi_popxy       ; Pop/store X1/Y1 into ptr1/ptr2
-        jmp     tgi_line        ; Call the driver
+        jsr     tgi_linepop             ; Pop/store Y2/X2
+        jsr     popax                   ; Y1
+        sta     tgi_clip_y1
+        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
 
index 8cc3dff89ba42e92a72a8b49b447424fd6c6437c..bbd147c99afbe54ce68dfccec7b6b97d1e398f9b 100644 (file)
@@ -7,17 +7,18 @@
         .include        "tgi-kernel.inc"
 
         .import         popax
-        .importzp       ptr3, ptr4
 
 .proc   tgi_linepop
 
-        sta     ptr4            ; Y2
-        stx     ptr4+1
+        sta     tgi_clip_y2     ; Y2
+        stx     tgi_clip_y2+1
         sta     _tgi_cury
         stx     _tgi_cury+1
+
         jsr     popax
-        sta     ptr3            ; X2
-        stx     ptr3+1
+
+        sta     tgi_clip_x2     ; X2
+        stx     tgi_clip_x2+1
         sta     _tgi_curx
         stx     _tgi_curx+1
         rts
index 2cf4a9a1d9768397fd2d62208750d395d2afa591..868f4cf4222cd2ab05ad98bd78f52ee4302f940b 100644 (file)
 
 .proc   _tgi_lineto
 
-        jsr     tgi_curtoxy     ; Copy curx/cury into ptr1/ptr2
-        jsr     tgi_linepop     ; Pop x2/y2 into ptr3/ptr4 and curx/cury
-        jmp     tgi_line        ; Call the driver
+        pha
+        ldy     #3              ; Copy curx/cury to tgi_clip_x1/tgi_clip_y1
+@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