summaryrefslogtreecommitdiff
path: root/src/common.c
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2012-07-24 19:36:31 +0400
committerAndrey Nazarov <skuller@skuller.net>2012-07-24 20:55:04 +0400
commit0b5a71869a4fd08524ea9c2a986b4744d0913e30 (patch)
treef50eea3188d5a221a8d3e2455d6635eddec9e35a /src/common.c
parent009390601fe318af50cde0f7f3449ed65365ea29 (diff)
Rework source tree layout.
Instead of having a mix of semi-randomly prefixed .c and .h files at src/, split the sources and public headers into src/ and inc/ directories. Further partition them down per subsystem. Add include guards to public headers. Split some headers into multiple ones.
Diffstat (limited to 'src/common.c')
-rw-r--r--src/common.c2303
1 files changed, 0 insertions, 2303 deletions
diff --git a/src/common.c b/src/common.c
deleted file mode 100644
index 5a5fa75..0000000
--- a/src/common.c
+++ /dev/null
@@ -1,2303 +0,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program 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.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-//
-// common.c -- misc functions used in client and server
-//
-
-#include "common.h"
-#include "files.h"
-#include "protocol.h"
-#include "q_msg.h"
-#include "q_fifo.h"
-#include "net_common.h"
-#include "net_chan.h"
-#include "sys_public.h"
-#include "cl_public.h"
-#include "sv_public.h"
-#include "q_list.h"
-#include "bsp.h"
-#include "cmodel.h"
-#include "q_field.h"
-#include "prompt.h"
-#include "fpu.h"
-#include <setjmp.h>
-
-static jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame
-
-static qboolean com_errorEntered;
-static char com_errorMsg[MAXERRORMSG]; // from Com_Printf/Com_Error
-
-static int com_printEntered;
-
-static char **com_argv;
-static int com_argc;
-
-#ifdef _DEBUG
-cvar_t *developer;
-#endif
-cvar_t *timescale;
-cvar_t *fixedtime;
-cvar_t *dedicated;
-cvar_t *com_version;
-
-cvar_t *logfile_enable; // 1 = create new, 2 = append to existing
-cvar_t *logfile_flush; // 1 = flush after each print
-cvar_t *logfile_name;
-cvar_t *logfile_prefix;
-
-#if USE_CLIENT
-cvar_t *cl_running;
-cvar_t *cl_paused;
-#endif
-cvar_t *sv_running;
-cvar_t *sv_paused;
-cvar_t *com_timedemo;
-cvar_t *com_date_format;
-cvar_t *com_time_format;
-#ifdef _DEBUG
-cvar_t *com_debug_break;
-#endif
-cvar_t *com_fatal_error;
-
-cvar_t *allow_download;
-cvar_t *allow_download_players;
-cvar_t *allow_download_models;
-cvar_t *allow_download_sounds;
-cvar_t *allow_download_maps;
-cvar_t *allow_download_textures;
-cvar_t *allow_download_pics;
-cvar_t *allow_download_others;
-
-cvar_t *rcon_password;
-
-const char com_version_string[] =
- APPLICATION " " VERSION " " __DATE__ " " BUILDSTRING " " CPUSTRING;
-
-qhandle_t com_logFile;
-qboolean com_logNewline;
-unsigned com_framenum;
-unsigned com_eventTime;
-unsigned com_localTime;
-qboolean com_initialized;
-time_t com_startTime;
-
-#if USE_CLIENT
-cvar_t *host_speeds;
-
-// host_speeds times
-unsigned time_before_game;
-unsigned time_after_game;
-unsigned time_before_ref;
-unsigned time_after_ref;
-#endif
-
-/*
-============================================================================
-
-CLIENT / SERVER interactions
-
-============================================================================
-*/
-
-static int rd_target;
-static char *rd_buffer;
-static size_t rd_buffersize;
-static size_t rd_length;
-static rdflush_t rd_flush;
-
-void Com_BeginRedirect(int target, char *buffer, size_t buffersize, rdflush_t flush)
-{
- if (rd_target || !target || !buffer || !buffersize || !flush) {
- return;
- }
- rd_target = target;
- rd_buffer = buffer;
- rd_buffersize = buffersize;
- rd_flush = flush;
- rd_length = 0;
-}
-
-static void Com_AbortRedirect(void)
-{
- rd_target = 0;
- rd_buffer = NULL;
- rd_buffersize = 0;
- rd_flush = NULL;
- rd_length = 0;
-}
-
-void Com_EndRedirect(void)
-{
- if (!rd_target) {
- return;
- }
- rd_flush(rd_target, rd_buffer, rd_length);
- rd_target = 0;
- rd_buffer = NULL;
- rd_buffersize = 0;
- rd_flush = NULL;
- rd_length = 0;
-}
-
-static void Com_Redirect(const char *msg, size_t total)
-{
- size_t length;
-
- while (total) {
- length = total;
- if (length > rd_buffersize) {
- length = rd_buffersize;
- }
- if (rd_length > rd_buffersize - length) {
- rd_flush(rd_target, rd_buffer, rd_length);
- rd_length = 0;
- }
- memcpy(rd_buffer + rd_length, msg, length);
- rd_length += length;
- total -= length;
- }
-}
-
-static void logfile_close(void)
-{
- if (!com_logFile) {
- return;
- }
-
- Com_Printf("Closing console log.\n");
-
- FS_FCloseFile(com_logFile);
- com_logFile = 0;
-}
-
-static void logfile_open(void)
-{
- char buffer[MAX_OSPATH];
- unsigned mode;
- qhandle_t f;
-
- mode = logfile_enable->integer > 1 ? FS_MODE_APPEND : FS_MODE_WRITE;
- if (logfile_flush->integer > 0) {
- if (logfile_flush->integer > 1) {
- mode |= FS_BUF_NONE;
- } else {
- mode |= FS_BUF_LINE;
- }
- }
-
- f = FS_EasyOpenFile(buffer, sizeof(buffer), mode | FS_FLAG_TEXT,
- "logs/", logfile_name->string, ".log");
- if (!f) {
- Cvar_Set("logfile", "0");
- return;
- }
-
- com_logFile = f;
- com_logNewline = qtrue;
- Com_Printf("Logging console to %s\n", buffer);
-}
-
-static void logfile_enable_changed(cvar_t *self)
-{
- logfile_close();
- if (self->integer) {
- logfile_open();
- }
-}
-
-static void logfile_param_changed(cvar_t *self)
-{
- if (logfile_enable->integer) {
- logfile_close();
- logfile_open();
- }
-}
-
-static size_t format_local_time(char *buffer, size_t size, const char *fmt)
-{
- static struct tm cached_tm;
- static time_t cached_time;
- time_t now;
- struct tm *tm;
-
- if (!size) {
- return 0;
- }
-
- buffer[0] = 0;
-
- now = time(NULL);
- if (now == cached_time) {
- // avoid calling localtime() too often since it is not that cheap
- tm = &cached_tm;
- } else {
- tm = localtime(&now);
- if (!tm) {
- return 0;
- }
- cached_time = now;
- cached_tm = *tm;
- }
-
- return strftime(buffer, size, fmt, tm);
-}
-
-static void logfile_write(print_type_t type, const char *s)
-{
- char text[MAXPRINTMSG];
- char buf[MAX_QPATH];
- char *p, *maxp;
- size_t len;
- ssize_t ret;
- int c;
-
- if (logfile_prefix->string[0]) {
- p = strchr(logfile_prefix->string, '@');
- if (p) {
- // expand it in place, hacky
- switch (type) {
- case PRINT_TALK: *p = 'T'; break;
- case PRINT_DEVELOPER: *p = 'D'; break;
- case PRINT_WARNING: *p = 'W'; break;
- case PRINT_ERROR: *p = 'E'; break;
- case PRINT_NOTICE: *p = 'N'; break;
- default: *p = 'A'; break;
- }
- }
- len = format_local_time(buf, sizeof(buf), logfile_prefix->string);
- if (p) {
- *p = '@';
- }
- } else {
- len = 0;
- }
-
- p = text;
- maxp = text + sizeof(text) - 1;
- while (*s) {
- if (com_logNewline) {
- if (len > 0 && p + len < maxp) {
- memcpy(p, buf, len);
- p += len;
- }
- com_logNewline = qfalse;
- }
-
- if (p == maxp) {
- break;
- }
-
- c = *s++;
- if (c == '\n') {
- com_logNewline = qtrue;
- } else {
- c = Q_charascii(c);
- }
-
- *p++ = c;
- }
- *p = 0;
-
- len = p - text;
- ret = FS_Write(text, len, com_logFile);
- if (ret != len) {
- // zero handle BEFORE doing anything else to avoid recursion
- qhandle_t tmp = com_logFile;
- com_logFile = 0;
- FS_FCloseFile(tmp);
- Com_EPrintf("Couldn't write console log: %s\n", Q_ErrorString(ret));
- Cvar_Set("logfile", "0");
- }
-}
-
-#ifndef _WIN32
-/*
-=============
-Com_FlushLogs
-
-When called from SIGHUP handler on UNIX-like systems,
-will close and reopen logfile handle for rotation.
-=============
-*/
-void Com_FlushLogs(void)
-{
- if (logfile_enable) {
- logfile_enable_changed(logfile_enable);
- }
-}
-#endif
-
-void Com_SetColor(color_index_t color)
-{
- if (rd_target) {
- return;
- }
-#if USE_CLIENT
- // graphical console
- Con_SetColor(color);
-#endif
-#if USE_SYSCON
- // debugging console
- Sys_SetConsoleColor(color);
-#endif
-}
-
-void Com_SetLastError(const char *msg)
-{
- if (msg) {
- Q_strlcpy(com_errorMsg, msg, sizeof(com_errorMsg));
- } else {
- strcpy(com_errorMsg, "No error");
- }
-}
-
-char *Com_GetLastError(void)
-{
- return com_errorMsg;
-}
-
-/*
-=============
-Com_Printf
-
-Both client and server can use this, and it will output
-to the apropriate place.
-=============
-*/
-void Com_LPrintf(print_type_t type, const char *fmt, ...)
-{
- va_list argptr;
- char msg[MAXPRINTMSG];
- size_t len;
-
- // may be entered recursively only once
- if (com_printEntered >= 2) {
- return;
- }
-
- com_printEntered++;
-
- va_start(argptr, fmt);
- len = Q_vscnprintf(msg, sizeof(msg), fmt, argptr);
- va_end(argptr);
-
- if (type == PRINT_ERROR && !com_errorEntered && len) {
- size_t errlen = len;
-
- if (errlen >= sizeof(com_errorMsg)) {
- errlen = sizeof(com_errorMsg) - 1;
- }
-
- // save error msg
- memcpy(com_errorMsg, msg, errlen);
- com_errorMsg[errlen] = 0;
-
- // strip trailing '\n'
- if (com_errorMsg[errlen - 1] == '\n') {
- com_errorMsg[errlen - 1] = 0;
- }
- }
-
- if (rd_target) {
- Com_Redirect(msg, len);
- } else {
- switch (type) {
- case PRINT_TALK:
- Com_SetColor(COLOR_ALT);
- break;
- case PRINT_DEVELOPER:
- Com_SetColor(COLOR_BLUE);
- break;
- case PRINT_WARNING:
- Com_SetColor(COLOR_YELLOW);
- break;
- case PRINT_ERROR:
- Com_SetColor(COLOR_RED);
- break;
- case PRINT_NOTICE:
- Com_SetColor(COLOR_CYAN);
- break;
- default:
- break;
- }
-
-#if USE_CLIENT
- // graphical console
- Con_Print(msg);
-#endif
-
-#if USE_SYSCON
- // debugging console
- Sys_ConsoleOutput(msg);
-#endif
-
- // remote console
- //SV_ConsoleOutput(msg);
-
- // logfile
- if (com_logFile) {
- logfile_write(type, msg);
- }
-
- if (type) {
- Com_SetColor(COLOR_NONE);
- }
- }
-
- com_printEntered--;
-}
-
-
-/*
-=============
-Com_Error
-
-Both client and server can use this, and it will
-do the apropriate things.
-=============
-*/
-void Com_Error(error_type_t code, const char *fmt, ...)
-{
- char msg[MAXERRORMSG];
- va_list argptr;
- size_t len;
-
- // may not be entered recursively
- if (com_errorEntered) {
-#ifdef _DEBUG
- if (com_debug_break && com_debug_break->integer) {
- Sys_DebugBreak();
- }
-#endif
- Sys_Error("recursive error after: %s", com_errorMsg);
- }
-
- com_errorEntered = qtrue;
-
- va_start(argptr, fmt);
- len = Q_vscnprintf(msg, sizeof(msg), fmt, argptr);
- va_end(argptr);
-
- // save error msg
- // can't print into it directly since it may
- // overlap with one of the arguments!
- memcpy(com_errorMsg, msg, len + 1);
-
- // fix up drity message buffers
- MSG_Init();
-
- // abort any console redirects
- Com_AbortRedirect();
-
- // reset Com_Printf recursion level
- com_printEntered = 0;
-
- X86_POP_FPCW;
-
- if (code == ERR_DISCONNECT || code == ERR_RECONNECT) {
- Com_WPrintf("%s\n", com_errorMsg);
- SV_Shutdown(va("Server was killed: %s\n", com_errorMsg), code);
-#if USE_CLIENT
- CL_Disconnect(code);
-#endif
- goto abort;
- }
-
-#ifdef _DEBUG
- if (com_debug_break && com_debug_break->integer) {
- Sys_DebugBreak();
- }
-#endif
-
- // make otherwise non-fatal errors fatal
- if (com_fatal_error && com_fatal_error->integer) {
- code = ERR_FATAL;
- }
-
- if (code == ERR_DROP) {
- Com_EPrintf("********************\n"
- "ERROR: %s\n"
- "********************\n", com_errorMsg);
- SV_Shutdown(va("Server crashed: %s\n", com_errorMsg), ERR_DROP);
-#if USE_CLIENT
- CL_Disconnect(ERR_DROP);
-#endif
- goto abort;
- }
-
- if (com_logFile) {
- FS_FPrintf(com_logFile, "FATAL: %s\n", com_errorMsg);
- }
-
- SV_Shutdown(va("Server fatal crashed: %s\n", com_errorMsg), ERR_FATAL);
-#if USE_CLIENT
- CL_Shutdown();
-#endif
- Qcommon_Shutdown();
-
- Sys_Error("%s", com_errorMsg);
- // doesn't get there
-
-abort:
- if (com_logFile) {
- FS_Flush(com_logFile);
- }
- com_errorEntered = qfalse;
- longjmp(abortframe, -1);
-}
-
-#ifdef _WIN32
-void Com_AbortFrame(void)
-{
- longjmp(abortframe, -1);
-}
-#endif
-
-/*
-=============
-Com_Quit
-
-Both client and server can use this, and it will
-do the apropriate things. This function never returns.
-=============
-*/
-void Com_Quit(const char *reason, error_type_t type)
-{
- char buffer[MAX_STRING_CHARS];
- char *what = type == ERR_RECONNECT ? "restarted" : "quit";
-
- if (reason && *reason) {
- Q_snprintf(buffer, sizeof(buffer),
- "Server %s: %s\n", what, reason);
- } else {
- Q_snprintf(buffer, sizeof(buffer),
- "Server %s\n", what);
- }
-
- SV_Shutdown(buffer, type);
-
-#if USE_CLIENT
- CL_Shutdown();
-#endif
- Qcommon_Shutdown();
-
- Sys_Quit();
-}
-
-static void Com_Quit_f(void)
-{
- Com_Quit(Cmd_Args(), ERR_DISCONNECT);
-}
-
-#if !USE_CLIENT
-static void Com_Recycle_f(void)
-{
- Com_Quit(Cmd_Args(), ERR_RECONNECT);
-}
-#endif
-
-
-/*
-==============================================================================
-
- ZONE MEMORY ALLOCATION
-
-just cleared malloc with counters now...
-
-==============================================================================
-*/
-
-#define Z_MAGIC 0x1d0d
-#define Z_TAIL 0x5b7b
-
-#define Z_TAIL_F(z) \
- *(uint16_t *)((byte *)(z) + (z)->size - sizeof(uint16_t))
-
-#define Z_FOR_EACH(z) \
- for ((z) = z_chain.next; (z) != &z_chain; (z) = (z)->next)
-
-#define Z_FOR_EACH_SAFE(z, n) \
- for ((z) = z_chain.next; (z) != &z_chain; (z) = (n))
-
-typedef struct zhead_s {
- uint16_t magic;
- uint16_t tag; // for group free
- size_t size;
-#ifdef _DEBUG
- void *addr;
- time_t time;
-#endif
- struct zhead_s *prev, *next;
-} zhead_t;
-
-// number of overhead bytes
-#define Z_EXTRA (sizeof(zhead_t) + sizeof(uint16_t))
-
-static zhead_t z_chain;
-
-static cvar_t *z_perturb;
-
-typedef struct {
- zhead_t z;
- char data[2];
- uint16_t tail;
-} zstatic_t;
-
-static const zstatic_t z_static[] = {
-#define Z_STATIC(x) \
- { { Z_MAGIC, TAG_STATIC, q_offsetof(zstatic_t, tail) + sizeof(uint16_t) }, x, Z_TAIL }
-
- Z_STATIC("0"),
- Z_STATIC("1"),
- Z_STATIC("2"),
- Z_STATIC("3"),
- Z_STATIC("4"),
- Z_STATIC("5"),
- Z_STATIC("6"),
- Z_STATIC("7"),
- Z_STATIC("8"),
- Z_STATIC("9"),
- Z_STATIC("")
-
-#undef Z_STATIC
-};
-
-typedef struct {
- size_t count;
- size_t bytes;
-} zstats_t;
-
-static zstats_t z_stats[TAG_MAX];
-
-static const char z_tagnames[TAG_MAX][8] = {
- "game",
- "static",
- "generic",
- "cmd",
- "cvar",
- "fs",
- "refresh",
- "ui",
- "server",
- "mvd",
- "sound",
- "cmodel"
-};
-
-static inline void Z_Validate(zhead_t *z, const char *func)
-{
- if (z->magic != Z_MAGIC) {
- Com_Error(ERR_FATAL, "%s: bad magic", func);
- }
- if (Z_TAIL_F(z) != Z_TAIL) {
- Com_Error(ERR_FATAL, "%s: bad tail", func);
- }
- if (z->tag == TAG_FREE) {
- Com_Error(ERR_FATAL, "%s: bad tag", func);
- }
-}
-
-void Z_Check(void)
-{
- zhead_t *z;
-
- Z_FOR_EACH(z) {
- Z_Validate(z, __func__);
- }
-}
-
-void Z_LeakTest(memtag_t tag)
-{
- zhead_t *z;
- size_t numLeaks = 0, numBytes = 0;
-
- Z_FOR_EACH(z) {
- Z_Validate(z, __func__);
- if (z->tag == tag) {
- numLeaks++;
- numBytes += z->size;
- }
- }
-
- if (numLeaks) {
- Com_WPrintf("************* Z_LeakTest *************\n"
- "%s leaked %"PRIz" bytes of memory (%"PRIz" object%s)\n"
- "**************************************\n",
- z_tagnames[tag < TAG_MAX ? tag : TAG_FREE],
- numBytes, numLeaks, numLeaks == 1 ? "" : "s");
- }
-}
-
-/*
-========================
-Z_Free
-========================
-*/
-void Z_Free(void *ptr)
-{
- zhead_t *z;
- zstats_t *s;
-
- if (!ptr) {
- return;
- }
-
- z = (zhead_t *)ptr - 1;
-
- Z_Validate(z, __func__);
-
- s = &z_stats[z->tag < TAG_MAX ? z->tag : TAG_FREE];
- s->count--;
- s->bytes -= z->size;
-
- if (z->tag != TAG_STATIC) {
- z->prev->next = z->next;
- z->next->prev = z->prev;
- z->magic = 0xdead;
- z->tag = TAG_FREE;
- free(z);
- }
-}
-
-#if 0
-/*
-========================
-Z_Realloc
-========================
-*/
-void *Z_Realloc(void *ptr, size_t size)
-{
- zhead_t *z;
- zstats_t *s;
-
- if (!ptr) {
- return Z_Malloc(size);
- }
-
- if (!size) {
- Z_Free(ptr);
- return NULL;
- }
-
- z = (zhead_t *)ptr - 1;
-
- Z_Validate(z, __func__);
-
- if (z->tag == TAG_STATIC) {
- Com_Error(ERR_FATAL, "%s: couldn't realloc static memory", __func__);
- }
-
- s = &z_stats[z->tag < TAG_MAX ? z->tag : TAG_FREE];
- s->bytes -= z->size;
-
- if (size > SIZE_MAX - Z_EXTRA - 3) {
- Com_Error(ERR_FATAL, "%s: bad size", __func__);
- }
-
- size = (size + Z_EXTRA + 3) & ~3;
- z = realloc(z, size);
- if (!z) {
- Com_Error(ERR_FATAL, "%s: couldn't realloc %"PRIz" bytes", __func__, size);
- }
-
- z->size = size;
- z->prev->next = z;
- z->next->prev = z;
-
- s->bytes += size;
-
- Z_TAIL_F(z) = Z_TAIL;
-
- return z + 1;
-}
-#endif
-
-/*
-========================
-Z_Stats_f
-========================
-*/
-static void Z_Stats_f(void)
-{
- size_t bytes = 0, count = 0;
- zstats_t *s;
- int i;
-
- Com_Printf(" bytes blocks name\n"
- "--------- ------ -------\n");
-
- for (i = 0, s = z_stats; i < TAG_MAX; i++, s++) {
- if (!s->count) {
- continue;
- }
- Com_Printf("%9"PRIz" %6"PRIz" %s\n", s->bytes, s->count, z_tagnames[i]);
- bytes += s->bytes;
- count += s->count;
- }
-
- Com_Printf("--------- ------ -------\n"
- "%9"PRIz" %6"PRIz" total\n",
- bytes, count);
-}
-
-/*
-========================
-Z_FreeTags
-========================
-*/
-void Z_FreeTags(memtag_t tag)
-{
- zhead_t *z, *n;
-
- Z_FOR_EACH_SAFE(z, n) {
- Z_Validate(z, __func__);
- n = z->next;
- if (z->tag == tag) {
- Z_Free(z + 1);
- }
- }
-}
-
-/*
-========================
-Z_TagMalloc
-========================
-*/
-void *Z_TagMalloc(size_t size, memtag_t tag)
-{
- zhead_t *z;
- zstats_t *s;
-
- if (!size) {
- return NULL;
- }
-
- if (tag == TAG_FREE) {
- Com_Error(ERR_FATAL, "%s: bad tag", __func__);
- }
-
- if (size > SIZE_MAX - Z_EXTRA - 3) {
- Com_Error(ERR_FATAL, "%s: bad size", __func__);
- }
-
- size = (size + Z_EXTRA + 3) & ~3;
- z = malloc(size);
- if (!z) {
- Com_Error(ERR_FATAL, "%s: couldn't allocate %"PRIz" bytes", __func__, size);
- }
- z->magic = Z_MAGIC;
- z->tag = tag;
- z->size = size;
-
-#ifdef _DEBUG
-#if (defined __GNUC__)
- z->addr = __builtin_return_address(0);
-#elif (defined _MSC_VER)
- z->addr = _ReturnAddress();
-#else
- z->addr = NULL;
-#endif
- z->time = time(NULL);
-#endif
-
- z->next = z_chain.next;
- z->prev = &z_chain;
- z_chain.next->prev = z;
- z_chain.next = z;
-
- if (z_perturb && z_perturb->integer) {
- memset(z + 1, z_perturb->integer, size - Z_EXTRA);
- }
-
- Z_TAIL_F(z) = Z_TAIL;
-
- s = &z_stats[tag < TAG_MAX ? tag : TAG_FREE];
- s->count++;
- s->bytes += size;
-
- return z + 1;
-}
-
-void *Z_TagMallocz(size_t size, memtag_t tag)
-{
- if (!size) {
- return NULL;
- }
- return memset(Z_TagMalloc(size, tag), 0, size);
-}
-
-static byte *z_reserved_data;
-static size_t z_reserved_inuse;
-static size_t z_reserved_total;
-
-void Z_TagReserve(size_t size, memtag_t tag)
-{
- z_reserved_data = Z_TagMalloc(size, tag);
- z_reserved_total = size;
- z_reserved_inuse = 0;
-}
-
-void *Z_ReservedAlloc(size_t size)
-{
- void *ptr;
-
- if (!size) {
- return NULL;
- }
-
- if (size > z_reserved_total - z_reserved_inuse) {
- Com_Error(ERR_FATAL, "%s: couldn't allocate %"PRIz" bytes", __func__, size);
- }
-
- ptr = z_reserved_data + z_reserved_inuse;
- z_reserved_inuse += size;
-
- return ptr;
-}
-
-void *Z_ReservedAllocz(size_t size)
-{
- if (!size) {
- return NULL;
- }
- return memset(Z_ReservedAlloc(size), 0, size);
-}
-
-char *Z_ReservedCopyString(const char *in)
-{
- size_t len;
-
- if (!in) {
- return NULL;
- }
-
- len = strlen(in) + 1;
- return memcpy(Z_ReservedAlloc(len), in, len);
-}
-
-/*
-========================
-Z_Init
-========================
-*/
-static void Z_Init(void)
-{
- z_chain.next = z_chain.prev = &z_chain;
-}
-
-/*
-================
-Z_TagCopyString
-================
-*/
-char *Z_TagCopyString(const char *in, memtag_t tag)
-{
- size_t len;
-
- if (!in) {
- return NULL;
- }
-
- len = strlen(in) + 1;
- return memcpy(Z_TagMalloc(len, tag), in, len);
-}
-
-/*
-================
-Cvar_CopyString
-================
-*/
-char *Cvar_CopyString(const char *in)
-{
- size_t len;
- zstatic_t *z;
- zstats_t *s;
- int i;
-
- if (!in) {
- return NULL;
- }
-
- if (!in[0]) {
- i = 10;
- } else if (!in[1] && Q_isdigit(in[0])) {
- i = in[0] - '0';
- } else {
- len = strlen(in) + 1;
- return memcpy(Z_TagMalloc(len, TAG_CVAR), in, len);
- }
-
- // return static storage
- z = (zstatic_t *)&z_static[i];
- s = &z_stats[TAG_STATIC];
- s->count++;
- s->bytes += z->z.size;
- return z->data;
-}
-
-/*
-==============================================================================
-
- FIFO
-
-==============================================================================
-*/
-
-size_t FIFO_Read(fifo_t *fifo, void *buffer, size_t len)
-{
- size_t wrapped, head = fifo->ay - fifo->ax;
-
- if (head > len) {
- if (buffer) {
- memcpy(buffer, fifo->data + fifo->ax, len);
- fifo->ax += len;
- }
- return len;
- }
-
- wrapped = len - head;
- if (wrapped > fifo->bs) {
- wrapped = fifo->bs;
- }
- if (buffer) {
- memcpy(buffer, fifo->data + fifo->ax, head);
- memcpy((byte *)buffer + head, fifo->data, wrapped);
- fifo->ax = wrapped;
- fifo->ay = fifo->bs;
- fifo->bs = 0;
- }
-
- return head + wrapped;
-}
-
-size_t FIFO_Write(fifo_t *fifo, const void *buffer, size_t len)
-{
- size_t tail, wrapped, remaining;
-
- if (fifo->bs) {
- remaining = fifo->ax - fifo->bs;
- if (len > remaining) {
- len = remaining;
- }
- if (buffer) {
- memcpy(fifo->data + fifo->bs, buffer, len);
- fifo->bs += len;
- }
- return len;
- }
-
- tail = fifo->size - fifo->ay;
- if (tail > len) {
- if (buffer) {
- memcpy(fifo->data + fifo->ay, buffer, len);
- fifo->ay += len;
- }
- return len;
- }
-
- wrapped = len - tail;
- if (wrapped > fifo->ax) {
- wrapped = fifo->ax;
- }
- if (buffer) {
- memcpy(fifo->data + fifo->ay, buffer, tail);
- memcpy(fifo->data, (byte *)buffer + tail, wrapped);
- fifo->ay = fifo->size;
- fifo->bs = wrapped;
- }
-
- return tail + wrapped;
-}
-
-qboolean FIFO_ReadMessage(fifo_t *fifo, size_t msglen)
-{
- size_t len;
- byte *data;
-
- data = FIFO_Peek(fifo, &len);
- if (len < msglen) {
- // read in two chunks into message buffer
- if (!FIFO_TryRead(fifo, msg_read_buffer, msglen)) {
- return qfalse; // not yet available
- }
- SZ_Init(&msg_read, msg_read_buffer, sizeof(msg_read_buffer));
- } else {
- // read in a single block without copying any memory
- SZ_Init(&msg_read, data, msglen);
- FIFO_Decommit(fifo, msglen);
- }
-
- msg_read.cursize = msglen;
- return qtrue;
-}
-
-/*
-==============================================================================
-
- MATH
-
-==============================================================================
-*/
-
-const vec3_t bytedirs[NUMVERTEXNORMALS] = {
-#include "anorms.h"
-};
-
-int DirToByte(const vec3_t dir)
-{
- int i, best;
- float d, bestd;
-
- if (!dir) {
- return 0;
- }
-
- bestd = 0;
- best = 0;
- for (i = 0; i < NUMVERTEXNORMALS; i++) {
- d = DotProduct(dir, bytedirs[i]);
- if (d > bestd) {
- bestd = d;
- best = i;
- }
- }
-
- return best;
-}
-
-#if 0
-void ByteToDir(int index, vec3_t dir)
-{
- if (index < 0 || index >= NUMVERTEXNORMALS) {
- Com_Error(ERR_FATAL, "ByteToDir: illegal index");
- }
-
- VectorCopy(bytedirs[index], dir);
-}
-#endif
-
-void SetPlaneType(cplane_t *plane)
-{
- vec_t *normal = plane->normal;
-
- if (normal[0] == 1) {
- plane->type = PLANE_X;
- return;
- }
- if (normal[1] == 1) {
- plane->type = PLANE_Y;
- return;
- }
- if (normal[2] == 1) {
- plane->type = PLANE_Z;
- return;
- }
-
- plane->type = PLANE_NON_AXIAL;
-}
-
-void SetPlaneSignbits(cplane_t *plane)
-{
- int bits = 0;
-
- if (plane->normal[0] < 0) {
- bits |= 1;
- }
- if (plane->normal[1] < 0) {
- bits |= 2;
- }
- if (plane->normal[2] < 0) {
- bits |= 4;
- }
- plane->signbits = bits;
-}
-
-/*
-==================
-BoxOnPlaneSide
-
-Returns 1, 2, or 1 + 2
-==================
-*/
-#if !USE_ASM
-int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, cplane_t *p)
-{
- vec_t *bounds[2] = { emins, emaxs };
- int i = p->signbits & 1;
- int j = (p->signbits >> 1) & 1;
- int k = (p->signbits >> 2) & 1;
-
-#define P(i, j, k) \
- p->normal[0] * bounds[i][0] + \
- p->normal[1] * bounds[j][1] + \
- p->normal[2] * bounds[k][2]
-
- vec_t dist1 = P(i ^ 1, j ^ 1, k ^ 1);
- vec_t dist2 = P(i, j, k);
- int sides = 0;
-
-#undef P
-
- if (dist1 >= p->dist)
- sides = 1;
- if (dist2 < p->dist)
- sides |= 2;
-
- return sides;
-}
-#endif // USE_ASM
-
-/*
-==============================================================================
-
- WILDCARD COMPARE
-
-==============================================================================
-*/
-
-static qboolean match_raw(int c1, int c2, qboolean ignorecase)
-{
- if (c1 != c2) {
- if (!ignorecase) {
- return qfalse;
- }
-#ifdef _WIN32
- // ugly hack for file listing
- c1 = c1 == '\\' ? '/' : Q_tolower(c1);
- c2 = c2 == '\\' ? '/' : Q_tolower(c2);
-#else
- c1 = Q_tolower(c1);
- c2 = Q_tolower(c2);
-#endif
- if (c1 != c2) {
- return qfalse;
- }
- }
-
- return qtrue;
-}
-
-static qboolean match_char(int c1, int c2, qboolean ignorecase)
-{
- if (c1 == '?') {
- return !!c2; // match any char except NUL
- }
-
- return match_raw(c1, c2, ignorecase);
-}
-
-static qboolean match_part(const char *filter, const char *string,
- size_t len, qboolean ignorecase)
-{
- qboolean match;
-
- do {
- // skip over escape character
- if (*filter == '\\') {
- filter++;
- match = match_raw(*filter, *string, ignorecase);
- } else {
- match = match_char(*filter, *string, ignorecase);
- }
-
- if (!match) {
- return qfalse;
- }
-
- filter++;
- string++;
- } while (--len);
-
- return qtrue;
-}
-
-// match the longest possible part
-static const char *match_filter(const char *filter, const char *string,
- size_t len, qboolean ignorecase)
-{
- const char *ret = NULL;
- size_t remaining = strlen(string);
-
- while (remaining >= len) {
- if (match_part(filter, string, len, ignorecase)) {
- string += len;
- remaining -= len;
- ret = string;
- continue;
- }
- string++;
- remaining--;
- }
-
- return ret;
-}
-
-/*
-=================
-Com_WildCmpEx
-
-Wildcard compare. Returns true if string matches the pattern, false otherwise.
-
-- 'term' is handled as an additional filter terminator (besides NUL).
-- '*' matches any substring, including the empty string, but prefers longest
-possible substrings.
-- '?' matches any single character except NUL.
-- '\\' can be used to escape any character, including itself. any special
-characters lose their meaning in this case.
-
-=================
-*/
-qboolean Com_WildCmpEx(const char *filter, const char *string,
- int term, qboolean ignorecase)
-{
- const char *sub;
- size_t len;
- qboolean match;
-
- while (*filter && *filter != term) {
- if (*filter == '*') {
- // skip consecutive wildcards
- do {
- filter++;
- } while (*filter == '*');
-
- // scan out filter part to match
- for (sub = filter, len = 0; *filter && *filter != term && *filter != '*'; filter++, len++) {
- // skip over escape character
- if (*filter == '\\') {
- filter++;
- if (!*filter) {
- break;
- }
- }
- }
-
- // wildcard at the end matches everything
- if (!len) {
- return qtrue;
- }
-
- string = match_filter(sub, string, len, ignorecase);
- if (!string) {
- return qfalse;
- }
- } else {
- // skip over escape character
- if (*filter == '\\') {
- filter++;
- if (!*filter) {
- break;
- }
- match = match_raw(*filter, *string, ignorecase);
- } else {
- match = match_char(*filter, *string, ignorecase);
- }
-
- // match single character
- if (!match) {
- return qfalse;
- }
-
- filter++;
- string++;
- }
- }
-
- // match NUL at the end
- return !*string;
-}
-
-/*
-==============================================================================
-
- MISC
-
-==============================================================================
-*/
-
-const char *const colorNames[10] = {
- "black", "red", "green", "yellow",
- "blue", "cyan", "magenta", "white",
- "alt", "none"
-};
-
-/*
-================
-Com_ParseColor
-
-Parses color name or index up to the maximum allowed index.
-Returns COLOR_NONE in case of error.
-================
-*/
-color_index_t Com_ParseColor(const char *s, color_index_t last)
-{
- color_index_t i;
-
- if (COM_IsUint(s)) {
- i = strtoul(s, NULL, 10);
- return i > last ? COLOR_NONE : i;
- }
-
- for (i = 0; i <= last; i++) {
- if (!strcmp(colorNames[i], s)) {
- return i;
- }
- }
-
- return COLOR_NONE;
-}
-
-#if USE_REF == REF_GL
-/*
-================
-Com_ParseExtensionString
-
-Helper function to parse an OpenGL-style extension string.
-================
-*/
-unsigned Com_ParseExtensionString(const char *s, const char *const extnames[])
-{
- unsigned mask;
- const char *p;
- size_t l1, l2;
- int i;
-
- if (!s) {
- return 0;
- }
-
- mask = 0;
- while (*s) {
- p = Q_strchrnul(s, ' ');
- l1 = p - s;
- for (i = 0; extnames[i]; i++) {
- l2 = strlen(extnames[i]);
- if (l1 == l2 && !memcmp(s, extnames[i], l1)) {
- mask |= 1 << i;
- break;
- }
- }
- if (!*p) {
- break;
- }
- s = p + 1;
- }
-
- return mask;
-}
-#endif
-
-/*
-================
-Com_PlayerToEntityState
-
-Restores entity origin and angles from player state
-================
-*/
-void Com_PlayerToEntityState(const player_state_t *ps, entity_state_t *es)
-{
- vec_t pitch;
-
- VectorScale(ps->pmove.origin, 0.125f, es->origin);
-
- pitch = ps->viewangles[PITCH];
- if (pitch > 180) {
- pitch -= 360;
- }
- es->angles[PITCH] = pitch / 3;
- es->angles[YAW] = ps->viewangles[YAW];
- es->angles[ROLL] = 0;
-}
-
-#if USE_CLIENT || USE_MVD_CLIENT
-/*
-================
-Com_ParseTimespec
-
-Parses time/frame specification for seeking in demos.
-Does not check for integer overflow...
-================
-*/
-qboolean Com_ParseTimespec(const char *s, int *frames)
-{
- unsigned long c1, c2, c3;
- char *p;
-
- c1 = strtoul(s, &p, 10);
- if (!*p) {
- *frames = c1 * 10; // sec
- return qtrue;
- }
-
- if (*p == '.') {
- c2 = strtoul(p + 1, &p, 10);
- if (*p)
- return qfalse;
- *frames = c1 * 10 + c2; // sec.frac
- return qtrue;
- }
-
- if (*p == ':') {
- c2 = strtoul(p + 1, &p, 10);
- if (!*p) {
- *frames = c1 * 600 + c2 * 10; // min:sec
- return qtrue;
- }
-
- if (*p == '.') {
- c3 = strtoul(p + 1, &p, 10);
- if (*p)
- return qfalse;
- *frames = c1 * 600 + c2 * 10 + c3; // min:sec.frac
- return qtrue;
- }
-
- return qfalse;
- }
-
- return qfalse;
-}
-#endif
-
-/*
-================
-Com_HashString
-================
-*/
-unsigned Com_HashString(const char *s, unsigned size)
-{
- unsigned hash, c;
-
- hash = 0;
- while (*s) {
- c = *s++;
- hash = 127 * hash + c;
- }
-
- hash = (hash >> 20) ^(hash >> 10) ^ hash;
- return hash & (size - 1);
-}
-
-/*
-================
-Com_HashStringLen
-
-A case-insensitive version of Com_HashString that hashes up to 'len'
-characters.
-================
-*/
-unsigned Com_HashStringLen(const char *s, size_t len, unsigned size)
-{
- unsigned hash, c;
-
- hash = 0;
- while (*s && len--) {
- c = Q_tolower(*s++);
- hash = 127 * hash + c;
- }
-
- hash = (hash >> 20) ^(hash >> 10) ^ hash;
- return hash & (size - 1);
-}
-
-/*
-===============
-Com_PageInMemory
-
-===============
-*/
-int paged_total;
-
-void Com_PageInMemory(void *buffer, size_t size)
-{
- int i;
-
- for (i = size - 1; i > 0; i -= 4096)
- paged_total += ((byte *)buffer)[i];
-}
-
-size_t Com_FormatTime(char *buffer, size_t size, time_t t)
-{
- int sec, min, hour, day;
-
- min = t / 60; sec = t % 60;
- hour = min / 60; min %= 60;
- day = hour / 24; hour %= 24;
-
- if (day) {
- return Q_scnprintf(buffer, size, "%d+%d:%02d.%02d", day, hour, min, sec);
- }
- if (hour) {
- return Q_scnprintf(buffer, size, "%d:%02d.%02d", hour, min, sec);
- }
- return Q_scnprintf(buffer, size, "%02d.%02d", min, sec);
-}
-
-size_t Com_FormatTimeLong(char *buffer, size_t size, time_t t)
-{
- int sec, min, hour, day;
- size_t len;
-
- if (!t) {
- return Q_scnprintf(buffer, size, "0 secs");
- }
-
- min = t / 60; sec = t % 60;
- hour = min / 60; min %= 60;
- day = hour / 24; hour %= 24;
-
- len = 0;
-
- if (day) {
- len += Q_scnprintf(buffer + len, size - len,
- "%d day%s%s", day, day == 1 ? "" : "s", (hour || min || sec) ? ", " : "");
- }
- if (hour) {
- len += Q_scnprintf(buffer + len, size - len,
- "%d hour%s%s", hour, hour == 1 ? "" : "s", (min || sec) ? ", " : "");
- }
- if (min) {
- len += Q_scnprintf(buffer + len, size - len,
- "%d min%s%s", min, min == 1 ? "" : "s", sec ? ", " : "");
- }
- if (sec) {
- len += Q_scnprintf(buffer + len, size - len,
- "%d sec%s", sec, sec == 1 ? "" : "s");
- }
-
- return len;
-}
-
-size_t Com_TimeDiff(char *buffer, size_t size, time_t *p, time_t now)
-{
- time_t diff;
-
- if (*p > now) {
- *p = now;
- }
- diff = now - *p;
- return Com_FormatTime(buffer, size, diff);
-}
-
-size_t Com_TimeDiffLong(char *buffer, size_t size, time_t *p, time_t now)
-{
- time_t diff;
-
- if (*p > now) {
- *p = now;
- }
- diff = now - *p;
- return Com_FormatTimeLong(buffer, size, diff);
-}
-
-size_t Com_FormatSize(char *dest, size_t destsize, off_t bytes)
-{
- if (bytes >= 10000000) {
- return Q_scnprintf(dest, destsize, "%dM", (int)(bytes / 1000000));
- }
- if (bytes >= 1000000) {
- return Q_scnprintf(dest, destsize, "%.1fM", (float)bytes / 1000000);
- }
- if (bytes >= 1000) {
- return Q_scnprintf(dest, destsize, "%dK", (int)(bytes / 1000));
- }
- if (bytes >= 0) {
- return Q_scnprintf(dest, destsize, "%d", (int)bytes);
- }
- return Q_scnprintf(dest, destsize, "???");
-}
-
-size_t Com_FormatSizeLong(char *dest, size_t destsize, off_t bytes)
-{
- if (bytes >= 10000000) {
- return Q_scnprintf(dest, destsize, "%d MB", (int)(bytes / 1000000));
- }
- if (bytes >= 1000000) {
- return Q_scnprintf(dest, destsize, "%.1f MB", (float)bytes / 1000000);
- }
- if (bytes >= 1000) {
- return Q_scnprintf(dest, destsize, "%d kB", (int)(bytes / 1000));
- }
- if (bytes >= 0) {
- return Q_scnprintf(dest, destsize, "%d byte%s",
- (int)bytes, bytes == 1 ? "" : "s");
- }
- return Q_scnprintf(dest, destsize, "unknown size");
-}
-
-/*
-==============================================================================
-
- INIT / SHUTDOWN
-
-==============================================================================
-*/
-
-size_t Com_Time_m(char *buffer, size_t size)
-{
- return format_local_time(buffer, size, com_time_format->string);
-}
-
-static size_t Com_Date_m(char *buffer, size_t size)
-{
- return format_local_time(buffer, size, com_date_format->string);
-}
-
-size_t Com_Uptime_m(char *buffer, size_t size)
-{
- return Com_TimeDiff(buffer, size, &com_startTime, time(NULL));
-}
-
-size_t Com_UptimeLong_m(char *buffer, size_t size)
-{
- return Com_TimeDiffLong(buffer, size, &com_startTime, time(NULL));
-}
-
-static size_t Com_Random_m(char *buffer, size_t size)
-{
- return Q_scnprintf(buffer, size, "%d", rand_byte() % 10);
-}
-
-static size_t Com_MapList_m(char *buffer, size_t size)
-{
- int i, numFiles;
- void **list;
- char *s, *p;
- size_t len, total = 0;
-
- list = FS_ListFiles("maps", ".bsp", 0, &numFiles);
- for (i = 0; i < numFiles; i++) {
- s = list[i];
- p = COM_FileExtension(list[i]);
- *p = 0;
- len = strlen(s);
- if (total + len + 1 < size) {
- memcpy(buffer + total, s, len);
- buffer[total + len] = ' ';
- total += len + 1;
- }
- Z_Free(s);
- }
- buffer[total] = 0;
-
- Z_Free(list);
- return total;
-}
-
-static void Com_LastError_f(void)
-{
- Com_Printf("%s\n", com_errorMsg);
-}
-
-#if 0
-static void Com_Setenv_f(void)
-{
- int argc = Cmd_Argc();
-
- if (argc > 2) {
- Q_setenv(Cmd_Argv(1), Cmd_ArgsFrom(2));
- } else if (argc == 2) {
- char *env = getenv(Cmd_Argv(1));
-
- if (env) {
- Com_Printf("%s=%s\n", Cmd_Argv(1), env);
- } else {
- Com_Printf("%s undefined\n", Cmd_Argv(1));
- }
- } else {
- Com_Printf("Usage: %s <name> [value]\n", Cmd_Argv(0));
- }
-}
-#endif
-
-void Com_Address_g(genctx_t *ctx)
-{
- int i;
- cvar_t *var;
-
- for (i = 0; i < 1024; i++) {
- var = Cvar_FindVar(va("adr%d", i));
- if (!var) {
- break;
- }
- if (!var->string[0]) {
- continue;
- }
- if (!Prompt_AddMatch(ctx, var->string)) {
- break;
- }
- }
-}
-
-void Com_Generic_c(genctx_t *ctx, int argnum)
-{
- xcompleter_t c;
- xgenerator_t g;
- cvar_t *var;
- char *s;
-
- // complete command, alias or cvar name
- if (!argnum) {
- Cmd_Command_g(ctx);
- Cvar_Variable_g(ctx);
- Cmd_Alias_g(ctx);
- return;
- }
-
- // protect against possible duplicates
- ctx->ignoredups = qtrue;
-
- s = Cmd_Argv(ctx->argnum - argnum);
-
- // complete command argument or cvar value
- if ((c = Cmd_FindCompleter(s)) != NULL) {
- c(ctx, argnum);
- } else if (argnum == 1 && (var = Cvar_FindVar(s)) != NULL) {
- g = var->generator;
- if (g) {
- ctx->data = var;
- g(ctx);
- }
- }
-}
-
-#if USE_CLIENT
-void Com_Color_g(genctx_t *ctx)
-{
- int color;
-
- for (color = 0; color < 8; color++) {
- if (!Prompt_AddMatch(ctx, colorNames[color])) {
- break;
- }
- }
-}
-#endif
-
-/*
-===============
-Com_AddEarlyCommands
-
-Adds command line parameters as script statements.
-Commands lead with a +, and continue until another +
-
-Set commands are added early, so they are guaranteed to be set before
-the client and server initialize for the first time.
-
-Other commands are added late, after all initialization is complete.
-===============
-*/
-static void Com_AddEarlyCommands(qboolean clear)
-{
- int i;
- char *s;
-
- for (i = 1; i < com_argc; i++) {
- s = com_argv[i];
- if (!s) {
- continue;
- }
- if (strcmp(s, "+set")) {
- continue;
- }
- if (i + 2 >= com_argc) {
- Com_Printf("Usage: +set <variable> <value>\n");
- com_argc = i;
- break;
- }
- Cvar_SetEx(com_argv[i + 1], com_argv[i + 2], FROM_CMDLINE);
- if (clear) {
- com_argv[i] = com_argv[i + 1] = com_argv[i + 2] = NULL;
- }
- i += 2;
- }
-}
-
-/*
-=================
-Com_AddLateCommands
-
-Adds command line parameters as script statements
-Commands lead with a + and continue until another +
-
-Returns qtrue if any late commands were added, which
-will keep the demoloop from immediately starting
-
-Assumes +set commands are already filtered out
-=================
-*/
-static qboolean Com_AddLateCommands(void)
-{
- int i;
- char *s;
- qboolean ret = qfalse;
-
- for (i = 1; i < com_argc; i++) {
- s = com_argv[i];
- if (!s) {
- continue;
- }
- if (*s == '+') {
- if (ret) {
- Cbuf_AddText(&cmd_buffer, "\n");
- }
- s++;
- } else if (ret) {
- Cbuf_AddText(&cmd_buffer, " ");
- }
- Cbuf_AddText(&cmd_buffer, s);
- ret = qtrue;
- }
-
- if (ret) {
- Cbuf_AddText(&cmd_buffer, "\n");
- Cbuf_Execute(&cmd_buffer);
- }
-
- return ret;
-}
-
-static void Com_AddConfigFile(const char *name, unsigned flags)
-{
- qerror_t ret;
-
- ret = Cmd_ExecuteFile(name, flags);
- if (ret == Q_ERR_SUCCESS) {
- Cbuf_Execute(&cmd_buffer);
- } else if (ret != Q_ERR_NOENT) {
- Com_WPrintf("Couldn't exec %s: %s\n", name, Q_ErrorString(ret));
- }
-}
-
-/*
-=================
-Qcommon_Init
-=================
-*/
-void Qcommon_Init(int argc, char **argv)
-{
- if (setjmp(abortframe))
- Sys_Error("Error during initialization: %s", com_errorMsg);
-
- com_argc = argc;
- com_argv = argv;
-
- Com_SetLastError(NULL);
-
- X86_SetFPCW();
-
- // prepare enough of the subsystems to handle
- // cvar and command buffer management
- Z_Init();
- MSG_Init();
- Cbuf_Init();
- Cmd_Init();
- Cvar_Init();
- Key_Init();
- Prompt_Init();
-#if USE_CLIENT
- Con_Init();
-#endif
-
- //
- // init commands and vars
- //
- z_perturb = Cvar_Get("z_perturb", "0", 0);
-#if USE_CLIENT
- host_speeds = Cvar_Get("host_speeds", "0", 0);
-#endif
-#ifdef _DEBUG
- developer = Cvar_Get("developer", "0", 0);
-#endif
- timescale = Cvar_Get("timescale", "1", CVAR_CHEAT);
- fixedtime = Cvar_Get("fixedtime", "0", CVAR_CHEAT);
- logfile_enable = Cvar_Get("logfile", "0", 0);
- logfile_flush = Cvar_Get("logfile_flush", "0", 0);
- logfile_name = Cvar_Get("logfile_name", "console", 0);
- logfile_prefix = Cvar_Get("logfile_prefix", "[%Y-%m-%d %H:%M] ", 0);
-#if USE_CLIENT
- dedicated = Cvar_Get("dedicated", "0", CVAR_NOSET);
- cl_running = Cvar_Get("cl_running", "0", CVAR_ROM);
- cl_paused = Cvar_Get("cl_paused", "0", CVAR_ROM);
-#else
- dedicated = Cvar_Get("dedicated", "1", CVAR_ROM);
-#endif
- sv_running = Cvar_Get("sv_running", "0", CVAR_ROM);
- sv_paused = Cvar_Get("sv_paused", "0", CVAR_ROM);
- com_timedemo = Cvar_Get("timedemo", "0", CVAR_CHEAT);
- com_date_format = Cvar_Get("com_date_format", "%Y-%m-%d", 0);
-#ifdef _WIN32
- com_time_format = Cvar_Get("com_time_format", "%H.%M", 0);
-#else
- com_time_format = Cvar_Get("com_time_format", "%H:%M", 0);
-#endif
-#ifdef _DEBUG
- com_debug_break = Cvar_Get("com_debug_break", "0", 0);
-#endif
- com_fatal_error = Cvar_Get("com_fatal_error", "0", 0);
- com_version = Cvar_Get("version", com_version_string, CVAR_SERVERINFO | CVAR_ROM);
-
- allow_download = Cvar_Get("allow_download", Com_IsDedicated() ? "0" : "1", CVAR_ARCHIVE);
- allow_download_players = Cvar_Get("allow_download_players", "1", CVAR_ARCHIVE);
- allow_download_models = Cvar_Get("allow_download_models", "1", CVAR_ARCHIVE);
- allow_download_sounds = Cvar_Get("allow_download_sounds", "1", CVAR_ARCHIVE);
- allow_download_maps = Cvar_Get("allow_download_maps", "1", CVAR_ARCHIVE);
- allow_download_textures = Cvar_Get("allow_download_textures", "1", CVAR_ARCHIVE);
- allow_download_pics = Cvar_Get("allow_download_pics", "1", CVAR_ARCHIVE);
- allow_download_others = Cvar_Get("allow_download_others", "0", 0);
-
- rcon_password = Cvar_Get("rcon_password", "", CVAR_PRIVATE);
-
- Cmd_AddCommand("z_stats", Z_Stats_f);
-
- //Cmd_AddCommand("setenv", Com_Setenv_f);
-
- Cmd_AddMacro("com_date", Com_Date_m);
- Cmd_AddMacro("com_time", Com_Time_m);
- Cmd_AddMacro("com_uptime", Com_Uptime_m);
- Cmd_AddMacro("com_uptime_long", Com_UptimeLong_m);
- Cmd_AddMacro("random", Com_Random_m);
- Cmd_AddMacro("com_maplist", Com_MapList_m);
-
- // add any system-wide configuration files
- Sys_AddDefaultConfig();
-
- // we need to add the early commands twice, because
- // a basedir or cddir needs to be set before execing
- // config files, but we want other parms to override
- // the settings of the config files
- Com_AddEarlyCommands(qfalse);
-
- Sys_Init();
-
-#if USE_SYSCON
- Sys_RunConsole();
-#endif
-
- FS_Init();
-
-#if USE_SYSCON
- Sys_RunConsole();
-#endif
-
- // no longer allow CVAR_NOSET modifications
- com_initialized = qtrue;
-
- // after FS is initialized, open logfile
- logfile_enable->changed = logfile_enable_changed;
- logfile_flush->changed = logfile_param_changed;
- logfile_name->changed = logfile_param_changed;
- logfile_enable_changed(logfile_enable);
-
- // execute configs: default.cfg may come from the packfile, but config.cfg
- // and autoexec.cfg must be real files within the game directory
- Com_AddConfigFile(COM_DEFAULT_CFG, 0);
- Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME);
- Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_GAME);
-
- Com_AddEarlyCommands(qtrue);
-
- Cmd_AddCommand("lasterror", Com_LastError_f);
-
- Cmd_AddCommand("quit", Com_Quit_f);
-#if !USE_CLIENT
- Cmd_AddCommand("recycle", Com_Recycle_f);
-#endif
-
- srand(Sys_Milliseconds());
-
- Netchan_Init();
- NET_Init();
- BSP_Init();
- CM_Init();
- SV_Init();
-#if USE_CLIENT
- CL_Init();
-#endif
-#if USE_TESTS
- Com_InitTests();
-#endif
-
-#if USE_SYSCON
- Sys_RunConsole();
-#endif
-
- // add + commands from command line
- if (!Com_AddLateCommands()) {
- // if the user didn't give any commands, run default action
- char *cmd = Com_IsDedicated() ? "dedicated_start" : "client_start";
- if ((cmd = Cmd_AliasCommand(cmd)) != NULL) {
- Cbuf_AddText(&cmd_buffer, cmd);
- Cbuf_Execute(&cmd_buffer);
- }
- }
-#if USE_CLIENT
- else {
- // the user asked for something explicit
- // so drop the loading plaque
- SCR_EndLoadingPlaque();
- }
-#endif
-
- // even not given a starting map, dedicated server starts
- // listening for rcon commands (create socket after all configs
- // are executed to make sure port number is properly set)
- if (Com_IsDedicated()) {
- NET_Config(NET_SERVER);
- }
-
- Com_AddConfigFile("postinit.cfg", FS_TYPE_REAL | FS_PATH_GAME);
-
- Com_Printf("====== " PRODUCT " initialized ======\n\n");
- Com_LPrintf(PRINT_NOTICE, APPLICATION " " VERSION ", " __DATE__ "\n");
- Com_Printf("http://skuller.net/q2pro/\n\n");
-
- time(&com_startTime);
-
- com_eventTime = Sys_Milliseconds();
-}
-
-/*
-=================
-Qcommon_Frame
-=================
-*/
-void Qcommon_Frame(void)
-{
-#if USE_CLIENT
- unsigned time_before, time_event, time_between, time_after;
- unsigned clientrem;
-#endif
- unsigned oldtime, msec;
- static unsigned remaining;
- static float frac;
-
- if (setjmp(abortframe)) {
- return; // an ERR_DROP was thrown
- }
-
-#if USE_CLIENT
- time_before = time_event = time_between = time_after = 0;
-
- if (host_speeds->integer)
- time_before = Sys_Milliseconds();
-#endif
-
- // sleep on network sockets when running a dedicated server
- // still do a select(), but don't sleep when running a client!
- NET_Sleep(remaining);
-
- // calculate time spent running last frame and sleeping
- oldtime = com_eventTime;
- com_eventTime = Sys_Milliseconds();
- if (oldtime > com_eventTime) {
- oldtime = com_eventTime;
- }
- msec = com_eventTime - oldtime;
-
-#if USE_CLIENT
- // spin until msec is non-zero if running a client
- if (!dedicated->integer && !com_timedemo->integer) {
- while (msec < 1) {
- qboolean break_now = CL_ProcessEvents();
- com_eventTime = Sys_Milliseconds();
- msec = com_eventTime - oldtime;
- if (break_now)
- break;
- }
- }
-#endif
-
- if (msec > 250) {
- Com_DPrintf("Hitch warning: %u msec frame time\n", msec);
- msec = 100; // time was unreasonable,
- // host OS was hibernated or something
- }
-
- if (fixedtime->integer) {
- Cvar_ClampInteger(fixedtime, 1, 1000);
- msec = fixedtime->integer;
- } else if (timescale->value > 0) {
- frac += msec * timescale->value;
- msec = frac;
- frac -= msec;
- }
-
- // run local time
- com_localTime += msec;
- com_framenum++;
-
-#if USE_CLIENT
- if (host_speeds->integer)
- time_event = Sys_Milliseconds();
-#endif
-
-#if USE_SYSCON
- // run system console
- Sys_RunConsole();
-#endif
-
- NET_UpdateStats();
-
- remaining = SV_Frame(msec);
-
-#if USE_CLIENT
- if (host_speeds->integer)
- time_between = Sys_Milliseconds();
-
- clientrem = CL_Frame(msec);
- if (remaining > clientrem) {
- remaining = clientrem;
- }
-
- if (host_speeds->integer)
- time_after = Sys_Milliseconds();
-
- if (host_speeds->integer) {
- int all, ev, sv, gm, cl, rf;
-
- all = time_after - time_before;
- ev = time_event - time_before;
- sv = time_between - time_event;
- cl = time_after - time_between;
- gm = time_after_game - time_before_game;
- rf = time_after_ref - time_before_ref;
- sv -= gm;
- cl -= rf;
-
- Com_Printf("all:%3i ev:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n",
- all, ev, sv, gm, cl, rf);
- }
-#endif
-}
-
-/*
-=================
-Qcommon_Shutdown
-=================
-*/
-void Qcommon_Shutdown(void)
-{
- NET_Shutdown();
- logfile_close();
- FS_Shutdown();
-}
-