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