Prevent frame-rate dependant games from running too fast
This commit is contained in:
parent
779be6c823
commit
65dfda6e2e
Binary file not shown.
BIN
resource/Cxbx.rc
BIN
resource/Cxbx.rc
Binary file not shown.
|
@ -40,7 +40,7 @@
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * func: XBVideo::XBVideo
|
// * func: XBVideo::XBVideo
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
XBVideo::XBVideo() : m_bVSync(true), m_bFullscreen(false), m_bHardwareYUV(false)
|
XBVideo::XBVideo() : m_bVSync(false), m_bFullscreen(false), m_bHardwareYUV(false)
|
||||||
{
|
{
|
||||||
strcpy(m_szVideoResolution, "Automatic (Default)");
|
strcpy(m_szVideoResolution, "Automatic (Default)");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//{{NO_DEPENDENCIES}}
|
//{{NO_DEPENDENCIES}}
|
||||||
// Microsoft Visual C++ generated include file.
|
// Microsoft Visual C++ generated include file.
|
||||||
// Used by C:\Work\Cxbx-Reloaded\resource\Cxbx.rc
|
// Used by C:\Users\Luke\Desktop\Projects\Cxbx-Reloaded\resource\Cxbx.rc
|
||||||
//
|
//
|
||||||
#define IDI_CXBX 101
|
#define IDI_CXBX 101
|
||||||
#define IDB_SPLASH 102
|
#define IDB_SPLASH 102
|
||||||
|
@ -109,6 +109,7 @@
|
||||||
#define ID_SETTINGS_INITIALIZE 40091
|
#define ID_SETTINGS_INITIALIZE 40091
|
||||||
#define ID_EMULATION_STARTDEBUGGER 40092
|
#define ID_EMULATION_STARTDEBUGGER 40092
|
||||||
#define ID_FPS 40096
|
#define ID_FPS 40096
|
||||||
|
#define ID_HACKS_UNCAPFRAMERATE 40097
|
||||||
#define IDC_STATIC -1
|
#define IDC_STATIC -1
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
|
|
|
@ -180,6 +180,12 @@ WndMain::WndMain(HINSTANCE x_hInstance) :
|
||||||
m_DisablePixelShaders = 0;
|
m_DisablePixelShaders = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
||||||
|
result = RegQueryValueEx(hKey, "HackUncapFrameRate", NULL, &dwType, (PBYTE)&m_UncapFramerate, &dwSize);
|
||||||
|
if (result != ERROR_SUCCESS) {
|
||||||
|
m_UncapFramerate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
dwType = REG_DWORD; dwSize = sizeof(DWORD);
|
||||||
result = RegQueryValueEx(hKey, "CxbxDebug", NULL, &dwType, (PBYTE)&m_CxbxDebug, &dwSize);
|
result = RegQueryValueEx(hKey, "CxbxDebug", NULL, &dwType, (PBYTE)&m_CxbxDebug, &dwSize);
|
||||||
if (result != ERROR_SUCCESS) {
|
if (result != ERROR_SUCCESS) {
|
||||||
|
@ -1296,6 +1302,12 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
RefreshMenus();
|
RefreshMenus();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ID_HACKS_UNCAPFRAMERATE:
|
||||||
|
m_UncapFramerate = !m_UncapFramerate;
|
||||||
|
RefreshMenus();
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case ID_HELP_ABOUT:
|
case ID_HELP_ABOUT:
|
||||||
{
|
{
|
||||||
ShowAboutDialog(hwnd);
|
ShowAboutDialog(hwnd);
|
||||||
|
@ -1715,6 +1727,9 @@ void WndMain::RefreshMenus()
|
||||||
|
|
||||||
chk_flag = (m_DisablePixelShaders) ? MF_CHECKED : MF_UNCHECKED;
|
chk_flag = (m_DisablePixelShaders) ? MF_CHECKED : MF_UNCHECKED;
|
||||||
CheckMenuItem(settings_menu, ID_HACKS_DISABLEPIXELSHADERS, chk_flag);
|
CheckMenuItem(settings_menu, ID_HACKS_DISABLEPIXELSHADERS, chk_flag);
|
||||||
|
|
||||||
|
chk_flag = (m_UncapFramerate) ? MF_CHECKED : MF_UNCHECKED;
|
||||||
|
CheckMenuItem(settings_menu, ID_HACKS_UNCAPFRAMERATE, chk_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emulation menu
|
// emulation menu
|
||||||
|
@ -2070,6 +2085,7 @@ void WndMain::StartEmulation(HWND hwndParent, DebuggerState LocalDebuggerState /
|
||||||
|
|
||||||
// register Hacks with emulator process
|
// register Hacks with emulator process
|
||||||
g_EmuShared->SetDisablePixelShaders(&m_DisablePixelShaders);
|
g_EmuShared->SetDisablePixelShaders(&m_DisablePixelShaders);
|
||||||
|
g_EmuShared->SetUncapFramerate(&m_UncapFramerate);
|
||||||
|
|
||||||
// shell exe
|
// shell exe
|
||||||
{
|
{
|
||||||
|
|
|
@ -212,6 +212,7 @@ class WndMain : public Wnd
|
||||||
// * Hack Flags
|
// * Hack Flags
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
int m_DisablePixelShaders;
|
int m_DisablePixelShaders;
|
||||||
|
int m_UncapFramerate;
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * debug output filenames
|
// * debug output filenames
|
||||||
|
|
|
@ -490,6 +490,7 @@ void PrintCurrentConfigurationLog()
|
||||||
{
|
{
|
||||||
printf("--------------------------- HACKS CONFIG ---------------------------\n");
|
printf("--------------------------- HACKS CONFIG ---------------------------\n");
|
||||||
printf("Disable Pixel Shaders: %s\n", g_DisablePixelShaders == 1 ? "On" : "Off");
|
printf("Disable Pixel Shaders: %s\n", g_DisablePixelShaders == 1 ? "On" : "Off");
|
||||||
|
printf("Uncap Framerate: %s\n", g_UncapFramerate == 1 ? "On" : "Off");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("------------------------- END OF CONFIG LOG ------------------------\n");
|
printf("------------------------- END OF CONFIG LOG ------------------------\n");
|
||||||
|
@ -939,6 +940,8 @@ __declspec(noreturn) void CxbxKrnlInit
|
||||||
int HackEnabled = 0;
|
int HackEnabled = 0;
|
||||||
g_EmuShared->GetDisablePixelShaders(&HackEnabled);
|
g_EmuShared->GetDisablePixelShaders(&HackEnabled);
|
||||||
g_DisablePixelShaders = !!HackEnabled;
|
g_DisablePixelShaders = !!HackEnabled;
|
||||||
|
g_EmuShared->GetUncapFramerate(&HackEnabled);
|
||||||
|
g_UncapFramerate = !!HackEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG_PRINT_CURRENT_CONF
|
#ifdef _DEBUG_PRINT_CURRENT_CONF
|
||||||
|
|
|
@ -65,6 +65,7 @@ volatile bool g_bEmuSuspended = false;
|
||||||
volatile bool g_bPrintfOn = true;
|
volatile bool g_bPrintfOn = true;
|
||||||
bool g_XInputEnabled = false;
|
bool g_XInputEnabled = false;
|
||||||
bool g_DisablePixelShaders = false;
|
bool g_DisablePixelShaders = false;
|
||||||
|
bool g_UncapFramerate = false;
|
||||||
|
|
||||||
// Delta added to host SystemTime, used in xboxkrnl::KeQuerySystemTime and xboxkrnl::NtSetSystemTime
|
// Delta added to host SystemTime, used in xboxkrnl::KeQuerySystemTime and xboxkrnl::NtSetSystemTime
|
||||||
LARGE_INTEGER HostSystemTimeDelta = {};
|
LARGE_INTEGER HostSystemTimeDelta = {};
|
||||||
|
|
|
@ -108,5 +108,5 @@ typedef struct DUMMY_KERNEL
|
||||||
|
|
||||||
|
|
||||||
extern bool g_DisablePixelShaders;
|
extern bool g_DisablePixelShaders;
|
||||||
|
extern bool g_UncapFramerate;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3982,6 +3982,8 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_Present)
|
||||||
EMUPATCH(D3DDevice_Swap)(CXBX_SWAP_PRESENT_FORWARD); // Xbox present ignores
|
EMUPATCH(D3DDevice_Swap)(CXBX_SWAP_PRESENT_FORWARD); // Xbox present ignores
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> frameStartTime;
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: D3DDevice_Swap
|
// * patch: D3DDevice_Swap
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -4003,16 +4005,25 @@ DWORD WINAPI XTL::EMUPATCH(D3DDevice_Swap)
|
||||||
|
|
||||||
CxbxReleaseBackBufferLock();
|
CxbxReleaseBackBufferLock();
|
||||||
|
|
||||||
// TODO: Make a video option to wait for VBlank before calling Present.
|
|
||||||
// Makes syncing to 30fps easier (which is the native frame rate for Azurik
|
|
||||||
// and Halo).
|
|
||||||
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
|
|
||||||
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
|
|
||||||
|
|
||||||
clock_t currentDrawFunctionCallTime = clock();
|
clock_t currentDrawFunctionCallTime = clock();
|
||||||
HRESULT hRet = g_pD3DDevice8->Present(0, 0, 0, 0);
|
HRESULT hRet = g_pD3DDevice8->Present(0, 0, 0, 0);
|
||||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice8->Present");
|
DEBUG_D3DRESULT(hRet, "g_pD3DDevice8->Present");
|
||||||
|
|
||||||
|
|
||||||
|
if (!g_UncapFramerate) {
|
||||||
|
// If the last frame completed faster than the Xbox VBlank period, wait for it
|
||||||
|
// TODO: Read the frame rate target from the Xbox display mode
|
||||||
|
// See comments in GetNextVblankTime();
|
||||||
|
auto targetDuration = 16.6666666667ms;
|
||||||
|
while (std::chrono::high_resolution_clock::now() - frameStartTime < targetDuration) {
|
||||||
|
// We use an empty while loop because actually sleeping is too unstable
|
||||||
|
// Sleeping causes the frame duration to jitter...
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
frameStartTime = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
g_DeltaTime += currentDrawFunctionCallTime - lastDrawFunctionCallTime;
|
g_DeltaTime += currentDrawFunctionCallTime - lastDrawFunctionCallTime;
|
||||||
lastDrawFunctionCallTime = currentDrawFunctionCallTime;
|
lastDrawFunctionCallTime = currentDrawFunctionCallTime;
|
||||||
g_Frames++;
|
g_Frames++;
|
||||||
|
|
|
@ -124,6 +124,8 @@ class EmuShared : public Mutex
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
void GetDisablePixelShaders(int* value) { Lock(); *value = m_DisablePixelShaders; Unlock(); }
|
void GetDisablePixelShaders(int* value) { Lock(); *value = m_DisablePixelShaders; Unlock(); }
|
||||||
void SetDisablePixelShaders(int* value) { Lock(); m_DisablePixelShaders = *value; Unlock(); }
|
void SetDisablePixelShaders(int* value) { Lock(); m_DisablePixelShaders = *value; Unlock(); }
|
||||||
|
void GetUncapFramerate(int* value) { Lock(); *value = m_UncapFramerate; Unlock(); }
|
||||||
|
void SetUncapFramerate(int* value) { Lock(); m_UncapFramerate = *value; Unlock(); }
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * MSpF/Benchmark values Accessors
|
// * MSpF/Benchmark values Accessors
|
||||||
|
@ -196,6 +198,7 @@ class EmuShared : public Mutex
|
||||||
int m_FlagsLLE;
|
int m_FlagsLLE;
|
||||||
int m_XInputEnabled;
|
int m_XInputEnabled;
|
||||||
int m_DisablePixelShaders;
|
int m_DisablePixelShaders;
|
||||||
|
int m_UncapFramerate;
|
||||||
float m_MSpF;
|
float m_MSpF;
|
||||||
float m_FPS;
|
float m_FPS;
|
||||||
bool m_bKeQuickReboot;
|
bool m_bKeQuickReboot;
|
||||||
|
|
Loading…
Reference in New Issue