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/FL8F.c $
21  * $Revision: 1.4 $
22  * $Author: kevin $
23  * $Date: 1994/08/16 12:50:13 $
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 int gri_floor_umap_loop(grs_tmap_loop_info *tli);
40 
gri_floor_umap_loop(grs_tmap_loop_info * tli)41 int gri_floor_umap_loop(grs_tmap_loop_info *tli) {
42     fix u, v, du, dv, dx, d;
43 
44     // locals used to store copies of tli-> stuff, so its in registers on the PPC
45     uchar t_wlog;
46     uint32_t t_mask;
47     int x, k;
48     uchar *t_bits;
49     uchar *p_dest;
50     fix inv;
51     uchar *t_clut;
52     uchar temp_pix;
53     int32_t *t_vtab;
54 
55 #if InvDiv
56     inv = fix_div(fix_make(1, 0), tli->w);
57     u = fix_mul_asm_safe(tli->left.u, inv);
58     du = fix_mul_asm_safe(tli->right.u, inv) - u;
59     v = fix_mul_asm_safe(tli->left.v, inv);
60     dv = fix_mul_asm_safe(tli->right.v, inv) - v;
61 #else
62     u = fix_div(tli->left.u, tli->w);
63     du = fix_div(tli->right.u, tli->w) - u;
64     v = fix_div(tli->left.v, tli->w);
65     dv = fix_div(tli->right.v, tli->w) - v;
66 #endif
67 
68     dx = tli->right.x - tli->left.x;
69 
70     t_clut = tli->clut;
71     t_mask = tli->mask;
72     t_wlog = tli->bm.wlog;
73     t_vtab = tli->vtab;
74     t_bits = tli->bm.bits;
75 
76     // handle PowerPC loop
77     do {
78         if ((d = fix_ceil(tli->right.x) - fix_ceil(tli->left.x)) > 0) {
79             d = fix_ceil(tli->left.x) - tli->left.x;
80 
81 #if InvDiv
82             inv = fix_div(fix_make(1, 0), dx);
83             du = fix_mul_asm_safe(du, inv);
84             dv = fix_mul_asm_safe(dv, inv);
85 #else
86             du = fix_div(du, dx);
87             dv = fix_div(dv, dx);
88 #endif
89 
90             u += fix_mul(du, d);
91             v += fix_mul(dv, d);
92 
93             // copy out tli-> stuff into locals
94             p_dest = grd_bm.bits + (grd_bm.row * tli->y) + fix_cint(tli->left.x);
95             x = fix_cint(tli->right.x) - fix_cint(tli->left.x);
96 
97             switch (tli->bm.hlog) {
98             case GRL_OPAQUE:
99                 for (; x > 0; x--) {
100                     k = t_vtab[fix_fint(v)] + fix_fint(u);
101                     *(p_dest++) = t_bits[k]; // gr_fill_upixel(t_bits[k],x,t_y);
102                     u += du;
103                     v += dv;
104                 }
105                 break;
106             case GRL_TRANS:
107                 for (; x > 0; x--) {
108                     k = t_vtab[fix_fint(v)] + fix_fint(u);
109                     temp_pix = t_bits[k];
110                     if (temp_pix != 0)
111                         *p_dest = temp_pix;
112                     // gr_fill_upixel(t_bits[k],x,t_y);
113                     p_dest++;
114                     u += du;
115                     v += dv;
116                 }
117                 break;
118             case GRL_OPAQUE | GRL_LOG2:
119                 for (; x > 0; x--) {
120                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
121                     *(p_dest++) = t_bits[k];
122                     // gr_fill_upixel(t_bits[k],x,t_y);
123                     u += du;
124                     v += dv;
125                 }
126                 break;
127             case GRL_TRANS | GRL_LOG2:
128                 for (; x > 0; x--) {
129                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
130                     temp_pix = t_bits[k];
131                     if (temp_pix != 0)
132                         *p_dest = temp_pix;
133                     // gr_fill_upixel(t_bits[k],x,t_y);
134                     p_dest++;
135                     u += du;
136                     v += dv;
137                 }
138                 break;
139             case GRL_OPAQUE | GRL_CLUT:
140                 for (; x > 0; x--) {
141                     k = t_vtab[fix_fint(v)] + fix_fint(u);
142                     *(p_dest++) = t_clut[t_bits[k]];
143                     // gr_fill_upixel(tli->clut[t_bits[k]],x,t_y);
144                     u += du;
145                     v += dv;
146                 }
147                 break;
148             case GRL_TRANS | GRL_CLUT:
149                 for (; x > 0; x--) {
150                     k = t_vtab[fix_fint(v)] + fix_fint(u);
151                     k = t_bits[k];
152                     if (k != 0)
153                         *p_dest = t_clut[k];
154                     // gr_fill_upixel(tli->clut[k],x,t_y);
155                     p_dest++;
156                     u += du;
157                     v += dv;
158                 }
159                 break;
160             case GRL_OPAQUE | GRL_LOG2 | GRL_CLUT:
161                 while (((intptr_t)p_dest & 3) != 0) {
162                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
163                     *(p_dest++) = t_clut[t_bits[k]];
164                     // gr_fill_upixel(tli->clut[t_bits[k]],x,t_y);
165                     u += du;
166                     v += dv;
167                     x--;
168                 }
169 
170                 while (x > 0) {
171                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
172                     inv = t_clut[t_bits[k]];
173                     // gr_fill_upixel(tli->clut[t_bits[k]],x,t_y);
174                     u += du;
175                     v += dv;
176                     *p_dest = inv;
177                     p_dest++;
178                     x--;
179                 }
180 
181                 for (; x > 0; x--) {
182                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
183                     *(p_dest++) = t_clut[t_bits[k]];
184                     // gr_fill_upixel(tli->clut[t_bits[k]],x,t_y);
185                     u += du;
186                     v += dv;
187                 }
188                 break;
189             case GRL_TRANS | GRL_LOG2 | GRL_CLUT:
190                 for (; x > 0; x--) {
191                     k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask;
192                     k = t_bits[k];
193                     if (k != 0)
194                         *p_dest = t_clut[k]; // gr_fill_upixel(tli->clut[k],x,t_y);
195                     p_dest++;
196                     u += du;
197                     v += dv;
198                 }
199             }
200         } else if (d < 0)
201             return TRUE; /* punt this tmap */
202 
203         tli->w += tli->dw;
204 
205 #if InvDiv
206         inv = fix_div(fix_make(1, 0), tli->w);
207         u = fix_mul_asm_safe((tli->left.u += tli->left.du), inv);
208         tli->right.u += tli->right.du;
209         du = fix_mul_asm_safe(tli->right.u, inv) - u;
210         v = fix_mul_asm_safe((tli->left.v += tli->left.dv), inv);
211         tli->right.v += tli->right.dv;
212         dv = fix_mul_asm_safe(tli->right.v, inv) - v;
213 #else
214         u = fix_div((tli->left.u += tli->left.du), tli->w);
215         tli->right.u += tli->right.du;
216         du = fix_div(tli->right.u, tli->w) - u;
217         v = fix_div((tli->left.v += tli->left.dv), tli->w);
218         tli->right.v += tli->right.dv;
219         dv = fix_div(tli->right.v, tli->w) - v;
220 #endif
221 
222         tli->left.x += tli->left.dx;
223         tli->right.x += tli->right.dx;
224         dx = tli->right.x - tli->left.x;
225         tli->y++;
226     } while (--(tli->n) > 0);
227     return FALSE; /* tmap OK */
228 }
229 
gri_trans_floor_umap_init(grs_tmap_loop_info * tli)230 void gri_trans_floor_umap_init(grs_tmap_loop_info *tli) {
231     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
232         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
233         tli->bm.hlog = GRL_TRANS | GRL_LOG2;
234     } else {
235         tli->vtab = gr_make_vtab(&(tli->bm));
236         tli->bm.hlog = GRL_TRANS;
237     }
238     tli->loop_func = (void (*)())gri_floor_umap_loop;
239     tli->left_edge_func = (void (*)())gri_uvwx_edge;
240     tli->right_edge_func = (void (*)())gri_uvwx_edge;
241 }
242 
gri_opaque_floor_umap_init(grs_tmap_loop_info * tli)243 void gri_opaque_floor_umap_init(grs_tmap_loop_info *tli) {
244     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
245         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
246         tli->bm.hlog = GRL_OPAQUE | GRL_LOG2;
247     } else {
248         tli->vtab = gr_make_vtab(&(tli->bm));
249         tli->bm.hlog = GRL_OPAQUE;
250     }
251     tli->loop_func = (void (*)())gri_floor_umap_loop;
252     tli->left_edge_func = (void (*)())gri_uvwx_edge;
253     tli->right_edge_func = (void (*)())gri_uvwx_edge;
254 }
255 
gri_trans_clut_floor_umap_init(grs_tmap_loop_info * tli)256 void gri_trans_clut_floor_umap_init(grs_tmap_loop_info *tli) {
257     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
258         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
259         tli->bm.hlog = GRL_TRANS | GRL_LOG2 | GRL_CLUT;
260     } else {
261         tli->vtab = gr_make_vtab(&(tli->bm));
262         tli->bm.hlog = GRL_TRANS | GRL_CLUT;
263     }
264     tli->loop_func = (void (*)())gri_floor_umap_loop;
265     tli->left_edge_func = (void (*)())gri_uvwx_edge;
266     tli->right_edge_func = (void (*)())gri_uvwx_edge;
267 }
268 
gri_opaque_clut_floor_umap_init(grs_tmap_loop_info * tli)269 void gri_opaque_clut_floor_umap_init(grs_tmap_loop_info *tli) {
270     if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) {
271         tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1;
272         tli->bm.hlog = GRL_OPAQUE | GRL_LOG2 | GRL_CLUT;
273     } else {
274         tli->vtab = gr_make_vtab(&(tli->bm));
275         tli->bm.hlog = GRL_OPAQUE | GRL_CLUT;
276     }
277     tli->loop_func = (void (*)())gri_floor_umap_loop;
278     tli->left_edge_func = (void (*)())gri_uvwx_edge;
279     tli->right_edge_func = (void (*)())gri_uvwx_edge;
280 }
281