This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[btb/d2x.git] / texmap / tmap_per.asm
1 ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
2 ;SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
3 ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
4 ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
5 ;IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
6 ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
7 ;FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
8 ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
9 ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
10 ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
11 ;
12 ; $Source: /cvs/cvsroot/d2x/texmap/tmap_per.asm,v $
13 ; $Revision: 1.2 $
14 ; $Author: bradleyb $
15 ; $Date: 2001-10-18 23:59:23 $
16 ;
17 ; Perspective texture mapper inner loop.
18 ;
19 ; $Log: not supported by cvs2svn $
20 ; Revision 1.1.1.1  2001/01/19 03:30:16  bradleyb
21 ; Import of d2x-0.0.8
22 ;
23 ; Revision 1.1.1.1  1999/06/14 22:14:01  donut
24 ; Import of d1x 1.37 source.
25 ;
26 ; Revision 1.26  1995/02/20  18:22:55  john
27 ; Put all the externs in the assembly modules into tmap_inc.asm.
28 ; Also, moved all the C versions of the inner loops into a new module,
29 ; scanline.c.
30 ;
31 ; Revision 1.25  1995/02/20  17:09:08  john
32 ; Added code so that you can build the tmapper with no assembly!
33 ;
34 ; Revision 1.24  1995/01/10  09:32:07  mike
35 ; mostly fix garbage at end of scanline, but slow down by 1-4%.
36 ;
37 ; Revision 1.23  1994/12/02  23:29:57  mike
38 ; optimizations.
39 ;
40 ; Revision 1.22  1994/11/30  00:57:00  mike
41 ; optimization.
42 ;
43 ; Revision 1.21  1994/11/21  13:57:42  mike
44 ; fix right side shear bug
45 ;
46 ; Revision 1.20  1994/11/12  16:41:09  mike
47 ; jae -> ja.
48 ;
49 ; Revision 1.19  1994/10/27  19:40:00  john
50 ; Made lighting table lookup be _gr_fade_table[eax] instead
51 ; of fs:[eax], which gets rig of a segment override that
52 ; supposedly costs 1 clock on a 486.  Mainly, I wanted to verify
53 ; that the only reason we need selectors is for the source texture
54 ; data .
55 ;
56 ; Revision 1.18  1994/05/03  11:08:32  mike
57 ; Trap divide overflows.
58 ;
59 ; Revision 1.17  1994/04/21  15:03:41  mike
60 ; make faster.
61 ;
62 ; Revision 1.16  1994/04/08  16:46:57  john
63 ; Made 32 fade levels. Hacked.
64 ;
65 ; Revision 1.15  1994/03/31  08:35:18  mike
66 ; Fix quantized-by-4 bug in inner loop.
67 ;
68 ; Revision 1.14  1994/03/14  17:41:14  mike
69 ; Fix bug in unlighted version.
70 ;
71 ; Revision 1.13  1994/03/14  15:45:14  mike
72 ; streamline code.
73 ;
74 ; Revision 1.12  1994/01/14  14:01:58  mike
75 ; *** empty log message ***
76 ;
77 ; Revision 1.11  1993/12/18  14:43:44  john
78 ; Messed around with doing 1/z, the u*(1/z) and v*(1/z)
79 ; (Went from 23 fps to 21 fps... not good! )
80 ;
81 ; Revision 1.10  1993/12/17  16:14:17  john
82 ; Split lighted/nonlighted, so there is no cmp lighting
83 ; in the inner loop.
84 ;
85 ; Revision 1.9  1993/12/17  12:34:29  john
86 ; Made leftover bytes use linear approx instead of correct...
87 ; should save about 8 divides per scanline on average.
88 ; Also, took out anti-aliasing code and rearranged to
89 ; order of some instructions to help on 486 pipelining.
90 ; (The anti-aliasing code did *not* look good, so I
91 ; figure there was no reason to keep it in. )
92 ;
93 ; Revision 1.8  1993/12/16  18:37:52  mike
94 ; Align some stuff on 4 byte boundaries.
95 ;
96 ; Revision 1.7  1993/11/30  08:44:18  john
97 ; Made selector set check for < 64*64 bitmaps.
98 ;
99 ; Revision 1.6  1993/11/23  17:25:26  john
100 ; Added safety "and eax, 0fffh" in lighting lookup.
101 ;
102 ; Revision 1.5  1993/11/23  15:08:52  mike
103 ; Fixed lighting bug.
104 ;
105 ; Revision 1.4  1993/11/23  14:38:50  john
106 ; optimized NORMAL code by switching EBX and ESI, so BH can be used in
107 ; the lighting process.
108 ;
109 ; Revision 1.3  1993/11/23  14:30:53  john
110 ; Made the perspective tmapper do 1/8 divides; added lighting.
111 ;
112 ; Revision 1.2  1993/11/22  10:24:59  mike
113 ; *** empty log message ***
114 ;
115 ; Revision 1.1  1993/09/08  17:29:53  mike
116 ; Initial revision
117 ;
118 ;
119 ;
120
121 [BITS 32]
122
123 global  _asm_tmap_scanline_per
124 global  asm_tmap_scanline_per
125
126 %include        "tmap_inc.asm"
127
128 [SECTION .data]
129 align 4
130     ;extern _per2_flag;:dword
131 %ifdef __linux__
132 ; Cater for linux ELF compilers...
133 global x
134 %define _loop_count loop_count
135 %define _new_end new_end
136 %define _scan_doubling_flag scan_doubling_flag
137 %define _linear_if_far_flag linear_if_far_flag
138 %endif
139
140         global _x
141         global _loop_count
142         global _new_end
143         global _scan_doubling_flag
144         global _linear_if_far_flag
145
146 ;        global _max_ecx
147 ;        global _min_ecx
148
149     mem_edx dd 0
150     x:
151     _x          dd      0
152     _loop_count dd      0
153
154 ;    _max_ecx    dd      0
155 ;    _min_ecx    dd      55555555h
156     _new_end     dd      1       ; if set, use new, but slower, way of finishing off extra pixels on scanline, 01/10/95 --MK
157
158     _scan_doubling_flag dd 0
159     _linear_if_far_flag dd 0
160
161 ;---------- local variables
162 align 4
163     req_base    dd      0
164     req_size    dd      0
165     U0          dd      0
166     U1          dd      0
167     V0          dd      0
168     V1          dd      0
169     num_left_over   dd  0
170     DU1         dd      0
171     DV1         dd      0
172     DZ1         dd      0
173
174 [SECTION .text]
175
176 ; --------------------------------------------------------------------------------------------------
177 ; Enter:
178 ;       _xleft  fixed point left x coordinate
179 ;       _xright fixed point right x coordinate
180 ;       _y      fixed point y coordinate
181 ;       _pixptr address of source pixel map
182 ;       _u      fixed point initial u coordinate
183 ;       _v      fixed point initial v coordinate
184 ;       _z      fixed point initial z coordinate
185 ;       _du_dx  fixed point du/dx
186 ;       _dv_dx  fixed point dv/dx
187 ;       _dz_dx  fixed point dz/dx
188
189 ;   for (x = (int) xleft; x <= (int) xright; x++) {
190 ;      _setcolor(read_pixel_from_tmap(srcb,((int) (u/z)) & 63,((int) (v/z)) & 63));
191 ;      _setpixel(x,y);
192 ;
193 ;      u += du_dx;
194 ;      v += dv_dx;
195 ;      z += dz_dx;
196 ;   }
197
198
199 align   16
200 _asm_tmap_scanline_per:
201 asm_tmap_scanline_per:
202 ;        push    es
203         pusha
204
205 ;---------------------------- setup for loop ---------------------------------
206 ; Setup for loop:       _loop_count  iterations = (int) xright - (int) xleft
207 ;       esi     source pixel pointer = pixptr
208 ;       edi     initial row pointer = y*320+x
209 ; NOTE: fx_xright and fx_xleft changed from fix to int by mk on 12/01/94.
210
211 ; set esi = pointer to start of texture map data
212
213 ; set edi = address of first pixel to modify
214         mov     edi,[_fx_y]
215 ;        mov     es,[_pixel_data_selector]       ; selector[0*2]
216
217         mov     edi,[_y_pointers+edi*4]
218
219         mov     ebx,[_fx_xleft]
220         test    ebx, ebx
221         jns     ebx_ok
222         xor     ebx, ebx
223 ebx_ok: add     edi,[_write_buffer]
224         add     edi,ebx
225
226 ; set _loop_count = # of iterations
227         mov     eax,[_fx_xright]
228         sub     eax,ebx
229         js      near _none_to_do
230         mov     [_loop_count],eax
231
232 ; lighting values are passed in fixed point, but need to be in 8 bit integer, 8 bit fraction so we can easily
233 ; get the integer by reading %bh
234         sar     dword [_fx_l], 8
235         sar     dword [_fx_dl_dx],8
236         jns     dl_dx_ok
237         inc     dword [_fx_dl_dx]       ; round towards 0 for negative deltas
238 dl_dx_ok:
239
240 ; set initial values
241         mov     ebx,[_fx_u]
242         mov     ebp,[_fx_v]
243         mov     ecx,[_fx_z]
244
245         test    dword [_per2_flag],-1
246         je      tmap_loop
247
248         test    dword [_Lighting_on], -1
249         je     near _tmap_loop_fast_nolight
250         jmp     _tmap_loop_fast
251 ;tmap_loop_fast_nolight_jumper:
252 ;    jmp tmap_loop_fast_nolight
253
254 ;================ PERSPECTIVE TEXTURE MAP INNER LOOPS ========================
255 ;
256 ; Usage in loop:        eax     division, pixel value
257 ;       ebx     u
258 ;       ecx     z
259 ;       edx     division
260 ;       ebp     v
261 ;       esi     source pixel pointer
262 ;       edi     destination pixel pointer
263
264 ;-------------------- NORMAL PERSPECTIVE TEXTURE MAP LOOP -----------------
265 tmap_loop:
266         mov     esi, ebx        ; esi becomes u coordinate
267
268         align   4
269 tmap_loop0:
270
271 ; compute v coordinate
272         mov     eax, ebp        ; get v
273         mov     edx, eax
274         sar     edx, 31
275         idiv    ecx     ; eax = (v/z)
276
277         and     eax,3fh ; mask with height-1
278         mov     ebx,eax
279
280 ; compute u coordinate
281         mov     eax, esi        ; get u
282         mov     edx, eax
283         sar     edx, 31
284         idiv    ecx     ; eax = (u/z)
285
286         shl     eax,26
287         shld    ebx,eax,6       ; esi = v*64+u
288
289 ; read 1 pixel
290         add     ebx, [_pixptr]
291         xor     eax, eax
292         test    dword [_Lighting_on], -1
293         mov     al, [ebx]    ; get pixel from source bitmap
294         je      NoLight1
295
296 ; LIGHTING CODE
297         mov     ebx, [_fx_l]    ; get temp copy of lighting value
298         mov     ah, bh  ; get lighting level
299         add     ebx, [_fx_dl_dx]        ; update lighting value
300         mov     al, [_gr_fade_table+eax]        ; xlat pixel thru lighting tables
301         mov     [_fx_l], ebx    ; save temp copy of lighting value
302
303 ; transparency check
304 NoLight1:       cmp     al,255
305         je      skip1
306
307         mov     [edi],al
308 skip1:  inc     edi
309
310 ; update deltas
311         add     ebp,[_fx_dv_dx]
312         add     esi,[_fx_du_dx]
313         add     ecx,[_fx_dz_dx]
314         je      _div_0_abort    ; would be dividing by 0, so abort
315
316         dec     dword [_loop_count]
317         jns     tmap_loop0
318
319 _none_to_do:
320         popa
321 ;        pop     es
322         ret
323
324 ; We detected a z=0 condition, which seems pretty bogus, don't you think?
325 ; So, we abort, but maybe we want to know about it.
326 _div_0_abort:
327         jmp     _none_to_do
328
329 ;-------------------------- PER/4 TMAPPER ----------------
330 ;
331 ;       x = x1
332 ;       U0 = u/w; V0 = v/w;
333 ;       while ( 1 )
334 ;               u += du_dx*4; v+= dv_dx*4
335 ;               U1 = u/w; V1 = v/w;
336 ;               DUDX = (U1-U0)/4; DVDX = (V1-V0)/4;
337 ;
338 ;       ; Pixel 0
339 ;               pixels = texmap[V0*64+U0];
340 ;               U0 += DUDX; V0 += DVDX
341 ;       ; Pixel 1
342 ;               pixels = (pixels<<8)+texmap[V0*64+U0];
343 ;               U0 += DUDX; V0 += DVDX
344 ;       ; Pixel 2
345 ;               pixels = (pixels<<8)+texmap[V0*64+U0];
346 ;               U0 += DUDX; V0 += DVDX
347 ;       ; Pixel 3
348 ;               pixels = (pixels<<8)+texmap[V0*64+U0];
349 ;
350 ;               screen[x] = pixel
351 ;               x += 4;
352 ;               U0 = U1; V0 = V1
353
354 NBITS equ 4     ; 2^NBITS pixels plotted per divide
355 ZSHIFT equ 4    ; precision used in PDIV macro
356
357
358 ;PDIV MACRO
359 ; Returns EAX/ECX in 16.16 format in EAX. Trashes EDX
360 ;          sig bits   6.3
361 ;       mov     edx,eax
362 ;       shl     eax,ZSHIFT
363 ;       sar     edx,32-ZSHIFT
364 ;       idiv    ecx     ; eax = (v/z)
365 ;   shl eax, 16-ZSHIFT
366 ;ENDM
367
368 global _tmap_loop_fast
369
370 ; -------------------------------------- Start of Getting Dword Aligned ----------------------------------------------
371 ;       ebx     fx_u
372
373 _tmap_loop_fast:
374         mov     esi,ebx
375
376         align   4
377 NotDwordAligned1:
378         test    edi, 11b
379         jz      DwordAligned1
380
381 ; compute v coordinate
382         mov     eax, ebp        ; get v
383         mov     edx, eax
384         sar     edx, 31
385         idiv    ecx     ; eax = (v/z)
386
387         and     eax,3fh ; mask with height-1
388         mov     ebx,eax
389
390 ; compute u coordinate
391         mov     eax, esi        ; get u
392         mov     edx, eax
393         sar     edx, 31
394         idiv    ecx     ; eax = (u/z)
395
396         shl     eax,26
397         shld    ebx,eax,6       ; esi = v*64+u
398
399 ; read 1  pixel
400         add     ebx,[_pixptr]
401         xor     eax, eax
402         mov     al, [ebx]    ; get pixel from source bitmap
403
404 ; lighting code
405         mov     ebx, [_fx_l]    ; get temp copy of lighting value
406         mov     ah, bh  ; get lighting level
407         add     ebx, [_fx_dl_dx]        ; update lighting value
408         mov     [_fx_l], ebx    ; save temp copy of lighting value
409
410 ; transparency check
411         cmp     al,255
412         je      skip2   ; this pixel is transparent, so don't write it (or light it)
413
414         mov     al, [_gr_fade_table+eax]        ; xlat pixel thru lighting tables
415
416 ; write 1 pixel
417         mov     [edi],al
418 skip2:  inc     edi
419
420 ; update deltas
421         add     ebp,[_fx_dv_dx]
422         add     esi,[_fx_du_dx]
423         add     ecx,[_fx_dz_dx]
424         je      _div_0_abort    ; would be dividing by 0, so abort
425
426         dec     dword [_loop_count]
427         jns     NotDwordAligned1
428
429         jmp     _none_to_do
430
431 ; -------------------------------------- End of Getting Dword Aligned ----------------------------------------------
432
433 DwordAligned1:
434
435         mov     eax, [_loop_count]
436         mov     ebx, esi        ; get fx_u [pentium pipelining]
437         inc     eax
438         mov     esi, eax
439         and     esi, (1 << NBITS) - 1
440         sar     eax, NBITS
441         mov     [num_left_over], esi
442         je      near tmap_loop  ; there are no 2^NBITS chunks, do divide/pixel for whole scanline
443         mov     [_loop_count], eax      ; _loop_count = pixels / NPIXS
444
445 ; compute initial v coordinate
446         mov     eax,ebp ; get v
447         mov     edx,ebp
448         shl     eax,ZSHIFT
449         sar     edx,32-ZSHIFT
450         idiv    ecx     ; eax = (v/z)
451         shl     eax, 16-ZSHIFT
452         mov     [V0], eax
453
454 ; compute initial u coordinate
455         mov     eax,ebx ; get u
456         mov     edx,ebx
457         shl     eax,ZSHIFT
458         sar     edx,32-ZSHIFT
459         idiv    ecx     ; eax = (v/z)
460         shl     eax, 16-ZSHIFT
461         mov     [U0], eax
462
463 ; Set deltas to NPIXS pixel increments
464         mov     eax, [_fx_du_dx]
465         shl     eax, NBITS
466         mov     [DU1], eax
467         mov     eax, [_fx_dv_dx]
468         shl     eax, NBITS
469         mov     [DV1], eax
470         mov     eax, [_fx_dz_dx]
471         shl     eax, NBITS
472         mov     [DZ1], eax
473
474         align   4
475 TopOfLoop4:
476         add     ebx, [DU1]
477         add     ebp, [DV1]
478         add     ecx, [DZ1]
479         je      near _div_0_abort       ; would be dividing by 0, so abort
480
481 ; Done with ebx, ebp, ecx until next iteration
482         push    ebx
483         push    ecx
484         push    ebp
485         push    edi
486
487 ; Find fixed U1
488         mov     eax, ebx
489         mov     edx,ebx
490         shl     eax,ZSHIFT
491         sar     edx,32-ZSHIFT
492         idiv    ecx     ; eax = (v/z)
493         shl     eax, 16-ZSHIFT
494         mov     ebx, eax        ; ebx = U1 until pop's
495
496 ; Find fixed V1
497         mov     eax, ebp
498         mov     edx, ebp
499         shl     eax,ZSHIFT
500         sar     edx,32-ZSHIFT
501         idiv    ecx     ; eax = (v/z)
502
503         mov     ecx, [U0]       ; ecx = U0 until pop's
504         mov     edi, [V0]       ; edi = V0 until pop's
505
506         shl     eax, 16-ZSHIFT
507         mov     ebp, eax        ; ebp = V1 until pop's
508
509 ; Make ESI =  V0:U0 in 6:10,6:10 format
510         mov     eax, ecx
511         shr     eax, 6
512         mov     esi, edi
513         shl     esi, 10
514         mov     si, ax
515
516 ; Make EDX = DV:DU in 6:10,6:10 format
517         mov     eax, ebx
518         sub     eax, ecx
519         sar     eax, NBITS+6
520         mov     edx, ebp
521         sub     edx, edi
522         shl     edx, 10-NBITS   ; EDX = V1-V0/ 4 in 6:10 int:frac
523         mov     dx, ax  ; put delta u in low word
524
525 ; Save the U1 and V1 so we don't have to divide on the next iteration
526         mov     [U0], ebx
527         mov     [V0], ebp
528
529         pop     edi     ; Restore EDI before using it
530
531 ; LIGHTING CODE
532         mov     ebx, [_fx_l]
533         mov     ebp, [_fx_dl_dx]
534
535         test    dword [_Transparency_on],-1
536         je      near no_trans1
537
538 %macro repproc1 0
539         mov     eax, esi        ; get u,v
540         shr     eax, 26 ; shift out all but int(v)
541         shld    ax,si,6 ; shift in u, shifting up v
542         add     esi, edx        ; inc u,v
543         add     eax, [_pixptr]
544         movzx   eax, byte [eax]    ; get pixel from source bitmap
545         cmp     al,255
546         je      %%skipa1
547         mov     ah, bh  ; form lighting table lookup value
548         add     ebx, ebp        ; update lighting value
549         mov     al, [_gr_fade_table+eax]        ; xlat thru lighting table into dest buffer
550         mov     [edi],al
551 %%skipa1:
552         inc     edi
553
554 ; Do odd pixel
555         mov     eax, esi        ; get u,v
556         shr     eax, 26 ; shift out all but int(v)
557         shld    ax,si,6 ; shift in u, shifting up v
558         add     esi, edx        ; inc u,v
559         add     eax,[_pixptr]
560         movzx   eax, byte [eax]    ; get pixel from source bitmap
561         cmp     al,255
562         je      %%skipa2
563         mov     ah, bh  ; form lighting table lookup value
564         add     ebx, ebp        ; update lighting value
565         mov     al, [_gr_fade_table+eax]        ; xlat thru lighting table into dest buffer
566         mov     [edi],al
567 %%skipa2:
568         inc     edi
569 %endmacro
570
571
572 %rep (2 << (NBITS-2))
573 ;       local   skip3,no_trans1
574 ;       local   skipa1,skipa2
575     repproc1
576 %endrep
577
578 jmp     cont1
579
580 ; -------------------------------------------------------
581 no_trans1:
582
583 %macro repproc2 0
584         mov     eax, esi        ; get u,v
585         shr     eax, 26 ; shift out all but int(v)
586         shld    ax,si,6 ; shift in u, shifting up v
587         add     esi, edx        ; inc u,v
588         add     eax,[_pixptr]
589         movzx   eax, byte [eax]    ; get pixel from source bitmap
590         mov     ah, bh  ; form lighting table lookup value
591         add     ebx, ebp        ; update lighting value
592         mov     cl, [_gr_fade_table+eax]        ; xlat thru lighting table into dest buffer
593
594 ; Do odd pixel
595         mov     eax, esi        ; get u,v
596         shr     eax, 26 ; shift out all but int(v)
597         shld    ax,si,6 ; shift in u, shifting up v
598         add     esi, edx        ; inc u,v
599         add     eax,[_pixptr]
600         movzx   eax, byte [eax]    ; get pixel from source bitmap
601         mov     ah, bh  ; form lighting table lookup value
602         add     ebx, ebp        ; update lighting value
603         mov     ch, [_gr_fade_table+eax]        ; xlat thru lighting table into dest buffer
604
605 ; ----- This is about 1% faster than the above, and could probably be optimized more.
606 ; ----- Problem is, it gets the u,v coordinates backwards.  What you would need to do
607 ; ----- is switch the packing of the u,v coordinates above (about 95 lines up).
608 ;----------;    mov     eax, esi
609 ;----------;    shr     ax, 10
610 ;----------;    rol     eax, 6
611 ;----------;    mov     dx, ax
612 ;----------;    add     esi, mem_edx
613 ;----------;    mov     dl, es:[edx]
614 ;----------;    mov     dh, bh
615 ;----------;    add     ebx, ebp
616 ;----------;    mov     cl, _gr_fade_table[edx]
617 ;----------;
618 ;----------;    mov     eax, esi
619 ;----------;    shr     ax, 10
620 ;----------;    rol     eax, 6
621 ;----------;    mov     dx, ax
622 ;----------;    add     esi, mem_edx
623 ;----------;    mov     dl, es:[edx]
624 ;----------;    mov     dh, bh
625 ;----------;    add     ebx, ebp
626 ;----------;    mov     ch, _gr_fade_table[edx]
627
628         ror     ecx, 16 ; move to next double dest pixel position
629 %endmacro
630
631 %rep (1 << (NBITS-2))
632
633     repproc2
634     repproc2
635
636         mov     [edi],ecx       ; Draw 4 pixels to display
637         add     edi,4
638 %endrep
639 ;; pop edx
640 cont1:
641
642 ; -------------------------------------------------------
643
644 ; LIGHTING CODE
645         mov     [_fx_l], ebx
646         pop     ebp
647         pop     ecx
648         pop     ebx
649         dec     dword [_loop_count]
650         jnz     near TopOfLoop4
651
652 EndOfLoop4:
653         test    dword [num_left_over], -1
654         je      near _none_to_do
655
656 ; ----------------------------------------- Start of LeftOver Pixels ------------------------------------------
657 DoEndPixels:
658         push    ecx
659
660         mov     eax, ecx
661         lea     eax, [eax*2+eax]
662
663         add     ecx, [DZ1]
664         js      notokhere
665         shl     ecx,2
666         cmp     eax, ecx
667         pop     ecx
668         jl      okhere
669         jmp     bah_bah
670 notokhere:
671         pop     ecx
672 bah_bah:
673         test    dword [_new_end],-1
674         jne     near NewDoEndPixels
675 okhere:
676
677         add     ebx, [DU1]
678         add     ebp, [DV1]
679         add     ecx, [DZ1]
680         je      near _div_0_abort
681         jns     dep_cont
682
683 ; z went negative.
684 ; this can happen because we added DZ1 to the current z, but dz1 represents dz for perhaps 16 pixels
685 ; though we might only plot one more pixel.
686         mov     cl, 1
687
688 dep_loop:       mov     eax, [DU1]
689         sar     eax, cl
690         sub     ebx, eax
691
692         mov     eax, [DV1]
693         sar     eax, cl
694         sub     ebp, eax
695
696         mov     eax, [DZ1]
697         sar     eax, cl
698         sub     ecx, eax
699         je      near _div_0_abort
700         jns     dep_cont
701
702         inc     cl
703         cmp     cl, NBITS
704         jne     dep_loop
705
706 dep_cont:
707         push    edi     ; use edi as a temporary variable
708
709         cmp     ecx,1 << (ZSHIFT+1)
710         jg      ecx_ok
711         mov     ecx, 1 << (ZSHIFT+1)
712 ecx_ok:
713
714 ; Find fixed U1
715         mov     eax, ebx
716         ;PDIV
717         mov     edx,eax
718         shl     eax,ZSHIFT
719         sar     edx,32-ZSHIFT
720         idiv    ecx     ; eax = (v/z)
721         shl     eax, 16-ZSHIFT
722
723         mov     ebx, eax        ; ebx = U1 until pop's
724
725 ; Find fixed V1
726         mov     eax, ebp
727         ;PDIV
728         mov     edx,eax
729         shl     eax,ZSHIFT
730         sar     edx,32-ZSHIFT
731         idiv    ecx     ; eax = (v/z)
732         shl     eax, 16-ZSHIFT
733
734         mov     ebp, eax        ; ebp = V1 until pop's
735
736         mov     ecx, [U0]       ; ecx = U0 until pop's
737         mov     edi, [V0]       ; edi = V0 until pop's
738
739 ; Make ESI =  V0:U0 in 6:10,6:10 format
740         mov     eax, ecx
741         shr     eax, 6
742         mov     esi, edi
743         shl     esi, 10
744         mov     si, ax
745
746 ; Make EDX = DV:DU in 6:10,6:10 format
747         mov     eax, ebx
748         sub     eax, ecx
749         sar     eax, NBITS+6
750         mov     edx, ebp
751         sub     edx, edi
752         shl     edx, 10-NBITS   ; EDX = V1-V0/ 4 in 6:10 int:frac
753         mov     dx, ax  ; put delta u in low word
754
755         pop     edi     ; Restore EDI before using it
756
757         mov     ecx, [num_left_over]
758
759 ; LIGHTING CODE
760         mov     ebx, [_fx_l]
761         mov     ebp, [_fx_dl_dx]
762
763     ITERATION equ 0
764
765 %macro repproc3 0
766 ; Do even pixel
767         mov     eax, esi        ; get u,v
768         shr     eax, 26 ; shift out all but int(v)
769         shld    ax,si,6 ; shift in u, shifting up v
770         add     eax,[_pixptr]
771         movzx   eax, byte [eax]    ; get pixel from source bitmap
772         add     esi, edx        ; inc u,v
773         mov     ah, bh  ; form lighting table lookup value
774         add     ebx, ebp        ; update lighting value
775         cmp     al,255
776         je      %%skip4
777         mov     al, [_gr_fade_table+eax]        ; xlat thru lighting table into dest buffer
778         mov     [edi+ITERATION], al     ; write pixel
779 %%skip4:        dec     ecx
780         jz      near _none_to_do
781
782 ; Do odd pixel
783         mov     eax, esi        ; get u,v
784         shr     eax, 26 ; shift out all but int(v)
785         shld    ax,si,6 ; shift in u, shifting up v
786         add     eax,[_pixptr]
787         movzx   eax, byte [eax]    ; get pixel from source bitmap
788         add     esi, edx        ; inc u,v
789         mov     ah, bh  ; form lighting table lookup value
790         add     ebx, [_fx_dl_dx]        ; update lighting value
791         cmp     al,255
792         je      %%skip5
793         mov     al, [_gr_fade_table+eax]        ; xlat thru lighting table into dest buffer
794         mov     [edi+ITERATION+1], al   ; write pixel
795 %%skip5:        dec     ecx
796         jz      near _none_to_do
797 %endmacro
798
799 %rep (1 << (NBITS-1))
800         ;local  skip4, skip5
801     repproc3
802 %assign ITERATION  ITERATION + 2
803
804 %endrep
805
806 ; Should never get here!!!!
807         int     3
808         jmp     _none_to_do
809
810 ; ----------------------------------------- End of LeftOver Pixels ------------------------------------------
811
812 ; --BUGGY NEW--NewDoEndPixels:
813 ; --BUGGY NEW-- mov     eax, num_left_over
814 ; --BUGGY NEW-- and     num_left_over, 3
815 ; --BUGGY NEW-- shr     eax, 2
816 ; --BUGGY NEW-- je      NDEP_1
817 ; --BUGGY NEW-- mov     _loop_count, eax
818 ; --BUGGY NEW--
819 ; --BUGGY NEW--; do 4 pixels per hunk, not 16, so div deltas by 4 (16/4=4)
820 ; --BUGGY NEW-- shr DU1,2
821 ; --BUGGY NEW-- shr DV1,2
822 ; --BUGGY NEW-- shr DZ1,2
823 ; --BUGGY NEW--
824 ; --BUGGY NEW--NDEP_TopOfLoop4:
825 ; --BUGGY NEW-- add     ebx, DU1
826 ; --BUGGY NEW-- add     ebp, DV1
827 ; --BUGGY NEW-- add     ecx, DZ1
828 ; --BUGGY NEW-- je      _div_0_abort    ; would be dividing by 0, so abort
829 ; --BUGGY NEW--
830 ; --BUGGY NEW--; Done with ebx, ebp, ecx until next iteration
831 ; --BUGGY NEW-- push    ebx
832 ; --BUGGY NEW-- push    ecx
833 ; --BUGGY NEW-- push    ebp
834 ; --BUGGY NEW-- push    edi
835 ; --BUGGY NEW--
836 ; --BUGGY NEW--; Find fixed U1
837 ; --BUGGY NEW-- mov     eax, ebx
838 ; --BUGGY NEW-- mov     edx,ebx
839 ; --BUGGY NEW-- shl     eax,(ZSHIFT-2)
840 ; --BUGGY NEW-- sar     edx,32-(ZSHIFT-2)
841 ; --BUGGY NEW-- idiv    ecx     ; eax = (v/z)
842 ; --BUGGY NEW-- shl     eax, 16-(ZSHIFT-2)
843 ; --BUGGY NEW-- mov     ebx, eax        ; ebx = U1 until pop's
844 ; --BUGGY NEW--
845 ; --BUGGY NEW--; Find fixed V1
846 ; --BUGGY NEW-- mov     eax, ebp
847 ; --BUGGY NEW-- mov     edx, ebp
848 ; --BUGGY NEW-- shl     eax,(ZSHIFT-2)
849 ; --BUGGY NEW-- sar     edx,32-(ZSHIFT-2)
850 ; --BUGGY NEW-- idiv    ecx     ; eax = (v/z)
851 ; --BUGGY NEW--
852 ; --BUGGY NEW-- mov     ecx, U0 ; ecx = U0 until pop's
853 ; --BUGGY NEW-- mov     edi, V0 ; edi = V0 until pop's
854 ; --BUGGY NEW--
855 ; --BUGGY NEW-- shl     eax, 16-(ZSHIFT-2)
856 ; --BUGGY NEW-- mov     ebp, eax        ; ebp = V1 until pop's
857 ; --BUGGY NEW--
858 ; --BUGGY NEW--; Make ESI =  V0:U0 in 6:10,6:10 format
859 ; --BUGGY NEW-- mov     eax, ecx
860 ; --BUGGY NEW-- shr     eax, 6
861 ; --BUGGY NEW-- mov     esi, edi
862 ; --BUGGY NEW-- shl     esi, 10
863 ; --BUGGY NEW-- mov     si, ax
864 ; --BUGGY NEW--
865 ; --BUGGY NEW--; Make EDX = DV:DU in 6:10,6:10 format
866 ; --BUGGY NEW-- mov     eax, ebx
867 ; --BUGGY NEW-- sub     eax, ecx
868 ; --BUGGY NEW-- sar     eax, (NBITS-2)+6
869 ; --BUGGY NEW-- mov     edx, ebp
870 ; --BUGGY NEW-- sub     edx, edi
871 ; --BUGGY NEW-- shl     edx, 10-(NBITS-2)       ; EDX = V1-V0/ 4 in 6:10 int:frac
872 ; --BUGGY NEW-- mov     dx, ax  ; put delta u in low word
873 ; --BUGGY NEW--
874 ; --BUGGY NEW--; Save the U1 and V1 so we don't have to divide on the next iteration
875 ; --BUGGY NEW-- mov     U0, ebx
876 ; --BUGGY NEW-- mov     V0, ebp
877 ; --BUGGY NEW--
878 ; --BUGGY NEW-- pop     edi     ; Restore EDI before using it
879 ; --BUGGY NEW--
880 ; --BUGGY NEW--; LIGHTING CODE
881 ; --BUGGY NEW-- mov     ebx, _fx_l
882 ; --BUGGY NEW-- mov     ebp, _fx_dl_dx
883 ; --BUGGY NEW--
884 ; --BUGGY NEW--;**      test    _Transparency_on,-1
885 ; --BUGGY NEW--;**      je      NDEP_no_trans1
886 ; --BUGGY NEW--
887 ; --BUGGY NEW--        REPT 2
888 ; --BUGGY NEW-- local   NDEP_skipa1, NDEP_skipa2
889 ; --BUGGY NEW--
890 ; --BUGGY NEW-- mov     eax, esi        ; get u,v
891 ; --BUGGY NEW-- shr     eax, 26 ; shift out all but int(v)
892 ; --BUGGY NEW-- shld    ax,si,6 ; shift in u, shifting up v
893 ; --BUGGY NEW-- add     esi, edx        ; inc u,v
894 ; --BUGGY NEW-- mov     al, es:[eax]    ; get pixel from source bitmap
895 ; --BUGGY NEW-- cmp     al,255
896 ; --BUGGY NEW-- je      NDEP_skipa1
897 ; --BUGGY NEW-- mov     ah, bh  ; form lighting table lookup value
898 ; --BUGGY NEW-- add     ebx, ebp        ; update lighting value
899 ; --BUGGY NEW-- mov     al, _gr_fade_table[eax] ; xlat thru lighting table into dest buffer
900 ; --BUGGY NEW-- mov     [edi],al
901 ; --BUGGY NEW--NDEP_skipa1:
902 ; --BUGGY NEW-- inc     edi
903 ; --BUGGY NEW--
904 ; --BUGGY NEW--; Do odd pixel
905 ; --BUGGY NEW-- mov     eax, esi        ; get u,v
906 ; --BUGGY NEW-- shr     eax, 26 ; shift out all but int(v)
907 ; --BUGGY NEW-- shld    ax,si,6 ; shift in u, shifting up v
908 ; --BUGGY NEW-- add     esi, edx        ; inc u,v
909 ; --BUGGY NEW-- mov     al, es:[eax]    ; get pixel from source bitmap
910 ; --BUGGY NEW-- cmp     al,255
911 ; --BUGGY NEW-- je      NDEP_skipa2
912 ; --BUGGY NEW-- mov     ah, bh  ; form lighting table lookup value
913 ; --BUGGY NEW-- add     ebx, ebp        ; update lighting value
914 ; --BUGGY NEW-- mov     al, _gr_fade_table[eax] ; xlat thru lighting table into dest buffer
915 ; --BUGGY NEW-- mov     [edi],al
916 ; --BUGGY NEW--NDEP_skipa2:
917 ; --BUGGY NEW-- inc     edi
918 ; --BUGGY NEW--
919 ; --BUGGY NEW--        ENDM
920 ; --BUGGY NEW--
921 ; --BUGGY NEW-- mov     _fx_l, ebx
922 ; --BUGGY NEW-- pop     ebp
923 ; --BUGGY NEW-- pop     ecx
924 ; --BUGGY NEW-- pop     ebx
925 ; --BUGGY NEW-- dec     _loop_count
926 ; --BUGGY NEW-- jnz     NDEP_TopOfLoop4
927 ; --BUGGY NEW--
928 ; --BUGGY NEW-- test    num_left_over, -1
929 ; --BUGGY NEW-- je      _none_to_do
930 ; --BUGGY NEW--
931 ; --BUGGY NEW--NDEP_1:
932 ; --BUGGY NEW-- mov     esi,ebx
933 ; --BUGGY NEW--
934 ; --BUGGY NEW-- align   4
935 ; --BUGGY NEW--NDEP_loop:
936 ; --BUGGY NEW--
937 ; --BUGGY NEW--; compute v coordinate
938 ; --BUGGY NEW-- mov     eax, ebp        ; get v
939 ; --BUGGY NEW-- mov     edx, eax
940 ; --BUGGY NEW-- sar     edx, 31
941 ; --BUGGY NEW-- idiv    ecx     ; eax = (v/z)
942 ; --BUGGY NEW--
943 ; --BUGGY NEW-- and     eax,3fh ; mask with height-1
944 ; --BUGGY NEW-- mov     ebx,eax
945 ; --BUGGY NEW--
946 ; --BUGGY NEW--; compute u coordinate
947 ; --BUGGY NEW-- mov     eax,    esi     ; get u
948 ; --BUGGY NEW-- mov     edx, eax
949 ; --BUGGY NEW-- sar     edx, 31
950 ; --BUGGY NEW-- idiv    ecx     ; eax = (u/z)
951 ; --BUGGY NEW--
952 ; --BUGGY NEW-- shl     eax,26
953 ; --BUGGY NEW-- shld    ebx,eax,6       ; esi = v*64+u
954 ; --BUGGY NEW--
955 ; --BUGGY NEW--; read 1  pixel
956 ; --BUGGY NEW-- xor     eax, eax
957 ; --BUGGY NEW-- mov     al, es:[ebx]    ; get pixel from source bitmap
958 ; --BUGGY NEW--
959 ; --BUGGY NEW--; lighting code
960 ; --BUGGY NEW-- mov     ebx, _fx_l      ; get temp copy of lighting value
961 ; --BUGGY NEW-- mov     ah, bh  ; get lighting level
962 ; --BUGGY NEW-- add     ebx, _fx_dl_dx  ; update lighting value
963 ; --BUGGY NEW-- mov     _fx_l, ebx      ; save temp copy of lighting value
964 ; --BUGGY NEW--
965 ; --BUGGY NEW--; transparency check
966 ; --BUGGY NEW-- cmp     al,255
967 ; --BUGGY NEW-- je      NDEP_skip2      ; this pixel is transparent, so don't write it (or light it)
968 ; --BUGGY NEW--
969 ; --BUGGY NEW-- mov     al, _gr_fade_table[eax] ; xlat pixel thru lighting tables
970 ; --BUGGY NEW--
971 ; --BUGGY NEW--; write 1 pixel
972 ; --BUGGY NEW-- mov     [edi],al
973 ; --BUGGY NEW--NDEP_skip2:      inc     edi
974 ; --BUGGY NEW--
975 ; --BUGGY NEW--; update deltas
976 ; --BUGGY NEW-- add     ebp,_fx_dv_dx
977 ; --BUGGY NEW-- add     esi,_fx_du_dx
978 ; --BUGGY NEW-- add     ecx,_fx_dz_dx
979 ; --BUGGY NEW-- je      _div_0_abort    ; would be dividing by 0, so abort
980 ; --BUGGY NEW--
981 ; --BUGGY NEW-- dec     num_left_over
982 ; --BUGGY NEW-- jne     NDEP_loop
983 ; --BUGGY NEW--
984 ; --BUGGY NEW-- jmp     _none_to_do
985
986 NewDoEndPixels:
987         mov     esi,ebx
988
989         align   4
990 NDEP_loop:
991
992 ; compute v coordinate
993         mov     eax, ebp        ; get v
994         mov     edx, eax
995         sar     edx, 31
996         idiv    ecx     ; eax = (v/z)
997
998         and     eax,3fh ; mask with height-1
999         mov     ebx,eax
1000
1001 ; compute u coordinate
1002         mov     eax,    esi     ; get u
1003         mov     edx, eax
1004         sar     edx, 31
1005         idiv    ecx     ; eax = (u/z)
1006
1007         shl     eax,26
1008         shld    ebx,eax,6       ; esi = v*64+u
1009
1010 ; read 1  pixel
1011         add     ebx,[_pixptr]
1012         xor     eax, eax
1013         mov     al, [ebx]    ; get pixel from source bitmap
1014
1015 ; lighting code
1016         mov     ebx, [_fx_l]    ; get temp copy of lighting value
1017         mov     ah, bh  ; get lighting level
1018         add     ebx, [_fx_dl_dx]        ; update lighting value
1019         mov     [_fx_l], ebx    ; save temp copy of lighting value
1020
1021 ; transparency check
1022         cmp     al,255
1023         je      NDEP_skip2      ; this pixel is transparent, so don't write it (or light it)
1024
1025         mov     al, [_gr_fade_table+eax]        ; xlat pixel thru lighting tables
1026
1027 ; write 1 pixel
1028         mov     [edi],al
1029 NDEP_skip2:     inc     edi
1030
1031 ; update deltas
1032         add     ebp,[_fx_dv_dx]
1033         add     esi,[_fx_du_dx]
1034         add     ecx,[_fx_dz_dx]
1035         je      near _div_0_abort    ; would be dividing by 0, so abort
1036
1037         dec     dword [num_left_over]
1038         jne     NDEP_loop
1039
1040         jmp     _none_to_do
1041
1042 ; ==================================================== No Lighting Code ======================================================
1043 global _tmap_loop_fast_nolight
1044 _tmap_loop_fast_nolight:
1045         mov     esi,ebx
1046
1047         align   4
1048 NotDwordAligned1_nolight:
1049         test    edi, 11b
1050         jz      DwordAligned1_nolight
1051
1052 ; compute v coordinate
1053         mov     eax,ebp ; get v
1054         mov     edx, eax
1055         sar     edx, 31
1056         idiv    ecx     ; eax = (v/z)
1057
1058         and     eax,3fh ; mask with height-1
1059         mov     ebx,eax
1060
1061 ; compute u coordinate
1062         mov     eax, esi        ; get u
1063         mov     edx, eax
1064         sar     edx, 31
1065         idiv    ecx     ; eax = (u/z)
1066
1067         shl     eax,26
1068         shld    ebx,eax,6       ; esi = v*64+u
1069
1070 ; read 1  pixel
1071         add     ebx,[_pixptr]
1072         mov     al,[ebx]     ; get pixel from source bitmap
1073
1074 ; write 1 pixel
1075         cmp     al,255
1076         je      skip6
1077         mov     [edi],al
1078 skip6:  inc     edi
1079
1080 ; update deltas
1081         add     ebp,[_fx_dv_dx]
1082         add     esi,[_fx_du_dx]
1083         add     ecx,[_fx_dz_dx]
1084         je      near _div_0_abort    ; would be dividing by 0, so abort
1085
1086         dec     dword [_loop_count]
1087         jns     NotDwordAligned1_nolight
1088         jmp     _none_to_do
1089
1090 DwordAligned1_nolight:
1091         mov     ebx,esi
1092
1093         mov     eax, [_loop_count]
1094         inc     eax
1095         mov     [num_left_over], eax
1096         shr     eax, NBITS
1097
1098         test    eax, -1
1099         je      near tmap_loop       ; no 2^NBITS chunks, do divide/pixel for whole scanline
1100
1101         mov     [_loop_count], eax      ; _loop_count = pixels / NPIXS
1102         shl     eax, NBITS
1103         sub     [num_left_over], eax    ; num_left_over = obvious
1104
1105 ; compute initial v coordinate
1106         mov     eax,ebp ; get v
1107         ;PDIV
1108         mov     edx,eax
1109         shl     eax,ZSHIFT
1110         sar     edx,32-ZSHIFT
1111         idiv    ecx     ; eax = (v/z)
1112         shl     eax, 16-ZSHIFT
1113
1114         mov     [V0], eax
1115
1116 ; compute initial u coordinate
1117         mov     eax,ebx ; get u
1118         ;PDIV
1119         mov     edx,eax
1120         shl     eax,ZSHIFT
1121         sar     edx,32-ZSHIFT
1122         idiv    ecx     ; eax = (v/z)
1123         shl     eax, 16-ZSHIFT
1124
1125         mov     [U0], eax
1126
1127 ; Set deltas to NPIXS pixel increments
1128         mov     eax, [_fx_du_dx]
1129         shl     eax, NBITS
1130         mov     [DU1], eax
1131         mov     eax, [_fx_dv_dx]
1132         shl     eax, NBITS
1133         mov     [DV1], eax
1134         mov     eax, [_fx_dz_dx]
1135         shl     eax, NBITS
1136         mov     [DZ1], eax
1137
1138         align   4
1139 TopOfLoop4_nolight:
1140         add     ebx, [DU1]
1141         add     ebp, [DV1]
1142         add     ecx, [DZ1]
1143         je      near _div_0_abort
1144
1145 ; Done with ebx, ebp, ecx until next iteration
1146         push    ebx
1147         push    ecx
1148         push    ebp
1149         push    edi
1150
1151 ; Find fixed U1
1152         mov     eax, ebx
1153         ;PDIV
1154         mov     edx,eax
1155         shl     eax,ZSHIFT
1156         sar     edx,32-ZSHIFT
1157         idiv    ecx     ; eax = (v/z)
1158         shl     eax, 16-ZSHIFT
1159
1160         mov     ebx, eax        ; ebx = U1 until pop's
1161
1162 ; Find fixed V1
1163         mov     eax, ebp
1164         ;PDIV
1165         mov     edx,eax
1166         shl     eax,ZSHIFT
1167         sar     edx,32-ZSHIFT
1168         idiv    ecx     ; eax = (v/z)
1169         shl     eax, 16-ZSHIFT
1170
1171         mov     ebp, eax        ; ebp = V1 until pop's
1172
1173         mov     ecx, [U0]       ; ecx = U0 until pop's
1174         mov     edi, [V0]       ; edi = V0 until pop's
1175
1176 ; Make ESI =  V0:U0 in 6:10,6:10 format
1177         mov     eax, ecx
1178         shr     eax, 6
1179         mov     esi, edi
1180         shl     esi, 10
1181         mov     si, ax
1182
1183 ; Make EDX = DV:DU in 6:10,6:10 format
1184         mov     eax, ebx
1185         sub     eax, ecx
1186         sar     eax, NBITS+6
1187         mov     edx, ebp
1188         sub     edx, edi
1189         shl     edx, 10-NBITS   ; EDX = V1-V0/ 4 in 6:10 int:frac
1190         mov     dx, ax  ; put delta u in low word
1191
1192 ; Save the U1 and V1 so we don't have to divide on the next iteration
1193         mov     [U0], ebx
1194         mov     [V0], ebp
1195
1196         pop     edi     ; Restore EDI before using it
1197
1198 %macro repproc4 0
1199 ; Do 1 pixel
1200         mov     eax, esi        ; get u,v
1201         shr     eax, 26 ; shift out all but int(v)
1202         shld    ax,si,6 ; shift in u, shifting up v
1203         add     esi, edx        ; inc u,v
1204         add     eax,[_pixptr]
1205         mov     cl, [eax]    ; load into buffer register
1206
1207         mov     eax, esi        ; get u,v
1208         shr     eax, 26 ; shift out all but int(v)
1209         shld    ax,si,6 ; shift in u, shifting up v
1210         add     eax,[_pixptr]
1211         mov     ch, [eax]    ; load into buffer register
1212         add     esi, edx        ; inc u,v
1213         ror     ecx, 16 ; move to next dest pixel
1214
1215         mov     eax, esi        ; get u,v
1216         shr     eax, 26 ; shift out all but int(v)
1217         shld    ax,si,6 ; shift in u, shifting up v
1218         add     eax,[_pixptr]
1219         mov     cl, [eax]    ; load into buffer register
1220         add     esi, edx        ; inc u,v
1221
1222         mov     eax, esi        ; get u,v
1223         shr     eax, 26 ; shift out all but int(v)
1224         shld    ax,si,6 ; shift in u, shifting up v
1225         add     eax,[_pixptr]
1226         mov     ch, [eax]    ; load into buffer register
1227         add     esi, edx        ; inc u,v
1228         ror     ecx, 16 ;-- can get rid of this, just write in different order below --         ; move to next dest pixel
1229
1230         test    dword [_Transparency_on],-1
1231         je      %%no_trans2
1232         cmp     ecx,-1
1233         je      %%skip7
1234
1235         cmp     cl,255
1236         je      %%skip1q
1237         mov     [edi],cl
1238 %%skip1q:
1239
1240         cmp     ch,255
1241         je      %%skip2q
1242         mov     [edi+1],ch
1243 %%skip2q:
1244         ror     ecx,16
1245
1246         cmp     cl,255
1247         je      %%skip3q
1248         mov     [edi+2],cl
1249 %%skip3q:
1250
1251
1252         cmp     ch,255
1253         je      %%skip4q
1254         mov     [edi+3],ch
1255 %%skip4q:
1256
1257         jmp     %%skip7
1258 %%no_trans2:
1259         mov     [edi],ecx       ; Draw 4 pixels to display
1260 %%skip7:        add     edi,4
1261 %endmacro
1262
1263 %rep (1 << (NBITS-2))
1264         ;local  skip7, no_trans2, skip1q, skip2q, skip3q, skip4q
1265     repproc4
1266
1267 %endrep
1268
1269         pop     ebp
1270         pop     ecx
1271         pop     ebx
1272         dec     dword [_loop_count]
1273         jnz     near TopOfLoop4_nolight
1274
1275 EndOfLoop4_nolight:
1276
1277         test    dword [num_left_over], -1
1278         je      near _none_to_do
1279
1280 DoEndPixels_nolight:
1281         add     ebx, [DU1]
1282         add     ebp, [DV1]
1283         add     ecx, [DZ1]
1284         je      near _div_0_abort
1285         push    edi     ; use edi as a temporary variable
1286
1287 ; Find fixed U1
1288         mov     eax, ebx
1289         mov     edx,eax
1290         shl     eax,ZSHIFT
1291         sar     edx,32-ZSHIFT
1292         idiv    ecx     ; eax = (v/z)
1293         shl     eax, 16-ZSHIFT
1294         mov     ebx, eax        ; ebx = U1 until pop's
1295
1296 ; Find fixed V1
1297         mov     eax, ebp
1298         mov     edx,eax
1299         shl     eax,ZSHIFT
1300         sar     edx,32-ZSHIFT
1301         idiv    ecx     ; eax = (v/z)
1302         shl     eax, 16-ZSHIFT
1303         mov     ebp, eax        ; ebp = V1 until pop's
1304
1305         mov     ecx, [U0]       ; ecx = U0 until pop's
1306         mov     edi, [V0]       ; edi = V0 until pop's
1307
1308 ; Make ESI =  V0:U0 in 6:10,6:10 format
1309         mov     eax, ecx
1310         shr     eax, 6
1311         mov     esi, edi
1312         shl     esi, 10
1313         mov     si, ax
1314
1315 ; Make EDX = DV:DU in 6:10,6:10 format
1316         mov     eax, ebx
1317         sub     eax, ecx
1318         sar     eax, NBITS+6
1319         mov     edx, ebp
1320         sub     edx, edi
1321         shl     edx, 10-NBITS   ; EDX = V1-V0/ 4 in 6:10 int:frac
1322         mov     dx, ax  ; put delta u in low word
1323
1324         pop     edi     ; Restore EDI before using it
1325
1326         mov     ecx, [num_left_over]
1327
1328 %assign ITERATION 0
1329 %macro repproc5 0
1330 ; Do 1 pixel
1331         mov     eax, esi        ; get u,v
1332         shr     eax, 26 ; shift out all but int(v)
1333         shld    ax,si,6 ; shift in u, shifting up v
1334         add     eax,[_pixptr]
1335         movzx   eax, byte [eax]    ; load into buffer register
1336         add     esi, edx        ; inc u,v
1337         cmp     al,255
1338         je      %%skip8
1339         mov     [edi+ITERATION], al     ; write pixel
1340 %%skip8:        dec     ecx
1341         jz      near _none_to_do
1342 %endmacro
1343
1344 %rep (1 << NBITS)
1345         ;local  skip8
1346         repproc5
1347 %assign ITERATION  ITERATION + 1
1348 %endrep
1349
1350 ; Should never get here!!!!!
1351         int     3
1352         jmp     _none_to_do
1353