/[projet1]/users/chema/TINE/oobj3d/LineDraw.s
Defence Force logotype

Contents of /users/chema/TINE/oobj3d/LineDraw.s

Parent Directory Parent Directory | Revision Log Revision Log


Revision 266 - (show annotations)
Mon Feb 8 22:12:53 2010 UTC (9 years, 8 months ago) by Chema
File size: 30884 byte(s)
many small changes and bug huntings. Newest line routine, removed clearing the laser vertices from the main loop...
1 #include "params.h"
2
3 #ifndef FILLEDPOLYS
4
5
6 .zero
7
8 i .dsb 1 ; Number of pixels to draw (iteration counter) 1 byte in zp
9 dx .dsb 1 ; Width
10 dy .dsb 1 ; Height
11 _CurrentPixelX .dsb 1
12 _CurrentPixelY .dsb 1
13 _OtherPixelX .dsb 1
14 _OtherPixelY .dsb 1
15
16
17 #define _LargeX0 X1
18 #define _LargeY0 Y1
19 #define _LargeX1 X2
20 #define _LargeY1 Y2
21
22 _LargeX .dsb 2
23 _LargeY .dsb 2
24 _ClipCode .dsb 1
25 _ClipCode0 .dsb 1
26 _ClipCode1 .dsb 1
27
28 #ifdef USE_ACCURATE_CLIPPING
29 .dsb 1
30 #endif
31 _ClipX0 .dsb 2
32 #ifdef USE_ACCURATE_CLIPPING
33 .dsb 1
34 #endif
35 _ClipY0 .dsb 2
36 #ifdef USE_ACCURATE_CLIPPING
37 .dsb 1
38 #endif
39 _ClipX1 .dsb 2
40 #ifdef USE_ACCURATE_CLIPPING
41 .dsb 1
42 #endif
43 _ClipY1 .dsb 2
44 #ifdef USE_ACCURATE_CLIPPING
45 .dsb 1
46 #endif
47 _ClipXc .dsb 2
48 #ifdef USE_ACCURATE_CLIPPING
49 .dsb 1
50 #endif
51 _ClipYc .dsb 2
52
53
54 l8save_a .dsb 1
55 curBit .dsb 1
56 chunk .dsb 1
57 lastSum .dsb 1
58
59
60 #define BYTE_PIXEL 6
61 #define X_SIZE 240
62 #define ROW_SIZE X_SIZE/BYTE_PIXEL
63
64 #define _NOP $ea
65 #define _INX $e8
66 #define _DEX $ca
67 #define _INY $c8
68 #define _DEY $88
69 #define _ASL $0a
70 #define _LSR $4a
71 #define _INC_ZP $e6
72 #define _DEC_ZP $c6
73
74
75
76 .text
77
78 ;; To include double-buffer (on and off)
79 double_buff .byt $ff
80
81
82 #define X_SIZE 240
83 #define Y_SIZE 200
84 #define ROW_SIZE X_SIZE/6
85
86 .dsb 256-(*&255)
87
88 _HiresAddrLow .dsb Y_SIZE
89
90 .dsb 256-(*&255)
91
92 _HiresAddrHigh .dsb Y_SIZE
93
94 .dsb 256-(*&255)
95
96 .byt 0
97 _TableDiv6 .dsb X_SIZE
98
99 .dsb 256-(*&255)
100
101 .byt 0
102 _TableMod6 .dsb X_SIZE
103
104 .dsb 256-(*&255)
105
106 .byt 0
107 _TableDiv6Rev .dsb X_SIZE
108
109 .dsb 256-(*&255)
110
111 .byt 0
112 _TableBit6Reverse
113 .byt 32,16,8,4,2,1
114 .byt 32,16,8,4,2,1
115 .byt 32,16,8,4,2,1
116 .byt 32,16,8,4,2,1
117 .byt 32,16,8,4,2,1
118 .byt 32,16,8,4,2,1
119 .byt 32,16,8,4,2,1
120 .byt 32,16,8,4,2,1
121 .byt 32,16,8,4,2,1
122 .byt 32,16,8,4,2,1
123
124 .byt 32,16,8,4,2,1
125 .byt 32,16,8,4,2,1
126 .byt 32,16,8,4,2,1
127 .byt 32,16,8,4,2,1
128 .byt 32,16,8,4,2,1
129 .byt 32,16,8,4,2,1
130 .byt 32,16,8,4,2,1
131 .byt 32,16,8,4,2,1
132 .byt 32,16,8,4,2,1
133 .byt 32,16,8,4,2,1
134
135 .byt 32,16,8,4,2,1
136 .byt 32,16,8,4,2,1
137 .byt 32,16,8,4,2,1
138 .byt 32,16,8,4,2,1
139 .byt 32,16,8,4,2,1
140 .byt 32,16,8,4,2,1
141 .byt 32,16,8,4,2,1
142 .byt 32,16,8,4,2,1
143 .byt 32,16,8,4,2,1
144 .byt 32,16,8,4,2,1
145
146 .byt 32,16,8,4,2,1
147 .byt 32,16,8,4,2,1
148 .byt 32,16,8,4,2,1
149 .byt 32,16,8,4,2,1
150 .byt 32,16,8,4,2,1
151 .byt 32,16,8,4,2,1
152 .byt 32,16,8,4,2,1
153 .byt 32,16,8,4,2,1
154 .byt 32,16,8,4,2,1
155 .byt 32,16,8,4,2,1
156
157 .dsb 256-(*&255)
158
159 .byt 0
160 _TableBit6
161 .byt 1,2,4,8,16,32
162 .byt 1,2,4,8,16,32
163 .byt 1,2,4,8,16,32
164 .byt 1,2,4,8,16,32
165 .byt 1,2,4,8,16,32
166 .byt 1,2,4,8,16,32
167 .byt 1,2,4,8,16,32
168 .byt 1,2,4,8,16,32
169 .byt 1,2,4,8,16,32
170 .byt 1,2,4,8,16,32
171
172 .byt 1,2,4,8,16,32
173 .byt 1,2,4,8,16,32
174 .byt 1,2,4,8,16,32
175 .byt 1,2,4,8,16,32
176 .byt 1,2,4,8,16,32
177 .byt 1,2,4,8,16,32
178 .byt 1,2,4,8,16,32
179 .byt 1,2,4,8,16,32
180 .byt 1,2,4,8,16,32
181 .byt 1,2,4,8,16,32
182
183 .byt 1,2,4,8,16,32
184 .byt 1,2,4,8,16,32
185 .byt 1,2,4,8,16,32
186 .byt 1,2,4,8,16,32
187 .byt 1,2,4,8,16,32
188 .byt 1,2,4,8,16,32
189 .byt 1,2,4,8,16,32
190 .byt 1,2,4,8,16,32
191 .byt 1,2,4,8,16,32
192 .byt 1,2,4,8,16,32
193
194 .byt 1,2,4,8,16,32
195 .byt 1,2,4,8,16,32
196 .byt 1,2,4,8,16,32
197 .byt 1,2,4,8,16,32
198 .byt 1,2,4,8,16,32
199 .byt 1,2,4,8,16,32
200 .byt 1,2,4,8,16,32
201 .byt 1,2,4,8,16,32
202 .byt 1,2,4,8,16,32
203 .byt 1,2,4,8,16,32
204
205
206 /////////////////////////////////////
207
208
209
210
211 ; History of linebench timings...
212 ;649
213 ;614 (replacing the update of tmp0)
214 ;607
215 ;588
216 ;583 after alignment
217 ;579
218 ;534 redid mainly_vertical
219 ;529 removed page penalty
220 ;517 final optimization at mainly_horizontal
221 ;501 chunking, initial version
222 ;482 optimized chunking (avg: 38.91 cylces)
223 ;473 final optimization for mainly_vertical (37.89 -> 38.34 corrected)
224
225 ; TODOs:
226 ; + chunking (-35)
227 ; - two separate branches instead of patching?
228 ; + countdown minor
229 ; x mainly_horizontal (won't work)
230 ; + mainly_vertical (-9)
231
232 .zero
233
234 ; *= tmp1
235
236
237
238 #define BYTE_PIXEL 6
239 #define X_SIZE 240
240 #define ROW_SIZE X_SIZE/BYTE_PIXEL
241
242 #define _NOP $ea
243 #define _INX $e8
244 #define _DEX $ca
245 #define _INY $c8
246 #define _DEY $88
247 #define _ASL $0a
248 #define _LSR $4a
249 #define _INC_ZP $e6
250 #define _DEC_ZP $c6
251
252
253 .text
254
255 .dsb 256-(*&255)
256
257 ;**********************************************************
258 draw_totaly_vertical_8
259 .(
260 ldx _CurrentPixelX
261 ldy _TableDiv6,x
262 lda _TableBit6Reverse,x ; 4
263 sta _mask_patch+1
264 ldx dy
265 inx
266 clc ; 2
267 loop
268 _mask_patch
269 lda #0 ; 2
270 ora (tmp0),y ; 5*
271 sta (tmp0),y ; 6*= 13**
272
273 ; update the screen address:
274 .(
275 tya ; 2
276 adc #ROW_SIZE ; 2
277 tay ; 2
278 bcc skip ; 2/3= 8/9
279 inc tmp0+1 ; 5
280 clc ; 2 = 7
281 skip ;
282 .)
283 dex ; 2
284 bne loop ; 2/3=4/5
285 rts
286 .)
287
288
289 ;**********************************************************
290 ;
291 ; Expects the following variables to be set when called:
292 ; _CurrentPixelX
293 ; _CurrentPixelY
294 ; _OtherPixelX
295 ; _OtherPixelY
296 ;
297 _DrawLine
298 ;
299 ; Compute deltas and signs
300 ;
301
302 ; Test Y value
303 .(
304 sec
305 lda _CurrentPixelY
306 sbc _OtherPixelY
307 beq end
308 bcc cur_smaller
309
310 cur_bigger ; y1>y2
311 ; Swap X and Y
312 ; So we always draw from top to bottom
313 ldy _CurrentPixelY
314 ldx _OtherPixelY
315 sty _OtherPixelY
316 stx _CurrentPixelY
317
318 ldy _CurrentPixelX
319 ldx _OtherPixelX
320 sty _OtherPixelX
321 stx _CurrentPixelX
322
323 jmp end
324
325 cur_smaller ; y1<y2
326 ; Absolute value
327 eor #$ff
328 adc #1
329 end
330 sta dy
331 .)
332
333 ;
334 ; Initialise screen pointer
335 ;
336 ldy _CurrentPixelY
337 lda _HiresAddrLow,y ; 4
338 sta tmp0+0 ; 3
339 lda _HiresAddrHigh,y ; 4
340 sta tmp0+1 ; 3 => Total 14 cycles
341
342 ; Test X value
343 .(
344 sec
345 lda _CurrentPixelX
346 sbc _OtherPixelX
347 sta dx
348 beq draw_totaly_vertical_8
349 bcc cur_smaller
350
351 cur_bigger ; x1>x2
352 lda #_DEX
353 bne end
354
355 cur_smaller ; x1<x2
356 ; Absolute value
357 eor #$ff
358 adc #1
359 sta dx
360
361 lda #_INX
362 end
363 .)
364
365 ; jmp alignIt
366 ;
367 ; .dsb 256-(*&255)
368 ;
369 ;alignIt
370 ; Compute slope and call the specialized code for mostly horizontal or vertical lines
371 ldy dy
372 beq draw_totaly_horizontal_8
373 cpy dx
374 bcc draw_mainly_horizontal_8
375 jmp draw_mainly_vertical_8
376
377 ;**********************************************************
378 draw_totaly_horizontal_8
379 .(
380 ; here we have DY in Y, and the OPCODE in A
381 sta _outer_patch ; Write a (dex / nop / inx) instruction
382
383 ldx _OtherPixelX
384 stx __auto_cpx+1
385
386 ldx _CurrentPixelX
387
388 ;
389 ; Draw loop
390 ;
391 outer_loop
392 ldy _TableDiv6,x
393 lda _TableBit6Reverse,x ; 4
394 ora (tmp0),y ; 5
395 sta (tmp0),y ; 6
396
397 _outer_patch
398 inx
399
400 __auto_cpx
401 cpx #00 ; At the endpoint yet?
402 bne outer_loop
403 rts
404 .)
405
406 ;**********************************************************
407 draw_mainly_horizontal_8
408 .(
409 tax
410 lda dx
411 lsr
412 cmp dy
413 bcs draw_very_horizontal_8
414
415 ; here we have DY in Y, and the OPCODE (inx, dex) in A
416 sty __auto_dy+1
417
418 ; all this stress to be able to use dex, beq :)
419 cpx #_INX
420 beq doInx
421
422 lda #<_TableDiv6-1 ; == 0
423 ; clc ; _DEX < _INX
424 adc _OtherPixelX
425 sta __auto_div6+1
426 lda #<_TableBit6Reverse-1 ; == 0
427 ; clc
428 adc _OtherPixelX
429
430 ldx #>_TableDiv6
431 ldy #>_TableBit6Reverse ;
432 bne endPatch
433
434 doInx
435 lda #X_SIZE-1
436 ; sec
437 sbc _OtherPixelX
438 sta __auto_div6+1
439 lda #X_SIZE-1
440 ; sec
441 sbc _OtherPixelX
442
443 ldx #>_TableDiv6Rev
444 ldy #>_TableBit6 ;
445 endPatch
446 sta __auto_bit6+1
447 stx __auto_div6+2
448 sty __auto_bit6+2
449
450 lda dx
451 tax
452 inx ; 2 +1 since we count to 0
453 sta __auto_dx+1
454 lsr
455 eor #$ff
456 clc
457 ; a = sum, x = dX+1
458 ;----------------------------------------------------------
459 loopX
460 sta l8save_a ; 3 = 3
461 loopY
462 ; Draw the pixel
463 __auto_div6
464 ldy _TableDiv6-1,x ; 4
465 __auto_bit6
466 lda _TableBit6Reverse-1,x;4
467 ora (tmp0),y ; 5*
468 sta (tmp0),y ; 6*= 19
469
470 dex ; 2 Step in x
471 beq exitLoop ; 2/3 At the endpoint yet?
472 lda l8save_a ; 3
473 __auto_dy
474 adc #00 ; 2 +DY
475 bcc loopX ; 2/3=11/12 ~33.3% taken (not 50% due do to special code for very horizontal lines)
476 ; Time to step in y
477 __auto_dx
478 sbc #00 ; 2 -DX
479 sta l8save_a ; 3 = 5
480
481 ; update the screen address:
482 lda tmp0+0 ; 3
483 adc #ROW_SIZE ; 2
484 sta tmp0+0 ; 3
485 bcc loopY ; 2/3=10/11 ~84.4% taken
486 inc tmp0+1 ; 5
487 clc ; 2
488 bcc loopY ; 3 = 10
489 ; average: 12.40
490
491 exitLoop
492 rts
493 ; Timings:
494 ; x++/y : 34 (33.3%)
495 ; x++/y++: 47.40 (66.7%)
496 ; average: 42.94
497 .)
498
499 .dsb 256-(*&255)
500 ;**********************************************************
501 draw_very_horizontal_8
502 .(
503 ; dX > 2*dY, here we use "chunking"
504 ; here we have DY in Y, and the OPCODE (inx, dex) in A
505 sty __auto_dy+1
506 sty __auto_dy2+1
507 cpx #_INX
508 php
509 ; setup pointer and Y:
510 ldx _CurrentPixelX
511 lda _TableDiv6,x
512 clc
513 adc tmp0
514 tay
515 bcc skipHi
516 inc tmp0+1
517 skipHi
518 lda #0
519 sta tmp0
520 ; patch the code:
521 plp
522 beq doInx
523 ; negative x-direction
524 lda _TableMod6,x
525 tax
526
527 lda #_DEY
528 sta __auto_stepx
529 sta __auto_stepx2
530 lda #$ff
531 sta __auto_cpy+1
532 sta __auto_cpy2+1
533 lda #_DEC_ZP
534 sta __auto_yHi
535 sta __auto_yHi2
536 lda Pot2NTbl,x
537 sta chunk
538 lda #<Pot2NTbl
539 bne endPatch
540
541 doInx
542 ; positive x-direction
543 lda #BYTE_PIXEL-1
544 ; sec
545 sbc _TableMod6,x
546 tax
547
548 lda #_INY
549 sta __auto_stepx
550 sta __auto_stepx2
551 lda #$00
552 sta __auto_cpy+1
553 sta __auto_cpy2+1
554 lda #_INC_ZP
555 sta __auto_yHi
556 sta __auto_yHi2
557 lda Pot2PTbl,x
558 sta chunk
559 lda #<Pot2PTbl
560 endPatch
561 sta __auto_pot1+1
562 sta __auto_pot2+1
563 sta __auto_pot3+1
564 lda dx
565 sta __auto_dx+1
566 ; calculate initial bresenham sum
567 lsr
568 sta lastSum ; 3 this is used for the last line segment
569 eor #$ff ; = -dx/2
570 clc
571 jmp loopX
572 ; a = sum, x = dX+1, y = ptr-offset
573
574 ;----------------------------------------------------------
575 nextColumn ;
576 tax ; 2
577 lda chunk ; 3
578 ora (tmp0),y ; 5
579 sta (tmp0),y ; 6
580 lda #%00111111 ; 2
581 sta chunk ; 3
582 txa ; 2
583 ldx #BYTE_PIXEL-1 ; 2
584 __auto_stepx
585 iny ; 2 next column
586 __auto_cpy
587 cpy #00 ; 2
588 clc ; 2
589 bne contColumn ; 2/3=33/34 99% taken
590 __auto_yHi
591 inc tmp0+1 ; 5 dec/inc
592 bcc contColumn ; 3 = 8
593 ;----------------------------------------------------------
594 loopY
595 dec dy ; 5 all but one vertical segments drawn?
596 beq exitLoop ; 2/3= 7/8 yes, exit loop
597 loopX
598 dex ; 2
599 bmi nextColumn ; 2/37.03 ~16.7% taken
600 contColumn ; = 9.85
601 __auto_dy
602 adc #00 ; 2 +DY
603 bcc loopX ; 2/3= 4/5 ~75% taken
604 ; Time to step in y
605 __auto_dx
606 sbc #00 ; 2 -DX
607 sta l8save_a ; 3 = 5
608
609 ; plot the last bits of current row:
610 __auto_pot1
611 lda Pot2PTbl,x ; 4
612 eor chunk ; 3
613 ora (tmp0),y ; 5
614 sta (tmp0),y ; 6
615 __auto_pot2
616 lda Pot2PTbl,x ; 4
617 sta chunk ; 3 = 25
618
619 ; update the screen address:
620 tya ; 2
621 adc #ROW_SIZE ; 2
622 tay ; 2
623 lda l8save_a ; 3
624 bcc loopY ; 2/3=11/12 ~84.4% taken
625 inc tmp0+1 ; 5
626 clc ; 2
627 bcc loopY ; 3 = 10
628 ; average: 13.40
629
630 ; Timings:
631 ; x++/y : 14.85 (75%)
632 ; x++/y++: 64.25 (25%)
633 ; average: 27.20
634 ;----------------------------------------------------------
635 exitLoop
636 ; draw the last horizontal line segment:
637 adc lastSum ; 3
638 loopXEnd
639 dex ; 2
640 bmi nextColumnEnd ; 2/37.03 ~16.7% taken
641 contColumnEnd ; = 9.85
642 __auto_dy2
643 adc #00 ; 2 +DY
644 bcc loopXEnd ; 2/3= 4/5 ~50% taken
645
646 ; plot last chunk:
647 __auto_pot3
648 lda Pot2PTbl,x ; 4
649 eor chunk ; 3
650 ora (tmp0),y ; 5
651 sta (tmp0),y ; 6 = 18
652 rts
653 ;----------------------------------------------------------
654 nextColumnEnd ;
655 tax ; 2
656 lda chunk ; 3
657 ora (tmp0),y ; 5
658 sta (tmp0),y ; 6
659 lda #%00111111 ; 2
660 sta chunk ; 3
661 txa ; 2
662 ldx #BYTE_PIXEL-1 ; 2
663 __auto_stepx2
664 iny ; 2 next column
665 __auto_cpy2
666 cpy #00 ; 2
667 clc ; 2
668 bne contColumnEnd ; 2/3=33/34 99% taken
669 __auto_yHi2
670 inc tmp0+1 ; 5 dec/inc
671 bcc contColumnEnd ; 3 = 8
672
673 Pot2PTbl
674 .byte %00000001, %00000011, %00000111, %00001111
675 .byte %00011111, %00111111
676 Pot2NTbl
677 .byte %00100000, %00110000
678 .byte %00111000, %00111100, %00111110, %00111111
679 .)
680
681 .dsb 256-(*&255)
682 ;**********************************************************
683 ;
684 ; This code is used when the things are moving faster
685 ; vertically than horizontally
686 ;
687 ; dy>dx
688 ;
689 draw_mainly_vertical_8
690 ; here we have DY in Y, and the OPCODE in A
691 .(
692 ; setup bresenham values:
693 sty __auto_dy+1
694
695 ; setup direction:
696 cmp #_DEX ; which direction?
697 bne doInx
698 ; dex -> moving left:
699 lda #%00100000
700 sta __auto_cpBit+1
701 lda #_ASL ;
702 sta __auto_shBit
703 lda #%00000001
704 sta __auto_ldBit+1
705 lda #_DEY
706 sta __auto_yLo
707 ldx #$ff
708 lda #_DEC_ZP
709 bne endPatch
710
711 doInx
712 ; inx -> moving right:
713 lda #%00000001
714 sta __auto_cpBit+1
715 lda #_LSR
716 sta __auto_shBit
717 lda #%00100000
718 sta __auto_ldBit+1
719 lda #_INY
720 sta __auto_yLo
721 ldx #$00
722 lda #_INC_ZP
723 endPatch
724 stx __auto_cpY+1
725 sta __auto_yHi
726 ; setup X
727 ldx dx ; X = dx
728 stx __auto_dx1+1
729 stx __auto_dx2+1
730 ; setup current bit:
731 ldy _CurrentPixelX
732 lda _TableBit6Reverse,y ; 4
733 sta curBit
734 ; setup pointer and Y:
735 ; TODO: self-modyfing code for the ptrs?
736 lda _TableDiv6,y
737 clc
738 adc tmp0
739 tay
740 lda #0
741 sta tmp0
742 bcc skipTmp0
743 inc tmp0+1
744 skipTmp0
745 ; calculate initial bresenham sum:
746 lda dy
747 lsr
748 sta lastSum
749 eor #$ff ; -DY/2
750 clc ; 2
751 bcc loopY ; 3
752 ; a = sum, y = tmp0, x = dX, tmp0 = 0
753 ;----------------------------------------------------------
754 incHiPtr ;
755 inc tmp0+1 ; 5
756 clc ; 2
757 bcc contHiPtr ; 3
758 ;----------------------------------------------------------
759 loopY
760 sta l8save_a ; 3
761 lda curBit ; 3 = 6
762 loopX
763 ; Draw the pixel
764 ora (tmp0),y ; 5
765 sta (tmp0),y ; 6 = 11
766 ; update the screen address:
767 tya ; 2
768 adc #ROW_SIZE ; 2
769 tay ; 2
770 bcs incHiPtr ; 2/13 ~15.6% taken
771 contHiPtr ; = 9.72 average
772 lda l8save_a ; 3
773 __auto_dx1
774 adc #00 ; 2 +DX
775 bcc loopY ; 2/3= 7/8 ~50% taken
776 ; Time to step in x
777 __auto_dy
778 sbc #00 ; 2 -DY
779 sta l8save_a ; 3 = 5
780
781 lda curBit ; 3
782 __auto_cpBit ; TODO: optimize
783 cmp #%00100000 ; 2 %00100000/%00000001
784 beq nextColumn ; 2/14.07 ~16.7% taken
785 __auto_shBit
786 asl ; 2 asl/lsr, clears carry
787 contNextColumn
788 sta curBit ; 3 =~13.68
789 ; step in x:
790 dex ; 2 At the endpoint yet?
791 bne loopX ; 2/3= 4/5
792
793 ; x ,y++: 34.72 (50%)
794 ; x++,y++: 51.40 (50%)
795 ; average: 43.06
796
797 ; draw the last vertical line segment:
798 lda l8save_a ; 3
799 adc lastSum ; 3
800 loopYEnd
801 tax ; 2 = 2
802 ; Draw the pixel
803 lda curBit ; 3
804 ora (tmp0),y ; 5
805 sta (tmp0),y ; 6 = 14
806 ; update the screen address:
807 tya ; 2
808 adc #ROW_SIZE ; 2
809 tay ; 2
810 bcs incHiPtrEnd ; 2/13 ~15.6% taken
811 contHiPtrEnd ; = 9.72 average
812 txa ; 2
813 __auto_dx2
814 adc #00 ; 2 +DX
815 bcc loopYEnd ; 2/3= 6/7 ~25% taken
816 rts
817 ;----------------------------------------------------------
818 nextColumn
819 __auto_ldBit
820 lda #%00000001 ; 2 %00000001/%00100000
821 __auto_yLo
822 dey ; 2 dey/iny
823 __auto_cpY
824 cpy #$ff ; 2 $ff/$00
825 clc ; 2 TODO: optimize
826 bne contNextColumn ; 2/3 ~99% taken
827 __auto_yHi
828 dec tmp0+1 ; 5 dec/inc
829 bcc contNextColumn ; 3
830
831 incHiPtrEnd ; 9
832 inc tmp0+1 ; 5
833 clc ; 2
834 bcc contHiPtrEnd ; 3
835 ;----------------------------------------------------------
836 .)
837
838 ; *** total timings: ***
839 ; draw_very_horizontal_8 (29.6%): 27.20
840 ; draw_mainly_horizontal_8 (20.4%): 42.94 <- corrected!
841 ; draw_mainly_vertical_8 (50.0%): 43.06
842 ;----------------------------------------
843 ; total average (100.0%): 38.34
844
845
846
847
848 ////////////////////////////////////////
849
850
851 _GenerateTables
852 .(
853
854 ; Generate screen offset data
855 .(
856 lda double_buff
857 beq toscreen
858
859 lda #<buffer
860 sta tmp0+0
861 lda #>buffer
862 sta tmp0+1
863 jmp nextstep
864 toscreen
865 lda #<$a000
866 sta tmp0+0
867 lda #>$a000
868 sta tmp0+1
869 nextstep
870
871 ldx #0
872 loop
873 ; generate two bytes screen adress
874 clc
875 lda tmp0+0
876 sta _HiresAddrLow,x
877 adc #ROW_SIZE
878 sta tmp0+0
879 lda tmp0+1
880 sta _HiresAddrHigh,x
881 adc #0
882 sta tmp0+1
883
884 inx
885 cpx #Y_SIZE
886 bne loop
887 .)
888
889
890 ; Generate multiple of 6 data table
891 .(
892 lda #0 ; cur div
893 tay ; cur mod
894 tax
895 loop
896 sta _TableDiv6,x
897 pha
898 tya
899 sta _TableMod6,x
900 pla
901
902 iny
903 cpy #6
904 bne skip_mod
905 ldy #0
906 adc #0 ; carry = 1!
907 skip_mod
908
909 inx
910 cpx #X_SIZE
911 bne loop
912 .)
913 .(
914 lda #0 ; cur div
915 tay ; cur mod
916 ldx #X_SIZE
917 loop
918 dex
919 sta _TableDiv6Rev,x
920
921 iny
922 cpy #6
923 bne skip_mod
924 ldy #0
925 adc #0 ; carry = 1!
926 skip_mod
927
928 cpx #0
929 bne loop
930 .)
931 .)
932 rts
933
934
935
936
937
938 _ClipComputeMidPoint
939 .(
940 ; xc=(x0+x1)>>1;
941 clc
942 #ifdef USE_ACCURATE_CLIPPING
943 lda _ClipX0-1
944 adc _ClipX1-1
945 sta _ClipXc-1
946 #endif
947 lda _ClipX0+0
948 adc _ClipX1+0
949 sta _ClipXc+0
950
951 lda _ClipX0+1
952 adc _ClipX1+1
953 sta _ClipXc+1
954
955 lda _ClipXc+1
956 cmp #$80
957 ror _ClipXc+1
958 ror _ClipXc+0
959 #ifdef USE_ACCURATE_CLIPPING
960 ror _ClipXc-1
961 #endif
962
963 ; yc=(y0+y1)>>1;
964 clc
965 #ifdef USE_ACCURATE_CLIPPING
966 lda _ClipY0-1
967 adc _ClipY1-1
968 sta _ClipYc-1
969 #endif
970 lda _ClipY0+0
971 adc _ClipY1+0
972 sta _ClipYc+0
973
974 lda _ClipY0+1
975 adc _ClipY1+1
976 sta _ClipYc+1
977
978 lda _ClipYc+1
979 cmp #$80
980 ror _ClipYc+1
981 ror _ClipYc+0
982 #ifdef USE_ACCURATE_CLIPPING
983 ror _ClipYc-1
984 #endif
985 rts
986 .)
987
988 _ClipMoveP1
989 .(
990 ; x1=xc;
991 lda _ClipXc+0
992 sta _ClipX1+0
993 lda _ClipXc+1
994 sta _ClipX1+1
995 #ifdef USE_ACCURATE_CLIPPING
996 lda _ClipXc-1
997 sta _ClipX1-1
998 #endif
999
1000 ; y1=yc;
1001 lda _ClipYc+0
1002 sta _ClipY1+0
1003 lda _ClipYc+1
1004 sta _ClipY1+1
1005 #ifdef USE_ACCURATE_CLIPPING
1006 lda _ClipYc-1
1007 sta _ClipY1-1
1008 #endif
1009 rts
1010 .)
1011
1012 _ClipMoveP0
1013 .(
1014 ; x0=xc;
1015 lda _ClipXc+0
1016 sta _ClipX0+0
1017 lda _ClipXc+1
1018 sta _ClipX0+1
1019 #ifdef USE_ACCURATE_CLIPPING
1020 lda _ClipXc-1
1021 sta _ClipX0-1
1022 #endif
1023
1024 ; y0=yc;
1025 lda _ClipYc+0
1026 sta _ClipY0+0
1027 lda _ClipYc+1
1028 sta _ClipY0+1
1029 #ifdef USE_ACCURATE_CLIPPING
1030 lda _ClipYc-1
1031 sta _ClipY0-1
1032 #endif
1033 rts
1034 .)
1035
1036
1037 _ClipReturnPc
1038 .(
1039 ; LargeX=ClipXc;
1040 lda _ClipXc+0
1041 sta _LargeX+0
1042 lda _ClipXc+1
1043 sta _LargeX+1
1044
1045 ; LargeY=ClipYc;
1046 lda _ClipYc+0
1047 sta _LargeY+0
1048 lda _ClipYc+1
1049 sta _LargeY+1
1050
1051 rts
1052 .)
1053
1054 _ClipReturnP0
1055 .(
1056 ; LargeX=LargeX0;
1057 lda _LargeX0+0
1058 sta _LargeX+0
1059 lda _LargeX0+1
1060 sta _LargeX+1
1061
1062 ; LargeY=LargeY0;
1063 lda _LargeY0+0
1064 sta _LargeY+0
1065 lda _LargeY0+1
1066 sta _LargeY+1
1067
1068 rts
1069 .)
1070
1071 _ClipReturnP1
1072 .(
1073 ; LargeX=LargeX1;
1074 lda _LargeX1+0
1075 sta _LargeX+0
1076 lda _LargeX1+1
1077 sta _LargeX+1
1078
1079 ; LargeY=LargeY1;
1080 lda _LargeY1+0
1081 sta _LargeY+0
1082 lda _LargeY+1
1083 sta _LargeY+1
1084
1085 rts
1086 .)
1087
1088 _ClipSetNormalStartPoints
1089 .(
1090 ; x0=LargeX0;
1091 ; y0=LargeY0;
1092 lda _LargeX0+0
1093 sta _ClipX0+0
1094 lda _LargeX0+1
1095 sta _ClipX0+1
1096
1097 lda _LargeY0+0
1098 sta _ClipY0+0
1099 lda _LargeY0+1
1100 sta _ClipY0+1
1101
1102 ; x1=LargeX1;
1103 ; y1=LargeY1;
1104 lda _LargeX1+0
1105 sta _ClipX1+0
1106 lda _LargeX1+1
1107 sta _ClipX1+1
1108
1109 lda _LargeY1+0
1110 sta _ClipY1+0
1111 lda _LargeY1+1
1112 sta _ClipY1+1
1113
1114 rts
1115 .)
1116
1117 _ClipSetInvertedStartPoints
1118 .(
1119 ; x0=LargeX1;
1120 ; y0=LargeY1;
1121 lda _LargeX1+0
1122 sta _ClipX0+0
1123 lda _LargeX1+1
1124 sta _ClipX0+1
1125
1126 lda _LargeY1+0
1127 sta _ClipY0+0
1128 lda _LargeY1+1
1129 sta _ClipY0+1
1130
1131 ; x1=LargeX0;
1132 ; y1=LargeY0;
1133 lda _LargeX0+0
1134 sta _ClipX1+0
1135 lda _LargeX0+1
1136 sta _ClipX1+1
1137
1138 lda _LargeY0+0
1139 sta _ClipY1+0
1140 lda _LargeY0+1
1141 sta _ClipY1+1
1142
1143 rts
1144 .)
1145
1146
1147 _ClipDichoTopBottom
1148 .(
1149 .(
1150 ; if (LargeY0==CLIP_TOP)
1151 cpx _LargeY0+0
1152 bne skip
1153 lda _LargeY0+1
1154 bne skip
1155 jmp _ClipReturnP0
1156 skip
1157 .)
1158
1159 .(
1160 ; if (LargeY1==CLIP_TOP)
1161 cpx _LargeY1+0
1162 bne skip
1163 lda _LargeY1+1
1164 bne skip
1165 jmp _ClipReturnP1
1166 skip
1167 .)
1168
1169 sec
1170 lda _LargeY0+0
1171 sbc _LargeY1+0
1172 lda _LargeY0+1
1173 sbc _LargeY1+1
1174 bmi label4
1175
1176 label3
1177 ; (LargeY0>=LargeY1)
1178 jsr _ClipSetInvertedStartPoints
1179 jmp end_swap
1180
1181 label4
1182 ; (LargeY0<LargeY1)
1183 jsr _ClipSetNormalStartPoints
1184
1185 end_swap
1186
1187 #ifdef USE_ACCURATE_CLIPPING
1188 lda #0
1189 sta _ClipX0-1
1190 sta _ClipY0-1
1191 sta _ClipX1-1
1192 sta _ClipY1-1
1193 #endif
1194
1195 loop
1196 jsr _ClipComputeMidPoint
1197
1198 ; if (yc==CLIP_TOP)
1199 cpx _ClipYc+0
1200 bne not_done
1201 lda _ClipYc+1
1202 beq done
1203
1204 not_done
1205
1206 sec
1207 txa
1208 sbc _ClipYc+0
1209 lda #0
1210 sbc _ClipYc+1
1211 bmi replace_first
1212
1213 replace_second
1214 ; if (yc<CLIP_TOP)
1215 jsr _ClipMoveP0
1216 jmp loop
1217
1218 replace_first
1219 ; if (yc>CLIP_TOP)
1220 jsr _ClipMoveP1
1221 jmp loop
1222
1223 done
1224 ; Finished !
1225 jmp _ClipReturnPc
1226 .)
1227
1228
1229 _ClipDichoLeftRight
1230 .(
1231 .(
1232 ; if (LargeX0==CLIP_LEFT/RIGHT)
1233 cpx _LargeX0+0
1234 bne skip
1235 lda _LargeX0+1
1236 bne skip
1237 jmp _ClipReturnP0
1238 skip
1239 .)
1240
1241 .(
1242 ; if (LargeX1==CLIP_LEFT/RIGHT)
1243 cpx _LargeX1+0
1244 bne skip
1245 lda _LargeX1+1
1246 bne skip
1247 jmp _ClipReturnP1
1248 skip
1249 .)
1250
1251 sec
1252 lda _LargeX0+0
1253 sbc _LargeX1+0
1254 lda _LargeX0+1
1255 sbc _LargeX1+1
1256 bmi label4
1257
1258 label3
1259 ; (LargeX0>=LargeX1)
1260 jsr _ClipSetInvertedStartPoints
1261 jmp end_swap
1262
1263 label4
1264 ; (LargeX0<LargeX1)
1265 jsr _ClipSetNormalStartPoints
1266
1267 end_swap
1268
1269 #ifdef USE_ACCURATE_CLIPPING
1270 lda #0
1271 sta _ClipX0-1
1272 sta _ClipY0-1
1273 sta _ClipX1-1
1274 sta _ClipY1-1
1275 #endif
1276
1277 loop
1278 jsr _ClipComputeMidPoint
1279
1280 ; if (xc==CLIP_LEFT/RIGHT)
1281 cpx _ClipXc+0
1282 bne not_done
1283 lda _ClipXc+1
1284 beq done
1285
1286 not_done
1287
1288 sec
1289 txa
1290 sbc _ClipXc+0
1291 lda #0
1292 sbc _ClipXc+1
1293 bmi replace_first
1294
1295 replace_second
1296 ; if (xc<CLIP_LEFT/RIGHT)
1297 jsr _ClipMoveP0
1298 jmp loop
1299
1300 replace_first
1301 ; if (xc>CLIP_LEFT/RIGHT)
1302 jsr _ClipMoveP1
1303 jmp loop
1304
1305 done
1306 ; Finished !
1307 jmp _ClipReturnPc
1308 .)
1309
1310
1311
1312
1313 ;
1314 ; In this code, we assume that the CLIP_ values are fitting
1315 ; the resolution of an Oric screen, so they will never be out
1316 ; of a 240x200 screen resolution, fit in an unsigned byte.
1317 ;
1318 _ClipFindRegion
1319 ;jmp _ClipFindRegion
1320 .(
1321 ; Initialize with 'not clipped'
1322 lda #0
1323
1324 ;
1325 ; Bottom test
1326 ;
1327 .(
1328 ldy _LargeY+1
1329 bmi end_bottom ; If the high byte of Y is negative, it's certainly not clipped
1330 bne clip_bottom ; If it's not negative, then it needs to be clipped for sure
1331
1332 ldy _LargeY+0
1333 cpy #(CLIP_BOTTOM+1) ; 194
1334 bcc end_bottom
1335
1336 clip_bottom
1337 ora #1 ; Means (y >= CLIP_BOTTOM)
1338
1339 jmp end_top ; If the end point is clipped on the bottom, it cannot be on the top side as well
1340 .)
1341 end_bottom
1342
1343 ;
1344 ; Top test
1345 ;
1346 .(
1347 ldy _LargeY+1
1348 bmi clip_top ; If the high byte of Y is negative, it certainly needs to be clipped
1349 bne end_top ; If it's not negative, then it's too large to be clipped on top
1350
1351 ldy _LargeY+0
1352 cpy #CLIP_TOP ; 5
1353 bcs end_top
1354
1355 clip_top
1356 ora #2 ; Means (y < CLIP_TOP)
1357 .)
1358 end_top
1359
1360 ;
1361 ; Righttest
1362 ;
1363 .(
1364 ldy _LargeX+1
1365 bmi end_right ; If the high byte of X is negative, it's certainly not clipped
1366 bne clip_right ; If it's not negative, then it needs to be clipped for sure
1367
1368 ldy _LargeX+0
1369 cpy #(CLIP_RIGHT+1)
1370 bcc end_right
1371
1372 clip_right
1373 ora #4 ; Means (x >= CLIP_RIGHT)
1374
1375 jmp end_left ; If the end point is clipped on the right, it cannot be on the left side as well
1376 .)
1377 end_right
1378
1379 ;
1380 ; Left test
1381 ;
1382 .(
1383 ldy _LargeX+1
1384 bmi clip_left ; If the high byte of X is negative, it certainly needs to be clipped
1385 bne end_left ; If it's not negative, then it's too large to be clipped on left
1386
1387 ldy _LargeX+0
1388 cpy #CLIP_LEFT
1389 bcs end_left
1390
1391 clip_left
1392 ora #8 ; Means (x < CLIP_LEFT)
1393 .)
1394 end_left
1395
1396 ; Save the result
1397 sta _ClipCode
1398 rts
1399 .)
1400
1401
1402 ; Compute the outcode for the first point
1403 _ClipComputeCode0
1404 .(
1405 lda _LargeX0+0
1406 sta _LargeX+0
1407 lda _LargeX0+1
1408 sta _LargeX+1
1409
1410 lda _LargeY0+0
1411 sta _LargeY+0
1412 lda _LargeY0+1
1413 sta _LargeY+1
1414
1415 jsr _ClipFindRegion
1416
1417 lda _ClipCode
1418 sta _ClipCode0
1419
1420 rts
1421 .)
1422
1423 ; Compute the outcode for the second point
1424 _ClipComputeCode1
1425 .(
1426 lda _LargeX1+0
1427 sta _LargeX+0
1428 lda _LargeX1+1
1429 sta _LargeX+1
1430
1431 lda _LargeY1+0
1432 sta _LargeY+0
1433 lda _LargeY1+1
1434 sta _LargeY+1
1435
1436 jsr _ClipFindRegion
1437
1438 lda _ClipCode
1439 sta _ClipCode1
1440
1441 rts
1442 .)
1443
1444 _DrawClippedLine
1445 .(
1446 ; The region outcodes for the the endpoints
1447 jsr _ClipComputeCode0
1448 jsr _ClipComputeCode1
1449
1450 ; In theory, this can never end up in an infinite loop, it'll always come in one of the trivial cases eventually
1451 clip_loop
1452
1453 lda _ClipCode0
1454 ora _ClipCode1
1455 bne end_trivial_draw
1456 .(
1457 ; /accept because both endpoints are in screen or on the border, trivial accept
1458 lda _LargeX0
1459 sta _CurrentPixelX
1460 lda _LargeY0
1461 sta _CurrentPixelY
1462 lda _LargeX1
1463 sta _OtherPixelX
1464 lda _LargeY1
1465 sta _OtherPixelY
1466 jmp _DrawLine
1467 ;rts
1468 .)
1469 end_trivial_draw
1470
1471 lda _ClipCode0
1472 and _ClipCode1
1473 beq end_invisible_line
1474 .(
1475 ; The line isn't visible on screen, trivial reject
1476 rts
1477 .)
1478 end_invisible_line
1479
1480 .(
1481 ; if no trivial reject or accept, continue the loop
1482 .(
1483 lda _ClipCode0
1484 bne skip
1485 lda _ClipCode1
1486 skip
1487 .)
1488
1489 lsr
1490 bcc end_clip_bottom
1491 ; Clip bottom
1492 ldx #CLIP_BOTTOM
1493 jsr _ClipDichoTopBottom
1494 jmp end_clip_switch
1495 end_clip_bottom
1496
1497 lsr
1498 bcc end_clip_top
1499 ; Clip top
1500 ldx #CLIP_TOP
1501 jsr _ClipDichoTopBottom
1502 jmp end_clip_switch
1503 end_clip_top
1504
1505 lsr
1506 bcc end_clip_right
1507 ; Clip right
1508 ldx #CLIP_RIGHT
1509 jsr _ClipDichoLeftRight
1510 jmp end_clip_switch
1511 end_clip_right
1512
1513 lsr
1514 bcc end_clip_left
1515 ; Clip left
1516 ldx #CLIP_LEFT
1517 jsr _ClipDichoLeftRight
1518 jmp end_clip_switch
1519 end_clip_left
1520
1521 end_clip_switch
1522
1523 lda _ClipCode0
1524 beq clip_second_point
1525
1526 clip_first_point
1527 ; First endpoint was clipped
1528 lda _LargeX+0
1529 sta _LargeX0+0
1530 lda _LargeX+1
1531 sta _LargeX0+1
1532
1533 lda _LargeY+0
1534 sta _LargeY0+0
1535 lda _LargeY+1
1536 sta _LargeY0+1
1537
1538 jsr _ClipComputeCode0
1539
1540 jmp clip_loop
1541
1542 clip_second_point
1543 ; Second endpoint was clipped
1544 lda _LargeX+0
1545 sta _LargeX1+0
1546 lda _LargeX+1
1547 sta _LargeX1+1
1548
1549 lda _LargeY+0
1550 sta _LargeY1+0
1551 lda _LargeY+1
1552 sta _LargeY1+1
1553
1554 jsr _ClipComputeCode1
1555
1556 jmp clip_loop
1557
1558 .)
1559
1560 ; Not supposed to arrive here :p
1561 rts
1562 .)
1563
1564
1565 _DoubleBuffOn
1566 .(
1567 lda double_buff
1568 beq _SwitchDoubleBuff
1569 rts
1570 .)
1571
1572 _DoubleBuffOff
1573 .(
1574 lda double_buff
1575 bne _SwitchDoubleBuff
1576 rts
1577 .)
1578
1579
1580 _SwitchDoubleBuff
1581 .(
1582
1583 ; Patch the circle routine
1584 lda patch_circleclip1+1
1585 cmp #199
1586 beq clip1
1587 lda #199
1588 jmp cont
1589 clip1
1590 lda #(CLIP_BOTTOM)
1591
1592 cont
1593 sta patch_circleclip1+1
1594 sta patch_circleclip2+1
1595 sta patch_circleclip3+1
1596 sta patch_circleclip4+1
1597 sta patch_circleclip5+1
1598 /* sta patch_circleclip6+1
1599 sta patch_circleclip7+1
1600 sta patch_circleclip8+1
1601 sta patch_circleclip9+1*/
1602 lda double_buff
1603 eor #$ff
1604 sta double_buff
1605 jmp _GenerateTables
1606 .)
1607
1608
1609
1610 #undef e
1611 #undef i
1612 #undef dx
1613 #undef dy
1614
1615
1616 #endif
1617
1618
1619
1620
1621
1622

  ViewVC Help
Powered by ViewVC 1.1.26