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