1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/lib/src/2d/RCS/fl8lw.c $
21  * $Revision: 1.4 $
22  * $Author: kevin $
23  * $Date: 1994/08/16 12:50:16 $
24  *
25  * Routines to wall floor map a flat8 bitmap to a generic canvas.
26  *
27  * This file is part of the 2d library.
28  *
29  */
30 
31 #include "cnvdat.h"
32 #include "fl8tf.h"
33 #include "fl8tmapdv.h"
34 #include "gente.h"
35 #include "poly.h"
36 #include "scrmac.h"
37 #include "tmapint.h"
38 #include "vtab.h"
39 
40 int gri_lit_wall_umap_loop(grs_tmap_loop_info *tli);
41 int gri_lit_wall_umap_loop_1D(grs_tmap_loop_info *tli);
42 
gri_lit_wall_umap_loop(grs_tmap_loop_info * tli)43 int gri_lit_wall_umap_loop(grs_tmap_loop_info *tli) {
44     fix u, v, i, du, dv, di, dy, d;
45 
46     // locals used to store copies of tli-> stuff, so its in registers on the PPC
47     int k, y;
48     uint32_t t_mask;
49     uint32_t t_wlog;
50     uchar *t_bits;
51     uchar *p_dest;
52     int32_t gr_row;
53     uchar *g_ltab;
54     fix inv_dy;
55     int32_t *t_vtab;
56 
57 #if InvDiv
58     inv_dy = fix_div(fix_make(1, 0), tli->w);
59     u = fix_mul_asm_safe(tli->left.u, inv_dy);
60     du = fix_mul_asm_safe(tli->right.u, inv_dy) - u;
61     v = fix_mul_asm_safe(tli->left.v, inv_dy);
62     dv = fix_mul_asm_safe(tli->right.v, inv_dy) - v;
63     i = fix_mul_asm_safe(tli->left.i, inv_dy);
64     di = fix_mul_asm_safe(tli->right.i, inv_dy) - i;
65     if (di >= -256 && di <= 256)
66         i += 1024;
67 #else
68     u = fix_div(tli->left.u, tli->w);
69     du = fix_div(tli->right.u, tli->w) - u;
70     v = fix_div(tli->left.v, tli->w);
71     dv = fix_div(tli->right.v, tli->w) - v;
72     i = fix_div(tli->left.i, tli->w);
73     di = fix_div(tli->right.i, tli->w) - i;
74     if (di >= -256 && di <= 256)
75         i += 1024;
76 #endif
77 
78     dy = tli->right.y - tli->left.y;
79 
80     t_mask = tli->mask;
81     t_wlog = tli->bm.wlog;
82     g_ltab = grd_screen->ltab;
83     t_vtab = tli->vtab;
84     t_bits = tli->bm.bits;
85     gr_row = grd_bm.row;
86 
87     do {
88         if ((d = fix_ceil(tli->right.y) - fix_ceil(tli->left.y)) > 0) {
89             d = fix_ceil(tli->left.y) - tli->left.y;
90 
91 #if InvDiv
92             inv_dy = fix_div(fix_make(1, 0) << 8, dy);
93             di = fix_mul_asm_safe_light(di, inv_dy);
94             inv_dy >>= 8;
95             du = fix_mul_asm_safe(du, inv_dy);
96             dv = fix_mul_asm_safe(dv, inv_dy);
97 #else
98             du = fix_div(du, dy);
99             dv = fix_div(dv, dy);
100             di = fix_div(di, dy);
101 #endif
102             u += fix_mul(du, d);
103             v += fix_mul(dv, d);
104             i += fix_mul(di, d);
105 
106             y = fix_cint(tli->right.y) - fix_cint(tli->left.y);
107             p_dest = grd_bm.bits + (gr_row * fix_cint(tli->left.y)) + tli->x;
108 
109             switch (tli->bm.hlog) {
110             case GRL_OPAQUE:
111                 for (; y > 0; y--) {
112                     k = t_vtab[fix_fint(v)] + fix_fint(u);
113                     *p_dest = g_ltab[t_bits[k] + fix_light(i)]; // gr_fill_upixel(g_ltab[t_bits[k]+fix_light(i)],t_x,y);
114                     p_dest += gr_row;
115                     u += du;
116                     v += dv;
117                     i += di;
118                 }
119                 break;
120             case GRL_TRANS:
121                 for (; y > 0; y--) {
122                     k = t_vtab[fix_fint(v)] + fix_fint(u);
123                     k = t_bits[k];
124                     if (k != 0)
125                         *p_dest = g_ltab[k + fix_light(i)]; // gr_fill_upixel(g_ltab[k+fix_light(i)],t_x,y);
126                     p_dest += gr_row;
127                     u += du;
128                     v += dv;
129                     i += di;
130                 }
131                 break;
132             case GRL_OPAQUE | GRL_LOG2:
133                 for (; y > 0; y--) {
134                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
135                     *p_dest = g_ltab[t_bits[k] + fix_light(i)];
136                     p_dest += gr_row;
137                     u += du;
138                     v += dv;
139                     i += di;
140                 }
141                 break;
142             case GRL_TRANS | GRL_LOG2:
143                 for (; y > 0; y--) {
144                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
145                     k = t_bits[k];
146                     if (k != 0)
147                         *p_dest = g_ltab[k + fix_light(i)]; // gr_fill_upixel(g_ltab[k+fix_light(i)],t_x,y);
148                     p_dest += gr_row;
149                     u += du;
150                     v += dv;
151                     i += di;
152                 }
153                 break;
154             }
155         } else if (d < 0)
156             return TRUE; /* punt this tmap */
157 
158         tli->w += tli->dw;
159 
160         // figure out new left u & v & i
161         inv_dy = 0;
162         k = tli->left.u + tli->left.du;
163         y = tli->left.v + tli->left.dv;
164         tli->left.i += tli->left.di;
165 
166 #if InvDiv
167         inv_dy = fix_div(fix_make(1, 0), tli->w);
168         u = fix_mul_asm_safe(k, inv_dy);
169         v = fix_mul_asm_safe(y, inv_dy);
170         i = fix_mul_asm_safe(tli->left.i, inv_dy);
171         if (di >= -256 && di <= 256)
172             i += 1024;
173 #else
174         u = fix_div(k, tli->w);
175         v = fix_div(y, tli->w);
176         i = fix_div(tli->left.i, tli->w);
177         if (di >= -256 && di <= 256)
178             i += 1024;
179 #endif
180 
181         tli->left.u = k;
182         tli->left.v = y;
183 
184         // figure out new right u & v & i
185         k = tli->right.u + tli->right.du;
186         y = tli->right.v + tli->right.dv;
187         tli->right.i += tli->right.di;
188 
189 #if InvDiv
190         du = fix_mul_asm_safe(k, inv_dy) - u;
191         dv = fix_mul_asm_safe(y, inv_dy) - v;
192         di = fix_mul_asm_safe(tli->right.i, inv_dy) - i;
193 #else
194         du = fix_div(k, tli->w) - u;
195         dv = fix_div(y, tli->w) - v;
196         di = fix_div(tli->right.i, tli->w) - i;
197 #endif
198         tli->right.u = k;
199         tli->right.v = y;
200 
201         tli->left.y += tli->left.dy;
202         tli->right.y += tli->right.dy;
203         dy = tli->right.y - tli->left.y;
204         tli->x++;
205     } while (--(tli->n) > 0);
206 
207     return FALSE; /* tmap OK */
208 }
209 
gri_trans_lit_wall_umap_init(grs_tmap_loop_info * tli)210 void gri_trans_lit_wall_umap_init(grs_tmap_loop_info *tli) {
211     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
212         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
213         tli->bm.hlog = GRL_TRANS | GRL_LOG2;
214     } else {
215         tli->vtab = gr_make_vtab(&(tli->bm));
216         tli->bm.hlog = GRL_TRANS;
217     }
218     tli->loop_func = (void (*)())gri_lit_wall_umap_loop;
219     tli->left_edge_func = (void (*)())gri_uviwy_edge;
220     tli->right_edge_func = (void (*)())gri_uviwy_edge;
221 }
222 
gri_opaque_lit_wall_umap_init(grs_tmap_loop_info * tli)223 void gri_opaque_lit_wall_umap_init(grs_tmap_loop_info *tli) {
224     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
225         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
226         tli->bm.hlog = GRL_OPAQUE | GRL_LOG2;
227     } else {
228         tli->vtab = gr_make_vtab(&(tli->bm));
229         tli->bm.hlog = GRL_OPAQUE;
230     }
231     tli->loop_func = (void (*)())gri_lit_wall_umap_loop;
232     tli->left_edge_func = (void (*)())gri_uviwy_edge;
233     tli->right_edge_func = (void (*)())gri_uviwy_edge;
234 }
235 
236 /*extern "C"
237 {
238 extern int HandleWallLitLoop1D_PPC(grs_tmap_loop_info *tli,
239                                                                                                                                                 fix u, fix v, fix i, fix dv, fix di, fix dy,
240                                                                                                                                                 uchar *g_ltab, int32_t *t_vtab, uchar *o_bits,
241                                                                                                                                                 int32_t gr_row, uint32_t t_mask, uint32_t t_wlog);
242 }*/
243 
HandleWallLitLoop1D_C(grs_tmap_loop_info * tli,fix u,fix v,fix i,fix dv,fix di,fix dy,uchar * g_ltab,uchar * o_bits,int32_t gr_row,uint32_t t_mask,uint32_t t_wlog)244 int HandleWallLitLoop1D_C(grs_tmap_loop_info *tli, fix u, fix v, fix i, fix dv, fix di, fix dy, uchar *g_ltab,
245                           uchar *o_bits, int32_t gr_row, uint32_t t_mask, uint32_t t_wlog) {
246     fix d, inv_dy;
247     register fix lefty, righty;
248     int32_t k, y;
249     uchar *t_bits;
250     uchar *p_dest;
251 
252     lefty = tli->left.y;
253     righty = tli->right.y;
254     do {
255         if ((d = fix_ceil(righty) - fix_ceil(lefty)) > 0) {
256             d = fix_ceil(lefty) - lefty;
257 
258             inv_dy = fix_div(fix_make(1, 0) << 8, dy);
259             dv = fix_mul_asm_safe(dv, inv_dy >> 8);
260             di = fix_mul_asm_safe_light(di, inv_dy);
261 
262             v += fix_mul(dv, d);
263             i += fix_mul(di, d);
264 
265             if (di >= -256 && di <= 256)
266                 i += 256;
267 
268             y = fix_cint(righty) - fix_cint(lefty);
269             p_dest = grd_bm.bits + (gr_row * fix_cint(lefty)) + tli->x;
270             t_bits = o_bits + fix_fint(u);
271 
272             // inner loop
273             for (; y > 0; y--) {
274                 k = (fix_fint(v) << t_wlog) & t_mask;
275                 *p_dest = g_ltab[t_bits[k] + fix_light(i)];
276                 p_dest += gr_row;
277                 v += dv;
278                 i += di;
279             }
280 
281         } else if (d < 0)
282             return TRUE; // punt this tmap
283 
284         tli->w += tli->dw;
285 
286         // figure out new left u & v & i
287         k = tli->left.u + tli->left.du;
288         y = tli->left.v + tli->left.dv;
289         tli->left.i += tli->left.di;
290 
291         inv_dy = fix_div(fix_make(1, 0), tli->w);
292         u = fix_mul_asm_safe(k, inv_dy);
293         v = fix_mul_asm_safe(y, inv_dy);
294         i = fix_mul_asm_safe(tli->left.i, inv_dy);
295 
296         tli->left.u = k;
297         tli->left.v = y;
298 
299         // figure out new right u & v & i
300         k = tli->right.u + tli->right.du;
301         y = tli->right.v + tli->right.dv;
302         tli->right.i += tli->right.di;
303 
304         dv = fix_mul_asm_safe(y, inv_dy) - v;
305         di = fix_mul_asm_safe(tli->right.i, inv_dy) - i;
306         if (di >= -256 && di <= 256)
307             i += 1024;
308 
309         tli->right.u = k;
310         tli->right.v = y;
311 
312         lefty += tli->left.dy;
313         righty += tli->right.dy;
314         dy = righty - lefty;
315         tli->x++;
316     } while (--(tli->n) > 0);
317 
318     tli->left.y = lefty;
319     tli->right.y = righty;
320 
321     return FALSE; // tmap OK
322 }
323 
324 // ==================================================================================
325 // Wall_1D versions of routines
gri_lit_wall_umap_loop_1D(grs_tmap_loop_info * tli)326 int gri_lit_wall_umap_loop_1D(grs_tmap_loop_info *tli) {
327     fix u, v, i, dv, di, dy;
328 
329     // locals used to store copies of tli-> stuff, so its in registers on the PPC
330     int k, y;
331     uint32_t t_mask;
332     uint32_t t_wlog;
333     int32_t gr_row;
334     uchar *g_ltab;
335     uchar *o_bits;
336     fix inv_dy;
337 
338 #if InvDiv
339     inv_dy = fix_div(fix_make(1, 0), tli->w);
340     u = fix_mul_asm_safe(tli->left.u, inv_dy);
341     v = fix_mul_asm_safe(tli->left.v, inv_dy);
342     dv = fix_mul_asm_safe(tli->right.v, inv_dy) - v;
343     i = fix_mul_asm_safe(tli->left.i, inv_dy);
344     di = fix_mul_asm_safe(tli->right.i, inv_dy) - i;
345     if (di >= -256 && di <= 256)
346         i += 512;
347 #else
348     u = fix_div(tli->left.u, tli->w);
349     v = fix_div(tli->left.v, tli->w);
350     dv = fix_div(tli->right.v, tli->w) - v;
351     i = fix_div(tli->left.i, tli->w);
352     di = fix_div(tli->right.i, tli->w) - i;
353     if (di >= -256 && di <= 256)
354         i += 512;
355 #endif
356 
357     dy = tli->right.y - tli->left.y;
358 
359     t_mask = tli->mask;
360     t_wlog = tli->bm.wlog;
361     g_ltab = grd_screen->ltab;
362     o_bits = tli->bm.bits;
363     gr_row = grd_bm.row;
364 
365     return HandleWallLitLoop1D_C(tli, u, v, i, dv, di, dy, g_ltab, o_bits, gr_row, t_mask, t_wlog);
366 }
367 
gri_opaque_lit_wall1d_umap_init(grs_tmap_loop_info * tli)368 void gri_opaque_lit_wall1d_umap_init(grs_tmap_loop_info *tli) {
369     // Wall1D is always log2
370     /*   if ((tli->bm.row==(1<<tli->bm.wlog)) &&
371                 (tli->bm.h==(1<<tli->bm.hlog))) {*/
372     tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
373     tli->bm.hlog = GRL_OPAQUE | GRL_LOG2;
374     /*   } else {
375           tli->vtab=gr_make_vtab(&(tli->bm));
376           tli->bm.hlog=GRL_OPAQUE;
377        }*/
378     tli->loop_func = (void (*)())gri_lit_wall_umap_loop_1D;
379     tli->left_edge_func = (void (*)())gri_uviwy_edge;
380     tli->right_edge_func = (void (*)())gri_uviwy_edge;
381 }
382