]> 4ch.mooo.com Git - 16.git/blob - 16/xlib/xpolygon.asm
16_ca needs huge amounts of work and I should remember what needs to be done soon...
[16.git] / 16 / xlib / xpolygon.asm
1 ;-----------------------------------------------------------------------\r
2 ; MODULE XPOLYGON\r
3 ;\r
4 ; Filled Triangle function for all MODE X 256 Color resolutions\r
5 ;\r
6 ; Compile with Tasm.\r
7 ; C callable.\r
8 ;\r
9 ; ****** XLIB - Mode X graphics library                ****************\r
10 ; ******                                               ****************\r
11 ; ****** Written By Themie Gouthas                     ****************\r
12 ;\r
13 ; This module is based on code developed by Steve Dollind for his\r
14 ; XSPACE game.\r
15 ; Copyright (C) 1992 Steven Dollins  --  sdollins@uiuc.edu\r
16 ;\r
17 ;\r
18 ; egg@dstos3.dsto.gov.au\r
19 ; teg@bart.dsto.gov.au\r
20 ;-----------------------------------------------------------------------\r
21 include xlib.inc\r
22 include xpolygon.inc\r
23 \r
24 .data\r
25 ; Plane masks for clipping left and right edges of rectangle.\r
26         LeftClipPlaneMask       db      00fh,00eh,00ch,008h\r
27         RightClipPlaneMask      db      00fh,001h,003h,007h\r
28 \r
29 .code\r
30 \r
31 \r
32 ;-----------------------------------------------------------------------\r
33 ; void HLineClipR\r
34 ;\r
35 ;       Draws a horizontal line from (X1, Y) to (X2, Y).\r
36 ;       Uses Watcom Parameter passing convention in registers\r
37 ;\r
38 ;   X1 in AX\r
39 ;   X2 in DX\r
40 ;   Y in CX\r
41 ;   Color in BX\r
42 ;   PageOffset in DI\r
43 ;\r
44 ; By Themie Gouthas - Adapted from x_fill_rect.\r
45 ;-----------------------------------------------------------------------\r
46 proc _HLineClipR near\r
47         push    di\r
48         cmp     dx,ax                ; if (X2 < X1) then assume no line\r
49         jl      @@Invisible          ;   is visible\r
50 \r
51         cmp     cx,[_TopClip]        ; if (Y < TopClip) then no line\r
52         jl      @@Invisible\r
53 \r
54         cmp     cx,[_BottomClip]     ;if (Y > BottomClip) then no line\r
55         jg      @@Invisible\r
56 \r
57         mov     di,[_RightClip]      ;convert RightClip to pixel coords\r
58         sal     di,2\r
59         cmp     ax,di                ; if (X1 > RightClip) then no line\r
60         jg      @@Invisible\r
61 \r
62         cmp     dx,di                ; if (X2 > RightClip) then\r
63         jle     @@ClipLeft           ;  X2:=RightClip\r
64         mov     dx,di\r
65 \r
66 @@ClipLeft:\r
67         mov     di,[_LeftClip]       ;convert LeftClip to pixel coords\r
68         sal     di,2\r
69         cmp     dx,di                ; if (X2 < LeftClip) then no line\r
70         jl      @@Invisible\r
71 \r
72         cmp     ax,di                ;if (X1 > LeftClip) then were ready to plot\r
73         jge     @@DoLine\r
74 \r
75         mov     ax,di                ;  X1:=LeftClip\r
76         jmp     short @@DoLine\r
77 \r
78 @@Invisible:\r
79         pop     di\r
80         ret\r
81 \r
82 @@DoLine:\r
83         pop     di                      ; di = PageOffset\r
84         xchg    cx,ax                   ; AX = Y,  CX = X1\r
85         mov     si,dx                   ; SI = DX = X2\r
86         mul     [_ScrnLogicalByteWidth]\r
87         mov     dx,si                   ; Reset DX to X1 since mul erases DX\r
88         add     ax,di\r
89         mov     di,cx\r
90         sar     di,2                    ; Convert to bytes\r
91         add     di,ax                   ; DI->First byte\r
92 \r
93         and     si,03h                  ; look up right edge plane mask\r
94         mov     ah,RightClipPlaneMask[si]\r
95         mov     si,cx                   ; look up left edge plane mask\r
96         and     si,03h\r
97         mov     al,LeftClipPlaneMask[si]\r
98 \r
99         cmp     dx,cx                   ; No harm in being paranoid..\r
100         jle     @@Invisible2\r
101 \r
102         xchg    cx,dx                   ;CX=X2, DX=X1\r
103         dec     cx\r
104         and     dx,not 03h\r
105         sub     cx,dx\r
106         js      @@Invisible2\r
107         shr     cx,2\r
108         jnz     @@MasksSet\r
109         and     al,ah\r
110 @@MasksSet:\r
111         mov     dl,bl                 ; set BX=Plane Masks, AH=Color\r
112         mov     bx,ax\r
113         mov     ah,dl\r
114         mov     dx,SC_INDEX+1         ;set the Sequence Controller Index to\r
115         mov     al,bl\r
116         out     dx,al\r
117         mov     al,ah\r
118         stosb                         ; Plot left byte\r
119         dec     cx\r
120         js      @@Invisible2\r
121         jz      @@RightEnd\r
122 \r
123 \r
124         mov     al,0fh                ; plot middle bytes\r
125         out     dx,al\r
126         mov     al,ah\r
127         shr     cx,1\r
128         rep     stosw\r
129         adc     cx,cx\r
130         rep     stosb\r
131 \r
132 \r
133 \r
134 @@RightEnd:\r
135         mov     al,bh              ; Plot right  byte\r
136         out     dx,al\r
137         mov     al,ah\r
138         stosb\r
139 @@Invisible2:\r
140         ret\r
141 _HLineClipR endp\r
142 \r
143 \r
144 ;-----------------------------------------------------------------------\r
145 ; void x_triangle( int X0, int Y0, int X1, int Y1,\r
146 ;                int X2, int Y2, unsigned Color, unsigned PageOffset );\r
147 ;\r
148 ;\r
149 ; Written by S. Dollins\r
150 \r
151 _x_triangle  proc\r
152 ARG   X0:word,Y0:word,X1:word,Y1:word,X2:word,Y2:word,Color:word,PageOffset:word\r
153 LOCAL DX01:word, DY01:word, DX02:word, DY02:word, DX12:word, DY12:word, \\r
154       DP01:word, DP02:word, DP12:word, XA01:word, XA02:word, XA12:word=STK\r
155 \r
156         push    bp\r
157         mov     bp,sp\r
158         sub     sp,STK\r
159         push    ds es si di  ; Save es for polygon routine\r
160 \r
161         mov     ax,X0\r
162         mov     bx,Y0\r
163         mov     cx,X1\r
164         mov     dx,Y1\r
165 \r
166         cmp     bx,dx   ; Y0,Y1\r
167         jl      tri_Y0lY1\r
168         je      tri_Y0eY1\r
169         xchg    ax,cx   ; X0,X1\r
170         xchg    bx,dx   ; Y0,Y1\r
171 tri_Y0lY1:\r
172         cmp     dx,Y2   ; Y1,Y2\r
173         jg      tri_a\r
174         jmp     tri_sorted\r
175 tri_a:  xchg    cx,X2   ; X1,X2\r
176         xchg    dx,Y2   ; Y1,Y2\r
177         cmp     bx,dx   ; Y0,Y1\r
178         jge     tri_b\r
179         jmp     tri_sorted\r
180 tri_b:  je      tri_bot\r
181         xchg    ax,cx   ; X0,X1\r
182         xchg    bx,dx   ; Y0,Y1\r
183         jmp     tri_sorted\r
184 tri_Y0eY1:\r
185         cmp     bx,Y2   ; Y0,Y2\r
186         jl      tri_bot\r
187         jg      tri_c\r
188         jmp     tri_done\r
189 tri_c:  xchg    ax,X2   ; X0,X2\r
190         xchg    bx,Y2   ; Y0,Y2\r
191         jmp     tri_sorted\r
192 \r
193 tri_bot:\r
194         cmp     ax,cx   ; X0,X1\r
195         jl      tri_bot_sorted\r
196         jg      tri_bot_a\r
197         jmp     tri_done\r
198 tri_bot_a:\r
199         xchg    ax,cx   ; X0,X1\r
200 tri_bot_sorted:\r
201         cmp     bx,[_BottomClip]\r
202         jle     tri_bot_y0ok\r
203         jmp     tri_done\r
204 tri_bot_y0ok:\r
205         mov     si,Y2\r
206         cmp     si,[_TopClip]\r
207         jge     tri_bot_y2ok\r
208         jmp     tri_done\r
209 tri_bot_y2ok:\r
210         mov     X0,ax\r
211         mov     Y0,bx\r
212         mov     X1,cx\r
213         mov     Y1,dx\r
214 \r
215         mov     bx,Y2   ;    bx <- Y2\r
216         sub     bx,Y0   ;    bx <- Y2 - Y0\r
217         mov     DY02,bx ;  DY02 <- Y2 - Y0\r
218         mov     ax,X2   ;    ax <- X2\r
219         sub     ax,X0   ;    ax <- X2 - X0\r
220         mov     DX02,ax ;  DX02 <- X2 - X0\r
221         mov     cx,ax   ;    cx <- DX02\r
222         cwd             ; dx:ax <- DX02\r
223         idiv    bx      ;    ax <- DX02 / DY02\r
224         cmp     cx,0\r
225         jge     short tri_bot02\r
226         dec     ax      ;    ax <- DX02 / DY02 - 1\r
227 tri_bot02:\r
228         mov     XA02,ax ;  XA02 <- DX02 / DY02\r
229         imul    bx      ;    ax <- XA02 * DY02\r
230         sub     cx,ax   ;    cx <- DX02 - XA02 * DY02\r
231         mov     DP02,cx ;  DP02 <- DX02 - XA02 * DY02\r
232 \r
233         mov     bx,Y2   ;    bx <- Y2\r
234         sub     bx,Y1   ;    bx <- Y2 - Y1\r
235         mov     DY12,bx ;  DY02 <- Y2 - Y1\r
236         mov     ax,X2   ;    ax <- X2\r
237         sub     ax,X1   ;    ax <- X2 - X1\r
238         mov     DX12,ax ;  DX12 <- X2 - X1\r
239         mov     cx,ax   ;    cx <- DX12\r
240         cwd             ; dx:ax <- DX12\r
241         idiv    bx      ;    ax <- DX12 / DY12\r
242         cmp     cx,0\r
243         jge     short tri_bot12\r
244         dec     ax      ;    ax <- DX12 / DY12 - 1\r
245 tri_bot12:\r
246         mov     XA12,ax ;  XA12 <- DX12 / DY12\r
247         imul    bx      ;    ax <- XA12 * DY12\r
248         sub     cx,ax   ;    cx <- DX12 - XA12 * DY12\r
249         mov     DP12,cx ;  DP12 <- DX12 - XA12 * DY12\r
250 \r
251         mov     ax,0    ; PL <- 0\r
252         mov     bx,0    ; PS <- 0\r
253         mov     cx,Y0   ;  Y <- Y0\r
254         mov     si,X0\r
255         mov     di,X1\r
256         dec     di\r
257 tri_bot_loop:\r
258         inc     cx      ; Y\r
259 \r
260         add     ax,DP02 ; PL,DP02\r
261         jle     short tri_bot_shortl\r
262         sub     ax,DY02 ; PL,DY02\r
263         inc     si      ; XL\r
264 tri_bot_shortl:\r
265         add     si,XA02 ; XL,XA02\r
266 \r
267         add     bx,DP12 ; PS,DP12\r
268         jle     short tri_bot_shortr\r
269         sub     bx,DY12 ; PS,DY12\r
270         inc     di      ; XS\r
271 tri_bot_shortr:\r
272         add     di,XA12 ; XS,XA12\r
273 \r
274         push    di      ; XS\r
275         push    si      ; XL\r
276         cmp     cx,Y2   ; Y,Y2\r
277         jl      short tri_bot_loop\r
278 \r
279         jmp     tri_draw_lines\r
280 \r
281 \r
282 tri_sorted:\r
283         cmp     bx,[_BottomClip]\r
284         jle     tri_y0ok\r
285         jmp     tri_done\r
286 tri_y0ok:\r
287         mov     si,Y2\r
288         cmp     si,[_TopClip]\r
289         jge     tri_y2ok\r
290         jmp     tri_done\r
291 tri_y2ok:\r
292         mov     X0,ax\r
293         mov     Y0,bx\r
294         mov     X1,cx\r
295         mov     Y1,dx\r
296 \r
297         mov     bx,dx   ;    bx <- Y1\r
298         sub     bx,Y0   ;    bx <- Y1 - Y0\r
299         mov     DY01,bx ;  DY01 <- Y1 - Y0\r
300         mov     ax,X1   ;    ax <- X1\r
301         sub     ax,X0   ;    ax <- X1 - X0\r
302         mov     DX01,ax ;  DX01 <- X1 - X0\r
303         mov     cx,ax   ;    cx <- DX01\r
304         cwd             ; dx:ax <- DX01\r
305         idiv    bx      ;    ax <- DX01 / DY01\r
306         cmp     cx,0    ;  DX01 ? 0\r
307         jge     short tri_psl01\r
308         dec     ax      ;    ax <- DX01 / DY01 - 1\r
309 tri_psl01:\r
310         mov     XA01,ax ;  XA01 <- DX01 / DY01\r
311         imul    bx      ;    ax <- XA01 * DY01\r
312         sub     cx,ax   ;    cx <- DX01 - XA01 * DY01\r
313         mov     DP01,cx ;  DP01 <- DX01 - XA01 * DY01\r
314 \r
315         mov     bx,Y2   ;    bx <- Y2\r
316         sub     bx,Y0   ;    bx <- Y2 - Y0\r
317         mov     DY02,bx ;  DY02 <- Y2 - Y0\r
318         mov     ax,X2   ;    ax <- X2\r
319         sub     ax,X0   ;    ax <- X2 - X0\r
320         mov     DX02,ax ;  DX02 <- X2 - X0\r
321         mov     cx,ax   ;    cx <- DX02\r
322         cwd             ; dx:ax <- DX02\r
323         idiv    bx      ;    ax <- DX02 / DY02\r
324         cmp     cx,0\r
325         jge     short tri_psl02\r
326         dec     ax      ;    ax <- DX02 / DY02 - 1\r
327 tri_psl02:\r
328         mov     XA02,ax ;  XA02 <- DX02 / DY02\r
329         imul    bx      ;    ax <- XA02 * DY02\r
330         sub     cx,ax   ;    cx <- DX02 - XA02 * DY02\r
331         mov     DP02,cx ;  DP02 <- DX02 - XA02 * DY02\r
332 \r
333         mov     bx,Y2   ;    bx <- Y2\r
334         sub     bx,Y1   ;    bx <- Y2 - Y1\r
335         jle     short tri_const_computed\r
336         mov     DY12,bx ;  DY12 <- Y2 - Y1\r
337         mov     ax,X2   ;    ax <- X2\r
338         sub     ax,X1   ;    ax <- X2 - X1\r
339         mov     DX12,ax ;  DX12 <- X2 - X1\r
340         mov     cx,ax   ;    cx <- DX12\r
341         cwd             ; dx:ax <- DX12\r
342         idiv    bx      ;    ax <- DX12 / DY12\r
343         cmp     cx,0\r
344         jge     short tri_psl12\r
345         dec     ax      ;    ax <- DX12 / DY12 - 1\r
346 tri_psl12:\r
347         mov     XA12,ax ;  XA12 <- DX12 / DY12\r
348         imul    bx      ;    ax <- XA12 * DY12\r
349         sub     cx,ax   ;    cx <- DX12 - XA12 * DY12\r
350         mov     DP12,cx ;  DP12 <- DX12 - XA12 * DY12\r
351 \r
352 tri_const_computed:\r
353         mov     ax,DX01\r
354         imul    word ptr DY02\r
355         mov     bx,ax\r
356         mov     cx,dx   ; DX01 * DY02 in cx:bx\r
357 \r
358         mov     ax,DX02\r
359         imul    word ptr DY01 ; DX02 * DY01 in dx:ax\r
360         cmp     cx,dx\r
361         jg      tri_pt1rt\r
362         jl      tri_pt1lt\r
363         cmp     bx,ax\r
364         ja      tri_pt1rt\r
365         jb      tri_pt1lt\r
366         jmp     tri_done\r
367 \r
368 ;------------------------------------\r
369 ; Short sides are on the left\r
370 ;\r
371 tri_pt1lt:\r
372         mov     ax,0    ; PL <- 0\r
373         mov     bx,0    ; PS <- 0\r
374         mov     cx,Y0   ;  Y <- Y0\r
375         mov     si,X0\r
376         mov     di,si\r
377         dec     si\r
378 tri_lt_loop:\r
379         inc     cx      ; Y\r
380 \r
381         add     ax,DP02 ; PL,DP02\r
382         jle     short tri_lt_shortl\r
383         sub     ax,DY02 ; PL,DY02\r
384         inc     si      ; XL\r
385 tri_lt_shortl:\r
386         add     si,XA02 ; XL,XA02\r
387 \r
388         add     bx,DP01 ; PS,DP01\r
389         jle     short tri_lt_shortr\r
390         sub     bx,DY01 ; PS,DY01\r
391         inc     di      ; XS\r
392 tri_lt_shortr:\r
393         add     di,XA01 ; XS,XA01\r
394 \r
395         push    si      ; XL\r
396         push    di      ; XS\r
397         cmp     cx,Y1   ; Y,Y1\r
398         jl      short tri_lt_loop\r
399 \r
400         jmp     short tri_lb_start\r
401 tri_lb_loop:\r
402         inc     cx      ; Y\r
403 \r
404         add     ax,DP02 ; PL,DP02\r
405         jle     short tri_lb_shortl\r
406         sub     ax,DY02 ; PL,DY02\r
407         inc     si      ; XL\r
408 tri_lb_shortl:\r
409         add     si,XA02 ; XL,XA02\r
410 \r
411         add     bx,DP12 ; PS,DP12\r
412         jle     short tri_lb_shortr\r
413         sub     bx,DY12 ; PS,DY12\r
414         inc     di      ; XS\r
415 tri_lb_shortr:\r
416         add     di,XA12 ; XS,XA12\r
417 \r
418         push    si      ; XL\r
419         push    di      ; XS\r
420 tri_lb_start:\r
421         cmp     cx,Y2   ; Y,Y2\r
422         jl      tri_lb_loop\r
423         jmp     short tri_draw_lines\r
424 \r
425 ;------------------------------------\r
426 ; short sides are on the right\r
427 ;\r
428 tri_pt1rt:\r
429         mov     ax,0    ; PL <- 0\r
430         mov     bx,0    ; PS <- 0\r
431         mov     cx,Y0   ;  Y <- Y0\r
432         mov     si,X0\r
433         mov     di,si\r
434         dec     di\r
435 tri_rt_loop:\r
436         inc     cx      ; Y\r
437 \r
438         add     ax,DP02 ; PL,DP02\r
439         jle     short tri_rt_shortl\r
440         sub     ax,DY02 ; PL,DY02\r
441         inc     si      ; XL\r
442 tri_rt_shortl:\r
443         add     si,XA02 ; XL,XA02\r
444 \r
445         add     bx,DP01 ; PS,DP01\r
446         jle     short tri_rt_shortr\r
447         sub     bx,DY01 ; PS,DY01\r
448         inc     di      ; XS\r
449 tri_rt_shortr:\r
450         add     di,XA01 ; XS,XA01\r
451 \r
452         push    di      ; XS\r
453         push    si      ; XL\r
454         cmp     cx,Y1   ; Y,Y1\r
455         jl      short tri_rt_loop\r
456 \r
457         jmp     short tri_rb_start\r
458 tri_rb_loop:\r
459         inc     cx      ; Y\r
460 \r
461         add     ax,DP02 ; PL,DP02\r
462         jle     short tri_rb_shortl\r
463         sub     ax,DY02 ; PL,DY02\r
464         inc     si      ; XL\r
465 tri_rb_shortl:\r
466         add     si,XA02 ; XL,XA02\r
467 \r
468         add     bx,DP12 ; PS,DP12\r
469         jle     short tri_rb_shorts\r
470         sub     bx,DY12 ; PS,DY12\r
471         inc     di      ; XS\r
472 tri_rb_shorts:\r
473         add     di,XA12 ; XS,XA12\r
474 \r
475         push    di      ; XS\r
476         push    si      ; XL\r
477 tri_rb_start:\r
478         cmp     cx,Y2   ; Y,Y2\r
479         jl      short tri_rb_loop\r
480 \r
481 ;------------------------------------\r
482 ; Draw the horizontal lines\r
483 ;\r
484 \r
485 \r
486 tri_draw_lines:\r
487 \r
488         mov     cx,SCREEN_SEG       ;point ES to video segment\r
489         mov     es,cx\r
490         mov     dx,SC_INDEX         ;set the Sequence Controller Index to\r
491         mov     al,MAP_MASK         ; point to the Map Mask register\r
492         out     dx,al\r
493 \r
494 \r
495 line_loop:\r
496         pop     ax\r
497         pop     dx\r
498         cmp     ax,dx\r
499         jg      tri_draw_next\r
500         mov     bx,Color\r
501         mov     cx,Y2\r
502         add     dx,2\r
503         mov     di,PageOffset\r
504         call    _HLineClipR\r
505 tri_draw_next:\r
506         dec     word ptr Y2\r
507         dec     word ptr DY02\r
508         jnz     line_loop\r
509 \r
510 tri_done:\r
511         pop     di si es ds\r
512         mov     sp,bp\r
513         pop     bp\r
514         ret\r
515 _x_triangle  endp\r
516 \r
517 ;-----------------------------------------------------------------------\r
518 ; void x_polygon( VERTEX vertices[], int num_vertices,unsigned Color,\r
519 ;                unsigned PageOffset );\r
520 ;\r
521 ; Where VERTEX is defined as:\r
522 ;\r
523 ; typedef struct {\r
524 ;    int X;\r
525 ;    int Y;\r
526 ; } far VERTEX;\r
527 ;\r
528 ;\r
529 ; Written by T. Gouthas\r
530 ;\r
531 ;\r
532 ;\r
533 ; Note: This is just a quick hack of a generalized polygon routine.\r
534 ;   The way it works is by splitting up polygons into triangles and\r
535 ;   drawing each individual triangle.\r
536 ;\r
537 ; Obviously this is not as fast as it could be, but for polygons of\r
538 ; 4 vertices it should perform quite respectably.\r
539 ;\r
540 ; Warning: Only works for convex polygons (convex polygons are such\r
541 ;  that if you draw a line from any two vertices, every point on that\r
542 ;  line will be within the polygon)\r
543 ;\r
544 ;\r
545 \r
546 _x_polygon proc\r
547        ARG   vertices:dword,numvertices:word,Color:word,PageOffset:word\r
548        LOCAL x0:word,y0:word,tri_count:word=STK\r
549        push  bp\r
550        mov   bp,sp\r
551        sub   sp,STK\r
552        push  di si\r
553 \r
554        mov   cx,numvertices\r
555        cmp   cx,3\r
556        jl    @@Done\r
557 \r
558        sub   cx,3\r
559        mov   tri_count,cx      ; Number of triangles to draw\r
560        les   di,vertices       ; ES:DI -> Vertices\r
561 \r
562        mov   ax,es:[di]        ; Save first vertex\r
563        mov   x0,ax\r
564        mov   ax,es:[di+2]\r
565        mov   y0,ax\r
566 \r
567        ; Set up permanent parameter stack frame for\r
568        ; triangle parameters\r
569 \r
570        mov   ax,PageOffset\r
571        push  ax\r
572        mov   ax,Color\r
573        push  ax\r
574 \r
575        sub   sp,12\r
576        mov   si,sp\r
577 \r
578 @@NextTriangle:\r
579 \r
580        add   di,4\r
581        mov   ax,es:[di]      ; Vertex 2\r
582        mov   ss:[si],ax\r
583        mov   ax,es:[di+2]\r
584        mov   ss:[si+2],ax\r
585 \r
586        mov   ax,es:[di+4]    ; Vertex 1\r
587        mov   ss:[si+4],ax\r
588        mov   ax,es:[di+6]\r
589        mov   ss:[si+6],ax\r
590 \r
591        mov   ax,x0           ; Vertex 0: The first vertex is\r
592        mov   ss:[si+8],ax    ; part of every triangle\r
593        mov   ax,y0\r
594        mov   ss:[si+10],ax\r
595 \r
596        call  _x_triangle\r
597        dec   tri_count\r
598        jns   @@NextTriangle\r
599 \r
600        add   sp,16    ; Remove triangle stack frame\r
601 \r
602 @@Done:\r
603        pop   si di\r
604        mov   sp,bp\r
605        pop   bp\r
606        ret\r
607 _x_polygon endp\r
608         end