Merge pull request #1503 from LukeUsher/fix-nxdk-and-more

Fix nxdk and KeQueryPerformanceCounter
This commit is contained in:
Luke Usher 2018-11-12 18:42:51 +00:00 committed by GitHub
commit 3393ccc684
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 102 deletions

View File

@ -252,74 +252,28 @@ Xbe::Xbe(const char *x_szFilename, bool bFromGUI)
}
// read Xbe library versions
if(m_Header.dwLibraryVersionsAddr != 0)
{
printf("Xbe::Xbe: Reading Library Versions...\n");
if (m_Header.dwLibraryVersionsAddr != 0)
{
printf("Xbe::Xbe: Reading Library Versions...\n");
fseek(XbeFile, m_Header.dwLibraryVersionsAddr - m_Header.dwBaseAddr, SEEK_SET);
fseek(XbeFile, m_Header.dwLibraryVersionsAddr - m_Header.dwBaseAddr, SEEK_SET);
m_LibraryVersion = new LibraryVersion[m_Header.dwLibraryVersions];
m_LibraryVersion = new LibraryVersion[m_Header.dwLibraryVersions];
for(uint32 v=0;v<m_Header.dwLibraryVersions;v++)
{
printf("Xbe::Xbe: Reading Library Version 0x%.04X...", v);
for (uint32 v = 0; v < m_Header.dwLibraryVersions; v++)
{
printf("Xbe::Xbe: Reading Library Version 0x%.04X...", v);
if(fread(&m_LibraryVersion[v], sizeof(*m_LibraryVersion), 1, XbeFile) != 1)
{
sprintf(szBuffer, "Unexpected end of file while reading Xbe Library Version %d (%Xh)", v, v);
SetFatalError(szBuffer);
goto cleanup;
}
if (fread(&m_LibraryVersion[v], sizeof(*m_LibraryVersion), 1, XbeFile) != 1)
{
sprintf(szBuffer, "Unexpected end of file while reading Xbe Library Version %d (%Xh)", v, v);
SetFatalError(szBuffer);
goto cleanup;
}
printf("OK\n");
}
// read Xbe kernel library version
{
printf("Xbe::Xbe: Reading Kernel Library Version...");
if(m_Header.dwKernelLibraryVersionAddr == 0)
{
SetFatalError("Could not locate kernel library version");
goto cleanup;
}
fseek(XbeFile, m_Header.dwKernelLibraryVersionAddr - m_Header.dwBaseAddr, SEEK_SET);
m_KernelLibraryVersion = new LibraryVersion;
if(fread(m_KernelLibraryVersion, sizeof(*m_LibraryVersion), 1, XbeFile) != 1)
{
SetFatalError("Unexpected end of file while reading Xbe Kernel Version");
goto cleanup;
}
printf("OK\n");
}
// read Xbe Xapi library version
{
printf("Xbe::Xbe: Reading Xapi Library Version...");
if(m_Header.dwXAPILibraryVersionAddr == 0)
{
SetFatalError("Could not locate Xapi Library Version");
goto cleanup;
}
fseek(XbeFile, m_Header.dwXAPILibraryVersionAddr - m_Header.dwBaseAddr, SEEK_SET);
m_XAPILibraryVersion = new LibraryVersion;
if(fread(m_XAPILibraryVersion, sizeof(*m_LibraryVersion), 1, XbeFile) != 1)
{
SetFatalError("Unexpected end of file while reading Xbe Xapi Version");
goto cleanup;
}
printf("OK\n");
}
}
printf("OK\n");
}
}
// read Xbe sections
{
@ -412,8 +366,6 @@ Xbe::~Xbe()
delete[] m_bzSection;
}
delete m_XAPILibraryVersion;
delete m_KernelLibraryVersion;
delete[] m_LibraryVersion;
delete m_TLS;
delete[] m_szSectionName;
@ -579,8 +531,6 @@ void Xbe::ConstructorInit()
m_SectionHeader = 0;
m_szSectionName = 0;
m_LibraryVersion = 0;
m_KernelLibraryVersion = 0;
m_XAPILibraryVersion = 0;
m_TLS = 0;
m_bzSection = 0;
m_SignatureHeader = 0;

View File

@ -230,7 +230,7 @@ class Xbe : public Error
};
}
#include "AlignPosfix1.h"
*m_LibraryVersion, *m_KernelLibraryVersion, *m_XAPILibraryVersion;
*m_LibraryVersion;
// Xbe thread local storage
#include "AlignPrefix1.h"

View File

@ -336,22 +336,27 @@ void InitDpcAndTimerThread()
g_DpcData.DpcEvent = CreateEvent(/*lpEventAttributes=*/nullptr, /*bManualReset=*/FALSE, /*bInitialState=*/FALSE, /*lpName=*/nullptr);
}
// Xbox Performance Counter Frequency = 733333333 (CPU Clock)
#define XBOX_PERFORMANCE_FREQUENCY 733333333
ULONGLONG NativeToXbox_FactorForPerformanceFrequency;
#define XBOX_TSC_FREQUENCY 733333333 // Xbox Time Stamp Counter Frequency = 733333333 (CPU Clock)
#define XBOX_ACPI_FREQUENCY 3375000 // Xbox ACPI frequency (3.375 mhz)
ULONGLONG NativeToXbox_FactorForRdtsc;
ULONGLONG NativeToXbox_FactorForAcpi;
void ConnectKeInterruptTimeToThunkTable(); // forward
ULONGLONG CxbxRdTsc(bool xbox) {
ULONGLONG CxbxGetPerformanceCounter(bool acpi) {
LARGE_INTEGER tsc;
ULARGE_INTEGER scaledTsc;
QueryPerformanceCounter(&tsc);
scaledTsc.QuadPart = 1000000000;
scaledTsc.QuadPart *= (ULONGLONG)tsc.QuadPart;
QueryPerformanceCounter(&tsc);
if (xbox && NativeToXbox_FactorForPerformanceFrequency) {
ULARGE_INTEGER scaledTsc;
scaledTsc.QuadPart = 1000000000;
scaledTsc.QuadPart *= (ULONGLONG)tsc.QuadPart;
scaledTsc.QuadPart /= NativeToXbox_FactorForPerformanceFrequency;
if (acpi == false && NativeToXbox_FactorForRdtsc) {
scaledTsc.QuadPart /= NativeToXbox_FactorForRdtsc;
return scaledTsc.QuadPart;
} else if (acpi == true && NativeToXbox_FactorForRdtsc) {
scaledTsc.QuadPart /= NativeToXbox_FactorForAcpi;
return scaledTsc.QuadPart;
}
@ -370,8 +375,13 @@ void CxbxInitPerformanceCounters()
LARGE_INTEGER t;
t.QuadPart = 1000000000;
t.QuadPart *= CxbxCalibrateTsc();
t.QuadPart /= XBOX_PERFORMANCE_FREQUENCY;
NativeToXbox_FactorForPerformanceFrequency = t.QuadPart;
t.QuadPart /= XBOX_TSC_FREQUENCY;
NativeToXbox_FactorForRdtsc = t.QuadPart;
t.QuadPart = 1000000000;
t.QuadPart *= CxbxCalibrateTsc();
t.QuadPart /= XBOX_ACPI_FREQUENCY;
NativeToXbox_FactorForAcpi = t.QuadPart;
ConnectKeInterruptTimeToThunkTable();
@ -1204,19 +1214,15 @@ XBSYSAPI EXPORTNUM(125) xboxkrnl::ULONGLONG NTAPI xboxkrnl::KeQueryInterruptTime
}
// ******************************************************************
// * 0x007E - KeQueryPerformanceCounter()
// * 0x007E - KeQueryPerformanceCounter()
// NOTE: The KeQueryPerformance* functions run at the ACPI clock
// The XAPI QueryPerformance* functions run at the TSC clock
// ******************************************************************
XBSYSAPI EXPORTNUM(126) xboxkrnl::ULONGLONG NTAPI xboxkrnl::KeQueryPerformanceCounter(void)
{
LOG_FUNC();
ULONGLONG ret;
//no matter rdtsc is patched or not, we should always return a scaled performance counter here.
DBG_PRINTF("host tick count : %lu\n", CxbxRdTsc(/*xbox=*/false));
ret = CxbxRdTsc(/*xbox=*/true);
DBG_PRINTF("emulated tick count : %lu\n", ret);
ret = CxbxGetPerformanceCounter(/*acpi=*/true);
RETURN(ret);
}
@ -1226,11 +1232,7 @@ XBSYSAPI EXPORTNUM(126) xboxkrnl::ULONGLONG NTAPI xboxkrnl::KeQueryPerformanceCo
XBSYSAPI EXPORTNUM(127) xboxkrnl::ULONGLONG NTAPI xboxkrnl::KeQueryPerformanceFrequency(void)
{
LOG_FUNC();
// Dxbx note : We return the real Xbox1 frequency here,
// to make subsequent calculations behave the same as on the real Xbox1 :
ULONGLONG ret = XBOX_PERFORMANCE_FREQUENCY;
ULONGLONG ret = XBOX_ACPI_FREQUENCY;
RETURN(ret);
}

View File

@ -1297,13 +1297,12 @@ bool EmuX86_Opcode_PUSH(LPEXCEPTION_POINTERS e, _DInst& info)
return true;
}
ULONGLONG CxbxRdTsc(bool xbox); // implemented in EmuKrnlKe.cpp
ULONGLONG CxbxGetPerformanceCounter(bool acpi); // implemented in EmuKrnlKe.cpp
void EmuX86_Opcode_RDTSC(LPEXCEPTION_POINTERS e)
{
// Avoid the overhead of xboxkrnl::KeQueryPerformanceCounter,
// by calling directly into it's backing implementation:
// We use CxbxGetPerformanceCounter. KeQueryPerformanceCounter is a differnet frequency and cannot be used!
ULARGE_INTEGER PerformanceCount;
PerformanceCount.QuadPart = CxbxRdTsc(/*xbox=*/true);
PerformanceCount.QuadPart = CxbxGetPerformanceCounter(/*acpi*/false);
e->ContextRecord->Eax = PerformanceCount.LowPart;
e->ContextRecord->Edx = PerformanceCount.HighPart;
}

View File

@ -1505,15 +1505,16 @@ LPVOID WINAPI XTL::EMUPATCH(ConvertThreadToFiber)
// ******************************************************************
// * patch: QueryPerformanceCounter
// ******************************************************************
// ******************************************************************
ULONGLONG CxbxGetPerformanceCounter(bool acpi); // implemented in EmuKrnlKe.cpp
BOOL WINAPI XTL::EMUPATCH(QueryPerformanceCounter)
(
LARGE_INTEGER * lpPerformanceCount
)
{
lpPerformanceCount->QuadPart = xboxkrnl::KeQueryPerformanceCounter();
// NOTE: QueryPerformanceCounter runs from the tsc via RdTsc (733mhz)
// However, KeQueryPerformanceCounter runs at 3.375Mhz, so we can't use that here
lpPerformanceCount->QuadPart = CxbxGetPerformanceCounter(false);
return TRUE;
}