diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index be22bef10659..9aac6a0f7140 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -650,16 +650,28 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 sys_rsx.warning("sys_rsx_context_attribute(): RSX is not idle while setting zcull"); } - const u32 offset = (a5 & 0xFFFFFFFF); + const u32 width = ((a4 & 0xFFFFFFFF) >> 22) << 6; + const u32 height = ((a4 & 0xFFFFFFFF) >> 6) << 6; + const u32 cullStart = (a5 >> 32) & ~0xFFF; + const u32 offset = (a5 & 0x0FFFFFFF); const bool bound = (a6 & 0xFFFFFFFF) != 0; if (bound) { - if (offset >= render->local_mem_size) + const auto cull_range = utils::address_range::start_length(cullStart, width * height); + + // cullStart is an offset inside ZCULL RAM which is 3MB long, check bounds + // width and height are not allowed to be zero (checked by range.valid()) + if (!cull_range.valid() || cull_range.end >= 3u << 20 || offset >= render->local_mem_size) { return CELL_EINVAL; } + if (a5 & 0xF0000000) + { + sys_rsx.warning("sys_rsx_context_attribute(): ZCULL offset greater than 256MB (offset=0x%x)", offset); + } + // Hardcoded values in gcm verify(HERE), !!(a4 & (1ull << 32)), (a6 & 0xFFFFFFFF) == 0u + ((0x2000 << 0) | (0x20 << 16)); } @@ -670,9 +682,9 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 zcull.zFormat = ((a4 >> 32) >> 4) & 0xF; zcull.aaFormat = ((a4 >> 32) >> 8) & 0xF; - zcull.width = ((a4 & 0xFFFFFFFF) >> 22) << 6; - zcull.height = (((a4 & 0xFFFFFFFF) >> 6) & 0xFF) << 6; - zcull.cullStart = (a5 >> 32); + zcull.width = width; + zcull.height = height; + zcull.cullStart = cullStart; zcull.offset = offset; zcull.zcullDir = ((a6 >> 32) >> 1) & 0x1; zcull.zcullFormat = ((a6 >> 32) >> 2) & 0x3FF; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7c100f870cd1..c14b651b9267 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2137,7 +2137,9 @@ namespace rsx //Find zeta address in bound zculls for (const auto& zcull : zculls) { - if (zcull.bound) + if (zcull.bound && + rsx::to_surface_depth_format(zcull.zFormat) == m_depth_surface_info.depth_format && + rsx::to_surface_antialiasing(zcull.aaFormat) == rsx::method_registers.surface_antialias()) { const u32 rsx_address = rsx::get_address(zcull.offset, CELL_GCM_LOCATION_LOCAL, HERE); if (rsx_address == zeta_address)