OSDN Git Service

modified: 16/DOS_GFX.OBJ
[proj16/16.git] / 16 / lib / x / MXPT.ASM
1 ;-----------------------------------------------------------\r
2 ;\r
3 ; MXPT.ASM - Convex polygon fill with texture mapping\r
4 ; Copyright (c) 1994 by Alessandro Scotti\r
5 ;\r
6 ;-----------------------------------------------------------\r
7 ;WARN    PRO\r
8 ;NOWARN  RES\r
9 INCLUDE MODEX.DEF\r
10 \r
11 PUBLIC  mxTexturePoly\r
12 \r
13 ;-----------------------------------------------------------\r
14 ;\r
15 ; "Local" definitions\r
16 ;\r
17 TPOINT  STRUC\r
18         X       DW      ?\r
19         Y       DW      ?\r
20 TPOINT  ENDS\r
21 \r
22 ; Do NOT change order!\r
23 TSCAN   STRUC\r
24         Y1      DW      ?\r
25         IX1     DW      ?\r
26         IY1     DW      ?\r
27         Y2      DW      ?\r
28         IX2     DW      ?\r
29         IY2     DW      ?\r
30 TSCAN   ENDS\r
31 \r
32 MAXSCANCOLUMNS  EQU     POLYSCANBUFSIZE / SIZE TSCAN\r
33 \r
34 MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
35                 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
36 \r
37 EXTRN   mx_VideoSegment : WORD\r
38 EXTRN   mx_CodeSegment  : WORD\r
39 EXTRN   mx_BytesPerLine : WORD\r
40 EXTRN   mx_ClipX1       : WORD\r
41 EXTRN   mx_ClipY1       : WORD\r
42 EXTRN   mx_ClipX2       : WORD\r
43 EXTRN   mx_ClipY2       : WORD\r
44 EXTRN   mx_ScanBuffer   : NEAR\r
45 \r
46 ; Global variables, to optimize allocation of local space\r
47 mx_Texture      DD      ?\r
48 mx_TextureWidth DW      ?\r
49 mx_XStepLo      DW      ?\r
50 mx_XStepHi      DW      ?\r
51 mx_XBump        DW      ?\r
52 mx_YStepLo      DW      ?\r
53 mx_YStepHi      DW      ?\r
54 mx_YBump        DW      ?\r
55 mx_TempX        DW      512 DUP(?)\r
56 mx_TempY        DW      512 DUP(?)\r
57 \r
58 ;-----------------------------------------------------------\r
59 ;\r
60 ; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
61 ; Also saves information for the texture scanner.\r
62 ;\r
63 ; Input:\r
64 ;       DS:BX   = pointer to start point (X1, Y1)\r
65 ;       DS:SI   = pointer to end point (X2, Y2)\r
66 ;       ES:DI   = pointer to edge buffer\r
67 ; Output:\r
68 ;       ES:DI   = updated pointer to edge buffer\r
69 ;\r
70 subScan         PROC NEAR\r
71         mov     cx, ds:[si].X\r
72         sub     cx, ds:[bx].X           ; Get width\r
73         mov     es:[di].IX1, cx         ; Save width\r
74         jg      @@1\r
75         ret\r
76 @@1:\r
77         push    bp                      ; Save BP\r
78 \r
79         mov     ax, ds:[si].Y\r
80         mov     bx, ds:[bx].Y\r
81         sub     ax, bx                  ; Get height\r
82         jg      @@T2B                   ; Scan top to bottom\r
83         jl      @@B2T                   ; Scan bottom to top\r
84 \r
85 ; Special case: vertical line\r
86         mov     ax, bx\r
87 @@V:\r
88         mov     es:[di].Y1, ax\r
89         add     di, SIZE TSCAN\r
90         dec     cx\r
91         jnz     @@V\r
92         jmp     @@Exit\r
93 \r
94 ; Scan top to bottom\r
95 @@T2B:\r
96         cwd\r
97         div     cx\r
98         mov     bp, ax\r
99         xor     ax, ax\r
100         div     cx\r
101         xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
102         mov     dx, 8000h\r
103 @@T2BLoop:\r
104         mov     es:[di].Y1, ax\r
105         add     di, SIZE TSCAN\r
106         add     dx, bx\r
107         adc     ax, bp\r
108         dec     cx\r
109         jnz     @@T2BLoop\r
110         jmp     @@Exit\r
111 \r
112 ; Scan bottom to top\r
113 @@B2T:\r
114         neg     ax\r
115         cwd\r
116         div     cx\r
117         mov     bp, ax\r
118         xor     ax, ax\r
119         div     cx\r
120         xchg    ax, bx\r
121         mov     dx, 8000h\r
122 @@B2TLoop:\r
123         mov     es:[di].Y1, ax\r
124         add     di, SIZE TSCAN\r
125         sub     dx, bx\r
126         sbb     ax, bp\r
127         dec     cx\r
128         jnz     @@B2TLoop\r
129 \r
130 @@Exit:\r
131         pop     bp\r
132         ret\r
133 subScan         ENDP\r
134 \r
135 ;-----------------------------------------------------------\r
136 ;\r
137 ; Scans a texture edge.\r
138 ;\r
139 ; Input:\r
140 ;       DS:BX   = pointer to start point (X1, Y1)\r
141 ;       DS:SI   = pointer to end point (X2, Y2)\r
142 ;       ES:DI   = pointer to edge buffer\r
143 ;       CX      = number of steps\r
144 ; Output:\r
145 ;       ES:DI   = updated pointer to edge buffer\r
146 ;\r
147 subScanTexture  PROC NEAR\r
148         .push   bp\r
149         .push   di, bx, cx              ; Save registers\r
150         mov     ax, ds:[si].X           ; Scan X coordinate first\r
151         mov     bx, ds:[bx].X\r
152         sub     ax, bx\r
153         jg      @@XP                    ; Positive\r
154         jl      @@XN                    ; Negative\r
155 \r
156 ; Special case: constant\r
157 @@XCLoop:\r
158         mov     es:[di].IX1, bx\r
159         add     di, SIZE TSCAN\r
160         dec     cx\r
161         jnz     @@XCLoop\r
162         jmp     @@ScanY\r
163 \r
164 ; Increasing step\r
165 @@XP:\r
166         cwd\r
167         div     cx\r
168         mov     bp, ax\r
169         xor     ax, ax\r
170         div     cx\r
171         xchg    ax, bx\r
172         mov     dx, 8000h\r
173 @@XPLoop:\r
174         mov     es:[di].IX1, ax\r
175         add     di, SIZE TSCAN\r
176         add     dx, bx\r
177         adc     ax, bp\r
178         dec     cx\r
179         jnz     @@XPLoop\r
180         jmp     @@ScanY\r
181 \r
182 ; Decreasing step\r
183 @@XN:\r
184         neg     ax\r
185         cwd\r
186         div     cx\r
187         mov     bp, ax\r
188         xor     ax, ax\r
189         div     cx\r
190         xchg    ax, bx\r
191         mov     dx, 8000h\r
192 @@XNLoop:\r
193         mov     es:[di].IX1, ax\r
194         add     di, SIZE TSCAN\r
195         sub     dx, bx\r
196         sbb     ax, bp\r
197         dec     cx\r
198         jnz     @@XNLoop\r
199 \r
200 ; Now scan the Y coordinate\r
201 @@ScanY:\r
202         .pop    di, bx, cx              ; Restore registers\r
203         mov     ax, ds:[si].Y\r
204         mov     bx, ds:[bx].Y\r
205         sub     ax, bx\r
206         jg      @@YP                    ; Positive\r
207         jl      @@YN                    ; Negative\r
208 \r
209 ; Special case: constant\r
210         mov     ax, cx\r
211 @@YCLoop:\r
212         mov     es:[di].IY1, bx\r
213         add     di, SIZE TSCAN\r
214         dec     ax\r
215         jnz     @@YCLoop\r
216         jmp     @@Exit\r
217 \r
218 ; Increasing step\r
219 @@YP:\r
220         cwd\r
221         div     cx\r
222         mov     bp, ax\r
223         xor     ax, ax\r
224         div     cx\r
225         xchg    ax, bx\r
226         mov     dx, 8000h\r
227 @@YPLoop:\r
228         mov     es:[di].IY1, ax\r
229         add     di, SIZE TSCAN\r
230         add     dx, bx\r
231         adc     ax, bp\r
232         dec     cx\r
233         jnz     @@YPLoop\r
234         jmp     @@Exit\r
235 \r
236 ; Decreasing step\r
237 @@YN:\r
238         neg     ax\r
239         cwd\r
240         div     cx\r
241         mov     bp, ax\r
242         xor     ax, ax\r
243         div     cx\r
244         xchg    ax, bx\r
245         mov     dx, 8000h\r
246 @@YNLoop:\r
247         mov     es:[di].IY1, ax\r
248         add     di, SIZE TSCAN\r
249         sub     dx, bx\r
250         sbb     ax, bp\r
251         dec     cx\r
252         jnz     @@YNLoop\r
253 \r
254 @@Exit:\r
255         .pop    bp\r
256         ret\r
257 subScanTexture  ENDP\r
258 \r
259 ;-----------------------------------------------------------\r
260 ;\r
261 ; Fills a scan column with texture.\r
262 ;\r
263 ; Input:\r
264 ;       DS:SI   = current TSCAN\r
265 ;       ES:DI   = address of top pixel\r
266 ;       CX      = number of pixels to write\r
267 ; Output:\r
268 ;       none\r
269 ; Notes:\r
270 ;       must preserve DS:SI, texture info in global variables.\r
271 ;\r
272 subFillScan     PROC NEAR\r
273         ASSUME  ds:NOTHING\r
274         .push   ds, si, bp, cx\r
275 \r
276         movzx   ecx, cx                 ; Clear high word of ECX\r
277 \r
278         movzx   eax, ds:[si].IX2\r
279         movzx   ebx, ds:[si].IX1\r
280         sub     ax, bx\r
281         jge     @@XP\r
282 \r
283 ;---------------------------------------\r
284 ; Delta X is negative\r
285 @@XN:\r
286         neg     ax                      ; Make AX positive\r
287         shl     eax, 8                  ; Convert 8:8 fixed to 16:16\r
288         cdq\r
289         idiv    ecx\r
290         ror     eax, 16\r
291         mov     ebp, eax                ; Save X step into EBP\r
292 \r
293         movzx   eax, ds:[si].IY2\r
294         movzx   esi, ds:[si].IY1\r
295         sub     ax, si\r
296         jge     @@XNYP\r
297 \r
298 ;-----------------------\r
299 ; DeltaX < 0, DeltaY < 0\r
300 @@XNYN:\r
301         neg     ax\r
302         shl     eax, 8\r
303         cdq\r
304         idiv    ecx\r
305         ror     eax, 16\r
306         mov     dx, [mx_TextureWidth]\r
307         mul     dl\r
308         xchg    eax, esi                ; ESI = Y step\r
309         ror     eax, 8\r
310         mul     dl\r
311         ror     ebx, 8\r
312         add     bx, ax                  ; BX = start offset in texture\r
313         lds     dx, [mx_Texture]\r
314         movzx   edx, dx\r
315         add     edx, ebx                ; EDX = X step lo:texture offset\r
316         xchg    edx, esi                ; EDX = Y step\r
317 @@XNYNLoop:\r
318         dec     cx\r
319         jl      @@XNYNDone\r
320         movzx   ax, ds:[si]\r
321         mov     es:[di], al\r
322         add     di, [mx_BytesPerLine]\r
323         sub     esi, ebp\r
324         sbb     si, 0\r
325         sub     si, dx\r
326         sub     eax, edx\r
327         jnc     @@XNYNLoop\r
328         sub     si, [mx_TextureWidth]\r
329         jmp     @@XNYNLoop\r
330 @@XNYNDone:\r
331         jmp     @@Exit\r
332 \r
333 ;-----------------------\r
334 ; DeltaX < 0, DeltaY > 0\r
335 @@XNYP:\r
336         shl     eax, 8\r
337         cdq\r
338         idiv    ecx\r
339         ror     eax, 16\r
340         mov     dx, [mx_TextureWidth]\r
341         mul     dl\r
342         xchg    eax, esi                ; ESI = Y step\r
343         ror     eax, 8\r
344         mul     dl\r
345         ror     ebx, 8\r
346         add     bx, ax                  ; BX = start offset in texture\r
347         lds     dx, [mx_Texture]\r
348         movzx   edx, dx\r
349         add     edx, ebx                ; EDX = X step lo:texture offset\r
350         xchg    edx, esi                ; EDX = Y step\r
351 @@XNYPLoop:\r
352         dec     cx\r
353         jl      @@XNYPDone\r
354         movzx   ax, ds:[si]\r
355         mov     es:[di], al\r
356         add     di, [mx_BytesPerLine]\r
357         sub     esi, ebp\r
358         sbb     si, 0\r
359         add     si, dx\r
360         add     eax, edx\r
361         jnc     @@XNYPLoop\r
362         add     si, [mx_TextureWidth]\r
363         jmp     @@XNYPLoop\r
364 @@XNYPDone:\r
365         jmp     @@Exit\r
366 \r
367 ;---------------------------------------\r
368 ; Delta X is positive\r
369 @@XP:\r
370         shl     eax, 8                  ; Convert 8:8 fixed to 16:16\r
371         cdq\r
372         idiv    ecx\r
373         ror     eax, 16\r
374         mov     ebp, eax                ; Save X step into EBP\r
375 \r
376         movzx   eax, ds:[si].IY2\r
377         movzx   esi, ds:[si].IY1\r
378         sub     ax, si\r
379         jge     @@XPYP\r
380 \r
381 ;-----------------------\r
382 ; DeltaX > 0, DeltaY < 0\r
383 @@XPYN:\r
384         neg     ax\r
385         shl     eax, 8\r
386         cdq\r
387         idiv    ecx\r
388         ror     eax, 16\r
389         mov     dx, [mx_TextureWidth]\r
390         mul     dl\r
391         xchg    eax, esi                ; ESI = Y step\r
392         ror     eax, 8\r
393         mul     dl\r
394         ror     ebx, 8\r
395         add     bx, ax                  ; BX = start offset in texture\r
396         lds     dx, [mx_Texture]\r
397         movzx   edx, dx\r
398         add     edx, ebx                ; EDX = X step lo:texture offset\r
399         xchg    edx, esi                ; EDX = Y step\r
400 @@XPYNLoop:\r
401         dec     cx\r
402         jl      @@XPYNDone\r
403         movzx   ax, ds:[si]\r
404         mov     es:[di], al\r
405         add     di, [mx_BytesPerLine]\r
406         add     esi, ebp\r
407         adc     si, 0\r
408         sub     si, dx\r
409         sub     eax, edx\r
410         jnc     @@XPYNLoop\r
411         sub     si, [mx_TextureWidth]\r
412         jmp     @@XPYNLoop\r
413 @@XPYNDone:\r
414         jmp     @@Exit\r
415 \r
416 ;-----------------------\r
417 ; DeltaX > 0, DeltaY > 0\r
418 @@XPYP:\r
419         shl     eax, 8\r
420         cdq\r
421         idiv    ecx\r
422         ror     eax, 16\r
423         mov     dx, [mx_TextureWidth]\r
424         mul     dl\r
425         xchg    eax, esi                ; ESI = Y step\r
426         ror     eax, 8\r
427         mul     dl\r
428         ror     ebx, 8\r
429         add     bx, ax                  ; BX = start offset in texture\r
430         lds     dx, [mx_Texture]\r
431         movzx   edx, dx\r
432         add     edx, ebx                ; EDX = X step lo:texture offset\r
433         xchg    edx, esi                ; EDX = Y step\r
434 @@XPYPLoop:\r
435         dec     cx\r
436         jl      @@XPYPDone\r
437         movzx   ax, ds:[si]\r
438         mov     es:[di], al\r
439         add     di, [mx_BytesPerLine]\r
440         add     esi, ebp\r
441         adc     si, 0\r
442         add     si, dx\r
443         add     eax, edx\r
444         jnc     @@XPYPLoop\r
445         add     si, [mx_TextureWidth]\r
446         jmp     @@XPYPLoop\r
447 @@XPYPDone:\r
448         jmp     @@Exit\r
449 \r
450 @@Exit:\r
451         .pop    ds, si, bp, cx\r
452         ASSUME  ds:NOTHING\r
453         ret\r
454 subFillScan     ENDP\r
455 \r
456 ;-----------------------------------------------------------\r
457 ;\r
458 ; Fills a convex polygon with the specified color.\r
459 ; Interpolates pixel colors using the Gouraud algorithm.\r
460 ;\r
461 ; Input:\r
462 ;       Count   = number of vertexes\r
463 ;       Map     = indexes of points and colors (integer)\r
464 ;       Points  = array of points (integer X, Y coordinates)\r
465 ;       TPoints = array of points inside texture (fixed 8:8 coordinates)\r
466 ;       Texture = pointer to texture image\r
467 ;       TWidth  = texture width in pixels\r
468 ; Output:\r
469 ;       none\r
470 ; Notes:\r
471 ;       vertexes must be in counterclockwise order, arrays are 0-based.\r
472 ;\r
473 mxTexturePoly   PROC FAR\r
474         ARG     TWidth:WORD,    \\r
475                 Texture:DWORD,  \\r
476                 TPoints:DWORD,  \\r
477                 Points:DWORD,   \\r
478                 Map:DWORD,      \\r
479                 Count:WORD      = ARG_SIZE\r
480         LOCAL   WritePlane:BYTE:2,      \\r
481                 ScanOffsetT:WORD,       \\r
482                 ScanOffsetB:WORD,       \\r
483                 ScanCount:WORD,         \\r
484                 Holder:WORD,            \\r
485                 Height:WORD,            \\r
486                 MinIdxT:WORD,           \\r
487                 MinIdxB:WORD,           \\r
488                 MaxIdx:WORD,            \\r
489                 Width:WORD,             \\r
490                 BoxX1:WORD,             \\r
491                 BoxY1:WORD,             \\r
492                 BoxX2:WORD,             \\r
493                 BoxY2::WORD             = AUTO_SIZE\r
494         .enter  AUTO_SIZE\r
495         .push   ds, si, es, di\r
496         ASSUME  ds:NOTHING\r
497 \r
498 IF USE386 EQ FALSE\r
499         jmp     @@Exit\r
500 ENDIF\r
501 \r
502 ; Check that at least three vertexes are specified\r
503         mov     cx, [Count]\r
504         cmp     cx, 3\r
505         jb      @@Exit\r
506 \r
507 ;------------------------------\r
508 ; Find bounding box for polygon\r
509         les     di, [Map]               ; Point to map table\r
510         lds     si, [Points]            ; Point to vertex array\r
511         mov     [BoxX1], 32767\r
512         mov     [BoxX2], -32768\r
513         mov     [BoxY1], 32767\r
514         mov     [BoxY2], -32768\r
515 \r
516         xor     dx, dx\r
517 @@MinMaxLoop:\r
518         mov     bx, es:[di]             ; Get index of vertex\r
519         .shl    bx, 2                   ; Get offset in point array\r
520         add     bx, si\r
521 \r
522 ; Check X range\r
523 @@CheckMinX:\r
524         mov     ax, ds:[bx].X           ; Get X coordinate\r
525         cmp     ax, [BoxX1]\r
526         jge     @@CheckMaxX\r
527         mov     [BoxX1], ax\r
528         mov     [MinIdxT], dx\r
529         mov     [MinIdxB], dx\r
530 @@CheckMaxX:\r
531         cmp     ax, [BoxX2]\r
532         jle     @@CheckMinY\r
533         mov     [BoxX2], ax\r
534         mov     [MaxIdx], dx\r
535 \r
536 ; Check Y range\r
537 @@CheckMinY:\r
538         mov     ax, ds:[bx].Y\r
539         cmp     ax, [BoxY1]\r
540         jge     @@CheckMaxY\r
541         mov     [BoxY1], ax\r
542 @@CheckMaxY:\r
543         cmp     ax, [BoxY2]\r
544         jle     @@CheckDone\r
545         mov     [BoxY2], ax\r
546 \r
547 ; Repeat thru all points\r
548 @@CheckDone:\r
549         add     di, 2                   ; Next map entry\r
550         add     dx, 2\r
551         dec     cx\r
552         jnz     @@MinMaxLoop\r
553 \r
554 ;---------------------------------\r
555 ; Check if polygon is full clipped\r
556         mov     ax, [BoxX2]\r
557         cmp     ax, [mx_ClipX1]         ; Is poly full clipped?\r
558         jl      @@Exit\r
559         mov     bx, [BoxX1]\r
560         cmp     bx, [mx_ClipX2]         ; Is poly full clipped?\r
561         jg      @@Exit\r
562         sub     ax, bx                  ; Get width\r
563         jle     @@Exit                  ; Exit if not positive\r
564         mov     ax, [BoxY2]\r
565         cmp     ax, [mx_ClipY1]         ; Is poly full clipped?\r
566         jl      @@Exit\r
567         mov     bx, [BoxY1]\r
568         cmp     bx, [mx_ClipY2]         ; Is poly full clipped?\r
569         jg      @@Exit\r
570         sub     ax, bx                  ; Get height\r
571         jle     @@Exit                  ; Exit if not positive\r
572 \r
573         dec     [Count]\r
574         shl     [Count], 1              ; We'll work with word offsets\r
575 \r
576 ;----------------------\r
577 ; Scan top polygon edge\r
578         mov     es, [mx_CodeSegment]\r
579         mov     di, OFFSET mx_ScanBuffer\r
580         mov     si, [MinIdxT]           ; Offset of top point index\r
581 @@STLoop:\r
582         mov     dx, si\r
583         lds     bx, [Map]               ; DS:BX -> map table\r
584         mov     ax, ds:[bx+si]          ; Index of top point #1\r
585         dec     si                      ; Next top point\r
586         dec     si\r
587         test    si, si\r
588         jns     @@ST1\r
589         mov     si, [Count]\r
590 @@ST1:\r
591         mov     [MinIdxT], si           ; Save new index of bottom point\r
592         mov     cx, si\r
593         mov     si, ds:[bx+si]          ; Get index of top point #2\r
594         .shl    ax, 2                   ; Convert indexes to offsets\r
595         .shl    si, 2\r
596         shl     cx, 1                   ; Save map points\r
597         shl     dx, 1\r
598         mov     dh, cl\r
599         mov     es:[di].IY1, dx\r
600         lds     bx, [Points]            ; Get pointer to vertexes\r
601         add     si, bx\r
602         add     bx, ax\r
603         call    subScan                 ; Scan poly top edge\r
604         mov     si, [MinIdxT]\r
605         cmp     si, [MaxIdx]            ; Reached last vertex?\r
606         jne     @@STLoop                ; No, continue\r
607         mov     es:[di].IX1, -1         ; Mark end of scan\r
608 \r
609 ;-------------------------\r
610 ; Scan bottom polygon edge\r
611         mov     di, OFFSET mx_ScanBuffer + OFFSET Y2\r
612         mov     si, [MinIdxB]\r
613 @@SBLoop:\r
614         mov     dx, si\r
615         lds     bx, [Map]               ; DS:BX -> map table\r
616         mov     ax, ds:[bx+si]          ; Index of bottom point #1\r
617         inc     si                      ; Next bottom point\r
618         inc     si\r
619         cmp     si, [Count]\r
620         jbe     @@SB1\r
621         xor     si, si\r
622 @@SB1:\r
623         mov     [MinIdxB], si           ; Save new index of bottom point\r
624         mov     cx, si\r
625         mov     si, ds:[bx+si]          ; Get index of bottom point #2\r
626         .shl    ax, 2                   ; Convert indexes to offsets\r
627         .shl    si, 2\r
628         shl     cx, 1                   ; Save map points\r
629         shl     dx, 1\r
630         mov     dh, cl\r
631         mov     es:[di].IY1, dx\r
632         lds     bx, [Points]            ; Get pointer to vertexes\r
633         add     si, bx\r
634         add     bx, ax\r
635         call    subScan                 ; Scan poly bottom edge\r
636         mov     si, [MinIdxB]\r
637         cmp     si, [MaxIdx]            ; Reached last vertex?\r
638         jne     @@SBLoop                ; No, continue\r
639         mov     es:[di].IX1, -1         ; Mark end of scan\r
640 \r
641 ;----------------------\r
642 ; Scan top texture edge\r
643         mov     di, OFFSET mx_ScanBuffer\r
644         mov     ds, WORD PTR [TPoints][2]\r
645 @@TTLoop:\r
646         mov     cx, es:[di].IX1\r
647         test    cx, cx\r
648         jle     @@TTDone\r
649         mov     ax, es:[di].IY1\r
650         mov     dl, ah\r
651         xor     ah, ah\r
652         xor     dh, dh\r
653         mov     si, dx\r
654         mov     bx, WORD PTR [TPoints][0]\r
655         add     si, bx\r
656         add     bx, ax\r
657         call    subScanTexture          ; Scan texture top edge\r
658         jmp     @@TTLoop\r
659 @@TTDone:\r
660 \r
661 ;-------------------------\r
662 ; Scan bottom texture edge\r
663         mov     di, OFFSET mx_ScanBuffer + OFFSET Y2\r
664 @@TBLoop:\r
665         mov     cx, es:[di].IX1\r
666         test    cx, cx\r
667         jle     @@TBDone\r
668         mov     ax, es:[di].IY1\r
669         mov     dl, ah\r
670         xor     ah, ah\r
671         xor     dh, dh\r
672         mov     si, dx\r
673         mov     bx, WORD PTR [TPoints][0]\r
674         add     si, bx\r
675         add     bx, ax\r
676         call    subScanTexture          ; Scan texture top edge\r
677         jmp     @@TBLoop\r
678 @@TBDone:\r
679 \r
680 ;--------------------\r
681 ; Clip left and right\r
682         mov     si, OFFSET mx_ScanBuffer\r
683         mov     ax, [BoxX1]\r
684         mov     cx, [BoxX2]\r
685         sub     cx, ax\r
686         mov     bx, [mx_ClipX1]         ; CX = bounding box width\r
687         sub     bx, ax\r
688         jle     @@ClipL1                ; No need to clip left\r
689         sub     cx, bx\r
690         add     ax, bx                  ; BoxX1 = mx_ClipX1\r
691         mov     [BoxX1], ax\r
692         .shl    bx, 2                   ; Warning!!! This is an hand-coded\r
693         add     si, bx                  ; multiply by the size of TSCAN\r
694         shl     bx, 1\r
695         add     si, bx\r
696 @@ClipL1:\r
697         mov     bx, ax\r
698         add     bx, cx                  ; Last scan column\r
699         sub     bx, [mx_ClipX2]\r
700         jle     @@ClipL2                ; No need to clip right\r
701         sub     cx, bx                  ; Clip right\r
702 @@ClipL2:\r
703         test    cx, cx                  ; Is clipped width positive?\r
704         jle     @@Exit                  ; No, exit\r
705         mov     [ScanCount], cx         ; Save number of columns to draw\r
706         mov     [ScanOffsetT], si       ; Remember offset of (clipped) buffer\r
707         mov     ds, [mx_CodeSegment]    ; DS:SI -> scan buffer\r
708 \r
709 ;------------------------------\r
710 ; Check if Y clipping is needed\r
711         mov     ax, [BoxY1]\r
712         cmp     ax, [mx_ClipY1]\r
713         jl      @@ClipTB                ; Need to clip top\r
714         mov     ax, [BoxY2]\r
715         cmp     ax, [mx_ClipY2]\r
716         jg      @@ClipTB                ; Need to clip bottom\r
717         jmp     @@ClipYExit             ; Skip Y clipping\r
718 \r
719 ;--------------------\r
720 ; Clip top and bottom\r
721 @@ClipTB:\r
722         mov     di, cx                  ; DI = scan count\r
723         inc     di                      ; Increment count for pre-loop test\r
724         sub     si, SIZE TSCAN\r
725 @@ClipYLoop:\r
726         dec     di                      ; Any column left?\r
727         jz      @@ClipYExit             ; No, exit\r
728         add     si, SIZE TSCAN\r
729         mov     ax, ds:[si].Y1          ; Y1\r
730         mov     cx, ds:[si].Y2          ; Y2\r
731         mov     dx, [mx_ClipY2]\r
732         cmp     ax, dx                  ; Full clipped?\r
733         jg      @@ClipYClip             ; Yes, skip this column\r
734         cmp     cx, dx                  ; Need to clip bottom?\r
735         jle     @@ClipY1                ; No, continue\r
736 ; Clip bottom, update texture too\r
737         mov     ds:[si].Y2, dx\r
738         mov     bx, cx\r
739         sub     bx, dx                  ; Number of pixels to clip\r
740         sub     cx, ax                  ; Height\r
741         jle     @@ClipYClip\r
742         mov     ax, ds:[si].IX1         ; Update texture\r
743         sub     ax, ds:[si].IX2\r
744         imul    bx\r
745         idiv    cx\r
746         add     ds:[si].IX2, ax\r
747         mov     ax, ds:[si].IY1\r
748         sub     ax, ds:[si].IY2\r
749         imul    bx\r
750         idiv    cx\r
751         add     ds:[si].IY2, ax\r
752         mov     ax, ds:[si].Y1          ; Reload coordinates\r
753         mov     cx, ds:[si].Y2          ;\r
754 @@ClipY1:\r
755         mov     dx, [mx_ClipY1]\r
756         cmp     cx, dx                  ; Full top clipped?\r
757         jl      @@ClipYClip             ; Yes, skip\r
758         sub     cx, ax                  ; Get height\r
759         jle     @@ClipYClip             ; Skip if not positive\r
760         cmp     ax, dx                  ; Need to clip top?\r
761         jge     @@ClipYLoop             ; No, continue\r
762 ; Clip top, update texture too\r
763         mov     ds:[si].Y1, dx          ; Y1 = mx_ClipY1\r
764         sub     dx, ax                  ; DX = number of pixels clipped\r
765         cmp     cx, dx\r
766         jbe     @@ClipYClip             ; Full clipped, skip\r
767         mov     bx, dx                  ; Save pixel count\r
768         mov     ax, ds:[si].IX2\r
769         sub     ax, ds:[si].IX1\r
770         imul    bx\r
771         idiv    cx\r
772         add     ds:[si].IX1, ax\r
773         mov     ax, ds:[si].IY2\r
774         sub     ax, ds:[si].IY1\r
775         imul    bx\r
776         idiv    cx\r
777         add     ds:[si].IY1, ax\r
778         jmp     @@ClipYLoop\r
779 @@ClipYClip:\r
780         mov     ds:[si].Y1, -1          ; Mark column as clipped\r
781         jmp     @@ClipYLoop\r
782 @@ClipYExit:\r
783 \r
784 ;-------------\r
785 ; Draw columns\r
786         mov     es, [mx_VideoSegment]\r
787         mov     ax, [TWidth]\r
788         mov     ds:[mx_TextureWidth], ax\r
789         mov     ax, WORD PTR [Texture][0]\r
790         mov     dx, WORD PTR [Texture][2]\r
791         mov     WORD PTR ds:[mx_Texture][0], ax\r
792         mov     WORD PTR ds:[mx_Texture][2], dx\r
793         mov     si, [ScanOffsetT]\r
794         mov     cl, BYTE PTR [BoxX1]    ; Init write plane\r
795         and     cl, 03h\r
796         mov     al, 11h\r
797         shl     al, cl\r
798         mov     [WritePlane], al\r
799         .shr    [BoxX1], 2\r
800 @@DrawLoop:\r
801         mov     ax, ds:[si].Y1\r
802         test    ax, ax                  ; Was column clipped?\r
803         js      @@DrawNext              ; Yes, skip\r
804         mov     cx, ds:[si].Y2\r
805         sub     cx, ax                  ; CX = height\r
806         jle     @@DrawNext\r
807         mul     [mx_BytesPerLine]       ; Get pixel address\r
808         add     ax, [BoxX1]\r
809         mov     di, ax\r
810         mov     ah, [WritePlane]\r
811         mov     al, 02h\r
812         mov     dx, TS\r
813         out     dx, ax\r
814         call    subFillScan\r
815 @@DrawNext:\r
816         rol     [WritePlane], 1\r
817         adc     [BoxX1], 0              ; Bump pointer to video memory if needed\r
818         add     si, SIZE TSCAN\r
819         dec     [ScanCount]\r
820         jnz     @@DrawLoop\r
821 \r
822 @@Exit:\r
823         xor     ax, ax\r
824         .pop    ds, si, es, di\r
825         .leave  ARG_SIZE\r
826 mxTexturePoly   ENDP\r
827 \r
828 MX_TEXT         ENDS\r
829 END\r