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 ; Line coordinates. Must be set before calling tgi_clippedline
37 ;----------------------------------------------------------------------------
48 ;----------------------------------------------------------------------------
49 ; Generate a Cohen Sutherland outcode
53 ; unsigned char o = 0;
56 ; } else if (Y >= yres) {
61 ; } else if (X >= xres) {
75 lda tgi_clip_y1+1,y ; High byte of Y1
76 bmi L2 ; Jump if bottom clip
78 ldx tgi_clip_y1,y ; Low byte of Y1
84 lda #CLIP_TOP ; Top clipping necessary
87 L3: sta tmp1 ; Save temp outcode
92 L4: lda tgi_clip_x1+1,y ; High byte of X1
93 bmi L7 ; Jump if left clip
95 ldx tgi_clip_x1,y ; Low byte of X1
102 ; No right or left clipping necessary
107 ; Need right clipping
122 ;----------------------------------------------------------------------------
123 ; Calculate outcodes for both ends of the line
139 ldy #(tgi_clip_y2 - tgi_clip_y1)
147 ;----------------------------------------------------------------------------
148 ; Negate tgi_clip_dxy
168 ;----------------------------------------------------------------------------
169 ; Calculate the absolute values of dx and dy and store the combined sign in
202 ldy #(tgi_clip_dy - tgi_clip_dx)
210 ;----------------------------------------------------------------------------
211 ; Helper routine. Generate the absolute value of y/a and calculate the sign
212 ; of the final result
218 tax ; Remember high byte
220 sta tmp1 ; Sign of result
232 ;----------------------------------------------------------------------------
233 ; Helper routine. Move the value in eax to ptr1:ptr2
237 .proc move_intermediate_result
250 ;----------------------------------------------------------------------------
251 ; Multiplicate value in y/a by dy, then divide by dx.
257 ; Generate the absolute value of y/a and calculate the sign of the final
262 ; All values are positive now (dx/dy have been made positive in calcdeltas)
263 ; and the sign of the final result is on tmp1, so we can use unsigned
264 ; operations and apply the final result later, after rounding.
267 ldx tgi_clip_dy+1 ; rhs
268 jsr umul16x16r32 ; Multiplicate
270 ; Move the result of the multiplication into ptr1:ptr2
272 jsr move_intermediate_result
274 ; Load divisor and divide
280 ; Check the sign of the final result and negate it if nessary
290 ;----------------------------------------------------------------------------
291 ; Multiplicate value in y/a by dx, then divide by dy.
297 ; Generate the absolute value of y/a and calculate the sign of the final
302 ; All values are positive now (dx/dy have been made positive in calcdeltas)
303 ; and the sign of the final result is on tmp1, so we can use unsigned
304 ; operations and apply the final result later, after rounding.
307 ldx tgi_clip_dx+1 ; rhs
308 jsr umul16x16r32 ; Multiplicate
310 ; Move the result of the multiplication into ptr1:ptr2
312 jsr move_intermediate_result
314 ; Load divisor and divide
320 ; Check the sign of the final result and negate it if nessary
322 jmp muldiv_dydx::done
328 ;----------------------------------------------------------------------------
329 ; Clip a line using Cohen Sutherland
333 .proc tgi_clippedline
335 ; Set a flag that we have no deltas calculated
345 ; if ((tgi_clip_o1 | tgi_clip_o2) == 0) {
346 ; tgi_line (x1, y1, x2, y2);
349 Loop: lda tgi_clip_o1
353 ; Copy the coordinates into ptr1-4 and draw the line
356 L0: lda tgi_clip_x1,x
362 ; if ((tgi_clip_o1 & tgi_clip_o2) != 0) reject;
367 rts ; Nothing to draw
369 ; We must clip. If we haven't already done so, calculate dx/dy.
371 L2: lda tgi_clip_d ; Deltas alreay calculated?
372 bne HaveDeltas ; Jump if yes
376 ; Check if X1/Y1 needs clipping
384 lsr a ; Check for CLIP_LEFT
387 ; tgi_clip_y1 += (0 - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
394 L3: lsr a ; Check for CLIP_RIGHT
397 ; tgi_clip_y1 += (tgi_xmax - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
398 ; tgi_clip_x1 = tgi_xmax;
426 L5: lsr a ; Check for CLIP_BOTTOM
429 ; tgi_clip_x1 = (0 - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
436 L6: lsr a ; Check for CLIP_TOP
439 ; tgi_clip_x1 += (tgi_ymax - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
440 ; tgi_clip_y1 = ymax;
463 ; We need to recalculate outcode1 in this case
467 ; Check if X2/Y2 needs clipping
474 lsr a ; Check for CLIP_LEFT
477 ; tgi_clip_y2 += (0 - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
484 L11: lsr a ; Check for CLIP_RIGHT
487 ; tgi_clip_y2 += (tgi_xmax - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
488 ; tgi_clip_x2 = tgi_xmax;
516 L13: lsr a ; Check for CLIP_BOTTOM
519 ; tgi_clip_x2 += (0 - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
526 L14: lsr a ; Check for CLIP_TOP
529 ; tgi_clip_x2 += (tgi_ymax - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
530 ; tgi_clip_y2 = tgi_ymax;
553 ; We need to recalculate outcode2 in this case