2# ifndef DONT_USE_SETDLLDIRECTORY
3# define _WIN32_WINNT 0x0502
16#pragma comment(lib, "winmm.lib")
20# include <sys/sysctl.h>
23# include <android/log.h>
51 localtime_s(&mytm, &mytime);
69 extern void monstartup(
const char *libname);
70 extern void moncleanup(
void);
72 monstartup(
"libmain.so");
76#elif (defined(__linux__) && (defined(__GLIBC__) || defined(__GNU_LIBRARY__))) || defined(__FreeBSD__)
77 extern int moncontrol(
int);
96 for (func = fcts; func && func->
name !=
NULL; func++)
101 Con_DPrintf (
" - missing function \"%s\" - broken library!", func->
name);
110 for (func = fcts; func && func->
name !=
NULL; func++)
123 dllhandle = LoadLibrary (
NULL);
125 dllhandle = dlopen (
NULL, RTLD_NOW | RTLD_GLOBAL);
143 dllhandle = dlopen(
NULL, RTLD_LAZY | RTLD_GLOBAL);
146 Con_DPrintf (
"All of %s's functions were already linked in! Not loading dynamically...\n", dllnames[0]);
157 for (func = fcts; func && func->
name !=
NULL; func++)
162 for (
i = 0; dllnames[
i] !=
NULL;
i++)
166# ifndef DONT_USE_SETDLLDIRECTORY
168 SetDllDirectory(
"bin64");
170 SetDllDirectory(
"bin32");
185 if (!dllhandle && strrchr(
sys.
argv[0],
'/'))
189 strrchr(path,
'/')[1] = 0;
190 for (
i = 0; dllnames[
i] !=
NULL;
i++)
215 Con_Printf(
"Loaded library \"%s\"\n", dllnames[
i]);
233 dllhandle = LoadLibrary (
name);
235 dllhandle = dlopen (
name, RTLD_LAZY | RTLD_GLOBAL);
248 if (handle ==
NULL || *handle ==
NULL)
252 FreeLibrary (*handle);
265 return (
void *)GetProcAddress (handle,
name);
267 return (
void *)dlsym (handle,
name);
277# define HAVE_TIMEGETTIME 1
278# define HAVE_QUERYPERFORMANCECOUNTER 1
279# define HAVE_WIN32_USLEEP 1
282# if defined(CLOCK_MONOTONIC) || defined(CLOCK_HIRES)
283# define HAVE_CLOCKGETTIME 1
285# if _POSIX_VERSION >= 200112L
289# define HAVE_SELECT_POSIX 1
291# define HAVE_CLOCK_NANOSLEEP 1
297# define HAVE_SELECT 1
301cvar_t sys_usenoclockbutbenchmark = {
CF_SHARED,
"sys_usenoclockbutbenchmark",
"0",
"don't use ANY real timing, and simulate a clock (for benchmarking); the game then runs as fast as possible. Run a QC mod with bots that does some stuff, then does a quit at the end, to benchmark a server. NEVER do this on a public server."};
308#if HAVE_QUERYPERFORMANCECOUNTER
309static cvar_t sys_usequeryperformancecounter = {
CF_SHARED |
CF_ARCHIVE,
"sys_usequeryperformancecounter",
"1",
"use windows QueryPerformanceCounter timer (which has issues on systems lacking constant-rate TSCs synchronised across all cores, such as ancient PCs or VMs) for timing rather than timeGetTime function (which is low precision and had issues on some old motherboards)"};
312static cvar_t sys_stdout = {
CF_SHARED,
"sys_stdout",
"1",
"0: nothing is written to stdout (-nostdout cmdline option sets this), 1: normal messages are written to stdout, 2: normal messages are written to stderr (-stderr cmdline option sets this)"};
314static cvar_t sys_stdout_blocks = {
CF_SHARED,
"sys_stdout_blocks",
"0",
"1: writes to stdout and stderr streams will block (causing a stutter or complete halt) if the buffer is full, ensuring no messages are lost at a price"};
348 case 1:
sys.
outfd = fileno(stdout);
break;
349 case 2:
sys.
outfd = fileno(stderr);
break;
358#if HAVE_TIMEGETTIME || HAVE_QUERYPERFORMANCECOUNTER || HAVE_CLOCKGETTIME
365#if HAVE_QUERYPERFORMANCECOUNTER
377static LARGE_INTEGER PerformanceFreq;
380static void Sys_SetTimerResolution(
void)
382 NTSTATUS(NTAPI *qNtQueryTimerResolution)(OUT PULONG MinRes, OUT PULONG MaxRes, OUT PULONG CurrentRes);
383 NTSTATUS(NTAPI *qNtSetTimerResolution)(IN ULONG DesiredRes, IN BOOLEAN SetRes, OUT PULONG ActualRes);
384 const char* ntdll_names [] =
391 {
"NtQueryTimerResolution", (
void **) &qNtQueryTimerResolution},
392 {
"NtSetTimerResolution", (
void **) &qNtSetTimerResolution},
396 unsigned long WorstRes, BestRes, CurrentRes;
404 qNtQueryTimerResolution(&WorstRes, &BestRes, &CurrentRes);
405 if (CurrentRes > BestRes)
406 qNtSetTimerResolution(BestRes,
true, &CurrentRes);
413 QueryPerformanceFrequency (&PerformanceFreq);
427 Sys_Error(
"sys_usenoclockbutbenchmark cannot run any longer, sorry");
434#if HAVE_QUERYPERFORMANCECOUNTER
435 if (sys_usequeryperformancecounter.
integer)
447 LARGE_INTEGER PerformanceCount;
449 if (PerformanceFreq.QuadPart)
451 QueryPerformanceCounter (&PerformanceCount);
452 return (
double)PerformanceCount.QuadPart * (1.0 / (double)PerformanceFreq.QuadPart);
466# ifdef CLOCK_MONOTONIC_RAW
468 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
469# elif defined(CLOCK_MONOTONIC)
471 clock_gettime(CLOCK_MONOTONIC, &ts);
474 clock_gettime(CLOCK_HIGHRES, &ts);
476 return (
double) ts.tv_sec + ts.tv_nsec / 1000000000.0;
491 return (
double) timeGetTime() / 1000.0;
503 uint32_t msec, usec, nsec;
510 usec =
time * 1000000;
511 nsec =
time * 1000000000;
518 Sys_Error(
"sys_usenoclockbutbenchmark cannot run any longer, sorry");
523 Con_Printf(
"sys_debugsleep: requested %u, ", usec);
546 if (lastfd < s->inetsocket)
547 lastfd = s->inetsocket;
548 #if defined(WIN32) && !defined(_MSC_VER)
549 FD_SET((
int)s->inetsocket, &fdreadset);
551 FD_SET((
unsigned int)s->inetsocket, &fdreadset);
559 select(lastfd + 1, &fdreadset,
NULL,
NULL, &tv);
562#if HAVE_CLOCK_NANOSLEEP
568 clock_nanosleep(CLOCK_MONOTONIC, 0, &ts,
NULL);
570#elif HAVE_SELECT_POSIX
578#elif HAVE_WIN32_USLEEP
582 LARGE_INTEGER sleeptime;
585 sleeptime.QuadPart = -((int64_t)nsec / 100);
586 timer = CreateWaitableTimer(
NULL,
true,
NULL);
587 SetWaitableTimer(timer, &sleeptime, 0,
NULL,
NULL, 0);
588 WaitForSingleObject(timer, INFINITE);
601 Con_Printf(
"got %u, oversleep %d\n", (uint32_t)(dt * 1000000), (uint32_t)(dt * 1000000) - usec);
602 return (dt < 0 || dt >= 1800) ? 0 : dt;
620 __android_log_write(ANDROID_LOG_DEBUG,
sys.
argv[0], text);
629 int origflags = fcntl(
sys.
outfd, F_GETFL, 0);
635 while(*text && textlen)
645 fcntl(
sys.
outfd, F_SETFL, origflags);
658 va_start(argptr,fmt);
659 msglen =
dpvsnprintf(msg,
sizeof(msg), fmt, argptr);
671 static unsigned int len = 0;
696 if (len <
sizeof (text) - 1)
705 struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
708 FD_SET(fileno(stdin), &fdset);
709 if (select(1, &fdset,
NULL,
NULL, &timeout) != -1 && FD_ISSET(fileno(stdin), &fdset))
710 return fgets(text,
sizeof(text), stdin);
739 va_start (argptr,
error);
773static const char *
Sys_FindInPATH(
const char *
name,
char namesep,
const char *PATH,
char pathsep,
char *
buf,
size_t bufsize)
775 const char *p = PATH;
779 while((q = strchr(p,
':')))
804#if defined(__FreeBSD__)
805 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
806 size_t exenamebuflen =
sizeof(exenamebuf)-1;
807 if (sysctl(mib, 4, exenamebuf, &exenamebuflen,
NULL, 0) == 0)
811#elif defined(__linux__)
812 n = readlink(
"/proc/self/exe", exenamebuf,
sizeof(exenamebuf)-1);
814 if(
n > 0 && (
size_t)(
n) <
sizeof(exenamebuf))
834#if defined(SSE_POSSIBLE) && !defined(SSE2_PRESENT)
836static int CPUID_Features(
void)
839# if (defined(__GNUC__) || defined(__clang__) || defined(__TINYC__)) && defined(__i386__)
842" xorl %%eax,%%eax \n"
844" cpuid # Get family/model/stepping/features\n"
849 :
"%eax",
"%ecx",
"%edx",
"%edi"
851# elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
855 cpuid ; Get family/
model/stepping/features
859# error SSE_POSSIBLE set but no CPUID implementation
877 if(CPUID_Features() & (1 << 25))
894 if((CPUID_Features() & (3 << 25)) == (3 << 25))
902#if defined(__linux__)
903#include <sys/resource.h>
916 Con_Printf(
"Kernel does not support reading process priority - cannot use niceness\n");
919 if(getrlimit(RLIMIT_NICE, &lim))
921 Con_Printf(
"Kernel does not support lowering nice level again - cannot use niceness\n");
924 if(lim.rlim_cur != RLIM_INFINITY &&
sys.
nicelevel < (
int) (20 - lim.rlim_cur))
926 Con_Printf(
"Current nice level is below the soft limit - cannot use niceness\n");
939 if(setpriority(PRIO_PROCESS, 0, 19))
972 case SIGINT:
return "Interrupt";
973 case SIGILL:
return "Illegal instruction";
974 case SIGABRT:
return "Aborted";
975 case SIGFPE:
return "Floating point exception";
976 case SIGSEGV:
return "Segmentation fault";
977 case SIGTERM:
return "Termination";
980 case SIGHUP:
return "Hangup";
981 case SIGQUIT:
return "Quit";
982 case SIGBUS:
return "Bus error (bad memory access)";
983 case SIGPIPE:
return "Broken pipe";
985 default:
return "Yo dawg, we bugged out while bugging out";
996#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
998 #include <execinfo.h>
999 void *stackframes[32];
1000 int framecount = backtrace(stackframes, 32);
1003 char dialogtext[3072];
1004 const char *sigdesc;
1017 Sys_Print(
"\n\n\x1B[1;37;41m Engine Crash: ", 30);
1020 #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
1022 backtrace_symbols_fd(stackframes + 2, framecount - 2,
sys.
outfd);
1043 dp_strlcpy(dialogtext, sigdesc,
sizeof(dialogtext));
1044 dp_strlcat(dialogtext,
"\n\n",
sizeof(dialogtext));
1045#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
1046 btstrings = backtrace_symbols(stackframes + 2, framecount - 2);
1048 for (
int i = 0;
i < framecount - 2; ++
i)
1050 dp_strlcat(dialogtext, btstrings[
i],
sizeof(dialogtext));
1051 dp_strlcat(dialogtext,
"\n",
sizeof(dialogtext));
1054 dp_strlcat(dialogtext,
"\n",
sizeof(dialogtext));
1065 signal(sig, SIG_DFL);
1070 const char *sigdesc;
1111 double time = newtime - oldtime;
1117 Con_Printf(
CON_WARN "Host_UpdateTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime,
time);
1120 else if (
time >= 1800)
1122 Con_Printf(
CON_WARN "Host_UpdateTime: time stepped forward (went from %f to %f, difference %f)\n", oldtime, newtime,
time);
1129#ifdef __EMSCRIPTEN__
1130 #include <emscripten.h>
1135 double time, newtime, sleeptime;
1136#ifdef __EMSCRIPTEN__
1137 static double sleepstarttime = 0;
1146#ifdef __EMSCRIPTEN__
1147 emscripten_cancel_main_loop();
1163#ifdef __EMSCRIPTEN__
1167 emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT,
host.
restless ? 0 : sleeptime * 1000.0);
1194 fcntl(fileno(stdin), F_SETFL, fcntl(fileno(stdin), F_GETFL, 0) |
O_NONBLOCK);
1196 fcntl(fileno(stdout), F_SETFL, fcntl(fileno(stdout), F_GETFL, 0) |
O_NONBLOCK);
1197 fcntl(fileno(stderr), F_SETFL, fcntl(fileno(stderr), F_GETFL, 0) |
O_NONBLOCK);
1210 Sys_SetTimerResolution();
1214#ifdef __EMSCRIPTEN__
1215 emscripten_set_main_loop(
Sys_Frame, 0,
true);
void CL_Stop_f(cmd_state_t *cmd)
cmd_state_t * cmd_local
command interpreter for local commands injected by SVQC, CSQC, MQC, server or client engine code uses...
#define CF_READONLY
cvar cannot be changed from the console or the command buffer, and is considered CF_PERSISTENT
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
#define List_For_Each_Entry(pos, head, type, member)
int dpvsnprintf(char *buffer, size_t buffersize, const char *format, va_list args)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
#define dp_strlcat(dst, src, dsize)
#define dp_strlcpy(dst, src, dsize)
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
void Cvar_SetValueQuick(cvar_t *var, float value)
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
void Cvar_RegisterCallback(cvar_t *variable, void(*callback)(cvar_t *))
char engineversion[128]
version string for the corner of the console, crash messages, status command, etc
int FS_SysOpenFD(const char *filepath, const char *mode, qbool nonblocking)
qbool FS_SysFileExists(const char *path)
Look for a file in the filesystem only.
GLenum GLuint GLenum GLsizei const GLchar * buf
double Host_Frame(double time)
@ host_failed
crashed or aborted, SDL dialog open
@ host_failing
crashing (inside crash handler)
@ host_shutdown
states >= host_shutdown cause graceful shutdown, see Sys_HandleCrash() comments
lhnetsocket_t lhnet_socketlist
bool Curl_Select(int timeout_ms)
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
#define MAX_OSPATH
max length of a filesystem pathname
void SV_DropClient(qbool leaving, const char *reason,...)
server_static_t svs
persistant server info
cvar_t sv_checkforpacketsduringsleep
void S_StopAllSounds(void)
qbool active
false = empty client slot
double sleeptime
time spent sleeping after the last frame
qbool restless
don't sleep
double dirtytime
the main loop wall time for this frame, equal to Sys_DirtyTime() at the start of this host frame
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
struct client_s * clients
client slots
int maxclients
number of svs.clients slots (updated by maxplayers command)
qbool active
false if only a net client
unsigned int Sys_SDL_GetTicks(void)
void Sys_SDL_Dialog(const char *title, const char *string)
void Sys_SDL_Delay(unsigned int milliseconds)
qbool sys_supportsdlgetticks
static const char * Sys_FindExecutableName(void)
static cvar_t sys_usesdldelay
static cvar_t sys_usesdlgetticks
size_t Sys_TimeString(char buf[], size_t bufsize, const char *timeformat)
static cvar_t sys_stdout_blocks
static const char * Sys_SigDesc(int sig)
void Sys_Print(const char *text, size_t textlen)
(may) output text to terminal which launched program is POSIX async-signal-safe textlen excludes any ...
void Sys_InitProcessNice(void)
called to set process priority for dedicated servers
void Sys_Printf(const char *fmt,...)
used to report failures inside Con_Printf()
void Sys_Error(const char *error,...)
Causes the entire program to exit ASAP.
void * Sys_GetProcAddress(dllhandle_t handle, const char *name)
static double benchmark_time
static const char * Sys_FindInPATH(const char *name, char namesep, const char *PATH, char pathsep, char *buf, size_t bufsize)
char * Sys_ConsoleInput(void)
Reads a line from POSIX stdin or the Windows console.
void Sys_MakeProcessNice(void)
qbool Sys_LoadLibrary(const char *name, dllhandle_t *handle)
void Sys_AllowProfiling(qbool enable)
static void Sys_UpdateOutFD_c(cvar_t *var)
qbool Sys_LoadDependency(const char **dllnames, dllhandle_t *handle, const dllfunction_t *fcts)
int Sys_Main(int argc, char *argv[])
main() but renamed so we can wrap it in sys_sdl.c and sys_null.c to avoid needing to include SDL....
static void Sys_InitSignals(void)
SDL2 only handles SIGINT and SIGTERM by default and doesn't log anything.
static qbool Sys_LoadDependencyFunctions(dllhandle_t dllhandle, const dllfunction_t *fcts, qbool complain, qbool has_next)
double Sys_DirtyTime(void)
void Sys_ProvideSelfFD(void)
void Sys_MakeProcessMean(void)
double Sys_Sleep(double time)
called to yield for a little bit so as not to hog cpu when paused or debugging
static void Sys_Frame(void)
JS+WebGL doesn't support a main loop, only a function called to run a frame.
static double Sys_UpdateTime(double newtime, double oldtime)
void Sys_Init_Commands(void)
called after command system is initialized but before first Con_Print
static cvar_t sys_debugsleep
cvar_t sys_usenoclockbutbenchmark
void Sys_FreeLibrary(dllhandle_t *handle)
int Sys_CheckParm(const char *parm)
static void Sys_HandleCrash(int sig)
Halt and try not to catch fire.
static void Sys_HandleSignal(int sig)
qbool Sys_LoadSelf(dllhandle_t *handle)
void VID_Shutdown(void)
Called at shutdown.