FIXME: lookupnoadd the token to speed search?
============
*/
+extern hook_t *csqc_concmd;
+
void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qboolean lockmutex)
{
int oldpos;
{
if (!strcasecmp(cmd->argv[0], func->name))
{
- if (func->csqcfunc && CL_VM_ConsoleCommand(text)) //[515]: csqc
+ if (func->csqcfunc && Hook_Call(csqc_concmd, text)->bval) //[515]: csqc
goto done;
break;
}
return true;
}
-qboolean CL_VM_ConsoleCommand (const char *cmd)
+hook_t *csqc_concmd;
+
+qboolean CL_VM_ConsoleCommand (hook_val_t *arg)
{
prvm_prog_t *prog = CLVM_prog;
int restorevm_tempstringsbuf_cursize;
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
- PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, cmd);
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, arg->str);
// optional entity parameter for self (EXT_ENTITYPARAM)
PRVM_G_INT(OFS_PARM1) = cl.csqc_server2csqcentitynumber[cl.playerentity];
prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_ConsoleCommand), "QC function CSQC_ConsoleCommand is missing");
void CL_VM_UpdateIntermissionState(int intermission);
void CL_VM_UpdateShowingScoresState(int showingscores);
qboolean CL_VM_InputEvent(int eventtype, float x, float y);
-qboolean CL_VM_ConsoleCommand(const char *cmd);
+qboolean CL_VM_ConsoleCommand(hook_val_t *arg);
void CL_VM_UpdateDmgGlobals(int dmg_take, int dmg_save, vec3_t dmg_origin);
void CL_VM_UpdateIntermissionState(int intermission);
qboolean CL_VM_Event_Sound(int sound_num, float volume, int channel, float attenuation, int ent, vec3_t pos, int flags, float speed);
if (r->depthisrenderbuffer)
r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
else
- r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+ r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
}
r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
}
--- /dev/null
+/*
+Copyright (C) 2020 Cloudwalk
+
+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.
+
+*/
+
+#include "quakedef.h"
+#include "hook.h"
+
+mempool_t *hooks;
+
+hook_t *_Hook_Register(hook_t *hook, const char *name, void *func, unsigned int argc)
+{
+ if (hook) {
+ Con_Printf("Hook %s already registered\n",hook->name);
+ } else {
+ hook = (hook_t *)Mem_Alloc(hooks, sizeof(hook_t));
+ hook->name = Mem_Alloc(hooks, strlen(name) + 1);
+ hook->arg = Mem_Alloc(hooks, sizeof(hook_val_t) * argc);
+
+ memcpy(hook->name, name, strlen(name) + 1);
+ hook->func = func;
+ hook->argc = argc;
+ }
+ return hook;
+}
+
+// Needs NULL pad to know when va_list ends.
+hook_val_t *_Hook_Call(hook_t *hook, ... )
+{
+ uintptr_t arg_ptr; // Align to platform size
+ va_list arg_list;
+ unsigned int i = 0;
+
+ if(!hook)
+ return (hook_val_t *)NULL;
+
+ va_start(arg_list, hook);
+
+ arg_ptr = va_arg(arg_list,intptr_t);
+
+ if((void *)arg_ptr && !hook->argc)
+ goto overflow;
+
+ // Loop until we encounter that NULL pad, but stop if we overflow.
+ while ((void *)arg_ptr != NULL && i != hook->argc)
+ {
+ if (i > hook->argc)
+ goto overflow;
+ hook->arg[i].val = arg_ptr;
+ arg_ptr = va_arg(arg_list,intptr_t);
+ i++;
+ }
+
+ va_end(arg_list);
+
+ // Should be fairly obvious why it's bad if args don't match
+ if(i != hook->argc)
+ goto underflow;
+ // Call it
+ hook->ret.uval = (uintptr_t)hook->func(hook->arg);
+
+ if (hook->ret.val)
+ return &hook->ret;
+ return (hook_val_t *)NULL;
+
+underflow:
+ Sys_Error("Hook_Call: Attempt to call hook '%s' with incorrect number of arguments. Got %i, expected %i\n", hook->name, i, hook->argc);
+overflow:
+ Sys_Error("Hook_Call: Stack overflow calling hook '%s' (argc = %u)\n", hook->name, hook->argc);
+
+}
+
+void Hook_Init(void)
+{
+ hooks = Mem_AllocPool("hooks",0,NULL);
+ return;
+}
\ No newline at end of file
--- /dev/null
+/*
+Copyright (C) 2020 Cloudwalk
+
+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.
+
+*/
+
+// hook.h
+
+#ifndef HOOK_H
+#define HOOK_H
+
+typedef union hook_val_s
+{
+ intptr_t val;
+ uintptr_t uval;
+ void *ptr;
+ char *str;
+ int ival;
+ unsigned int uival;
+ double fval;
+ qboolean bval;
+} hook_val_t;
+
+typedef struct hook_s
+{
+ char *name;
+ hook_val_t *(*func)(hook_val_t *hook);
+ hook_val_t *arg;
+ hook_val_t ret;
+ unsigned int argc;
+} hook_t;
+
+hook_t *_Hook_Register(hook_t *hook, const char *name, void *func, unsigned int argc);
+hook_val_t *_Hook_Call(hook_t *hook, ... );
+void Hook_Init(void);
+void Hook_Shutdown(void);
+
+// For your convenience
+#define Hook_Register(hook, func, argc) _Hook_Register(hook, #hook, func, argc)
+#define Hook_Call(hook, ... ) _Hook_Call(hook, __VA_ARGS__, NULL)
+
+#endif
\ No newline at end of file
}
}
+extern hook_t *csqc_concmd;
+
/*
====================
Host_Init
// initialize memory subsystem cvars/commands
Memory_Init_Commands();
+ Hook_Init();
+ csqc_concmd = Hook_Register(csqc_concmd,CL_VM_ConsoleCommand,1);
// initialize console and logging and its cvars/commands
Con_Init();
gl_rsurf.o \
gl_textures.o \
hmac.o \
+ hook.o \
host.o \
host_cmd.o \
image.o \
else
vertex3f = model->surfmesh.data_vertex3f;
for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
- Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceLineTriangleMeshFloat(trace, start, end, surface->num_triangles, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
if (freevertex3f)
Mem_Free(freevertex3f);
}
Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
- Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, surface->num_triangles, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
if (vertex3f != vertex3fbuf)
Mem_Free(vertex3f);
}
#ifndef QTYPES_H
#define QTYPES_H
+#include <stdint.h>
+
#ifndef __cplusplus
#ifdef _MSC_VER
typedef enum {false, true} bool;
#include "sys.h"
#include "vid.h"
#include "mathlib.h"
+#include "hook.h"
#include "r_textures.h"
#include "quakedef.h"
#include "taskqueue.h"
-cvar_t taskqueue_minthreads = {CVAR_CLIENT | CVAR_SERVER | CVAR_SAVE, "taskqueue_minthreads", "4", "minimum number of threads to keep active for executing tasks"};
+cvar_t taskqueue_minthreads = {CVAR_CLIENT | CVAR_SERVER | CVAR_SAVE, "taskqueue_minthreads", "0", "minimum number of threads to keep active for executing tasks"};
cvar_t taskqueue_maxthreads = {CVAR_CLIENT | CVAR_SERVER | CVAR_SAVE, "taskqueue_maxthreads", "32", "maximum number of threads to start up as needed based on task count"};
cvar_t taskqueue_tasksperthread = {CVAR_CLIENT | CVAR_SERVER | CVAR_SAVE, "taskqueue_tasksperthread", "4000", "expected amount of work that a single thread can do in a frame - the number of threads being used depends on the average workload in recent frames"};
int _Thread_AtomicGet(Thread_Atomic *a, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p atomic get at %s:%i\n", a, v, filename, fileline);
+ Sys_PrintfToTerminal("%p atomic get at %s:%i\n", a, filename, fileline);
#endif
return SDL_AtomicGet((SDL_atomic_t *)a);
}
void _Thread_AtomicIncRef(Thread_Atomic *a, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p atomic incref %s:%i\n", lock, filename, fileline);
+ Sys_PrintfToTerminal("%p atomic incref %s:%i\n", a, filename, fileline);
#endif
SDL_AtomicIncRef((SDL_atomic_t *)a);
}
qboolean _Thread_AtomicDecRef(Thread_Atomic *a, const char *filename, int fileline)
{
#ifdef THREADDEBUG
- Sys_PrintfToTerminal("%p atomic decref %s:%i\n", lock, filename, fileline);
+ Sys_PrintfToTerminal("%p atomic decref %s:%i\n", a, filename, fileline);
#endif
return SDL_AtomicDecRef((SDL_atomic_t *)a) != SDL_FALSE;
}