/* =========================================================================== IceTech GPL Source Code Copyright (C) 2026 Justin Marshall This file is part of the IceTech GPL Source Code (?IceTech Source Code?). IceTech Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. IceTech Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with IceTech Source Code. If not, see . In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com =========================================================================== */ #include "precompiled.h" #pragma hdrstop #include "win_local.h" /* ============================================================== Clock ticks ============================================================== */ /* ================ Sys_GetClockTicks ================ */ double Sys_GetClockTicks(void) { LARGE_INTEGER li; QueryPerformanceCounter(&li); return (double)li.LowPart + (double)0xFFFFFFFF * li.HighPart; } /* ================ Sys_ClockTicksPerSecond ================ */ double Sys_ClockTicksPerSecond(void) { static double ticks = 0; if (!ticks) { HKEY hKey; LPBYTE ProcSpeed; DWORD buflen, ret; if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey)) { ProcSpeed = 0; buflen = sizeof(ProcSpeed); ret = RegQueryValueEx(hKey, "~MHz", NULL, NULL, (LPBYTE)&ProcSpeed, &buflen); // If we don't succeed, try some other spellings. if (ret != ERROR_SUCCESS) { ret = RegQueryValueEx(hKey, "~Mhz", NULL, NULL, (LPBYTE)&ProcSpeed, &buflen); } if (ret != ERROR_SUCCESS) { ret = RegQueryValueEx(hKey, "~mhz", NULL, NULL, (LPBYTE)&ProcSpeed, &buflen); } RegCloseKey(hKey); if (ret == ERROR_SUCCESS) { ticks = (double)((unsigned long)ProcSpeed) * 1000000; } } } return ticks; } /* ============================================================== CPU ============================================================== */ /* ================ HasCPUID ================ */ static bool HasCPUID(void) { return true; } #define _REG_EAX 0 #define _REG_EBX 1 #define _REG_ECX 2 #define _REG_EDX 3 /* ================ CPUID ================ */ static void CPUID(int func, unsigned regs[4]) { } /* ================ IsAMD ================ */ static bool IsAMD(void) { return false; } /* ================ HasCMOV ================ */ static bool HasCMOV(void) { return false; } /* ================ Has3DNow ================ */ static bool Has3DNow(void) { return false; } /* ================ HasMMX ================ */ static bool HasMMX(void) { return false; } /* ================ HasSSE ================ */ static bool HasSSE(void) { return false; } /* ================ HasSSE2 ================ */ static bool HasSSE2(void) { return false; } /* ================ HasSSE3 ================ */ static bool HasSSE3(void) { return false; } /* ================ CPUCount logicalNum is the number of logical CPU per physical CPU physicalNum is the total number of physical processor returns one of the HT_* flags ================ */ #define HT_NOT_CAPABLE 0 #define HT_ENABLED 1 #define HT_DISABLED 2 #define HT_SUPPORTED_NOT_ENABLED 3 #define HT_CANNOT_DETECT 4 int CPUCount(int& logicalNum, int& physicalNum) { logicalNum = 8; physicalNum = 8; return 1; } /* ================ HasHTT ================ */ static bool HasHTT(void) { return true; } /* ================ HasHTT ================ */ static bool HasDAZ(void) { return false; } /* ================ Sys_GetCPUId ================ */ cpuid_t Sys_GetCPUId(void) { int flags; // verify we're at least a Pentium or 486 with CPUID support if (!HasCPUID()) { return CPUID_UNSUPPORTED; } // check for an AMD if (IsAMD()) { flags = CPUID_AMD; } else { flags = CPUID_INTEL; } // check for Multi Media Extensions if (HasMMX()) { flags |= CPUID_MMX; } // check for 3DNow! if (Has3DNow()) { flags |= CPUID_3DNOW; } // check for Streaming SIMD Extensions if (HasSSE()) { flags |= CPUID_SSE | CPUID_FTZ; } // check for Streaming SIMD Extensions 2 if (HasSSE2()) { flags |= CPUID_SSE2; } // check for Streaming SIMD Extensions 3 aka Prescott's New Instructions if (HasSSE3()) { flags |= CPUID_SSE3; } // check for Hyper-Threading Technology if (HasHTT()) { flags |= CPUID_HTT; } // check for Conditional Move (CMOV) and fast floating point comparison (FCOMI) instructions if (HasCMOV()) { flags |= CPUID_CMOV; } // check for Denormals-Are-Zero mode if (HasDAZ()) { flags |= CPUID_DAZ; } return (cpuid_t)flags; } /* =============================================================================== FPU =============================================================================== */ typedef struct bitFlag_s { char* name; int bit; } bitFlag_t; static byte fpuState[128], * statePtr = fpuState; static char fpuString[2048]; static bitFlag_t controlWordFlags[] = { { "Invalid operation", 0 }, { "Denormalized operand", 1 }, { "Divide-by-zero", 2 }, { "Numeric overflow", 3 }, { "Numeric underflow", 4 }, { "Inexact result (precision)", 5 }, { "Infinity control", 12 }, { "", 0 } }; static char* precisionControlField[] = { "Single Precision (24-bits)", "Reserved", "Double Precision (53-bits)", "Double Extended Precision (64-bits)" }; static char* roundingControlField[] = { "Round to nearest", "Round down", "Round up", "Round toward zero" }; static bitFlag_t statusWordFlags[] = { { "Invalid operation", 0 }, { "Denormalized operand", 1 }, { "Divide-by-zero", 2 }, { "Numeric overflow", 3 }, { "Numeric underflow", 4 }, { "Inexact result (precision)", 5 }, { "Stack fault", 6 }, { "Error summary status", 7 }, { "FPU busy", 15 }, { "", 0 } }; /* =============== Sys_FPU_PrintStateFlags =============== */ int Sys_FPU_PrintStateFlags(char* ptr, int ctrl, int stat, int tags, int inof, int inse, int opof, int opse) { int i, length = 0; length += sprintf(ptr + length, "CTRL = %08x\n" "STAT = %08x\n" "TAGS = %08x\n" "INOF = %08x\n" "INSE = %08x\n" "OPOF = %08x\n" "OPSE = %08x\n" "\n", ctrl, stat, tags, inof, inse, opof, opse); length += sprintf(ptr + length, "Control Word:\n"); for (i = 0; controlWordFlags[i].name[0]; i++) { length += sprintf(ptr + length, " %-30s = %s\n", controlWordFlags[i].name, (ctrl & (1 << controlWordFlags[i].bit)) ? "true" : "false"); } length += sprintf(ptr + length, " %-30s = %s\n", "Precision control", precisionControlField[(ctrl >> 8) & 3]); length += sprintf(ptr + length, " %-30s = %s\n", "Rounding control", roundingControlField[(ctrl >> 10) & 3]); length += sprintf(ptr + length, "Status Word:\n"); for (i = 0; statusWordFlags[i].name[0]; i++) { ptr += sprintf(ptr + length, " %-30s = %s\n", statusWordFlags[i].name, (stat & (1 << statusWordFlags[i].bit)) ? "true" : "false"); } length += sprintf(ptr + length, " %-30s = %d%d%d%d\n", "Condition code", (stat >> 8) & 1, (stat >> 9) & 1, (stat >> 10) & 1, (stat >> 14) & 1); length += sprintf(ptr + length, " %-30s = %d\n", "Top of stack pointer", (stat >> 11) & 7); return length; } /* =============== Sys_FPU_StackIsEmpty =============== */ bool Sys_FPU_StackIsEmpty(void) { return true; } /* =============== Sys_FPU_ClearStack =============== */ void Sys_FPU_ClearStack(void) { } /* =============== Sys_FPU_GetState gets the FPU state without changing the state =============== */ const char* Sys_FPU_GetState(void) { return ""; } /* =============== Sys_FPU_EnableExceptions =============== */ void Sys_FPU_EnableExceptions(int exceptions) { } /* =============== Sys_FPU_SetPrecision =============== */ void Sys_FPU_SetPrecision(int precision) { } /* ================ Sys_FPU_SetRounding ================ */ void Sys_FPU_SetRounding(int rounding) { } /* ================ Sys_FPU_SetDAZ ================ */ void Sys_FPU_SetDAZ(bool enable) { } /* ================ Sys_FPU_SetFTZ ================ */ void Sys_FPU_SetFTZ(bool enable) { }