diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 9f69f78..b612ac4 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -190,12 +190,24 @@ namespace D3dDdi HRESULT Resource::blt(D3DDDIARG_BLT data) { - auto srcResource = m_device.getResource(data.hSrcResource); - if (srcResource && - D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool && - D3DDDIPOOL_SYSTEMMEM == srcResource->m_fixedData.Pool) + if (!isValidRect(data.DstSubResourceIndex, data.DstRect)) { - return m_device.getOrigVtable().pfnBlt(m_device, &data); + return S_OK; + } + + auto srcResource = m_device.getResource(data.hSrcResource); + if (srcResource) + { + if (!srcResource->isValidRect(data.SrcSubResourceIndex, data.SrcRect)) + { + return S_OK; + } + + if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool && + D3DDDIPOOL_SYSTEMMEM == srcResource->m_fixedData.Pool) + { + return m_device.getOrigVtable().pfnBlt(m_device, &data); + } } if (isOversized()) @@ -257,9 +269,23 @@ namespace D3dDdi return LOG_RESULT(S_OK); } - HRESULT Resource::colorFill(const D3DDDIARG_COLORFILL& data) + void Resource::clipRect(UINT subResourceIndex, RECT& rect) + { + rect.left = std::max(rect.left, 0); + rect.top = std::max(rect.top, 0); + rect.right = std::min(rect.right, m_fixedData.pSurfList[subResourceIndex].Width); + rect.bottom = std::min(rect.bottom, m_fixedData.pSurfList[subResourceIndex].Height); + } + + HRESULT Resource::colorFill(D3DDDIARG_COLORFILL data) { LOG_FUNC("Resource::colorFill", data); + clipRect(data.SubResourceIndex, data.DstRect); + if (data.DstRect.left >= data.DstRect.right || data.DstRect.top >= data.DstRect.bottom) + { + return S_OK; + } + if (m_lockResource) { auto& lockData = m_lockData[data.SubResourceIndex]; @@ -464,6 +490,13 @@ namespace D3dDdi return m_fixedData.SurfCount != m_origData.SurfCount; } + bool Resource::isValidRect(UINT subResourceIndex, const RECT& rect) + { + return rect.left >= 0 && rect.top >= 0 && rect.left < rect.right && rect.top < rect.bottom && + rect.right <= static_cast(m_fixedData.pSurfList[subResourceIndex].Width) && + rect.bottom <= static_cast(m_fixedData.pSurfList[subResourceIndex].Height); + } + HRESULT Resource::lock(D3DDDIARG_LOCK& data) { if (isOversized()) diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index 990f412..c616b06 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -27,7 +27,7 @@ namespace D3dDdi operator HANDLE() const { return m_handle; } HRESULT blt(D3DDDIARG_BLT data); - HRESULT colorFill(const D3DDDIARG_COLORFILL& data); + HRESULT colorFill(D3DDDIARG_COLORFILL data); void fixVertexData(UINT offset, UINT count, UINT stride); void* getLockPtr(UINT subResourceIndex); HRESULT lock(D3DDDIARG_LOCK& data); @@ -77,6 +77,7 @@ namespace D3dDdi HRESULT bltLock(D3DDDIARG_LOCK& data); HRESULT bltUnlock(const D3DDDIARG_UNLOCK& data); + void clipRect(UINT subResourceIndex, RECT& rect); HRESULT copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex); void copyToSysMem(UINT subResourceIndex); void copyToVidMem(UINT subResourceIndex); @@ -84,6 +85,7 @@ namespace D3dDdi void createLockResource(); void createSysMemResource(const std::vector& surfaceInfo); bool isOversized() const; + bool isValidRect(UINT subResourceIndex, const RECT& rect); HRESULT presentationBlt(const D3DDDIARG_BLT& data, Resource& srcResource); HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect);