]> git.sur5r.net Git - cc65/blob - libsrc/tgi/tgi_clipline.s
96ef5b860ea0a9fa2e9d72d97040bb19de54690e
[cc65] / libsrc / tgi / tgi_clipline.s
1 ;
2 ; Ullrich von Bassewitz, 2009-10-25
3 ;
4 ; Clips the line in ptr1/ptr2/ptr3/ptr4 to the screen coordinates
5 ;
6
7
8         .export _tgi_clipline
9         .export _tgi_clip_x1, _tgi_clip_y1, _tgi_clip_x2, _tgi_clip_y2
10         .export _tgi_clip_o1, _tgi_clip_o2      ; Debugging!
11         .export _tgi_clip_dx, _tgi_clip_dy
12         .export _tgi_xmax, _tgi_ymax
13
14         .import negax, pushax
15         .import imul16x16r32, idiv32by16r16
16         .import return0, return1
17
18         .include "tgi-kernel.inc"
19         .include "zeropage.inc"
20
21         .macpack longbranch
22
23 .code
24
25 ;----------------------------------------------------------------------------
26 ; outcode constants. These aren't really used because most stuff is done by
27 ; shifting the values, but they're here for documentation.
28
29 CLIP_NONE       = $00
30 CLIP_LEFT       = $01
31 CLIP_RIGHT      = $02
32 CLIP_BOTTOM     = $04
33 CLIP_TOP        = $08
34
35
36
37 ;----------------------------------------------------------------------------
38 ; Generate a Cohen Sutherland outcode for tgi_clip_x1/tgi_clip_y1 in _tgi_clip_o1
39 ;
40 ; void outcode1 ()
41 ; {
42 ;     _tgi_clip_o1 = 0;
43 ;     if (Y1 < 0) {
44 ;         _tgi_clip_o1 = CLIP_BOTTOM;
45 ;     } else if (Y1 >= yres) {
46 ;         _tgi_clip_o1 = CLIP_TOP;
47 ;     }
48 ;     if (X1 < 0) {
49 ;         _tgi_clip_o1 |= CLIP_LEFT;
50 ;     } else if (X1 >= xres) {
51 ;         _tgi_clip_o1 |= CLIP_RIGHT;
52 ;     }
53 ; }
54
55 .proc   outcode1
56
57         ldy     #CLIP_BOTTOM            ; Assume line needs bottom clip
58
59 ; Check Y coordinate
60
61         lda     _tgi_clip_y1+1          ; High byte of Y1
62         bmi     L2                      ; Jump if bottom clip
63
64         ldy     #CLIP_TOP               ; Assume line needs top clip
65         ldx     _tgi_clip_y1            ; Low byte of Y1
66         cpx     _tgi_yres
67         sbc     _tgi_yres+1
68         bvs     L1
69         eor     #$80
70 L1:     bmi     L2             
71
72         ldy     #CLIP_NONE              ; No clipping actually
73
74 L2:     sty     _tgi_clip_o1
75
76
77 ; Check X coordinate
78
79         ldy     #CLIP_LEFT              ; Assume line needs left clip
80
81         lda     _tgi_clip_x1+1          ; High byte of X1
82         bmi     L4                      ; Jump if left clip
83
84         ldy     #CLIP_RIGHT             ; Assume line needs right clip
85
86         ldx     _tgi_clip_x1            ; Low byte of X1
87         cpx     _tgi_xres
88         sbc     _tgi_xres+1
89         bvs     L3
90         eor     #$80
91 L3:     bmi     L4
92
93         ldy     #CLIP_NONE              ; No clipping actually
94
95 L4:     tya
96         ora     _tgi_clip_o1
97         sta     _tgi_clip_o1
98
99         rts
100
101 .endproc
102
103
104 ;----------------------------------------------------------------------------
105 ; Generate a Cohen Sutherland outcode for tgi_clip_x2/tgi_clip_y2 in _tgi_clip_o2
106 ;
107 ; void outcode2 ()
108 ; {
109 ;     _tgi_clip_o2 = 0;
110 ;     if (Y2 < 0) {
111 ;         _tgi_clip_o2 = CLIP_BOTTOM;
112 ;     } else if (Y2 >= yres) {
113 ;         _tgi_clip_o2 = CLIP_TOP;
114 ;     }
115 ;     if (X2 < 0) {
116 ;         _tgi_clip_o2 |= CLIP_LEFT;
117 ;     } else if (X2 >= xres) {
118 ;         _tgi_clip_o2 |= CLIP_RIGHT;
119 ;     }
120 ; }
121
122 .proc   outcode2
123
124         ldy     #CLIP_BOTTOM            ; Assume line needs bottom clip
125
126 ; Check Y coordinate
127
128         lda     _tgi_clip_y2+1          ; High byte of Y2
129         bmi     L2                      ; Jump if bottom clip
130
131         ldy     #CLIP_TOP               ; Assume line needs top clip
132         ldx     _tgi_clip_y2            ; Low byte of Y4
133         cpx     _tgi_yres
134         sbc     _tgi_yres+1
135         bvs     L1
136         eor     #$80
137 L1:     bmi     L2
138
139         ldy     #CLIP_NONE              ; No clipping actually
140
141 L2:     sty     _tgi_clip_o2
142
143
144 ; Check X coordinate
145
146         ldy     #CLIP_LEFT              ; Assume line needs left clip
147
148         lda     _tgi_clip_x2+1          ; High byte of X2
149         bmi     L4                      ; Jump if left clip
150
151         ldy     #CLIP_RIGHT             ; Assume line needs right clip
152
153         ldx     _tgi_clip_x2            ; Low byte of X2
154         cpx     _tgi_xres
155         sbc     _tgi_xres+1
156         bvs     L3
157         eor     #$80
158 L3:     bmi     L4
159
160         ldy     #CLIP_NONE              ; No clipping actually
161
162 L4:     tya
163         ora     _tgi_clip_o2
164         sta     _tgi_clip_o2
165
166         rts
167
168 .endproc
169
170
171
172 ;----------------------------------------------------------------------------
173 ; Calculate dx and dy
174 ;
175
176 .proc   calcdeltas
177
178         lda     _tgi_clip_x2
179         sec
180         sbc     _tgi_clip_x1
181         sta     _tgi_clip_dx
182         lda     _tgi_clip_x2+1
183         sbc     _tgi_clip_x1+1
184         sta     _tgi_clip_dx+1
185
186         lda     _tgi_clip_y2
187         sec
188         sbc     _tgi_clip_y1
189         sta     _tgi_clip_dy
190         lda     _tgi_clip_y2+1
191         sbc     _tgi_clip_y1+1
192         sta     _tgi_clip_dy+1
193
194         rts
195
196 .endproc
197
198
199
200 ;----------------------------------------------------------------------------
201 ; Multiplicate value in y/a by dy, then divide by dx.
202 ;
203
204 .proc   muldiv_dydx
205
206         sty     ptr1                    ; lhs
207         sta     ptr1+1
208         lda     _tgi_clip_dy
209         ldx     _tgi_clip_dy+1          ; rhs
210         jsr     imul16x16r32            ; Multiplicate
211
212 ; Move the result of the multiplication into ptr1:ptr2
213
214         sta     ptr1
215         stx     ptr1+1
216         ldy     sreg
217         sty     ptr2
218         ldy     sreg+1
219         sty     ptr2+1
220
221 ; Load divisor and divide
222
223         lda     _tgi_clip_dx
224         ldx     _tgi_clip_dx+1
225         jmp     idiv32by16r16
226
227 .endproc
228
229
230
231 ;----------------------------------------------------------------------------
232 ; Multiplicate value in y/a by dx, then divide by dy.
233 ;
234
235 .proc   muldiv_dxdy
236
237         sty     ptr1                    ; lhs
238         sta     ptr1+1
239         lda     _tgi_clip_dx
240         ldx     _tgi_clip_dx+1          ; rhs
241         jsr     imul16x16r32            ; Multiplicate
242
243 ; Move the result of the multiplication into ptr1:ptr2
244
245         sta     ptr1
246         stx     ptr1+1
247         ldy     sreg
248         sty     ptr2
249         ldy     sreg+1
250         sty     ptr2+1
251
252 ; Load divisor and divide
253
254         lda     _tgi_clip_dy
255         ldx     _tgi_clip_dy+1
256         jmp     idiv32by16r16
257
258 .endproc
259
260
261
262 ;----------------------------------------------------------------------------
263 ; Clip a line using Cohen Sutherland
264 ;
265
266 .proc   _tgi_clipline
267
268 ; Generate outcodes
269
270         jsr     outcode1
271         jsr     outcode2
272         jsr     calcdeltas
273
274 ; if ((_tgi_clip_o1 | _tgi_clip_o2) == 0) accept;
275
276 Loop:   lda     _tgi_clip_o1
277         ora     _tgi_clip_o2
278         bne     L1
279         jmp     return0
280
281 ; if ((_tgi_clip_o1 & _tgi_clip_o2) != 0) reject;
282
283 L1:     lda     _tgi_clip_o1
284         and     _tgi_clip_o2
285         beq     L2
286         jmp     return1
287
288 ; Check if X1/Y1 needs clipping
289
290 L2:     lda     _tgi_clip_o1
291         jeq     L10
292
293 ; Need to clip X1/Y1
294
295         lsr     a                       ; Check for CLIP_LEFT
296         bcc     L3
297
298 ; tgi_clip_y1 += (0 - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
299 ; tgi_clip_x1 = 0;
300
301         lda     #$00
302         tax
303         beq     L4
304
305 L3:     lsr     a                       ; Check for CLIP_RIGHT
306         bcc     L5
307
308 ; tgi_clip_y1 += (tgi_xmax - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx;
309 ; tgi_clip_x1 = tgi_xmax;
310
311         lda     _tgi_xmax
312         ldx     _tgi_xmax+1
313
314 L4:     tay
315         sec
316         sbc     _tgi_clip_x1
317         sty     _tgi_clip_x1
318         tay
319         txa
320         sbc     _tgi_clip_x1+1
321         stx     _tgi_clip_x1+1
322
323         jsr     muldiv_dydx
324
325         clc
326         adc     _tgi_clip_y1
327         sta     _tgi_clip_y1
328         txa
329         adc     _tgi_clip_y1+1
330         sta     _tgi_clip_y1+1
331
332 ;
333
334         lda     _tgi_clip_o1
335         lsr     a
336         lsr     a
337 L5:     lsr     a                               ; Check for CLIP_BOTTOM
338         bcc     L6
339
340 ; tgi_clip_x1 = (0 - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
341 ; tgi_clip_y1 = 0;
342
343         lda     #$00
344         tax
345         beq     L7
346
347 L6:     lsr     a                               ; Check for CLIP_TOP
348         bcc     L8
349
350 ; tgi_clip_x1 += (tgi_ymax - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy;
351 ; tgi_clip_y1 = ymax;
352
353         lda     _tgi_ymax
354         ldx     _tgi_ymax+1
355
356 L7:     tay
357         sec
358         sbc     _tgi_clip_y1
359         sty     _tgi_clip_y1
360         tay
361         txa
362         sbc     _tgi_clip_y1+1
363         stx     _tgi_clip_y1+1
364
365         jsr     muldiv_dxdy
366
367         clc
368         adc     _tgi_clip_x1
369         sta     _tgi_clip_x1
370         txa
371         adc     _tgi_clip_x1+1
372         sta     _tgi_clip_x1+1
373
374 ; We need to recalculate outcode1 in this case
375
376 L8:     jsr     outcode1
377
378 ; Check if X2/Y2 needs clipping
379
380 L10:    lda     _tgi_clip_o2
381         jeq     Loop
382
383 ; Need to clip X2/Y2
384
385         lsr     a                       ; Check for CLIP_LEFT
386         bcc     L11
387
388 ; tgi_clip_y2 += (0 - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
389 ; tgi_clip_x2 = 0;
390
391         lda     #$00
392         tax
393         beq     L12
394
395 L11:    lsr     a                       ; Check for CLIP_RIGHT
396         bcc     L13
397
398 ; tgi_clip_y2 += (tgi_xmax - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx;
399 ; tgi_clip_x2 = tgi_xmax;
400
401         lda     _tgi_xmax
402         ldx     _tgi_xmax+1
403
404 L12:    tay
405         sec
406         sbc     _tgi_clip_x2
407         sty     _tgi_clip_x2
408         tay
409         txa
410         sbc     _tgi_clip_x2+1
411         stx     _tgi_clip_x2+1
412
413         jsr     muldiv_dydx
414
415         clc
416         adc     _tgi_clip_y2
417         sta     _tgi_clip_y2
418         txa
419         adc     _tgi_clip_y2+1
420         sta     _tgi_clip_y2+1
421
422 ;
423
424         lda     _tgi_clip_o2
425         lsr     a
426         lsr     a
427 L13:    lsr     a                       ; Check for CLIP_BOTTOM
428         bcc     L14
429
430 ; tgi_clip_x2 += (0 - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
431 ; tgi_clip_y2 = 0;
432
433         lda     #$00
434         tax
435         beq     L15
436
437 L14:    lsr     a                               ; Check for CLIP_TOP
438         bcc     L16
439
440 ; tgi_clip_x2 += (tgi_ymax - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy;
441 ; tgi_clip_y2 = tgi_ymax;
442
443         lda     _tgi_ymax
444         ldx     _tgi_ymax+1
445
446 L15:    tay
447         sec
448         sbc     _tgi_clip_y2
449         sty     _tgi_clip_y2
450         tay
451         txa
452         sbc     _tgi_clip_y2+1
453         stx     _tgi_clip_y2+1
454
455         jsr     muldiv_dxdy
456
457         clc
458         adc     _tgi_clip_x2
459         sta     _tgi_clip_x2
460         txa
461         adc     _tgi_clip_x2+1
462         sta     _tgi_clip_x2+1
463
464 ; We need to recalculate outcode2 in this case
465
466 L16:    jsr     outcode2
467
468 ; Try again
469
470         jmp     Loop
471
472 .endproc
473
474
475
476
477 ;----------------------------------------------------------------------------
478 ; Data
479
480 .bss
481
482 _tgi_clip_x1:   .res    2
483 _tgi_clip_y1:   .res    2
484 _tgi_clip_x2:   .res    2
485 _tgi_clip_y2:   .res    2
486
487 _tgi_clip_o1:   .res    1
488 _tgi_clip_o2:   .res    1
489
490 _tgi_clip_dx:   .res    2
491 _tgi_clip_dy:   .res    2
492
493 _tgi_xmax:      .res    2
494 _tgi_ymax:      .res    2