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 // Implementation solid transparent mappers
20 //
21 // This file is part of the 2d library.
22 //
23 
24 #include "cnvdat.h"
25 #include "fl8tf.h"
26 #include "gente.h"
27 #include "poly.h"
28 #include "tmapint.h"
29 #include "vtab.h"
30 
31 // prototypes
32 int gri_trans_solid_lin_umap_loop(grs_tmap_loop_info *tli);
33 int gri_trans_solid_floor_umap_loop(grs_tmap_loop_info *tli);
34 int gri_solid_wall_umap_loop(grs_tmap_loop_info *tli);
35 void gri_trans_solid_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm);
36 void gri_trans_solid_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm);
37 
gri_trans_solid_lin_umap_loop(grs_tmap_loop_info * tli)38 int gri_trans_solid_lin_umap_loop(grs_tmap_loop_info *tli) {
39     fix u, v, du, dv, dx, d;
40 
41     // locals used to store copies of tli-> stuff, so its in registers on the PPC
42     int x;
43     uchar solid_color;
44     int t_xl, t_xr;
45     uchar *p_dest;
46     int32_t *t_vtab;
47     uchar *t_bits;
48     uchar *t_clut;
49     uchar t_wlog;
50     uint32_t t_mask;
51     int32_t gr_row;
52     uchar *start_pdest;
53 
54     solid_color = tli->solid;
55     u = tli->left.u;
56     du = tli->right.u - u;
57     v = tli->left.v;
58     dv = tli->right.v - v;
59     dx = tli->right.x - tli->left.x;
60 
61     t_vtab = tli->vtab;
62     t_mask = tli->mask;
63     t_wlog = tli->bm.wlog;
64 
65     t_bits = tli->bm.bits;
66     gr_row = grd_bm.row;
67     start_pdest = grd_bm.bits + (gr_row * (tli->y));
68 
69     do {
70         if ((d = fix_ceil(tli->right.x) - fix_ceil(tli->left.x)) > 0) {
71             d = fix_ceil(tli->left.x) - tli->left.x;
72             du = fix_div(du, dx);
73             dv = fix_div(dv, dx);
74             u += fix_mul(du, d);
75             v += fix_mul(dv, d);
76 
77             // copy out tli-> stuff into locals
78             t_xl = fix_cint(tli->left.x);
79             t_xr = fix_cint(tli->right.x);
80             p_dest = start_pdest + t_xl;
81 
82             if (tli->bm.hlog == GRL_TRANS) {
83                 for (x = t_xl; x < t_xr; x++) {
84                     if (t_bits[t_vtab[fix_fint(v)] + fix_fint(u)])
85                         *p_dest = solid_color; // gr_fill_upixel(t_bits[k],x,y);
86                     p_dest++;
87                     u += du;
88                     v += dv;
89                 }
90             } else {
91                 for (x = t_xl; x < t_xr; x++) {
92                     if (t_bits[((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask])
93                         *p_dest = solid_color; // gr_fill_upixel(t_bits[k],x,y);
94                     p_dest++;
95                     u += du;
96                     v += dv;
97                 }
98             }
99         } else if (d < 0)
100             return TRUE; /* punt this tmap */
101 
102         u = (tli->left.u += tli->left.du);
103         tli->right.u += tli->right.du;
104         du = tli->right.u - u;
105         v = (tli->left.v += tli->left.dv);
106         tli->right.v += tli->right.dv;
107         dv = tli->right.v - v;
108         tli->left.x += tli->left.dx;
109         tli->right.x += tli->right.dx;
110         dx = tli->right.x - tli->left.x;
111         tli->y++;
112         start_pdest += gr_row;
113     } while (--(tli->n) > 0);
114 
115     return FALSE; /* tmap OK */
116 }
117 
gri_trans_solid_lin_umap_init(grs_tmap_loop_info * tli)118 void gri_trans_solid_lin_umap_init(grs_tmap_loop_info *tli) {
119     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
120         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
121         tli->bm.hlog = GRL_TRANS | GRL_LOG2;
122     } else {
123         tli->vtab = gr_make_vtab(&(tli->bm));
124         tli->bm.hlog = GRL_TRANS;
125     }
126     tli->loop_func = (void (*)())gri_trans_solid_lin_umap_loop;
127     tli->right_edge_func = (void (*)())gri_uvx_edge;
128     tli->left_edge_func = (void (*)())gri_uvx_edge;
129 }
130 
gri_trans_solid_floor_umap_loop(grs_tmap_loop_info * tli)131 int gri_trans_solid_floor_umap_loop(grs_tmap_loop_info *tli) {
132     fix u, v, du, dv, dx, d;
133     uchar solid_color;
134     int x;
135     // locals used to store copies of tli-> stuff, so its in registers on the PPC
136     int t_xl, t_xr, t_y, gr_row;
137     int32_t *t_vtab;
138     uchar *t_bits;
139     uchar *p_dest;
140     uchar temp_pix;
141     uchar t_wlog;
142     uint32_t t_mask;
143 
144     solid_color = tli->solid;
145     u = fix_div(tli->left.u, tli->w);
146     du = fix_div(tli->right.u, tli->w) - u;
147     v = fix_div(tli->left.v, tli->w);
148     dv = fix_div(tli->right.v, tli->w) - v;
149     dx = tli->right.x - tli->left.x;
150 
151     t_mask = tli->mask;
152     t_wlog = tli->bm.wlog;
153     t_vtab = tli->vtab;
154     t_bits = tli->bm.bits;
155     gr_row = grd_bm.row;
156 
157     do {
158         if ((d = fix_ceil(tli->right.x) - fix_ceil(tli->left.x)) > 0) {
159             d = fix_ceil(tli->left.x) - tli->left.x;
160             du = fix_div(du, dx);
161             u += fix_mul(du, d);
162             dv = fix_div(dv, dx);
163             v += fix_mul(dv, d);
164 
165             // copy out tli-> stuff into locals
166             t_xl = fix_cint(tli->left.x);
167             t_xr = fix_cint(tli->right.x);
168             t_y = tli->y;
169             p_dest = grd_bm.bits + (grd_bm.row * t_y) + t_xl;
170 
171             if (tli->bm.hlog == GRL_TRANS) {
172                 for (x = t_xl; x < t_xr; x++) {
173                     int k = t_vtab[fix_fint(v)] + fix_fint(u);
174                     if (t_bits[k])
175                         *p_dest = solid_color; // gr_fill_upixel(t_bits[k],x,t_y);
176                     p_dest++;
177                     u += du;
178                     v += dv;
179                 }
180             } else {
181                 for (x = t_xl; x < t_xr; x++) {
182                     int k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
183                     if (t_bits[k])
184                         *p_dest = solid_color; // gr_fill_upixel(t_bits[k],x,t_y);
185                     p_dest++;
186                     u += du;
187                     v += dv;
188                 }
189             }
190         } else if (d < 0)
191             return TRUE; /* punt this tmap */
192         tli->w += tli->dw;
193         u = fix_div((tli->left.u += tli->left.du), tli->w);
194         tli->right.u += tli->right.du;
195         du = fix_div(tli->right.u, tli->w) - u;
196         v = fix_div((tli->left.v += tli->left.dv), tli->w);
197         tli->right.v += tli->right.dv;
198         dv = fix_div(tli->right.v, tli->w) - v;
199         tli->left.x += tli->left.dx;
200         tli->right.x += tli->right.dx;
201         dx = tli->right.x - tli->left.x;
202         tli->y++;
203     } while (--(tli->n) > 0);
204     return FALSE; /* tmap OK */
205 }
206 
gri_trans_solid_floor_umap_init(grs_tmap_loop_info * tli)207 void gri_trans_solid_floor_umap_init(grs_tmap_loop_info *tli) {
208     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
209         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
210         tli->bm.hlog = GRL_TRANS | GRL_LOG2;
211     } else {
212         tli->vtab = gr_make_vtab(&(tli->bm));
213         tli->bm.hlog = GRL_TRANS;
214     }
215     tli->loop_func = (void (*)())gri_trans_solid_floor_umap_loop;
216     tli->left_edge_func = (void (*)())gri_uvwx_edge;
217     tli->right_edge_func = (void (*)())gri_uvwx_edge;
218 }
219 
gri_solid_wall_umap_loop(grs_tmap_loop_info * tli)220 int gri_solid_wall_umap_loop(grs_tmap_loop_info *tli) {
221     fix u, v, du, dv, dy, d;
222     uchar solid_color;
223 
224     // locals used to store copies of tli-> stuff, so its in registers on the PPC
225     int t_yl, t_yr;
226     int32_t *t_vtab;
227     uchar *t_bits;
228     uchar *p_dest;
229     uchar *t_clut;
230     uchar t_wlog;
231     uint32_t t_mask;
232     int32_t gr_row;
233     int y;
234 
235     solid_color = tli->solid;
236     u = fix_div(tli->left.u, tli->w);
237     du = fix_div(tli->right.u, tli->w) - u;
238     v = fix_div(tli->left.v, tli->w);
239     dv = fix_div(tli->right.v, tli->w) - v;
240     dy = tli->right.y - tli->left.y;
241 
242     t_bits = tli->bm.bits;
243     t_vtab = tli->vtab;
244     t_mask = tli->mask;
245     t_wlog = tli->bm.wlog;
246 
247     gr_row = grd_bm.row;
248 
249     // handle PowerPC loop
250     do {
251         if ((d = fix_ceil(tli->right.y) - fix_ceil(tli->left.y)) > 0) {
252 
253             d = fix_ceil(tli->left.y) - tli->left.y;
254             du = fix_div(du, dy);
255             dv = fix_div(dv, dy);
256             u += fix_mul(du, d);
257             v += fix_mul(dv, d);
258 
259             t_yl = fix_cint(tli->left.y);
260             t_yr = fix_cint(tli->right.y);
261             p_dest = grd_bm.bits + (gr_row * t_yl) + tli->x;
262 
263             if (tli->bm.hlog == GRL_TRANS) {
264                 for (y = t_yl; y < t_yr; y++) {
265                     int k = t_vtab[fix_fint(v)] + fix_fint(u);
266                     if (t_bits[k])
267                         *p_dest = solid_color; // gr_fill_upixel(t_bits[k],t_x,y);
268                     p_dest += gr_row;
269                     u += du;
270                     v += dv;
271                 }
272             } else {
273                 for (y = t_yl; y < t_yr; y++) {
274                     int k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
275                     if (t_bits[k])
276                         *p_dest = solid_color; // gr_fill_upixel(t_bits[k],t_x,y);
277                     p_dest += gr_row;
278                     u += du;
279                     v += dv;
280                 }
281             }
282         } else if (d < 0)
283             return TRUE; /* punt this tmap */
284 
285         tli->w += tli->dw;
286         u = fix_div((tli->left.u += tli->left.du), tli->w);
287         tli->right.u += tli->right.du;
288         du = fix_div(tli->right.u, tli->w) - u;
289         v = fix_div((tli->left.v += tli->left.dv), tli->w);
290         tli->right.v += tli->right.dv;
291         dv = fix_div(tli->right.v, tli->w) - v;
292         tli->left.y += tli->left.dy;
293         tli->right.y += tli->right.dy;
294         dy = tli->right.y - tli->left.y;
295         tli->x++;
296 
297     } while (--(tli->n) > 0);
298 
299     return FALSE;
300 }
301 
gri_trans_solid_wall_umap_init(grs_tmap_loop_info * tli)302 void gri_trans_solid_wall_umap_init(grs_tmap_loop_info *tli) {
303     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
304         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
305         tli->bm.hlog = GRL_TRANS | GRL_LOG2;
306     } else {
307         tli->vtab = gr_make_vtab(&(tli->bm));
308         tli->bm.hlog = GRL_TRANS;
309     }
310     tli->loop_func = (void (*)())gri_solid_wall_umap_loop;
311     tli->left_edge_func = (void (*)())gri_uvwy_edge;
312     tli->right_edge_func = (void (*)())gri_uvwy_edge;
313 }
314 
gri_trans_solid_per_umap_hscan_scanline(grs_per_info * pi,grs_bitmap * bm)315 void gri_trans_solid_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
316     int y_cint;
317     uchar *p;
318     uchar solid_color;
319 
320     // locals used to speed PPC code
321     fix l_u, l_v, l_du, l_dv, l_y_fix, l_scan_slope, l_dtl, l_dxl, l_dyl, l_dtr, l_dyr;
322     int l_x, l_xl, l_xr, l_xr0, l_u_mask, l_v_mask, l_v_shift;
323     int gr_row, temp_y;
324     uchar *bm_bits;
325 
326     solid_color = pi->fill_parm;
327     gr_row = grd_bm.row;
328     bm_bits = bm->bits;
329     l_dyr = pi->dyr;
330     l_dtr = pi->dtr;
331     l_dyl = pi->dyl;
332     l_dxl = pi->dxl;
333     l_dtl = pi->dtl;
334     l_scan_slope = pi->scan_slope;
335     l_y_fix = pi->y_fix;
336     l_v_shift = pi->v_shift;
337     l_v_mask = pi->v_mask;
338     l_u_mask = pi->u_mask;
339     l_xr0 = pi->xr0;
340     l_x = pi->x;
341     l_xl = pi->xl;
342     l_xr = pi->xr;
343     l_u = pi->u;
344     l_v = pi->v;
345     l_du = pi->du;
346     l_dv = pi->dv;
347 
348     l_y_fix = l_x * l_scan_slope + fix_make(pi->yp, 0xffff);
349     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
350     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
351     l_du = fix_div(pi->dunum, pi->denom);
352     l_dv = fix_div(pi->dvnum, pi->denom);
353     l_u += l_x * l_du;
354     l_v += l_x * l_dv;
355 
356     y_cint = fix_int(l_y_fix);
357     if (l_scan_slope < 0)
358         gr_row = -gr_row;
359 
360     p = grd_bm.bits + l_x + y_cint * grd_bm.row;
361     if (l_x < l_xl) {
362         fix test = l_x * l_dyl - y_cint * l_dxl + pi->cl;
363         for (; l_x < l_xl; l_x++) {
364             if (test <= 0) {
365                 int k = (l_u >> 16) & l_u_mask;
366                 k += (l_v >> l_v_shift) & l_v_mask;
367                 if (bm_bits[k])
368                     *p = solid_color; // gr_fill_upixel(bm_bits[k],l_x,y_cint);
369             }
370             temp_y = y_cint;
371             y_cint = fix_int(l_y_fix += l_scan_slope);
372             if (temp_y != y_cint) {
373                 test += l_dtl;
374                 p += gr_row;
375             } else
376                 test += l_dyl;
377 
378             p++;
379             l_u += l_du;
380             l_v += l_dv;
381         }
382     }
383 
384     for (; l_x < l_xr0; l_x++) {
385         int k = (l_u >> 16) & l_u_mask;
386         k += (l_v >> l_v_shift) & l_v_mask;
387         if (bm_bits[k])
388             *p = solid_color; // gr_fill_upixel(bm_bits[k],l_x,y_cint);
389         temp_y = y_cint;
390         y_cint = fix_int(l_y_fix += l_scan_slope);
391         if (temp_y != y_cint) // y_cint=fix_int((l_y_fix+=l_scan_slope));
392         {
393             temp_y -= y_cint;
394             p += gr_row;
395         }
396 
397         p++;
398         l_u += l_du;
399         l_v += l_dv;
400     }
401 
402     if (l_x < l_xr) {
403         fix test = l_x * l_dyr - y_cint * pi->dxr + pi->cr;
404         p = grd_bm.bits + l_x + y_cint * grd_bm.row;
405         for (; l_x < l_xr; l_x++) {
406             if (test >= 0) {
407                 int k = (l_u >> 16) & l_u_mask;
408                 k += (l_v >> l_v_shift) & l_v_mask;
409                 if (bm_bits[k])
410                     *p = solid_color; // gr_fill_upixel(bm_bits[k],l_x,y_cint);
411             }
412             temp_y = y_cint;
413             y_cint = fix_int(l_y_fix += l_scan_slope);
414             if (temp_y != y_cint) {
415                 test += l_dtr;
416                 p += gr_row;
417             } else
418                 test += l_dyr;
419 
420             p++;
421             l_u += l_du;
422             l_v += l_dv;
423         }
424     }
425 
426     pi->y_fix = l_y_fix;
427     pi->x = l_x;
428     pi->u = l_u;
429     pi->v = l_v;
430     pi->du = l_du;
431     pi->dv = l_dv;
432 }
433 
gri_trans_solid_per_umap_vscan_scanline(grs_per_info * pi,grs_bitmap * bm)434 void gri_trans_solid_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
435     int x_cint;
436     uchar solid_color;
437 
438     // locals used to speed PPC code
439     fix l_dxr, l_x_fix, l_u, l_v, l_du, l_dv, l_scan_slope, l_dtl, l_dxl, l_dyl, l_dtr, l_dyr;
440     int l_yl, l_yr0, l_yr, l_y, l_u_mask, l_v_mask, l_v_shift;
441     int gr_row, temp_x;
442     uchar *bm_bits;
443     uchar *p;
444 
445     solid_color = pi->fill_parm;
446     gr_row = grd_bm.row;
447     bm_bits = bm->bits;
448     l_dxr = pi->dxr;
449     l_x_fix = pi->x_fix;
450     l_y = pi->y;
451     l_yr = pi->yr;
452     l_yr0 = pi->yr0;
453     l_yl = pi->yl;
454     l_dyr = pi->dyr;
455     l_dtr = pi->dtr;
456     l_dyl = pi->dyl;
457     l_dxl = pi->dxl;
458     l_dtl = pi->dtl;
459     l_scan_slope = pi->scan_slope;
460     l_v_shift = pi->v_shift;
461     l_v_mask = pi->v_mask;
462     l_u_mask = pi->u_mask;
463     l_u = pi->u;
464     l_v = pi->v;
465     l_du = pi->du;
466     l_dv = pi->dv;
467 
468     l_x_fix = l_y * l_scan_slope + fix_make(pi->xp, 0xffff);
469 
470     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
471     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
472     l_du = fix_div(pi->dunum, pi->denom);
473     l_dv = fix_div(pi->dvnum, pi->denom);
474     l_u += l_y * l_du;
475     l_v += l_y * l_dv;
476 
477     x_cint = fix_int(l_x_fix);
478     p = grd_bm.bits + x_cint + l_y * gr_row;
479     if (l_y < l_yl) {
480         fix test = l_y * l_dxl - x_cint * l_dyl + pi->cl;
481         for (; l_y < l_yl; l_y++) {
482             if (test <= 0) {
483                 int k = (l_u >> 16) & l_u_mask;
484                 k += (l_v >> l_v_shift) & l_v_mask;
485                 if (bm_bits[k])
486                     *p = solid_color; // gr_fill_upixel(bm_bits[k],x_cint,l_y);
487             }
488             temp_x = x_cint;
489             x_cint = fix_int(l_x_fix += l_scan_slope);
490             if (temp_x != x_cint) {
491                 test += l_dtl;
492                 p -= (temp_x - x_cint);
493             } else
494                 test += l_dxl;
495 
496             p += gr_row;
497             l_u += l_du;
498             l_v += l_dv;
499         }
500     }
501 
502     for (; l_y < l_yr0; l_y++) {
503         int k = (l_u >> 16) & l_u_mask;
504         k += (l_v >> l_v_shift) & l_v_mask;
505         if (bm_bits[k])
506             *p = solid_color; // gr_fill_upixel(bm_bits[k],x_cint,l_y);
507 
508         temp_x = x_cint;
509         x_cint = fix_int(l_x_fix += l_scan_slope);
510         if (temp_x != x_cint)
511             p -= (temp_x - x_cint);
512 
513         p += gr_row;
514         l_u += l_du;
515         l_v += l_dv;
516     }
517 
518     if (l_y < l_yr) {
519         fix test = l_y * l_dxr - x_cint * l_dyr + pi->cr;
520         p = grd_bm.bits + x_cint + l_y * gr_row;
521         for (; l_y < l_yr; l_y++) {
522             if (test >= 0) {
523                 int k = (l_u >> 16) & l_u_mask;
524                 k += (l_v >> l_v_shift) & l_v_mask;
525                 if (bm_bits[k])
526                     *p = solid_color; // gr_fill_upixel(bm_bits[k],x_cint,l_y);
527             }
528 
529             temp_x = x_cint;
530             x_cint = fix_int(l_x_fix += l_scan_slope);
531             if (temp_x != x_cint) {
532                 test += l_dtr;
533                 p -= (temp_x - x_cint);
534             } else
535                 test += l_dxr;
536 
537             p += gr_row;
538             l_u += l_du;
539             l_v += l_dv;
540         }
541     }
542 
543     pi->x_fix = l_x_fix;
544     pi->y = l_y;
545     pi->u = l_u;
546     pi->v = l_v;
547     pi->du = l_du;
548     pi->dv = l_dv;
549 }
550 
551 extern void gri_per_umap_hscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
552 extern void gri_per_umap_vscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
553 
gri_trans_solid_per_umap_hscan_init(grs_bitmap * bm,grs_per_setup * ps)554 void gri_trans_solid_per_umap_hscan_init(grs_bitmap *bm, grs_per_setup *ps) {
555     ps->shell_func = (void (*)())gri_per_umap_hscan;
556     ps->scanline_func = (void (*)())gri_trans_solid_per_umap_hscan_scanline;
557 }
558 
gri_trans_solid_per_umap_vscan_init(grs_bitmap * bm,grs_per_setup * ps)559 void gri_trans_solid_per_umap_vscan_init(grs_bitmap *bm, grs_per_setup *ps) {
560     ps->shell_func = (void (*)())gri_per_umap_vscan;
561     ps->scanline_func = (void (*)())gri_trans_solid_per_umap_vscan_scanline;
562 }
563