123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /*
- ===========================================================================
- 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 Foobar; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- ===========================================================================
- */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
- #include <stdio.h>
- #include <dirent.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #include <sys/time.h>
- #include <pwd.h>
- #include "../game/q_shared.h"
- #include "../qcommon/qcommon.h"
- //=============================================================================
- // Used to determine CD Path
- static char cdPath[MAX_OSPATH];
- // Used to determine local installation path
- static char installPath[MAX_OSPATH];
- // Used to determine where to store user-specific files
- static char homePath[MAX_OSPATH];
- /*
- ================
- Sys_Milliseconds
- ================
- */
- /* base time in seconds, that's our origin
- timeval:tv_sec is an int:
- assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038
- using unsigned long data type to work right with Sys_XTimeToSysTime */
- unsigned long sys_timeBase = 0;
- /* current time in ms, using sys_timeBase as origin
- NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch
- 0x7fffffff ms - ~24 days
- although timeval:tv_usec is an int, I'm not sure wether it is actually used as an unsigned int
- (which would affect the wrap period) */
- int curtime;
- int Sys_Milliseconds (void)
- {
- struct timeval tp;
- gettimeofday(&tp, NULL);
-
- if (!sys_timeBase)
- {
- sys_timeBase = tp.tv_sec;
- return tp.tv_usec/1000;
- }
- curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
-
- return curtime;
- }
- #if defined(__linux__) && !defined(DEDICATED)
- /*
- ================
- Sys_XTimeToSysTime
- sub-frame timing of events returned by X
- X uses the Time typedef - unsigned long
- disable with in_subframe 0
- sys_timeBase*1000 is the number of ms since the Epoch of our origin
- xtime is in ms and uses the Epoch as origin
- Time data type is an unsigned long: 0xffffffff ms - ~49 days period
- I didn't find much info in the XWindow documentation about the wrapping
- we clamp sys_timeBase*1000 to unsigned long, that gives us the current origin for xtime
- the computation will still work if xtime wraps (at ~49 days period since the Epoch) after we set sys_timeBase
- ================
- */
- extern cvar_t *in_subframe;
- int Sys_XTimeToSysTime (unsigned long xtime)
- {
- int ret, time, test;
-
- if (!in_subframe->value)
- {
- // if you don't want to do any event times corrections
- return Sys_Milliseconds();
- }
- // test the wrap issue
- #if 0
- // reference values for test: sys_timeBase 0x3dc7b5e9 xtime 0x541ea451 (read these from a test run)
- // xtime will wrap in 0xabe15bae ms >~ 0x2c0056 s (33 days from Nov 5 2002 -> 8 Dec)
- // NOTE: date -d '1970-01-01 UTC 1039384002 seconds' +%c
- // use sys_timeBase 0x3dc7b5e9+0x2c0056 = 0x3df3b63f
- // after around 5s, xtime would have wrapped around
- // we get 7132, the formula handles the wrap safely
- unsigned long xtime_aux,base_aux;
- int test;
- // Com_Printf("sys_timeBase: %p\n", sys_timeBase);
- // Com_Printf("xtime: %p\n", xtime);
- xtime_aux = 500; // 500 ms after wrap
- base_aux = 0x3df3b63f; // the base a few seconds before wrap
- test = xtime_aux - (unsigned long)(base_aux*1000);
- Com_Printf("xtime wrap test: %d\n", test);
- #endif
- // some X servers (like suse 8.1's) report weird event times
- // if the game is loading, resolving DNS, etc. we are also getting old events
- // so we only deal with subframe corrections that look 'normal'
- ret = xtime - (unsigned long)(sys_timeBase*1000);
- time = Sys_Milliseconds();
- test = time - ret;
- //printf("delta: %d\n", test);
- if (test < 0 || test > 30) // in normal conditions I've never seen this go above
- {
- return time;
- }
- return ret;
- }
- #endif
- //#if 0 // bk001215 - see snapvector.nasm for replacement
- #if (defined __APPLE__) // rcg010206 - using this for PPC builds...
- long fastftol( float f ) { // bk001213 - from win32/win_shared.c
- //static int tmp;
- // __asm fld f
- //__asm fistp tmp
- //__asm mov eax, tmp
- return (long)f;
- }
- void Sys_SnapVector( float *v ) { // bk001213 - see win32/win_shared.c
- // bk001213 - old linux
- v[0] = rint(v[0]);
- v[1] = rint(v[1]);
- v[2] = rint(v[2]);
- }
- #endif
- void Sys_Mkdir( const char *path )
- {
- mkdir (path, 0777);
- }
- char *strlwr (char *s) {
- if ( s==NULL ) { // bk001204 - paranoia
- assert(0);
- return s;
- }
- while (*s) {
- *s = tolower(*s);
- s++;
- }
- return s; // bk001204 - duh
- }
- //============================================
- #define MAX_FOUND_FILES 0x1000
- // bk001129 - new in 1.26
- void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) {
- char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
- char filename[MAX_OSPATH];
- DIR *fdir;
- struct dirent *d;
- struct stat st;
- if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
- return;
- }
- if (strlen(subdirs)) {
- Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs );
- }
- else {
- Com_sprintf( search, sizeof(search), "%s", basedir );
- }
- if ((fdir = opendir(search)) == NULL) {
- return;
- }
- while ((d = readdir(fdir)) != NULL) {
- Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
- if (stat(filename, &st) == -1)
- continue;
- if (st.st_mode & S_IFDIR) {
- if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) {
- if (strlen(subdirs)) {
- Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
- }
- else {
- Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
- }
- Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
- }
- }
- if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
- break;
- }
- Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name );
- if (!Com_FilterPath( filter, filename, qfalse ))
- continue;
- list[ *numfiles ] = CopyString( filename );
- (*numfiles)++;
- }
- closedir(fdir);
- }
- // bk001129 - in 1.17 this used to be
- // char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs )
- char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs )
- {
- struct dirent *d;
- // char *p; // bk001204 - unused
- DIR *fdir;
- qboolean dironly = wantsubs;
- char search[MAX_OSPATH];
- int nfiles;
- char **listCopy;
- char *list[MAX_FOUND_FILES];
- //int flag; // bk001204 - unused
- int i;
- struct stat st;
- int extLen;
- if (filter) {
- nfiles = 0;
- Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
- list[ nfiles ] = 0;
- *numfiles = nfiles;
- if (!nfiles)
- return NULL;
- listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
- for ( i = 0 ; i < nfiles ; i++ ) {
- listCopy[i] = list[i];
- }
- listCopy[i] = NULL;
- return listCopy;
- }
- if ( !extension)
- extension = "";
- if ( extension[0] == '/' && extension[1] == 0 ) {
- extension = "";
- dironly = qtrue;
- }
- extLen = strlen( extension );
-
- // search
- nfiles = 0;
- if ((fdir = opendir(directory)) == NULL) {
- *numfiles = 0;
- return NULL;
- }
- while ((d = readdir(fdir)) != NULL) {
- Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
- if (stat(search, &st) == -1)
- continue;
- if ((dironly && !(st.st_mode & S_IFDIR)) ||
- (!dironly && (st.st_mode & S_IFDIR)))
- continue;
- if (*extension) {
- if ( strlen( d->d_name ) < strlen( extension ) ||
- Q_stricmp(
- d->d_name + strlen( d->d_name ) - strlen( extension ),
- extension ) ) {
- continue; // didn't match
- }
- }
- if ( nfiles == MAX_FOUND_FILES - 1 )
- break;
- list[ nfiles ] = CopyString( d->d_name );
- nfiles++;
- }
- list[ nfiles ] = 0;
- closedir(fdir);
- // return a copy of the list
- *numfiles = nfiles;
- if ( !nfiles ) {
- return NULL;
- }
- listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
- for ( i = 0 ; i < nfiles ; i++ ) {
- listCopy[i] = list[i];
- }
- listCopy[i] = NULL;
- return listCopy;
- }
- void Sys_FreeFileList( char **list ) {
- int i;
- if ( !list ) {
- return;
- }
- for ( i = 0 ; list[i] ; i++ ) {
- Z_Free( list[i] );
- }
- Z_Free( list );
- }
- char *Sys_Cwd( void )
- {
- static char cwd[MAX_OSPATH];
- getcwd( cwd, sizeof( cwd ) - 1 );
- cwd[MAX_OSPATH-1] = 0;
- return cwd;
- }
- void Sys_SetDefaultCDPath(const char *path)
- {
- Q_strncpyz(cdPath, path, sizeof(cdPath));
- }
- char *Sys_DefaultCDPath(void)
- {
- return cdPath;
- }
- void Sys_SetDefaultInstallPath(const char *path)
- {
- Q_strncpyz(installPath, path, sizeof(installPath));
- }
- char *Sys_DefaultInstallPath(void)
- {
- if (*installPath)
- return installPath;
- else
- return Sys_Cwd();
- }
- void Sys_SetDefaultHomePath(const char *path)
- {
- Q_strncpyz(homePath, path, sizeof(homePath));
- }
- char *Sys_DefaultHomePath(void)
- {
- char *p;
- if (*homePath)
- return homePath;
-
- if ((p = getenv("HOME")) != NULL) {
- Q_strncpyz(homePath, p, sizeof(homePath));
- #ifdef MACOS_X
- Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/Quake3");
- #else
- Q_strcat(homePath, sizeof(homePath), "/.q3a");
- #endif
- if (mkdir(homePath, 0777)) {
- if (errno != EEXIST)
- Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", homePath, strerror(errno), errno);
- }
- return homePath;
- }
- return ""; // assume current dir
- }
- //============================================
- int Sys_GetProcessorId( void )
- {
- return CPUID_GENERIC;
- }
- void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
- {
- }
- char *Sys_GetCurrentUser( void )
- {
- struct passwd *p;
- if ( (p = getpwuid( getuid() )) == NULL ) {
- return "player";
- }
- return p->pw_name;
- }
- #if defined(__linux__)
- // TTimo
- // sysconf() in libc, POSIX.1 compliant
- unsigned int Sys_ProcessorCount()
- {
- return sysconf(_SC_NPROCESSORS_ONLN);
- }
- #endif
|