Skip to content

Commit

Permalink
Add custom add-on server support
Browse files Browse the repository at this point in the history
Defaults to https://kexquake.s3.amazonaws.com
(see https://kexquake.s3.amazonaws.com/index.html)

New command-line options:
  -addons <url>: specify a different server
  -noaddons    : disable add-on server support
  • Loading branch information
andrei-drexler committed Jan 8, 2023
1 parent 5f6866d commit 7ab6d8a
Show file tree
Hide file tree
Showing 33 changed files with 6,525 additions and 68 deletions.
1 change: 1 addition & 0 deletions Linux/CodeBlocks/QuakeSpasm-SDL2.cbp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<Add option="-logg" />
<Add option="-lmad" />
<Add option="-lm" />
<Add option="-lcurl" />
</Linker>
<Unit filename="../../Quake/anorm_dots.h" />
<Unit filename="../../Quake/anorms.h" />
Expand Down
3 changes: 3 additions & 0 deletions Quake/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ else
NET_LIBS :=
endif

NET_LIBS += -lcurl
CFLAGS += $(shell $(PKG_CONFIG) --cflags libcurl)

ifneq ($(VORBISLIB),vorbis)
ifneq ($(VORBISLIB),tremor)
$(error Invalid VORBISLIB setting)
Expand Down
4 changes: 4 additions & 0 deletions Quake/Makefile.w32
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ endif
CFLAGS += $(DEFWINSOCK)
NET_LIBS := $(LIBWINSOCK)

NET_LIBS += -lcurl
CFLAGS += -I../Windows/curl/include
LDFLAGS += -L../Windows/curl/lib/x86

ifneq ($(VORBISLIB),vorbis)
ifneq ($(VORBISLIB),tremor)
$(error Invalid VORBISLIB setting)
Expand Down
4 changes: 4 additions & 0 deletions Quake/Makefile.w64
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ LIBWINSOCK := -lws2_32
CFLAGS += $(DEFWINSOCK)
NET_LIBS := $(LIBWINSOCK)

NET_LIBS += -lcurl
CFLAGS += -I../Windows/curl/include
LDFLAGS += -L../Windows/curl/lib/x64

ifneq ($(VORBISLIB),vorbis)
ifneq ($(VORBISLIB),tremor)
$(error Invalid VORBISLIB setting)
Expand Down
92 changes: 92 additions & 0 deletions Quake/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "q_ctype.h"
#include "steam.h"
#include <time.h>
#include <errno.h>

#include "miniz.h"
Expand Down Expand Up @@ -1582,6 +1583,64 @@ void COM_WriteFile (const char *filename, const void *data, int len)
Sys_FileClose (handle);
}

/*
============
COM_WriteFile_OSPath
============
*/
qboolean COM_WriteFile_OSPath (const char *filename, const void *data, size_t len)
{
qboolean ret = false;
FILE *f = Sys_fopen (filename, "wb");

if (f)
{
ret = fwrite (data, len, 1, f) == 1;
fclose (f);
if (!ret)
Sys_remove (filename);
}

return ret;
}

/*
============
COM_TempSuffix
============
*/
char *COM_TempSuffix (unsigned seq)
{
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=#";
static char buf[64];
time_t now = 0;
int r, len = 0, maxlen = sizeof (buf) - 1;

time (&now);
while (now && len < maxlen)
{
buf[len++] = base64[now & 63];
now >>= 6;
}

r = rand ();
while (r && len < maxlen)
{
buf[len++] = base64[r & 63];
r >>= 6;
}

while (seq && len < maxlen)
{
buf[len++] = base64[seq & 63];
seq >>= 6;
}

buf[len] = '\0';

return buf;
}

/*
============
COM_CreatePath
Expand Down Expand Up @@ -1944,6 +2003,39 @@ byte *COM_LoadMallocFile_TextMode_OSPath (const char *path, long *len_out)
return data;
}

char *COM_NormalizeLineEndings (char *buffer)
{
char *src, *dst;

src = dst = buffer;

while (*src)
{
if (src == dst)
{
while (*src && *src != '\r')
src++;
dst = src;
}
else
{
while (*src && *src != '\r')
*dst++ = *src++;
}

if (!*src)
break;

src++;
if (*src != '\n')
*dst++ = '\n';
}

*dst = '\0';

return buffer;
}

const char *COM_ParseIntNewline(const char *buffer, int *value)
{
char *end;
Expand Down
7 changes: 7 additions & 0 deletions Quake/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ extern char *q_strupr (char *str);
extern int q_snprintf (char *str, size_t size, const char *format, ...) FUNC_PRINTF(3,4);
extern int q_vsnprintf(char *str, size_t size, const char *format, va_list args) FUNC_PRINTF(3,0);

#define PLURAL(count) (&"s"[(count)==1])

//============================================================================

extern THREAD_LOCAL char com_token[1024];
Expand Down Expand Up @@ -296,6 +298,7 @@ void COM_DefaultExtension (char *path, const char *extension, size_t len);
#endif
const char *COM_FileGetExtension (const char *in); /* doesn't return NULL */
void COM_ExtractExtension (const char *in, char *out, size_t outsize);
char *COM_TempSuffix (unsigned seq);
void COM_CreatePath (char *path);

char *va (const char *format, ...) FUNC_PRINTF(1,2);
Expand Down Expand Up @@ -356,6 +359,7 @@ extern char com_gamedir[MAX_OSPATH];
extern THREAD_LOCAL int file_from_pak; // global indicating that file came from a pak

void COM_WriteFile (const char *filename, const void *data, int len);
qboolean COM_WriteFile_OSPath (const char *filename, const void *data, size_t len);
int COM_OpenFile (const char *filename, int *handle, unsigned int *path_id);
int COM_FOpenFile (const char *filename, FILE **file, unsigned int *path_id);
qboolean COM_FileExists (const char *filename, unsigned int *path_id);
Expand Down Expand Up @@ -386,6 +390,9 @@ byte *COM_LoadMallocFile (const char *path, unsigned int *path_id);
// Loads in "t" mode so CRLF to LF translation is performed on Windows.
byte *COM_LoadMallocFile_TextMode_OSPath (const char *path, long *len_out);

// Replaces CR/CRLF with LF.
char *COM_NormalizeLineEndings (char *buffer);

// Attempts to parse an int, followed by a newline.
// Returns advanced buffer position.
// Doesn't signal parsing failure, but this is not needed for savegame loading.
Expand Down
123 changes: 117 additions & 6 deletions Quake/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,108 @@ void Host_ClearMemory (void)
}


//==============================================================================
//
// Main thread APC queue
//
//==============================================================================

typedef struct asyncproc_s
{
void (*func) (void *param);
void *param;
} asyncproc_t;

typedef struct asyncqueue_s
{
size_t head;
size_t tail;
size_t capacity;
qboolean teardown;
SDL_mutex *mutex;
SDL_cond *notfull;
asyncproc_t *procs;
} asyncqueue_t;

static asyncqueue_t async_queue;

static void AsyncQueue_Init (asyncqueue_t *queue, size_t capacity)
{
memset (queue, 0, sizeof (*queue));

if (!capacity)
capacity = 1024;
else
capacity = Q_nextPow2 (capacity);
queue->capacity = capacity;
capacity *= sizeof (queue->procs[0]);
queue->procs = (asyncproc_t *) malloc (capacity);
if (!queue->procs)
Sys_Error ("AsyncQueue_Init: malloc failed on %" SDL_PRIu64 " bytes", (uint64_t) capacity);

queue->mutex = SDL_CreateMutex ();
if (!queue->mutex)
Sys_Error ("AsyncQueue_Init: could not create mutex");

queue->notfull = SDL_CreateCond ();
if (!queue->notfull)
Sys_Error ("AsyncQueue_Init: could not create condition variable");
}

static void AsyncQueue_Push (asyncqueue_t *queue, void (*func) (void *param), void *param)
{
asyncproc_t *proc;

if (!queue->mutex)
return;
SDL_LockMutex (queue->mutex);
while (!queue->teardown && queue->tail - queue->head >= queue->capacity)
SDL_CondWait (queue->notfull, queue->mutex);

if (!queue->teardown)
{
proc = &queue->procs[(queue->tail++) & (queue->capacity - 1)];
proc->func = func;
proc->param = param;
}

SDL_UnlockMutex (queue->mutex);
}

static void AsyncQueue_Drain (asyncqueue_t *queue)
{
SDL_LockMutex (queue->mutex);
while (queue->head != queue->tail)
{
asyncproc_t *proc = &queue->procs[(queue->head++) & (queue->capacity - 1)];
proc->func (proc->param);
SDL_CondSignal (queue->notfull);
}
SDL_UnlockMutex (queue->mutex);
}

static void AsyncQueue_Destroy (asyncqueue_t *queue)
{
if (!queue->mutex)
return;

SDL_LockMutex (queue->mutex);
queue->teardown = true;
SDL_UnlockMutex (queue->mutex);
SDL_CondBroadcast (queue->notfull);

AsyncQueue_Drain (queue);

SDL_DestroyCond (queue->notfull);
SDL_DestroyMutex (queue->mutex);
memset (queue, 0, sizeof (*queue));
}

void Host_InvokeOnMainThread (void (*func) (void *param), void *param)
{
AsyncQueue_Push (&async_queue, func, param);
}

//==============================================================================
//
// Host Frame
Expand Down Expand Up @@ -914,6 +1016,9 @@ void _Host_Frame (double time)
accumtime += host_netinterval?CLAMP(0.0, time, 0.2):0.0; //for renderer/server isolation
Host_AdvanceTime (time);

// run async procs
AsyncQueue_Drain (&async_queue);

// get new key events
Key_UpdateForDest ();
IN_UpdateInputMode ();
Expand Down Expand Up @@ -1113,6 +1218,7 @@ void Host_Init (void)
Mod_Init ();
NET_Init ();
SV_Init ();
AsyncQueue_Init (&async_queue, 1024);

Con_Printf ("Exe: " __TIME__ " " __DATE__ " (%s %d-bit)\n", SDL_GetPlatform (), (int)sizeof(void*)*8);
Con_Printf ("%4.1f megabyte heap\n", host_parms->memsize/ (1024*1024.0));
Expand All @@ -1126,12 +1232,6 @@ void Host_Init (void)
V_Init ();
Chase_Init ();
M_Init ();
ExtraMaps_Init (); //johnfitz
Modlist_Init (); //johnfitz
DemoList_Init (); //ericw
SaveList_Init ();
SkyList_Init ();
M_CheckMods ();
VID_Init ();
IN_Init ();
TexMgr_Init (); //johnfitz
Expand All @@ -1143,6 +1243,12 @@ void Host_Init (void)
BGM_Init();
Sbar_Init ();
CL_Init ();
Modlist_Init (); //johnfitz
ExtraMaps_Init (); //johnfitz
DemoList_Init (); //ericw
SaveList_Init ();
SkyList_Init ();
M_CheckMods ();
}

LOC_Init (); // for 2021 rerelease support.
Expand Down Expand Up @@ -1194,9 +1300,14 @@ void Host_Shutdown(void)
// keep Con_Printf from trying to update the screen
scr_disabled_for_loading = true;

AsyncQueue_Destroy (&async_queue);

Host_ShutdownSave ();
Host_WriteConfiguration ();

// stop downloads before shutting down networking
Modlist_ShutDown ();

NET_Shutdown ();

if (cls.state != ca_dedicated)
Expand Down
Loading

0 comments on commit 7ab6d8a

Please sign in to comment.