cnq3/code/win32/win_shared.cpp
2016-12-17 20:43:04 -08:00

177 lines
3.6 KiB
C++

/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena 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 2 of the License,
or (at your option) any later version.
Quake III Arena 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "win_local.h"
int Sys_Milliseconds()
{
static int sys_timeBase = 0;
if (!sys_timeBase)
sys_timeBase = timeGetTime();
return (timeGetTime() - sys_timeBase);
}
// disable all optimizations temporarily so this code works correctly!
#ifdef _MSC_VER
#pragma optimize( "", off )
#pragma warning(disable : 4748) // don't fkn WHINE about using that pragma
#endif
static void CPUID( int func, unsigned regs[4] )
{
unsigned regEAX, regEBX, regECX, regEDX;
__asm mov eax, func
__asm __emit 00fh
__asm __emit 0a2h
__asm mov regEAX, eax
__asm mov regEBX, ebx
__asm mov regECX, ecx
__asm mov regEDX, edx
regs[0] = regEAX;
regs[1] = regEBX;
regs[2] = regECX;
regs[3] = regEDX;
}
static qbool IsPentium()
{
__asm
{
pushfd // save eflags
pop eax
test eax, 0x00200000 // check ID bit
jz set21 // bit 21 is not set, so jump to set_21
and eax, 0xffdfffff // clear bit 21
push eax // save new value in register
popfd // store new value in flags
pushfd
pop eax
test eax, 0x00200000 // check ID bit
jz good
jmp err // cpuid not supported
set21:
or eax, 0x00200000 // set ID bit
push eax // store new value
popfd // store new value in EFLAGS
pushfd
pop eax
test eax, 0x00200000 // if bit 21 is on
jnz good
jmp err
}
err:
return qfalse;
good:
return qtrue;
}
static const char* CPU_Name()
{
static unsigned regs[4];
CPUID( 0, regs );
regs[0] = regs[1];
regs[1] = regs[3];
regs[3] = 0;
return (const char*)regs;
}
static int CPU_Cores()
{
unsigned regs[4];
CPUID( 1, regs );
return ((regs[1] & 0x00FF0000) >> 16);
}
struct CPU_FeatureBit { const char* s; int reg, bit; } CPU_FeatureBits[] =
{
{ " MMX", 3, 23 },
{ " SSE", 3, 25 },
{ " SSE2", 3, 26 },
{ " SSE3", 2, 26 },
{ 0 }
};
int Sys_GetProcessorId()
{
#if defined _M_ALPHA
return CPUID_AXP;
#elif !defined _M_IX86
return CPUID_GENERIC;
#else
// verify we're at least a Pentium or 486 w/ CPUID support
if ( !IsPentium() ) {
Cvar_Set( "sys_cpustring", "x86 (pre-Pentium)" );
return CPUID_UNSUPPORTED;
}
char s[64] = "";
Q_strcat( s, sizeof(s), CPU_Name() );
if (CPU_Cores() > 1)
Q_strcat( s, sizeof(s), va(" %d cores", CPU_Cores()) );
unsigned regs[4];
CPUID( 1, regs );
for (int i = 0; CPU_FeatureBits[i].s; ++i) {
if (regs[CPU_FeatureBits[i].reg] & (1 << regs[CPU_FeatureBits[i].bit])) {
Q_strcat( s, sizeof(s), CPU_FeatureBits[i].s );
}
}
Cvar_Set( "sys_cpustring", s );
return CPUID_GENERIC;
#endif
}
#ifdef _MSC_VER
#pragma optimize( "", on )
#endif
const char* Sys_GetCurrentUser()
{
return "player";
}
const char* Sys_DefaultHomePath()
{
return NULL;
}