Skip to content

Commit 286dc6b

Browse files
committed
skyrim x32 build
1 parent 19207e0 commit 286dc6b

7 files changed

Lines changed: 216 additions & 43 deletions

File tree

src/CMakeLists.txt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,54 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
144144
endif()
145145

146146

147+
# --- D3D9 Skyrim Support (x32 only) ---
148+
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
149+
# --- D3D9 Framework ---
150+
add_library(framework_skyrim STATIC
151+
${SHARED_SOURCES}
152+
d3d9/framework.cpp
153+
d3d9/d3d9_proxy.cpp
154+
d3d9/d3d9_proxy_d3d9.cpp
155+
d3d9/d3d9_proxy_device.cpp
156+
d3d9/d3d9_proxy_surface.cpp
157+
d3d9/d3d9_proxy_swapchain.cpp
158+
d3d9/dx_overlay.cpp
159+
d3d9/upscaler_manager.cpp
160+
${PROJECT_SOURCE_DIR}/external/imgui/backends/imgui_impl_dx9.cpp
161+
)
162+
163+
set_target_properties(framework_skyrim PROPERTIES OUTPUT_NAME "framework_skyrim")
164+
165+
target_compile_definitions(framework_skyrim PRIVATE
166+
GAMEPLUG_DIRECTX
167+
FRAMEWORK_EXPORTS
168+
GamePlug_INTERNAL_LOGGER
169+
)
170+
target_include_directories(framework_skyrim PUBLIC
171+
${PROJECT_SOURCE_DIR}/include
172+
${PROJECT_SOURCE_DIR}/src/d3d9
173+
${PROJECT_SOURCE_DIR}/src/shared
174+
${PROJECT_SOURCE_DIR}/external/spdlog/include
175+
${PROJECT_SOURCE_DIR}/external/imgui
176+
${PROJECT_SOURCE_DIR}/external/imgui/backends
177+
${PROJECT_SOURCE_DIR}/external/minhook/include
178+
)
179+
target_compile_definitions(framework_skyrim PUBLIC
180+
"IMGUI_USER_CONFIG=\"GAMEPLUG_imgui_config.h\""
181+
)
182+
target_link_libraries(framework_skyrim PUBLIC
183+
minhook
184+
d3d9
185+
d3dcompiler
186+
dxguid
187+
)
188+
189+
if(MSVC)
190+
target_compile_options(framework_skyrim PRIVATE /utf-8 /FS)
191+
endif()
192+
193+
endif()
194+
147195
# --- D3D9 Support (x32 only) ---
148196
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
149197
# --- D3D9 Framework ---

src/d3d9/CMakeLists.txt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,48 @@ if(BIN_OUTPUT_DIR)
5454
COMMENT "Copying D3D9 proxy to d3d9/dinput8.dll"
5555
)
5656
endif()
57+
58+
# --- Skyrim Specific Target ---
59+
add_library(dinput8_skyrim SHARED
60+
d3d9.cpp
61+
d3d9.def
62+
)
63+
64+
target_include_directories(dinput8_skyrim PRIVATE
65+
${PROJECT_SOURCE_DIR}/include
66+
${PROJECT_SOURCE_DIR}/src/d3d9
67+
${PROJECT_SOURCE_DIR}/src/shared
68+
${PROJECT_SOURCE_DIR}/external/imgui
69+
${PROJECT_SOURCE_DIR}/external/imgui/backends
70+
)
71+
72+
if(MSVC)
73+
target_compile_options(dinput8_skyrim PRIVATE /utf-8 /FS)
74+
endif()
75+
76+
target_link_libraries(dinput8_skyrim PRIVATE
77+
shlwapi
78+
framework_skyrim
79+
minhook
80+
d3d9
81+
d3dcompiler
82+
dxguid
83+
)
84+
85+
set_target_properties(dinput8_skyrim PROPERTIES
86+
PREFIX ""
87+
SUFFIX ".dll"
88+
OUTPUT_NAME "dinput8"
89+
)
90+
91+
# Deployment for Skyrim
92+
if(BIN_OUTPUT_DIR)
93+
add_custom_command(TARGET dinput8_skyrim POST_BUILD
94+
COMMAND ${CMAKE_COMMAND} -E make_directory "${BIN_OUTPUT_DIR}/skyrim"
95+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
96+
"$<TARGET_FILE:dinput8_skyrim>"
97+
"${BIN_OUTPUT_DIR}/skyrim/dinput8.dll"
98+
COMMENT "Copying Skyrim D3D9 proxy to skyrim/dinput8.dll"
99+
)
100+
endif()
101+

src/d3d9/d3d9_proxy_d3d9.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "d3d9_proxy_d3d9.h"
22
#include "d3d9_proxy_device.h"
3+
#include "upscaler_manager.h"
34

45
ProxyDirect3D9::ProxyDirect3D9(IDirect3D9* pReal)
56
: m_pReal(pReal)
@@ -119,9 +120,11 @@ STDMETHODIMP ProxyDirect3D9::CreateDevice(UINT A, D3DDEVTYPE DT, HWND hFW, DWORD
119120
return D3DERR_INVALIDCALL;
120121
OverlayRenderer::Get().SetWindow(hFW);
121122

122-
int scaledW = pPP->BackBufferWidth;
123-
int scaledH = pPP->BackBufferHeight;
124-
GetScaledResolution(scaledW, scaledH);
123+
// Load the upscaler plugin early so GetScaledResolution can check its status correctly
124+
UpscalerManager::Get().LoadUpscaler();
125+
126+
int requestedW = pPP->BackBufferWidth;
127+
int requestedH = pPP->BackBufferHeight;
125128

126129
int nativeW = Config::Get().GetTargetWidth();
127130
int nativeH = Config::Get().GetTargetHeight();
@@ -133,17 +136,21 @@ STDMETHODIMP ProxyDirect3D9::CreateDevice(UINT A, D3DDEVTYPE DT, HWND hFW, DWORD
133136
nativeW = dm.Width;
134137
nativeH = dm.Height;
135138
} else {
136-
nativeW = pPP->BackBufferWidth;
137-
nativeH = pPP->BackBufferHeight;
139+
nativeW = requestedW;
140+
nativeH = requestedH;
138141
}
139142
}
140143

144+
int scaledW = nativeW;
145+
int scaledH = nativeH;
146+
GetScaledResolution(scaledW, scaledH);
147+
141148
D3DPRESENT_PARAMETERS realPP = *pPP;
142149
realPP.BackBufferWidth = nativeW;
143150
realPP.BackBufferHeight = nativeH;
144151

145-
Logger::info("CreateDevice: Game requested {}x{}, Proxy creating device at {}x{}, Game will see {}x{}", pPP->BackBufferWidth,
146-
pPP->BackBufferHeight, nativeW, nativeH, scaledW, scaledH);
152+
Logger::info("CreateDevice: Game requested {}x{}, Proxy creating device at {}x{}, Game will see {}x{}", requestedW, requestedH, nativeW,
153+
nativeH, scaledW, scaledH);
147154

148155
HRESULT hr = m_pReal->CreateDevice(A, DT, hFW, BF, &realPP, ppRDI);
149156
if (SUCCEEDED(hr) && ppRDI && *ppRDI) {
@@ -203,9 +210,11 @@ STDMETHODIMP ProxyDirect3D9::CreateDeviceEx(
203210
return D3DERR_INVALIDCALL;
204211
OverlayRenderer::Get().SetWindow(hFW);
205212

206-
int scaledW = pPP->BackBufferWidth;
207-
int scaledH = pPP->BackBufferHeight;
208-
GetScaledResolution(scaledW, scaledH);
213+
// Load the upscaler plugin early so GetScaledResolution can check its status correctly
214+
UpscalerManager::Get().LoadUpscaler();
215+
216+
int requestedW = pPP->BackBufferWidth;
217+
int requestedH = pPP->BackBufferHeight;
209218

210219
int nativeW = Config::Get().GetTargetWidth();
211220
int nativeH = Config::Get().GetTargetHeight();
@@ -218,11 +227,15 @@ STDMETHODIMP ProxyDirect3D9::CreateDeviceEx(
218227
nativeW = mode.Width;
219228
nativeH = mode.Height;
220229
} else {
221-
nativeW = pPP->BackBufferWidth;
222-
nativeH = pPP->BackBufferHeight;
230+
nativeW = requestedW;
231+
nativeH = requestedH;
223232
}
224233
}
225234

235+
int scaledW = nativeW;
236+
int scaledH = nativeH;
237+
GetScaledResolution(scaledW, scaledH);
238+
226239
D3DPRESENT_PARAMETERS realPP = *pPP;
227240
realPP.BackBufferWidth = nativeW;
228241
realPP.BackBufferHeight = nativeH;

src/d3d9/d3d9_proxy_device.cpp

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ void ProxyDirect3DDevice9::UpdateScaledResolution() {
2929
m_pFakeBackBuffer->SetInternalSurface(pRealSurf);
3030
}
3131

32+
m_pReal->SetRenderTarget(0, pRealSurf);
33+
3234
if (pRealSurf)
3335
pRealSurf->Release(); // Proxy holds a ref
3436
Logger::info("Proxy: Fake backbuffer re-created at {}x{}", m_renderW, m_renderH);
@@ -64,6 +66,7 @@ ProxyDirect3DDevice9::ProxyDirect3DDevice9(
6466
IDirect3DSurface9* pRealSurf = nullptr;
6567
m_pFakeBackBufferTex->GetSurfaceLevel(0, &pRealSurf);
6668
m_pFakeBackBuffer = new ProxySurface9(pRealSurf, this, m_displayW, m_displayH);
69+
m_pReal->SetRenderTarget(0, pRealSurf);
6770
if (pRealSurf)
6871
pRealSurf->Release();
6972
Logger::info("Proxy: Fake backbuffer created at native {}x{}", m_renderW, m_renderH);
@@ -159,14 +162,14 @@ STDMETHODIMP_(BOOL) ProxyDirect3DDevice9::ShowCursor(BOOL bShow) {
159162
STDMETHODIMP ProxyDirect3DDevice9::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPP, IDirect3DSwapChain9** ppSC) {
160163
HRESULT hr = m_pReal->CreateAdditionalSwapChain(pPP, ppSC);
161164
if (SUCCEEDED(hr) && ppSC && *ppSC)
162-
*ppSC = new ProxyDirect3DSwapChain9(*ppSC, (IDirect3DDevice9*)this);
165+
*ppSC = new ProxyDirect3DSwapChain9(*ppSC, (IDirect3DDevice9*)this, m_pReal->GetNumberOfSwapChains() - 1);
163166
return hr;
164167
}
165168

166169
STDMETHODIMP ProxyDirect3DDevice9::GetSwapChain(UINT iSC, IDirect3DSwapChain9** ppSC) {
167170
HRESULT hr = m_pReal->GetSwapChain(iSC, ppSC);
168171
if (SUCCEEDED(hr) && ppSC && *ppSC)
169-
*ppSC = new ProxyDirect3DSwapChain9(*ppSC, (IDirect3DDevice9*)this);
172+
*ppSC = new ProxyDirect3DSwapChain9(*ppSC, (IDirect3DDevice9*)this, iSC);
170173
return hr;
171174
}
172175

@@ -186,24 +189,32 @@ STDMETHODIMP ProxyDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPP) {
186189
m_pFakeBackBufferTex = nullptr;
187190
}
188191

189-
int scaledW = pPP->BackBufferWidth;
190-
int scaledH = pPP->BackBufferHeight;
191-
GetScaledResolution(scaledW, scaledH);
192+
int requestedW = pPP->BackBufferWidth;
193+
int requestedH = pPP->BackBufferHeight;
192194

193195
int nativeW = Config::Get().GetTargetWidth();
194196
int nativeH = Config::Get().GetTargetHeight();
195197

196198
if (nativeW <= 0 || nativeH <= 0) {
197-
D3DDISPLAYMODE dm;
198-
if (SUCCEEDED(m_pReal->GetDisplayMode(0, &dm))) {
199-
nativeW = dm.Width;
200-
nativeH = dm.Height;
199+
if (m_isUpscaling && requestedW == (int)m_renderW && requestedH == (int)m_renderH) {
200+
nativeW = m_displayW;
201+
nativeH = m_displayH;
201202
} else {
202-
nativeW = pPP->BackBufferWidth;
203-
nativeH = pPP->BackBufferHeight;
203+
D3DDISPLAYMODE dm;
204+
if (SUCCEEDED(m_pReal->GetDisplayMode(0, &dm))) {
205+
nativeW = dm.Width;
206+
nativeH = dm.Height;
207+
} else {
208+
nativeW = requestedW;
209+
nativeH = requestedH;
210+
}
204211
}
205212
}
206213

214+
int scaledW = nativeW;
215+
int scaledH = nativeH;
216+
GetScaledResolution(scaledW, scaledH);
217+
207218
D3DPRESENT_PARAMETERS realPP = *pPP;
208219
realPP.BackBufferWidth = nativeW;
209220
realPP.BackBufferHeight = nativeH;
@@ -214,8 +225,8 @@ STDMETHODIMP ProxyDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPP) {
214225
m_displayH = nativeH;
215226
m_isUpscaling = true;
216227

217-
Logger::info("Reset: Game requested {}x{}, Proxy created device at {}x{}, Game sees {}x{}", pPP->BackBufferWidth, pPP->BackBufferHeight,
218-
nativeW, nativeH, scaledW, scaledH);
228+
Logger::info("Reset: Game requested {}x{}, Proxy created device at {}x{}, Game sees {}x{}", requestedW, requestedH, nativeW, nativeH,
229+
scaledW, scaledH);
219230

220231
HRESULT hr = m_pReal->Reset(&realPP);
221232
if (SUCCEEDED(hr)) {
@@ -235,6 +246,7 @@ STDMETHODIMP ProxyDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPP) {
235246
} else {
236247
m_pFakeBackBuffer->SetInternalSurface(pRealSurf);
237248
}
249+
m_pReal->SetRenderTarget(0, pRealSurf);
238250
if (pRealSurf)
239251
pRealSurf->Release();
240252
Logger::info("Proxy: Fake backbuffer re-created at {}x{} (Reset path)", m_renderW, m_renderH);
@@ -933,28 +945,74 @@ STDMETHODIMP ProxyDirect3DDevice9::CreateDepthStencilSurfaceEx(
933945
STDMETHODIMP ProxyDirect3DDevice9::ResetEx(D3DPRESENT_PARAMETERS* pPP, D3DDISPLAYMODEEX* pFDM) {
934946
OverlayRenderer::Get().OnReset();
935947
UpscalerManager::Get().OnReset();
948+
if (m_pFakeBackBuffer) {
949+
m_pFakeBackBuffer->Release();
950+
m_pFakeBackBuffer = nullptr;
951+
}
952+
if (m_pFakeBackBufferTex) {
953+
m_pFakeBackBufferTex->Release();
954+
m_pFakeBackBufferTex = nullptr;
955+
}
936956

937-
int scaledW = pPP->BackBufferWidth;
938-
int scaledH = pPP->BackBufferHeight;
939-
GetScaledResolution(scaledW, scaledH);
957+
int requestedW = pPP->BackBufferWidth;
958+
int requestedH = pPP->BackBufferHeight;
940959

941960
int nativeW = Config::Get().GetTargetWidth();
942961
int nativeH = Config::Get().GetTargetHeight();
943-
if (nativeW <= 0)
944-
nativeW = pPP->BackBufferWidth;
945-
if (nativeH <= 0)
946-
nativeH = pPP->BackBufferHeight;
962+
963+
if (nativeW <= 0 || nativeH <= 0) {
964+
if (m_isUpscaling && requestedW == (int)m_renderW && requestedH == (int)m_renderH) {
965+
nativeW = m_displayW;
966+
nativeH = m_displayH;
967+
} else {
968+
nativeW = requestedW;
969+
nativeH = requestedH;
970+
}
971+
}
972+
973+
int scaledW = nativeW;
974+
int scaledH = nativeH;
975+
GetScaledResolution(scaledW, scaledH);
947976

948977
D3DPRESENT_PARAMETERS realPP = *pPP;
949978
realPP.BackBufferWidth = nativeW;
950979
realPP.BackBufferHeight = nativeH;
951980

981+
m_renderW = scaledW;
982+
m_renderH = scaledH;
983+
m_displayW = nativeW;
984+
m_displayH = nativeH;
985+
m_isUpscaling = true;
986+
987+
Logger::info("ResetEx: Game requested {}x{}, Proxy created device at {}x{}, Game sees {}x{}", requestedW, requestedH, nativeW, nativeH,
988+
scaledW, scaledH);
989+
952990
if (!m_pRealEx)
953991
return E_NOTIMPL;
954992
HRESULT hr = m_pRealEx->ResetEx(&realPP, pFDM);
955993
if (SUCCEEDED(hr)) {
956994
pPP->BackBufferWidth = scaledW;
957995
pPP->BackBufferHeight = scaledH;
996+
if (m_isUpscaling) {
997+
if (m_pFakeBackBufferTex) {
998+
m_pFakeBackBufferTex->Release();
999+
m_pFakeBackBufferTex = nullptr;
1000+
}
1001+
if (SUCCEEDED(m_pReal->CreateTexture(
1002+
m_renderW, m_renderH, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pFakeBackBufferTex, nullptr))) {
1003+
IDirect3DSurface9* pRealSurf = nullptr;
1004+
m_pFakeBackBufferTex->GetSurfaceLevel(0, &pRealSurf);
1005+
if (!m_pFakeBackBuffer) {
1006+
m_pFakeBackBuffer = new ProxySurface9(pRealSurf, this, m_displayW, m_displayH);
1007+
} else {
1008+
m_pFakeBackBuffer->SetInternalSurface(pRealSurf);
1009+
}
1010+
m_pReal->SetRenderTarget(0, pRealSurf);
1011+
if (pRealSurf)
1012+
pRealSurf->Release();
1013+
Logger::info("Proxy: Fake backbuffer re-created at {}x{} (ResetEx path)", m_renderW, m_renderH);
1014+
}
1015+
}
9581016
OverlayRenderer::Get().OnPostReset();
9591017
}
9601018
return hr;

src/d3d9/d3d9_proxy_swapchain.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#include "d3d9_proxy_swapchain.h"
22

3-
ProxyDirect3DSwapChain9::ProxyDirect3DSwapChain9(IDirect3DSwapChain9* pReal, IDirect3DDevice9* pProxyDevice)
3+
ProxyDirect3DSwapChain9::ProxyDirect3DSwapChain9(IDirect3DSwapChain9* pReal, IDirect3DDevice9* pProxyDevice, UINT swapChainIndex)
44
: m_pReal(pReal)
5-
, m_pProxyDevice(pProxyDevice) {
5+
, m_pProxyDevice(pProxyDevice)
6+
, m_swapChainIndex(swapChainIndex) {
67
}
78

89
STDMETHODIMP ProxyDirect3DSwapChain9::QueryInterface(REFIID riid, void** ppvObj) {
@@ -35,6 +36,9 @@ STDMETHODIMP ProxyDirect3DSwapChain9::GetFrontBufferData(IDirect3DSurface9* pDes
3536
}
3637

3738
STDMETHODIMP ProxyDirect3DSwapChain9::GetBackBuffer(UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) {
39+
if (m_pProxyDevice) {
40+
return m_pProxyDevice->GetBackBuffer(m_swapChainIndex, iBackBuffer, Type, ppBackBuffer);
41+
}
3842
return m_pReal->GetBackBuffer(iBackBuffer, Type, ppBackBuffer);
3943
}
4044

src/d3d9/d3d9_proxy_swapchain.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
class ProxyDirect3DSwapChain9 : public IDirect3DSwapChain9 {
77
IDirect3DSwapChain9* m_pReal;
88
IDirect3DDevice9* m_pProxyDevice;
9+
UINT m_swapChainIndex;
910

1011
public:
11-
ProxyDirect3DSwapChain9(IDirect3DSwapChain9* pReal, IDirect3DDevice9* pProxyDevice);
12+
ProxyDirect3DSwapChain9(IDirect3DSwapChain9* pReal, IDirect3DDevice9* pProxyDevice, UINT swapChainIndex);
1213

1314
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override;
1415
STDMETHOD_(ULONG, AddRef)() override;

0 commit comments

Comments
 (0)