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