fix ps/2 mouse init, make Stall more precise, rename CurrentProcess to KeGetCurrentProcess, correct type about maneuvers, add file writing to win32
This commit is contained in:
1 parent
8c7564d5e1
commit
a37f5b1581
14 files changed
+288
-75
No files matched your search
+77
-8
@@ -23,6 +23,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Syscall stubs (from syscall.dll, assembled from syscall_stubs.asm)
|
||||
@@ -155,7 +156,7 @@ __declspec(dllexport) void OutputDebugStringA(const char* str) {
|
||||
// Timer
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) DWORD GetTickCount(void) {
|
||||
return (DWORD)SysGetTick();
|
||||
return (DWORD)SysGetTick() * 10;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1041,35 +1042,103 @@ __declspec(dllexport) void WakeAllConditionVariable(CONDITION_VARIABLE* cv) { (v
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Timing & Performance Counters
|
||||
// We report a 1 MHz counter so QPC / QPF is consistent with GetTickCount.
|
||||
//
|
||||
// We use the CPU's Time Stamp Counter (TSC) for QueryPerformanceCounter so
|
||||
// that callers like Bink get a truly high-resolution, continuously-advancing
|
||||
// clock. The TSC frequency is measured once on first use.
|
||||
//
|
||||
// Calibration strategy:
|
||||
// 1. Try CPUID leaf 0x15 (TSC / Crystal-clock ratio). If the crystal
|
||||
// frequency (ECX) is non-zero, compute TSC Hz = crystal_hz * EBX / EAX
|
||||
// with no blocking at all.
|
||||
// 2. Otherwise fall back to measuring TSC ticks over a known wall-clock
|
||||
// interval supplied by SysGetTick(). SysGetTick() returns raw LAPIC
|
||||
// interrupt counts; each unit represents QUANTUM_MS = 10 ms. We wait
|
||||
// for two consecutive tick-boundary crossings and divide.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define QUANTUM_MS 10 // must match hal_timer.c QUANTUM_MS
|
||||
|
||||
typedef union {
|
||||
struct { DWORD LowPart; long HighPart; } u;
|
||||
long long QuadPart;
|
||||
} LARGE_INTEGER;
|
||||
|
||||
#define QPC_FREQUENCY 1000000LL // 1 MHz
|
||||
static volatile long long gTscFreq = 0; // TSC ticks per second; 0 = uninitialised
|
||||
|
||||
// Attempt to read TSC frequency from CPUID leaf 0x15.
|
||||
// Returns 0 if the leaf is absent or the crystal frequency is not enumerated.
|
||||
static long long TscFreqFromCpuid(void) {
|
||||
int info[4];
|
||||
__cpuid(info, 0);
|
||||
if ((unsigned)info[0] < 0x15) return 0;
|
||||
|
||||
__cpuid(info, 0x15);
|
||||
unsigned denom = (unsigned)info[0]; // EAX – TSC/crystal denominator
|
||||
unsigned numer = (unsigned)info[1]; // EBX – TSC/crystal numerator
|
||||
unsigned crystal_hz = (unsigned)info[2]; // ECX – crystal clock in Hz
|
||||
|
||||
if (!denom || !numer || !crystal_hz) return 0;
|
||||
return (long long)crystal_hz * numer / denom;
|
||||
}
|
||||
|
||||
// Calibrate TSC frequency by timing over two LAPIC-tick boundaries.
|
||||
// Each SysGetTick() unit = QUANTUM_MS ms; we measure across N_TICKS units
|
||||
// for a total gate time of N_TICKS * QUANTUM_MS ms.
|
||||
static long long TscFreqCalibrate(void) {
|
||||
const uint64_t N_TICKS = 10; // 10 * 10 ms = 100 ms gate time
|
||||
|
||||
// Synchronise to the leading edge of a tick.
|
||||
uint64_t t = SysGetTick();
|
||||
while (SysGetTick() == t) { _mm_pause(); }
|
||||
|
||||
uint64_t tsc0 = __rdtsc();
|
||||
uint64_t t0 = SysGetTick();
|
||||
|
||||
// Wait for N_TICKS more ticks.
|
||||
while ((SysGetTick() - t0) < N_TICKS) { _mm_pause(); }
|
||||
|
||||
uint64_t tsc1 = __rdtsc();
|
||||
uint64_t ticks_got = SysGetTick() - t0; // actual ticks elapsed (>= N_TICKS)
|
||||
|
||||
// ticks_got LAPIC ticks = ticks_got * QUANTUM_MS ms = ticks_got * QUANTUM_MS / 1000 s
|
||||
// TSC Hz = (tsc1-tsc0) / (ticks_got * QUANTUM_MS / 1000)
|
||||
// = (tsc1-tsc0) * 1000 / (ticks_got * QUANTUM_MS)
|
||||
return (long long)((tsc1 - tsc0) * 1000ULL / (ticks_got * (uint64_t)QUANTUM_MS));
|
||||
}
|
||||
|
||||
static long long TscFreqGet(void) {
|
||||
if (gTscFreq) return gTscFreq;
|
||||
|
||||
long long f = TscFreqFromCpuid();
|
||||
if (!f) f = TscFreqCalibrate();
|
||||
|
||||
gTscFreq = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
__declspec(dllexport) BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency) {
|
||||
if (lpFrequency) lpFrequency->QuadPart = QPC_FREQUENCY;
|
||||
if (lpFrequency) lpFrequency->QuadPart = TscFreqGet();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
__declspec(dllexport) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount) {
|
||||
// SysGetTick returns milliseconds; scale to microseconds for 1 MHz QPC.
|
||||
// Ensure frequency is measured before the first counter read so that the
|
||||
// baseline TSC and the frequency come from the same calibration window.
|
||||
TscFreqGet();
|
||||
if (lpPerformanceCount)
|
||||
lpPerformanceCount->QuadPart = (long long)SysGetTick() * 1000LL;
|
||||
lpPerformanceCount->QuadPart = (long long)__rdtsc();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void GetSystemTimeAsFileTime(void* lpSystemTimeAsFileTime) {
|
||||
// Return a fixed FILETIME representing 2024-01-01 00:00:00 UTC.
|
||||
// FILETIME = 100-nanosecond intervals since 1601-01-01.
|
||||
// 2024-01-01 offset from 1601 in 100ns units: 133186080000000000
|
||||
// 2024-01-01 offset: 133186080000000000 * 100 ns
|
||||
if (!lpSystemTimeAsFileTime) return;
|
||||
// SysGetTick() units = QUANTUM_MS ms = QUANTUM_MS * 10000 * 100-ns intervals.
|
||||
unsigned long long ft = 133186080000000000ULL
|
||||
+ (unsigned long long)SysGetTick() * 10000ULL;
|
||||
+ SysGetTick() * ((unsigned long long)QUANTUM_MS * 10000ULL);
|
||||
unsigned char* p = (unsigned char*)lpSystemTimeAsFileTime;
|
||||
for (int i = 0; i < 8; i++) p[i] = (unsigned char)(ft >> (i * 8));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user