Cleanup the system specific code.

* Remove a bunch of unnecessary functions.
* Reorder functions into logical groups. The orderig is now the same
  on Unix and Windows.

While at it add several TODOs to the code. There's not need for special
library loading functions for the game, the Windows backend still uses
a lot of old and fishy DOS functions, etc. All this will be done at a
later time.
This commit is contained in:
Yamagi Burmeister 2018-02-04 10:46:44 +01:00
parent acb50c6907
commit 2096d57eb8
3 changed files with 363 additions and 406 deletions

View file

@ -19,32 +19,21 @@
*
* =======================================================================
*
* This file implements all system dependend generic funktions
* This file implements all system dependent generic functions.
*
* =======================================================================
*/
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <errno.h>
#include <dlfcn.h>
#include <dirent.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#ifdef __APPLE__
#include <mach/clock.h>
@ -55,27 +44,67 @@
#include "../../common/header/glob.h"
#include "../generic/header/input.h"
unsigned sys_frame_time;
// Pointer to game library
static void *game_library;
// File searching
static char findbase[MAX_OSPATH];
static char findpath[MAX_OSPATH];
static char findpattern[MAX_OSPATH];
static DIR *fdir;
// Evil hack to determine if stdin is available
qboolean stdin_active = true;
// Console logfile
extern FILE *logfile;
static qboolean
CompareAttributes(char *path, char *name, unsigned musthave, unsigned canthave)
// TODO
unsigned sys_frame_time;
/* ================================================================ */
void
Sys_Error(char *error, ...)
{
/* . and .. never match */
if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
va_list argptr;
char string[1024];
/* change stdin to non blocking */
fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~FNDELAY);
#ifndef DEDICATED_ONLY
CL_Shutdown();
#endif
Qcommon_Shutdown();
va_start(argptr, error);
vsnprintf(string, 1024, error, argptr);
va_end(argptr);
fprintf(stderr, "Error: %s\n", string);
exit(1);
}
void
Sys_Quit(void)
{
#ifndef DEDICATED_ONLY
CL_Shutdown();
#endif
if (logfile)
{
return false;
fclose(logfile);
logfile = NULL;
}
return true;
Qcommon_Shutdown();
fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~FNDELAY);
printf("------------------------------------\n");
exit(0);
}
void
@ -83,6 +112,62 @@ Sys_Init(void)
{
}
/* ================================================================ */
char *
Sys_ConsoleInput(void)
{
static char text[256];
int len;
fd_set fdset;
struct timeval timeout;
if (!dedicated || !dedicated->value)
{
return NULL;
}
if (!stdin_active)
{
return NULL;
}
FD_ZERO(&fdset);
FD_SET(0, &fdset); /* stdin */
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if ((select(1, &fdset, NULL, NULL, &timeout) == -1) || !FD_ISSET(0, &fdset))
{
return NULL;
}
len = read(0, text, sizeof(text));
if (len == 0) /* eof! */
{
stdin_active = false;
return NULL;
}
if (len < 1)
{
return NULL;
}
text[len - 1] = 0; /* rip off the /n and terminate */
return text;
}
void
Sys_ConsoleOutput(char *string)
{
fputs(string, stdout);
}
/* ================================================================ */
long long
Sys_Microseconds(void)
{
@ -102,11 +187,11 @@ Sys_Microseconds(void)
struct timespec now;
static struct timespec first;
#ifdef _POSIX_MONOTONIC_CLOCK
#ifdef _POSIX_MONOTONIC_CLOCK
clock_gettime(CLOCK_MONOTONIC, &now);
#else
#else
clock_gettime(CLOCK_REALTIME, &now);
#endif
#endif
#endif // not __APPLE__
@ -146,22 +231,24 @@ Sys_Milliseconds(void)
}
void
Sys_Mkdir(char *path)
Sys_Nanosleep(int nanosec)
{
mkdir(path, 0755);
struct timespec t = {0, nanosec};
nanosleep(&t, NULL);
}
char *
Sys_GetCurrentDirectory(void)
{
static char dir[MAX_OSPATH];
/* ================================================================ */
if (!getcwd(dir, sizeof(dir)))
static qboolean
CompareAttributes(char *path, char *name, unsigned musthave, unsigned canthave)
{
/* . and .. never match */
if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
{
Sys_Error("Couldn't get current working directory");
return false;
}
return dir;
return true;
}
char *
@ -248,148 +335,9 @@ Sys_FindClose(void)
fdir = NULL;
}
void
Sys_ConsoleOutput(char *string)
{
fputs(string, stdout);
}
/* ================================================================ */
void
Sys_Printf(char *fmt, ...)
{
va_list argptr;
char text[1024];
unsigned char *p;
va_start(argptr, fmt);
vsnprintf(text, 1024, fmt, argptr);
va_end(argptr);
for (p = (unsigned char *)text; *p; p++)
{
*p &= 0x7f;
if (((*p > 128) || (*p < 32)) && (*p != 10) && (*p != 13) && (*p != 9))
{
printf("[%02x]", *p);
}
else
{
putc(*p, stdout);
}
}
}
void
Sys_Quit(void)
{
#ifndef DEDICATED_ONLY
CL_Shutdown();
#endif
if (logfile)
{
fclose(logfile);
logfile = NULL;
}
Qcommon_Shutdown();
fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~FNDELAY);
printf("------------------------------------\n");
exit(0);
}
void
Sys_Error(char *error, ...)
{
va_list argptr;
char string[1024];
/* change stdin to non blocking */
fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~FNDELAY);
#ifndef DEDICATED_ONLY
CL_Shutdown();
#endif
Qcommon_Shutdown();
va_start(argptr, error);
vsnprintf(string, 1024, error, argptr);
va_end(argptr);
fprintf(stderr, "Error: %s\n", string);
exit(1);
}
/*
* returns -1 if not present
*/
int
Sys_FileTime(char *path)
{
struct stat buf;
if (stat(path, &buf) == -1)
{
return -1;
}
return buf.st_mtime;
}
void
floating_point_exception_handler(int whatever)
{
signal(SIGFPE, floating_point_exception_handler);
}
char *
Sys_ConsoleInput(void)
{
static char text[256];
int len;
fd_set fdset;
struct timeval timeout;
if (!dedicated || !dedicated->value)
{
return NULL;
}
if (!stdin_active)
{
return NULL;
}
FD_ZERO(&fdset);
FD_SET(0, &fdset); /* stdin */
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if ((select(1, &fdset, NULL, NULL, &timeout) == -1) || !FD_ISSET(0, &fdset))
{
return NULL;
}
len = read(0, text, sizeof(text));
if (len == 0) /* eof! */
{
stdin_active = false;
return NULL;
}
if (len < 1)
{
return NULL;
}
text[len - 1] = 0; /* rip off the /n and terminate */
return text;
}
// TODO: Unnecessary, use generic functions instead.
void
Sys_UnloadGame(void)
@ -402,9 +350,6 @@ Sys_UnloadGame(void)
game_library = NULL;
}
/*
* Loads the game dll
*/
void *
Sys_GetGameAPI(void *parms)
{
@ -413,11 +358,11 @@ Sys_GetGameAPI(void *parms)
char name[MAX_OSPATH];
char *path;
char *str_p;
#ifdef __APPLE__
const char *gamename = "game.dylib";
#else
const char *gamename = "game.so";
#endif
#ifdef __APPLE__
const char *gamename = "game.dylib";
#else
const char *gamename = "game.so";
#endif
setreuid(getuid(), getuid());
setegid(getgid());
@ -495,17 +440,15 @@ Sys_GetGameAPI(void *parms)
return GetGameAPI(parms);
}
void
Sys_SendKeyEvents(void)
{
#ifndef DEDICATED_ONLY
IN_Update();
#endif
/* ================================================================ */
/* grab frame time */
sys_frame_time = Sys_Milliseconds();
void
Sys_Mkdir(char *path)
{
mkdir(path, 0755);
}
char *
Sys_GetHomeDir(void)
{
@ -524,6 +467,8 @@ Sys_GetHomeDir(void)
return gdir;
}
/* ================================================================ */
void *
Sys_GetProcAddress(void *handle, const char *sym)
{
@ -544,6 +489,15 @@ Sys_GetProcAddress(void *handle, const char *sym)
return dlsym(handle, sym);
}
void
Sys_FreeLibrary(void *handle)
{
if (handle && dlclose(handle))
{
Com_Error(ERR_FATAL, "dlclose failed on %p: %s", handle, dlerror());
}
}
void *
Sys_LoadLibrary(const char *path, const char *sym, void **handle)
{
@ -582,28 +536,17 @@ Sys_LoadLibrary(const char *path, const char *sym, void **handle)
return entry;
}
void
Sys_FreeLibrary(void *handle)
{
if (handle && dlclose(handle))
{
Com_Error(ERR_FATAL, "dlclose failed on %p: %s", handle, dlerror());
}
}
/* ================================================================ */
/*
* Just a dummy. There's no need on unixoid systems to
* redirect stdout and stderr.
*/
void
Sys_RedirectStdout(void)
{
return;
}
// TODO: Remove.
void
Sys_Nanosleep(int nanosec)
Sys_SendKeyEvents(void)
{
struct timespec t = {0, nanosec};
nanosleep(&t, NULL);
#ifndef DEDICATED_ONLY
IN_Update();
#endif
/* grab frame time */
sys_frame_time = Sys_Milliseconds();
}

View file

@ -19,42 +19,43 @@
*
* =======================================================================
*
* This file is the starting point of the program and implements
* several support functions and the main loop.
* This file implements all system dependent generic functions.
*
* =======================================================================
*/
#include <conio.h>
#include <direct.h>
#include <errno.h>
#include <float.h>
#include <fcntl.h>
#include <stdio.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
#include <shlobj.h>
#include <stdio.h>
#include <windows.h>
#include "../../common/header/common.h"
#include "../generic/header/input.h"
#include "header/resource.h"
int starttime;
// stdin and stdout handles
static HANDLE hinput, houtput;
// Game library handle
static HINSTANCE game_library;
unsigned int sys_frame_time;
// Buffer for the dedicated server console
static char console_text[256];
static int console_textlen;
static size_t console_textlen;
// File searching
char findbase[MAX_OSPATH];
char findpath[MAX_OSPATH];
int findhandle;
// TODO
qboolean is_portable;
unsigned int sys_frame_time;
/* ================================================================ */
@ -108,11 +109,11 @@ Sys_Quit(void)
fclose(stderr);
#endif
printf("------------------------------------\n");
exit(0);
}
/* ================================================================ */
void
Sys_Init(void)
{
@ -131,8 +132,8 @@ Sys_Init(void)
above. Testing older version would be a
PITA. */
if (!((vinfo.dwMajorVersion > 5) ||
((vinfo.dwMajorVersion == 5) &&
(vinfo.dwMinorVersion >= 1))))
((vinfo.dwMajorVersion == 5) &&
(vinfo.dwMinorVersion >= 1))))
{
Sys_Error("Yamagi Quake II needs Windows XP or higher!\n");
}
@ -147,6 +148,8 @@ Sys_Init(void)
}
}
/* ================================================================ */
char *
Sys_ConsoleInput(void)
{
@ -262,88 +265,8 @@ Sys_ConsoleOutput(char *string)
}
}
void
Sys_SendKeyEvents(void)
{
#ifndef DEDICATED_ONLY
IN_Update();
#endif
/* grab frame time */
sys_frame_time = timeGetTime();
}
/* ================================================================ */
void
Sys_UnloadGame(void)
{
if (!FreeLibrary(game_library))
{
Com_Error(ERR_FATAL, "FreeLibrary failed for game library");
}
game_library = NULL;
}
void *
Sys_GetGameAPI(void *parms)
{
void *(*GetGameAPI)(void *);
char name[MAX_OSPATH];
char *path = NULL;
if (game_library)
{
Com_Error(ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
}
/* now run through the search paths */
path = NULL;
while (1)
{
path = FS_NextPath(path);
if (!path)
{
return NULL; /* couldn't find one anywhere */
}
/* Try game.dll */
Com_sprintf(name, sizeof(name), "%s/%s", path, "game.dll");
game_library = LoadLibrary(name);
if (game_library)
{
Com_DPrintf("LoadLibrary (%s)\n", name);
break;
}
/* Try gamex86.dll as fallback */
Com_sprintf(name, sizeof(name), "%s/%s", path, "gamex86.dll");
game_library = LoadLibrary(name);
if (game_library)
{
Com_DPrintf("LoadLibrary (%s)\n", name);
break;
}
}
GetGameAPI = (void *)GetProcAddress(game_library, "GetGameAPI");
if (!GetGameAPI)
{
Sys_UnloadGame();
return NULL;
}
return GetGameAPI(parms);
}
/* ======================================================================= */
long long
Sys_Microseconds(void)
{
@ -378,12 +301,6 @@ Sys_Milliseconds(void)
return (int)(Sys_Microseconds()/1000ll);
}
void
Sys_Sleep(int msec)
{
Sleep(msec);
}
void Sys_Nanosleep(int nanosec)
{
HANDLE timer;
@ -400,8 +317,10 @@ void Sys_Nanosleep(int nanosec)
CloseHandle(timer);
}
/* ======================================================================= */
/* ================================================================ */
// TODO: Still uses broken DOS functions.
// Have a look at FindFirstFile(), FindNextFile() and FindClose().
static qboolean
CompareAttributes(unsigned found, unsigned musthave, unsigned canthave)
{
@ -522,25 +441,86 @@ Sys_FindClose(void)
findhandle = 0;
}
/* ================================================================ */
// TODO: Unnecessary, use generic functions instead.
void
Sys_UnloadGame(void)
{
if (!FreeLibrary(game_library))
{
Com_Error(ERR_FATAL, "FreeLibrary failed for game library");
}
game_library = NULL;
}
void *
Sys_GetGameAPI(void *parms)
{
void *(*GetGameAPI)(void *);
char name[MAX_OSPATH];
char *path = NULL;
if (game_library)
{
Com_Error(ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
}
/* now run through the search paths */
path = NULL;
while (1)
{
path = FS_NextPath(path);
if (!path)
{
return NULL; /* couldn't find one anywhere */
}
/* Try game.dll */
Com_sprintf(name, sizeof(name), "%s/%s", path, "game.dll");
game_library = LoadLibrary(name);
if (game_library)
{
Com_DPrintf("LoadLibrary (%s)\n", name);
break;
}
/* Try gamex86.dll as fallback */
Com_sprintf(name, sizeof(name), "%s/%s", path, "gamex86.dll");
game_library = LoadLibrary(name);
if (game_library)
{
Com_DPrintf("LoadLibrary (%s)\n", name);
break;
}
}
GetGameAPI = (void *)GetProcAddress(game_library, "GetGameAPI");
if (!GetGameAPI)
{
Sys_UnloadGame();
return NULL;
}
return GetGameAPI(parms);
}
/* ======================================================================= */
void
Sys_Mkdir(char *path)
{
// TODO: Use CreateDirectory() instead
_mkdir(path);
}
char *
Sys_GetCurrentDirectory(void)
{
static char dir[MAX_OSPATH];
if (!_getcwd(dir, sizeof(dir)))
{
Sys_Error("Couldn't get current working directory");
}
return dir;
}
char *
Sys_GetHomeDir(void)
{
@ -608,6 +588,73 @@ Sys_GetHomeDir(void)
return gdir;
}
/* ======================================================================= */
void *
Sys_GetProcAddress(void *handle, const char *sym)
{
return GetProcAddress(handle, sym);
}
void
Sys_FreeLibrary(void *handle)
{
if (!handle)
{
return;
}
if (!FreeLibrary(handle))
{
Com_Error(ERR_FATAL, "FreeLibrary failed on %p", handle);
}
}
void *
Sys_LoadLibrary(const char *path, const char *sym, void **handle)
{
HMODULE module;
void *entry;
*handle = NULL;
module = LoadLibraryA(path);
if (!module)
{
Com_Printf("%s failed: LoadLibrary returned %lu on %s\n",
__func__, GetLastError(), path);
return NULL;
}
if (sym)
{
entry = GetProcAddress(module, sym);
if (!entry)
{
Com_Printf("%s failed: GetProcAddress returned %lu on %s\n",
__func__, GetLastError(), path);
FreeLibrary(module);
return NULL;
}
}
else
{
entry = NULL;
}
*handle = module;
Com_DPrintf("%s succeeded: %s\n", __func__, path);
return entry;
}
/* ======================================================================= */
// This one is Windows specific.
void
Sys_RedirectStdout(void)
{
@ -655,6 +702,8 @@ Sys_RedirectStdout(void)
/* ======================================================================= */
// This one is windows specific.
typedef enum YQ2_PROCESS_DPI_AWARENESS {
YQ2_PROCESS_DPI_UNAWARE = 0,
YQ2_PROCESS_SYSTEM_DPI_AWARE = 1,
@ -699,64 +748,15 @@ Sys_SetHighDPIMode(void)
/* ======================================================================= */
// TODO: Remove.
void
Sys_FreeLibrary(void *handle)
Sys_SendKeyEvents(void)
{
if (!handle)
{
return;
}
#ifndef DEDICATED_ONLY
IN_Update();
#endif
if (!FreeLibrary(handle))
{
Com_Error(ERR_FATAL, "FreeLibrary failed on %p", handle);
}
/* grab frame time */
sys_frame_time = timeGetTime();
}
void *
Sys_LoadLibrary(const char *path, const char *sym, void **handle)
{
HMODULE module;
void *entry;
*handle = NULL;
module = LoadLibraryA(path);
if (!module)
{
Com_Printf("%s failed: LoadLibrary returned %lu on %s\n",
__func__, GetLastError(), path);
return NULL;
}
if (sym)
{
entry = GetProcAddress(module, sym);
if (!entry)
{
Com_Printf("%s failed: GetProcAddress returned %lu on %s\n",
__func__, GetLastError(), path);
FreeLibrary(module);
return NULL;
}
}
else
{
entry = NULL;
}
*handle = module;
Com_DPrintf("%s succeeded: %s\n", __func__, path);
return entry;
}
void *
Sys_GetProcAddress(void *handle, const char *sym)
{
return GetProcAddress(handle, sym);
}

View file

@ -755,28 +755,6 @@ extern vec3_t bytedirs[NUMVERTEXNORMALS];
/* this is in the client code, but can be used for debugging from server */
void SCR_DebugGraph(float value, int color);
void *Sys_GetGameAPI(void *parms);
/* NON-PORTABLE OSTYPE SERVICES */
void Sys_Init(void);
void Sys_UnloadGame(void);
char *Sys_ConsoleInput(void);
void Sys_ConsoleOutput(char *string);
void Sys_SendKeyEvents(void);
void Sys_Error(char *error, ...);
void Sys_Quit(void);
char *Sys_GetHomeDir(void);
const char *Sys_GetBinaryDir(void);
long long Sys_Microseconds(void);
void Sys_FreeLibrary(void *handle);
void *Sys_LoadLibrary(const char *path, const char *sym, void **handle);
void *Sys_GetProcAddress(void *handle, const char *sym);
void Sys_RedirectStdout(void);
void Sys_SetupFPU(void);
void Sys_Nanosleep(int);
/* CLIENT / SERVER SYSTEMS */
void CL_Init(void);
@ -790,4 +768,40 @@ void SV_Init(void);
void SV_Shutdown(char *finalmsg, qboolean reconnect);
void SV_Frame(int msec);
/* ======================================================================= */
// Platform specific functions.
// system.c
char *Sys_ConsoleInput(void);
void Sys_ConsoleOutput(char *string);
void Sys_Error(char *error, ...);
void Sys_Quit(void);
void Sys_Init(void);
char *Sys_GetHomeDir(void);
long long Sys_Microseconds(void);
void Sys_Nanosleep(int);
void *Sys_GetProcAddress(void *handle, const char *sym);
void Sys_FreeLibrary(void *handle);
void *Sys_LoadLibrary(const char *path, const char *sym, void **handle);
// TODO: Use generic functions instead
void *Sys_GetGameAPI(void *parms);
void Sys_UnloadGame(void);
// TODO: Remove
void Sys_SendKeyEvents(void);
// Windows only (system.c)
#ifdef _WIN32
void Sys_RedirectStdout(void);
void Sys_SetHighDPIMode(void);
#endif
// misc.c
const char *Sys_GetBinaryDir(void);
void Sys_SetupFPU(void);
/* ======================================================================= */
#endif