diff --git a/DDrawCompat/Common/Comparison.h b/DDrawCompat/Common/Comparison.h index b4c5768..651a29c 100644 --- a/DDrawCompat/Common/Comparison.h +++ b/DDrawCompat/Common/Comparison.h @@ -33,6 +33,11 @@ inline auto toTuple(const POINT& pt) return std::make_tuple(pt.x, pt.y); } +inline auto toTuple(const RGBQUAD& q) +{ + return std::make_tuple(q.rgbBlue, q.rgbGreen, q.rgbRed, q.rgbReserved); +} + inline auto toTuple(const SIZE& size) { return std::make_tuple(size.cx, size.cy); diff --git a/DDrawCompat/Config/Config.cpp b/DDrawCompat/Config/Config.cpp index b8804d1..d3989dc 100644 --- a/DDrawCompat/Config/Config.cpp +++ b/DDrawCompat/Config/Config.cpp @@ -19,6 +19,7 @@ namespace Config Settings::FpsLimiter fpsLimiter; Settings::FullscreenMode fullscreenMode; Settings::LogLevel logLevel; + Settings::PalettizedTextures palettizedTextures; Settings::RemoveBorders removeBorders; Settings::RenderColorDepth renderColorDepth; Settings::ResolutionScale resolutionScale; diff --git a/DDrawCompat/Config/Config.h b/DDrawCompat/Config/Config.h index 439bbbe..60f644c 100644 --- a/DDrawCompat/Config/Config.h +++ b/DDrawCompat/Config/Config.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ namespace Config extern Settings::FpsLimiter fpsLimiter; extern Settings::FullscreenMode fullscreenMode; extern Settings::LogLevel logLevel; + extern Settings::PalettizedTextures palettizedTextures; extern Settings::RemoveBorders removeBorders; extern Settings::RenderColorDepth renderColorDepth; extern Settings::ResolutionScale resolutionScale; diff --git a/DDrawCompat/Config/Settings/PalettizedTextures.h b/DDrawCompat/Config/Settings/PalettizedTextures.h new file mode 100644 index 0000000..bf3e9e9 --- /dev/null +++ b/DDrawCompat/Config/Settings/PalettizedTextures.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace Config +{ + namespace Settings + { + class PalettizedTextures : public MappedSetting + { + public: + PalettizedTextures() + : MappedSetting("PalettizedTextures", "on", { {"off", false}, {"on", true} }) + { + } + }; + } +} diff --git a/DDrawCompat/D3dDdi/Adapter.cpp b/DDrawCompat/D3dDdi/Adapter.cpp index 54fd640..9cc516a 100644 --- a/DDrawCompat/D3dDdi/Adapter.cpp +++ b/DDrawCompat/D3dDdi/Adapter.cpp @@ -266,6 +266,27 @@ namespace D3dDdi { caps.dwDeviceZBufferBitDepth = getInfo().supportedZBufferBitDepths; } + if (Config::palettizedTextures.get()) + { + caps.dpcTriCaps.dwTextureCaps |= D3DPTEXTURECAPS_ALPHAPALETTE; + } + break; + } + + case D3DDDICAPS_GETFORMATDATA: + { + if (Config::palettizedTextures.get()) + { + UINT count = pData->DataSize / sizeof(FORMATOP); + auto formatOp = static_cast(pData->pData); + for (UINT i = 0; i < count; ++i) + { + if (D3DDDIFMT_P8 == formatOp[i].Format) + { + formatOp[i].Operations |= FORMATOP_TEXTURE | FORMATOP_CUBETEXTURE; + } + } + } break; } } diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index 0e12ec5..d4ea847 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -359,6 +359,25 @@ namespace D3dDdi return result; } + HRESULT Device::pfnSetPalette(const D3DDDIARG_SETPALETTE* data) + { + flushPrimitives(); + if (data->PaletteHandle >= m_palettes.size()) + { + m_palettes.resize(data->PaletteHandle + 1); + m_paletteFlags.resize(data->PaletteHandle + 1); + } + + m_paletteFlags[data->PaletteHandle] = data->PaletteFlags; + + auto it = m_resources.find(data->hResource); + if (it != m_resources.end()) + { + it->second->setPaletteHandle(data->PaletteHandle); + } + return S_OK; + } + HRESULT Device::pfnUnlock(const D3DDDIARG_UNLOCK* data) { flushPrimitives(); @@ -370,6 +389,35 @@ namespace D3dDdi return m_origVtable.pfnUnlock(m_device, data); } + HRESULT Device::pfnUpdatePalette(const D3DDDIARG_UPDATEPALETTE* data, const PALETTEENTRY* paletteData) + { + LOG_DEBUG << Compat::array(reinterpret_cast(paletteData), data->NumEntries); + flushPrimitives(); + if (data->PaletteHandle >= m_palettes.size()) + { + m_palettes.resize(data->PaletteHandle + 1); + } + + const bool useAlpha = m_paletteFlags[data->PaletteHandle] & D3DDDISETPALETTE_ALPHA; + for (UINT i = 0; i < data->NumEntries; ++i) + { + auto& rgbQuad = m_palettes[data->PaletteHandle][data->StartIndex + i]; + rgbQuad.rgbReserved = useAlpha ? paletteData[i].peFlags : 0xFF; + rgbQuad.rgbRed = paletteData[i].peRed; + rgbQuad.rgbGreen = paletteData[i].peGreen; + rgbQuad.rgbBlue = paletteData[i].peBlue; + } + + for (auto& resourcePair : m_resources) + { + if (resourcePair.second->getPaletteHandle() == data->PaletteHandle) + { + resourcePair.second->invalidatePalettizedTexture(); + } + } + return S_OK; + } + void Device::updateAllConfig() { g_isConfigUpdatePending = true; diff --git a/DDrawCompat/D3dDdi/Device.h b/DDrawCompat/D3dDdi/Device.h index 5760e26..78f137d 100644 --- a/DDrawCompat/D3dDdi/Device.h +++ b/DDrawCompat/D3dDdi/Device.h @@ -1,7 +1,9 @@ #pragma once +#include #include #include +#include #include #include @@ -44,11 +46,14 @@ namespace D3dDdi HRESULT pfnOpenResource(D3DDDIARG_OPENRESOURCE* data); HRESULT pfnPresent(const D3DDDIARG_PRESENT* data); HRESULT pfnPresent1(D3DDDIARG_PRESENT1* data); + HRESULT pfnSetPalette(const D3DDDIARG_SETPALETTE* data); HRESULT pfnUnlock(const D3DDDIARG_UNLOCK* data); + HRESULT pfnUpdatePalette(const D3DDDIARG_UPDATEPALETTE* data, const PALETTEENTRY* paletteData); Adapter& getAdapter() const { return m_adapter; } DrawPrimitive& getDrawPrimitive() { return m_drawPrimitive; } const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; } + RGBQUAD* getPalette(UINT paletteHandle) { return m_palettes[paletteHandle].data(); } Resource* getResource(HANDLE resource); DeviceState& getState() { return m_state; } ShaderBlitter& getShaderBlitter() { return m_shaderBlitter; } @@ -84,6 +89,8 @@ namespace D3dDdi DrawPrimitive m_drawPrimitive; DeviceState m_state; ShaderBlitter m_shaderBlitter; + std::vector> m_palettes; + std::vector m_paletteFlags; static std::map s_devices; static bool s_isFlushEnabled; diff --git a/DDrawCompat/D3dDdi/DeviceFuncs.cpp b/DDrawCompat/D3dDdi/DeviceFuncs.cpp index 525a2aa..6ee6830 100644 --- a/DDrawCompat/D3dDdi/DeviceFuncs.cpp +++ b/DDrawCompat/D3dDdi/DeviceFuncs.cpp @@ -64,7 +64,9 @@ namespace SET_DEVICE_FUNC(pfnOpenResource); SET_DEVICE_FUNC(pfnPresent); SET_DEVICE_FUNC(pfnPresent1); + SET_DEVICE_FUNC(pfnSetPalette); SET_DEVICE_FUNC(pfnUnlock); + SET_DEVICE_FUNC(pfnUpdatePalette); SET_DEVICE_STATE_FUNC(pfnCreateVertexShaderDecl); SET_DEVICE_STATE_FUNC(pfnDeletePixelShader); @@ -96,12 +98,10 @@ namespace SET_FLUSH_PRIMITIVES_FUNC(pfnDiscard); SET_FLUSH_PRIMITIVES_FUNC(pfnGenerateMipSubLevels); SET_FLUSH_PRIMITIVES_FUNC(pfnSetClipPlane); - SET_FLUSH_PRIMITIVES_FUNC(pfnSetPalette); SET_FLUSH_PRIMITIVES_FUNC(pfnSetScissorRect); SET_FLUSH_PRIMITIVES_FUNC(pfnStateSet); SET_FLUSH_PRIMITIVES_FUNC(pfnTexBlt); SET_FLUSH_PRIMITIVES_FUNC(pfnTexBlt1); - SET_FLUSH_PRIMITIVES_FUNC(pfnUpdatePalette); } } diff --git a/DDrawCompat/D3dDdi/DeviceState.cpp b/DDrawCompat/D3dDdi/DeviceState.cpp index 9168a6f..56a0d6f 100644 --- a/DDrawCompat/D3dDdi/DeviceState.cpp +++ b/DDrawCompat/D3dDdi/DeviceState.cpp @@ -230,6 +230,8 @@ namespace D3dDdi return; } + prepareTextures(); + if (m_changedStates & CS_RENDER_STATE) { updateRenderStates(); @@ -257,6 +259,10 @@ namespace D3dDdi Resource* DeviceState::getTextureResource(UINT stage) { + if (!m_app.textures[stage]) + { + return nullptr; + } if (!m_textureResource[stage] || *m_textureResource[stage] != m_app.textures[stage]) { m_textureResource[stage] = m_device.getResource(m_app.textures[stage]); @@ -336,7 +342,7 @@ namespace D3dDdi return value; } - void DeviceState::onDestroyResource(D3dDdi::Resource* resource, HANDLE resourceHandle) + void DeviceState::onDestroyResource(Resource* resource, HANDLE resourceHandle) { for (UINT i = 0; i < m_current.textures.size(); ++i) { @@ -574,6 +580,18 @@ namespace D3dDdi return S_OK; } + void DeviceState::prepareTextures() + { + for (UINT stage = 0; stage < m_app.textures.size(); ++stage) + { + auto resource = getTextureResource(stage); + if (resource) + { + resource->updatePalettizedTexture(stage); + } + } + } + template void DeviceState::removeResource(HANDLE resource, Data State::* data, HANDLE Data::* resourceMember, HRESULT(DeviceState::* pfnSetResourceFunc)(const Data*)) @@ -985,6 +1003,13 @@ namespace D3dDdi void DeviceState::updateTextureColorKey(UINT stage) { + m_changedTextureStageStates[stage].reset(D3DDDITSS_DISABLETEXTURECOLORKEY); + m_changedTextureStageStates[stage].reset(D3DDDITSS_TEXTURECOLORKEYVAL); + if (!m_app.textures[stage]) + { + return; + } + D3DDDIARG_TEXTURESTAGESTATE tss = {}; tss.Stage = stage; @@ -998,14 +1023,18 @@ namespace D3dDdi { tss.State = D3DDDITSS_TEXTURECOLORKEYVAL; tss.Value = m_app.textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL]; + auto resource = getTextureResource(stage); + if (resource && resource->getPalettizedTexture()) + { + tss.Value = reinterpret_cast( + m_device.getPalette(resource->getPalettizedTexture()->getPaletteHandle())[tss.Value]); + } m_current.textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL] = tss.Value; m_current.textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = FALSE; } m_device.flushPrimitives(); m_device.getOrigVtable().pfnSetTextureStageState(m_device, &tss); - m_changedTextureStageStates[stage].reset(D3DDDITSS_DISABLETEXTURECOLORKEY); - m_changedTextureStageStates[stage].reset(D3DDDITSS_TEXTURECOLORKEYVAL); LOG_DS << tss; } @@ -1013,21 +1042,11 @@ namespace D3dDdi { for (UINT stage = 0; stage <= m_maxChangedTextureStage; ++stage) { - if (setTexture(stage, m_app.textures[stage])) - { - updateTextureColorKey(stage); - } - else if (m_changedTextureStageStates[stage].test(D3DDDITSS_DISABLETEXTURECOLORKEY) || + if (setTexture(stage, m_app.textures[stage]) || + m_changedTextureStageStates[stage].test(D3DDDITSS_DISABLETEXTURECOLORKEY) || m_changedTextureStageStates[stage].test(D3DDDITSS_TEXTURECOLORKEYVAL)) { - if (m_app.textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] != - m_current.textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] || - !m_app.textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] && - m_current.textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL] != - m_app.textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL]) - { - updateTextureColorKey(stage); - } + updateTextureColorKey(stage); } m_changedTextureStageStates[stage].forEach([&](UINT stateIndex) diff --git a/DDrawCompat/D3dDdi/DeviceState.h b/DDrawCompat/D3dDdi/DeviceState.h index f8e5b0e..bdc8835 100644 --- a/DDrawCompat/D3dDdi/DeviceState.h +++ b/DDrawCompat/D3dDdi/DeviceState.h @@ -131,7 +131,7 @@ namespace D3dDdi const VertexDecl& getVertexDecl() const; HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); } bool isLocked() const { return m_isLocked; } - void onDestroyResource(D3dDdi::Resource* resource, HANDLE resourceHandle); + void onDestroyResource(Resource* resource, HANDLE resourceHandle); void updateConfig(); void updateStreamSource(); @@ -159,6 +159,7 @@ namespace D3dDdi UINT mapRsValue(D3DDDIRENDERSTATETYPE state, UINT value); UINT mapTssValue(UINT stage, D3DDDITEXTURESTAGESTATETYPE state, UINT value); + void prepareTextures(); template void removeResource(HANDLE resource, Data State::* data, HANDLE Data::* resourceMember, diff --git a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp index 38a88f3..f06caf5 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp @@ -218,6 +218,14 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETDEPTHSTENCIL& val) << val.hZBuffer; } +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETPALETTE& val) +{ + return Compat::LogStruct(os) + << Compat::hex(val.PaletteHandle) + << Compat::hex(val.PaletteFlags) + << val.hResource; +} + std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETPIXELSHADERCONST& val) { return Compat::LogStruct(os) @@ -272,6 +280,14 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val) << Compat::hex(val.Flags.Value); } +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UPDATEPALETTE& val) +{ + return Compat::LogStruct(os) + << Compat::hex(val.PaletteHandle) + << val.StartIndex + << val.NumEntries; +} + std::ostream& operator<<(std::ostream& os, const D3DDDIARG_VIEWPORTINFO& val) { return Compat::LogStruct(os) diff --git a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h index 17e1043..e410e91 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h @@ -27,6 +27,7 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENT1& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENTSURFACE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_RENDERSTATE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETDEPTHSTENCIL& val); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETPALETTE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETPIXELSHADERCONST& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETRENDERTARGET& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCE& val); @@ -34,6 +35,7 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCEUM& va std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETVERTEXSHADERCONST& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXTURESTAGESTATE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UPDATEPALETTE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_VIEWPORTINFO& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_WINFO& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_ZRANGE& val); diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 3a4da64..167daee 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -118,10 +118,14 @@ namespace D3dDdi , m_formatConfig(D3DDDIFMT_UNKNOWN) , m_multiSampleConfig{ D3DDDIMULTISAMPLE_NONE, 0 } , m_scaledSize{} + , m_palettizedTexture(nullptr) + , m_paletteHandle(0) + , m_paletteColorKeyIndex(-1) , m_isOversized(false) , m_isSurfaceRepoResource(SurfaceRepository::inCreateSurface()) , m_isClampable(true) , m_isPrimary(false) + , m_isPalettizedTextureUpToDate(false) { if (m_origData.Flags.VertexBuffer && m_origData.Flags.MightDrawFromLocked && @@ -888,6 +892,10 @@ namespace D3dDdi return bltLock(data); } + if (!data.Flags.ReadOnly) + { + m_isPalettizedTextureUpToDate = false; + } return m_device.getOrigVtable().pfnLock(m_device, &data); } @@ -932,6 +940,7 @@ namespace D3dDdi Resource& Resource::prepareForBltDst(HANDLE& resource, UINT subResourceIndex, RECT& rect) { + m_isPalettizedTextureUpToDate = false; if (m_lockResource) { loadFromLockRefResource(subResourceIndex); @@ -1272,6 +1281,18 @@ namespace D3dDdi } } + void Resource::setPaletteHandle(UINT paletteHandle) + { + m_paletteHandle = paletteHandle; + m_isPalettizedTextureUpToDate = false; + } + + void Resource::setPalettizedTexture(Resource& resource) + { + m_palettizedTexture = &resource; + resource.m_isPalettizedTextureUpToDate = false; + } + HRESULT Resource::shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource) { LOG_FUNC("Resource::shaderBlt", data, srcResource); @@ -1462,4 +1483,43 @@ namespace D3dDdi } } } + + void Resource::updatePalettizedTexture(UINT stage) + { + if (!m_palettizedTexture) + { + return; + } + + auto& appState = m_device.getState().getAppState(); + int paletteColorKeyIndex = appState.textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] + ? -1 : appState.textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL]; + + if (m_palettizedTexture->m_isPalettizedTextureUpToDate && + (-1 == paletteColorKeyIndex || paletteColorKeyIndex == m_paletteColorKeyIndex)) + { + return; + } + + auto palettePtr = m_device.getPalette(m_palettizedTexture->m_paletteHandle); + if (paletteColorKeyIndex >= 0) + { + static RGBQUAD palette[256] = {}; + memcpy(palette, m_device.getPalette(m_palettizedTexture->m_paletteHandle), sizeof(palette)); + for (int i = 0; i < 256; ++i) + { + if (i != paletteColorKeyIndex && palette[i] == palette[paletteColorKeyIndex]) + { + palette[i].rgbBlue += 0xFF == palette[i].rgbBlue ? -1 : 1; + } + } + palettePtr = palette; + } + + auto rect = getRect(0); + m_device.getShaderBlitter().palettizedBlt(*this, 0, rect, *m_palettizedTexture, 0, rect, palettePtr); + + m_palettizedTexture->m_isPalettizedTextureUpToDate = true; + m_paletteColorKeyIndex = paletteColorKeyIndex; + } } diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index e0bf4e8..a047c15 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -30,7 +30,10 @@ namespace D3dDdi Device& getDevice() const { return m_device; } const D3DDDIARG_CREATERESOURCE2& getFixedDesc() const { return m_fixedData; } const D3DDDIARG_CREATERESOURCE2& getOrigDesc() const { return m_origData; } + UINT getPaletteHandle() const { return m_paletteHandle; } + Resource* getPalettizedTexture() { return m_palettizedTexture; } bool isClampable() const { return m_isClampable; } + void invalidatePalettizedTexture() { m_isPalettizedTextureUpToDate = false; } HRESULT blt(D3DDDIARG_BLT data); HRESULT colorFill(D3DDDIARG_COLORFILL data); @@ -50,8 +53,11 @@ namespace D3dDdi void setAsGdiResource(bool isGdiResource); void setAsPrimary(); void setFullscreenMode(bool isFullscreen); + void setPaletteHandle(UINT paletteHandle); + void setPalettizedTexture(Resource& resource); HRESULT unlock(const D3DDDIARG_UNLOCK& data); void updateConfig(); + void updatePalettizedTexture(UINT stage); private: class Data : public D3DDDIARG_CREATERESOURCE2 @@ -125,9 +131,13 @@ namespace D3dDdi D3DDDIFORMAT m_formatConfig; std::pair m_multiSampleConfig; SIZE m_scaledSize; + Resource* m_palettizedTexture; + UINT m_paletteHandle; + int m_paletteColorKeyIndex; bool m_isOversized; bool m_isSurfaceRepoResource; bool m_isClampable; bool m_isPrimary; + bool m_isPalettizedTextureUpToDate; }; } diff --git a/DDrawCompat/D3dDdi/ShaderBlitter.cpp b/DDrawCompat/D3dDdi/ShaderBlitter.cpp index cb57c4b..b912ebe 100644 --- a/DDrawCompat/D3dDdi/ShaderBlitter.cpp +++ b/DDrawCompat/D3dDdi/ShaderBlitter.cpp @@ -94,6 +94,7 @@ namespace D3dDdi } auto& state = m_device.getState(); + state.setSpriteMode(false); state.setTempRenderState({ D3DDDIRS_SCENECAPTURE, TRUE }); state.setTempVertexShaderDecl(m_vertexShaderDecl.get()); state.setTempPixelShader(pixelShader); diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.cpp b/DDrawCompat/D3dDdi/SurfaceRepository.cpp index 1923596..aa2520d 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.cpp +++ b/DDrawCompat/D3dDdi/SurfaceRepository.cpp @@ -208,7 +208,7 @@ namespace D3dDdi Resource* SurfaceRepository::getPaletteTexture() { - return getSurface(m_paletteTexture, 256, 1, DDraw::DirectDraw::getRgbPixelFormat(32), + return getSurface(m_paletteTexture, 256, 1, getPixelFormat(D3DDDIFMT_A8R8G8B8), DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource; } diff --git a/DDrawCompat/DDraw/DirectDraw.cpp b/DDrawCompat/DDraw/DirectDraw.cpp index 4ce4b42..831a698 100644 --- a/DDrawCompat/DDraw/DirectDraw.cpp +++ b/DDrawCompat/DDraw/DirectDraw.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,14 @@ namespace { return DDraw::PrimarySurface::create(*This, *lpDDSurfaceDesc, *lplpDDSurface); } + else if (Config::palettizedTextures.get() && + (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_TEXTURE) && + !(lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) && + (lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) && + (DDPF_RGB | DDPF_PALETTEINDEXED8) == lpDDSurfaceDesc->ddpfPixelFormat.dwFlags) + { + return DDraw::PalettizedTexture::create(*This, *lpDDSurfaceDesc, *lplpDDSurface); + } else { return DDraw::Surface::create( diff --git a/DDrawCompat/DDraw/DirectDrawSurface.cpp b/DDrawCompat/DDraw/DirectDrawSurface.cpp index ed286e8..fbdec2a 100644 --- a/DDrawCompat/DDraw/DirectDrawSurface.cpp +++ b/DDrawCompat/DDraw/DirectDrawSurface.cpp @@ -62,6 +62,7 @@ namespace SET_COMPAT_METHOD(Flip); SET_COMPAT_METHOD(GetCaps); SET_COMPAT_METHOD(GetDC); + SET_COMPAT_METHOD(GetPalette); SET_COMPAT_METHOD(GetSurfaceDesc); SET_COMPAT_METHOD(IsLost); SET_COMPAT_METHOD(Lock); diff --git a/DDrawCompat/DDraw/Surfaces/PalettizedTexture.cpp b/DDrawCompat/DDraw/Surfaces/PalettizedTexture.cpp new file mode 100644 index 0000000..2dd62c1 --- /dev/null +++ b/DDrawCompat/DDraw/Surfaces/PalettizedTexture.cpp @@ -0,0 +1,77 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace DDraw +{ + template + HRESULT PalettizedTexture::create(CompatRef dd, TSurfaceDesc desc, TSurface*& surface) + { + LOG_FUNC("PalettizedTexture::create", &dd, desc, surface); + + DDSURFACEDESC d = {}; + memcpy(&d, &desc, sizeof(d)); + d.dwSize = sizeof(d); + + auto dd1(CompatPtr::from(&dd)); + CompatPtr palettizedSurface; + HRESULT result = Surface::create(*dd1, d, palettizedSurface.getRef(), + std::make_unique(desc.ddsCaps.dwCaps)); + if (FAILED(result)) + { + return LOG_RESULT(result); + } + + auto privateData(std::make_unique(desc.ddsCaps.dwCaps)); + auto data = privateData.get(); + data->m_palettizedSurface = palettizedSurface; + + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | + (desc.dwFlags & (DDSD_CKSRCBLT | DDSD_CKDESTBLT)); + desc.ddpfPixelFormat = D3dDdi::getPixelFormat(D3DDDIFMT_A8R8G8B8); + desc.ddsCaps = {}; + desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY; + result = Surface::create(dd, desc, surface, std::move(privateData)); + if (FAILED(result)) + { + return LOG_RESULT(result); + } + + auto palettizedResource = D3dDdi::Device::findResource( + DDraw::DirectDrawSurface::getDriverResourceHandle(*data->m_palettizedSurface)); + auto paletteResolvedResource = D3dDdi::Device::findResource( + DDraw::DirectDrawSurface::getDriverResourceHandle(*surface)); + paletteResolvedResource->setPalettizedTexture(*palettizedResource); + + return LOG_RESULT(DD_OK); + } + + template HRESULT PalettizedTexture::create( + CompatRef dd, DDSURFACEDESC desc, IDirectDrawSurface*& surface); + template HRESULT PalettizedTexture::create( + CompatRef dd, DDSURFACEDESC desc, IDirectDrawSurface*& surface); + template HRESULT PalettizedTexture::create( + CompatRef dd, DDSURFACEDESC2 desc, IDirectDrawSurface4*& surface); + template HRESULT PalettizedTexture::create( + CompatRef dd, DDSURFACEDESC2 desc, IDirectDrawSurface7*& surface); + + PalettizedTexture::~PalettizedTexture() + { + LOG_FUNC("PalettizedTexture::~PalettizedTexture", this); + } + + void PalettizedTexture::createImpl() + { + m_impl.reset(new PalettizedTextureImpl(*this, m_palettizedSurface)); + m_impl2.reset(new PalettizedTextureImpl(*this, m_palettizedSurface)); + m_impl3.reset(new PalettizedTextureImpl(*this, m_palettizedSurface)); + m_impl4.reset(new PalettizedTextureImpl(*this, m_palettizedSurface)); + m_impl7.reset(new PalettizedTextureImpl(*this, m_palettizedSurface)); + } +} diff --git a/DDrawCompat/DDraw/Surfaces/PalettizedTexture.h b/DDrawCompat/DDraw/Surfaces/PalettizedTexture.h new file mode 100644 index 0000000..d1a2675 --- /dev/null +++ b/DDrawCompat/DDraw/Surfaces/PalettizedTexture.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include +#include +#include + +namespace DDraw +{ + class PalettizedTexture : public Surface + { + public: + PalettizedTexture(DWORD origCaps) : Surface(origCaps) {} + virtual ~PalettizedTexture() override; + + template + static HRESULT create(CompatRef dd, TSurfaceDesc desc, TSurface*& surface); + + private: + CompatPtr m_palettizedSurface; + + virtual void createImpl() override; + }; +} diff --git a/DDrawCompat/DDraw/Surfaces/PalettizedTextureImpl.cpp b/DDrawCompat/DDraw/Surfaces/PalettizedTextureImpl.cpp new file mode 100644 index 0000000..fc04f95 --- /dev/null +++ b/DDrawCompat/DDraw/Surfaces/PalettizedTextureImpl.cpp @@ -0,0 +1,101 @@ +#include +#include +#include + +namespace DDraw +{ + template + PalettizedTextureImpl::PalettizedTextureImpl(PalettizedTexture& data, CompatPtr palettizedSurface) + : SurfaceImpl(&data) + , m_data(data) + , m_palettizedSurface(palettizedSurface) + { + } + + template + HRESULT PalettizedTextureImpl::Blt( + TSurface* /*This*/, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, + DWORD dwFlags, LPDDBLTFX lpDDBltFx) + { + return SurfaceImpl::Blt(m_palettizedSurface, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); + } + + template + HRESULT PalettizedTextureImpl::BltFast( + TSurface* /*This*/, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) + { + return SurfaceImpl::BltFast(m_palettizedSurface, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); + } + + template + TSurface* PalettizedTextureImpl::getBltSrc(TSurface* /*src*/) + { + return m_palettizedSurface; + } + + template + HRESULT PalettizedTextureImpl::GetCaps(TSurface* /*This*/, TDdsCaps* lpDDSCaps) + { + return SurfaceImpl::GetCaps(m_palettizedSurface, lpDDSCaps); + } + + template + HRESULT PalettizedTextureImpl::GetDC(TSurface* /*This*/, HDC* lphDC) + { + return SurfaceImpl::GetDC(m_palettizedSurface, lphDC); + } + + template + HRESULT PalettizedTextureImpl::GetPalette(TSurface* /*This*/, LPDIRECTDRAWPALETTE* lplpDDPalette) + { + return SurfaceImpl::GetPalette(m_palettizedSurface, lplpDDPalette); + } + + template + HRESULT PalettizedTextureImpl::GetSurfaceDesc(TSurface* /*This*/, TSurfaceDesc* lpDDSurfaceDesc) + { + return SurfaceImpl::GetSurfaceDesc(m_palettizedSurface, lpDDSurfaceDesc); + } + + template + HRESULT PalettizedTextureImpl::Lock( + TSurface* /*This*/, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) + { + return SurfaceImpl::Lock(m_palettizedSurface, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent); + } + + template + HRESULT PalettizedTextureImpl::ReleaseDC(TSurface* /*This*/, HDC hDC) + { + return SurfaceImpl::ReleaseDC(m_palettizedSurface, hDC); + } + + template + HRESULT PalettizedTextureImpl::Restore(TSurface* This) + { + HRESULT result = SurfaceImpl::Restore(m_palettizedSurface); + if (SUCCEEDED(result)) + { + result = SurfaceImpl::Restore(This); + } + return result; + } + + template + HRESULT PalettizedTextureImpl::SetPalette(TSurface* /*This*/, LPDIRECTDRAWPALETTE lpDDPalette) + { + return SurfaceImpl::SetPalette(m_palettizedSurface, lpDDPalette); + } + + template + HRESULT PalettizedTextureImpl::Unlock(TSurface* /*This*/, TUnlockParam lpRect) + { + return SurfaceImpl::Unlock(m_palettizedSurface, lpRect); + } + + template PalettizedTextureImpl; + template PalettizedTextureImpl; + template PalettizedTextureImpl; + template PalettizedTextureImpl; + template PalettizedTextureImpl; +} diff --git a/DDrawCompat/DDraw/Surfaces/PalettizedTextureImpl.h b/DDrawCompat/DDraw/Surfaces/PalettizedTextureImpl.h new file mode 100644 index 0000000..e6b3d60 --- /dev/null +++ b/DDrawCompat/DDraw/Surfaces/PalettizedTextureImpl.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace DDraw +{ + class PalettizedTexture; + + template + class PalettizedTextureImpl : public SurfaceImpl + { + public: + PalettizedTextureImpl(PalettizedTexture& data, CompatPtr palettizedSurface); + + virtual HRESULT Blt(TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, + DWORD dwFlags, LPDDBLTFX lpDDBltFx) override; + virtual HRESULT BltFast(TSurface* This, DWORD dwX, DWORD dwY, + TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) override; + virtual HRESULT GetCaps(TSurface* This, TDdsCaps* lpDDSCaps) override; + virtual HRESULT GetDC(TSurface* This, HDC* lphDC); + virtual HRESULT GetPalette(TSurface* This, LPDIRECTDRAWPALETTE* lplpDDPalette) override; + virtual HRESULT GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc) override; + virtual HRESULT Lock(TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc, + DWORD dwFlags, HANDLE hEvent) override; + virtual HRESULT ReleaseDC(TSurface* This, HDC hDC) override; + virtual HRESULT Restore(TSurface* This) override; + virtual HRESULT SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette) override; + virtual HRESULT Unlock(TSurface* This, TUnlockParam lpRect) override; + + virtual TSurface* getBltSrc(TSurface* src) override; + + private: + PalettizedTexture& m_data; + CompatPtr m_palettizedSurface; + }; +} diff --git a/DDrawCompat/DDraw/Surfaces/Surface.cpp b/DDrawCompat/DDraw/Surfaces/Surface.cpp index 7ba7f1f..14edfce 100644 --- a/DDrawCompat/DDraw/Surfaces/Surface.cpp +++ b/DDrawCompat/DDraw/Surfaces/Surface.cpp @@ -79,8 +79,8 @@ namespace DDraw if (SUCCEEDED(dds->SetPrivateData(&dds, IID_CompatSurfacePrivateData, privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER))) { - privateData->createImpl(); privateData->m_surface = &dds; + privateData->createImpl(); privateData.release(); } } diff --git a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp index d05859b..837a292 100644 --- a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp @@ -45,6 +45,12 @@ namespace return bltFunc(This, lpDDSrcSurface, lpSrcRect); } + auto srcSurface = DDraw::Surface::getSurface(*lpDDSrcSurface); + if (srcSurface) + { + lpDDSrcSurface = srcSurface->getImpl()->getBltSrc(lpDDSrcSurface); + } + auto dstDesc = getDesc(This); if (!(dstDesc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) || !(dstDesc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) { @@ -134,6 +140,12 @@ namespace DDraw return getOrigVtable(This).Flip(This, lpDDSurfaceTargetOverride, dwFlags); } + template + TSurface* SurfaceImpl::getBltSrc(TSurface* src) + { + return src; + } + template HRESULT SurfaceImpl::GetCaps(TSurface* This, TDdsCaps* lpDDSCaps) { @@ -158,6 +170,12 @@ namespace DDraw return result; } + template + HRESULT SurfaceImpl::GetPalette(TSurface* This, LPDIRECTDRAWPALETTE* lplpDDPalette) + { + return getOrigVtable(This).GetPalette(This, lplpDDPalette); + } + template HRESULT SurfaceImpl::GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc) { diff --git a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.h b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.h index 99ea70a..db8d689 100644 --- a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.h +++ b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.h @@ -31,6 +31,7 @@ namespace DDraw virtual HRESULT Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags); virtual HRESULT GetCaps(TSurface* This, TDdsCaps* lpDDSCaps); virtual HRESULT GetDC(TSurface* This, HDC* lphDC); + virtual HRESULT GetPalette(TSurface* This, LPDIRECTDRAWPALETTE* lplpDDPalette); virtual HRESULT GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc); virtual HRESULT IsLost(TSurface* This); virtual HRESULT Lock(TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc, @@ -43,6 +44,8 @@ namespace DDraw virtual HRESULT SetSurfaceDesc(TSurface* This, TSurfaceDesc* lpddsd, DWORD dwFlags); virtual HRESULT Unlock(TSurface* This, TUnlockParam lpRect); + virtual TSurface* getBltSrc(TSurface* src); + protected: Surface* m_data; diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index f44e4a2..725c1a8 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -176,6 +176,7 @@ + @@ -224,6 +225,8 @@ + + @@ -352,6 +355,8 @@ + + @@ -437,4 +442,4 @@ - + \ No newline at end of file diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 7204285..a6f2bed 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -588,6 +588,15 @@ Header Files\Win32 + + Header Files\DDraw\Surfaces + + + Header Files\DDraw\Surfaces + + + Header Files\Config\Settings + @@ -923,6 +932,12 @@ Source Files\Win32 + + Source Files\DDraw\Surfaces + + + Source Files\DDraw\Surfaces +