diff --git a/core/hw/pvr/ta.cpp b/core/hw/pvr/ta.cpp index 176dd94d2..df932bbf9 100644 --- a/core/hw/pvr/ta.cpp +++ b/core/hw/pvr/ta.cpp @@ -270,10 +270,25 @@ static u32 opbSize(int n) static void markObjectListBlocks() { + u32 addr = TA_OL_BASE; + // opaque u32 opBlockSize = opbSize(TA_ALLOC_CTRL & 3); if (opBlockSize == 0) - return; - u32 addr = TA_OL_BASE; + { + // skip modvols OPBs + addr += opbSize((TA_ALLOC_CTRL >> 4) & 3) * (TA_GLOB_TILE_CLIP.tile_y_num + 1) * (TA_GLOB_TILE_CLIP.tile_x_num + 1); + // transparent + opBlockSize = opbSize((TA_ALLOC_CTRL >> 8) & 3); + if (opBlockSize == 0) + { + // skip TR modvols OPBs + addr += opbSize((TA_ALLOC_CTRL >> 12) & 3) * (TA_GLOB_TILE_CLIP.tile_y_num + 1) * (TA_GLOB_TILE_CLIP.tile_x_num + 1); + // punch-through + opBlockSize = opbSize((TA_ALLOC_CTRL >> 16) & 3); + if (opBlockSize == 0) + return; + } + } for (int y = 0; y <= TA_GLOB_TILE_CLIP.tile_y_num; y++) for (int x = 0; x <= TA_GLOB_TILE_CLIP.tile_x_num; x++) { diff --git a/core/hw/pvr/ta_ctx.h b/core/hw/pvr/ta_ctx.h index b5f30a19b..2ae9f998a 100644 --- a/core/hw/pvr/ta_ctx.h +++ b/core/hw/pvr/ta_ctx.h @@ -94,10 +94,10 @@ struct PolyParam { return ((pcw.full ^ other.pcw.full) & 0x300CE) == 0 && ((isp.full ^ other.isp.full) & 0xF4000000) == 0 - && ((tcw.full ^ other.tcw.full) & 0xFE1FFFFF) == 0 + && tcw.full == other.tcw.full && tsp.full == other.tsp.full && tileclip == other.tileclip - && ((tcw1.full ^ other.tcw1.full) & 0xFE1FFFFF) == 0 + && tcw1.full == other.tcw1.full && tsp1.full == other.tsp1.full && mvMatrix == other.mvMatrix && normalMatrix == other.normalMatrix diff --git a/core/hw/pvr/ta_vtx.cpp b/core/hw/pvr/ta_vtx.cpp index 7af3a8d62..31230a0f4 100644 --- a/core/hw/pvr/ta_vtx.cpp +++ b/core/hw/pvr/ta_vtx.cpp @@ -2122,7 +2122,24 @@ int getTAContextAddresses(u32 *addresses) tile.full = pvr_read32p(addr); if (tile.X != x || tile.Y != y) break; + // Try the opaque pointer u32 opbAddr = pvr_read32p(addr + 4); + if (opbAddr == 0xffffffff) + { + // Try the translucent pointer + opbAddr = pvr_read32p(addr + 12); + if (opbAddr == 0xffffffff) + { + // Try the punch-through pointer + if (tile_size >= 24) + opbAddr = pvr_read32p(addr + 20); + if (opbAddr == 0xffffffff) + { + INFO_LOG(PVR, "Can't find any non-null OPB for pass %d", count); + break; + } + } + } addresses[count++] = pvr_read32p(opbAddr); addr += tile_size; } while (!tile.LastRegion && count < MAX_PASSES);