2 ; Ullrich von Bassewitz, 2009-10-25
4 ; Clips line coordinates to the screen coordinates and calls tgi_line
8 .import umul16x16r32, udiv32by16r16
11 .include "tgi-kernel.inc"
12 .include "zeropage.inc"
16 ;----------------------------------------------------------------------------
21 ; Outcodes for both ends
33 ;----------------------------------------------------------------------------
34 ; Calculate outcodes for both ends of the line
50 ldy #<(tgi_clip_y2 - tgi_clip_y1)
58 ;----------------------------------------------------------------------------
79 ;----------------------------------------------------------------------------
80 ; Calculate the absolute values of dx and dy and store the combined sign in
113 ldy #(tgi_clip_dy - tgi_clip_dx)
121 ;----------------------------------------------------------------------------
122 ; Helper routine. Generate the absolute value of y/a and calculate the sign
123 ; of the final result
129 tax ; Remember high byte
131 sta tmp1 ; Sign of result
143 ;----------------------------------------------------------------------------
144 ; Helper routine. Move the value in eax to ptr1:ptr2
148 .proc move_intermediate_result
161 ;----------------------------------------------------------------------------
162 ; Multiplicate value in y/a by dy, then divide by dx.
168 ; Generate the absolute value of y/a and calculate the sign of the final
173 ; All values are positive now (dx/dy have been made positive in calcdeltas)
174 ; and the sign of the final result is on tmp1, so we can use unsigned
175 ; operations and apply the final result later, after rounding.
178 ldx tgi_clip_dy+1 ; rhs
179 jsr umul16x16r32 ; Multiplicate
181 ; Move the result of the multiplication into ptr1:ptr2
183 jsr move_intermediate_result
185 ; Load divisor and divide
191 ; Check the sign of the final result and negate it if nessary
201 ;----------------------------------------------------------------------------
202 ; Multiplicate value in y/a by dx, then divide by dy.
208 ; Generate the absolute value of y/a and calculate the sign of the final
213 ; All values are positive now (dx/dy have been made positive in calcdeltas)
214 ; and the sign of the final result is on tmp1, so we can use unsigned
215 ; operations and apply the final result later, after rounding.
218 ldx tgi_clip_dx+1 ; rhs
219 jsr umul16x16r32 ; Multiplicate
221 ; Move the result of the multiplication into ptr1:ptr2
223 jsr move_intermediate_result
225 ; Load divisor and divide
231 ; Check the sign of the final result and negate it if nessary
233 jmp muldiv_dydx::done
239 ;----------------------------------------------------------------------------
240 ; Clip a line using Cohen Sutherland
244 .proc tgi_clippedline
246 ; Set a flag that we have no deltas calculated
256 ; if ((tgi_clip_o1 | tgi_clip_o2) == 0) {
257 ; tgi_line (x1, y1, x2, y2);
260 Loop: lda tgi_clip_o1
264 ; Copy the coordinates into ptr1-4 and draw the line
267 L0: lda tgi_clip_x1,x
273 ; if ((tgi_clip_o1 & tgi_clip_o2) != 0) reject;
278 rts ; Nothing to draw
280 ; We must clip. If we haven't already done so, calculate dx/dy.
282 L2: lda tgi_clip_d ; Deltas alreay calculated?
283 bne HaveDeltas ; Jump if yes
287 ; Check if X1/Y1 needs clipping
295 lsr a ; Check for TGI_CLIP_LEFT
298 ; tgi_clip_y1 += (0 - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
305 L3: lsr a ; Check for TGI_CLIP_RIGHT
308 ; tgi_clip_y1 += (tgi_xmax - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
309 ; tgi_clip_x1 = tgi_xmax;
337 L5: lsr a ; Check for TGI_CLIP_BOTTOM
340 ; tgi_clip_x1 = (0 - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
347 L6: lsr a ; Check for TGI_CLIP_TOP
350 ; tgi_clip_x1 += (tgi_ymax - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
351 ; tgi_clip_y1 = ymax;
374 ; We need to recalculate outcode1 in this case
378 ; Check if X2/Y2 needs clipping
385 lsr a ; Check for TGI_CLIP_LEFT
388 ; tgi_clip_y2 += (0 - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
395 L11: lsr a ; Check for TGI_CLIP_RIGHT
398 ; tgi_clip_y2 += (tgi_xmax - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
399 ; tgi_clip_x2 = tgi_xmax;
427 L13: lsr a ; Check for TGI_CLIP_BOTTOM
430 ; tgi_clip_x2 += (0 - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
437 L14: lsr a ; Check for TGI_CLIP_TOP
440 ; tgi_clip_x2 += (tgi_ymax - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
441 ; tgi_clip_y2 = tgi_ymax;
464 ; We need to recalculate outcode2 in this case