divide negative window x-coordinates properly, fixing random crashes
[btb/d2x.git] / texmap / tmap_ll.asm
1 ; $Id: tmap_ll.asm,v 1.3 2004-08-28 23:17:46 schaffner Exp $
2 ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 ;SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 ;IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 ;FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 ;
13 ;
14 ; Linear, lighted texture mapper inner loop.
15 ;
16 ;
17
18 [BITS 32]
19
20 global  _asm_tmap_scanline_lin_lighted
21 global  asm_tmap_scanline_lin_lighted
22
23 [SECTION .data]
24
25 %include        "tmap_inc.asm"
26
27 ALLOW_DITHERING equ     1
28
29 _fx_dl_dx1      dd 0
30 _fx_dl_dx2      dd 0
31
32 _loop_count     dd 0
33
34
35 [SECTION .text]
36
37 ; --------------------------------------------------------------------------------------------------
38 ; Enter:
39 ;       _xleft  fixed point left x coordinate
40 ;       _xright fixed point right x coordinate
41 ;       _y      fixed point y coordinate
42 ;       _pixptr address of source pixel map
43 ;       _u      fixed point initial u coordinate
44 ;       _v      fixed point initial v coordinate
45 ;       _du_dx  fixed point du/dx
46 ;       _dv_dx  fixed point dv/dx
47
48 ;   for (x = (int) xleft; x <= (int) xright; x++) {
49 ;      _setcolor(read_pixel_from_tmap(srcb,((int) (u/z)) & 63,((int) (v/z)) & 63));
50 ;      _setpixel(x,y);
51 ;
52 ;      u += du_dx;
53 ;      v += dv_dx;
54 ;      z += dz_dx;
55 ;   }
56
57         align   4
58 _asm_tmap_scanline_lin_lighted:
59 asm_tmap_scanline_lin_lighted:
60 ;        push    es  ; DPH: No selectors in windows :-(
61 ;        push    fs
62         pusha
63
64 ;        mov     es,[_pixel_data_selector]       ; selector[0*2] ; DPH: No... :-)
65 ;        mov     fs,[_gr_fade_table_selector]    ; selector[1*2] ; fs = bmd_fade_table
66
67 ; Setup for loop:       _loop_count  iterations = (int) xright - (int) xleft
68 ;   esi source pixel pointer = pixptr
69 ;   edi initial row pointer = y*320+x
70
71 ; set esi = pointer to start of texture map data
72         mov     esi,[_pixptr]
73
74 ; set edi = address of first pixel to modify
75         mov     edi,[_fx_y]     ; this is actually an int
76         cmp     edi,[_window_bottom]
77         ja      near all_done
78
79         imul    edi,[_bytes_per_row]
80         mov     ebx,[_fx_xleft]
81         test    ebx,ebx
82         jns     ebx_ok
83         sub     ebx,ebx
84 ebx_ok:
85         add     edi,ebx
86         add     edi,[_write_buffer]
87
88 ; set _loop_count = # of iterations
89         mov     eax,[_fx_xright]
90         cmp     eax,[_window_right]
91         jl      eax_ok1
92         mov     eax,[_window_right]
93 eax_ok1:        cmp     eax,[_window_left]
94         jg      eax_ok2
95         mov     eax,[_window_left]
96 eax_ok2:
97
98         sub     eax,ebx
99         js      near all_done
100         cmp     eax,[_window_width]
101         jbe     _ok_to_do
102         mov     eax,[_window_width]
103 _ok_to_do:
104         mov     [_loop_count],eax
105
106 ;       edi     destination pixel pointer
107
108
109         mov     ecx,_gr_fade_table  ;originally offset _lighting_tables
110         mov     eax,[_fx_u]     ; get 32 bit u coordinate
111         shr     eax,6   ; get 6:10 int:frac u coordinate into low word
112         mov     ebp,[_fx_v]     ; get 32 bit v coordinate
113         shl     ebp,10  ; put 6:10 int:frac into high word
114         mov     bp,ax   ; put u coordinate in low word
115
116         mov     eax,[_fx_du_dx] ; get 32 bit delta u
117         shr     eax,6   ; get 6:10 int:frac delta u into low word
118         mov     edx,[_fx_dv_dx] ; get 32 bit delta v
119         shl     edx,10  ; put 6:10 int:frac into high word
120         mov     dx,ax   ; put delta u in low word
121
122         sar     dword [_fx_dl_dx],8
123         jns     dl_dx_ok
124         inc     dword [_fx_dl_dx]       ; round towards 0 for negative deltas
125 dl_dx_ok:
126
127 %if ALLOW_DITHERING
128 ; do dithering, use lighting values which are .5 less than and .5 more than actual value
129         mov     ebx,80h ; assume dithering on
130         test    dword [_dither_intensity_lighting],-1
131         jne     do_dither
132         sub     ebx,ebx ; no dithering
133 do_dither:
134         mov     eax,[_fx_dl_dx]
135         add     eax,ebx ; add 1/2
136         mov     [_fx_dl_dx1],eax
137         sub     eax,ebx
138         sub     eax,ebx
139         mov     [_fx_dl_dx2],eax
140         mov     ebx,[_fx_xleft]
141         xor     ebx,[_fx_y]
142         and     ebx,1
143         jne     dith_1
144         xchg    eax,[_fx_dl_dx1]
145 dith_1: mov     [_fx_dl_dx2],eax
146 %endif
147
148         mov     ebx,[_fx_l]
149
150 ; lighting values are passed in fixed point, but need to be in 8 bit integer, 8 bit fraction so we can easily
151 ; get the integer by reading %bh
152         sar     ebx,8
153
154         test    dword [_Transparency_on],-1
155         jne     do_transparency_ll
156
157 ;; esi, ecx should be free
158 loop_test equ 1 ; set to 1 to run as loop for better profiling
159 %if loop_test
160         mov     esi,[_fx_dl_dx]
161
162         mov     ecx,[_loop_count]
163         inc     ecx
164         shr     ecx,1
165         je      one_more_pix
166         pushf
167
168         align   4
169
170 loop1:
171         mov     eax,ebp ; get u, v
172         shr     eax,26  ; shift out all but int(v)
173         shld    ax,bp,6 ; shift in u, shifting up v
174
175         add     ebp,edx ; u += du, v += dv
176
177         add eax,[_pixptr] ; DPH: No selectors in windows
178         movzx   eax,byte [eax]     ; get pixel from source bitmap
179         mov     ah,bh   ; get lighting table
180         add     ebx,esi ; _fx_dl_dx     ; update lighting value
181         mov     al,[_gr_fade_table + eax]     ; xlat pixel through lighting tables
182         mov     [edi],al        ; write pixel...
183         inc     edi     ; ...and advance
184
185 ; --- ---
186
187         mov     eax,ebp ; get u, v
188         shr     eax,26  ; shift out all but int(v)
189         shld    ax,bp,6 ; shift in u, shifting up v
190
191         add     ebp,edx ; u += du, v += dv
192
193         add eax,[_pixptr] ; DPH:
194         movzx   eax,byte [eax]     ; get pixel from source bitmap
195         mov     ah,bh   ; get lighting table
196         add     ebx,esi ; _fx_dl_dx     ; update lighting value
197         mov     al,[_gr_fade_table + eax]     ; xlat pixel through lighting tables
198         mov     [edi],al        ; write pixel...
199         inc     edi     ; ...and advance
200
201         dec     ecx     ; _loop_count
202         jne     loop1
203
204         popf
205         jnc     all_done
206
207 one_more_pix:   mov     eax,ebp ; get u, v
208         shr     eax,26  ; shift out all but int(v)
209         shld    ax,bp,6 ; shift in u, shifting up v
210
211         add eax,[_pixptr] ; DPH:
212         movzx   eax,byte [eax]     ; get pixel from source bitmap
213         mov     ah,bh   ; get lighting table
214         mov     al,[_gr_fade_table + eax]     ; xlat pixel through lighting tables
215         mov     [edi],al        ; write pixel...
216
217 all_done:       popa
218 ;        pop     fs
219 ;        pop     es
220         ret
221
222
223 %else
224
225 ; usage:
226 ;       eax     work
227 ;       ebx     lighting value
228 ;       ecx     _lighting_tables
229 ;       edx     du, dv 6:10:6:10
230 ;       ebp     u, v coordinates 6:10:6:10
231 ;       esi     pointer to source bitmap
232 ;       edi     write address
233
234 ;_size = (_end1 - _start1)/num_iters
235 ;  note: if eax is odd, you will not be writing the last pixel, you must clean up at the end
236 %if ALLOW_DITHERING
237     mov eax,[_loop_count]
238     shr eax,1
239     neg eax
240     add eax,num_iters
241 %else
242         mov     eax,num_iters
243         sub     eax,[_loop_count]
244
245 %endif
246         imul    eax,eax,(_end1 - _start1)/num_iters
247         add     eax,_start1     ;originally offset _start1
248         jmp     eax
249
250         align   4
251 _start1:
252
253 ; usage:
254 ;       eax     work
255 ;       ebx     lighting value
256 ;       ecx     _lighting_tables
257 ;       edx     du, dv 6:10:6:10
258 ;       ebp     u, v coordinates 6:10:6:10
259 ;       esi     pointer to source bitmap
260 ;       edi     write address
261
262 ; do all but the last pixel in the unwound loop, last pixel done separately because less work is needed
263 %rep num_iters
264 %if 1
265
266 ;**; inner loop if lighting value is constant
267 ;**; can be optimized if source bitmap pixels are stored as words, then the mov ah,bh is not necessary
268 ;**     mov     eax,ebp ; get u, v
269 ;**     shr     eax,26  ; shift out all but int(v)
270 ;**     shld    ax,bp,6 ; shift in u, shifting up v
271 ;**
272 ;**     add     ebp,edx ; u += du, v += dv
273 ;**
274 ;**     mov     al,[esi+eax]    ; get pixel from source bitmap
275 ;**     mov     ah,bh   ; get lighting table
276 ;**     mov     al,[ecx+eax]    ; xlat pixel through lighting tables
277 ;**     mov     [edi],al        ; write pixel...
278 ;**     inc     edi     ; ...and advance
279
280
281 %if ALLOW_DITHERING
282
283 ; dithering
284 ; loop contains two iterations which must be the same length
285         mov     eax,ebp ; get u, v
286         shr     eax,26  ; shift out all but int(v)
287         shld    ax,bp,6 ; shift in u, shifting up v
288
289         add     ebp,edx ; u += du, v += dv
290
291         mov     al,[esi+eax]    ; get pixel from source bitmap
292         mov     ah,bh   ; get lighting table
293         add     ebx,[_fx_dl_dx1]        ; update lighting value
294         mov     al,[ecx+eax]    ; xlat pixel through lighting tables
295         mov     [edi],al        ; write pixel...
296         inc     edi     ; ...and advance
297
298 ; second iteration
299         mov     eax,ebp ; get u, v
300         shr     eax,26  ; shift out all but int(v)
301         shld    ax,bp,6 ; shift in u, shifting up v
302
303         add     ebp,edx ; u += du, v += dv
304
305         mov     al,[esi+eax]    ; get pixel from source bitmap
306         mov     ah,bh   ; get lighting table
307         add     ebx,[_fx_dl_dx2]        ; update lighting value
308         mov     al,[ecx+eax]    ; xlat pixel through lighting tables
309         mov     [edi],al        ; write pixel...
310         inc     edi     ; ...and advance
311 %else
312         mov     eax,ebp ; get u, v
313         shr     eax,26  ; shift out all but int(v)
314         shld    ax,bp,6 ; shift in u, shifting up v
315
316         add     ebp,edx ; u += du, v += dv
317
318         mov     al,[esi+eax]    ; get pixel from source bitmap
319         mov     ah,bh   ; get lighting table
320         add     ebx,[_fx_dl_dx] ; update lighting value
321         mov     al,[ecx+eax]    ; xlat pixel through lighting tables
322         mov     [edi],al        ; write pixel...
323         inc     edi     ; ...and advance
324 %endif
325
326
327 %else
328
329 ;obsolete: ; version which assumes segment overrides are in place (which they are obviously not)
330 ;obsolete:      mov     eax,ebp ; get u, v
331 ;obsolete:      shr     eax,26  ; shift out all but int(v)
332 ;obsolete:      shld    ax,bp,6 ; shift in u, shifting up v
333 ;obsolete:
334 ;obsolete:      add     ebp,edx ; u += du, v += dv
335 ;obsolete:
336 ;obsolete:      mov     al,[eax]        ; get pixel from source bitmap
337 ;obsolete:      mov     ah,bh   ; get lighting table
338 ;obsolete:      add     ebx,esi ; update lighting value
339 ;obsolete:      mov     al,[eax]        ; xlat pixel through lighting tables
340 ;obsolete:      mov     [edi],al        ; write pixel...
341 ;obsolete:      inc     edi     ; ...and advance
342 %endif
343 %endrep
344
345 _end1:
346
347 ; now do the leftover pixel
348         mov     eax,ebp
349         shr     eax,26  ; shift in v coordinate
350         shld    ax,bp,6 ; shift in u coordinate while shifting up v coordinate
351         mov     al,[esi+eax]    ; get pixel from source bitmap
352         mov     ah,bh   ; get lighting table
353  or ah,ah
354  jns ok1
355  sub ah,ah
356 ok1:
357         mov     al,[_gr_fade_table+eax] ; xlat pixel through lighting tables
358         mov     [edi],al        ; write pixel...
359
360 _none_to_do:    popa
361 ;        pop     fs
362 ;        pop     es
363         ret
364
365 %endif
366 ; -- Code to get rgb 5 bits integer, 5 bits fraction value into 5 bits integer (for each gun)
367 ; suitable for inverse color lookup
368 ;**__test:
369 ;** int 3
370 ;**;                  rrrrrfffffrrrrrfffffxxbbbbbfffff
371 ;**     mov     eax,11111001001010101110101101110111b
372 ;**     and     eax,11111000001111100000001111100000b
373 ;**     shld    ebx,eax,15
374 ;**     or      bx,ax
375
376
377 ;; esi, ecx should be free
378 do_transparency_ll:
379         mov     esi,[_fx_dl_dx]
380
381         mov     ecx,[_loop_count]
382         inc     ecx
383         shr     ecx,1
384         je      one_more_pix2
385         pushf
386
387         align   4
388
389 loop1a:
390         mov     eax,ebp ; get u, v
391         shr     eax,26  ; shift out all but int(v)
392         shld    ax,bp,6 ; shift in u, shifting up v
393
394         add     ebp,edx ; u += du, v += dv
395
396         add eax,[_pixptr] ; DPH:
397         movzx   eax,byte [eax]     ; get pixel from source bitmap
398         cmp     al,255
399         je      skip1a
400         mov     ah,bh   ; get lighting table
401         add     ebx,esi ; _fx_dl_dx     ; update lighting value
402         mov     al,[_gr_fade_table + eax]     ; xlat pixel through lighting tables
403         mov     [edi],al        ; write pixel...
404 skip1a: inc     edi     ; ...and advance
405
406 ; --- ---
407
408         mov     eax,ebp ; get u, v
409         shr     eax,26  ; shift out all but int(v)
410         shld    ax,bp,6 ; shift in u, shifting up v
411
412         add     ebp,edx ; u += du, v += dv
413
414         add eax,[_pixptr] ; DPH:
415         movzx   eax,byte [eax]     ; get pixel from source bitmap
416         cmp     al,255
417         je      skip2a
418         mov     ah,bh   ; get lighting table
419         add     ebx,esi ; _fx_dl_dx     ; update lighting value
420         mov     al,[_gr_fade_table + eax]     ; xlat pixel through lighting tables
421         mov     [edi],al        ; write pixel...
422 skip2a: inc     edi     ; ...and advance
423
424         dec     ecx     ; _loop_count
425         jne     loop1a
426
427         popf
428         jnc     all_done_1
429
430 one_more_pix2:  mov     eax,ebp ; get u, v
431         shr     eax,26  ; shift out all but int(v)
432         shld    ax,bp,6 ; shift in u, shifting up v
433
434         add eax,[_pixptr] ; DPH:
435         movzx   eax,byte [eax]     ; get pixel from source bitmap
436         cmp     al,255
437         je      skip3a
438         mov     ah,bh   ; get lighting table
439         mov     al,[_gr_fade_table + eax]     ; xlat pixel through lighting tables
440         mov     [edi],al        ; write pixel...
441
442 skip3a:
443 all_done_1:     popa
444 ;        pop     fs ; DPH:
445 ;        pop     es
446         ret
447