diff --git a/DDrawCompat/Common/Time.h b/DDrawCompat/Common/Time.h
index 56098ed..93e11c9 100644
--- a/DDrawCompat/Common/Time.h
+++ b/DDrawCompat/Common/Time.h
@@ -24,4 +24,11 @@ namespace Time
QueryPerformanceCounter(&qpc);
return qpc.QuadPart;
}
+
+ inline ULONG64 queryThreadCycleTime()
+ {
+ ULONG64 cycleTime = 0;
+ QueryThreadCycleTime(GetCurrentThread(), &cycleTime);
+ return cycleTime;
+ }
}
diff --git a/DDrawCompat/Config/Config.h b/DDrawCompat/Config/Config.h
index 2720b36..01d3cb2 100644
--- a/DDrawCompat/Config/Config.h
+++ b/DDrawCompat/Config/Config.h
@@ -1,11 +1,10 @@
#pragma once
-typedef unsigned long DWORD;
-
namespace Config
{
- const int delayedFlipModeTimeout = 200;
- const int evictionTimeout = 200;
- const int maxPaletteUpdatesPerMs = 5;
- const int maxUserModeDisplayDrivers = 3;
+ const unsigned delayedFlipModeTimeout = 200;
+ const unsigned evictionTimeout = 200;
+ const unsigned maxPaletteUpdatesPerMs = 5;
+ const unsigned maxUserModeDisplayDrivers = 3;
+ const unsigned threadSwitchCycleTime = 3 * 1000 * 1000;
}
diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj
index f166d58..1aeae37 100644
--- a/DDrawCompat/DDrawCompat.vcxproj
+++ b/DDrawCompat/DDrawCompat.vcxproj
@@ -231,7 +231,6 @@
-
@@ -302,7 +301,6 @@
-
diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters
index 45ef71b..d6e6de0 100644
--- a/DDrawCompat/DDrawCompat.vcxproj.filters
+++ b/DDrawCompat/DDrawCompat.vcxproj.filters
@@ -357,9 +357,6 @@
Header Files\Win32
-
- Header Files\Win32
-
Header Files\Direct3d
@@ -572,9 +569,6 @@
Source Files\Win32
-
- Source Files\Win32
-
Source Files\Direct3d
diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp
index e41add3..5edc9ef 100644
--- a/DDrawCompat/Dll/DllMain.cpp
+++ b/DDrawCompat/Dll/DllMain.cpp
@@ -20,7 +20,6 @@
#include
#include
#include
-#include
#include
HRESULT WINAPI SetAppCompatData(DWORD, DWORD);
@@ -106,7 +105,6 @@ namespace
Compat::Log() << "Installing Direct3D driver hooks";
D3dDdi::installHooks(g_origDDrawModule);
Compat::Log() << "Installing Win32 hooks";
- Win32::TimeFunctions::installHooks();
Win32::WaitFunctions::installHooks();
Gdi::VirtualScreen::init();
diff --git a/DDrawCompat/Win32/TimeFunctions.cpp b/DDrawCompat/Win32/TimeFunctions.cpp
deleted file mode 100644
index d7b23ca..0000000
--- a/DDrawCompat/Win32/TimeFunctions.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#include
-#include
-
-#include
-#include
-
-namespace
-{
- typedef DWORD(WINAPI* TimeFunc)();
-
- template
- DWORD WINAPI getTime()
- {
- thread_local DWORD prevTime = 0;
- auto origTimeFunc = Compat::getOrigFuncPtr();
- DWORD time = origTimeFunc();
- if (prevTime == time)
- {
- SwitchToThread();
- time = origTimeFunc();
- }
- prevTime = time;
- return time;
- }
-}
-
-namespace Win32
-{
- namespace TimeFunctions
- {
- void installHooks()
- {
- HOOK_FUNCTION(kernel32, GetTickCount, getTime<&GetTickCount>);
- HOOK_FUNCTION(winmm, timeGetTime, getTime<&timeGetTime>);
- }
- }
-}
diff --git a/DDrawCompat/Win32/TimeFunctions.h b/DDrawCompat/Win32/TimeFunctions.h
deleted file mode 100644
index 4a2e836..0000000
--- a/DDrawCompat/Win32/TimeFunctions.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-namespace Win32
-{
- namespace TimeFunctions
- {
- void installHooks();
- }
-}
diff --git a/DDrawCompat/Win32/WaitFunctions.cpp b/DDrawCompat/Win32/WaitFunctions.cpp
index d31b74f..431a35a 100644
--- a/DDrawCompat/Win32/WaitFunctions.cpp
+++ b/DDrawCompat/Win32/WaitFunctions.cpp
@@ -1,66 +1,52 @@
#include
+#include
-#include
#include
+#include
+#include
#include
namespace
{
- DWORD mitigateBusyWaiting(DWORD dwMilliseconds, DWORD waitResult)
+ void mitigateBusyWaiting()
{
- if (0 == dwMilliseconds && WAIT_TIMEOUT == waitResult)
+ thread_local ULONG64 ctLastThreadSwitch = Time::queryThreadCycleTime();
+ ULONG64 ctNow = Time::queryThreadCycleTime();
+ if (ctNow - ctLastThreadSwitch >= Config::threadSwitchCycleTime)
{
- SwitchToThread();
+ Sleep(0);
+ ctLastThreadSwitch = ctNow;
}
- return waitResult;
}
- DWORD WINAPI msgWaitForMultipleObjects(
- DWORD nCount, const HANDLE* pHandles, BOOL fWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask)
+ template
+ Result WINAPI mitigatedBusyWaitingFunc(Params... params)
{
- return mitigateBusyWaiting(dwMilliseconds, CALL_ORIG_FUNC(MsgWaitForMultipleObjects)(
- nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask));
- }
-
- DWORD WINAPI msgWaitForMultipleObjectsEx(
- DWORD nCount, const HANDLE* pHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags)
- {
- return mitigateBusyWaiting(dwMilliseconds, CALL_ORIG_FUNC(MsgWaitForMultipleObjectsEx)(
- nCount, pHandles, dwMilliseconds, dwWakeMask, dwFlags));
- }
-
- DWORD WINAPI signalObjectAndWait(
- HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
- {
- return mitigateBusyWaiting(dwMilliseconds, CALL_ORIG_FUNC(SignalObjectAndWait)(
- hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable));
- }
-
- DWORD WINAPI waitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
- {
- return mitigateBusyWaiting(dwMilliseconds, CALL_ORIG_FUNC(WaitForSingleObjectEx)(
- hHandle, dwMilliseconds, bAlertable));
- }
-
- DWORD WINAPI waitForMultipleObjectsEx(
- DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
- {
- return mitigateBusyWaiting(dwMilliseconds, CALL_ORIG_FUNC(WaitForMultipleObjectsEx)(
- nCount, lpHandles, bWaitAll, dwMilliseconds, bAlertable));
+ mitigateBusyWaiting();
+ return Compat::getOrigFuncPtr()(params...);
}
}
+#define MITIGATE_BUSY_WAITING(module, func) \
+ Compat::hookFunction(#module, #func, &mitigatedBusyWaitingFunc)
+
namespace Win32
{
namespace WaitFunctions
{
void installHooks()
{
- HOOK_FUNCTION(user32, MsgWaitForMultipleObjects, msgWaitForMultipleObjects);
- HOOK_FUNCTION(user32, MsgWaitForMultipleObjectsEx, msgWaitForMultipleObjectsEx);
- HOOK_FUNCTION(kernel32, SignalObjectAndWait, signalObjectAndWait);
- HOOK_FUNCTION(kernel32, WaitForSingleObjectEx, waitForSingleObjectEx);
- HOOK_FUNCTION(kernel32, WaitForMultipleObjectsEx, waitForMultipleObjectsEx);
+ MITIGATE_BUSY_WAITING(user32, GetMessageA);
+ MITIGATE_BUSY_WAITING(user32, GetMessageW);
+ MITIGATE_BUSY_WAITING(kernel32, GetTickCount);
+ MITIGATE_BUSY_WAITING(user32, MsgWaitForMultipleObjects);
+ MITIGATE_BUSY_WAITING(user32, MsgWaitForMultipleObjectsEx);
+ MITIGATE_BUSY_WAITING(user32, PeekMessageA);
+ MITIGATE_BUSY_WAITING(user32, PeekMessageW);
+ MITIGATE_BUSY_WAITING(kernel32, SignalObjectAndWait);
+ MITIGATE_BUSY_WAITING(winmm, timeGetTime);
+ MITIGATE_BUSY_WAITING(kernel32, WaitForSingleObjectEx);
+ MITIGATE_BUSY_WAITING(kernel32, WaitForMultipleObjectsEx);
}
}
}