diff --git a/DDrawCompat/Config/Config.cpp b/DDrawCompat/Config/Config.cpp index 56ec5a3..2373a0b 100644 --- a/DDrawCompat/Config/Config.cpp +++ b/DDrawCompat/Config/Config.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ namespace Config Settings::DepthFormat depthFormat; Settings::DisplayAspectRatio displayAspectRatio; Settings::DesktopColorDepth desktopColorDepth; + Settings::DesktopResolution desktopResolution; Settings::DisplayFilter displayFilter; Settings::DisplayRefreshRate displayRefreshRate; Settings::DisplayResolution displayResolution; diff --git a/DDrawCompat/Config/Settings/DesktopResolution.cpp b/DDrawCompat/Config/Settings/DesktopResolution.cpp new file mode 100644 index 0000000..416bad0 --- /dev/null +++ b/DDrawCompat/Config/Settings/DesktopResolution.cpp @@ -0,0 +1,38 @@ +#include + +namespace Config +{ + namespace Settings + { + DesktopResolution::DesktopResolution() + : MappedSetting("DesktopResolution", "desktop", { {"desktop", DESKTOP} }) + { + } + + std::string DesktopResolution::getValueStr() const + { + try + { + return MappedSetting::getValueStr(); + } + catch (const ParsingError&) + { + return std::to_string(m_value.cx) + 'x' + std::to_string(m_value.cy); + } + } + + void DesktopResolution::setValue(const std::string& value) + { + try + { + MappedSetting::setValue(value); + } + catch (const ParsingError&) + { + m_value = Parser::parseResolution(value); + } + } + + const SIZE DesktopResolution::DESKTOP = { 0, 0 }; + } +} diff --git a/DDrawCompat/Config/Settings/DesktopResolution.h b/DDrawCompat/Config/Settings/DesktopResolution.h new file mode 100644 index 0000000..b18eee3 --- /dev/null +++ b/DDrawCompat/Config/Settings/DesktopResolution.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include +#include + +namespace Config +{ + namespace Settings + { + class DesktopResolution : public MappedSetting + { + public: + static const SIZE DESKTOP; + + DesktopResolution(); + + protected: + std::string getValueStr() const override; + void setValue(const std::string& value) override; + }; + } + + extern Settings::DesktopResolution desktopResolution; +} diff --git a/DDrawCompat/D3dDdi/Adapter.cpp b/DDrawCompat/D3dDdi/Adapter.cpp index 5df18bb..2db54ea 100644 --- a/DDrawCompat/D3dDdi/Adapter.cpp +++ b/DDrawCompat/D3dDdi/Adapter.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include namespace @@ -422,6 +423,7 @@ namespace D3dDdi if (adapter.second.m_luid == luid) { adapter.second.m_repository = repository; + SurfaceRepository::get(adapter.second).setRepository(repository); } } } diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.cpp b/DDrawCompat/D3dDdi/SurfaceRepository.cpp index f4d7e63..3bc1db5 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.cpp +++ b/DDrawCompat/D3dDdi/SurfaceRepository.cpp @@ -22,9 +22,8 @@ namespace namespace D3dDdi { - SurfaceRepository::SurfaceRepository(const Adapter& adapter) - : m_adapter(adapter) - , m_cursor(nullptr) + SurfaceRepository::SurfaceRepository() + : m_cursor(nullptr) , m_cursorSize{} , m_cursorHotspot{} { @@ -33,8 +32,7 @@ namespace D3dDdi CompatPtr SurfaceRepository::createSurface( DWORD width, DWORD height, D3DDDIFORMAT format, DWORD caps, UINT surfaceCount) { - auto dd(m_adapter.getRepository()); - if (!dd) + if (!m_dd) { LOG_ONCE("ERROR: no DirectDraw repository available"); return nullptr; @@ -65,7 +63,7 @@ namespace D3dDdi DDraw::SuppressResourceFormatLogs suppressResourceFormatLogs; s_inCreateSurface = true; - HRESULT result = dd.get()->lpVtbl->CreateSurface(dd, &desc, &surface.getRef(), nullptr); + HRESULT result = m_dd.get()->lpVtbl->CreateSurface(m_dd, &desc, &surface.getRef(), nullptr); s_inCreateSurface = false; D3dDdi::Resource::setFormatOverride(D3DDDIFMT_UNKNOWN); if (FAILED(result)) @@ -83,12 +81,7 @@ namespace D3dDdi SurfaceRepository& SurfaceRepository::get(const Adapter& adapter) { - auto it = g_repositories.find(adapter.getLuid()); - if (it != g_repositories.end()) - { - return it->second; - } - return g_repositories.emplace(adapter.getLuid(), SurfaceRepository(adapter)).first->second; + return g_repositories[adapter.getLuid()]; } SurfaceRepository::Cursor SurfaceRepository::getCursor(HCURSOR cursor) diff --git a/DDrawCompat/D3dDdi/SurfaceRepository.h b/DDrawCompat/D3dDdi/SurfaceRepository.h index d8e0c63..c874786 100644 --- a/DDrawCompat/D3dDdi/SurfaceRepository.h +++ b/DDrawCompat/D3dDdi/SurfaceRepository.h @@ -35,6 +35,8 @@ namespace D3dDdi D3DDDIFORMAT format = D3DDDIFMT_UNKNOWN; }; + SurfaceRepository(); + Cursor getCursor(HCURSOR cursor); Resource* getLogicalXorTexture(); Resource* getPaletteTexture(); @@ -47,14 +49,13 @@ namespace D3dDdi D3DDDIFORMAT format, DWORD caps, UINT surfaceCount = 1); const Surface& getTempTexture(DWORD width, DWORD height, D3DDDIFORMAT format); void release(Surface& surface); + void setRepository(CompatWeakPtr dd) { m_dd = dd; } static SurfaceRepository& get(const Adapter& adapter); static bool inCreateSurface() { return s_inCreateSurface; } static void enableSurfaceCheck(bool enable); private: - SurfaceRepository(const Adapter& adapter); - CompatPtr createSurface(DWORD width, DWORD height, D3DDDIFORMAT format, DWORD caps, UINT surfaceCount); bool getCursorImage(Surface& surface, HCURSOR cursor, DWORD width, DWORD height, UINT flags); @@ -63,7 +64,7 @@ namespace D3dDdi bool hasAlpha(CompatRef surface); bool isLost(Surface& surface); - const Adapter& m_adapter; + CompatWeakPtr m_dd; HCURSOR m_cursor; SIZE m_cursorSize; POINT m_cursorHotspot; diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 7d507ae..cad4865 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -142,6 +142,7 @@ namespace { return FALSE; } + DDraw::DirectDraw::onCreate(lpGUID, *dd); if (FAILED(dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL))) { @@ -160,7 +161,8 @@ namespace void createDefaultPrimary() { - if (g_defaultPrimary ? SUCCEEDED(g_defaultPrimary->IsLost(g_defaultPrimary)) : g_frontBuffer) + if (!Dll::g_isHooked || + (g_defaultPrimary ? SUCCEEDED(g_defaultPrimary->IsLost(g_defaultPrimary)) : g_frontBuffer)) { return; } diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 4b9bf29..31466e0 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -170,6 +170,7 @@ + @@ -332,6 +333,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 072379a..a142b74 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -657,6 +657,9 @@ Header Files\Common + + Header Files\Config\Settings + @@ -1037,6 +1040,9 @@ Source Files\Config\Settings + + Source Files\Config\Settings + diff --git a/DDrawCompat/Dll/Dll.cpp b/DDrawCompat/Dll/Dll.cpp index f4d96bd..6d1c3c9 100644 --- a/DDrawCompat/Dll/Dll.cpp +++ b/DDrawCompat/Dll/Dll.cpp @@ -10,6 +10,7 @@ namespace Dll HMODULE g_origDciman32Module = nullptr; Procs g_origProcs = {}; Procs g_jmpTargetProcs = {}; + bool g_isHooked = false; HANDLE createThread(unsigned(__stdcall* threadProc)(void*), unsigned int* threadId, int priority, unsigned initFlags) { diff --git a/DDrawCompat/Dll/Dll.h b/DDrawCompat/Dll/Dll.h index ba5ada6..721bacf 100644 --- a/DDrawCompat/Dll/Dll.h +++ b/DDrawCompat/Dll/Dll.h @@ -80,6 +80,7 @@ namespace Dll extern HMODULE g_origDciman32Module; extern Procs g_origProcs; extern Procs g_jmpTargetProcs; + extern bool g_isHooked; } #undef ADD_FARPROC_MEMBER diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index 63ca710..af00281 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -51,7 +52,7 @@ namespace template HRESULT WINAPI directDrawFunc(FirstParam firstParam, Params... params) { - LOG_FUNC(getFuncName(), params...); + LOG_FUNC(getFuncName(), firstParam, params...); installHooks(); if constexpr (&Dll::Procs::DirectDrawCreate == origFunc || &Dll::Procs::DirectDrawCreateEx == origFunc) { @@ -70,8 +71,7 @@ namespace void installHooks() { - static bool isAlreadyInstalled = false; - if (!isAlreadyInstalled) + if (!Dll::g_isHooked) { DDraw::SuppressResourceFormatLogs suppressResourceFormatLogs; LOG_INFO << "Installing display mode hooks"; @@ -121,10 +121,16 @@ namespace Compat::closeDbgEng(); Gdi::GuiThread::start(); LOG_INFO << "Finished installing hooks"; - isAlreadyInstalled = true; + Dll::g_isHooked = true; } } + unsigned WINAPI installHooksThreadProc(LPVOID /*lpParameter*/) + { + installHooks(); + return 0; + } + bool isOtherDDrawWrapperLoaded() { const auto currentDllPath(Compat::getModulePath(Dll::g_currentModule)); @@ -308,6 +314,11 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) CALL_ORIG_PROC(SetAppCompatData)(disableMaxWindowedMode, 0); } + if (Config::Settings::DesktopResolution::DESKTOP != Config::desktopResolution.get()) + { + Dll::createThread(&installHooksThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL); + } + LOG_INFO << "DDrawCompat loaded successfully"; } else if (fdwReason == DLL_PROCESS_DETACH) diff --git a/DDrawCompat/Win32/DisplayMode.cpp b/DDrawCompat/Win32/DisplayMode.cpp index 9be0f98..99e83f4 100644 --- a/DDrawCompat/Win32/DisplayMode.cpp +++ b/DDrawCompat/Win32/DisplayMode.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -109,6 +110,27 @@ namespace LONG changeDisplaySettingsEx(const Char* lpszDeviceName, typename DevMode* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam) { DDraw::ScopedThreadLock lock; + auto desktopResolution = Config::desktopResolution.get(); + if (!lpDevMode && 0 == dwflags && Config::Settings::DesktopResolution::DESKTOP != desktopResolution) + { + auto mi = Win32::DisplayMode::getMonitorInfo(getDeviceName(lpszDeviceName)); + if (0 == mi.rcMonitor.left && 0 == mi.rcMonitor.top) + { + DevMode dm = {}; + dm.dmSize = sizeof(dm); + enumDisplaySettingsEx(lpszDeviceName, ENUM_REGISTRY_SETTINGS, &dm, 0); + + dm.dmBitsPerPel = g_desktopBpp; + dm.dmPelsWidth = desktopResolution.cx; + dm.dmPelsHeight = desktopResolution.cy; + + if (DISP_CHANGE_SUCCESSFUL == changeDisplaySettingsEx(lpszDeviceName, &dm, nullptr, 0, nullptr)) + { + return DISP_CHANGE_SUCCESSFUL; + } + } + } + DevMode targetDevMode = {}; SIZE emulatedResolution = {}; if (lpDevMode) @@ -781,13 +803,12 @@ namespace Win32 void installHooks() { - DEVMODEA dm = {}; - dm.dmSize = sizeof(dm); - EnumDisplaySettingsEx(nullptr, ENUM_CURRENT_SETTINGS, &dm, 0); - g_desktopBpp = Config::desktopColorDepth.get(); if (Config::Settings::DesktopColorDepth::INITIAL == g_desktopBpp) { + DEVMODEA dm = {}; + dm.dmSize = sizeof(dm); + EnumDisplaySettingsEx(nullptr, ENUM_CURRENT_SETTINGS, &dm, 0); g_desktopBpp = dm.dmBitsPerPel; } g_emulatedDisplayMode.bpp = g_desktopBpp; @@ -804,6 +825,11 @@ namespace Win32 HOOK_FUNCTION(user32, GetMonitorInfoW, getMonitorInfoW); disableDwm8And16BitMitigation(); + + if (Config::Settings::DesktopResolution::DESKTOP != Config::desktopResolution.get()) + { + changeDisplaySettingsExA(nullptr, nullptr, nullptr, 0, nullptr); + } } } }