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/genw.c $
21 * $Revision: 1.4 $
22 * $Author: kevin $
23 * $Date: 1994/08/16 12:50:15 $
24 *
25 * Routines to floor texture 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 "tmapint.h"
37 #include "vtab.h"
38
39 #include <stdbool.h>
40
41 int gri_wall_umap_loop(grs_tmap_loop_info *tli);
42 int gri_wall_umap_loop_1D(grs_tmap_loop_info *tli);
43
gri_wall_umap_loop(grs_tmap_loop_info * tli)44 int gri_wall_umap_loop(grs_tmap_loop_info *tli) {
45 fix u, v, du, dv, dy, d;
46
47 // locals used to store copies of tli-> stuff, so its in registers on the PPC
48 int k, y;
49 uchar t_wlog;
50 uint32_t t_mask;
51 int32_t *t_vtab;
52 uchar *t_bits;
53 uchar *p_dest;
54 fix inv_dy;
55 uchar temp_pix;
56 uchar *t_clut;
57 int32_t gr_row;
58
59 #if InvDiv
60 inv_dy = fix_div(fix_make(1, 0), tli->w);
61 u = fix_mul_asm_safe(tli->left.u, inv_dy);
62 du = fix_mul_asm_safe(tli->right.u, inv_dy) - u;
63 v = fix_mul_asm_safe(tli->left.v, inv_dy);
64 dv = fix_mul_asm_safe(tli->right.v, inv_dy) - v;
65 #else
66 u = fix_div(tli->left.u, tli->w);
67 du = fix_div(tli->right.u, tli->w) - u;
68 v = fix_div(tli->left.v, tli->w);
69 dv = fix_div(tli->right.v, tli->w) - v;
70 #endif
71
72 dy = tli->right.y - tli->left.y;
73
74 t_vtab = tli->vtab;
75 t_bits = tli->bm.bits;
76
77 t_clut = tli->clut;
78 t_mask = tli->mask;
79 t_wlog = tli->bm.wlog;
80
81 gr_row = grd_bm.row;
82
83 do {
84 if ((d = fix_ceil(tli->right.y) - fix_ceil(tli->left.y)) > 0) {
85
86 d = fix_ceil(tli->left.y) - tli->left.y;
87
88 #if InvDiv
89 inv_dy = fix_div(fix_make(1, 0), dy);
90 du = fix_mul_asm_safe(du, inv_dy);
91 dv = fix_mul_asm_safe(dv, inv_dy);
92 #else
93 du = fix_div(du, dy);
94 dv = fix_div(dv, dy);
95 #endif
96 u += fix_mul(du, d);
97 v += fix_mul(dv, d);
98
99 p_dest = grd_bm.bits + (gr_row * fix_cint(tli->left.y)) + tli->x;
100 y = fix_cint(tli->right.y) - fix_cint(tli->left.y);
101
102 switch (tli->bm.hlog) {
103 case GRL_OPAQUE:
104 for (; y > 0; y--) {
105 k = t_vtab[fix_fint(v)] + fix_fint(u);
106 *p_dest = t_bits[k]; // gr_fill_upixel(t_bits[k],t_x,y);
107 p_dest += gr_row;
108 u += du;
109 v += dv;
110 }
111 break;
112 case GRL_TRANS:
113 for (; y > 0; y--) {
114 temp_pix = t_bits[t_vtab[fix_fint(v)] + fix_fint(u)];
115 if (temp_pix != 0)
116 *p_dest = temp_pix; // gr_fill_upixel(t_bits[k],t_x,y);
117 p_dest += gr_row;
118 u += du;
119 v += dv;
120 }
121 break;
122 case GRL_OPAQUE | GRL_LOG2:
123 for (; y > 0; y--) {
124 *p_dest =
125 t_bits[((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask]; // gr_fill_upixel(t_bits[k],t_x,y);
126 p_dest += gr_row;
127 u += du;
128 v += dv;
129 }
130 break;
131 case GRL_TRANS | GRL_LOG2:
132 for (; y > 0; y--) {
133 temp_pix = t_bits[((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask];
134 if (temp_pix != 0)
135 *p_dest = temp_pix; // gr_fill_upixel(t_bits[k],t_x,y);
136 p_dest += gr_row;
137 u += du;
138 v += dv;
139 }
140 break;
141 case GRL_OPAQUE | GRL_CLUT:
142 for (; y > 0; y--) {
143 *p_dest =
144 t_clut[t_bits[t_vtab[fix_fint(v)] + fix_fint(u)]]; // gr_fill_upixel(t_clut[t_bits[k]],t_x,y);
145 p_dest += gr_row;
146 u += du;
147 v += dv;
148 }
149 break;
150 case GRL_TRANS | GRL_CLUT:
151 for (; y > 0; y--) {
152 k = t_vtab[fix_fint(v)] + fix_fint(u);
153 k = t_bits[k];
154 if (k != 0)
155 *p_dest = t_clut[k]; // gr_fill_upixel(t_clut[k],t_x,y);
156 p_dest += gr_row;
157 u += du;
158 v += dv;
159 }
160 break;
161 case GRL_OPAQUE | GRL_LOG2 | GRL_CLUT:
162 for (; y > 0; y--) {
163 *p_dest = t_clut[t_bits[((fix_fint(v) << t_wlog) + fix_fint(u)) &
164 t_mask]]; // gr_fill_upixel(t_clut[t_bits[k]],t_x,y);
165 p_dest += gr_row;
166 u += du;
167 v += dv;
168 }
169 break;
170 case GRL_TRANS | GRL_LOG2 | GRL_CLUT:
171 for (; y > 0; y--) {
172 k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
173 k = t_bits[k];
174 if (k != 0)
175 *p_dest = t_clut[k]; // gr_fill_upixel(t_clut[k],t_x,y);
176 p_dest += gr_row;
177 u += du;
178 v += dv;
179 }
180 break;
181 }
182 } else if (d < 0)
183 return TRUE; /* punt this tmap */
184
185 tli->w += tli->dw;
186
187 // figure out new left u & v & i
188 inv_dy = 0;
189 k = tli->left.u + tli->left.du;
190 y = tli->left.v + tli->left.dv;
191
192 #if InvDiv
193 inv_dy = fix_div(fix_make(1, 0), tli->w);
194 u = fix_mul_asm_safe(k, inv_dy);
195 v = fix_mul_asm_safe(y, inv_dy);
196 #else
197 u = fix_div(k, tli->w);
198 v = fix_div(y, tli->w);
199 #endif
200
201 tli->left.u = k;
202 tli->left.v = y;
203
204 // figure out new right u & v & i
205 k = tli->right.u + tli->right.du;
206 y = tli->right.v + tli->right.dv;
207
208 #if InvDiv
209 du = fix_mul_asm_safe(k, inv_dy) - u;
210 dv = fix_mul_asm_safe(y, inv_dy) - v;
211 #else
212 du = fix_div(k, tli->w) - u;
213 dv = fix_div(y, tli->w) - v;
214 #endif
215
216 tli->right.u = k;
217 tli->right.v = y;
218
219 tli->left.y += tli->left.dy;
220 tli->right.y += tli->right.dy;
221 dy = tli->right.y - tli->left.y;
222 tli->x++;
223
224 } while (--(tli->n) > 0);
225
226 return false;
227 }
228
gri_trans_wall_umap_init(grs_tmap_loop_info * tli)229 void gri_trans_wall_umap_init(grs_tmap_loop_info *tli) {
230 if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
231 tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
232 tli->bm.hlog = GRL_TRANS | GRL_LOG2;
233 } else {
234 tli->vtab = gr_make_vtab(&(tli->bm));
235 tli->bm.hlog = GRL_TRANS;
236 }
237 tli->loop_func = (void (*)())gri_wall_umap_loop;
238 tli->left_edge_func = (void (*)())gri_uvwy_edge;
239 tli->right_edge_func = (void (*)())gri_uvwy_edge;
240 }
241
gri_opaque_wall_umap_init(grs_tmap_loop_info * tli)242 void gri_opaque_wall_umap_init(grs_tmap_loop_info *tli) {
243 if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
244 tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
245 tli->bm.hlog = GRL_OPAQUE | GRL_LOG2;
246 } else {
247 tli->vtab = gr_make_vtab(&(tli->bm));
248 tli->bm.hlog = GRL_OPAQUE;
249 }
250 tli->loop_func = (void (*)())gri_wall_umap_loop;
251 tli->left_edge_func = (void (*)())gri_uvwy_edge;
252 tli->right_edge_func = (void (*)())gri_uvwy_edge;
253 }
254
gri_trans_clut_wall_umap_init(grs_tmap_loop_info * tli)255 void gri_trans_clut_wall_umap_init(grs_tmap_loop_info *tli) {
256 if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
257 tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
258 tli->bm.hlog = GRL_TRANS | GRL_LOG2 | GRL_CLUT;
259 } else {
260 tli->vtab = gr_make_vtab(&(tli->bm));
261 tli->bm.hlog = GRL_TRANS | GRL_CLUT;
262 }
263 tli->loop_func = (void (*)())gri_wall_umap_loop;
264 tli->left_edge_func = (void (*)())gri_uvwy_edge;
265 tli->right_edge_func = (void (*)())gri_uvwy_edge;
266 }
267
gri_opaque_clut_wall_umap_init(grs_tmap_loop_info * tli)268 void gri_opaque_clut_wall_umap_init(grs_tmap_loop_info *tli) {
269 if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
270 tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
271 tli->bm.hlog = GRL_OPAQUE | GRL_LOG2 | GRL_CLUT;
272 } else {
273 tli->vtab = gr_make_vtab(&(tli->bm));
274 tli->bm.hlog = GRL_OPAQUE | GRL_CLUT;
275 }
276 tli->loop_func = (void (*)())gri_wall_umap_loop;
277 tli->left_edge_func = (void (*)())gri_uvwy_edge;
278 tli->right_edge_func = (void (*)())gri_uvwy_edge;
279 }
280
281 /*extern "C"
282 {
283 extern int HandleWallLoop1D_PPC(grs_tmap_loop_info *tli,
284 fix u, fix v, fix dv, fix dy,
285 uchar *t_clut, int32_t *t_vtab, uchar *o_bits,
286 int32_t gr_row, uint32_t t_mask, uint32_t t_wlog);
287 }*/
288
HandleWallLoop1D_C(grs_tmap_loop_info * tli,fix u,fix v,fix dv,fix dy,uchar * t_clut,int32_t * t_vtab,uchar * o_bits,int32_t gr_row,uint32_t t_mask,uint32_t t_wlog)289 int HandleWallLoop1D_C(grs_tmap_loop_info *tli, fix u, fix v, fix dv, fix dy, uchar *t_clut, int32_t *t_vtab,
290 uchar *o_bits, int32_t gr_row, uint32_t t_mask, uint32_t t_wlog) {
291 register int k, y;
292 register fix inv_dy;
293 register uchar *grd_bits, *p_dest, *t_bits;
294 register fix ry, ly;
295
296 ry = tli->right.y;
297 ly = tli->left.y;
298
299 grd_bits = grd_bm.bits + tli->x;
300 tli->x += tli->n;
301 do {
302 if ((k = fix_ceil(ry) - fix_ceil(ly)) > 0) {
303
304 k = fix_ceil(ly) - ly;
305
306 dv = fix_div(dv, dy);
307 v += fix_mul(dv, k);
308
309 p_dest = grd_bits + (gr_row * fix_cint(ly));
310 y = fix_cint(ry) - fix_cint(ly);
311 t_bits = o_bits + fix_fint(u);
312 for (; y > 0; y--) {
313 k = ((fix_fint(v) << t_wlog)) & t_mask;
314 *p_dest = t_clut[t_bits[k]]; // gr_fill_upixel(t_clut[t_bits[k]],t_x,y);
315 v += dv;
316 p_dest += gr_row;
317 }
318 } else if (k < 0)
319 return TRUE; // punt this tmap
320
321 tli->w += tli->dw;
322
323 // figure out new left u & v
324 k = tli->left.u + tli->left.du;
325 y = tli->left.v + tli->left.dv;
326
327 inv_dy = fix_div(fix_make(1, 0), tli->w);
328 u = fix_mul_asm_safe(k, inv_dy);
329 v = fix_mul_asm_safe(y, inv_dy);
330
331 tli->left.u = k;
332 tli->left.v = y;
333
334 // figure out new right u & v
335 tli->right.u += tli->right.du;
336 y = tli->right.v + tli->right.dv;
337 dv = fix_mul_asm_safe(y, inv_dy) - v;
338 tli->right.v = y;
339
340 ly += tli->left.dy;
341 ry += tli->right.dy;
342 dy = ry - ly;
343 grd_bits++;
344 } while (--(tli->n) > 0);
345
346 tli->right.y = ry;
347 tli->left.y = ly;
348
349 return false;
350 }
351
352 // ==================================================================
353 // 1D versions
gri_wall_umap_loop_1D(grs_tmap_loop_info * tli)354 int gri_wall_umap_loop_1D(grs_tmap_loop_info *tli) {
355 fix u, v, dv, dy, d;
356
357 // locals used to store copies of tli-> stuff, so its in registers on the PPC
358 int k, y;
359 uchar t_wlog;
360 uint32_t t_mask;
361 int32_t *t_vtab;
362 uchar *t_bits, *o_bits;
363 uchar *p_dest;
364 fix inv_dy;
365 uchar temp_pix;
366 uchar *t_clut;
367 int32_t gr_row;
368
369 #if InvDiv
370 inv_dy = fix_div(fix_make(1, 0), tli->w);
371 u = fix_mul_asm_safe(tli->left.u, inv_dy);
372 v = fix_mul_asm_safe(tli->left.v, inv_dy);
373 dv = fix_mul_asm_safe(tli->right.v, inv_dy) - v;
374 #else
375 u = fix_div(tli->left.u, tli->w);
376 v = fix_div(tli->left.v, tli->w);
377 dv = fix_div(tli->right.v, tli->w) - v;
378 #endif
379
380 dy = tli->right.y - tli->left.y;
381
382 t_vtab = tli->vtab;
383 o_bits = tli->bm.bits;
384
385 t_clut = tli->clut;
386 t_mask = tli->mask;
387 t_wlog = tli->bm.wlog;
388
389 gr_row = grd_bm.row;
390
391 return HandleWallLoop1D_C(tli, u, v, dv, dy, t_clut, t_vtab, o_bits, gr_row, t_mask, t_wlog);
392 }
393
gri_opaque_clut_wall1d_umap_init(grs_tmap_loop_info * tli)394 void gri_opaque_clut_wall1d_umap_init(grs_tmap_loop_info *tli) {
395 // MLA - Wall1d is always log2
396 /* if ((tli->bm.row==(1<<tli->bm.wlog)) &&
397 (tli->bm.h==(1<<tli->bm.hlog))) {*/
398 tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
399 tli->bm.hlog = GRL_OPAQUE | GRL_LOG2 | GRL_CLUT;
400 /* } else {
401 tli->vtab=gr_make_vtab(&(tli->bm));
402 tli->bm.hlog=GRL_OPAQUE|GRL_CLUT;
403 }*/
404 tli->loop_func = (void (*)())gri_wall_umap_loop_1D;
405 tli->left_edge_func = (void (*)())gri_uvwy_edge;
406 tli->right_edge_func = (void (*)())gri_uvwy_edge;
407 }
408