| 198 | } |
| 199 | |
| 200 | bool GSTextureCacheSW::Texture::Update(const GSVector4i& rect) |
| 201 | { |
| 202 | if (m_complete) |
| 203 | { |
| 204 | return true; |
| 205 | } |
| 206 | |
| 207 | const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[m_TEX0.PSM]; |
| 208 | |
| 209 | GSVector2i bs = psm.bs; |
| 210 | |
| 211 | int shift = psm.pal == 0 ? 2 : 0; |
| 212 | |
| 213 | int tw = std::max<int>(1 << m_TEX0.TW, bs.x); |
| 214 | int th = std::max<int>(1 << m_TEX0.TH, bs.y); |
| 215 | |
| 216 | GSVector4i r = rect; |
| 217 | |
| 218 | r = r.ralign<Align_Outside>(bs); |
| 219 | |
| 220 | if (r.eq(GSVector4i(0, 0, tw, th))) |
| 221 | { |
| 222 | m_complete = true; // lame, but better than nothing |
| 223 | } |
| 224 | |
| 225 | if (!m_buff) |
| 226 | { |
| 227 | const u32 pitch = (1 << m_tw) << shift; |
| 228 | const size_t size = pitch * th * 4; |
| 229 | |
| 230 | m_buff = _aligned_malloc(size, VECTOR_ALIGNMENT); |
| 231 | if (!m_buff) |
| 232 | return false; |
| 233 | |
| 234 | // This _shouldn't_ be necessary, but apparently our texture min/max is wrong somewhere, |
| 235 | // and we end up sampling from "random" malloc memory, which breaks GS dump runs. |
| 236 | std::memset(m_buff, 0, size); |
| 237 | } |
| 238 | |
| 239 | GSLocalMemory& mem = g_gs_renderer->m_mem; |
| 240 | |
| 241 | GSOffset off = m_offset; |
| 242 | |
| 243 | u32 blocks = 0; |
| 244 | |
| 245 | GSLocalMemory::readTextureBlock rtxbP = psm.rtxbP; |
| 246 | |
| 247 | u32 pitch = (1 << m_tw) << shift; |
| 248 | |
| 249 | u8* dst = (u8*)m_buff + pitch * r.top; |
| 250 | |
| 251 | int block_pitch = pitch * bs.y; |
| 252 | |
| 253 | shift += off.blockShiftX(); |
| 254 | int bottom = r.bottom >> off.blockShiftY(); |
| 255 | int right = r.right >> off.blockShiftX(); |
| 256 | |
| 257 | GSOffset::BNHelper bn = off.bnMulti(r.left, r.top); |
no test coverage detected