trunk/src/mame/video/rdpspn16.c
r25470 | r25471 | |
15 | 15 | #include "includes/n64.h" |
16 | 16 | #include "video/n64.h" |
17 | 17 | |
18 | | #define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D] |
| 18 | #define LookUpCC(A, B, C, D) GetCCLUT2()[(GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D] |
19 | 19 | |
20 | 20 | void n64_rdp::RenderSpans(int start, int end, int tilenum, bool flip, extent_t *Spans, bool rect, rdp_poly_state *object) |
21 | 21 | { |
r25470 | r25471 | |
81 | 81 | |
82 | 82 | void n64_rdp::RGBAZClip(int sr, int sg, int sb, int sa, int *sz, rdp_span_aux *userdata) |
83 | 83 | { |
84 | | userdata->ShadeColor.i.r = m_special_9bit_clamptable[sr & 0x1ff]; |
85 | | userdata->ShadeColor.i.g = m_special_9bit_clamptable[sg & 0x1ff]; |
86 | | userdata->ShadeColor.i.b = m_special_9bit_clamptable[sb & 0x1ff]; |
87 | | userdata->ShadeColor.i.a = m_special_9bit_clamptable[sa & 0x1ff]; |
| 84 | userdata->ShadeColor.i.r = s_special_9bit_clamptable[sr & 0x1ff]; |
| 85 | userdata->ShadeColor.i.g = s_special_9bit_clamptable[sg & 0x1ff]; |
| 86 | userdata->ShadeColor.i.b = s_special_9bit_clamptable[sb & 0x1ff]; |
| 87 | userdata->ShadeColor.i.a = s_special_9bit_clamptable[sa & 0x1ff]; |
88 | 88 | |
89 | 89 | INT32 zanded = (*sz) & 0x60000; |
90 | 90 | |
r25470 | r25471 | |
134 | 134 | { |
135 | 135 | int clipx1 = object.Scissor.m_xh; |
136 | 136 | int clipx2 = object.Scissor.m_xl; |
137 | | n64_rdp *m_rdp = object.m_rdp; |
138 | 137 | int tilenum = object.tilenum; |
139 | 138 | bool flip = object.flip; |
140 | 139 | |
r25470 | r25471 | |
157 | 156 | |
158 | 157 | INT32 m_clamp_s_diff[8]; |
159 | 158 | INT32 m_clamp_t_diff[8]; |
160 | | m_rdp->TexPipe.CalculateClampDiffs(tile1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 159 | TexPipe.CalculateClampDiffs(tile1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
161 | 160 | |
162 | 161 | bool partialreject = (userdata->ColorInputs.blender2b_a[0] == &userdata->InvPixelColor.i.a && userdata->ColorInputs.blender1b_a[0] == &userdata->PixelColor.i.a); |
163 | 162 | int sel0 = (OtherModes.force_blend ? 2 : 0) | ((userdata->ColorInputs.blender2b_a[0] == &userdata->MemoryColor.i.a) ? 1 : 0); |
r25470 | r25471 | |
209 | 208 | int blend_index = (object.OtherModes.alpha_cvg_select ? 2 : 0) | ((object.OtherModes.rgb_dither_sel < 3) ? 1 : 0); |
210 | 209 | int read_index = ((object.MiscState.FBSize - 2) << 1) | object.OtherModes.image_read_en; |
211 | 210 | int write_index = ((object.MiscState.FBSize - 2) << 3) | (object.OtherModes.cvg_dest << 1); |
| 211 | int cycle0 = ((object.OtherModes.sample_type & 1) << 1) | (object.OtherModes.bi_lerp0 & 1); |
212 | 212 | int acmode = (object.OtherModes.alpha_compare_en ? 2 : 0) | (object.OtherModes.dither_alpha_en ? 1 : 0); |
213 | 213 | |
| 214 | INT32 sss = 0; |
| 215 | INT32 sst = 0; |
| 216 | |
| 217 | if (object.OtherModes.persp_tex_en) |
| 218 | { |
| 219 | TCDiv(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); |
| 220 | } |
| 221 | else |
| 222 | { |
| 223 | TCDivNoPersp(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); |
| 224 | } |
| 225 | |
214 | 226 | userdata->m_start_span = true; |
215 | 227 | for (int j = 0; j <= length; j++) |
216 | 228 | { |
r25470 | r25471 | |
218 | 230 | int sg = g.w >> 14; |
219 | 231 | int sb = b.w >> 14; |
220 | 232 | int sa = a.w >> 14; |
221 | | int ss = s.w >> 16; |
222 | | int st = t.w >> 16; |
223 | | int sw = w.w >> 16; |
224 | 233 | int sz = (z.w >> 10) & 0x3fffff; |
225 | | INT32 sss = 0; |
226 | | INT32 sst = 0; |
227 | | |
228 | 234 | bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored); |
229 | 235 | |
230 | 236 | if (x >= clipx1 && x < clipx2 && valid_x) |
231 | 237 | { |
232 | | m_rdp->lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); |
| 238 | lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); |
233 | 239 | |
234 | | if (userdata->m_start_span) |
235 | | { |
236 | | if (object.OtherModes.persp_tex_en) |
237 | | { |
238 | | m_rdp->TCDiv(ss, st, sw, &sss, &sst); |
239 | | } |
240 | | else |
241 | | { |
242 | | m_rdp->TCDivNoPersp(ss, st, sw, &sss, &sst); |
243 | | } |
244 | | } |
245 | | else |
246 | | { |
247 | | sss = userdata->m_precomp_s; |
248 | | sst = userdata->m_precomp_t; |
249 | | } |
| 240 | TexPipe.LOD1Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, userdata, object); |
250 | 241 | |
251 | | m_rdp->TexPipe.LOD1Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, userdata, object); |
252 | | |
253 | 242 | RGBAZCorrectTriangle(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object); |
254 | 243 | RGBAZClip(sr, sg, sb, sa, &sz, userdata); |
255 | 244 | |
256 | | m_rdp->TexPipe.Cycle(&userdata->Texel0Color, &userdata->Texel0Color, sss, sst, tilenum, 0, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 245 | ((TexPipe).*(TexPipe.cycle[cycle0]))(&userdata->Texel0Color, &userdata->Texel0Color, sss, sst, tilenum, 0, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 246 | //TexPipe.Cycle(&userdata->Texel0Color, &userdata->Texel0Color, sss, sst, tilenum, 0, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
257 | 247 | |
258 | | m_rdp->ColorCombiner1Cycle(userdata); |
| 248 | userdata->NoiseColor.i.r = userdata->NoiseColor.i.g = userdata->NoiseColor.i.b = rand() << 3; // Not accurate |
259 | 249 | |
| 250 | userdata->PixelColor.i.r = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_r[1],*userdata->ColorInputs.combiner_rgbsub_b_r[1],*userdata->ColorInputs.combiner_rgbmul_r[1],*userdata->ColorInputs.combiner_rgbadd_r[1]); |
| 251 | userdata->PixelColor.i.g = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_g[1],*userdata->ColorInputs.combiner_rgbsub_b_g[1],*userdata->ColorInputs.combiner_rgbmul_g[1],*userdata->ColorInputs.combiner_rgbadd_g[1]); |
| 252 | userdata->PixelColor.i.b = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_b[1],*userdata->ColorInputs.combiner_rgbsub_b_b[1],*userdata->ColorInputs.combiner_rgbmul_b[1],*userdata->ColorInputs.combiner_rgbadd_b[1]); |
| 253 | userdata->PixelColor.i.a = AlphaCombinerEquation(*userdata->ColorInputs.combiner_alphasub_a[1],*userdata->ColorInputs.combiner_alphasub_b[1],*userdata->ColorInputs.combiner_alphamul[1],*userdata->ColorInputs.combiner_alphaadd[1]); |
| 254 | |
260 | 255 | //Alpha coverage combiner |
261 | 256 | GetAlphaCvg(&userdata->PixelColor.i.a, userdata, object); |
262 | 257 | |
r25470 | r25471 | |
266 | 261 | |
267 | 262 | ((this)->*(_Read[read_index]))(curpixel, userdata, object); |
268 | 263 | |
269 | | if(m_rdp->ZCompare(zbcur, zhbcur, sz, dzpix, userdata, object)) |
| 264 | if(ZCompare(zbcur, zhbcur, sz, dzpix, userdata, object)) |
270 | 265 | { |
271 | | m_rdp->GetDitherValues(scanline, j, &cdith, &adith, object); |
| 266 | GetDitherValues(scanline, j, &cdith, &adith, object); |
272 | 267 | |
273 | | bool rendered = ((&m_rdp->Blender)->*(m_rdp->Blender.blend1[(userdata->BlendEnable << 2) | blend_index]))(&fir, &fig, &fib, cdith, adith, partialreject, sel0, acmode, userdata, object); |
| 268 | bool rendered = ((&Blender)->*(Blender.blend1[(userdata->BlendEnable << 2) | blend_index]))(&fir, &fig, &fib, cdith, adith, partialreject, sel0, acmode, userdata, object); |
274 | 269 | |
275 | 270 | if (rendered) |
276 | 271 | { |
r25470 | r25471 | |
278 | 273 | |
279 | 274 | if (object.OtherModes.z_update_en) |
280 | 275 | { |
281 | | m_rdp->ZStore(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); |
| 276 | ZStore(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); |
282 | 277 | } |
283 | 278 | } |
284 | 279 | } |
| 280 | |
| 281 | sss = userdata->m_precomp_s; |
| 282 | sst = userdata->m_precomp_t; |
285 | 283 | } |
286 | 284 | |
287 | 285 | r.w += drinc; |
r25470 | r25471 | |
301 | 299 | { |
302 | 300 | int clipx1 = object.Scissor.m_xh; |
303 | 301 | int clipx2 = object.Scissor.m_xl; |
304 | | n64_rdp *m_rdp = object.m_rdp; |
305 | 302 | int tilenum = object.tilenum; |
306 | 303 | bool flip = object.flip; |
307 | 304 | |
r25470 | r25471 | |
316 | 313 | |
317 | 314 | UINT32 zb = object.MiscState.ZBAddress >> 1; |
318 | 315 | UINT32 zhb = object.MiscState.ZBAddress; |
319 | | UINT8 offx = 0, offy = 0; |
320 | 316 | |
321 | 317 | INT32 tile2 = (tilenum + 1) & 7; |
322 | 318 | INT32 tile1 = tilenum; |
r25470 | r25471 | |
330 | 326 | |
331 | 327 | INT32 m_clamp_s_diff[8]; |
332 | 328 | INT32 m_clamp_t_diff[8]; |
333 | | m_rdp->TexPipe.CalculateClampDiffs(tile1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 329 | TexPipe.CalculateClampDiffs(tile1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
334 | 330 | |
335 | 331 | bool partialreject = (userdata->ColorInputs.blender2b_a[1] == &userdata->InvPixelColor.i.a && userdata->ColorInputs.blender1b_a[1] == &userdata->PixelColor.i.a); |
336 | 332 | int sel0 = (OtherModes.force_blend ? 2 : 0) | ((userdata->ColorInputs.blender2b_a[0] == &userdata->MemoryColor.i.a) ? 1 : 0); |
r25470 | r25471 | |
371 | 367 | int blend_index = (object.OtherModes.alpha_cvg_select ? 2 : 0) | ((object.OtherModes.rgb_dither_sel < 3) ? 1 : 0); |
372 | 368 | int read_index = ((object.MiscState.FBSize - 2) << 1) | object.OtherModes.image_read_en; |
373 | 369 | int write_index = ((object.MiscState.FBSize - 2) << 3) | (object.OtherModes.cvg_dest << 1); |
| 370 | int cycle0 = ((object.OtherModes.sample_type & 1) << 1) | (object.OtherModes.bi_lerp0 & 1); |
| 371 | int cycle1 = ((object.OtherModes.sample_type & 1) << 1) | (object.OtherModes.bi_lerp1 & 1); |
374 | 372 | int acmode = (object.OtherModes.alpha_compare_en ? 2 : 0) | (object.OtherModes.dither_alpha_en ? 1 : 0); |
375 | 373 | |
| 374 | INT32 sss = 0; |
| 375 | INT32 sst = 0; |
| 376 | |
| 377 | if (object.OtherModes.persp_tex_en) |
| 378 | { |
| 379 | TCDiv(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); |
| 380 | } |
| 381 | else |
| 382 | { |
| 383 | TCDivNoPersp(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); |
| 384 | } |
| 385 | |
376 | 386 | userdata->m_start_span = true; |
377 | 387 | for (int j = 0; j <= length; j++) |
378 | 388 | { |
r25470 | r25471 | |
380 | 390 | int sg = g.w >> 14; |
381 | 391 | int sb = b.w >> 14; |
382 | 392 | int sa = a.w >> 14; |
383 | | int ss = s.h.h; |
384 | | int st = t.h.h; |
385 | | int sw = w.h.h; |
386 | 393 | int sz = (z.w >> 10) & 0x3fffff; |
387 | | INT32 sss = 0; |
388 | | INT32 sst = 0; |
389 | 394 | Color c1; |
390 | 395 | Color c2; |
391 | 396 | |
r25470 | r25471 | |
393 | 398 | |
394 | 399 | if (x >= clipx1 && x < clipx2 && valid_x) |
395 | 400 | { |
396 | | m_rdp->lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); |
| 401 | UINT32 compidx = compressed_cvmasks[userdata->m_cvg[x]]; |
| 402 | userdata->CurrentPixCvg = cvarray[compidx].cvg; |
| 403 | userdata->CurrentCvgBit = cvarray[compidx].cvbit; |
| 404 | UINT8 offx = cvarray[compidx].xoff; |
| 405 | UINT8 offy = cvarray[compidx].yoff; |
| 406 | //lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); |
397 | 407 | |
398 | | if (userdata->m_start_span) |
399 | | { |
400 | | if (object.OtherModes.persp_tex_en) |
401 | | { |
402 | | m_rdp->TCDiv(ss, st, sw, &sss, &sst); |
403 | | } |
404 | | else |
405 | | { |
406 | | m_rdp->TCDivNoPersp(ss, st, sw, &sss, &sst); |
407 | | } |
408 | | } |
409 | | else |
410 | | { |
411 | | sss = userdata->m_precomp_s; |
412 | | sst = userdata->m_precomp_t; |
413 | | } |
| 408 | TexPipe.LOD2Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &tile1, &tile2, userdata, object); |
414 | 409 | |
415 | | m_rdp->TexPipe.LOD2Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &tile1, &tile2, userdata, object); |
416 | | |
417 | 410 | news = userdata->m_precomp_s; |
418 | 411 | newt = userdata->m_precomp_t; |
419 | | m_rdp->TexPipe.LOD2CycleLimited(&news, &newt, s.w + dsinc, t.w + dtinc, w.w + dwinc, dsinc, dtinc, dwinc, prim_tile, &newtile1, object); |
| 412 | TexPipe.LOD2CycleLimited(&news, &newt, s.w + dsinc, t.w + dtinc, w.w + dwinc, dsinc, dtinc, dwinc, prim_tile, &newtile1, object); |
420 | 413 | |
421 | 414 | RGBAZCorrectTriangle(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object); |
422 | 415 | RGBAZClip(sr, sg, sb, sa, &sz, userdata); |
423 | 416 | |
424 | | m_rdp->TexPipe.Cycle(&userdata->Texel0Color, &userdata->Texel0Color, sss, sst, tile1, 0, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
425 | | m_rdp->TexPipe.Cycle(&userdata->Texel1Color, &userdata->Texel0Color, sss, sst, tile2, 1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 417 | ((TexPipe).*(TexPipe.cycle[cycle0]))(&userdata->Texel0Color, &userdata->Texel0Color, sss, sst, tile1, 0, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 418 | ((TexPipe).*(TexPipe.cycle[cycle1]))(&userdata->Texel1Color, &userdata->Texel0Color, sss, sst, tile2, 1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 419 | ((TexPipe).*(TexPipe.cycle[cycle1]))(&userdata->NextTexelColor, &userdata->NextTexelColor, sss, sst, tile2, 1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 420 | //TexPipe.Cycle(&userdata->Texel0Color, &userdata->Texel0Color, sss, sst, tile1, 0, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 421 | //TexPipe.Cycle(&userdata->Texel1Color, &userdata->Texel0Color, sss, sst, tile2, 1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 422 | //TexPipe.Cycle(&userdata->NextTexelColor, &userdata->NextTexelColor, sss, sst, tile2, 1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
426 | 423 | |
427 | | m_rdp->TexPipe.Cycle(&userdata->NextTexelColor, &userdata->NextTexelColor, sss, sst, tile2, 1, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 424 | userdata->NoiseColor.i.r = userdata->NoiseColor.i.g = userdata->NoiseColor.i.b = rand() << 3; // Not accurate |
| 425 | userdata->CombinedColor.i.r = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_r[0], |
| 426 | *userdata->ColorInputs.combiner_rgbsub_b_r[0], |
| 427 | *userdata->ColorInputs.combiner_rgbmul_r[0], |
| 428 | *userdata->ColorInputs.combiner_rgbadd_r[0]); |
| 429 | userdata->CombinedColor.i.g = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_g[0], |
| 430 | *userdata->ColorInputs.combiner_rgbsub_b_g[0], |
| 431 | *userdata->ColorInputs.combiner_rgbmul_g[0], |
| 432 | *userdata->ColorInputs.combiner_rgbadd_g[0]); |
| 433 | userdata->CombinedColor.i.b = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_b[0], |
| 434 | *userdata->ColorInputs.combiner_rgbsub_b_b[0], |
| 435 | *userdata->ColorInputs.combiner_rgbmul_b[0], |
| 436 | *userdata->ColorInputs.combiner_rgbadd_b[0]); |
| 437 | userdata->CombinedColor.i.a = AlphaCombinerEquation(*userdata->ColorInputs.combiner_alphasub_a[0], |
| 438 | *userdata->ColorInputs.combiner_alphasub_b[0], |
| 439 | *userdata->ColorInputs.combiner_alphamul[0], |
| 440 | *userdata->ColorInputs.combiner_alphaadd[0]); |
428 | 441 | |
429 | | m_rdp->ColorCombiner2Cycle(userdata); |
| 442 | userdata->Texel0Color = userdata->Texel1Color; |
| 443 | userdata->Texel1Color = userdata->NextTexelColor; |
430 | 444 | |
| 445 | userdata->PixelColor.i.r = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_r[1], |
| 446 | *userdata->ColorInputs.combiner_rgbsub_b_r[1], |
| 447 | *userdata->ColorInputs.combiner_rgbmul_r[1], |
| 448 | *userdata->ColorInputs.combiner_rgbadd_r[1]); |
| 449 | userdata->PixelColor.i.g = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_g[1], |
| 450 | *userdata->ColorInputs.combiner_rgbsub_b_g[1], |
| 451 | *userdata->ColorInputs.combiner_rgbmul_g[1], |
| 452 | *userdata->ColorInputs.combiner_rgbadd_g[1]); |
| 453 | userdata->PixelColor.i.b = ColorCombinerEquation(*userdata->ColorInputs.combiner_rgbsub_a_b[1], |
| 454 | *userdata->ColorInputs.combiner_rgbsub_b_b[1], |
| 455 | *userdata->ColorInputs.combiner_rgbmul_b[1], |
| 456 | *userdata->ColorInputs.combiner_rgbadd_b[1]); |
| 457 | userdata->PixelColor.i.a = AlphaCombinerEquation(*userdata->ColorInputs.combiner_alphasub_a[1], |
| 458 | *userdata->ColorInputs.combiner_alphasub_b[1], |
| 459 | *userdata->ColorInputs.combiner_alphamul[1], |
| 460 | *userdata->ColorInputs.combiner_alphaadd[1]); |
| 461 | |
431 | 462 | //Alpha coverage combiner |
432 | 463 | GetAlphaCvg(&userdata->PixelColor.i.a, userdata, object); |
433 | 464 | |
r25470 | r25471 | |
437 | 468 | |
438 | 469 | ((this)->*(_Read[read_index]))(curpixel, userdata, object); |
439 | 470 | |
440 | | if(m_rdp->ZCompare(zbcur, zhbcur, sz, dzpix, userdata, object)) |
| 471 | if(ZCompare(zbcur, zhbcur, sz, dzpix, userdata, object)) |
441 | 472 | { |
442 | | m_rdp->GetDitherValues(scanline, j, &cdith, &adith, object); |
| 473 | GetDitherValues(scanline, j, &cdith, &adith, object); |
443 | 474 | |
444 | | bool rendered = ((&m_rdp->Blender)->*(m_rdp->Blender.blend2[(userdata->BlendEnable << 2) | blend_index]))(&fir, &fig, &fib, cdith, adith, partialreject, sel0, sel1, acmode, userdata, object); |
| 475 | bool rendered = ((&Blender)->*(Blender.blend2[(userdata->BlendEnable << 2) | blend_index]))(&fir, &fig, &fib, cdith, adith, partialreject, sel0, sel1, acmode, userdata, object); |
445 | 476 | |
446 | 477 | if (rendered) |
447 | 478 | { |
448 | 479 | ((this)->*(_Write[write_index | userdata->BlendEnable]))(curpixel, fir, fig, fib, userdata, object); |
449 | 480 | if (object.OtherModes.z_update_en) |
450 | 481 | { |
451 | | m_rdp->ZStore(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); |
| 482 | ZStore(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); |
452 | 483 | } |
453 | 484 | } |
454 | 485 | } |
| 486 | sss = userdata->m_precomp_s; |
| 487 | sst = userdata->m_precomp_t; |
455 | 488 | } |
456 | 489 | |
457 | 490 | r.w += drinc; |
r25470 | r25471 | |
471 | 504 | { |
472 | 505 | int clipx1 = object.Scissor.m_xh; |
473 | 506 | int clipx2 = object.Scissor.m_xl; |
474 | | n64_rdp *m_rdp = object.m_rdp; |
475 | 507 | int tilenum = object.tilenum; |
476 | 508 | bool flip = object.flip; |
477 | 509 | |
r25470 | r25471 | |
503 | 535 | { |
504 | 536 | INT32 sss = s.h.h; |
505 | 537 | INT32 sst = t.h.h; |
506 | | m_rdp->TexPipe.Copy(&userdata->Texel0Color, sss, sst, tilenum, object, userdata); |
| 538 | TexPipe.Copy(&userdata->Texel0Color, sss, sst, tilenum, object, userdata); |
507 | 539 | |
508 | 540 | UINT32 curpixel = fb_index + x; |
509 | 541 | if ((userdata->Texel0Color.i.a != 0) || (!object.OtherModes.alpha_compare_en)) |
trunk/src/mame/video/rdptpipe.c
r25470 | r25471 | |
36 | 36 | |
37 | 37 | void N64TexturePipeT::Mask(INT32* S, INT32* T, INT32 num, const rdp_poly_state& object) |
38 | 38 | { |
39 | | const N64Tile* tile = object.m_tiles; |
| 39 | const N64Tile* tiles = object.m_tiles; |
40 | 40 | |
41 | | if (tile[num].mask_s) |
| 41 | if (tiles[num].mask_s) |
42 | 42 | { |
43 | | INT32 wrap = *S >> (tile[num].mask_s > 10 ? 10 : tile[num].mask_s); |
| 43 | INT32 wrap = *S >> (tiles[num].mask_s > 10 ? 10 : tiles[num].mask_s); |
44 | 44 | wrap &= 1; |
45 | | if (tile[num].ms && wrap) |
| 45 | if (tiles[num].ms && wrap) |
46 | 46 | { |
47 | 47 | *S = (~(*S)); |
48 | 48 | } |
49 | | *S &= m_maskbits_table[tile[num].mask_s]; |
| 49 | *S &= m_maskbits_table[tiles[num].mask_s]; |
50 | 50 | } |
51 | 51 | |
52 | | if (tile[num].mask_t) |
| 52 | if (tiles[num].mask_t) |
53 | 53 | { |
54 | | INT32 wrap = *T >> (tile[num].mask_t > 10 ? 10 : tile[num].mask_t); |
| 54 | INT32 wrap = *T >> (tiles[num].mask_t > 10 ? 10 : tiles[num].mask_t); |
55 | 55 | wrap &= 1; |
56 | | if (tile[num].mt && wrap) |
| 56 | if (tiles[num].mt && wrap) |
57 | 57 | { |
58 | 58 | *T = (~(*T)); |
59 | 59 | } |
60 | | *T &= m_maskbits_table[tile[num].mask_t]; |
| 60 | *T &= m_maskbits_table[tiles[num].mask_t]; |
61 | 61 | } |
62 | 62 | } |
63 | 63 | |
| 64 | #define MASK_COUPLED(param, param1, num, coord) \ |
| 65 | if (tiles[num].mask_##coord) \ |
| 66 | { \ |
| 67 | INT32 maskbits_##coord = m_maskbits_table[tiles[num].mask_##coord]; \ |
| 68 | if (tiles[num].m##coord) \ |
| 69 | { \ |
| 70 | INT32 wrapthreshold = tiles[num].mask_##coord > 10 ? 10 : tiles[num].mask_##coord; \ |
| 71 | if ((param >> wrapthreshold) & 1) \ |
| 72 | { \ |
| 73 | param = ~param; \ |
| 74 | } \ |
| 75 | if ((param1 >> wrapthreshold) & 1) \ |
| 76 | { \ |
| 77 | param1 = ~param1; \ |
| 78 | } \ |
| 79 | } \ |
| 80 | param &= maskbits_##coord; \ |
| 81 | param1 &= maskbits_##coord; \ |
| 82 | } |
| 83 | |
64 | 84 | void N64TexturePipeT::MaskCoupled(INT32* S, INT32* S1, INT32* T, INT32* T1, INT32 num, const rdp_poly_state& object) |
65 | 85 | { |
66 | | const N64Tile* tile = object.m_tiles; |
| 86 | const N64Tile* tiles = object.m_tiles; |
67 | 87 | |
68 | | if (tile[num].mask_s) |
| 88 | if (tiles[num].mask_s) |
69 | 89 | { |
70 | | INT32 maskbits_s = m_maskbits_table[tile[num].mask_s]; |
71 | | if (tile[num].ms) |
| 90 | INT32 maskbits_s = m_maskbits_table[tiles[num].mask_s]; |
| 91 | if (tiles[num].ms) |
72 | 92 | { |
73 | | INT32 swrapthreshold = tile[num].mask_s > 10 ? 10 : tile[num].mask_s; |
| 93 | INT32 swrapthreshold = tiles[num].mask_s > 10 ? 10 : tiles[num].mask_s; |
74 | 94 | INT32 wrap = (*S >> swrapthreshold) & 1; |
75 | 95 | INT32 wrap1 = (*S1 >> swrapthreshold) & 1; |
76 | 96 | if (wrap) |
r25470 | r25471 | |
86 | 106 | *S1 &= maskbits_s; |
87 | 107 | } |
88 | 108 | |
89 | | if (tile[num].mask_t) |
| 109 | if (tiles[num].mask_t) |
90 | 110 | { |
91 | | INT32 maskbits_t = m_maskbits_table[tile[num].mask_t]; |
92 | | if (tile[num].mt) |
| 111 | INT32 maskbits_t = m_maskbits_table[tiles[num].mask_t]; |
| 112 | if (tiles[num].mt) |
93 | 113 | { |
94 | | INT32 twrapthreshold = tile[num].mask_t > 10 ? 10 : tile[num].mask_t; |
| 114 | INT32 twrapthreshold = tiles[num].mask_t > 10 ? 10 : tiles[num].mask_t; |
95 | 115 | INT32 wrap = (*T >> twrapthreshold) & 1; |
96 | 116 | INT32 wrap1 = (*T1 >> twrapthreshold) & 1; |
97 | 117 | if (wrap) |
r25470 | r25471 | |
108 | 128 | } |
109 | 129 | } |
110 | 130 | |
| 131 | #define SHIFT_CYCLE(param, max, num, coord) \ |
| 132 | param = SIGN16(param); \ |
| 133 | if (tiles[num].shift_##coord < 11) \ |
| 134 | { \ |
| 135 | param >>= tiles[num].shift_##coord; \ |
| 136 | } \ |
| 137 | else \ |
| 138 | { \ |
| 139 | param <<= (16 - tiles[num].shift_##coord); \ |
| 140 | } \ |
| 141 | param = SIGN16(param); \ |
| 142 | max = ((param >> 3) >= tiles[num].coord##h); |
| 143 | |
111 | 144 | void N64TexturePipeT::ShiftCycle(INT32* S, INT32* T, INT32* maxs, INT32* maxt, UINT32 num, const rdp_poly_state& object) |
112 | 145 | { |
113 | | const N64Tile* tile = object.m_tiles; |
| 146 | const N64Tile* tiles = object.m_tiles; |
114 | 147 | *S = SIGN16(*S); |
115 | | *T = SIGN16(*T); |
116 | | if (tile[num].shift_s < 11) |
| 148 | if (tiles[num].shift_s < 11) |
117 | 149 | { |
118 | | *S >>= tile[num].shift_s; |
| 150 | *S >>= tiles[num].shift_s; |
119 | 151 | } |
120 | 152 | else |
121 | 153 | { |
122 | | *S <<= (16 - tile[num].shift_s); |
| 154 | *S <<= (16 - tiles[num].shift_s); |
123 | 155 | } |
124 | 156 | *S = SIGN16(*S); |
125 | | if (tile[num].shift_t < 11) |
| 157 | *maxs = ((*S >> 3) >= tiles[num].sh); |
| 158 | |
| 159 | *T = SIGN16(*T); |
| 160 | if (tiles[num].shift_t < 11) |
126 | 161 | { |
127 | | *T >>= tile[num].shift_t; |
| 162 | *T >>= tiles[num].shift_t; |
128 | 163 | } |
129 | 164 | else |
130 | 165 | { |
131 | | *T <<= (16 - tile[num].shift_t); |
| 166 | *T <<= (16 - tiles[num].shift_t); |
132 | 167 | } |
133 | 168 | *T = SIGN16(*T); |
134 | | |
135 | | *maxs = ((*S >> 3) >= tile[num].sh); |
136 | | *maxt = ((*T >> 3) >= tile[num].th); |
| 169 | *maxt = ((*T >> 3) >= tiles[num].th); |
137 | 170 | } |
138 | 171 | |
139 | 172 | void N64TexturePipeT::ShiftCopy(INT32* S, INT32* T, UINT32 num, const rdp_poly_state& object) |
140 | 173 | { |
141 | | const N64Tile* tile = object.m_tiles; |
| 174 | const N64Tile* tiles = object.m_tiles; |
142 | 175 | *S = SIGN16(*S); |
143 | 176 | *T = SIGN16(*T); |
144 | | if (tile[num].shift_s < 11)//?-? tcu_tile |
| 177 | if (tiles[num].shift_s < 11)//?-? tcu_tile |
145 | 178 | { |
146 | | *S >>= tile[num].shift_s; |
| 179 | *S >>= tiles[num].shift_s; |
147 | 180 | } |
148 | 181 | else |
149 | 182 | { |
150 | | *S <<= (16 - tile[num].shift_s); |
| 183 | *S <<= (16 - tiles[num].shift_s); |
151 | 184 | } |
152 | 185 | *S = SIGN16(*S); |
153 | | if (tile[num].shift_t < 11) |
| 186 | if (tiles[num].shift_t < 11) |
154 | 187 | { |
155 | | *T >>= tile[num].shift_t; |
| 188 | *T >>= tiles[num].shift_t; |
156 | 189 | } |
157 | 190 | else |
158 | 191 | { |
159 | | *T <<= (16 - tile[num].shift_t); |
| 192 | *T <<= (16 - tiles[num].shift_t); |
160 | 193 | } |
161 | 194 | *T = SIGN16(*T); |
162 | 195 | } |
163 | 196 | |
| 197 | #define CLAMP_CYCLE(param, frac, max, num, coord) \ |
| 198 | if (tiles[num].c##coord || !tiles[num].mask_##coord) \ |
| 199 | { \ |
| 200 | if (param & 0x10000) \ |
| 201 | { \ |
| 202 | param = 0; \ |
| 203 | frac = 0; \ |
| 204 | } \ |
| 205 | else if (max) \ |
| 206 | { \ |
| 207 | param = m_clamp_##coord##_diff[num]; \ |
| 208 | frac = 0; \ |
| 209 | } \ |
| 210 | else \ |
| 211 | { \ |
| 212 | param = (SIGN17(param) >> 5) & 0x1fff; \ |
| 213 | } \ |
| 214 | } \ |
| 215 | else \ |
| 216 | { \ |
| 217 | param = (SIGN17(param) >> 5) & 0x1fff; \ |
| 218 | } |
| 219 | |
164 | 220 | void N64TexturePipeT::ClampCycle(INT32* S, INT32* T, INT32* SFRAC, INT32* TFRAC, INT32 maxs, INT32 maxt, INT32 num, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
165 | 221 | { |
166 | | const N64Tile* tile = object.m_tiles; |
167 | | int dos = tile[num].cs || !tile[num].mask_s; |
168 | | int dot = tile[num].ct || !tile[num].mask_t; |
| 222 | const N64Tile* tiles = object.m_tiles; |
169 | 223 | |
170 | | if (dos) |
| 224 | if (tiles[num].cs || !tiles[num].mask_s) |
171 | 225 | { |
172 | 226 | if (*S & 0x10000) |
173 | 227 | { |
r25470 | r25471 | |
189 | 243 | *S = (SIGN17(*S) >> 5) & 0x1fff; |
190 | 244 | } |
191 | 245 | |
192 | | if (dot) |
| 246 | if (tiles[num].ct || !tiles[num].mask_t) |
193 | 247 | { |
194 | 248 | if (*T & 0x10000) |
195 | 249 | { |
r25470 | r25471 | |
214 | 268 | |
215 | 269 | void N64TexturePipeT::ClampCycleLight(INT32* S, INT32* T, bool maxs, bool maxt, INT32 num, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
216 | 270 | { |
217 | | const N64Tile* tile = object.m_tiles; |
218 | | int dos = tile[num].cs || !tile[num].mask_s; |
219 | | int dot = tile[num].ct || !tile[num].mask_t; |
| 271 | const N64Tile* tiles = object.m_tiles; |
| 272 | int dos = tiles[num].cs || !tiles[num].mask_s; |
| 273 | int dot = tiles[num].ct || !tiles[num].mask_t; |
220 | 274 | |
221 | 275 | if (dos) |
222 | 276 | { |
r25470 | r25471 | |
259 | 313 | } |
260 | 314 | } |
261 | 315 | |
262 | | void N64TexturePipeT::Cycle(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
| 316 | void N64TexturePipeT::CycleNearest(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
263 | 317 | { |
264 | | const N64Tile* tile = object.m_tiles; |
| 318 | const N64Tile* tiles = object.m_tiles; |
| 319 | const N64Tile& tile = tiles[tilenum]; |
| 320 | UINT32 tformat = tile.format; |
| 321 | UINT32 tsize = tile.size; |
| 322 | UINT32 tpal = tile.palette; |
| 323 | UINT32 index = (tformat << 4) | (tsize << 2) | ((UINT32) object.OtherModes.en_tlut << 1) | (UINT32) object.OtherModes.tlut_type; |
265 | 324 | |
266 | 325 | #define TRELATIVE(x, y) ((((x) >> 3) - (y)) << 3) | (x & 7); |
267 | | INT32 bilerp = cycle ? object.OtherModes.bi_lerp1 : object.OtherModes.bi_lerp0; |
268 | 326 | int convert = object.OtherModes.convert_one && cycle; |
269 | 327 | Color t0; |
270 | | Color t1; |
271 | | Color t2; |
272 | | Color t3; |
273 | | if (object.OtherModes.sample_type) |
| 328 | |
| 329 | INT32 sss1 = SSS; |
| 330 | INT32 maxs; |
| 331 | SHIFT_CYCLE(sss1, maxs, tilenum, s); |
| 332 | sss1 = TRELATIVE(sss1, tile.sl); |
| 333 | |
| 334 | INT32 sst1 = SST; |
| 335 | INT32 maxt; |
| 336 | SHIFT_CYCLE(sst1, maxt, tilenum, t); |
| 337 | sst1 = TRELATIVE(sst1, tile.tl); |
| 338 | |
| 339 | ClampCycleLight(&sss1, &sst1, maxs, maxt, tilenum, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 340 | Mask(&sss1, &sst1, tilenum, object); |
| 341 | |
| 342 | UINT32 tbase = tile.tmem + ((tile.line * sst1) & 0x1ff); |
| 343 | |
| 344 | t0.c = ((this)->*(TexelFetch[index]))(sss1, sst1, tbase, tpal, userdata); |
| 345 | |
| 346 | INT32 newk0 = SIGN9(m_rdp->GetK0()); |
| 347 | INT32 newk1 = SIGN9(m_rdp->GetK1()); |
| 348 | INT32 newk2 = SIGN9(m_rdp->GetK2()); |
| 349 | INT32 newk3 = SIGN9(m_rdp->GetK3()); |
| 350 | INT32 invk0 = ~newk0; |
| 351 | INT32 invk1 = ~newk1; |
| 352 | INT32 invk2 = ~newk2; |
| 353 | INT32 invk3 = ~newk3; |
| 354 | if (convert) |
274 | 355 | { |
275 | | int sss1, sst1, sss2, sst2; |
| 356 | t0 = *prev; |
| 357 | } |
| 358 | t0.i.r = SIGN9(t0.i.r); |
| 359 | t0.i.g = SIGN9(t0.i.g); |
| 360 | t0.i.b = SIGN9(t0.i.b); |
| 361 | TEX->i.r = t0.i.b + (((newk0 - invk0) * t0.i.g + 0x80) >> 8); |
| 362 | TEX->i.g = t0.i.b + (((newk1 - invk1) * t0.i.r + (newk2 - invk2) * t0.i.g + 0x80) >> 8); |
| 363 | TEX->i.b = t0.i.b + (((newk3 - invk3) * t0.i.r + 0x80) >> 8); |
| 364 | TEX->i.a = t0.i.b; |
| 365 | TEX->i.r &= 0x1ff; |
| 366 | TEX->i.g &= 0x1ff; |
| 367 | TEX->i.b &= 0x1ff; |
| 368 | TEX->i.a &= 0x1ff; |
| 369 | } |
276 | 370 | |
277 | | INT32 invsf = 0; |
278 | | INT32 invtf = 0; |
279 | | int center = 0; |
| 371 | void N64TexturePipeT::CycleNearestLerp(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
| 372 | { |
| 373 | const N64Tile* tiles = object.m_tiles; |
| 374 | const N64Tile& tile = tiles[tilenum]; |
| 375 | UINT32 tformat = tile.format; |
| 376 | UINT32 tsize = tile.size; |
| 377 | UINT32 tpal = tile.palette; |
| 378 | UINT32 index = (tformat << 4) | (tsize << 2) | ((UINT32) object.OtherModes.en_tlut << 1) | (UINT32) object.OtherModes.tlut_type; |
280 | 379 | |
281 | | sss1 = SSS; |
282 | | sst1 = SST; |
| 380 | #define TRELATIVE(x, y) ((((x) >> 3) - (y)) << 3) | (x & 7); |
| 381 | Color t0; |
283 | 382 | |
284 | | INT32 maxs; |
285 | | INT32 maxt; |
| 383 | INT32 sss1 = SSS; |
| 384 | INT32 maxs; |
| 385 | SHIFT_CYCLE(sss1, maxs, tilenum, s); |
| 386 | sss1 = TRELATIVE(sss1, tile.sl); |
286 | 387 | |
287 | | ShiftCycle(&sss1, &sst1, &maxs, &maxt, tilenum, object); |
| 388 | INT32 sst1 = SST; |
| 389 | INT32 maxt; |
| 390 | SHIFT_CYCLE(sst1, maxt, tilenum, t); |
| 391 | sst1 = TRELATIVE(sst1, tile.tl); |
288 | 392 | |
289 | | sss1 = TRELATIVE(sss1, tile[tilenum].sl); |
290 | | sst1 = TRELATIVE(sst1, tile[tilenum].tl); |
| 393 | ClampCycleLight(&sss1, &sst1, maxs, maxt, tilenum, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 394 | Mask(&sss1, &sst1, tilenum, object); |
291 | 395 | |
292 | | INT32 sfrac = sss1 & 0x1f; |
293 | | INT32 tfrac = sst1 & 0x1f; |
| 396 | UINT32 tbase = tile.tmem + ((tile.line * sst1) & 0x1ff); |
294 | 397 | |
295 | | ClampCycle(&sss1, &sst1, &sfrac, &tfrac, maxs, maxt, tilenum, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 398 | (*TEX).c = ((this)->*(TexelFetch[index]))(sss1, sst1, tbase, tpal, userdata); |
| 399 | } |
296 | 400 | |
297 | | sss2 = sss1 + 1; |
298 | | sst2 = sst1 + 1; |
| 401 | void N64TexturePipeT::CycleLinear(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
| 402 | { |
| 403 | const N64Tile* tiles = object.m_tiles; |
| 404 | const N64Tile& tile = tiles[tilenum]; |
299 | 405 | |
300 | | MaskCoupled(&sss1, &sss2, &sst1, &sst2, tilenum, object); |
| 406 | #define TRELATIVE(x, y) ((((x) >> 3) - (y)) << 3) | (x & 7); |
| 407 | int convert = object.OtherModes.convert_one && cycle; |
| 408 | UINT32 tpal = tile.palette; |
| 409 | UINT32 index = (tile.format << 4) | (tile.size << 2) | ((UINT32) object.OtherModes.en_tlut << 1) | (UINT32) object.OtherModes.tlut_type; |
301 | 410 | |
302 | | bool upper = ((sfrac + tfrac) >= 0x20); |
| 411 | INT32 invsf = 0; |
| 412 | INT32 sss1 = SSS; |
| 413 | INT32 maxs; |
| 414 | SHIFT_CYCLE(sss1, maxs, tilenum, s); |
| 415 | sss1 = TRELATIVE(sss1, tile.sl); |
| 416 | INT32 sfrac = sss1 & 0x1f; |
| 417 | CLAMP_CYCLE(sss1, sfrac, maxs, tilenum, s); |
| 418 | INT32 sss2 = sss1 + 1; |
| 419 | MASK_COUPLED(sss1, sss2, tilenum, s); |
303 | 420 | |
304 | | if (upper) |
305 | | { |
306 | | invsf = 0x20 - sfrac; |
307 | | invtf = 0x20 - tfrac; |
308 | | } |
| 421 | INT32 invtf = 0; |
| 422 | INT32 sst1 = SST; |
| 423 | INT32 maxt; |
| 424 | SHIFT_CYCLE(sst1, maxt, tilenum, t); |
| 425 | sst1 = TRELATIVE(sst1, tile.tl); |
| 426 | INT32 tfrac = sst1 & 0x1f; |
| 427 | CLAMP_CYCLE(sst1, tfrac, maxt, tilenum, t); |
| 428 | INT32 sst2 = sst1 + 1; |
| 429 | MASK_COUPLED(sst1, sst2, tilenum, t); |
309 | 430 | |
310 | | center = (sfrac == 0x10) && (tfrac == 0x10) && object.OtherModes.mid_texel; |
| 431 | UINT32 tbase = tile.tmem + ((tile.line * sst1) & 0x1ff); |
311 | 432 | |
| 433 | bool upper = ((sfrac + tfrac) >= 0x20); |
| 434 | |
| 435 | if (upper) |
| 436 | { |
| 437 | invsf = 0x20 - sfrac; |
312 | 438 | invsf <<= 3; |
| 439 | |
| 440 | invtf = 0x20 - tfrac; |
313 | 441 | invtf <<= 3; |
314 | | sfrac <<= 3; |
315 | | tfrac <<= 3; |
| 442 | } |
316 | 443 | |
317 | | t0.c = Fetch(sss1, sst1, tilenum, object, userdata); |
| 444 | sfrac <<= 3; |
| 445 | tfrac <<= 3; |
318 | 446 | |
319 | | if (bilerp) |
320 | | { |
321 | | t1.c = Fetch(sss2, sst1, tilenum, object, userdata); |
322 | | t2.c = Fetch(sss1, sst2, tilenum, object, userdata); |
323 | | t3.c = Fetch(sss2, sst2, tilenum, object, userdata); |
324 | | if (!center) |
325 | | { |
326 | | if (upper) |
327 | | { |
328 | | TEX->i.r = t3.i.r + (((invsf * (t2.i.r - t3.i.r)) + (invtf * (t1.i.r - t3.i.r)) + 0x80) >> 8); |
329 | | TEX->i.g = t3.i.g + (((invsf * (t2.i.g - t3.i.g)) + (invtf * (t1.i.g - t3.i.g)) + 0x80) >> 8); |
330 | | TEX->i.b = t3.i.b + (((invsf * (t2.i.b - t3.i.b)) + (invtf * (t1.i.b - t3.i.b)) + 0x80) >> 8); |
331 | | TEX->i.a = t3.i.a + (((invsf * (t2.i.a - t3.i.a)) + (invtf * (t1.i.a - t3.i.a)) + 0x80) >> 8); |
332 | | } |
333 | | else |
334 | | { |
335 | | TEX->i.r = t0.i.r + (((sfrac * (t1.i.r - t0.i.r)) + (tfrac * (t2.i.r - t0.i.r)) + 0x80) >> 8); |
336 | | TEX->i.g = t0.i.g + (((sfrac * (t1.i.g - t0.i.g)) + (tfrac * (t2.i.g - t0.i.g)) + 0x80) >> 8); |
337 | | TEX->i.b = t0.i.b + (((sfrac * (t1.i.b - t0.i.b)) + (tfrac * (t2.i.b - t0.i.b)) + 0x80) >> 8); |
338 | | TEX->i.a = t0.i.a + (((sfrac * (t1.i.a - t0.i.a)) + (tfrac * (t2.i.a - t0.i.a)) + 0x80) >> 8); |
339 | | } |
340 | | TEX->i.r &= 0x1ff; |
341 | | TEX->i.g &= 0x1ff; |
342 | | TEX->i.b &= 0x1ff; |
343 | | TEX->i.a &= 0x1ff; |
344 | | } |
345 | | else |
346 | | { |
347 | | TEX->i.r = (t0.i.r + t1.i.r + t2.i.r + t3.i.r) >> 2; |
348 | | TEX->i.g = (t0.i.g + t1.i.g + t2.i.g + t3.i.g) >> 2; |
349 | | TEX->i.b = (t0.i.b + t1.i.b + t2.i.b + t3.i.b) >> 2; |
350 | | TEX->i.a = (t0.i.a + t1.i.a + t2.i.a + t3.i.a) >> 2; |
351 | | } |
352 | | } |
353 | | else |
354 | | { |
355 | | INT32 newk0 = SIGN9(m_rdp->GetK0()); |
356 | | INT32 newk1 = SIGN9(m_rdp->GetK1()); |
357 | | INT32 newk2 = SIGN9(m_rdp->GetK2()); |
358 | | INT32 newk3 = SIGN9(m_rdp->GetK3()); |
359 | | INT32 invk0 = ~newk0; |
360 | | INT32 invk1 = ~newk1; |
361 | | INT32 invk2 = ~newk2; |
362 | | INT32 invk3 = ~newk3; |
363 | | if (convert) |
364 | | { |
365 | | t0 = *prev; |
366 | | } |
367 | | t0.i.r = SIGN9(t0.i.r); t0.i.g = SIGN9(t0.i.g); t0.i.b = SIGN9(t0.i.b); |
368 | | TEX->i.r = t0.i.b + (((newk0 - invk0) * t0.i.g + 0x80) >> 8); |
369 | | TEX->i.g = t0.i.b + (((newk1 - invk1) * t0.i.r + (newk2 - invk2) * t0.i.g + 0x80) >> 8); |
370 | | TEX->i.b = t0.i.b + (((newk3 - invk3) * t0.i.r + 0x80) >> 8); |
371 | | TEX->i.a = t0.i.b; |
372 | | TEX->i.r &= 0x1ff; |
373 | | TEX->i.g &= 0x1ff; |
374 | | TEX->i.b &= 0x1ff; |
375 | | TEX->i.a &= 0x1ff; |
376 | | } |
| 447 | Color t0; |
| 448 | t0.c = ((this)->*(TexelFetch[index]))(sss1, sst1, tbase, tpal, userdata); |
| 449 | INT32 newk0 = SIGN9(m_rdp->GetK0()); |
| 450 | INT32 newk1 = SIGN9(m_rdp->GetK1()); |
| 451 | INT32 newk2 = SIGN9(m_rdp->GetK2()); |
| 452 | INT32 newk3 = SIGN9(m_rdp->GetK3()); |
| 453 | INT32 invk0 = ~newk0; |
| 454 | INT32 invk1 = ~newk1; |
| 455 | INT32 invk2 = ~newk2; |
| 456 | INT32 invk3 = ~newk3; |
| 457 | if (convert) |
| 458 | { |
| 459 | t0 = *prev; |
377 | 460 | } |
378 | | else |
| 461 | t0.i.r = SIGN9(t0.i.r); t0.i.g = SIGN9(t0.i.g); t0.i.b = SIGN9(t0.i.b); |
| 462 | TEX->i.r = t0.i.b + (((newk0 - invk0) * t0.i.g + 0x80) >> 8); |
| 463 | TEX->i.g = t0.i.b + (((newk1 - invk1) * t0.i.r + (newk2 - invk2) * t0.i.g + 0x80) >> 8); |
| 464 | TEX->i.b = t0.i.b + (((newk3 - invk3) * t0.i.r + 0x80) >> 8); |
| 465 | TEX->i.a = t0.i.b; |
| 466 | TEX->i.r &= 0x1ff; |
| 467 | TEX->i.g &= 0x1ff; |
| 468 | TEX->i.b &= 0x1ff; |
| 469 | TEX->i.a &= 0x1ff; |
| 470 | } |
| 471 | |
| 472 | void N64TexturePipeT::CycleLinearLerp(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
| 473 | { |
| 474 | const N64Tile* tiles = object.m_tiles; |
| 475 | const N64Tile& tile = tiles[tilenum]; |
| 476 | |
| 477 | #define TRELATIVE(x, y) ((((x) >> 3) - (y)) << 3) | (x & 7); |
| 478 | UINT32 tpal = tile.palette; |
| 479 | UINT32 index = (tile.format << 4) | (tile.size << 2) | ((UINT32) object.OtherModes.en_tlut << 1) | (UINT32) object.OtherModes.tlut_type; |
| 480 | |
| 481 | int center = 0; |
| 482 | |
| 483 | INT32 invsf = 0; |
| 484 | INT32 sss1 = SSS; |
| 485 | INT32 maxs; |
| 486 | SHIFT_CYCLE(sss1, maxs, tilenum, s); |
| 487 | sss1 = TRELATIVE(sss1, tile.sl); |
| 488 | INT32 sfrac = sss1 & 0x1f; |
| 489 | CLAMP_CYCLE(sss1, sfrac, maxs, tilenum, s); |
| 490 | INT32 sss2 = sss1 + 1; |
| 491 | MASK_COUPLED(sss1, sss2, tilenum, s); |
| 492 | |
| 493 | INT32 invtf = 0; |
| 494 | INT32 sst1 = SST; |
| 495 | INT32 maxt; |
| 496 | SHIFT_CYCLE(sst1, maxt, tilenum, t); |
| 497 | sst1 = TRELATIVE(sst1, tile.tl); |
| 498 | INT32 tfrac = sst1 & 0x1f; |
| 499 | CLAMP_CYCLE(sst1, tfrac, maxt, tilenum, t); |
| 500 | INT32 sst2 = sst1 + 1; |
| 501 | MASK_COUPLED(sst1, sst2, tilenum, t); |
| 502 | |
| 503 | UINT32 tbase1 = tile.tmem + ((tile.line * sst1) & 0x1ff); |
| 504 | UINT32 tbase2 = tile.tmem + ((tile.line * sst2) & 0x1ff); |
| 505 | |
| 506 | bool upper = ((sfrac + tfrac) >= 0x20); |
| 507 | |
| 508 | if (upper) |
379 | 509 | { |
380 | | INT32 sss1 = SSS; |
381 | | INT32 sst1 = SST; |
| 510 | invsf = 0x20 - sfrac; |
| 511 | invsf <<= 3; |
382 | 512 | |
383 | | INT32 maxs; |
384 | | INT32 maxt; |
| 513 | invtf = 0x20 - tfrac; |
| 514 | invtf <<= 3; |
| 515 | } |
385 | 516 | |
386 | | ShiftCycle(&sss1, &sst1, &maxs, &maxt, tilenum, object); |
387 | | sss1 = TRELATIVE(sss1, tile[tilenum].sl); |
388 | | sst1 = TRELATIVE(sst1, tile[tilenum].tl); |
| 517 | center = (sfrac == 0x10) && (tfrac == 0x10) && object.OtherModes.mid_texel; |
389 | 518 | |
390 | | ClampCycleLight(&sss1, &sst1, maxs, maxt, tilenum, userdata, object, m_clamp_s_diff, m_clamp_t_diff); |
| 519 | sfrac <<= 3; |
| 520 | tfrac <<= 3; |
391 | 521 | |
392 | | Mask(&sss1, &sst1, tilenum, object); |
393 | | |
394 | | t0.c = Fetch(sss1, sst1, tilenum, object, userdata); |
395 | | if (bilerp) |
| 522 | Color t1; |
| 523 | Color t2; |
| 524 | t1.c = ((this)->*(TexelFetch[index]))(sss2, sst1, tbase1, tpal, userdata); |
| 525 | t2.c = ((this)->*(TexelFetch[index]))(sss1, sst2, tbase2, tpal, userdata); |
| 526 | if (!center) |
| 527 | { |
| 528 | if (upper) |
396 | 529 | { |
397 | | *TEX = t0; |
| 530 | Color t3; |
| 531 | t3.c = ((this)->*(TexelFetch[index]))(sss2, sst2, tbase2, tpal, userdata); |
| 532 | TEX->i.r = t3.i.r + (((invsf * (t2.i.r - t3.i.r)) + (invtf * (t1.i.r - t3.i.r)) + 0x80) >> 8); |
| 533 | TEX->i.g = t3.i.g + (((invsf * (t2.i.g - t3.i.g)) + (invtf * (t1.i.g - t3.i.g)) + 0x80) >> 8); |
| 534 | TEX->i.b = t3.i.b + (((invsf * (t2.i.b - t3.i.b)) + (invtf * (t1.i.b - t3.i.b)) + 0x80) >> 8); |
| 535 | TEX->i.a = t3.i.a + (((invsf * (t2.i.a - t3.i.a)) + (invtf * (t1.i.a - t3.i.a)) + 0x80) >> 8); |
398 | 536 | } |
399 | 537 | else |
400 | 538 | { |
401 | | INT32 newk0 = SIGN9(m_rdp->GetK0()); |
402 | | INT32 newk1 = SIGN9(m_rdp->GetK1()); |
403 | | INT32 newk2 = SIGN9(m_rdp->GetK2()); |
404 | | INT32 newk3 = SIGN9(m_rdp->GetK3()); |
405 | | INT32 invk0 = ~newk0; |
406 | | INT32 invk1 = ~newk1; |
407 | | INT32 invk2 = ~newk2; |
408 | | INT32 invk3 = ~newk3; |
409 | | if (convert) |
410 | | { |
411 | | t0 = *prev; |
412 | | } |
413 | | t0.i.r = SIGN9(t0.i.r); |
414 | | t0.i.g = SIGN9(t0.i.g); |
415 | | t0.i.b = SIGN9(t0.i.b); |
416 | | TEX->i.r = t0.i.b + (((newk0 - invk0) * t0.i.g + 0x80) >> 8); |
417 | | TEX->i.g = t0.i.b + (((newk1 - invk1) * t0.i.r + (newk2 - invk2) * t0.i.g + 0x80) >> 8); |
418 | | TEX->i.b = t0.i.b + (((newk3 - invk3) * t0.i.r + 0x80) >> 8); |
419 | | TEX->i.a = t0.i.b; |
420 | | TEX->i.r &= 0x1ff; |
421 | | TEX->i.g &= 0x1ff; |
422 | | TEX->i.b &= 0x1ff; |
423 | | TEX->i.a &= 0x1ff; |
| 539 | Color t0; |
| 540 | t0.c = ((this)->*(TexelFetch[index]))(sss1, sst1, tbase1, tpal, userdata); |
| 541 | TEX->i.r = t0.i.r + (((sfrac * (t1.i.r - t0.i.r)) + (tfrac * (t2.i.r - t0.i.r)) + 0x80) >> 8); |
| 542 | TEX->i.g = t0.i.g + (((sfrac * (t1.i.g - t0.i.g)) + (tfrac * (t2.i.g - t0.i.g)) + 0x80) >> 8); |
| 543 | TEX->i.b = t0.i.b + (((sfrac * (t1.i.b - t0.i.b)) + (tfrac * (t2.i.b - t0.i.b)) + 0x80) >> 8); |
| 544 | TEX->i.a = t0.i.a + (((sfrac * (t1.i.a - t0.i.a)) + (tfrac * (t2.i.a - t0.i.a)) + 0x80) >> 8); |
424 | 545 | } |
| 546 | TEX->i.r &= 0x1ff; |
| 547 | TEX->i.g &= 0x1ff; |
| 548 | TEX->i.b &= 0x1ff; |
| 549 | TEX->i.a &= 0x1ff; |
425 | 550 | } |
| 551 | else |
| 552 | { |
| 553 | Color t0; |
| 554 | Color t3; |
| 555 | t0.c = ((this)->*(TexelFetch[index]))(sss1, sst1, 1, tpal, userdata); |
| 556 | t3.c = ((this)->*(TexelFetch[index]))(sss2, sst2, tbase2, tpal, userdata); |
| 557 | TEX->i.r = (t0.i.r + t1.i.r + t2.i.r + t3.i.r) >> 2; |
| 558 | TEX->i.g = (t0.i.g + t1.i.g + t2.i.g + t3.i.g) >> 2; |
| 559 | TEX->i.b = (t0.i.b + t1.i.b + t2.i.b + t3.i.b) >> 2; |
| 560 | TEX->i.a = (t0.i.a + t1.i.a + t2.i.a + t3.i.a) >> 2; |
| 561 | } |
426 | 562 | } |
427 | 563 | |
428 | 564 | void N64TexturePipeT::Copy(Color* TEX, INT32 SSS, INT32 SST, UINT32 tilenum, const rdp_poly_state& object, rdp_span_aux *userdata) |
429 | 565 | { |
430 | | const N64Tile* tile = object.m_tiles; |
| 566 | const N64Tile* tiles = object.m_tiles; |
| 567 | const N64Tile& tile = tiles[tilenum]; |
431 | 568 | INT32 sss1 = SSS; |
432 | 569 | INT32 sst1 = SST; |
433 | 570 | ShiftCopy(&sss1, &sst1, tilenum, object); |
434 | | sss1 = TRELATIVE(sss1, tile[tilenum].sl); |
435 | | sst1 = TRELATIVE(sst1, tile[tilenum].tl); |
| 571 | sss1 = TRELATIVE(sss1, tile.sl); |
| 572 | sst1 = TRELATIVE(sst1, tile.tl); |
436 | 573 | sss1 = (SIGN17(sss1) >> 5) & 0x1fff; |
437 | 574 | sst1 = (SIGN17(sst1) >> 5) & 0x1fff; |
438 | 575 | Mask(&sss1, &sst1, tilenum, object); |
r25470 | r25471 | |
789 | 926 | |
790 | 927 | void N64TexturePipeT::CalculateClampDiffs(UINT32 prim_tile, rdp_span_aux *userdata, const rdp_poly_state& object, INT32 *m_clamp_s_diff, INT32 *m_clamp_t_diff) |
791 | 928 | { |
792 | | const N64Tile* tile = object.m_tiles; |
| 929 | const N64Tile* tiles = object.m_tiles; |
793 | 930 | if (object.OtherModes.cycle_type == CYCLE_TYPE_2) |
794 | 931 | { |
795 | 932 | if (object.OtherModes.tex_lod_en) |
r25470 | r25471 | |
798 | 935 | int end = 7; |
799 | 936 | for (; start <= end; start++) |
800 | 937 | { |
801 | | m_clamp_s_diff[start] = (tile[start].sh >> 2) - (tile[start].sl >> 2); |
802 | | m_clamp_t_diff[start] = (tile[start].th >> 2) - (tile[start].tl >> 2); |
| 938 | m_clamp_s_diff[start] = (tiles[start].sh >> 2) - (tiles[start].sl >> 2); |
| 939 | m_clamp_t_diff[start] = (tiles[start].th >> 2) - (tiles[start].tl >> 2); |
803 | 940 | } |
804 | 941 | } |
805 | 942 | else |
806 | 943 | { |
807 | 944 | int start = prim_tile; |
808 | 945 | int end = (prim_tile + 1) & 7; |
809 | | m_clamp_s_diff[start] = (tile[start].sh >> 2) - (tile[start].sl >> 2); |
810 | | m_clamp_t_diff[start] = (tile[start].th >> 2) - (tile[start].tl >> 2); |
811 | | m_clamp_s_diff[end] = (tile[end].sh >> 2) - (tile[end].sl >> 2); |
812 | | m_clamp_t_diff[end] = (tile[end].th >> 2) - (tile[end].tl >> 2); |
| 946 | m_clamp_s_diff[start] = (tiles[start].sh >> 2) - (tiles[start].sl >> 2); |
| 947 | m_clamp_t_diff[start] = (tiles[start].th >> 2) - (tiles[start].tl >> 2); |
| 948 | m_clamp_s_diff[end] = (tiles[end].sh >> 2) - (tiles[end].sl >> 2); |
| 949 | m_clamp_t_diff[end] = (tiles[end].th >> 2) - (tiles[end].tl >> 2); |
813 | 950 | } |
814 | 951 | } |
815 | 952 | else//1-cycle or copy |
816 | 953 | { |
817 | | m_clamp_s_diff[prim_tile] = (tile[prim_tile].sh >> 2) - (tile[prim_tile].sl >> 2); |
818 | | m_clamp_t_diff[prim_tile] = (tile[prim_tile].th >> 2) - (tile[prim_tile].tl >> 2); |
| 954 | m_clamp_s_diff[prim_tile] = (tiles[prim_tile].sh >> 2) - (tiles[prim_tile].sl >> 2); |
| 955 | m_clamp_t_diff[prim_tile] = (tiles[prim_tile].th >> 2) - (tiles[prim_tile].tl >> 2); |
819 | 956 | } |
820 | 957 | } |
821 | 958 | |
r25470 | r25471 | |
1377 | 1514 | |
1378 | 1515 | UINT32 N64TexturePipeT::Fetch(INT32 s, INT32 t, INT32 tilenum, const rdp_poly_state& object, rdp_span_aux *userdata) |
1379 | 1516 | { |
1380 | | const N64Tile* tile = object.m_tiles; |
1381 | | UINT32 tformat = tile[tilenum].format; |
1382 | | UINT32 tsize = tile[tilenum].size; |
| 1517 | const N64Tile* tiles = object.m_tiles; |
| 1518 | const N64Tile& tile = tiles[tilenum]; |
| 1519 | UINT32 tformat = tile.format; |
| 1520 | UINT32 tsize = tile.size; |
| 1521 | UINT32 tpal = tile.palette; |
| 1522 | UINT32 index = (tformat << 4) | (tsize << 2) | ((UINT32) object.OtherModes.en_tlut << 1) | (UINT32) object.OtherModes.tlut_type; |
1383 | 1523 | |
1384 | | UINT32 tbase = (tile[tilenum].line * t) & 0x1ff; |
1385 | | tbase += tile[tilenum].tmem; |
1386 | | UINT32 tpal = tile[tilenum].palette; |
| 1524 | UINT32 tbase = tile.tmem + ((tile.line * t) & 0x1ff); |
1387 | 1525 | |
1388 | | UINT32 index = (tformat << 4) | (tsize << 2) | ((UINT32) object.OtherModes.en_tlut << 1) | (UINT32) object.OtherModes.tlut_type; |
1389 | | |
1390 | 1526 | return ((this)->*(TexelFetch[index]))(s, t, tbase, tpal, userdata); |
1391 | 1527 | } |