From 5d510752e62fd1d175ad0146a54e8f26b5e1e329 Mon Sep 17 00:00:00 2001 From: ergo720 <45463469+ergo720@users.noreply.github.com> Date: Sun, 12 Mar 2023 16:20:28 +0100 Subject: [PATCH] Adjust KeSystemTime when the host system time is changed by the user --- src/common/IPCHybrid.hpp | 5 +++-- src/common/win32/IPCWindows.cpp | 4 ++++ src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 16 ++++++++++++++ src/core/kernel/exports/EmuKrnlKe.cpp | 1 + src/core/kernel/exports/EmuKrnlKe.h | 2 ++ src/core/kernel/exports/EmuKrnlKi.cpp | 26 +++++++++++++++++------ src/gui/WndMain.cpp | 7 ++++++ src/gui/resource/ResCxbx.h | 3 ++- 8 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/common/IPCHybrid.hpp b/src/common/IPCHybrid.hpp index 079a1baaf..a0a1ec215 100644 --- a/src/common/IPCHybrid.hpp +++ b/src/common/IPCHybrid.hpp @@ -49,8 +49,9 @@ void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value); // ****************************************************************** typedef enum class _IPC_UPDATE_KERNEL { - CONFIG_LOGGING_SYNC = 0 - , CONFIG_INPUT_SYNC + CONFIG_LOGGING_SYNC = 0, + CONFIG_INPUT_SYNC, + CONFIG_CHANGE_TIME } IPC_UPDATE_KERNEL; void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const int value, const unsigned int hwnd); diff --git a/src/common/win32/IPCWindows.cpp b/src/common/win32/IPCWindows.cpp index 82a342d89..cbf04f2c7 100644 --- a/src/common/win32/IPCWindows.cpp +++ b/src/common/win32/IPCWindows.cpp @@ -101,6 +101,10 @@ void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const int value, const un cmdParam = ID_SYNC_CONFIG_INPUT; break; + case IPC_UPDATE_KERNEL::CONFIG_CHANGE_TIME: + cmdParam = ID_SYNC_TIME_CHANGE; + break; + default: cmdParam = 0; break; diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 674d55c06..188096a70 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -38,6 +38,7 @@ #include "core\kernel\support\Emu.h" #include "core\kernel\support\EmuFS.h" #include "core\kernel\support\NativeHandle.h" +#include "core\kernel\exports\EmuKrnlKe.h" #include "EmuShared.h" #include "..\FixedFunctionState.h" #include "core\hle\D3D8\ResourceTracker.h" @@ -1685,6 +1686,13 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar } break; + case ID_SYNC_TIME_CHANGE: + { + // Sent by the GUI when it detects WM_TIMECHANGE + xbox::KeSystemTimeChanged.test_and_set(); + } + break; + default: break; } @@ -1702,6 +1710,14 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar } break; + case WM_TIMECHANGE: + { + // NOTE: this is only received if the loader was launched from the command line without the GUI + xbox::KeSystemTimeChanged.test_and_set(); + return DefWindowProc(hWnd, msg, wParam, lParam); + } + break; + case WM_SYSKEYDOWN: { if(wParam == VK_RETURN) diff --git a/src/core/kernel/exports/EmuKrnlKe.cpp b/src/core/kernel/exports/EmuKrnlKe.cpp index 25de991f7..540d5a274 100644 --- a/src/core/kernel/exports/EmuKrnlKe.cpp +++ b/src/core/kernel/exports/EmuKrnlKe.cpp @@ -101,6 +101,7 @@ typedef struct _DpcData { } DpcData; DpcData g_DpcData = { 0 }; // Note : g_DpcData is initialized in InitDpcData() +std::atomic_flag xbox::KeSystemTimeChanged; xbox::ulonglong_xt LARGE_INTEGER2ULONGLONG(xbox::LARGE_INTEGER value) { diff --git a/src/core/kernel/exports/EmuKrnlKe.h b/src/core/kernel/exports/EmuKrnlKe.h index a7e2ebbc7..03c514eca 100644 --- a/src/core/kernel/exports/EmuKrnlKe.h +++ b/src/core/kernel/exports/EmuKrnlKe.h @@ -27,6 +27,8 @@ namespace xbox { + extern std::atomic_flag KeSystemTimeChanged; + void_xt NTAPI KeSetSystemTime ( IN PLARGE_INTEGER NewTime, diff --git a/src/core/kernel/exports/EmuKrnlKi.cpp b/src/core/kernel/exports/EmuKrnlKi.cpp index 8680815bf..b48db1b94 100644 --- a/src/core/kernel/exports/EmuKrnlKi.cpp +++ b/src/core/kernel/exports/EmuKrnlKi.cpp @@ -86,6 +86,7 @@ the said software). #include "Logging.h" // For LOG_FUNC() #include "EmuKrnl.h" // for the list support functions #include "EmuKrnlKi.h" +#include "EmuKrnlKe.h" #define MAX_TIMER_DPCS 16 @@ -163,12 +164,25 @@ xbox::void_xt xbox::KiClockIsr(ulonglong_xt ExtraMs) KeInterruptTime.High1Time = InterruptTime.u.HighPart; // Update the system time - SystemTime.u.LowPart = KeSystemTime.LowPart; - SystemTime.u.HighPart = KeSystemTime.High1Time; - SystemTime.QuadPart += (CLOCK_TIME_INCREMENT * (1 + ExtraMs)); - KeSystemTime.High2Time = SystemTime.u.HighPart; - KeSystemTime.LowPart = SystemTime.u.LowPart; - KeSystemTime.High1Time = SystemTime.u.HighPart; + if (KeSystemTimeChanged.test()) [[unlikely]] { + KeSystemTimeChanged.clear(); + LARGE_INTEGER HostSystemTime, OldSystemTime; + GetSystemTimeAsFileTime((LPFILETIME)&HostSystemTime); + xbox::KeSystemTime.High2Time = HostSystemTime.u.HighPart; + xbox::KeSystemTime.LowPart = HostSystemTime.u.LowPart; + xbox::KeSystemTime.High1Time = HostSystemTime.u.HighPart; + KfLowerIrql(OldIrql); + KeSetSystemTime(&HostSystemTime, &OldSystemTime); + OldIrql = KfRaiseIrql(CLOCK_LEVEL); + } + else { + SystemTime.u.LowPart = KeSystemTime.LowPart; + SystemTime.u.HighPart = KeSystemTime.High1Time; + SystemTime.QuadPart += (CLOCK_TIME_INCREMENT * (1 + ExtraMs)); + KeSystemTime.High2Time = SystemTime.u.HighPart; + KeSystemTime.LowPart = SystemTime.u.LowPart; + KeSystemTime.High1Time = SystemTime.u.HighPart; + } // Update the tick counter OldKeTickCount = KeTickCount; diff --git a/src/gui/WndMain.cpp b/src/gui/WndMain.cpp index d34447ee7..557173090 100644 --- a/src/gui/WndMain.cpp +++ b/src/gui/WndMain.cpp @@ -393,6 +393,13 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP }; break; // added per PVS suggestion. + case WM_TIMECHANGE: + { + ipc_send_kernel_update(IPC_UPDATE_KERNEL::CONFIG_CHANGE_TIME, 0, reinterpret_cast(m_hwndChild)); + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + break; + case WM_TIMER: { switch (wParam) diff --git a/src/gui/resource/ResCxbx.h b/src/gui/resource/ResCxbx.h index 927737d14..eff2e721a 100644 --- a/src/gui/resource/ResCxbx.h +++ b/src/gui/resource/ResCxbx.h @@ -353,6 +353,7 @@ #define ID_SETTINGS_EXPERIMENTAL 40113 #define ID_SETTINGS_IGNOREINVALIDXBESIG 40114 #define ID_SETTINGS_IGNOREINVALIDXBESEC 40115 +#define ID_SYNC_TIME_CHANGE 40116 #define IDC_STATIC -1 // Next default values for new objects @@ -360,7 +361,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 139 -#define _APS_NEXT_COMMAND_VALUE 40116 +#define _APS_NEXT_COMMAND_VALUE 40117 #define _APS_NEXT_CONTROL_VALUE 1308 #define _APS_NEXT_SYMED_VALUE 109 #endif