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