1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /******************************************************************************
4
5
6 SGI/Nintendo Reality Display Texture Fetch Unit (TF)
7 -------------------
8
9 by Ryan Holtz
10 based on initial C code by Ville Linde
11 contains additional improvements from angrylion, Ziggy, Gonetz and Orkin
12
13
14 ******************************************************************************/
15
16 #include "emu.h"
17 #include "includes/n64.h"
18 #include "video/rdptpipe.h"
19 #include "video/n64.h"
20 #include "video/rgbutil.h"
21
22 #define RELATIVE(x, y) ((((x) >> 3) - (y)) << 3) | (x & 7);
23
set_machine(running_machine & machine)24 void n64_texture_pipe_t::set_machine(running_machine &machine)
25 {
26 n64_state* state = machine.driver_data<n64_state>();
27
28 m_rdp = state->rdp();
29
30 for(int32_t i = 0; i < 0x10000; i++)
31 {
32 m_expand_16to32_table[i] = color_t((i & 1) ? 0xff : 0x00, m_rdp->m_replicated_rgba[(i >> 11) & 0x1f], m_rdp->m_replicated_rgba[(i >> 6) & 0x1f], m_rdp->m_replicated_rgba[(i >> 1) & 0x1f]);
33 }
34
35 for(uint32_t i = 0; i < 0x80000; i++)
36 {
37 if (i & 0x40000)
38 {
39 m_lod_lookup[i] = 0x7fff;
40 }
41 else if (i & 0x20000)
42 {
43 m_lod_lookup[i] = 0x8000;
44 }
45 else
46 {
47 if ((i & 0x18000) == 0x8000)
48 {
49 m_lod_lookup[i] = 0x7fff;
50 }
51 else if ((i & 0x18000) == 0x10000)
52 {
53 m_lod_lookup[i] = 0x8000;
54 }
55 else
56 {
57 m_lod_lookup[i] = i & 0xffff;
58 }
59 }
60 }
61
62 m_st2_add.set(1, 0, 1, 0);
63 m_v1.set(1, 1, 1, 1);
64 }
65
mask(rgbaint_t & sstt,const n64_tile_t & tile)66 void n64_texture_pipe_t::mask(rgbaint_t& sstt, const n64_tile_t& tile)
67 {
68 uint32_t s_mask_bits = m_maskbits_table[tile.mask_s];
69 uint32_t t_mask_bits = m_maskbits_table[tile.mask_t];
70 rgbaint_t maskbits(s_mask_bits, s_mask_bits, t_mask_bits, t_mask_bits);
71
72 rgbaint_t do_wrap(sstt);
73 do_wrap.sra(tile.wrapped_mask);
74 do_wrap.and_reg(m_v1);
75 do_wrap.cmpeq(m_v1);
76 do_wrap.and_reg(tile.mm);
77
78 rgbaint_t wrapped(sstt);
79 wrapped.xor_reg(do_wrap);
80 wrapped.and_reg(maskbits);
81 wrapped.and_reg(tile.mask);
82 sstt.and_reg(tile.invmask);
83 sstt.or_reg(wrapped);
84 }
85
shift_cycle(rgbaint_t & st,const n64_tile_t & tile)86 rgbaint_t n64_texture_pipe_t::shift_cycle(rgbaint_t& st, const n64_tile_t& tile)
87 {
88 st.sign_extend(0x00008000, 0xffff8000);
89 st.sra(tile.rshift);
90 st.shl(tile.lshift);
91
92 rgbaint_t maxst(st);
93 maxst.sra_imm(3);
94 rgbaint_t maxst_eq(maxst);
95 maxst.cmpgt(tile.sth);
96 maxst_eq.cmpeq(tile.sth);
97 maxst.or_reg(maxst_eq);
98
99 rgbaint_t stlsb(st);
100 stlsb.and_imm(7);
101
102 st.sra_imm(3);
103 st.sub(tile.stl);
104 st.shl_imm(3);
105 st.or_reg(stlsb);
106
107 return maxst;
108 }
109
shift_copy(rgbaint_t & st,const n64_tile_t & tile)110 inline void n64_texture_pipe_t::shift_copy(rgbaint_t& st, const n64_tile_t& tile)
111 {
112 st.shr(tile.rshift);
113 st.shl(tile.lshift);
114 }
115
clamp_cycle(rgbaint_t & st,rgbaint_t & stfrac,rgbaint_t & maxst,const int32_t tilenum,const n64_tile_t & tile,rdp_span_aux * userdata)116 void n64_texture_pipe_t::clamp_cycle(rgbaint_t& st, rgbaint_t& stfrac, rgbaint_t& maxst, const int32_t tilenum, const n64_tile_t& tile, rdp_span_aux* userdata)
117 {
118 rgbaint_t not_clamp(tile.clamp_st);
119 not_clamp.xor_imm(0xffffffff);
120
121 rgbaint_t highbit_mask(0x10000, 0x10000, 0x10000, 0x10000);
122 rgbaint_t highbit(st);
123 highbit.and_reg(highbit_mask);
124 highbit.cmpeq(highbit_mask);
125
126 rgbaint_t not_highbit(highbit);
127 not_highbit.xor_imm(0xffffffff);
128
129 rgbaint_t not_maxst(maxst);
130 not_maxst.xor_imm(0xffffffff);
131 not_maxst.and_reg(not_highbit);
132 not_maxst.or_reg(not_clamp);
133
134 rgbaint_t shifted_st(st);
135 shifted_st.sign_extend(0x00010000, 0xffff0000);
136 shifted_st.shr_imm(5);
137 shifted_st.and_imm(0x1fff);
138 shifted_st.and_reg(not_maxst);
139 stfrac.and_reg(not_maxst);
140
141 rgbaint_t clamp_diff(userdata->m_clamp_diff[tilenum]);
142 clamp_diff.and_reg(tile.clamp_st);
143 clamp_diff.and_reg(maxst);
144
145 st.set(shifted_st);
146 st.or_reg(clamp_diff);
147 }
148
clamp_cycle_light(rgbaint_t & st,rgbaint_t & maxst,const int32_t tilenum,const n64_tile_t & tile,rdp_span_aux * userdata)149 void n64_texture_pipe_t::clamp_cycle_light(rgbaint_t& st, rgbaint_t& maxst, const int32_t tilenum, const n64_tile_t& tile, rdp_span_aux* userdata)
150 {
151 rgbaint_t not_clamp(tile.clamp_st);
152 not_clamp.xor_imm(0xffffffff);
153
154 rgbaint_t highbit_mask(0x10000, 0x10000, 0x10000, 0x10000);
155 rgbaint_t highbit(st);
156 highbit.and_reg(highbit_mask);
157 highbit.cmpeq(highbit_mask);
158
159 rgbaint_t not_highbit(highbit);
160 not_highbit.xor_imm(0xffffffff);
161
162 rgbaint_t not_maxst(maxst);
163 not_maxst.xor_imm(0xffffffff);
164 not_maxst.and_reg(not_highbit);
165 not_maxst.or_reg(not_clamp);
166
167 rgbaint_t shifted_st(st);
168 shifted_st.sign_extend(0x00010000, 0xffff0000);
169 shifted_st.shr_imm(5);
170 shifted_st.and_imm(0x1fff);
171 shifted_st.and_reg(not_maxst);
172
173 rgbaint_t clamp_diff(userdata->m_clamp_diff[tilenum]);
174 clamp_diff.and_reg(tile.clamp_st);
175 clamp_diff.and_reg(maxst);
176
177 st.set(shifted_st);
178 st.or_reg(clamp_diff);
179 }
180
cycle_nearest(color_t * TEX,color_t * prev,int32_t SSS,int32_t SST,uint32_t tilenum,uint32_t cycle,rdp_span_aux * userdata,const rdp_poly_state & object)181 void n64_texture_pipe_t::cycle_nearest(color_t* TEX, color_t* prev, int32_t SSS, int32_t SST, uint32_t tilenum, uint32_t cycle, rdp_span_aux* userdata, const rdp_poly_state& object)
182 {
183 const n64_tile_t& tile = object.m_tiles[tilenum];
184 const uint32_t index = (tile.format << 4) | (tile.size << 2) | ((uint32_t) object.m_other_modes.en_tlut << 1) | (uint32_t) object.m_other_modes.tlut_type;
185
186 rgbaint_t st(0, SSS, 0, SST);
187 rgbaint_t maxst = shift_cycle(st, tile);
188 clamp_cycle_light(st, maxst, tilenum, tile, userdata);
189 mask(st, tile);
190
191 uint32_t tbase = tile.tmem + ((tile.line * st.get_b32()) & 0x1ff);
192
193 rgbaint_t t0;
194 ((this)->*(m_texel_fetch[index]))(t0, st.get_r32(), st.get_b32(), tbase, tile.palette, userdata);
195 if (object.m_other_modes.convert_one && cycle)
196 {
197 t0.set(*prev);
198 }
199
200 t0.sign_extend(0x00000100, 0xffffff00);
201
202 rgbaint_t k1r(m_rdp->get_k1());
203 k1r.mul_imm(t0.get_r32());
204
205 TEX->set(m_rdp->get_k023());
206 TEX->mul_imm(t0.get_g32());
207 TEX->add(k1r);
208 TEX->add_imm(0x80);
209 TEX->shr_imm(8);
210 TEX->add_imm(t0.get_b32());
211 TEX->and_imm(0x1ff);
212 }
213
cycle_nearest_lerp(color_t * TEX,color_t * prev,int32_t SSS,int32_t SST,uint32_t tilenum,uint32_t cycle,rdp_span_aux * userdata,const rdp_poly_state & object)214 void n64_texture_pipe_t::cycle_nearest_lerp(color_t* TEX, color_t* prev, int32_t SSS, int32_t SST, uint32_t tilenum, uint32_t cycle, rdp_span_aux* userdata, const rdp_poly_state& object)
215 {
216 const n64_tile_t& tile = object.m_tiles[tilenum];
217 const uint32_t index = (tile.format << 4) | (tile.size << 2) | ((uint32_t) object.m_other_modes.en_tlut << 1) | (uint32_t) object.m_other_modes.tlut_type;
218
219 rgbaint_t st(0, SSS, 0, SST);
220 rgbaint_t maxst = shift_cycle(st, tile);
221 clamp_cycle_light(st, maxst, tilenum, tile, userdata);
222 mask(st, tile);
223
224 uint32_t tbase = tile.tmem + ((tile.line * st.get_b32()) & 0x1ff);
225
226 ((this)->*(m_texel_fetch[index]))(*TEX, st.get_r32(), st.get_b32(), tbase, tile.palette, userdata);
227 }
228
cycle_linear(color_t * TEX,color_t * prev,int32_t SSS,int32_t SST,uint32_t tilenum,uint32_t cycle,rdp_span_aux * userdata,const rdp_poly_state & object)229 void n64_texture_pipe_t::cycle_linear(color_t* TEX, color_t* prev, int32_t SSS, int32_t SST, uint32_t tilenum, uint32_t cycle, rdp_span_aux* userdata, const rdp_poly_state& object)
230 {
231 const n64_tile_t& tile = object.m_tiles[tilenum];
232 const uint32_t index = (tile.format << 4) | (tile.size << 2) | ((uint32_t) object.m_other_modes.en_tlut << 1) | (uint32_t) object.m_other_modes.tlut_type;
233
234 rgbaint_t st(0, SSS, 0, SST);
235 rgbaint_t maxst = shift_cycle(st, tile);
236
237 clamp_cycle_light(st, maxst, tilenum, tile, userdata);
238
239 mask(st, tile);
240
241 const uint32_t tbase = tile.tmem + ((tile.line * st.get_b32()) & 0x1ff);
242
243 rgbaint_t t0;
244 ((this)->*(m_texel_fetch[index]))(t0, st.get_r32(), st.get_b32(), tbase, tile.palette, userdata);
245 if (object.m_other_modes.convert_one && cycle)
246 {
247 t0.set(*prev);
248 }
249
250 t0.sign_extend(0x00000100, 0xffffff00);
251
252 rgbaint_t k1r(m_rdp->get_k1());
253 k1r.mul_imm(t0.get_r32());
254
255 TEX->set(m_rdp->get_k023());
256 TEX->mul_imm(t0.get_g32());
257 TEX->add(k1r);
258 TEX->add_imm(0x80);
259 TEX->shr_imm(8);
260 TEX->add_imm(t0.get_b32());
261 TEX->and_imm(0x1ff);
262 }
263
cycle_linear_lerp(color_t * TEX,color_t * prev,int32_t SSS,int32_t SST,uint32_t tilenum,uint32_t cycle,rdp_span_aux * userdata,const rdp_poly_state & object)264 void n64_texture_pipe_t::cycle_linear_lerp(color_t* TEX, color_t* prev, int32_t SSS, int32_t SST, uint32_t tilenum, uint32_t cycle, rdp_span_aux* userdata, const rdp_poly_state& object)
265 {
266 const n64_tile_t& tile = object.m_tiles[tilenum];
267
268 uint32_t tpal = tile.palette;
269 uint32_t index = (tile.format << 4) | (tile.size << 2) | ((uint32_t) object.m_other_modes.en_tlut << 1) | (uint32_t) object.m_other_modes.tlut_type;
270
271 rgbaint_t sstt(SSS, SSS, SST, SST);
272 rgbaint_t maxst = shift_cycle(sstt, tile);
273 rgbaint_t stfrac = sstt;
274 stfrac.and_imm(0x1f);
275
276 clamp_cycle(sstt, stfrac, maxst, tilenum, tile, userdata);
277
278 sstt.add(m_st2_add);
279
280 mask(sstt, tile);
281
282 const uint32_t tbase1 = tile.tmem + ((tile.line * sstt.get_b32()) & 0x1ff);
283 const uint32_t tbase2 = tile.tmem + ((tile.line * sstt.get_g32()) & 0x1ff);
284
285 bool upper = ((stfrac.get_r32() + stfrac.get_b32()) >= 0x20);
286
287 rgbaint_t invstf(stfrac);
288 if (upper)
289 {
290 invstf.subr_imm(0x20);
291 invstf.shl_imm(3);
292 }
293
294 stfrac.shl_imm(3);
295
296 bool center = (stfrac.get_r32() == 0x10) && (stfrac.get_b32() == 0x10) && object.m_other_modes.mid_texel;
297
298 rgbaint_t t2;
299 ((this)->*(m_texel_fetch[index]))(*TEX, sstt.get_a32(), sstt.get_b32(), tbase1, tpal, userdata);
300 ((this)->*(m_texel_fetch[index]))(t2, sstt.get_r32(), sstt.get_g32(), tbase2, tpal, userdata);
301
302 if (!center)
303 {
304 if (upper)
305 {
306 rgbaint_t t3;
307 ((this)->*(m_texel_fetch[index]))(t3, sstt.get_a32(), sstt.get_g32(), tbase2, tpal, userdata);
308
309 TEX->sub(t3);
310 t2.sub(t3);
311
312 TEX->mul_imm(invstf.get_b32());
313 t2.mul_imm(invstf.get_r32());
314
315 TEX->add(t2);
316 TEX->add_imm(0x0080);
317 TEX->sra_imm(8);
318 TEX->add(t3);
319 }
320 else
321 {
322 rgbaint_t t0;
323 ((this)->*(m_texel_fetch[index]))(t0, sstt.get_r32(), sstt.get_b32(), tbase1, tpal, userdata);
324
325 TEX->sub(t0);
326 t2.sub(t0);
327
328 TEX->mul_imm(stfrac.get_r32());
329 t2.mul_imm(stfrac.get_b32());
330
331 TEX->add(t2);
332 TEX->add_imm(0x80);
333 TEX->sra_imm(8);
334 TEX->add(t0);
335 }
336 }
337 else
338 {
339 rgbaint_t t0, t3;
340 ((this)->*(m_texel_fetch[index]))(t0, sstt.get_r32(), sstt.get_b32(), tbase1, tpal, userdata);
341 ((this)->*(m_texel_fetch[index]))(t3, sstt.get_a32(), sstt.get_g32(), tbase2, tpal, userdata);
342 TEX->add(t0);
343 TEX->add(t2);
344 TEX->add(t3);
345 TEX->sra_imm(2);
346 }
347 }
348
copy(color_t * TEX,int32_t SSS,int32_t SST,uint32_t tilenum,const rdp_poly_state & object,rdp_span_aux * userdata)349 void n64_texture_pipe_t::copy(color_t* TEX, int32_t SSS, int32_t SST, uint32_t tilenum, const rdp_poly_state& object, rdp_span_aux* userdata)
350 {
351 const n64_tile_t* tiles = object.m_tiles;
352 const n64_tile_t& tile = tiles[tilenum];
353
354 rgbaint_t st(0, SSS, 0, SST);
355 shift_copy(st, tile);
356 rgbaint_t stlsb(st);
357 stlsb.and_imm(7);
358 st.shr_imm(3);
359 st.sub(rgbaint_t(0, tile.sl, 0, tile.tl));
360 st.shl_imm(3);
361 st.add(stlsb);
362 st.sign_extend(0x00010000, 0xffff0000);
363 st.shr_imm(5);
364 st.and_imm(0x1fff);
365 mask(st, tile);
366
367 const uint32_t index = (tile.format << 4) | (tile.size << 2) | ((uint32_t) object.m_other_modes.en_tlut << 1) | (uint32_t) object.m_other_modes.tlut_type;
368 const uint32_t tbase = tile.tmem + ((tile.line * st.get_b32()) & 0x1ff);
369 ((this)->*(m_texel_fetch[index]))(*TEX, st.get_r32(), st.get_b32(), tbase, tile.palette, userdata);
370 }
371
lod_1cycle(int32_t * sss,int32_t * sst,const int32_t s,const int32_t t,const int32_t w,const int32_t dsinc,const int32_t dtinc,const int32_t dwinc,rdp_span_aux * userdata,const rdp_poly_state & object)372 void n64_texture_pipe_t::lod_1cycle(int32_t* sss, int32_t* sst, const int32_t s, const int32_t t, const int32_t w, const int32_t dsinc, const int32_t dtinc, const int32_t dwinc, rdp_span_aux* userdata, const rdp_poly_state& object)
373 {
374 const int32_t nextsw = (w + dwinc) >> 16;
375 int32_t nexts = (s + dsinc) >> 16;
376 int32_t nextt = (t + dtinc) >> 16;
377
378 if (object.m_other_modes.persp_tex_en)
379 {
380 m_rdp->tc_div(nexts, nextt, nextsw, &nexts, &nextt);
381 }
382 else
383 {
384 m_rdp->tc_div_no_perspective(nexts, nextt, nextsw, &nexts, &nextt);
385 }
386
387 userdata->m_start_span = false;
388 userdata->m_precomp_s = nexts;
389 userdata->m_precomp_t = nextt;
390
391 const int32_t lodclamp = (((*sst & 0x60000) > 0) | ((nextt & 0x60000) > 0)) || (((*sss & 0x60000) > 0) | ((nexts & 0x60000) > 0));
392
393 int32_t horstep = SIGN17(nexts & 0x1ffff) - SIGN17(*sss & 0x1ffff);
394 int32_t vertstep = SIGN17(nextt & 0x1ffff) - SIGN17(*sst & 0x1ffff);
395 if (horstep & 0x20000)
396 {
397 horstep = ~horstep & 0x1ffff;
398 }
399 if (vertstep & 0x20000)
400 {
401 vertstep = ~vertstep & 0x1ffff;
402 }
403
404 int32_t lod = (horstep >= vertstep) ? horstep : vertstep;
405
406 *sss = m_lod_lookup[*sss & 0x7ffff];
407 *sst = m_lod_lookup[*sst & 0x7ffff];
408
409 if ((lod & 0x4000) || lodclamp)
410 {
411 lod = 0x7fff;
412 }
413 else if (lod < object.m_misc_state.m_min_level)
414 {
415 lod = object.m_misc_state.m_min_level;
416 }
417
418 int32_t l_tile = m_rdp->get_log2((lod >> 5) & 0xff);
419 const bool magnify = (lod < 32);
420 const bool distant = ((lod & 0x6000) || (l_tile >= object.m_misc_state.m_max_level));
421
422 uint8_t lod_fraction = ((lod << 3) >> l_tile) & 0xff;
423
424 if(!object.m_other_modes.sharpen_tex_en && !object.m_other_modes.detail_tex_en)
425 {
426 if (distant)
427 {
428 lod_fraction = 0xff;
429 }
430 else if (magnify)
431 {
432 lod_fraction = 0;
433 }
434 }
435
436 userdata->m_lod_fraction.set(lod_fraction, lod_fraction, lod_fraction, lod_fraction);
437 /* FIXME: ???
438 if(object.m_other_modes.sharpen_tex_en && magnify)
439 {
440 userdata->m_lod_fraction |= 0x100;
441 }
442 */
443 }
444
lod_2cycle(int32_t * sss,int32_t * sst,const int32_t s,const int32_t t,const int32_t w,const int32_t dsinc,const int32_t dtinc,const int32_t dwinc,const int32_t prim_tile,int32_t * t1,int32_t * t2,rdp_span_aux * userdata,const rdp_poly_state & object)445 void n64_texture_pipe_t::lod_2cycle(int32_t* sss, int32_t* sst, const int32_t s, const int32_t t, const int32_t w, const int32_t dsinc, const int32_t dtinc, const int32_t dwinc, const int32_t prim_tile, int32_t* t1, int32_t* t2, rdp_span_aux* userdata, const rdp_poly_state& object)
446 {
447 const int32_t nextsw = (w + dwinc) >> 16;
448 int32_t nexts = (s + dsinc) >> 16;
449 int32_t nextt = (t + dtinc) >> 16;
450
451 if (object.m_other_modes.persp_tex_en)
452 {
453 m_rdp->tc_div(nexts, nextt, nextsw, &nexts, &nextt);
454 }
455 else
456 {
457 m_rdp->tc_div_no_perspective(nexts, nextt, nextsw, &nexts, &nextt);
458 }
459
460 userdata->m_start_span = false;
461 userdata->m_precomp_s = nexts;
462 userdata->m_precomp_t = nextt;
463
464 const int32_t lodclamp = (((*sst & 0x60000) > 0) | ((nextt & 0x60000) > 0)) || (((*sss & 0x60000) > 0) | ((nexts & 0x60000) > 0));
465
466 int32_t horstep = SIGN17(nexts & 0x1ffff) - SIGN17(*sss & 0x1ffff);
467 int32_t vertstep = SIGN17(nextt & 0x1ffff) - SIGN17(*sst & 0x1ffff);
468 if (horstep & 0x20000)
469 {
470 horstep = ~horstep & 0x1ffff;
471 }
472 if (vertstep & 0x20000)
473 {
474 vertstep = ~vertstep & 0x1ffff;
475 }
476
477 int32_t lod = (horstep >= vertstep) ? horstep : vertstep;
478
479 *sss = m_lod_lookup[*sss & 0x7ffff];
480 *sst = m_lod_lookup[*sst & 0x7ffff];
481
482 if ((lod & 0x4000) || lodclamp)
483 {
484 lod = 0x7fff;
485 }
486 else if (lod < object.m_misc_state.m_min_level)
487 {
488 lod = object.m_misc_state.m_min_level;
489 }
490
491 int32_t l_tile = m_rdp->get_log2((lod >> 5) & 0xff);
492 const bool magnify = (lod < 32);
493 const bool distant = ((lod & 0x6000) || (l_tile >= object.m_misc_state.m_max_level));
494
495 uint8_t lod_fraction = ((lod << 3) >> l_tile) & 0xff;
496
497 if(!object.m_other_modes.sharpen_tex_en && !object.m_other_modes.detail_tex_en)
498 {
499 if (distant)
500 {
501 lod_fraction = 0xff;
502 }
503 else if (magnify)
504 {
505 lod_fraction = 0;
506 }
507 }
508
509 userdata->m_lod_fraction.set(lod_fraction, lod_fraction, lod_fraction, lod_fraction);
510
511 /* FIXME: ???
512 if(object.m_other_modes.sharpen_tex_en && magnify)
513 {
514 userdata->m_lod_fraction |= 0x100;
515 }*/
516
517 if (object.m_other_modes.tex_lod_en)
518 {
519 if (distant)
520 {
521 l_tile = object.m_misc_state.m_max_level;
522 }
523 if (!object.m_other_modes.detail_tex_en)
524 {
525 *t1 = (prim_tile + l_tile) & 7;
526 if (!(distant || (!object.m_other_modes.sharpen_tex_en && magnify)))
527 {
528 *t2 = (*t1 + 1) & 7;
529 }
530 else
531 {
532 *t2 = *t1; // World Driver Championship, Stunt Race 64, Beetle Adventure Racing
533 }
534 }
535 else // Beetle Adventure Racing, World Driver Championship (ingame_, NFL Blitz 2001, Pilotwings
536 {
537 if (!magnify)
538 {
539 *t1 = (prim_tile + l_tile + 1);
540 }
541 else
542 {
543 *t1 = (prim_tile + l_tile);
544 }
545 *t1 &= 7;
546 if (!distant && !magnify)
547 {
548 *t2 = (prim_tile + l_tile + 2) & 7;
549 }
550 else
551 {
552 *t2 = (prim_tile + l_tile + 1) & 7;
553 }
554 }
555 }
556 }
557
lod_2cycle_limited(int32_t * sss,int32_t * sst,const int32_t s,const int32_t t,const int32_t w,const int32_t dsinc,const int32_t dtinc,const int32_t dwinc,const int32_t prim_tile,int32_t * t1,const rdp_poly_state & object)558 void n64_texture_pipe_t::lod_2cycle_limited(int32_t* sss, int32_t* sst, const int32_t s, const int32_t t, const int32_t w, const int32_t dsinc, const int32_t dtinc, const int32_t dwinc, const int32_t prim_tile, int32_t* t1, const rdp_poly_state& object)
559 {
560 const int32_t nextsw = (w + dwinc) >> 16;
561 int32_t nexts = (s + dsinc) >> 16;
562 int32_t nextt = (t + dtinc) >> 16;
563
564 if (object.m_other_modes.persp_tex_en)
565 {
566 m_rdp->tc_div(nexts, nextt, nextsw, &nexts, &nextt);
567 }
568 else
569 {
570 m_rdp->tc_div_no_perspective(nexts, nextt, nextsw, &nexts, &nextt);
571 }
572
573 const int32_t lodclamp = (((*sst & 0x60000) > 0) | ((nextt & 0x60000) > 0)) || (((*sss & 0x60000) > 0) | ((nexts & 0x60000) > 0));
574
575 int32_t horstep = SIGN17(nexts & 0x1ffff) - SIGN17(*sss & 0x1ffff);
576 int32_t vertstep = SIGN17(nextt & 0x1ffff) - SIGN17(*sst & 0x1ffff);
577 if (horstep & 0x20000)
578 {
579 horstep = ~horstep & 0x1ffff;
580 }
581 if (vertstep & 0x20000)
582 {
583 vertstep = ~vertstep & 0x1ffff;
584 }
585
586 int32_t lod = (horstep >= vertstep) ? horstep : vertstep;
587
588 *sss = m_lod_lookup[*sss & 0x7ffff];
589 *sst = m_lod_lookup[*sst & 0x7ffff];
590
591 if ((lod & 0x4000) || lodclamp)
592 {
593 lod = 0x7fff;
594 }
595 else if (lod < object.m_misc_state.m_min_level)
596 {
597 lod = object.m_misc_state.m_min_level;
598 }
599
600 int32_t l_tile = m_rdp->get_log2((lod >> 5) & 0xff);
601 const bool magnify = (lod < 32);
602 const bool distant = (lod & 0x6000) || (l_tile >= object.m_misc_state.m_max_level);
603
604 if (object.m_other_modes.tex_lod_en)
605 {
606 if (distant)
607 {
608 l_tile = object.m_misc_state.m_max_level;
609 }
610 if (!object.m_other_modes.detail_tex_en)
611 {
612 *t1 = (prim_tile + l_tile) & 7;
613 }
614 else
615 {
616 if (!magnify)
617 {
618 *t1 = (prim_tile + l_tile + 1);
619 }
620 else
621 {
622 *t1 = (prim_tile + l_tile);
623 }
624 *t1 &= 7;
625 }
626 }
627 }
628
calculate_clamp_diffs(uint32_t prim_tile,rdp_span_aux * userdata,const rdp_poly_state & object)629 void n64_texture_pipe_t::calculate_clamp_diffs(uint32_t prim_tile, rdp_span_aux* userdata, const rdp_poly_state& object)
630 {
631 const n64_tile_t* tiles = object.m_tiles;
632 if (object.m_other_modes.cycle_type == CYCLE_TYPE_2)
633 {
634 if (object.m_other_modes.tex_lod_en)
635 {
636 for (int32_t start = 0; start <= 7; start++)
637 {
638 userdata->m_clamp_diff[start].set((tiles[start].sh >> 2) - (tiles[start].sl >> 2), (tiles[start].sh >> 2) - (tiles[start].sl >> 2), (tiles[start].th >> 2) - (tiles[start].tl >> 2), (tiles[start].th >> 2) - (tiles[start].tl >> 2));
639 }
640 }
641 else
642 {
643 const int32_t start = prim_tile;
644 const int32_t end = (prim_tile + 1) & 7;
645 userdata->m_clamp_diff[start].set((tiles[start].sh >> 2) - (tiles[start].sl >> 2), (tiles[start].sh >> 2) - (tiles[start].sl >> 2), (tiles[start].th >> 2) - (tiles[start].tl >> 2), (tiles[start].th >> 2) - (tiles[start].tl >> 2));
646 userdata->m_clamp_diff[end].set((tiles[end].sh >> 2) - (tiles[end].sl >> 2), (tiles[end].sh >> 2) - (tiles[end].sl >> 2), (tiles[end].th >> 2) - (tiles[end].tl >> 2), (tiles[end].th >> 2) - (tiles[end].tl >> 2));
647 }
648 }
649 else//1-cycle or copy
650 {
651 userdata->m_clamp_diff[prim_tile].set((tiles[prim_tile].sh >> 2) - (tiles[prim_tile].sl >> 2), (tiles[prim_tile].sh >> 2) - (tiles[prim_tile].sl >> 2), (tiles[prim_tile].th >> 2) - (tiles[prim_tile].tl >> 2), (tiles[prim_tile].th >> 2) - (tiles[prim_tile].tl >> 2));
652 }
653 }
654
655 #define USE_64K_LUT (1)
656
657 static int32_t sTexAddrSwap16[2] = { WORD_ADDR_XOR, WORD_XOR_DWORD_SWAP };
658 static int32_t sTexAddrSwap8[2] = { BYTE_ADDR_XOR, BYTE_XOR_DWORD_SWAP };
659
fetch_rgba16_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)660 void n64_texture_pipe_t::fetch_rgba16_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
661 {
662 int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x7ff;
663
664 uint16_t c = ((uint16_t*)userdata->m_tmem)[taddr];
665 c = ((uint16_t*)(userdata->m_tmem + 0x800))[(c >> 8) << 2];
666
667 #if USE_64K_LUT
668 out.set(m_expand_16to32_table[c]);
669 #else
670 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
671 #endif
672 }
673
fetch_rgba16_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)674 void n64_texture_pipe_t::fetch_rgba16_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
675 {
676 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x7ff;
677
678 uint16_t c = ((uint16_t*)userdata->m_tmem)[taddr];
679 c = ((uint16_t*)(userdata->m_tmem + 0x800))[(c >> 8) << 2];
680
681 const uint8_t k = (c >> 8) & 0xff;
682 out.set(c & 0xff, k, k, k);
683 }
684
fetch_rgba16_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)685 void n64_texture_pipe_t::fetch_rgba16_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
686 {
687 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x7ff;
688
689 const uint16_t c = ((uint16_t*)userdata->m_tmem)[taddr];
690
691 #if USE_64K_LUT
692 out.set(m_expand_16to32_table[c]);
693 #else
694 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
695 #endif
696 }
697
fetch_rgba32_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)698 void n64_texture_pipe_t::fetch_rgba32_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
699 {
700 const uint32_t *tc = ((uint32_t*)userdata->m_tmem);
701 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x3ff;
702
703 uint32_t c = tc[taddr];
704 c = ((uint16_t*)(userdata->m_tmem + 0x800))[(c >> 24) << 2];
705
706 #if USE_64K_LUT
707 out.set(m_expand_16to32_table[c]);
708 #else
709 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
710 #endif
711 }
712
fetch_rgba32_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)713 void n64_texture_pipe_t::fetch_rgba32_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
714 {
715 const uint32_t *tc = ((uint32_t*)userdata->m_tmem);
716 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x3ff;
717
718 uint32_t c = tc[taddr];
719 c = ((uint16_t*)(userdata->m_tmem + 0x800))[(c >> 24) << 2];
720
721 const uint8_t k = (c >> 8) & 0xff;
722 out.set(c & 0xff, k, k, k);
723 }
724
fetch_rgba32_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)725 void n64_texture_pipe_t::fetch_rgba32_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
726 {
727 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x3ff;
728
729 const uint16_t cl = ((uint16_t*)userdata->m_tmem)[taddr];
730 const uint16_t ch = ((uint16_t*)userdata->m_tmem)[taddr | 0x400];
731
732 out.set(ch & 0xff, cl >> 8, cl & 0xff, ch >> 8);
733 }
734
fetch_nop(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)735 void n64_texture_pipe_t::fetch_nop(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata) { }
736
fetch_yuv(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)737 void n64_texture_pipe_t::fetch_yuv(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
738 {
739 const uint16_t *tc = ((uint16_t*)userdata->m_tmem);
740
741 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
742 const int32_t taddrlow = ((taddr >> 1) ^ sTexAddrSwap16[t & 1]) & 0x3ff;
743
744 const uint16_t c = tc[taddrlow];
745
746 int32_t y = userdata->m_tmem[taddr | 0x800];
747 int32_t u = c >> 8;
748 int32_t v = c & 0xff;
749
750 v ^= 0x80; u ^= 0x80;
751 u |= ((u & 0x80) << 1);
752 v |= ((v & 0x80) << 1);
753
754 out.set(y & 0xff, y & 0xff, u & 0xff, v & 0xff);
755 }
756
fetch_ci4_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)757 void n64_texture_pipe_t::fetch_ci4_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
758 {
759 const uint8_t *tc = userdata->m_tmem;
760 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
761
762 const uint8_t p = (s & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4);
763 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | p) << 2];
764
765 #if USE_64K_LUT
766 out.set(m_expand_16to32_table[c]);
767 #else
768 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
769 #endif
770 }
771
fetch_ci4_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)772 void n64_texture_pipe_t::fetch_ci4_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
773 {
774 const uint8_t *tc = userdata->m_tmem;
775 int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
776
777 const uint8_t p = (s & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4);
778 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | p) << 2];
779
780 const uint8_t k = (c >> 8) & 0xff;
781 out.set(c & 0xff, k, k, k);
782 }
783
fetch_ci4_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)784 void n64_texture_pipe_t::fetch_ci4_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
785 {
786 const uint8_t *tc = userdata->m_tmem;
787 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0xfff;
788
789 uint8_t p = (s & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4);
790 p = (tpal << 4) | p;
791
792 out.set(p, p, p, p);
793 }
794
fetch_ci8_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)795 void n64_texture_pipe_t::fetch_ci8_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
796 {
797 const uint8_t *tc = userdata->m_tmem;
798 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
799
800 const uint8_t p = tc[taddr];
801 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[p << 2];
802
803 #if USE_64K_LUT
804 out.set(m_expand_16to32_table[c]);
805 #else
806 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
807 #endif
808 }
809
fetch_ci8_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)810 void n64_texture_pipe_t::fetch_ci8_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
811 {
812 const uint8_t *tc = userdata->m_tmem;
813 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
814
815 const uint8_t p = tc[taddr];
816 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[p << 2];
817
818 const uint8_t k = (c >> 8) & 0xff;
819 out.set(c & 0xff, k, k, k);
820 }
821
fetch_ci8_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)822 void n64_texture_pipe_t::fetch_ci8_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
823 {
824 const uint8_t *tc = userdata->m_tmem;
825 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0xfff;
826
827 const uint8_t p = tc[taddr];
828 out.set(p, p, p, p);
829 }
830
fetch_ia4_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)831 void n64_texture_pipe_t::fetch_ia4_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
832 {
833 const uint8_t *tc = userdata->m_tmem;
834 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
835
836 const uint8_t p = ((s) & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4);
837 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | p) << 2];
838
839 #if USE_64K_LUT
840 out.set(m_expand_16to32_table[c]);
841 #else
842 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
843 #endif
844 }
845
fetch_ia4_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)846 void n64_texture_pipe_t::fetch_ia4_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
847 {
848 const uint8_t *tc = userdata->m_tmem;
849 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
850
851 const uint8_t p = ((s) & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4);
852 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | p) << 2];
853
854 const uint8_t k = (c >> 8) & 0xff;
855 out.set(c & 0xff, k, k, k);
856 }
857
fetch_ia4_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)858 void n64_texture_pipe_t::fetch_ia4_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
859 {
860 const uint8_t *tc = userdata->m_tmem;
861 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0xfff;
862
863 const uint8_t p = ((s) & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4);
864 uint8_t i = p & 0xe;
865 i = (i << 4) | (i << 1) | (i >> 2);
866
867 out.set((p & 1) * 0xff, i, i, i);
868 }
869
fetch_ia8_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)870 void n64_texture_pipe_t::fetch_ia8_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
871 {
872 const uint8_t *tc = userdata->m_tmem;
873 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
874
875 const uint8_t p = tc[taddr];
876 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[p << 2];
877
878 #if USE_64K_LUT
879 out.set(m_expand_16to32_table[c]);
880 #else
881 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
882 #endif
883 }
884
fetch_ia8_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)885 void n64_texture_pipe_t::fetch_ia8_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
886 {
887 const uint8_t *tc = userdata->m_tmem;
888 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
889
890 const uint8_t p = tc[taddr];
891 const uint16_t c = ((uint16_t*)(userdata->m_tmem + 0x800))[p << 2];
892
893 const uint8_t k = (c >> 8) & 0xff;
894 out.set(c & 0xff, k, k, k);
895 }
896
fetch_ia8_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)897 void n64_texture_pipe_t::fetch_ia8_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
898 {
899 const uint8_t *tc = userdata->m_tmem;
900 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0xfff;
901
902 const uint8_t p = tc[taddr];
903 uint8_t i = p & 0xf0;
904 i |= (i >> 4);
905
906 out.set(((p << 4) | (p & 0xf)) & 0xff, i, i, i);
907 }
908
fetch_ia16_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)909 void n64_texture_pipe_t::fetch_ia16_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
910 {
911 const uint16_t *tc = ((uint16_t*)userdata->m_tmem);
912 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x3ff;
913
914 uint16_t c = tc[taddr];
915 c = ((uint16_t*)(userdata->m_tmem + 0x800))[(c >> 8) << 2];
916
917 #if USE_64K_LUT
918 out.set(m_expand_16to32_table[c]);
919 #else
920 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
921 #endif
922 }
923
fetch_ia16_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)924 void n64_texture_pipe_t::fetch_ia16_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
925 {
926 const uint16_t *tc = ((uint16_t*)userdata->m_tmem);
927 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x3ff;
928
929 uint16_t c = tc[taddr];
930 c = ((uint16_t*)(userdata->m_tmem + 0x800))[(c >> 8) << 2];
931
932 const uint8_t k = (c >> 8) & 0xff;
933 out.set(c & 0xff, k, k, k);
934 }
935
fetch_ia16_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)936 void n64_texture_pipe_t::fetch_ia16_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
937 {
938 const uint16_t *tc = ((uint16_t*)userdata->m_tmem);
939 const int32_t taddr = (((tbase << 2) + s) ^ sTexAddrSwap16[t & 1]) & 0x7ff;
940
941 const uint16_t c = tc[taddr];
942 const uint8_t i = (c >> 8);
943 out.set(c & 0xff, i, i, i);
944 }
945
fetch_i4_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)946 void n64_texture_pipe_t::fetch_i4_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
947 {
948 const uint8_t *tc = userdata->m_tmem;
949 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
950
951 const uint8_t byteval = tc[taddr];
952 const uint8_t c = ((s & 1)) ? (byteval & 0xf) : ((byteval >> 4) & 0xf);
953 const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | c) << 2];
954
955 #if USE_64K_LUT
956 out.set(m_expand_16to32_table[k]);
957 #else
958 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
959 #endif
960 }
961
fetch_i4_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)962 void n64_texture_pipe_t::fetch_i4_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
963 {
964 const uint8_t *tc = userdata->m_tmem;
965 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
966
967 const uint8_t byteval = tc[taddr];
968 const uint8_t c = ((s & 1)) ? (byteval & 0xf) : ((byteval >> 4) & 0xf);
969 const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[((tpal << 4) | c) << 2];
970
971 const uint8_t i = (k >> 8) & 0xff;
972 out.set(k & 0xff, i, i, i);
973 }
974
fetch_i4_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)975 void n64_texture_pipe_t::fetch_i4_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
976 {
977 const uint8_t *tc = userdata->m_tmem;
978 const int32_t taddr = ((((tbase << 4) + s) >> 1) ^ sTexAddrSwap8[t & 1]) & 0xfff;
979
980 const uint8_t byteval = tc[taddr];
981 uint8_t c = ((s & 1)) ? (byteval & 0xf) : ((byteval >> 4) & 0xf);
982 c |= (c << 4);
983
984 out.set(c, c, c, c);
985 }
986
fetch_i8_tlut0(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)987 void n64_texture_pipe_t::fetch_i8_tlut0(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
988 {
989 const uint8_t *tc = userdata->m_tmem;
990 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
991
992 const uint8_t c = tc[taddr];
993 const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[c << 2];
994
995 #if USE_64K_LUT
996 out.set(m_expand_16to32_table[k]);
997 #else
998 out.set((c & 1) * 0xff, GET_HI_RGBA16_TMEM(c), GET_MED_RGBA16_TMEM(c), GET_LOW_RGBA16_TMEM(c));
999 #endif
1000 }
1001
fetch_i8_tlut1(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)1002 void n64_texture_pipe_t::fetch_i8_tlut1(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
1003 {
1004 const uint8_t *tc = userdata->m_tmem;
1005 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0x7ff;
1006
1007 const uint8_t c = tc[taddr];
1008 const uint16_t k = ((uint16_t*)(userdata->m_tmem + 0x800))[c << 2];
1009
1010 const uint8_t i = (k >> 8) & 0xff;
1011 out.set(k & 0xff, i, i, i);
1012 }
1013
fetch_i8_raw(rgbaint_t & out,int32_t s,int32_t t,int32_t tbase,int32_t tpal,rdp_span_aux * userdata)1014 void n64_texture_pipe_t::fetch_i8_raw(rgbaint_t& out, int32_t s, int32_t t, int32_t tbase, int32_t tpal, rdp_span_aux* userdata)
1015 {
1016 const uint8_t *tc = userdata->m_tmem;
1017 const int32_t taddr = (((tbase << 3) + s) ^ sTexAddrSwap8[t & 1]) & 0xfff;
1018
1019 const uint8_t c = tc[taddr];
1020
1021 out.set(c, c, c, c);
1022 }
1023