]> icculus.org git repositories - btb/d2x.git/blob - texmap/tmap_lin.asm
fix off by .5 errors in ogl_upixelc and ogl_ulinec (d1x r1.29)
[btb/d2x.git] / texmap / tmap_lin.asm
1 ; $Id: tmap_lin.asm,v 1.2 2003-02-18 20:15:48 btb 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 ; Linearly interpolating texture mapper inner loop
15 ;
16 ; Old Log:
17 ; Revision 1.3  1995/02/20  18:22:57  john
18 ; Put all the externs in the assembly modules into tmap_inc.asm.
19 ; Also, moved all the C versions of the inner loops into a new module,
20 ; scanline.c.
21 ;
22 ; Revision 1.2  1995/02/20  17:09:10  john
23 ; Added code so that you can build the tmapper with no assembly!
24 ;
25 ; Revision 1.1  1994/11/30  12:24:04  mike
26 ; Initial revision
27 ;
28 ; Revision 1.6  1994/11/12  16:39:40  mike
29 ; jae to ja.
30 ;
31 ; Revision 1.5  1994/02/10  21:24:43  matt
32 ; Got rid of debug_on set
33 ;
34 ; Revision 1.4  1994/01/31  15:39:53  mike
35 ; Write additional inner loop for transparency.
36 ;
37 ; Revision 1.3  1994/01/26  11:50:04  john
38 ; Added transparency to linear unlighted texture mapper.
39 ;
40 ; Revision 1.2  1993/11/22  10:24:36  mike
41 ; *** empty log message ***
42 ;
43 ; Revision 1.1  1993/09/08  17:29:50  mike
44 ; Initial revision
45 ;
46 ;
47 ;
48
49 [BITS 32]
50
51 global  _asm_tmap_scanline_lin
52 global  asm_tmap_scanline_lin
53
54 [SECTION .data]
55
56 %include        "tmap_inc.asm"
57
58 _loop_count     dd      0
59
60 [SECTION .text]
61
62 ; --------------------------------------------------------------------------------------------------
63 ; Enter:
64 ;       _xleft  fixed point left x coordinate
65 ;       _xright fixed point right x coordinate
66 ;       _y      fixed point y coordinate
67 ;       _pixptr address of source pixel map
68 ;       _u      fixed point initial u coordinate
69 ;       _v      fixed point initial v coordinate
70 ;       _du_dx  fixed point du/dx
71 ;       _dv_dx  fixed point dv/dx
72
73 ;   for (x = (int) xleft; x <= (int) xright; x++) {
74 ;      _setcolor(read_pixel_from_tmap(srcb,((int) (u/z)) & 63,((int) (v/z)) & 63));
75 ;      _setpixel(x,y);
76 ;
77 ;      u += du_dx;
78 ;      v += dv_dx;
79 ;      z += dz_dx;
80 ;   }
81
82         align   4
83 _asm_tmap_scanline_lin:
84 asm_tmap_scanline_lin:
85         pusha
86
87 ; Setup for loop:       _loop_count  iterations = (int) xright - (int) xleft
88 ;       esi     source pixel pointer = pixptr
89 ;       edi     initial row pointer = y*320+x
90
91 ; set esi = pointer to start of texture map data
92         mov     esi,[_pixptr]
93
94 ; set edi = address of first pixel to modify
95         mov     edi,[_fx_y]
96         cmp     edi,[_window_bottom]
97         ja      near _none_to_do
98
99         imul    edi,[_bytes_per_row]
100         mov     eax,[_fx_xleft]
101         test    eax, eax
102         jns     eax_ok
103         sub     eax,eax
104 eax_ok:
105         add     edi,eax
106         add     edi,[_write_buffer]
107
108 ; set _loop_count = # of iterations
109         mov     eax,[_fx_xright]
110         cmp     eax,[_window_right]
111         jb      eax_ok1
112         mov     eax,[_window_right]
113 eax_ok1:        cmp     eax,[_window_left]
114         ja      eax_ok2
115         mov     eax,[_window_left]
116 eax_ok2:
117
118         mov     ebx,[_fx_xleft]
119         sub     eax,ebx
120         js      near _none_to_do
121         cmp     eax,[_window_width]
122         jbe     _ok_to_do
123         mov     eax,[_window_width]
124 _ok_to_do:
125         mov     [_loop_count],eax
126
127 ;       edi     destination pixel pointer
128
129
130         mov     ebx,[_fx_u]
131         mov     ecx,[_fx_du_dx]
132         mov     edx,[_fx_dv_dx]
133         mov     ebp,[_fx_v]
134
135         shl     ebx,10
136         shl     ebp,10
137         shl     edx,10
138         shl     ecx,10
139
140 ; eax   work
141 ; ebx   u
142 ; ecx   du_dx
143 ; edx   dv_dx
144 ; ebp   v
145 ; esi   read address
146 ; edi   write address
147
148         test    dword [_Transparency_on],-1
149         jne     near transparent_texture
150
151 %define _size   (_end1 - _start1)/num_iters
152         mov     eax,num_iters-1
153         sub     eax,[_loop_count]
154         jns     j_eax_ok1
155         inc     eax     ; sort of a hack, but we can get -1 here and want to be graceful
156         jns     j_eax_ok1       ; if we jump, we had -1, which is kind of ok, if not, we int 3
157         int     3       ; oops, going to jump behind _start1, very bad...
158         sub     eax,eax ; ok to continue
159 j_eax_ok1:      imul    eax,eax,_size
160         add     eax,_start1
161         jmp     eax
162
163         align   4
164 _start1:
165
166 ; "OPTIMIZATIONS" maybe not worth making
167 ;    Getting rid of the esi from the mov al,[esi+eax] instruction.
168 ;       This would require moving into eax at the top of the loop, rather than doing the sub eax,eax.
169 ;       You would have to align your bitmaps so that the two shlds would create the proper base address.
170 ;       In other words, your bitmap data would have to begin at 4096x (for 64x64 bitmaps).
171 ;       I did timings without converting the sub to a mov eax,esi and setting esi to the proper value.
172 ;       There was a speedup of about 1% to 1.5% without converting the sub to a mov.
173 ;    Getting rid of the edi by doing a mov nnnn[edi],al instead of mov [edi],al.
174 ;       The problem with this is you would have a dword offset for nnnn.  My timings indicate it is slower.  (I think.)
175 ;    Combining u,v and du,dv into single longwords.
176 ;       The problem with this is you then must do a 16 bit operation to extract them, and you don't have enough
177 ;       instructions to separate a destination operand from being used by the next instruction.  It shaves out one
178 ;       register instruction (an add reg,reg), but adds a 16 bit operation, and the setup is more complicated.
179 ; usage:
180 ;       eax     work
181 ;       ebx     u coordinate
182 ;       ecx     delta u
183 ;       edx     delta v
184 ;       ebp     v coordinate
185 ;       esi     pointer to source bitmap
186 ;       edi     write address
187 %rep num_iters
188         mov     eax,ebp ; clear for 
189         add     ebp,edx ; update v coordinate
190         shr     eax,26  ; shift in v coordinate
191         shld    eax,ebx,6       ; shift in u coordinate while shifting up v coordinate
192         add     ebx,ecx ; update u coordinate
193         mov     al,[esi+eax]    ; get pixel from source bitmap
194         mov     [edi],al
195         inc     edi             ; XPARENT ADDED BY JOHN
196
197 ; inner loop if bitmaps are 256x256
198 ; your register usage is bogus, and you must clear ecx
199 ; fix your setup
200 ; this is only about 10% faster in the inner loop
201 ; this method would adapt to writing two pixels at a time better than
202 ; the 64x64 method because you wouldn't run out of registers
203 ; Note that this method assumes that both dv_dx and du_dx are in edx.
204 ; edx = vi|vf|ui|uf
205 ; where each field is 8 bits, vi = integer v coordinate, vf = fractional v coordinate, etc.
206 ;** add ebx,edx
207 ;** mov cl,bh
208 ;** shld cx,bx,8
209 ;** mov al,[esi+ecx]
210 ;** mov [edi],al
211 ;** inc edi
212 %endrep
213
214 _end1:
215
216 _none_to_do:    popa
217
218         ret
219
220 ; ----------------------------------------------------------------------------------------
221 ; if texture map has transparency, use this code.
222 transparent_texture:
223         test    dword [_loop_count],-1
224         je      _t_none_to_do
225 loop_transparent:
226         mov     eax,ebp ; clear for 
227         add     ebp,edx ; update v coordinate
228         shr     eax,26  ; shift in v coordinate
229         shld    eax,ebx,6       ; shift in u coordinate while shifting up v coordinate
230         add     ebx,ecx ; update u coordinate
231         mov     al,[esi+eax]    ; get pixel from source bitmap
232         cmp     al,255
233         je      transp
234         mov     [edi],al
235 transp: inc     edi             ; XPARENT ADDED BY JOHN
236
237         dec     dword [_loop_count]
238         jne     loop_transparent
239
240 _t_none_to_do:  popa
241         ret
242
243
244 ; This is the inner loop to write two pixels at a time
245 ; This is about 2.5% faster overall (on Mike's 66 MHz 80486 DX2, VLB)
246 ; You must write code to even align edi and do half as many iterations, and write
247 ; the beginning and ending extra pixels, if necessary.
248 ;       sub     eax,eax ; clear for 
249 ;       shld    eax,ebp,6       ; shift in v coordinate
250 ;       add     ebp,_fx_dv_dx   ; update v coordinate
251 ;       shld    eax,ebx,6       ; shift in u coordinate while shifting up v coordinate
252 ;       add     ebx,ecx ; update u coordinate
253 ;       mov     dl,[esi+eax]    ; get pixel from source bitmap
254 ;
255 ;       sub     eax,eax ; clear for 
256 ;       shld    eax,ebp,6       ; shift in v coordinate
257 ;       add     ebp,_fx_dv_dx   ; update v coordinate
258 ;       shld    eax,ebx,6       ; shift in u coordinate while shifting up v coordinate
259 ;       add     ebx,ecx ; update u coordinate
260 ;       mov     dh,[esi+eax]    ; get pixel from source bitmap
261 ;
262 ;       mov     [edi],dx
263 ;       add     edi,2
264