/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. Copyright (C) 2000-2006 Tim Angus This file is part of Tremulous. Tremulous 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. Tremulous 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 Tremulous; 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" #include #include #include #include #include #include #include #include #include /* ================ Sys_Milliseconds ================ */ int sys_timeBase; int Sys_Milliseconds (void) { int sys_curtime; static qboolean initialized = qfalse; if (!initialized) { sys_timeBase = timeGetTime(); initialized = qtrue; } sys_curtime = timeGetTime() - sys_timeBase; return sys_curtime; } #ifndef __GNUC__ //see snapvectora.s /* ================ Sys_SnapVector ================ */ void Sys_SnapVector( float *v ) { int i; float f; f = *v; __asm fld f; __asm fistp i; *v = i; v++; f = *v; __asm fld f; __asm fistp i; *v = i; v++; f = *v; __asm fld f; __asm fistp i; *v = i; } #endif /* ** ** Disable all optimizations temporarily so this code works correctly! ** */ #ifdef _MSC_VER #pragma optimize( "", off ) #endif // If you fancy porting this stuff to AT&T then feel free... :) // It's not actually used functionally though, so it may be a waste of effort #ifndef __MINGW32__ /* ** -------------------------------------------------------------------------------- ** ** PROCESSOR STUFF ** ** -------------------------------------------------------------------------------- */ 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 int IsPentium( void ) { __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 int Is3DNOW( void ) { unsigned regs[4]; char pstring[16]; char processorString[13]; // get name of processor CPUID( 0, ( unsigned int * ) pstring ); processorString[0] = pstring[4]; processorString[1] = pstring[5]; processorString[2] = pstring[6]; processorString[3] = pstring[7]; processorString[4] = pstring[12]; processorString[5] = pstring[13]; processorString[6] = pstring[14]; processorString[7] = pstring[15]; processorString[8] = pstring[8]; processorString[9] = pstring[9]; processorString[10] = pstring[10]; processorString[11] = pstring[11]; processorString[12] = 0; // REMOVED because you can have 3DNow! on non-AMD systems // if ( strcmp( processorString, "AuthenticAMD" ) ) // return qfalse; // check AMD-specific functions CPUID( 0x80000000, regs ); if ( regs[0] < 0x80000000 ) return qfalse; // bit 31 of EDX denotes 3DNOW! support CPUID( 0x80000001, regs ); if ( regs[3] & ( 1 << 31 ) ) return qtrue; return qfalse; } static int IsKNI( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 25 of EDX denotes KNI existence if ( regs[3] & ( 1 << 25 ) ) return qtrue; return qfalse; } static int IsMMX( void ) { unsigned regs[4]; // get CPU feature bits CPUID( 1, regs ); // bit 23 of EDX denotes MMX existence if ( regs[3] & ( 1 << 23 ) ) return qtrue; return qfalse; } int Sys_GetProcessorId( void ) { #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() ) return CPUID_INTEL_UNSUPPORTED; // check for MMX if ( !IsMMX() ) { // Pentium or PPro return CPUID_INTEL_PENTIUM; } // see if we're an AMD 3DNOW! processor if ( Is3DNOW() ) { return CPUID_AMD_3DNOW; } // see if we're an Intel Katmai if ( IsKNI() ) { return CPUID_INTEL_KATMAI; } // by default we're functionally a vanilla Pentium/MMX or P2/MMX return CPUID_INTEL_MMX; #endif } #endif /* ** ** Re-enable optimizations back to what they were ** */ #ifdef _MSC_VER #pragma optimize( "", on ) #endif //============================================ char *Sys_GetCurrentUser( void ) { static char s_userName[1024]; unsigned long size = sizeof( s_userName ); if ( !GetUserName( s_userName, &size ) ) strcpy( s_userName, "player" ); if ( !s_userName[0] ) { strcpy( s_userName, "player" ); } return s_userName; } char *Sys_DefaultHomePath(void) { TCHAR szPath[MAX_PATH]; static char path[MAX_OSPATH]; if( !SUCCEEDED( SHGetFolderPath( NULL, CSIDL_LOCAL_APPDATA, NULL, 0, szPath ) ) ) { return NULL; } Q_strncpyz( path, szPath, sizeof(path) ); Q_strcat( path, sizeof(path), "\\Quake3" ); if( !CreateDirectory( path, NULL ) ) { if( GetLastError() != ERROR_ALREADY_EXISTS ) { Com_Printf("Unable to create directory \"%s\"\n", path); return NULL; } } return path; } char *Sys_DefaultInstallPath(void) { return Sys_Cwd(); }