HACK: Alternate method of handling Performance Counter

This commit is contained in:
Luke Usher 2018-04-14 17:30:47 +01:00
parent 389ec4fb80
commit b6c1f5b714
11 changed files with 78 additions and 5 deletions

View File

@ -112,6 +112,7 @@
#define ID_FPS 40096
#define ID_HACKS_UNCAPFRAMERATE 40097
#define ID_HACKS_RUNXBOXTHREADSONALLCORES 40098
#define ID_HACKS_PATCHCPUFREQUENCY 40099
#define IDC_STATIC -1
// Next default values for new objects

View File

@ -190,6 +190,12 @@ WndMain::WndMain(HINSTANCE x_hInstance) :
m_UseAllCores = 0;
}
dwType = REG_DWORD; dwSize = sizeof(DWORD);
result = RegQueryValueEx(hKey, "HackPatchCpuFrequency", NULL, &dwType, (PBYTE)&m_PatchCpuFrequency, &dwSize);
if (result != ERROR_SUCCESS) {
m_PatchCpuFrequency = 0;
}
dwType = REG_DWORD; dwSize = sizeof(DWORD);
result = RegQueryValueEx(hKey, "CxbxDebug", NULL, &dwType, (PBYTE)&m_CxbxDebug, &dwSize);
if (result != ERROR_SUCCESS) {
@ -349,6 +355,9 @@ WndMain::~WndMain()
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegSetValueEx(hKey, "HackUseAllCores", 0, dwType, (PBYTE)&m_UseAllCores, dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegSetValueEx(hKey, "HackPatchCpuFrequency", 0, dwType, (PBYTE)&m_PatchCpuFrequency, dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegSetValueEx(hKey, "CxbxDebug", 0, dwType, (PBYTE)&m_CxbxDebug, dwSize);
@ -1311,6 +1320,10 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP
RefreshMenus();
break;
case ID_HACKS_PATCHCPUFREQUENCY:
m_PatchCpuFrequency = !m_PatchCpuFrequency;
RefreshMenus();
break;
case ID_HELP_ABOUT:
{
@ -1739,6 +1752,9 @@ void WndMain::RefreshMenus()
chk_flag = (m_UseAllCores) ? MF_CHECKED : MF_UNCHECKED;
CheckMenuItem(settings_menu, ID_HACKS_RUNXBOXTHREADSONALLCORES, chk_flag);
chk_flag = (m_PatchCpuFrequency) ? MF_CHECKED : MF_UNCHECKED;
CheckMenuItem(settings_menu, ID_HACKS_PATCHCPUFREQUENCY, chk_flag);
}
// emulation menu
@ -2112,6 +2128,7 @@ void WndMain::StartEmulation(HWND hwndParent, DebuggerState LocalDebuggerState /
g_EmuShared->SetDisablePixelShaders(&m_DisablePixelShaders);
g_EmuShared->SetUncapFramerate(&m_UncapFramerate);
g_EmuShared->SetUseAllCores(&m_UseAllCores);
g_EmuShared->SetPatchCpuFrequency(&m_PatchCpuFrequency);
// shell exe
{

View File

@ -216,6 +216,7 @@ class WndMain : public Wnd
int m_DisablePixelShaders;
int m_UncapFramerate;
int m_UseAllCores;
int m_PatchCpuFrequency;
// ******************************************************************
// * debug output filenames

View File

@ -579,6 +579,7 @@ void PrintCurrentConfigurationLog()
printf("Disable Pixel Shaders: %s\n", g_DisablePixelShaders == 1 ? "On" : "Off");
printf("Uncap Framerate: %s\n", g_UncapFramerate == 1 ? "On" : "Off");
printf("Run Xbox threads on all cores: %s\n", g_UseAllCores == 1 ? "On" : "Off");
printf("Patch CPU Frequency (rdtsc): %s\n", g_PatchCpuFrequency == 1 ? "On" : "Off");
}
printf("------------------------- END OF CONFIG LOG ------------------------\n");
@ -648,6 +649,38 @@ static unsigned int WINAPI CxbxKrnlInterruptThread(PVOID param)
return 0;
}
void PatchPerformanceFrequency()
{
DWORD xboxFrequency = 733333333; // 733mhz
LARGE_INTEGER hostFrequency;
QueryPerformanceFrequency(&hostFrequency);
DbgPrintf("INIT: Patching FS Register Accesses\n");
DWORD sizeOfImage = CxbxKrnl_XbeHeader->dwSizeofImage;
// Iterate through each CODE section
for (uint32 sectionIndex = 0; sectionIndex < CxbxKrnl_Xbe->m_Header.dwSections; sectionIndex++) {
if (!CxbxKrnl_Xbe->m_SectionHeader[sectionIndex].dwFlags.bExecutable) {
continue;
}
printf("INIT: Searching for xbox performance frequency in section %s\n", CxbxKrnl_Xbe->m_szSectionName[sectionIndex]);
xbaddr startAddr = CxbxKrnl_Xbe->m_SectionHeader[sectionIndex].dwVirtualAddr;
xbaddr endAddr = startAddr + CxbxKrnl_Xbe->m_SectionHeader[sectionIndex].dwSizeofRaw;
for (xbaddr addr = startAddr; addr < endAddr; addr++)
{
if (memcmp((void*)addr, &xboxFrequency, sizeof(DWORD)) == 0) {
printf("INIT: Patching Frequency at 0x%.8X\n", addr);
*(uint32*)(addr + 1) = (uint32)hostFrequency.QuadPart;
addr += sizeof(DWORD);
break;
}
}
}
printf("INIT: Done patching xbox performance frequency\n");
}
void CxbxKrnlMain(int argc, char* argv[])
{
// Skip '/load' switch
@ -1039,6 +1072,8 @@ __declspec(noreturn) void CxbxKrnlInit
g_UncapFramerate = !!HackEnabled;
g_EmuShared->GetUseAllCores(&HackEnabled);
g_UseAllCores = !!HackEnabled;
g_EmuShared->GetPatchCpuFrequency(&HackEnabled);
g_PatchCpuFrequency = !!HackEnabled;
}
#ifdef _DEBUG_PRINT_CURRENT_CONF
@ -1204,6 +1239,10 @@ __declspec(noreturn) void CxbxKrnlInit
// See: https://multimedia.cx/eggs/xbox-sphinx-protocol/
ApplyMediaPatches();
if (g_PatchCpuFrequency) {
PatchPerformanceFrequency();
}
// Setup per-title encryption keys
SetupPerTitleKeys();

View File

@ -67,6 +67,7 @@ bool g_XInputEnabled = false;
bool g_DisablePixelShaders = false;
bool g_UncapFramerate = false;
bool g_UseAllCores = false;
bool g_PatchCpuFrequency = false;
// Delta added to host SystemTime, used in xboxkrnl::KeQuerySystemTime and xboxkrnl::NtSetSystemTime
LARGE_INTEGER HostSystemTimeDelta = {};

View File

@ -110,4 +110,5 @@ typedef struct DUMMY_KERNEL
extern bool g_DisablePixelShaders;
extern bool g_UncapFramerate;
extern bool g_UseAllCores;
extern bool g_PatchCpuFrequency;
#endif

View File

@ -215,11 +215,6 @@ g_EmuCDPD = {0};
#endif
// Declares an unpatched Xbox function trampoline, callable by name (with a 'XB_' prefix attached)
#define XB_trampoline(ret, conv, name, arguments) \
typedef ret(conv *XB_##name##_t)arguments; \
static XB_##name##_t XB_##name = (XB_##name##_t)GetXboxFunctionPointer(#name);
// TODO: This should be a D3DDevice structure
DWORD* g_XboxD3DDevice;

View File

@ -1096,6 +1096,11 @@ XBSYSAPI EXPORTNUM(126) xboxkrnl::ULONGLONG NTAPI xboxkrnl::KeQueryPerformanceCo
ULONGLONG ret;
::LARGE_INTEGER PerformanceCounter;
if (g_PatchCpuFrequency) {
RETURN((ULONGLONG)__rdtsc());
}
// TODO : When Cxbx emulates the RDTSC opcode, use the same handling here.
// Dxbx note : Xbox actually uses the RDTSC machine code instruction for this,

View File

@ -126,6 +126,8 @@ class EmuShared : public Mutex
void SetUncapFramerate(int* value) { Lock(); m_UncapFramerate = *value; Unlock(); }
void GetUseAllCores(int* value) { Lock(); *value = m_UseAllCores; Unlock(); }
void SetUseAllCores(int* value) { Lock(); m_UseAllCores = *value; Unlock(); }
void GetPatchCpuFrequency(int* value) { Lock(); *value = m_PatchCpuFrequeny; Unlock(); }
void SetPatchCpuFrequency(int* value) { Lock(); m_PatchCpuFrequeny = *value; Unlock(); }
// ******************************************************************
// * MSpF/Benchmark values Accessors
@ -194,6 +196,7 @@ class EmuShared : public Mutex
int m_DisablePixelShaders;
int m_UncapFramerate;
int m_UseAllCores;
int m_PatchCpuFrequeny;
float m_MSpF;
float m_FPS;
bool m_bMultiXbeFlag;

View File

@ -940,6 +940,11 @@ BOOL WINAPI XTL::EMUPATCH(QueryPerformanceCounter)
{
FUNC_EXPORTS;
if (g_PatchCpuFrequency) {
lpPerformanceCount->QuadPart = (LONGLONG)__rdtsc();
return TRUE;
}
lpPerformanceCount->QuadPart = xboxkrnl::KeQueryPerformanceCounter();
return TRUE;
}

View File

@ -47,6 +47,11 @@ void EmuHLEIntercept(Xbe::Header *XbeHeader);
std::string GetDetectedSymbolName(xbaddr address, int *symbolOffset);
void* GetXboxFunctionPointer(std::string functionName);
// Declares an unpatched Xbox function trampoline, callable by name (with a 'XB_' prefix attached)
#define XB_trampoline(ret, conv, name, arguments) \
typedef ret(conv *XB_##name##_t)arguments; \
static XB_##name##_t XB_##name = (XB_##name##_t)GetXboxFunctionPointer(#name);
#ifdef _DEBUG_TRACE
void VerifyHLEDataBase();
#endif