2005-08-26 17:39:27 +00:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
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
|
2005-10-29 01:53:09 +00:00
|
|
|
along with Quake III Arena source code; if not, write to the Free Software
|
2005-08-26 17:39:27 +00:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
2005-10-26 19:45:21 +00:00
|
|
|
#include "../qcommon/q_shared.h"
|
2005-08-26 17:39:27 +00:00
|
|
|
#include "../qcommon/qcommon.h"
|
|
|
|
#include "win_local.h"
|
|
|
|
#include <lmerr.h>
|
|
|
|
#include <lmcons.h>
|
|
|
|
#include <lmwksta.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <direct.h>
|
|
|
|
#include <io.h>
|
|
|
|
#include <conio.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-09-23 02:59:15 +00:00
|
|
|
#ifndef __GNUC__ //see snapvectora.s
|
2005-08-26 17:39:27 +00:00
|
|
|
/*
|
|
|
|
================
|
|
|
|
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;
|
|
|
|
}
|
2005-09-23 02:59:15 +00:00
|
|
|
#endif
|
2005-08-26 17:39:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
**
|
|
|
|
** Disable all optimizations temporarily so this code works correctly!
|
|
|
|
**
|
|
|
|
*/
|
2005-09-22 03:21:33 +00:00
|
|
|
#ifdef _MSC_VER
|
2005-08-26 17:39:27 +00:00
|
|
|
#pragma optimize( "", off )
|
2005-09-22 03:21:33 +00:00
|
|
|
#endif
|
2005-08-26 17:39:27 +00:00
|
|
|
|
2005-09-22 03:21:33 +00:00
|
|
|
// 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__
|
2005-08-26 17:39:27 +00:00
|
|
|
/*
|
|
|
|
** --------------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
** 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
|
|
|
|
}
|
2005-09-22 03:21:33 +00:00
|
|
|
#endif
|
2005-08-26 17:39:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
**
|
|
|
|
** Re-enable optimizations back to what they were
|
|
|
|
**
|
|
|
|
*/
|
2005-09-22 03:21:33 +00:00
|
|
|
#ifdef _MSC_VER
|
2005-08-26 17:39:27 +00:00
|
|
|
#pragma optimize( "", on )
|
2005-09-22 03:21:33 +00:00
|
|
|
#endif
|
2005-08-26 17:39:27 +00:00
|
|
|
|
|
|
|
//============================================
|
|
|
|
|
|
|
|
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) {
|
2006-08-01 11:41:49 +00:00
|
|
|
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" );
|
2006-08-01 17:36:47 +00:00
|
|
|
if( !CreateDirectory( path, NULL ) )
|
2006-08-01 11:41:49 +00:00
|
|
|
{
|
|
|
|
if( GetLastError() != ERROR_ALREADY_EXISTS )
|
|
|
|
{
|
|
|
|
Com_Printf("Unable to create directory \"%s\"\n", path);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return path;
|
2005-08-26 17:39:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *Sys_DefaultInstallPath(void)
|
|
|
|
{
|
|
|
|
return Sys_Cwd();
|
|
|
|
}
|
|
|
|
|