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 | } |