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/FL8CTP.c $
21  * $Revision: 1.2 $
22  * $Author: kevin $
23  * $Date: 1994/08/16 12:57:23 $
24  *
25  * full perspective texture mapper.
26  * scanline processors.
27  *
28  */
29 
30 #include "cnvdat.h"
31 #include "fl8tmapdv.h"
32 #include "pertyp.h"
33 #include "plytyp.h"
34 
35 // prototypes
36 void gri_trans_clut_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm);
37 void gri_trans_clut_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm);
38 void gri_trans_clut_per_umap_hscan_init(grs_bitmap *bm, grs_per_setup *ps);
39 void gri_trans_clut_per_umap_vscan_init(grs_bitmap *bm, grs_per_setup *ps);
40 
gri_trans_clut_per_umap_hscan_scanline(grs_per_info * pi,grs_bitmap * bm)41 void gri_trans_clut_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
42     register int k, y_cint;
43     uchar *p;
44 
45     // ltc_als used to speed PPC code
46     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;
47     int l_x, l_xl, l_xr, l_xr0, l_u_mask, l_v_mask, l_v_shift;
48     int gr_row, temp_y;
49     uchar *bm_bits;
50     uchar *t_clut, temp_pix;
51 
52     t_clut = pi->clut;
53     gr_row = grd_bm.row;
54     bm_bits = bm->bits;
55     l_dyr = pi->dyr;
56     l_dtr = pi->dtr;
57     l_dyl = pi->dyl;
58     l_dxl = pi->dxl;
59     l_dtl = pi->dtl;
60     l_scan_slope = pi->scan_slope;
61     l_y_fix = pi->y_fix;
62     l_v_shift = pi->v_shift;
63     l_v_mask = pi->v_mask;
64     l_u_mask = pi->u_mask;
65     l_xr0 = pi->xr0;
66     l_x = pi->x;
67     l_xl = pi->xl;
68     l_xr = pi->xr;
69     l_u = pi->u;
70     l_v = pi->v;
71     l_du = pi->du;
72     l_dv = pi->dv;
73 
74     l_y_fix = l_x * l_scan_slope + fix_make(pi->yp, 0xffff);
75 
76 #if InvDiv
77     k = fix_div(fix_make(1, 0), pi->denom);
78     l_u = pi->u0 + fix_mul_asm_safe(pi->unum, k);
79     l_v = pi->v0 + fix_mul_asm_safe(pi->vnum, k);
80     l_du = fix_mul_asm_safe(pi->dunum, k);
81     l_dv = fix_mul_asm_safe(pi->dvnum, k);
82 #else
83     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
84     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
85     l_du = fix_div(pi->dunum, pi->denom);
86     l_dv = fix_div(pi->dvnum, pi->denom);
87 #endif
88 
89     l_u += l_x * l_du;
90     l_v += l_x * l_dv;
91 
92     y_cint = fix_int(l_y_fix);
93     if (l_scan_slope < 0)
94         gr_row = -gr_row;
95 
96     p = grd_bm.bits + l_x + y_cint * grd_bm.row;
97     if (l_x < l_xl) {
98         fix test = l_x * l_dyl - y_cint * l_dxl + pi->cl;
99         for (; l_x < l_xl; l_x++) {
100             if (test <= 0) {
101                 k = (l_u >> 16) & l_u_mask;
102                 k += (l_v >> l_v_shift) & l_v_mask;
103                 temp_pix = bm_bits[k];
104                 if (temp_pix != 0)
105                     *p = t_clut[temp_pix]; // gr_fill_upixel(t_clut[bm_bits[k]],l_x,y_cint);
106             }
107             temp_y = y_cint;
108             y_cint = fix_int(l_y_fix += l_scan_slope);
109 
110             if (temp_y != y_cint) {
111                 p += gr_row;
112                 test += l_dtl;
113             } else
114                 test += l_dyl;
115 
116             p++;
117             l_u += l_du;
118             l_v += l_dv;
119         }
120     }
121 
122     for (; l_x < l_xr0; l_x++) {
123         k = (l_u >> 16) & l_u_mask;
124         k += (l_v >> l_v_shift) & l_v_mask;
125         temp_pix = bm_bits[k];
126         if (temp_pix != 0)
127             *p = t_clut[temp_pix]; // gr_fill_upixel(t_clut[bm_bits[k]],l_x,y_cint);
128         temp_y = y_cint;
129         y_cint = fix_int(l_y_fix += l_scan_slope);
130         if (temp_y != y_cint)
131             p += gr_row;
132 
133         p++;
134         l_u += l_du;
135         l_v += l_dv;
136     }
137 
138     if (l_x < l_xr) {
139         fix test = l_x * l_dyr - y_cint * pi->dxr + pi->cr;
140         p = grd_bm.bits + l_x + y_cint * grd_bm.row;
141         for (; l_x < l_xr; l_x++) {
142             if (test >= 0) {
143                 k = (l_u >> 16) & l_u_mask;
144                 k += (l_v >> l_v_shift) & l_v_mask;
145                 temp_pix = bm_bits[k];
146                 if (temp_pix != 0)
147                     *p = t_clut[temp_pix]; // gr_fill_upixel(t_clut[bm_bits[k]],l_x,y_cint);
148             }
149             temp_y = y_cint;
150             y_cint = fix_int(l_y_fix += l_scan_slope);
151 
152             if (temp_y != y_cint) {
153                 p += gr_row;
154                 test += l_dtr;
155             } else
156                 test += l_dyr;
157 
158             p++;
159             l_u += l_du;
160             l_v += l_dv;
161         }
162     }
163 
164     pi->y_fix = l_y_fix;
165     pi->x = l_x;
166     pi->u = l_u;
167     pi->v = l_v;
168     pi->du = l_du;
169     pi->dv = l_dv;
170 }
171 
gri_trans_clut_per_umap_vscan_scanline(grs_per_info * pi,grs_bitmap * bm)172 void gri_trans_clut_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
173     register int k, x_cint;
174 
175     // locals used to speed PPC code
176     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;
177     int l_yl, l_yr0, l_yr, l_y, l_u_mask, l_v_mask, l_v_shift;
178     int gr_row, temp_x;
179     uchar *bm_bits;
180     uchar *p;
181     uchar *t_clut, temp_pix;
182 
183     t_clut = pi->clut;
184     gr_row = grd_bm.row;
185     bm_bits = bm->bits;
186     l_dxr = pi->dxr;
187     l_x_fix = pi->x_fix;
188     l_y = pi->y;
189     l_yr = pi->yr;
190     l_yr0 = pi->yr0;
191     l_yl = pi->yl;
192     l_dyr = pi->dyr;
193     l_dtr = pi->dtr;
194     l_dyl = pi->dyl;
195     l_dxl = pi->dxl;
196     l_dtl = pi->dtl;
197     l_scan_slope = pi->scan_slope;
198     l_v_shift = pi->v_shift;
199     l_v_mask = pi->v_mask;
200     l_u_mask = pi->u_mask;
201     l_u = pi->u;
202     l_v = pi->v;
203     l_du = pi->du;
204     l_dv = pi->dv;
205 
206     l_x_fix = l_y * l_scan_slope + fix_make(pi->xp, 0xffff);
207 
208 #if InvDiv
209     k = fix_div(fix_make(1, 0), pi->denom);
210     l_u = pi->u0 + fix_mul_asm_safe(pi->unum, k);
211     l_v = pi->v0 + fix_mul_asm_safe(pi->vnum, k);
212     l_du = fix_mul_asm_safe(pi->dunum, k);
213     l_dv = fix_mul_asm_safe(pi->dvnum, k);
214 #else
215     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
216     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
217     l_du = fix_div(pi->dunum, pi->denom);
218     l_dv = fix_div(pi->dvnum, pi->denom);
219 #endif
220 
221     l_u += l_y * l_du;
222     l_v += l_y * l_dv;
223 
224     x_cint = fix_int(l_x_fix);
225     p = grd_bm.bits + x_cint + l_y * gr_row;
226     if (l_y < l_yl) {
227         fix test = l_y * l_dxl - x_cint * l_dyl + pi->cl;
228         for (; l_y < l_yl; l_y++) {
229             if (test <= 0) {
230                 k = (l_u >> 16) & l_u_mask;
231                 k += (l_v >> l_v_shift) & l_v_mask;
232                 temp_pix = bm_bits[k];
233                 if (temp_pix != 0)
234                     *p = t_clut[temp_pix]; // gr_fill_upixel(t_clut[bm_bits[k]],x_cint,l_y);
235             }
236             temp_x = x_cint;
237             x_cint = fix_int(l_x_fix += l_scan_slope);
238             if (temp_x != x_cint) {
239                 test += l_dtl;
240                 p -= (temp_x - x_cint);
241             } else
242                 test += l_dxl;
243 
244             p += gr_row;
245             l_u += l_du;
246             l_v += l_dv;
247         }
248     }
249 
250     for (; l_y < l_yr0; l_y++) {
251         k = (l_u >> 16) & l_u_mask;
252         k += (l_v >> l_v_shift) & l_v_mask;
253         temp_pix = bm_bits[k];
254         if (temp_pix != 0)
255             *p = t_clut[temp_pix]; // gr_fill_upixel(t_clut[bm_bits[k]],x_cint,l_y);
256 
257         temp_x = x_cint;
258         x_cint = fix_int(l_x_fix += l_scan_slope);
259         if (temp_x != x_cint)
260             p -= (temp_x - x_cint);
261 
262         p += gr_row;
263         l_u += l_du;
264         l_v += l_dv;
265     }
266 
267     if (l_y < l_yr) {
268         fix test = l_y * l_dxr - x_cint * l_dyr + pi->cr;
269         p = grd_bm.bits + x_cint + l_y * gr_row;
270         for (; l_y < l_yr; l_y++) {
271             if (test >= 0) {
272                 k = (l_u >> 16) & l_u_mask;
273                 k += (l_v >> l_v_shift) & l_v_mask;
274                 temp_pix = bm_bits[k];
275                 if (temp_pix != 0)
276                     *p = t_clut[temp_pix]; // gr_fill_upixel(t_clut[bm_bits[k]],x_cint,l_y);
277             }
278 
279             temp_x = x_cint;
280             x_cint = fix_int(l_x_fix += l_scan_slope);
281             if (temp_x != x_cint) {
282                 test += l_dtr;
283                 p -= (temp_x - x_cint);
284             } else
285                 test += l_dxr;
286 
287             p += gr_row;
288             l_u += l_du;
289             l_v += l_dv;
290         }
291     }
292 
293     pi->x_fix = l_x_fix;
294     pi->y = l_y;
295     pi->u = l_u;
296     pi->v = l_v;
297     pi->du = l_du;
298     pi->dv = l_dv;
299 }
300 
301 extern void gri_per_umap_hscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
302 extern void gri_per_umap_vscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
303 
gri_trans_clut_per_umap_hscan_init(grs_bitmap * bm,grs_per_setup * ps)304 void gri_trans_clut_per_umap_hscan_init(grs_bitmap *bm, grs_per_setup *ps) {
305     ps->shell_func = (void (*)())gri_per_umap_hscan;
306     ps->scanline_func = (void (*)())gri_trans_clut_per_umap_hscan_scanline;
307 }
308 
gri_trans_clut_per_umap_vscan_init(grs_bitmap * bm,grs_per_setup * ps)309 void gri_trans_clut_per_umap_vscan_init(grs_bitmap *bm, grs_per_setup *ps) {
310     ps->shell_func = (void (*)())gri_per_umap_vscan;
311     ps->scanline_func = (void (*)())gri_trans_clut_per_umap_vscan_scanline;
312 }
313