<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
- <string>darkplaces-sdl</string>
+ <string>darkplaces-osx-sdl</string>
<key>CFBundleIconFile</key>
<string>Darkplaces</string>
<key>CFBundlePackageType</key>
{
LOAD_FORMATSPECIFIC_AVI();
if(!format->canseek)
- Host_Error("SCR_CaptureVideo_RIFF_IndexEntry called on non-seekable AVI");
+ Sys_Error("SCR_CaptureVideo_RIFF_IndexEntry called on non-seekable AVI");
if (format->riffstacklevel != 2)
Sys_Error("SCR_Capturevideo_RIFF_IndexEntry: RIFF stack level is %i (should be 2)\n", format->riffstacklevel);
fs_offset_t pos, sz;
if(!format->canseek)
- Host_Error("SCR_CaptureVideo_RIFF_MakeIxChunk called on non-seekable AVI");
+ Sys_Error("SCR_CaptureVideo_RIFF_MakeIxChunk called on non-seekable AVI");
if(*masteridx_count >= AVI_MASTER_INDEX_SIZE)
return;
blockb = b[0];
*out = cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
}
- if ((y & 1) == 0)
+ if ((y & 1) == 0 && y/2 < height/2) // if h is odd, this skips the last row
{
// 2x2 Cr and Cb planes
int inpitch = width*4;
}
}
-void SCR_CaptureVideo_Avi_EndVideo(void)
+static void SCR_CaptureVideo_Avi_EndVideo(void)
{
LOAD_FORMATSPECIFIC_AVI();
Mem_Free(format);
}
-void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
+static void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
{
LOAD_FORMATSPECIFIC_AVI();
int x;
{
int n0, n1;
- n0 = paintbuffer[i].sample[0];
+ n0 = paintbuffer[i].sample[0] * 32768.0f;
n0 = bound(-32768, n0, 32767);
out_ptr[0] = (unsigned char)n0;
out_ptr[1] = (unsigned char)(n0 >> 8);
- n1 = paintbuffer[i].sample[1];
+ n1 = paintbuffer[i].sample[1] * 32768.0f;
n1 = bound(-32768, n1, 32767);
out_ptr[2] = (unsigned char)n1;
out_ptr[3] = (unsigned char)(n1 >> 8);
int n, d;
unsigned int i;
double aspect;
+ char vabuf[1024];
aspect = vid.width / (vid.height * vid_pixelheight.value);
cls.capturevideo.format = CAPTUREVIDEOFORMAT_AVI_I420;
cls.capturevideo.formatextension = "avi";
- cls.capturevideo.videofile = FS_OpenRealFile(va("%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
+ cls.capturevideo.videofile = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
cls.capturevideo.endvideo = SCR_CaptureVideo_Avi_EndVideo;
cls.capturevideo.videoframes = SCR_CaptureVideo_Avi_VideoFrames;
cls.capturevideo.soundframe = SCR_CaptureVideo_Avi_SoundFrame;
static dllhandle_t og_dll = NULL, vo_dll = NULL, ve_dll = NULL, th_dll = NULL;
-qboolean SCR_CaptureVideo_Ogg_OpenLibrary(void)
+static qboolean SCR_CaptureVideo_Ogg_OpenLibrary(void)
{
const char* dllnames_og [] =
{
format->videopage.len = pg.header_len + pg.body_len;
format->videopage.time = qtheora_granule_time(&format->ts, qogg_page_granulepos(&pg));
if(format->videopage.len > sizeof(format->videopage.data))
- Host_Error("video page too long");
+ Sys_Error("video page too long");
memcpy(format->videopage.data, pg.header, pg.header_len);
memcpy(format->videopage.data + pg.header_len, pg.body, pg.body_len);
}
format->audiopage.len = pg.header_len + pg.body_len;
format->audiopage.time = qvorbis_granule_time(&format->vd, qogg_page_granulepos(&pg));
if(format->audiopage.len > sizeof(format->audiopage.data))
- Host_Error("audio page too long");
+ Sys_Error("audio page too long");
memcpy(format->audiopage.data, pg.header, pg.header_len);
memcpy(format->audiopage.data + pg.header_len, pg.body, pg.body_len);
}
while (1) {
int result = qogg_stream_flush (&format->to, &pg);
if (result < 0)
- fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
+ fprintf (stderr, "Internal Ogg library error.\n"); // TODO Sys_Error
if (result <= 0)
break;
FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
while (1) {
int result = qogg_stream_flush (&format->vo, &pg);
if (result < 0)
- fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
+ fprintf (stderr, "Internal Ogg library error.\n"); // TODO Sys_Error
if (result <= 0)
break;
FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
b += 4;
}
- if((y & 1) == 0)
+ if ((y & 1) == 0 && y/2 < h/2) // if h is odd, this skips the last row
{
for(b = cls.capturevideo.outbuffer + (h-2-y)*w*4, x = 0; x < w/2; ++x)
{
{
float *b = vorbis_buffer[map[j]];
for(i = 0; i < length; ++i)
- b[i] = paintbuffer[i].sample[j] / 32768.0f;
+ b[i] = paintbuffer[i].sample[j];
}
qvorbis_analysis_wrote(&format->vd, length);
void SCR_CaptureVideo_Ogg_BeginVideo(void)
{
+ char vabuf[1024];
cls.capturevideo.format = CAPTUREVIDEOFORMAT_OGG_VORBIS_THEORA;
cls.capturevideo.formatextension = "ogv";
- cls.capturevideo.videofile = FS_OpenRealFile(va("%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
+ cls.capturevideo.videofile = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
cls.capturevideo.endvideo = SCR_CaptureVideo_Ogg_EndVideo;
cls.capturevideo.videoframes = SCR_CaptureVideo_Ogg_VideoFrames;
cls.capturevideo.soundframe = SCR_CaptureVideo_Ogg_SoundFrame;
{
int result = qogg_stream_flush (&format->to, &pg);
if (result < 0)
- fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
+ fprintf (stderr, "Internal Ogg library error.\n"); // TODO Sys_Error
if (result <= 0)
break;
FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
{
int result = qogg_stream_flush (&format->vo, &pg);
if (result < 0)
- fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
+ fprintf (stderr, "Internal Ogg library error.\n"); // TODO Sys_Error
if (result <= 0)
break;
FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
*/
#include "quakedef.h"
+#include "cdaudio.h"
void CDAudio_SysEject (void)
#include "cdaudio.h"
#include "sound.h"
-// Prototypes of the system dependent functions
-extern void CDAudio_SysEject (void);
-extern void CDAudio_SysCloseDoor (void);
-extern int CDAudio_SysGetAudioDiskInfo (void);
-extern float CDAudio_SysGetVolume (void);
-extern void CDAudio_SysSetVolume (float volume);
-extern int CDAudio_SysPlay (int track);
-extern int CDAudio_SysStop (void);
-extern int CDAudio_SysPause (void);
-extern int CDAudio_SysResume (void);
-extern int CDAudio_SysUpdate (void);
-extern void CDAudio_SysInit (void);
-extern int CDAudio_SysStartup (void);
-extern void CDAudio_SysShutdown (void);
-
// used by menu to ghost CD audio slider
cvar_t cdaudioinitialized = {CVAR_READONLY,"cdaudioinitialized","0","indicates if CD Audio system is active"};
cvar_t cdaudio = {CVAR_SAVE,"cdaudio","1","CD playing mode (0 = never access CD drive, 1 = play CD tracks if no replacement available, 2 = play fake tracks if no CD track available, 3 = play only real CD tracks, 4 = play real CD tracks even instead of named fake tracks)"};
return 0;
}
-qboolean CDAudio_Play_real (int track, qboolean looping, qboolean complain)
+static qboolean CDAudio_Play_real (int track, qboolean looping, qboolean complain)
{
if(track < 1)
{
}
if (FS_FileExists(filename) && (sfx = S_PrecacheSound (filename, false, false)))
{
- faketrack = S_StartSound_StartPosition_Flags (-1, 0, sfx, vec3_origin, cdvolume, 0, startposition, (looping ? CHANNELFLAG_FORCELOOP : 0) | CHANNELFLAG_FULLVOLUME | CHANNELFLAG_LOCALSOUND);
+ faketrack = S_StartSound_StartPosition_Flags (-1, 0, sfx, vec3_origin, cdvolume, 0, startposition, (looping ? CHANNELFLAG_FORCELOOP : 0) | CHANNELFLAG_FULLVOLUME | CHANNELFLAG_LOCALSOUND, 1.0f);
if (faketrack != -1)
{
if(track >= 1)
Con_Printf("cd info - prints basic disc information (number of tracks, currently playing track, volume level)\n");
}
-void CDAudio_SetVolume (float newvol)
+static void CDAudio_SetVolume (float newvol)
{
// If the volume hasn't changed
if (newvol == cdvolume)
void CDAudio_Update(void);
float CDAudio_GetPosition(void);
void CDAudio_StartPlaylist(qboolean resume);
+
+// Prototypes of the system dependent functions
+void CDAudio_SysEject (void);
+void CDAudio_SysCloseDoor (void);
+int CDAudio_SysGetAudioDiskInfo (void);
+float CDAudio_SysGetVolume (void);
+void CDAudio_SysSetVolume (float volume);
+int CDAudio_SysPlay (int track);
+int CDAudio_SysStop (void);
+int CDAudio_SysPause (void);
+int CDAudio_SysResume (void);
+int CDAudio_SysUpdate (void);
+void CDAudio_SysInit (void);
+int CDAudio_SysStartup (void);
+void CDAudio_SysShutdown (void);
dp_model_t *CL_GetModelFromEdict(prvm_edict_t *ed)
{
+ prvm_prog_t *prog = CLVM_prog;
if (!ed || ed->priv.server->free)
return NULL;
return CL_GetModelByIndex((int)PRVM_clientedictfloat(ed, modelindex));
void CL_LinkEdict(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = CLVM_prog;
vec3_t mins, maxs;
if (ent == prog->edicts)
int CL_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
{
+ prvm_prog_t *prog = CLVM_prog;
if (passedict)
{
int dphitcontentsmask = (int)PRVM_clientedictfloat(passedict, dphitcontentsmask);
*/
trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
{
+ prvm_prog_t *prog = CLVM_prog;
int i, bodysupercontents;
int passedictprog;
prvm_edict_t *traceowner, *touch;
trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities, qboolean hitsurfaces)
#endif
{
+ prvm_prog_t *prog = CLVM_prog;
int i, bodysupercontents;
int passedictprog;
prvm_edict_t *traceowner, *touch;
trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities)
#endif
{
+ prvm_prog_t *prog = CLVM_prog;
vec3_t hullmins, hullmaxs;
int i, bodysupercontents;
int passedictprog;
#endif
return cliptrace;
}
+
+/*
+==================
+CL_Cache_TraceLine
+==================
+*/
+#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
+trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t pEnd, int type, int hitsupercontentsmask)
+#else
+trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int type, int hitsupercontentsmask)
+#endif
+{
+ prvm_prog_t *prog = CLVM_prog;
+ int i;
+ prvm_edict_t *touch;
+ trace_t trace;
+ // bounding box of entire move area
+ vec3_t clipboxmins, clipboxmaxs;
+ // start and end origin of move
+ vec3_t clipstart, clipend;
+ // trace results
+ trace_t cliptrace;
+ // matrices to transform into/out of other entity's space
+ matrix4x4_t matrix, imatrix;
+ // model of other entity
+ dp_model_t *model;
+ // list of entities to test for collisions
+ int numtouchedicts;
+ static prvm_edict_t *touchedicts[MAX_EDICTS];
+#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
+ vec3_t end;
+ vec_t len = 0;
+
+ if(collision_endposnudge.value > 0 && !VectorCompare(start, pEnd))
+ {
+ // TRICK: make the trace 1 qu longer!
+ VectorSubtract(pEnd, start, end);
+ len = VectorNormalizeLength(end);
+ VectorMA(pEnd, collision_endposnudge.value, end, end);
+ }
+ else
+ VectorCopy(pEnd, end);
+#endif
+
+ VectorCopy(start, clipstart);
+ VectorCopy(end, clipend);
+#if COLLISIONPARANOID >= 3
+ Con_Printf("move(%f %f %f,%f %f %f)", clipstart[0], clipstart[1], clipstart[2], clipend[0], clipend[1], clipend[2]);
+#endif
+
+ // clip to world
+ Collision_Cache_ClipLineToWorldSurfaces(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask);
+ cliptrace.bmodelstartsolid = cliptrace.startsolid;
+ if (cliptrace.startsolid || cliptrace.fraction < 1)
+ cliptrace.ent = prog ? prog->edicts : NULL;
+ if (type == MOVE_WORLDONLY)
+ goto finished;
+
+ // create the bounding box of the entire move
+ for (i = 0;i < 3;i++)
+ {
+ clipboxmins[i] = min(clipstart[i], cliptrace.endpos[i]) - 1;
+ clipboxmaxs[i] = max(clipstart[i], cliptrace.endpos[i]) + 1;
+ }
+
+ // if the passedict is world, make it NULL (to avoid two checks each time)
+ // this checks prog because this function is often called without a CSQC
+ // VM context
+
+ // collide against network entities
+ for (i = 0;i < cl.num_brushmodel_entities;i++)
+ {
+ entity_render_t *ent = &cl.entities[cl.brushmodel_entities[i]].render;
+ if (!BoxesOverlap(clipboxmins, clipboxmaxs, ent->mins, ent->maxs))
+ continue;
+ Collision_Cache_ClipLineToGenericEntitySurfaces(&trace, ent->model, &ent->matrix, &ent->inversematrix, start, end, hitsupercontentsmask);
+ Collision_CombineTraces(&cliptrace, &trace, NULL, true);
+ }
+
+ // clip to entities
+ // because this uses World_EntitiestoBox, we know all entity boxes overlap
+ // the clip region, so we can skip culling checks in the loop below
+ // note: if prog is NULL then there won't be any linked entities
+ numtouchedicts = 0;
+ if (prog != NULL)
+ {
+ numtouchedicts = World_EntitiesInBox(&cl.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ if (numtouchedicts > MAX_EDICTS)
+ {
+ // this never happens
+ Con_Printf("CL_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
+ numtouchedicts = MAX_EDICTS;
+ }
+ }
+ for (i = 0;i < numtouchedicts;i++)
+ {
+ touch = touchedicts[i];
+ // might interact, so do an exact clip
+ // only hit entity models, not collision shapes
+ model = CL_GetModelFromEdict(touch);
+ if (!model)
+ continue;
+ // animated models are too slow to collide against and can't be cached
+ if (touch->priv.server->frameblend || touch->priv.server->skeleton.relativetransforms)
+ continue;
+ if (type == MOVE_NOMONSTERS && PRVM_clientedictfloat(touch, solid) != SOLID_BSP)
+ continue;
+ Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_clientedictvector(touch, origin)[0], PRVM_clientedictvector(touch, origin)[1], PRVM_clientedictvector(touch, origin)[2], PRVM_clientedictvector(touch, angles)[0], PRVM_clientedictvector(touch, angles)[1], PRVM_clientedictvector(touch, angles)[2], 1);
+ Matrix4x4_Invert_Simple(&imatrix, &matrix);
+ Collision_Cache_ClipLineToGenericEntitySurfaces(&trace, model, &matrix, &imatrix, clipstart, clipend, hitsupercontentsmask);
+ Collision_CombineTraces(&cliptrace, &trace, (void *)touch, PRVM_clientedictfloat(touch, solid) == SOLID_BSP);
+ }
+
+finished:
+#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
+ if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
+ Collision_ShortenTrace(&cliptrace, len / (len + collision_endposnudge.value), pEnd);
+#endif
+ return cliptrace;
+}
+
trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities);
trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities, qboolean hitsurfaces);
trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities);
+trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int type, int hitsupercontentsmask);
#define CL_PointSuperContents(point) (CL_TracePoint((point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0, true, false, NULL, false).startsupercontents)
#endif
extern cvar_t cl_capturevideo;
int old_vsync = 0;
-void CL_FinishTimeDemo (void);
+static void CL_FinishTimeDemo (void);
/*
==============================================================================
if (cls.timedemo)
CL_FinishTimeDemo ();
- if (COM_CheckParm("-demo") || COM_CheckParm("-capturedemo"))
- Host_Quit_f();
+ if (!cls.demostarting) // only quit if not starting another demo
+ if (COM_CheckParm("-demo") || COM_CheckParm("-capturedemo"))
+ Host_Quit_f();
}
CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
-====================
+#====================
*/
void CL_WriteDemoMessage (sizebuf_t *message)
{
// restart the demo recording
cls.demofile = FS_OpenRealFile(cls.demoname, "wb", false);
if(!cls.demofile)
- Host_Error("failed to reopen the demo file");
+ Sys_Error("failed to reopen the demo file");
FS_Printf(cls.demofile, "%i\n", cls.forcetrack);
}
}
// get the next message
- FS_Read(cls.demofile, &net_message.cursize, 4);
- net_message.cursize = LittleLong(net_message.cursize);
- if(net_message.cursize & DEMOMSG_CLIENT_TO_SERVER) // This is a client->server message! Ignore for now!
+ FS_Read(cls.demofile, &cl_message.cursize, 4);
+ cl_message.cursize = LittleLong(cl_message.cursize);
+ if(cl_message.cursize & DEMOMSG_CLIENT_TO_SERVER) // This is a client->server message! Ignore for now!
{
// skip over demo packet
- FS_Seek(cls.demofile, 12 + (net_message.cursize & (~DEMOMSG_CLIENT_TO_SERVER)), SEEK_CUR);
+ FS_Seek(cls.demofile, 12 + (cl_message.cursize & (~DEMOMSG_CLIENT_TO_SERVER)), SEEK_CUR);
continue;
}
- if (net_message.cursize > net_message.maxsize)
- Host_Error("Demo message (%i) > net_message.maxsize (%i)", net_message.cursize, net_message.maxsize);
+ if (cl_message.cursize > cl_message.maxsize)
+ {
+ Con_Printf("Demo message (%i) > cl_message.maxsize (%i)", cl_message.cursize, cl_message.maxsize);
+ cl_message.cursize = 0;
+ CL_Disconnect();
+ return;
+ }
VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
for (i = 0;i < 3;i++)
{
cl.mviewangles[0][i] = LittleFloat(f);
}
- if (FS_Read(cls.demofile, net_message.data, net_message.cursize) == net_message.cursize)
+ if (FS_Read(cls.demofile, cl_message.data, cl_message.cursize) == cl_message.cursize)
{
- MSG_BeginReading();
+ MSG_BeginReading(&cl_message);
CL_ParseServerMessage();
if (cls.signon != SIGNONS)
}
// write a disconnect message to the demo file
- // LordHavoc: don't replace the net_message when doing this
+ // LordHavoc: don't replace the cl_message when doing this
buf.data = bufdata;
buf.maxsize = sizeof(bufdata);
SZ_Clear(&buf);
{
int c, track;
char name[MAX_OSPATH];
+ char vabuf[1024];
c = Cmd_Argc();
if (c != 2 && c != 3 && c != 4)
// start the map up
if (c > 2)
- Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
+ Cmd_ExecuteString ( va(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(2)), src_command, false);
// open the demo file
Con_Printf("recording to %s.\n", name);
char name[MAX_QPATH];
int c;
qboolean neg = false;
+ qfile_t *f;
if (Cmd_Argc() != 2)
{
return;
}
+ // open the demo file
+ strlcpy (name, Cmd_Argv(1), sizeof (name));
+ FS_DefaultExtension (name, ".dem", sizeof (name));
+ f = FS_OpenVirtualFile(name, false);
+ if (!f)
+ {
+ Con_Printf("ERROR: couldn't open %s.\n", name);
+ cls.demonum = -1; // stop demo loop
+ return;
+ }
+
+ cls.demostarting = true;
+
// disconnect from server
CL_Disconnect ();
Host_ShutdownServer ();
// update networking ports (this is mainly just needed at startup)
NetConn_UpdateSockets();
- // open the demo file
- strlcpy (name, Cmd_Argv(1), sizeof (name));
- FS_DefaultExtension (name, ".dem", sizeof (name));
cls.protocol = PROTOCOL_QUAKE;
Con_Printf("Playing demo %s.\n", name);
- cls.demofile = FS_OpenVirtualFile(name, false);
- if (!cls.demofile)
- {
- Con_Print("ERROR: couldn't open.\n");
- cls.demonum = -1; // stop demo loop
- return;
- }
+ cls.demofile = f;
strlcpy(cls.demoname, name, sizeof(cls.demoname));
cls.demoplayback = true;
if (neg)
cls.forcetrack = -cls.forcetrack;
+
+ cls.demostarting = false;
+}
+
+typedef struct
+{
+ int frames;
+ double time, totalfpsavg;
+ double fpsmin, fpsavg, fpsmax;
+}
+benchmarkhistory_t;
+static size_t doublecmp_offset;
+static int doublecmp_withoffset(const void *a_, const void *b_)
+{
+ const double *a = (const double *) ((const char *) a_ + doublecmp_offset);
+ const double *b = (const double *) ((const char *) b_ + doublecmp_offset);
+ if(*a > *b)
+ return +1;
+ if(*a < *b)
+ return -1;
+ return 0;
}
/*
====================
*/
-void CL_FinishTimeDemo (void)
+static void CL_FinishTimeDemo (void)
{
int frames;
int i;
double time, totalfpsavg;
double fpsmin, fpsavg, fpsmax; // report min/avg/max fps
static int benchmark_runs = 0;
+ char vabuf[1024];
cls.timedemo = false;
i = COM_CheckParm("-benchmarkruns");
if(i && i + 1 < com_argc)
{
+ static benchmarkhistory_t *history = NULL;
+ if(!history)
+ history = (benchmarkhistory_t *)Z_Malloc(sizeof(*history) * atoi(com_argv[i + 1]));
+
+ history[benchmark_runs - 1].frames = frames;
+ history[benchmark_runs - 1].time = time;
+ history[benchmark_runs - 1].totalfpsavg = totalfpsavg;
+ history[benchmark_runs - 1].fpsmin = fpsmin;
+ history[benchmark_runs - 1].fpsavg = fpsavg;
+ history[benchmark_runs - 1].fpsmax = fpsmax;
+
if(atoi(com_argv[i + 1]) > benchmark_runs)
{
// restart the benchmark
- Cbuf_AddText(va("timedemo %s\n", cls.demoname));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "timedemo %s\n", cls.demoname));
// cannot execute here
}
else
+ {
+ // print statistics
+ int first = COM_CheckParm("-benchmarkruns_skipfirst") ? 1 : 0;
+ if(benchmark_runs > first)
+ {
+#define DO_MIN(f) \
+ for(i = first; i < benchmark_runs; ++i) if((i == first) || (history[i].f < f)) f = history[i].f
+
+#define DO_MAX(f) \
+ for(i = first; i < benchmark_runs; ++i) if((i == first) || (history[i].f > f)) f = history[i].f
+
+#define DO_MED(f) \
+ doublecmp_offset = (char *)&history->f - (char *)history; \
+ qsort(history + first, benchmark_runs - first, sizeof(*history), doublecmp_withoffset); \
+ if((first + benchmark_runs) & 1) \
+ f = history[(first + benchmark_runs - 1) / 2].f; \
+ else \
+ f = (history[(first + benchmark_runs - 2) / 2].f + history[(first + benchmark_runs) / 2].f) / 2
+
+ DO_MIN(frames);
+ DO_MAX(time);
+ DO_MIN(totalfpsavg);
+ DO_MIN(fpsmin);
+ DO_MIN(fpsavg);
+ DO_MIN(fpsmax);
+ Con_Printf("MIN: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
+
+ DO_MED(frames);
+ DO_MED(time);
+ DO_MED(totalfpsavg);
+ DO_MED(fpsmin);
+ DO_MED(fpsavg);
+ DO_MED(fpsmax);
+ Con_Printf("MED: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
+
+ DO_MAX(frames);
+ DO_MIN(time);
+ DO_MAX(totalfpsavg);
+ DO_MAX(fpsmin);
+ DO_MAX(fpsavg);
+ DO_MAX(fpsmax);
+ Con_Printf("MAX: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
+ }
+ Z_Free(history);
+ history = NULL;
Host_Quit_f();
+ }
}
else
Host_Quit_f();
#include "quakedef.h"
#include "csprogs.h"
+#include "thread.h"
/*
===============================================================================
-void KeyDown (kbutton_t *b)
+static void KeyDown (kbutton_t *b)
{
int k;
const char *c;
b->state |= 1 + 2; // down + impulse down
}
-void KeyUp (kbutton_t *b)
+static void KeyUp (kbutton_t *b)
{
int k;
const char *c;
b->state |= 4; // impulse up
}
-void IN_KLookDown (void) {KeyDown(&in_klook);}
-void IN_KLookUp (void) {KeyUp(&in_klook);}
-void IN_MLookDown (void) {KeyDown(&in_mlook);}
-void IN_MLookUp (void)
+static void IN_KLookDown (void) {KeyDown(&in_klook);}
+static void IN_KLookUp (void) {KeyUp(&in_klook);}
+static void IN_MLookDown (void) {KeyDown(&in_mlook);}
+static void IN_MLookUp (void)
{
KeyUp(&in_mlook);
if ( !(in_mlook.state&1) && lookspring.value)
V_StartPitchDrift();
}
-void IN_UpDown(void) {KeyDown(&in_up);}
-void IN_UpUp(void) {KeyUp(&in_up);}
-void IN_DownDown(void) {KeyDown(&in_down);}
-void IN_DownUp(void) {KeyUp(&in_down);}
-void IN_LeftDown(void) {KeyDown(&in_left);}
-void IN_LeftUp(void) {KeyUp(&in_left);}
-void IN_RightDown(void) {KeyDown(&in_right);}
-void IN_RightUp(void) {KeyUp(&in_right);}
-void IN_ForwardDown(void) {KeyDown(&in_forward);}
-void IN_ForwardUp(void) {KeyUp(&in_forward);}
-void IN_BackDown(void) {KeyDown(&in_back);}
-void IN_BackUp(void) {KeyUp(&in_back);}
-void IN_LookupDown(void) {KeyDown(&in_lookup);}
-void IN_LookupUp(void) {KeyUp(&in_lookup);}
-void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
-void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
-void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
-void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
-void IN_MoverightDown(void) {KeyDown(&in_moveright);}
-void IN_MoverightUp(void) {KeyUp(&in_moveright);}
-
-void IN_SpeedDown(void) {KeyDown(&in_speed);}
-void IN_SpeedUp(void) {KeyUp(&in_speed);}
-void IN_StrafeDown(void) {KeyDown(&in_strafe);}
-void IN_StrafeUp(void) {KeyUp(&in_strafe);}
-
-void IN_AttackDown(void) {KeyDown(&in_attack);}
-void IN_AttackUp(void) {KeyUp(&in_attack);}
-
-void IN_UseDown(void) {KeyDown(&in_use);}
-void IN_UseUp(void) {KeyUp(&in_use);}
+static void IN_UpDown(void) {KeyDown(&in_up);}
+static void IN_UpUp(void) {KeyUp(&in_up);}
+static void IN_DownDown(void) {KeyDown(&in_down);}
+static void IN_DownUp(void) {KeyUp(&in_down);}
+static void IN_LeftDown(void) {KeyDown(&in_left);}
+static void IN_LeftUp(void) {KeyUp(&in_left);}
+static void IN_RightDown(void) {KeyDown(&in_right);}
+static void IN_RightUp(void) {KeyUp(&in_right);}
+static void IN_ForwardDown(void) {KeyDown(&in_forward);}
+static void IN_ForwardUp(void) {KeyUp(&in_forward);}
+static void IN_BackDown(void) {KeyDown(&in_back);}
+static void IN_BackUp(void) {KeyUp(&in_back);}
+static void IN_LookupDown(void) {KeyDown(&in_lookup);}
+static void IN_LookupUp(void) {KeyUp(&in_lookup);}
+static void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
+static void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
+static void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
+static void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
+static void IN_MoverightDown(void) {KeyDown(&in_moveright);}
+static void IN_MoverightUp(void) {KeyUp(&in_moveright);}
+
+static void IN_SpeedDown(void) {KeyDown(&in_speed);}
+static void IN_SpeedUp(void) {KeyUp(&in_speed);}
+static void IN_StrafeDown(void) {KeyDown(&in_strafe);}
+static void IN_StrafeUp(void) {KeyUp(&in_strafe);}
+
+static void IN_AttackDown(void) {KeyDown(&in_attack);}
+static void IN_AttackUp(void) {KeyUp(&in_attack);}
+
+static void IN_UseDown(void) {KeyDown(&in_use);}
+static void IN_UseUp(void) {KeyUp(&in_use);}
// LordHavoc: added 6 new buttons
-void IN_Button3Down(void) {KeyDown(&in_button3);}
-void IN_Button3Up(void) {KeyUp(&in_button3);}
-void IN_Button4Down(void) {KeyDown(&in_button4);}
-void IN_Button4Up(void) {KeyUp(&in_button4);}
-void IN_Button5Down(void) {KeyDown(&in_button5);}
-void IN_Button5Up(void) {KeyUp(&in_button5);}
-void IN_Button6Down(void) {KeyDown(&in_button6);}
-void IN_Button6Up(void) {KeyUp(&in_button6);}
-void IN_Button7Down(void) {KeyDown(&in_button7);}
-void IN_Button7Up(void) {KeyUp(&in_button7);}
-void IN_Button8Down(void) {KeyDown(&in_button8);}
-void IN_Button8Up(void) {KeyUp(&in_button8);}
-
-void IN_Button9Down(void) {KeyDown(&in_button9);}
-void IN_Button9Up(void) {KeyUp(&in_button9);}
-void IN_Button10Down(void) {KeyDown(&in_button10);}
-void IN_Button10Up(void) {KeyUp(&in_button10);}
-void IN_Button11Down(void) {KeyDown(&in_button11);}
-void IN_Button11Up(void) {KeyUp(&in_button11);}
-void IN_Button12Down(void) {KeyDown(&in_button12);}
-void IN_Button12Up(void) {KeyUp(&in_button12);}
-void IN_Button13Down(void) {KeyDown(&in_button13);}
-void IN_Button13Up(void) {KeyUp(&in_button13);}
-void IN_Button14Down(void) {KeyDown(&in_button14);}
-void IN_Button14Up(void) {KeyUp(&in_button14);}
-void IN_Button15Down(void) {KeyDown(&in_button15);}
-void IN_Button15Up(void) {KeyUp(&in_button15);}
-void IN_Button16Down(void) {KeyDown(&in_button16);}
-void IN_Button16Up(void) {KeyUp(&in_button16);}
-
-void IN_JumpDown (void) {KeyDown(&in_jump);}
-void IN_JumpUp (void) {KeyUp(&in_jump);}
-
-void IN_Impulse (void) {in_impulse=atoi(Cmd_Argv(1));}
+static void IN_Button3Down(void) {KeyDown(&in_button3);}
+static void IN_Button3Up(void) {KeyUp(&in_button3);}
+static void IN_Button4Down(void) {KeyDown(&in_button4);}
+static void IN_Button4Up(void) {KeyUp(&in_button4);}
+static void IN_Button5Down(void) {KeyDown(&in_button5);}
+static void IN_Button5Up(void) {KeyUp(&in_button5);}
+static void IN_Button6Down(void) {KeyDown(&in_button6);}
+static void IN_Button6Up(void) {KeyUp(&in_button6);}
+static void IN_Button7Down(void) {KeyDown(&in_button7);}
+static void IN_Button7Up(void) {KeyUp(&in_button7);}
+static void IN_Button8Down(void) {KeyDown(&in_button8);}
+static void IN_Button8Up(void) {KeyUp(&in_button8);}
+
+static void IN_Button9Down(void) {KeyDown(&in_button9);}
+static void IN_Button9Up(void) {KeyUp(&in_button9);}
+static void IN_Button10Down(void) {KeyDown(&in_button10);}
+static void IN_Button10Up(void) {KeyUp(&in_button10);}
+static void IN_Button11Down(void) {KeyDown(&in_button11);}
+static void IN_Button11Up(void) {KeyUp(&in_button11);}
+static void IN_Button12Down(void) {KeyDown(&in_button12);}
+static void IN_Button12Up(void) {KeyUp(&in_button12);}
+static void IN_Button13Down(void) {KeyDown(&in_button13);}
+static void IN_Button13Up(void) {KeyUp(&in_button13);}
+static void IN_Button14Down(void) {KeyDown(&in_button14);}
+static void IN_Button14Up(void) {KeyUp(&in_button14);}
+static void IN_Button15Down(void) {KeyDown(&in_button15);}
+static void IN_Button15Up(void) {KeyUp(&in_button15);}
+static void IN_Button16Down(void) {KeyDown(&in_button16);}
+static void IN_Button16Up(void) {KeyUp(&in_button16);}
+
+static void IN_JumpDown (void) {KeyDown(&in_jump);}
+static void IN_JumpUp (void) {KeyUp(&in_jump);}
+
+static void IN_Impulse (void) {in_impulse=atoi(Cmd_Argv(1));}
in_bestweapon_info_t in_bestweapon_info[IN_BESTWEAPON_MAX];
-void IN_BestWeapon_Register(const char *name, int impulse, int weaponbit, int activeweaponcode, int ammostat, int ammomin)
+static void IN_BestWeapon_Register(const char *name, int impulse, int weaponbit, int activeweaponcode, int ammostat, int ammomin)
{
int i;
for(i = 0; i < IN_BESTWEAPON_MAX && in_bestweapon_info[i].impulse; ++i)
IN_BestWeapon_Register("h", 226, HIT_MJOLNIR, HIT_MJOLNIR, STAT_CELLS, 0); // hipnotic mjolnir hammer
}
-void IN_BestWeapon_Register_f (void)
+static void IN_BestWeapon_Register_f (void)
{
if(Cmd_Argc() == 7)
{
}
}
-void IN_BestWeapon (void)
+static void IN_BestWeapon (void)
{
int i, n;
const char *t;
cvar_t cl_nodelta = {0, "cl_nodelta", "0", "disables delta compression of non-player entities in QW network protocol"};
+cvar_t cl_csqc_generatemousemoveevents = {0, "cl_csqc_generatemousemoveevents", "1", "enables calls to CSQC_InputEvent with type 2, for compliance with EXT_CSQC spec"};
+
extern cvar_t v_flipped;
/*
Moves the local angle positions
================
*/
-void CL_AdjustAngles (void)
+static void CL_AdjustAngles (void)
{
float speed;
float up, down;
// allow mice or other external controllers to add to the move
IN_Move ();
+ // send mouse move to csqc
+ if (cl.csqc_loaded && cl_csqc_generatemousemoveevents.integer)
+ {
+ if (cl.csqc_wantsmousemove)
+ {
+ // event type 3 is a DP_CSQC thing
+ static int oldwindowmouse[2];
+ if (oldwindowmouse[0] != in_windowmouse_x || oldwindowmouse[1] != in_windowmouse_y)
+ {
+ CL_VM_InputEvent(3, in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height);
+ oldwindowmouse[0] = in_windowmouse_x;
+ oldwindowmouse[1] = in_windowmouse_y;
+ }
+ }
+ else
+ {
+ if (in_mouse_x || in_mouse_y)
+ CL_VM_InputEvent(2, in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height);
+ }
+ }
+
// apply m_accelerate if it is on
if(m_accelerate.value > 1)
{
#include "cl_collision.h"
-void CL_UpdatePrydonCursor(void)
+static void CL_UpdatePrydonCursor(void)
{
vec3_t temp;
cl.cmd.cursor_fraction = CL_SelectTraceLine(cl.cmd.cursor_start, cl.cmd.cursor_end, cl.cmd.cursor_impact, cl.cmd.cursor_normal, &cl.cmd.cursor_entitynumber, (chase_active.integer || cl.intermission) ? &cl.entities[cl.playerentity].render : NULL);
}
-typedef enum waterlevel_e
-{
- WATERLEVEL_NONE,
- WATERLEVEL_WETFEET,
- WATERLEVEL_SWIMMING,
- WATERLEVEL_SUBMERGED
-}
-waterlevel_t;
-
-typedef struct cl_clientmovement_state_s
-{
- // position
- vec3_t origin;
- vec3_t velocity;
- // current bounding box (different if crouched vs standing)
- vec3_t mins;
- vec3_t maxs;
- // currently on the ground
- qboolean onground;
- // currently crouching
- qboolean crouched;
- // what kind of water (SUPERCONTENTS_LAVA for instance)
- int watertype;
- // how deep
- waterlevel_t waterlevel;
- // weird hacks when jumping out of water
- // (this is in seconds and counts down to 0)
- float waterjumptime;
-
- // user command
- usercmd_t cmd;
-}
-cl_clientmovement_state_t;
-
#define NUMOFFSETS 27
static vec3_t offsets[NUMOFFSETS] =
{
{-0.125, 0.125, -0.125}, { 0.125, 0.125, -0.125},
};
-qboolean CL_ClientMovement_Unstick(cl_clientmovement_state_t *s)
+static qboolean CL_ClientMovement_Unstick(cl_clientmovement_state_t *s)
{
int i;
vec3_t neworigin;
for (i = 0;i < NUMOFFSETS;i++)
{
VectorAdd(offsets[i], s->origin, neworigin);
- if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false).startsolid)
+ if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true).startsolid)
{
VectorCopy(neworigin, s->origin);
return true;
return false;
}
-void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
+static void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
{
+ vec_t f;
vec3_t origin1, origin2;
trace_t trace;
// low ceiling first
if (s->crouched)
{
- trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
if (!trace.startsolid)
s->crouched = false;
}
// set onground
VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1);
VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 1); // -2 causes clientside doublejump bug at above 150fps, raising that to 300fps :)
- trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
- s->onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7;
+ trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
+ if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
+ {
+ s->onground = true;
+
+ // this code actually "predicts" an impact; so let's clip velocity first
+ f = DotProduct(s->velocity, trace.plane.normal);
+ if(f < 0) // only if moving downwards actually
+ VectorMA(s->velocity, -f, trace.plane.normal, s->velocity);
+ }
+ else
+ s->onground = false;
// set watertype/waterlevel
VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1);
s->waterjumptime = 0;
}
-void CL_ClientMovement_Move(cl_clientmovement_state_t *s)
+static void CL_ClientMovement_Move(cl_clientmovement_state_t *s)
{
int bump;
double t;
for (bump = 0, t = s->cmd.frametime;bump < 8 && VectorLength2(s->velocity) > 0;bump++)
{
VectorMA(s->origin, t, s->velocity, neworigin);
- trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
if (trace.fraction < 1 && trace.plane.normal[2] == 0)
{
// may be a step or wall, try stepping up
// first move forward at a higher level
VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + cl.movevars_stepheight);
VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + cl.movevars_stepheight);
- trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
if (!trace2.startsolid)
{
// then move down from there
VectorCopy(trace2.endpos, currentorigin2);
VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], s->origin[2]);
- trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
//Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]);
// accept the new trace if it made some progress
if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125)
}
-void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
+static void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
{
vec_t wishspeed;
vec_t f;
return a * pow(fabs(b / a), lerp);
}
-void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
+static void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
{
vec_t zspeed, speed, dot, k;
s->velocity[2] = zspeed;
}
-float CL_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor)
+static float CL_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor)
{
return
(accelqw < 0 ? -1 : +1)
bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1);
}
-void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t stretchfactor, vec_t sidefric, vec_t speedlimit)
+static void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t stretchfactor, vec_t sidefric, vec_t speedlimit)
{
vec_t vel_straight;
vec_t vel_z;
s->velocity[2] += vel_z;
}
-void CL_ClientMovement_Physics_PM_AirAccelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
+static void CL_ClientMovement_Physics_PM_AirAccelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
{
vec3_t curvel, wishvel, acceldir, curdir;
float addspeed, accelspeed, curspeed;
VectorMA( s->velocity, accelspeed, acceldir, s->velocity );
}
-void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
+static void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
{
vec_t friction;
vec_t wishspeed;
// released at least once since the last jump
if (s->cmd.jump)
{
- if (s->onground && (s->cmd.canjump || !cl_movement_track_canjump.integer)) // FIXME remove this cvar again when canjump logic actually works, or maybe keep it for mods that allow "pogo-ing"
+ if (s->onground && (s->cmd.canjump || !cl_movement_track_canjump.integer))
{
s->velocity[2] += cl.movevars_jumpvelocity;
s->onground = false;
VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]);
VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34);
if (cls.protocol == PROTOCOL_QUAKEWORLD)
- trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
else
- trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false, false);
+ trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true, false);
if (trace.fraction == 1 && !trace.startsolid)
friction *= cl.movevars_edgefriction;
}
double totalmovemsec;
cl_clientmovement_state_t s;
+ VectorCopy(cl.mvelocity[0], cl.movement_velocity);
+
if (cl.movement_predicted && !cl.movement_replay)
return;
s.cmd = cl.movecmd[i];
if (i < CL_MAX_USERCMDS - 1)
s.cmd.canjump = cl.movecmd[i+1].canjump;
+
// if a move is more than 50ms, do it as two moves (matching qwsv)
//Con_Printf("%i ", s.cmd.msec);
if(s.cmd.frametime > 0.0005)
CL_ClientMovement_PlayerMove(&s);
}
CL_ClientMovement_PlayerMove(&s);
- cl.movecmd[i].canjump = s.cmd.canjump;
}
+ else
+ {
+ // we REALLY need this handling to happen, even if the move is not executed
+ if (!s.cmd.jump)
+ s.cmd.canjump = true;
+ }
+ cl.movecmd[i].canjump = s.cmd.canjump;
}
//Con_Printf("\n");
CL_ClientMovement_UpdateStatus(&s);
s.cmd = cl.movecmd[0];
}
- if (cls.demoplayback) // for bob, speedometer
- VectorCopy(cl.mvelocity[0], cl.movement_velocity);
- else
+ if (!cls.demoplayback) // for bob, speedometer
{
cl.movement_replay = false;
// update the interpolation target position and velocity
if (s.onground)
cl.onground = true;
}
-
- // react to onground state changes (for gun bob)
- if (cl.onground)
- {
- if (!cl.oldonground)
- cl.hitgroundtime = cl.movecmd[0].time;
- cl.lastongroundtime = cl.movecmd[0].time;
- }
- cl.oldonground = cl.onground;
}
-void QW_MSG_WriteDeltaUsercmd(sizebuf_t *buf, usercmd_t *from, usercmd_t *to)
+static void QW_MSG_WriteDeltaUsercmd(sizebuf_t *buf, usercmd_t *from, usercmd_t *to)
{
int bits;
{
Con_Print("CL_SendMove: lost server connection\n");
CL_Disconnect();
+ SV_LockThreadMutex();
Host_ShutdownServer();
+ SV_UnlockThreadMutex();
}
}
Cvar_RegisterVariable(&cl_netimmediatebuttons);
Cvar_RegisterVariable(&cl_nodelta);
+
+ Cvar_RegisterVariable(&cl_csqc_generatemousemoveevents);
}
#include "quakedef.h"
#include "cl_collision.h"
-#include "cl_gecko.h"
#include "cl_video.h"
#include "image.h"
#include "csprogs.h"
cvar_t csqc_progname = {0, "csqc_progname","csprogs.dat","name of csprogs.dat file to load"};
cvar_t csqc_progcrc = {CVAR_READONLY, "csqc_progcrc","-1","CRC of csprogs.dat file to load (-1 is none), only used during level changes and then reset to -1"};
cvar_t csqc_progsize = {CVAR_READONLY, "csqc_progsize","-1","file size of csprogs.dat file to load (-1 is none), only used during level changes and then reset to -1"};
+cvar_t csqc_usedemoprogs = {0, "csqc_usedemoprogs","1","use csprogs stored in demos"};
cvar_t cl_shownet = {0, "cl_shownet","0","1 = print packet size, 2 = print packet message list"};
cvar_t cl_nolerp = {0, "cl_nolerp", "0","network update smoothing"};
=====================
*/
-void CL_VM_ShutDown (void);
void CL_ClearState(void)
{
int i;
{
int i;
qboolean fail = false;
+ char vabuf[1024];
if (!allowstarkey && key[0] == '*')
fail = true;
if (!allowmodel && (!strcasecmp(key, "pmodel") || !strcasecmp(key, "emodel")))
if (cls.protocol == PROTOCOL_QUAKEWORLD)
{
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("setinfo \"%s\" \"%s\"", key, value));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "setinfo \"%s\" \"%s\"", key, value));
}
else if (!strcasecmp(key, "name"))
{
MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("name \"%s\"", value));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "name \"%s\"", value));
}
else if (!strcasecmp(key, "playermodel"))
{
MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("playermodel \"%s\"", value));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "playermodel \"%s\"", value));
}
else if (!strcasecmp(key, "playerskin"))
{
MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("playerskin \"%s\"", value));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "playerskin \"%s\"", value));
}
else if (!strcasecmp(key, "topcolor"))
{
else if (!strcasecmp(key, "rate"))
{
MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("rate \"%s\"", value));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "rate \"%s\"", value));
}
}
}
cls.netcon = NULL;
}
cls.state = ca_disconnected;
+ cl.islocalgame = false;
cls.demoplayback = cls.timedemo = false;
cls.signon = 0;
// make sure the client ports are open before attempting to connect
NetConn_UpdateSockets();
- // run a network frame
- //NetConn_ClientFrame();SV_VM_Begin();NetConn_ServerFrame();SV_VM_End();
-
if (LHNETADDRESS_FromString(&cls.connect_address, host, 26000) && (cls.connect_mysocket = NetConn_ChooseClientSocketForAddress(&cls.connect_address)))
{
cls.connect_trying = true;
}
M_Update_Return_Reason("Trying to connect...");
-
- // run several network frames to jump into the game quickly
- //if (sv.active)
- //{
- // NetConn_ClientFrame();SV_VM_Begin();NetConn_ServerFrame();SV_VM_End();
- // NetConn_ClientFrame();SV_VM_Begin();NetConn_ServerFrame();SV_VM_End();
- // NetConn_ClientFrame();SV_VM_Begin();NetConn_ServerFrame();SV_VM_End();
- // NetConn_ClientFrame();SV_VM_Begin();NetConn_ServerFrame();SV_VM_End();
- //}
}
else
{
for (i = -MAX_MODELS;i < MAX_MODELS;i++)
{
model = CL_GetModelByIndex(i);
+ if (!model)
+ continue;
if(model->loaded || i == 1)
Con_Printf("%3i: %-30s %-8s %-10i\n", i, model->name, model->modeldatatypestring, model->surfmesh.num_triangles);
else
dl->specularscale = specularscale;
}
-void CL_DecayLightFlashes(void)
+static void CL_DecayLightFlashes(void)
{
int i, oldmax;
dlight_t *dl;
}
}
-void CL_AddQWCTFFlagModel(entity_t *player, int skin)
+static void CL_AddQWCTFFlagModel(entity_t *player, int skin)
{
int frame = player->render.framegroupblend[0].frame;
float f;
static const vec3_t muzzleflashorigin = {18, 0, 0};
-extern void V_DriftPitch(void);
-extern void V_FadeViewFlashs(void);
-extern void V_CalcViewBlend(void);
-extern void V_CalcRefdef(void);
-
void CL_SetEntityColormapColors(entity_render_t *ent, int colormap)
{
const unsigned char *cbcolor;
}
// note this is a recursive function, recursionlimit should be 32 or so on the initial call
-void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolate)
+static void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolate)
{
const matrix4x4_t *matrix;
matrix4x4_t blendmatrix, tempmatrix, matrix2;
}
// creates light and trails from an entity
-void CL_UpdateNetworkEntityTrail(entity_t *e)
+static void CL_UpdateNetworkEntityTrail(entity_t *e)
{
effectnameindex_t trailtype;
vec3_t origin;
if (len > 0)
len = 1.0f / len;
VectorScale(vel, len, vel);
- CL_ParticleTrail(trailtype, 1, e->persistent.trail_origin, origin, vel, vel, e, e->state_current.glowcolor, false, true, NULL, NULL);
+ // pass time as count so that trails that are time based (such as an emitter) will emit properly as long as they don't use trailspacing
+ CL_ParticleTrail(trailtype, bound(0, cl.time - cl.oldtime, 0.1), e->persistent.trail_origin, origin, vel, vel, e, e->state_current.glowcolor, false, true, NULL, NULL);
}
// now that the entity has survived one trail update it is allowed to
// leave a real trail on later frames
CL_UpdateNetworkCollisionEntities
===============
*/
-void CL_UpdateNetworkCollisionEntities(void)
+static void CL_UpdateNetworkCollisionEntities(void)
{
entity_t *ent;
int i;
}
}
-extern void R_DecalSystem_Reset(decalsystem_t *decalsystem);
-
/*
===============
CL_UpdateNetworkEntities
===============
*/
-void CL_UpdateNetworkEntities(void)
+static void CL_UpdateNetworkEntities(void)
{
entity_t *ent;
int i;
}
}
-void CL_UpdateViewModel(void)
+static void CL_UpdateViewModel(void)
{
entity_t *ent;
ent = &cl.viewent;
}
// note this is a recursive function, but it can never get in a runaway loop (because of the delayedlink flags)
-void CL_LinkNetworkEntity(entity_t *e)
+static void CL_LinkNetworkEntity(entity_t *e)
{
effectnameindex_t trailtype;
vec3_t origin;
vec3_t dlightcolor;
vec_t dlightradius;
+ char vabuf[1024];
// skip inactive entities and world
if (!e->state_current.active || e == cl.entities)
// FIXME: add ambient/diffuse/specular scales as an extension ontop of TENEBRAE_GFX_DLIGHTS?
Matrix4x4_Normalize(&dlightmatrix, &e->render.matrix);
Matrix4x4_Scale(&dlightmatrix, light[3], 1);
- R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &dlightmatrix, light, e->state_current.lightstyle, e->state_current.skin > 0 ? va("cubemaps/%i", e->state_current.skin) : NULL, !(e->state_current.lightpflags & PFLAGS_NOSHADOW), (e->state_current.lightpflags & PFLAGS_CORONA) != 0, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+ R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &dlightmatrix, light, e->state_current.lightstyle, e->state_current.skin > 0 ? va(vabuf, sizeof(vabuf), "cubemaps/%i", e->state_current.skin) : NULL, !(e->state_current.lightpflags & PFLAGS_NOSHADOW), (e->state_current.lightpflags & PFLAGS_CORONA) != 0, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++;
}
// make the glow dlight
// Matrix4x4_Print(&e->render.matrix);
}
-void CL_RelinkWorld(void)
+static void CL_RelinkWorld(void)
{
entity_t *ent = &cl.entities[0];
// FIXME: this should be done at load
}
}
-void CL_LerpPlayer(float frac)
+static void CL_LerpPlayer(float frac)
{
int i;
static void CL_TimeRefresh_f (void)
{
int i;
- float timestart, timedelta;
+ double timestart, timedelta;
r_refdef.scene.extraupdate = false;
- timestart = Sys_DoubleTime();
+ timestart = Sys_DirtyTime();
for (i = 0;i < 128;i++)
{
Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], 0, i / 128.0 * 360.0, 0, 1);
r_refdef.view.quality = 1;
CL_UpdateScreen();
}
- timedelta = Sys_DoubleTime() - timestart;
+ timedelta = Sys_DirtyTime() - timestart;
Con_Printf("%f seconds (%f fps)\n", timedelta, 128/timedelta);
}
-void CL_AreaStats_f(void)
+static void CL_AreaStats_f(void)
{
World_PrintAreaStats(&cl.world, "client");
}
dpsnprintf(buffer, buffersize, "LOC=%.0f:%.0f:%.0f", point[0], point[1], point[2]);
}
-void CL_Locs_FreeNode(cl_locnode_t *node)
+static void CL_Locs_FreeNode(cl_locnode_t *node)
{
cl_locnode_t **pointer, **next;
for (pointer = &cl.locnodes;*pointer;pointer = next)
Con_Printf("CL_Locs_FreeNode: no such node! (%p)\n", (void *)node);
}
-void CL_Locs_AddNode(vec3_t mins, vec3_t maxs, const char *name)
+static void CL_Locs_AddNode(vec3_t mins, vec3_t maxs, const char *name)
{
cl_locnode_t *node, **pointer;
int namelen;
*pointer = node;
}
-void CL_Locs_Add_f(void)
+static void CL_Locs_Add_f(void)
{
vec3_t mins, maxs;
if (Cmd_Argc() != 5 && Cmd_Argc() != 8)
CL_Locs_AddNode(mins, mins, Cmd_Argv(4));
}
-void CL_Locs_RemoveNearest_f(void)
+static void CL_Locs_RemoveNearest_f(void)
{
cl_locnode_t *loc;
loc = CL_Locs_FindNearest(r_refdef.view.origin);
Con_Printf("no loc point or box found for your location\n");
}
-void CL_Locs_Clear_f(void)
+static void CL_Locs_Clear_f(void)
{
while (cl.locnodes)
CL_Locs_FreeNode(cl.locnodes);
}
-void CL_Locs_Save_f(void)
+static void CL_Locs_Save_f(void)
{
cl_locnode_t *loc;
qfile_t *outfile;
CL_Screen_Init();
CL_Video_Init();
- CL_Gecko_Init();
}
static qboolean QW_CL_CheckOrDownloadFile(const char *filename);
static void QW_CL_RequestNextDownload(void);
static void QW_CL_NextUpload(void);
-void QW_CL_StartUpload(unsigned char *data, int size);
//static qboolean QW_CL_IsUploading(void);
static void QW_CL_StopUpload(void);
-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);
/*
==================
CL_ParseStartSoundPacket
==================
*/
-void CL_ParseStartSoundPacket(int largesoundindex)
+static void CL_ParseStartSoundPacket(int largesoundindex)
{
vec3_t pos;
int channel, ent;
int volume;
int field_mask;
float attenuation;
+ float speed;
+ int fflags = CHANNELFLAG_NONE;
if (cls.protocol == PROTOCOL_QUAKEWORLD)
{
- channel = MSG_ReadShort();
+ channel = MSG_ReadShort(&cl_message);
if (channel & (1<<15))
- volume = MSG_ReadByte ();
+ volume = MSG_ReadByte(&cl_message);
else
volume = DEFAULT_SOUND_PACKET_VOLUME;
if (channel & (1<<14))
- attenuation = MSG_ReadByte () / 64.0;
+ attenuation = MSG_ReadByte(&cl_message) / 64.0;
else
attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
+
+ speed = 1.0f;
ent = (channel>>3)&1023;
channel &= 7;
- sound_num = MSG_ReadByte ();
+ sound_num = MSG_ReadByte(&cl_message);
}
else
{
- field_mask = MSG_ReadByte();
+ field_mask = MSG_ReadByte(&cl_message);
if (field_mask & SND_VOLUME)
- volume = MSG_ReadByte ();
+ volume = MSG_ReadByte(&cl_message);
else
volume = DEFAULT_SOUND_PACKET_VOLUME;
if (field_mask & SND_ATTENUATION)
- attenuation = MSG_ReadByte () / 64.0;
+ attenuation = MSG_ReadByte(&cl_message) / 64.0;
else
attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
+ if (field_mask & SND_SPEEDUSHORT4000)
+ speed = ((unsigned short)MSG_ReadShort(&cl_message)) / 4000.0f;
+ else
+ speed = 1.0f;
+
if (field_mask & SND_LARGEENTITY)
{
- ent = (unsigned short) MSG_ReadShort ();
- channel = MSG_ReadChar ();
+ ent = (unsigned short) MSG_ReadShort(&cl_message);
+ channel = MSG_ReadChar(&cl_message);
}
else
{
- channel = (unsigned short) MSG_ReadShort ();
+ channel = (unsigned short) MSG_ReadShort(&cl_message);
ent = channel >> 3;
channel &= 7;
}
if (largesoundindex || (field_mask & SND_LARGESOUND) || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3)
- sound_num = (unsigned short) MSG_ReadShort ();
+ sound_num = (unsigned short) MSG_ReadShort(&cl_message);
else
- sound_num = MSG_ReadByte ();
+ sound_num = MSG_ReadByte(&cl_message);
}
channel = CHAN_NET2ENGINE(channel);
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
if (sound_num >= MAX_SOUNDS)
{
if (ent >= cl.max_entities)
CL_ExpandEntities(ent);
- if( !CL_VM_Event_Sound(sound_num, volume / 255.0f, channel, attenuation, ent, pos) )
- S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0f, attenuation);
+ if( !CL_VM_Event_Sound(sound_num, volume / 255.0f, channel, attenuation, ent, pos, fflags, speed) )
+ S_StartSound_StartPosition_Flags (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0f, attenuation, 0, fflags, speed);
}
/*
static unsigned char olddata[NET_MAXMESSAGE];
void CL_KeepaliveMessage (qboolean readmessages)
{
- float time;
- static double nextmsg = -1;
- static double nextupdate = -1;
-#if 0
- static double lasttime = -1;
-#endif
- int oldreadcount;
- qboolean oldbadread;
+ static double lastdirtytime = 0;
+ static qboolean recursive = false;
+ double dirtytime;
+ double deltatime;
+ static double countdownmsg = 0;
+ static double countdownupdate = 0;
sizebuf_t old;
- if(cls.state != ca_dedicated)
+ qboolean thisrecursive;
+
+ thisrecursive = recursive;
+ recursive = true;
+
+ dirtytime = Sys_DirtyTime();
+ deltatime = dirtytime - lastdirtytime;
+ lastdirtytime = dirtytime;
+ if (deltatime <= 0 || deltatime >= 1800.0)
+ return;
+
+ countdownmsg -= deltatime;
+ countdownupdate -= deltatime;
+
+ if(!thisrecursive)
{
- if((time = Sys_DoubleTime()) >= nextupdate)
+ if(cls.state != ca_dedicated)
{
- SCR_UpdateLoadingScreenIfShown();
- nextupdate = time + 2;
+ if(countdownupdate <= 0) // check if time stepped backwards
+ {
+ SCR_UpdateLoadingScreenIfShown();
+ countdownupdate = 2;
+ }
}
}
// no need if server is local and definitely not if this is a demo
- if (!cls.netcon || cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon >= SIGNONS)
+ if (sv.active || !cls.netcon || cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon >= SIGNONS)
+ {
+ recursive = thisrecursive;
return;
+ }
if (readmessages)
{
// read messages from server, should just be nops
- oldreadcount = msg_readcount;
- oldbadread = msg_badread;
- old = net_message;
- memcpy(olddata, net_message.data, net_message.cursize);
+ old = cl_message;
+ memcpy(olddata, cl_message.data, cl_message.cursize);
NetConn_ClientFrame();
- msg_readcount = oldreadcount;
- msg_badread = oldbadread;
- net_message = old;
- memcpy(net_message.data, olddata, net_message.cursize);
- }
-
-#if 0
- if((time = Sys_DoubleTime()) >= lasttime + 1)
- {
- Con_Printf("long delta: %f\n", time - lasttime);
+ cl_message = old;
+ memcpy(cl_message.data, olddata, cl_message.cursize);
}
- lasttime = Sys_DoubleTime();
-#endif
- if (cls.netcon && (time = Sys_DoubleTime()) >= nextmsg)
+ if (cls.netcon && countdownmsg <= 0) // check if time stepped backwards
{
sizebuf_t msg;
unsigned char buf[4];
- nextmsg = time + 5;
+ countdownmsg = 5;
// write out a nop
// LordHavoc: must use unreliable because reliable could kill the sigon message!
Con_Print("--> client to server keepalive\n");
MSG_WriteChar(&msg, clc_nop);
NetConn_SendUnreliableMessage(cls.netcon, &msg, cls.protocol, 10000, false);
}
+
+ recursive = thisrecursive;
}
void CL_ParseEntityLump(char *entdata)
data = entdata;
if (!data)
return;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
if (com_token[0] != '{')
return; // error
while (1)
{
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
if (com_token[0] == '}')
break; // end of worldspawn
strlcpy (key, com_token, sizeof (key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
strlcpy (value, com_token, sizeof (value));
if (!strcmp("sky", key))
}
}
-extern void CL_Locs_Reload_f(void);
-extern void CL_VM_Init (void);
static const vec3_t defaultmins = {-4096, -4096, -4096};
static const vec3_t defaultmaxs = {4096, 4096, 4096};
static void CL_SetupWorldModel(void)
{
+ prvm_prog_t *prog = CLVM_prog;
// update the world model
cl.entities[0].render.model = cl.worldmodel = CL_GetModelByIndex(1);
CL_UpdateRenderEntity(&cl.entities[0].render);
Cvar_SetQuick(&cl_worldname, cl.worldname);
Cvar_SetQuick(&cl_worldnamenoextension, cl.worldnamenoextension);
Cvar_SetQuick(&cl_worldbasename, cl.worldbasename);
- World_SetSize(&cl.world, cl.worldname, cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
+ World_SetSize(&cl.world, cl.worldname, cl.worldmodel->normalmins, cl.worldmodel->normalmaxs, prog);
}
else
{
Cvar_SetQuick(&cl_worldmessage, cl.worldmessage);
Cvar_SetQuick(&cl_worldnamenoextension, "");
Cvar_SetQuick(&cl_worldbasename, "");
- World_SetSize(&cl.world, "", defaultmins, defaultmaxs);
+ World_SetSize(&cl.world, "", defaultmins, defaultmaxs, prog);
}
World_Start(&cl.world);
static qboolean QW_CL_CheckOrDownloadFile(const char *filename)
{
qfile_t *file;
+ char vabuf[1024];
// see if the file already exists
file = FS_OpenVirtualFile(filename, true);
}
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("download %s", filename));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "download %s", filename));
cls.qw_downloadnumber++;
cls.qw_downloadpercent = 0;
static void QW_CL_RequestNextDownload(void)
{
int i;
+ char vabuf[1024];
// clear name of file that just finished
cls.qw_downloadname[0] = 0;
if (!cl.scores[cls.qw_downloadnumber].name[0])
continue;
// check if we need to download the file, and return if so
- if (!QW_CL_CheckOrDownloadFile(va("skins/%s.pcx", cl.scores[cls.qw_downloadnumber].qw_skin)))
+ if (!QW_CL_CheckOrDownloadFile(va(vabuf, sizeof(vabuf), "skins/%s.pcx", cl.scores[cls.qw_downloadnumber].qw_skin)))
return;
}
cls.signon = SIGNONS-1;
// we'll go to SIGNONS when the first entity update is received
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("begin %i", cl.qw_servercount));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "begin %i", cl.qw_servercount));
}
break;
case dl_model:
CL_SetupWorldModel();
// add pmodel/emodel CRCs to userinfo
- CL_SetInfo("pmodel", va("%i", FS_CRCFile("progs/player.mdl", NULL)), true, true, true, true);
- CL_SetInfo("emodel", va("%i", FS_CRCFile("progs/eyes.mdl", NULL)), true, true, true, true);
+ CL_SetInfo("pmodel", va(vabuf, sizeof(vabuf), "%i", FS_CRCFile("progs/player.mdl", NULL)), true, true, true, true);
+ CL_SetInfo("emodel", va(vabuf, sizeof(vabuf), "%i", FS_CRCFile("progs/eyes.mdl", NULL)), true, true, true, true);
// done checking sounds and models, send a prespawn command now
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("prespawn %i 0 %i", cl.qw_servercount, cl.model_precache[1]->brush.qw_md4sum2));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "prespawn %i 0 %i", cl.qw_servercount, cl.model_precache[1]->brush.qw_md4sum2));
if (cls.qw_downloadmemory)
{
for (;cl.sound_name[cls.qw_downloadnumber][0];cls.qw_downloadnumber++)
{
// check if we need to download the file, and return if so
- if (!QW_CL_CheckOrDownloadFile(va("sound/%s", cl.sound_name[cls.qw_downloadnumber])))
+ if (!QW_CL_CheckOrDownloadFile(va(vabuf, sizeof(vabuf), "sound/%s", cl.sound_name[cls.qw_downloadnumber])))
return;
}
// done with sound downloads, next we check models
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("modellist %i %i", cl.qw_servercount, 0));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "modellist %i %i", cl.qw_servercount, 0));
break;
case dl_none:
default:
static void QW_CL_ParseDownload(void)
{
- int size = (signed short)MSG_ReadShort();
- int percent = MSG_ReadByte();
+ int size = (signed short)MSG_ReadShort(&cl_message);
+ int percent = MSG_ReadByte(&cl_message);
//Con_Printf("download %i %i%% (%i/%i)\n", size, percent, cls.qw_downloadmemorycursize, cls.qw_downloadmemorymaxsize);
if (!cls.netcon)
{
if (size > 0)
- msg_readcount += size;
+ cl_message.readcount += size;
return;
}
return;
}
- if (msg_readcount + (unsigned short)size > net_message.cursize)
+ if (cl_message.readcount + (unsigned short)size > cl_message.cursize)
Host_Error("corrupt download message\n");
// make sure the buffer is big enough to include this new fragment
}
// read the fragment out of the packet
- MSG_ReadBytes(size, cls.qw_downloadmemory + cls.qw_downloadmemorycursize);
+ MSG_ReadBytes(&cl_message, size, cls.qw_downloadmemory + cls.qw_downloadmemorycursize);
cls.qw_downloadmemorycursize += size;
cls.qw_downloadspeedcount += size;
static void QW_CL_ParseModelList(void)
{
int n;
- int nummodels = MSG_ReadByte();
+ int nummodels = MSG_ReadByte(&cl_message);
char *str;
+ char vabuf[1024];
// parse model precache list
for (;;)
{
- str = MSG_ReadString();
+ str = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
if (!str[0])
break;
nummodels++;
strlcpy(cl.model_name[nummodels], str, sizeof (cl.model_name[nummodels]));
}
- n = MSG_ReadByte();
+ n = MSG_ReadByte(&cl_message);
if (n)
{
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("modellist %i %i", cl.qw_servercount, n));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "modellist %i %i", cl.qw_servercount, n));
return;
}
static void QW_CL_ParseSoundList(void)
{
int n;
- int numsounds = MSG_ReadByte();
+ int numsounds = MSG_ReadByte(&cl_message);
char *str;
+ char vabuf[1024];
// parse sound precache list
for (;;)
{
- str = MSG_ReadString();
+ str = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
if (!str[0])
break;
numsounds++;
strlcpy(cl.sound_name[numsounds], str, sizeof (cl.sound_name[numsounds]));
}
- n = MSG_ReadByte();
+ n = MSG_ReadByte(&cl_message);
if (n)
{
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, n));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "soundlist %i %i", cl.qw_servercount, n));
return;
}
static void QW_CL_UpdateUserInfo(void)
{
int slot;
- slot = MSG_ReadByte();
+ slot = MSG_ReadByte(&cl_message);
if (slot >= cl.maxclients)
{
Con_Printf("svc_updateuserinfo >= cl.maxclients\n");
- MSG_ReadLong();
- MSG_ReadString();
+ MSG_ReadLong(&cl_message);
+ MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
return;
}
- cl.scores[slot].qw_userid = MSG_ReadLong();
- strlcpy(cl.scores[slot].qw_userinfo, MSG_ReadString(), sizeof(cl.scores[slot].qw_userinfo));
+ cl.scores[slot].qw_userid = MSG_ReadLong(&cl_message);
+ strlcpy(cl.scores[slot].qw_userinfo, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(cl.scores[slot].qw_userinfo));
QW_CL_ProcessUserInfo(slot);
}
int slot;
char key[2048];
char value[2048];
- slot = MSG_ReadByte();
- strlcpy(key, MSG_ReadString(), sizeof(key));
- strlcpy(value, MSG_ReadString(), sizeof(value));
+ slot = MSG_ReadByte(&cl_message);
+ strlcpy(key, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(key));
+ strlcpy(value, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(value));
if (slot >= cl.maxclients)
{
Con_Printf("svc_setinfo >= cl.maxclients\n");
char key[2048];
char value[2048];
char temp[32];
- strlcpy(key, MSG_ReadString(), sizeof(key));
- strlcpy(value, MSG_ReadString(), sizeof(value));
+ strlcpy(key, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(key));
+ strlcpy(value, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(value));
Con_DPrintf("SERVERINFO: %s=%s\n", key, value);
InfoString_SetValue(cl.qw_serverinfo, sizeof(cl.qw_serverinfo), key, value);
InfoString_GetValue(cl.qw_serverinfo, "teamplay", temp, sizeof(temp));
static void QW_CL_ParseNails(void)
{
int i, j;
- int numnails = MSG_ReadByte();
+ int numnails = MSG_ReadByte(&cl_message);
vec_t *v;
unsigned char bits[6];
for (i = 0;i < numnails;i++)
{
for (j = 0;j < 6;j++)
- bits[j] = MSG_ReadByte();
+ bits[j] = MSG_ReadByte(&cl_message);
if (cl.qw_num_nails > 255)
continue;
v = cl.qw_nails[cl.qw_num_nails++];
#define LOADPROGRESSWEIGHT_WORLDMODEL 30.0
#define LOADPROGRESSWEIGHT_WORLDMODEL_INIT 2.0
-void CL_BeginDownloads(qboolean aborteddownload)
+static void CL_BeginDownloads(qboolean aborteddownload)
{
+ char vabuf[1024];
// quakeworld works differently
if (cls.protocol == PROTOCOL_QUAKEWORLD)
return;
&& csqc_progcrc.integer >= 0
&& cl_serverextension_download.integer
&& (FS_CRCFile(csqc_progname.string, &progsize) != csqc_progcrc.integer || ((int)progsize != csqc_progsize.integer && csqc_progsize.integer != -1))
- && !FS_FileExists(va("dlcache/%s.%i.%i", csqc_progname.string, csqc_progsize.integer, csqc_progcrc.integer)))
+ && !FS_FileExists(va(vabuf, sizeof(vabuf), "dlcache/%s.%i.%i", csqc_progname.string, csqc_progsize.integer, csqc_progcrc.integer)))
{
Con_Printf("Downloading new CSQC code to dlcache/%s.%i.%i\n", csqc_progname.string, csqc_progsize.integer, csqc_progcrc.integer);
if(cl_serverextension_download.integer == 2 && FS_HasZlib())
- Cmd_ForwardStringToServer(va("download %s deflate", csqc_progname.string));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "download %s deflate", csqc_progname.string));
else
- Cmd_ForwardStringToServer(va("download %s", csqc_progname.string));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "download %s", csqc_progname.string));
return;
}
}
// regarding the * check: don't try to download submodels
if (cl_serverextension_download.integer && cls.netcon && cl.model_name[cl.downloadmodel_current][0] != '*' && !sv.active)
{
- Cmd_ForwardStringToServer(va("download %s", cl.model_name[cl.downloadmodel_current]));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "download %s", cl.model_name[cl.downloadmodel_current]));
// we'll try loading again when the download finishes
return;
}
Mod_FreeQ3Shaders();
}
- cl.model_precache[cl.downloadmodel_current] = Mod_ForName(cl.model_name[cl.downloadmodel_current], false, false, cl.model_name[cl.downloadmodel_current][0] == '*' ? cl.model_name[1] : NULL);
+ cl.model_precache[cl.downloadmodel_current] = Mod_ForName(cl.model_name[cl.downloadmodel_current], false, true, cl.model_name[cl.downloadmodel_current][0] == '*' ? cl.model_name[1] : NULL);
if (cl.downloadmodel_current == 1)
{
// we now have the worldmodel so we can set up the game world
Con_Printf("Sound %s not found\n", soundname);
if (cl_serverextension_download.integer && cls.netcon && !sv.active)
{
- Cmd_ForwardStringToServer(va("download %s", soundname));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "download %s", soundname));
// we'll try loading again when the download finishes
return;
}
}
}
-void CL_BeginDownloads_f(void)
+static void CL_BeginDownloads_f(void)
{
// prevent cl_begindownloads from being issued multiple times in one match
// to prevent accidentally cancelled downloads
CL_BeginDownloads(false);
}
-void CL_StopDownload(int size, int crc)
+static void CL_StopDownload(int size, int crc)
{
if (cls.qw_downloadmemory && cls.qw_downloadmemorycursize == size && CRC_Block(cls.qw_downloadmemory, cls.qw_downloadmemorycursize) == crc)
{
cls.qw_downloadpercent = 0;
}
-void CL_ParseDownload(void)
+static void CL_ParseDownload(void)
{
int i, start, size;
static unsigned char data[NET_MAXMESSAGE];
- start = MSG_ReadLong();
- size = (unsigned short)MSG_ReadShort();
+ start = MSG_ReadLong(&cl_message);
+ size = (unsigned short)MSG_ReadShort(&cl_message);
// record the start/size information to ack in the next input packet
for (i = 0;i < CL_MAX_DOWNLOADACKS;i++)
}
}
- MSG_ReadBytes(size, data);
+ MSG_ReadBytes(&cl_message, size, data);
if (!cls.qw_downloadname[0])
{
cls.qw_downloadspeedcount += size;
}
-void CL_DownloadBegin_f(void)
+static void CL_DownloadBegin_f(void)
{
int size = atoi(Cmd_Argv(1));
Cmd_ForwardStringToServer("sv_startdownload");
}
-void CL_StopDownload_f(void)
+static void CL_StopDownload_f(void)
{
Curl_CancelAll();
if (cls.qw_downloadname[0])
CL_BeginDownloads(true);
}
-void CL_DownloadFinished_f(void)
+static void CL_DownloadFinished_f(void)
{
if (Cmd_Argc() < 3)
{
static void CL_SendPlayerInfo(void)
{
+ char vabuf[1024];
MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
- MSG_WriteString (&cls.netcon->message, va("name \"%s\"", cl_name.string));
+ MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "name \"%s\"", cl_name.string));
MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
- MSG_WriteString (&cls.netcon->message, va("color %i %i", cl_color.integer >> 4, cl_color.integer & 15));
+ MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "color %i %i", cl_color.integer >> 4, cl_color.integer & 15));
MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
- MSG_WriteString (&cls.netcon->message, va("rate %i", cl_rate.integer));
+ MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "rate %i", cl_rate.integer));
if (cl_pmodel.integer)
{
MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
- MSG_WriteString (&cls.netcon->message, va("pmodel %i", cl_pmodel.integer));
+ MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "pmodel %i", cl_pmodel.integer));
}
if (*cl_playermodel.string)
{
MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
- MSG_WriteString (&cls.netcon->message, va("playermodel %s", cl_playermodel.string));
+ MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "playermodel %s", cl_playermodel.string));
}
if (*cl_playerskin.string)
{
MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
- MSG_WriteString (&cls.netcon->message, va("playerskin %s", cl_playerskin.string));
+ MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "playerskin %s", cl_playerskin.string));
}
}
CL_ParseServerInfo
==================
*/
-void CL_ParseServerInfo (void)
+static void CL_ParseServerInfo (void)
{
char *str;
int i;
protocolversion_t protocol;
int nummodels, numsounds;
+ char vabuf[1024];
// if we start loading a level and a video is still playing, stop it
CL_VideoStop();
CL_ClearState ();
// parse protocol version number
- i = MSG_ReadLong ();
+ i = MSG_ReadLong(&cl_message);
protocol = Protocol_EnumForNumber(i);
if (protocol == PROTOCOL_UNKNOWN)
{
{
char gamedir[1][MAX_QPATH];
- cl.qw_servercount = MSG_ReadLong();
+ cl.qw_servercount = MSG_ReadLong(&cl_message);
- str = MSG_ReadString();
+ str = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
Con_Printf("server gamedir is %s\n", str);
strlcpy(gamedir[0], str, sizeof(gamedir[0]));
cl.maxclients = 32;
// parse player number
- i = MSG_ReadByte();
+ i = MSG_ReadByte(&cl_message);
// cl.qw_spectator is an unneeded flag, cl.scores[cl.playerentity].qw_spectator works better (it can be updated by the server during the game)
//cl.qw_spectator = (i & 128) != 0;
cl.realplayerentity = cl.playerentity = cl.viewentity = (i & 127) + 1;
cl.scores = (scoreboard_t *)Mem_Alloc(cls.levelmempool, cl.maxclients*sizeof(*cl.scores));
// get the full level name
- str = MSG_ReadString ();
+ str = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
strlcpy (cl.worldmessage, str, sizeof(cl.worldmessage));
// get the movevars that are defined in the qw protocol
- cl.movevars_gravity = MSG_ReadFloat();
- cl.movevars_stopspeed = MSG_ReadFloat();
- cl.movevars_maxspeed = MSG_ReadFloat();
- cl.movevars_spectatormaxspeed = MSG_ReadFloat();
- cl.movevars_accelerate = MSG_ReadFloat();
- cl.movevars_airaccelerate = MSG_ReadFloat();
- cl.movevars_wateraccelerate = MSG_ReadFloat();
- cl.movevars_friction = MSG_ReadFloat();
- cl.movevars_waterfriction = MSG_ReadFloat();
- cl.movevars_entgravity = MSG_ReadFloat();
+ cl.movevars_gravity = MSG_ReadFloat(&cl_message);
+ cl.movevars_stopspeed = MSG_ReadFloat(&cl_message);
+ cl.movevars_maxspeed = MSG_ReadFloat(&cl_message);
+ cl.movevars_spectatormaxspeed = MSG_ReadFloat(&cl_message);
+ cl.movevars_accelerate = MSG_ReadFloat(&cl_message);
+ cl.movevars_airaccelerate = MSG_ReadFloat(&cl_message);
+ cl.movevars_wateraccelerate = MSG_ReadFloat(&cl_message);
+ cl.movevars_friction = MSG_ReadFloat(&cl_message);
+ cl.movevars_waterfriction = MSG_ReadFloat(&cl_message);
+ cl.movevars_entgravity = MSG_ReadFloat(&cl_message);
// other movevars not in the protocol...
cl.movevars_wallfriction = 0;
if (cls.netcon)
{
MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, 0));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "soundlist %i %i", cl.qw_servercount, 0));
}
cl.loadbegun = false;
else
{
// parse maxclients
- cl.maxclients = MSG_ReadByte ();
+ cl.maxclients = MSG_ReadByte(&cl_message);
if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
{
Host_Error("Bad maxclients (%u) from server", cl.maxclients);
cl.scores = (scoreboard_t *)Mem_Alloc(cls.levelmempool, cl.maxclients*sizeof(*cl.scores));
// parse gametype
- cl.gametype = MSG_ReadByte ();
+ cl.gametype = MSG_ReadByte(&cl_message);
// the original id singleplayer demos are bugged and contain
// GAME_DEATHMATCH even for singleplayer
if (cl.maxclients == 1 && cls.protocol == PROTOCOL_QUAKE)
cl.gametype = GAME_COOP;
// parse signon message
- str = MSG_ReadString ();
+ str = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
strlcpy (cl.worldmessage, str, sizeof(cl.worldmessage));
// seperate the printfs so the server message can have a color
// parse model precache list
for (nummodels=1 ; ; nummodels++)
{
- str = MSG_ReadString();
+ str = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
if (!str[0])
break;
if (nummodels==MAX_MODELS)
// parse sound precache list
for (numsounds=1 ; ; numsounds++)
{
- str = MSG_ReadString();
+ str = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
if (!str[0])
break;
if (numsounds==MAX_SOUNDS)
Con_Print ("ERROR: couldn't open.\n");
}
}
+ cl.islocalgame = NetConn_IsLocalGame();
}
void CL_ValidateState(entity_state_t *s)
CL_ParseBaseline
==================
*/
-void CL_ParseBaseline (entity_t *ent, int large)
+static void CL_ParseBaseline (entity_t *ent, int large)
{
int i;
ent->state_baseline.active = true;
if (large)
{
- ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
- ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
+ ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort(&cl_message);
+ ent->state_baseline.frame = (unsigned short) MSG_ReadShort(&cl_message);
}
else if (cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3)
{
- ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
- ent->state_baseline.frame = MSG_ReadByte ();
+ ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort(&cl_message);
+ ent->state_baseline.frame = MSG_ReadByte(&cl_message);
}
else
{
- ent->state_baseline.modelindex = MSG_ReadByte ();
- ent->state_baseline.frame = MSG_ReadByte ();
+ ent->state_baseline.modelindex = MSG_ReadByte(&cl_message);
+ ent->state_baseline.frame = MSG_ReadByte(&cl_message);
}
- ent->state_baseline.colormap = MSG_ReadByte();
- ent->state_baseline.skin = MSG_ReadByte();
+ ent->state_baseline.colormap = MSG_ReadByte(&cl_message);
+ ent->state_baseline.skin = MSG_ReadByte(&cl_message);
for (i = 0;i < 3;i++)
{
- ent->state_baseline.origin[i] = MSG_ReadCoord(cls.protocol);
- ent->state_baseline.angles[i] = MSG_ReadAngle(cls.protocol);
+ ent->state_baseline.origin[i] = MSG_ReadCoord(&cl_message, cls.protocol);
+ ent->state_baseline.angles[i] = MSG_ReadAngle(&cl_message, cls.protocol);
}
ent->state_previous = ent->state_current = ent->state_baseline;
}
Server information pertaining to this client only
==================
*/
-void CL_ParseClientdata (void)
+static void CL_ParseClientdata (void)
{
int i, bits;
cl.mvelocity[0][2] = 0;
cl.mviewzoom[0] = 1;
- bits = (unsigned short) MSG_ReadShort ();
+ bits = (unsigned short) MSG_ReadShort(&cl_message);
if (bits & SU_EXTEND1)
- bits |= (MSG_ReadByte() << 16);
+ bits |= (MSG_ReadByte(&cl_message) << 16);
if (bits & SU_EXTEND2)
- bits |= (MSG_ReadByte() << 24);
+ bits |= (MSG_ReadByte(&cl_message) << 24);
if (bits & SU_VIEWHEIGHT)
- cl.stats[STAT_VIEWHEIGHT] = MSG_ReadChar ();
+ cl.stats[STAT_VIEWHEIGHT] = MSG_ReadChar(&cl_message);
if (bits & SU_IDEALPITCH)
- cl.idealpitch = MSG_ReadChar ();
+ cl.idealpitch = MSG_ReadChar(&cl_message);
for (i = 0;i < 3;i++)
{
if (bits & (SU_PUNCH1<<i) )
{
if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3)
- cl.mpunchangle[0][i] = MSG_ReadChar();
+ cl.mpunchangle[0][i] = MSG_ReadChar(&cl_message);
else
- cl.mpunchangle[0][i] = MSG_ReadAngle16i();
+ cl.mpunchangle[0][i] = MSG_ReadAngle16i(&cl_message);
}
if (bits & (SU_PUNCHVEC1<<i))
{
if (cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4)
- cl.mpunchvector[0][i] = MSG_ReadCoord16i();
+ cl.mpunchvector[0][i] = MSG_ReadCoord16i(&cl_message);
else
- cl.mpunchvector[0][i] = MSG_ReadCoord32f();
+ cl.mpunchvector[0][i] = MSG_ReadCoord32f(&cl_message);
}
if (bits & (SU_VELOCITY1<<i) )
{
if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4)
- cl.mvelocity[0][i] = MSG_ReadChar()*16;
+ cl.mvelocity[0][i] = MSG_ReadChar(&cl_message)*16;
else
- cl.mvelocity[0][i] = MSG_ReadCoord32f();
+ cl.mvelocity[0][i] = MSG_ReadCoord32f(&cl_message);
}
}
// LordHavoc: hipnotic demos don't have this bit set but should
if (bits & SU_ITEMS || cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5)
- cl.stats[STAT_ITEMS] = MSG_ReadLong ();
+ cl.stats[STAT_ITEMS] = MSG_ReadLong(&cl_message);
cl.onground = (bits & SU_ONGROUND) != 0;
cl.inwater = (bits & SU_INWATER) != 0;
if (cls.protocol == PROTOCOL_DARKPLACES5)
{
- cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadShort() : 0;
- cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadShort() : 0;
- cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadShort() : 0;
- cl.stats[STAT_HEALTH] = MSG_ReadShort();
- cl.stats[STAT_AMMO] = MSG_ReadShort();
- cl.stats[STAT_SHELLS] = MSG_ReadShort();
- cl.stats[STAT_NAILS] = MSG_ReadShort();
- cl.stats[STAT_ROCKETS] = MSG_ReadShort();
- cl.stats[STAT_CELLS] = MSG_ReadShort();
- cl.stats[STAT_ACTIVEWEAPON] = (unsigned short) MSG_ReadShort ();
+ cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadShort(&cl_message) : 0;
+ cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadShort(&cl_message) : 0;
+ cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadShort(&cl_message) : 0;
+ cl.stats[STAT_HEALTH] = MSG_ReadShort(&cl_message);
+ cl.stats[STAT_AMMO] = MSG_ReadShort(&cl_message);
+ cl.stats[STAT_SHELLS] = MSG_ReadShort(&cl_message);
+ cl.stats[STAT_NAILS] = MSG_ReadShort(&cl_message);
+ cl.stats[STAT_ROCKETS] = MSG_ReadShort(&cl_message);
+ cl.stats[STAT_CELLS] = MSG_ReadShort(&cl_message);
+ cl.stats[STAT_ACTIVEWEAPON] = (unsigned short) MSG_ReadShort(&cl_message);
}
else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4)
{
- cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
- cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
+ cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte(&cl_message) : 0;
+ cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte(&cl_message) : 0;
if (cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3)
- cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? (unsigned short)MSG_ReadShort() : 0;
+ cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? (unsigned short)MSG_ReadShort(&cl_message) : 0;
else
- cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
- cl.stats[STAT_HEALTH] = MSG_ReadShort();
- cl.stats[STAT_AMMO] = MSG_ReadByte();
- cl.stats[STAT_SHELLS] = MSG_ReadByte();
- cl.stats[STAT_NAILS] = MSG_ReadByte();
- cl.stats[STAT_ROCKETS] = MSG_ReadByte();
- cl.stats[STAT_CELLS] = MSG_ReadByte();
+ cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte(&cl_message) : 0;
+ cl.stats[STAT_HEALTH] = MSG_ReadShort(&cl_message);
+ cl.stats[STAT_AMMO] = MSG_ReadByte(&cl_message);
+ cl.stats[STAT_SHELLS] = MSG_ReadByte(&cl_message);
+ cl.stats[STAT_NAILS] = MSG_ReadByte(&cl_message);
+ cl.stats[STAT_ROCKETS] = MSG_ReadByte(&cl_message);
+ cl.stats[STAT_CELLS] = MSG_ReadByte(&cl_message);
if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
- cl.stats[STAT_ACTIVEWEAPON] = (1<<MSG_ReadByte ());
+ cl.stats[STAT_ACTIVEWEAPON] = (1<<MSG_ReadByte(&cl_message));
else
- cl.stats[STAT_ACTIVEWEAPON] = MSG_ReadByte ();
+ cl.stats[STAT_ACTIVEWEAPON] = MSG_ReadByte(&cl_message);
}
if (bits & SU_VIEWZOOM)
{
if (cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4)
- cl.stats[STAT_VIEWZOOM] = MSG_ReadByte();
+ cl.stats[STAT_VIEWZOOM] = MSG_ReadByte(&cl_message);
else
- cl.stats[STAT_VIEWZOOM] = (unsigned short) MSG_ReadShort();
+ cl.stats[STAT_VIEWZOOM] = (unsigned short) MSG_ReadShort(&cl_message);
}
// viewzoom interpolation
CL_ParseStatic
=====================
*/
-void CL_ParseStatic (int large)
+static void CL_ParseStatic (int large)
{
entity_t *ent;
CL_ParseStaticSound
===================
*/
-void CL_ParseStaticSound (int large)
+static void CL_ParseStaticSound (int large)
{
vec3_t org;
int sound_num, vol, atten;
- MSG_ReadVector(org, cls.protocol);
+ MSG_ReadVector(&cl_message, org, cls.protocol);
if (large || cls.protocol == PROTOCOL_NEHAHRABJP2)
- sound_num = (unsigned short) MSG_ReadShort ();
+ sound_num = (unsigned short) MSG_ReadShort(&cl_message);
else
- sound_num = MSG_ReadByte ();
- vol = MSG_ReadByte ();
- atten = MSG_ReadByte ();
+ sound_num = MSG_ReadByte(&cl_message);
+ vol = MSG_ReadByte(&cl_message);
+ atten = MSG_ReadByte(&cl_message);
S_StaticSound (cl.sound_precache[sound_num], org, vol/255.0f, atten);
}
-void CL_ParseEffect (void)
+static void CL_ParseEffect (void)
{
vec3_t org;
int modelindex, startframe, framecount, framerate;
- MSG_ReadVector(org, cls.protocol);
- modelindex = MSG_ReadByte ();
- startframe = MSG_ReadByte ();
- framecount = MSG_ReadByte ();
- framerate = MSG_ReadByte ();
+ MSG_ReadVector(&cl_message, org, cls.protocol);
+ modelindex = MSG_ReadByte(&cl_message);
+ startframe = MSG_ReadByte(&cl_message);
+ framecount = MSG_ReadByte(&cl_message);
+ framerate = MSG_ReadByte(&cl_message);
CL_Effect(org, modelindex, startframe, framecount, framerate);
}
-void CL_ParseEffect2 (void)
+static void CL_ParseEffect2 (void)
{
vec3_t org;
int modelindex, startframe, framecount, framerate;
- MSG_ReadVector(org, cls.protocol);
- modelindex = (unsigned short) MSG_ReadShort ();
- startframe = (unsigned short) MSG_ReadShort ();
- framecount = MSG_ReadByte ();
- framerate = MSG_ReadByte ();
+ MSG_ReadVector(&cl_message, org, cls.protocol);
+ modelindex = (unsigned short) MSG_ReadShort(&cl_message);
+ startframe = (unsigned short) MSG_ReadShort(&cl_message);
+ framecount = MSG_ReadByte(&cl_message);
+ framerate = MSG_ReadByte(&cl_message);
CL_Effect(org, modelindex, startframe, framecount, framerate);
}
Con_Print("beam list overflow!\n");
}
-void CL_ParseBeam (dp_model_t *m, int lightning)
+static void CL_ParseBeam (dp_model_t *m, int lightning)
{
int ent;
vec3_t start, end;
- ent = (unsigned short) MSG_ReadShort ();
- MSG_ReadVector(start, cls.protocol);
- MSG_ReadVector(end, cls.protocol);
+ ent = (unsigned short) MSG_ReadShort(&cl_message);
+ MSG_ReadVector(&cl_message, start, cls.protocol);
+ MSG_ReadVector(&cl_message, end, cls.protocol);
if (ent >= MAX_EDICTS)
{
CL_NewBeam(ent, start, end, m, lightning);
}
-void CL_ParseTempEntity(void)
+static void CL_ParseTempEntity(void)
{
int type;
vec3_t pos, pos2;
if (cls.protocol == PROTOCOL_QUAKEWORLD)
{
- type = MSG_ReadByte();
+ type = MSG_ReadByte(&cl_message);
switch (type)
{
case QW_TE_WIZSPIKE:
// spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_wizhit, pos, 1, 1);
case QW_TE_KNIGHTSPIKE:
// spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_knighthit, pos, 1, 1);
case QW_TE_SPIKE:
// spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5)
break;
case QW_TE_SUPERSPIKE:
// super spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5)
case QW_TE_EXPLOSION:
// rocket explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1);
case QW_TE_TAREXPLOSION:
// tarbaby explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1);
break;
case QW_TE_LAVASPLASH:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
case QW_TE_TELEPORT:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
case QW_TE_GUNSHOT:
// bullet hitting wall
- radius = MSG_ReadByte();
- MSG_ReadVector(pos, cls.protocol);
+ radius = MSG_ReadByte(&cl_message);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
VectorSet(pos2, pos[0] + radius, pos[1] + radius, pos[2] + radius);
VectorSet(pos, pos[0] - radius, pos[1] - radius, pos[2] - radius);
break;
case QW_TE_BLOOD:
- count = MSG_ReadByte();
- MSG_ReadVector(pos, cls.protocol);
+ count = MSG_ReadByte(&cl_message);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_BLOOD, count, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
case QW_TE_LIGHTNINGBLOOD:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_BLOOD, 2.5, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
}
else
{
- type = MSG_ReadByte();
+ type = MSG_ReadByte(&cl_message);
switch (type)
{
case TE_WIZSPIKE:
// spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_wizhit, pos, 1, 1);
case TE_KNIGHTSPIKE:
// spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_knighthit, pos, 1, 1);
case TE_SPIKE:
// spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5)
break;
case TE_SPIKEQUAD:
// quad spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5)
break;
case TE_SUPERSPIKE:
// super spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5)
break;
case TE_SUPERSPIKEQUAD:
// quad super spike hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if (rand() % 5)
// LordHavoc: added for improved blood splatters
case TE_BLOOD:
// blood puff
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
- dir[0] = MSG_ReadChar();
- dir[1] = MSG_ReadChar();
- dir[2] = MSG_ReadChar();
- count = MSG_ReadByte();
+ dir[0] = MSG_ReadChar(&cl_message);
+ dir[1] = MSG_ReadChar(&cl_message);
+ dir[2] = MSG_ReadChar(&cl_message);
+ count = MSG_ReadByte(&cl_message);
CL_ParticleEffect(EFFECT_TE_BLOOD, count, pos, pos, dir, dir, NULL, 0);
break;
case TE_SPARK:
// spark shower
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
- dir[0] = MSG_ReadChar();
- dir[1] = MSG_ReadChar();
- dir[2] = MSG_ReadChar();
- count = MSG_ReadByte();
+ dir[0] = MSG_ReadChar(&cl_message);
+ dir[1] = MSG_ReadChar(&cl_message);
+ dir[2] = MSG_ReadChar(&cl_message);
+ count = MSG_ReadByte(&cl_message);
CL_ParticleEffect(EFFECT_TE_SPARK, count, pos, pos, dir, dir, NULL, 0);
break;
case TE_PLASMABURN:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
// LordHavoc: added for improved gore
case TE_BLOODSHOWER:
// vaporized body
- MSG_ReadVector(pos, cls.protocol); // mins
- MSG_ReadVector(pos2, cls.protocol); // maxs
- velspeed = MSG_ReadCoord(cls.protocol); // speed
- count = (unsigned short) MSG_ReadShort(); // number of particles
+ MSG_ReadVector(&cl_message, pos, cls.protocol); // mins
+ MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs
+ velspeed = MSG_ReadCoord(&cl_message, cls.protocol); // speed
+ count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles
vel1[0] = -velspeed;
vel1[1] = -velspeed;
vel1[2] = -velspeed;
case TE_PARTICLECUBE:
// general purpose particle effect
- MSG_ReadVector(pos, cls.protocol); // mins
- MSG_ReadVector(pos2, cls.protocol); // maxs
- MSG_ReadVector(dir, cls.protocol); // dir
- count = (unsigned short) MSG_ReadShort(); // number of particles
- colorStart = MSG_ReadByte(); // color
- colorLength = MSG_ReadByte(); // gravity (1 or 0)
- velspeed = MSG_ReadCoord(cls.protocol); // randomvel
+ MSG_ReadVector(&cl_message, pos, cls.protocol); // mins
+ MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs
+ MSG_ReadVector(&cl_message, dir, cls.protocol); // dir
+ count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles
+ colorStart = MSG_ReadByte(&cl_message); // color
+ colorLength = MSG_ReadByte(&cl_message); // gravity (1 or 0)
+ velspeed = MSG_ReadCoord(&cl_message, cls.protocol); // randomvel
CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength != 0, velspeed);
break;
case TE_PARTICLERAIN:
// general purpose particle effect
- MSG_ReadVector(pos, cls.protocol); // mins
- MSG_ReadVector(pos2, cls.protocol); // maxs
- MSG_ReadVector(dir, cls.protocol); // dir
- count = (unsigned short) MSG_ReadShort(); // number of particles
- colorStart = MSG_ReadByte(); // color
+ MSG_ReadVector(&cl_message, pos, cls.protocol); // mins
+ MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs
+ MSG_ReadVector(&cl_message, dir, cls.protocol); // dir
+ count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles
+ colorStart = MSG_ReadByte(&cl_message); // color
CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
break;
case TE_PARTICLESNOW:
// general purpose particle effect
- MSG_ReadVector(pos, cls.protocol); // mins
- MSG_ReadVector(pos2, cls.protocol); // maxs
- MSG_ReadVector(dir, cls.protocol); // dir
- count = (unsigned short) MSG_ReadShort(); // number of particles
- colorStart = MSG_ReadByte(); // color
+ MSG_ReadVector(&cl_message, pos, cls.protocol); // mins
+ MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs
+ MSG_ReadVector(&cl_message, dir, cls.protocol); // dir
+ count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles
+ colorStart = MSG_ReadByte(&cl_message); // color
CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
break;
case TE_GUNSHOT:
// bullet hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if(cl_sound_ric_gunshot.integer & RIC_GUNSHOT)
case TE_GUNSHOTQUAD:
// quad bullet hitting wall
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
if(cl_sound_ric_gunshot.integer & RIC_GUNSHOTQUAD)
case TE_EXPLOSION:
// rocket explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1);
case TE_EXPLOSIONQUAD:
// quad rocket explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1);
case TE_EXPLOSION3:
// Nehahra movie colored lighting explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
- color[0] = MSG_ReadCoord(cls.protocol) * (2.0f / 1.0f);
- color[1] = MSG_ReadCoord(cls.protocol) * (2.0f / 1.0f);
- color[2] = MSG_ReadCoord(cls.protocol) * (2.0f / 1.0f);
+ color[0] = MSG_ReadCoord(&cl_message, cls.protocol) * (2.0f / 1.0f);
+ color[1] = MSG_ReadCoord(&cl_message, cls.protocol) * (2.0f / 1.0f);
+ color[2] = MSG_ReadCoord(&cl_message, cls.protocol) * (2.0f / 1.0f);
CL_ParticleExplosion(pos);
Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
CL_AllocLightFlash(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
case TE_EXPLOSIONRGB:
// colored lighting explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleExplosion(pos);
- color[0] = MSG_ReadByte() * (2.0f / 255.0f);
- color[1] = MSG_ReadByte() * (2.0f / 255.0f);
- color[2] = MSG_ReadByte() * (2.0f / 255.0f);
+ color[0] = MSG_ReadByte(&cl_message) * (2.0f / 255.0f);
+ color[1] = MSG_ReadByte(&cl_message) * (2.0f / 255.0f);
+ color[2] = MSG_ReadByte(&cl_message) * (2.0f / 255.0f);
Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
CL_AllocLightFlash(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1);
case TE_TAREXPLOSION:
// tarbaby explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1);
break;
case TE_SMALLFLASH:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
case TE_CUSTOMFLASH:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 4);
- radius = (MSG_ReadByte() + 1) * 8;
- velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
- color[0] = MSG_ReadByte() * (2.0f / 255.0f);
- color[1] = MSG_ReadByte() * (2.0f / 255.0f);
- color[2] = MSG_ReadByte() * (2.0f / 255.0f);
+ radius = (MSG_ReadByte(&cl_message) + 1) * 8;
+ velspeed = (MSG_ReadByte(&cl_message) + 1) * (1.0 / 256.0);
+ color[0] = MSG_ReadByte(&cl_message) * (2.0f / 255.0f);
+ color[1] = MSG_ReadByte(&cl_message) * (2.0f / 255.0f);
+ color[2] = MSG_ReadByte(&cl_message) * (2.0f / 255.0f);
Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
CL_AllocLightFlash(NULL, &tempmatrix, radius, color[0], color[1], color[2], radius / velspeed, velspeed, 0, -1, true, 1, 0.25, 1, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
break;
case TE_FLAMEJET:
- MSG_ReadVector(pos, cls.protocol);
- MSG_ReadVector(dir, cls.protocol);
- count = MSG_ReadByte();
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
+ MSG_ReadVector(&cl_message, dir, cls.protocol);
+ count = MSG_ReadByte(&cl_message);
CL_ParticleEffect(EFFECT_TE_FLAMEJET, count, pos, pos, dir, dir, NULL, 0);
break;
// LordHavoc: for compatibility with the Nehahra movie...
case TE_LIGHTNING4NEH:
- CL_ParseBeam(Mod_ForName(MSG_ReadString(), true, false, NULL), false);
+ CL_ParseBeam(Mod_ForName(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), true, false, NULL), false);
break;
case TE_LAVASPLASH:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
case TE_TELEPORT:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
case TE_EXPLOSION2:
// color mapped explosion
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
- colorStart = MSG_ReadByte();
- colorLength = MSG_ReadByte();
+ colorStart = MSG_ReadByte(&cl_message);
+ colorLength = MSG_ReadByte(&cl_message);
CL_ParticleExplosion2(pos, colorStart, colorLength);
tempcolor = palette_rgb[(rand()%colorLength) + colorStart];
color[0] = tempcolor[0] * (2.0f / 255.0f);
break;
case TE_TEI_G3:
- MSG_ReadVector(pos, cls.protocol);
- MSG_ReadVector(pos2, cls.protocol);
- MSG_ReadVector(dir, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos2, cls.protocol);
+ MSG_ReadVector(&cl_message, dir, cls.protocol);
CL_ParticleEffect(EFFECT_TE_TEI_G3, 1, pos, pos2, dir, dir, NULL, 0);
break;
case TE_TEI_SMOKE:
- MSG_ReadVector(pos, cls.protocol);
- MSG_ReadVector(dir, cls.protocol);
- count = MSG_ReadByte();
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
+ MSG_ReadVector(&cl_message, dir, cls.protocol);
+ count = MSG_ReadByte(&cl_message);
CL_FindNonSolidLocation(pos, pos, 4);
CL_ParticleEffect(EFFECT_TE_TEI_SMOKE, count, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
case TE_TEI_BIGEXPLOSION:
- MSG_ReadVector(pos, cls.protocol);
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
CL_FindNonSolidLocation(pos, pos, 10);
CL_ParticleEffect(EFFECT_TE_TEI_BIGEXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0);
S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1);
break;
case TE_TEI_PLASMAHIT:
- MSG_ReadVector(pos, cls.protocol);
- MSG_ReadVector(dir, cls.protocol);
- count = MSG_ReadByte();
+ MSG_ReadVector(&cl_message, pos, cls.protocol);
+ MSG_ReadVector(&cl_message, dir, cls.protocol);
+ count = MSG_ReadByte(&cl_message);
CL_FindNonSolidLocation(pos, pos, 5);
CL_ParticleEffect(EFFECT_TE_TEI_PLASMAHIT, count, pos, pos, vec3_origin, vec3_origin, NULL, 0);
break;
}
}
-void CL_ParseTrailParticles(void)
+static void CL_ParseTrailParticles(void)
{
int entityindex;
int effectindex;
vec3_t start, end;
- entityindex = (unsigned short)MSG_ReadShort();
+ entityindex = (unsigned short)MSG_ReadShort(&cl_message);
if (entityindex >= MAX_EDICTS)
entityindex = 0;
if (entityindex >= cl.max_entities)
CL_ExpandEntities(entityindex);
- effectindex = (unsigned short)MSG_ReadShort();
- MSG_ReadVector(start, cls.protocol);
- MSG_ReadVector(end, cls.protocol);
+ effectindex = (unsigned short)MSG_ReadShort(&cl_message);
+ MSG_ReadVector(&cl_message, start, cls.protocol);
+ MSG_ReadVector(&cl_message, end, cls.protocol);
CL_ParticleEffect(effectindex, 1, start, end, vec3_origin, vec3_origin, entityindex > 0 ? cl.entities + entityindex : NULL, 0);
}
-void CL_ParsePointParticles(void)
+static void CL_ParsePointParticles(void)
{
int effectindex, count;
vec3_t origin, velocity;
- effectindex = (unsigned short)MSG_ReadShort();
- MSG_ReadVector(origin, cls.protocol);
- MSG_ReadVector(velocity, cls.protocol);
- count = (unsigned short)MSG_ReadShort();
+ effectindex = (unsigned short)MSG_ReadShort(&cl_message);
+ MSG_ReadVector(&cl_message, origin, cls.protocol);
+ MSG_ReadVector(&cl_message, velocity, cls.protocol);
+ count = (unsigned short)MSG_ReadShort(&cl_message);
CL_ParticleEffect(effectindex, count, origin, origin, velocity, velocity, NULL, 0);
}
-void CL_ParsePointParticles1(void)
+static void CL_ParsePointParticles1(void)
{
int effectindex;
vec3_t origin;
- effectindex = (unsigned short)MSG_ReadShort();
- MSG_ReadVector(origin, cls.protocol);
+ effectindex = (unsigned short)MSG_ReadShort(&cl_message);
+ MSG_ReadVector(&cl_message, origin, cls.protocol);
CL_ParticleEffect(effectindex, 1, origin, origin, vec3_origin, vec3_origin, NULL, 0);
}
}
// look for anything interesting like player IP addresses or ping reports
-qboolean CL_ExaminePrintString(const char *text)
+static qboolean CL_ExaminePrintString(const char *text)
{
int len;
const char *t;
extern cvar_t slowmo;
extern cvar_t cl_lerpexcess;
-extern void CSQC_UpdateNetworkTimes(double newtime, double oldtime);
static void CL_NetworkTimeReceived(double newtime)
{
double timehigh;
}
}
-#define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf("%3i:%s(%i)\n", msg_readcount-1, x, cmd);
-
-//[515]: csqc
-qboolean CL_VM_Parse_TempEntity (void);
-void CL_VM_Parse_StuffCmd (const char *msg);
-void CL_VM_Parse_CenterPrint (const char *msg);
-void CSQC_AddPrintText (const char *msg);
-void CSQC_ReadEntities (void);
+#define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf("%3i:%s(%i)\n", cl_message.readcount-1, x, cmd);
/*
=====================
=====================
*/
int parsingerror = false;
-extern void CL_UpdateMoveVars(void);
void CL_ParseServerMessage(void)
{
int cmd;
int cmdindex, cmdcount = 0;
qboolean qwplayerupdatereceived;
qboolean strip_pqc;
+ char vabuf[1024];
// LordHavoc: moved demo message writing from before the packet parse to
// after the packet parse so that CL_Stop_f can be called by cl_autodemo
// code in CL_ParseServerinfo
//if (cls.demorecording)
- // CL_WriteDemoMessage (&net_message);
+ // CL_WriteDemoMessage (&cl_message);
cl.last_received_message = realtime;
// if recording demos, copy the message out
//
if (cl_shownet.integer == 1)
- Con_Printf("%f %i\n", realtime, net_message.cursize);
+ Con_Printf("%f %i\n", realtime, cl_message.cursize);
else if (cl_shownet.integer == 2)
Con_Print("------------------\n");
while (1)
{
- if (msg_badread)
+ if (cl_message.badread)
Host_Error ("CL_ParseServerMessage: Bad QW server message");
- cmd = MSG_ReadByte ();
+ cmd = MSG_ReadByte(&cl_message);
if (cmd == -1)
{
return;
case qw_svc_print:
- i = MSG_ReadByte();
- temp = MSG_ReadString();
+ i = MSG_ReadByte(&cl_message);
+ temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports
{
if (i == 3) // chat
- CSQC_AddPrintText(va("\1%s", temp)); //[515]: csqc
+ CSQC_AddPrintText(va(vabuf, sizeof(vabuf), "\1%s", temp)); //[515]: csqc
else
CSQC_AddPrintText(temp);
}
break;
case qw_svc_centerprint:
- CL_VM_Parse_CenterPrint(MSG_ReadString ()); //[515]: csqc
+ CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc
break;
case qw_svc_stufftext:
- CL_VM_Parse_StuffCmd(MSG_ReadString ()); //[515]: csqc
+ CL_VM_Parse_StuffCmd(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc
break;
case qw_svc_damage:
case qw_svc_setangle:
for (i=0 ; i<3 ; i++)
- cl.viewangles[i] = MSG_ReadAngle (cls.protocol);
+ cl.viewangles[i] = MSG_ReadAngle(&cl_message, cls.protocol);
if (!cls.demoplayback)
{
cl.fixangle[0] = true;
break;
case qw_svc_lightstyle:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.max_lightstyle)
{
Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES");
break;
}
- strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map));
+ strlcpy (cl.lightstyle[i].map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.lightstyle[i].map));
cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
break;
break;
case qw_svc_stopsound:
- i = (unsigned short) MSG_ReadShort();
+ i = (unsigned short) MSG_ReadShort(&cl_message);
S_StopSound(i>>3, i&7);
break;
case qw_svc_updatefrags:
- i = MSG_ReadByte();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.maxclients)
Host_Error("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
- cl.scores[i].frags = (signed short) MSG_ReadShort();
+ cl.scores[i].frags = (signed short) MSG_ReadShort(&cl_message);
break;
case qw_svc_updateping:
- i = MSG_ReadByte();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.maxclients)
Host_Error("CL_ParseServerMessage: svc_updateping >= cl.maxclients");
- cl.scores[i].qw_ping = MSG_ReadShort();
+ cl.scores[i].qw_ping = MSG_ReadShort(&cl_message);
break;
case qw_svc_updatepl:
- i = MSG_ReadByte();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.maxclients)
Host_Error("CL_ParseServerMessage: svc_updatepl >= cl.maxclients");
- cl.scores[i].qw_packetloss = MSG_ReadByte();
+ cl.scores[i].qw_packetloss = MSG_ReadByte(&cl_message);
break;
case qw_svc_updateentertime:
- i = MSG_ReadByte();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.maxclients)
Host_Error("CL_ParseServerMessage: svc_updateentertime >= cl.maxclients");
// seconds ago
- cl.scores[i].qw_entertime = cl.time - MSG_ReadFloat();
+ cl.scores[i].qw_entertime = cl.time - MSG_ReadFloat(&cl_message);
break;
case qw_svc_spawnbaseline:
- i = (unsigned short) MSG_ReadShort();
+ i = (unsigned short) MSG_ReadShort(&cl_message);
if (i < 0 || i >= MAX_EDICTS)
Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
if (i >= cl.max_entities)
break;
case qw_svc_updatestat:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i < 0 || i >= MAX_CL_STATS)
Host_Error ("svc_updatestat: %i is invalid", i);
- cl.stats[i] = MSG_ReadByte ();
+ cl.stats[i] = MSG_ReadByte(&cl_message);
break;
case qw_svc_updatestatlong:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i < 0 || i >= MAX_CL_STATS)
Host_Error ("svc_updatestatlong: %i is invalid", i);
- cl.stats[i] = MSG_ReadLong ();
+ cl.stats[i] = MSG_ReadLong(&cl_message);
break;
case qw_svc_spawnstaticsound:
break;
case qw_svc_cdtrack:
- cl.cdtrack = cl.looptrack = MSG_ReadByte ();
+ cl.cdtrack = cl.looptrack = MSG_ReadByte(&cl_message);
if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
CDAudio_Play ((unsigned char)cls.forcetrack, true);
else
if(!cl.intermission)
cl.completed_time = cl.time;
cl.intermission = 1;
- MSG_ReadVector(cl.qw_intermission_origin, cls.protocol);
+ MSG_ReadVector(&cl_message, cl.qw_intermission_origin, cls.protocol);
for (i = 0;i < 3;i++)
- cl.qw_intermission_angles[i] = MSG_ReadAngle(cls.protocol);
+ cl.qw_intermission_angles[i] = MSG_ReadAngle(&cl_message, cls.protocol);
break;
case qw_svc_finale:
if(!cl.intermission)
cl.completed_time = cl.time;
cl.intermission = 2;
- SCR_CenterPrint(MSG_ReadString ());
+ SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
break;
case qw_svc_sellscreen:
- Cmd_ExecuteString ("help", src_command);
+ Cmd_ExecuteString ("help", src_command, true);
break;
case qw_svc_smallkick:
break;
case qw_svc_muzzleflash:
- i = (unsigned short) MSG_ReadShort();
+ i = (unsigned short) MSG_ReadShort(&cl_message);
// NOTE: in QW this only worked on clients
if (i < 0 || i >= MAX_EDICTS)
Host_Error("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
break;
case qw_svc_chokecount:
- i = MSG_ReadByte();
+ i = MSG_ReadByte(&cl_message);
// FIXME: apply to netgraph
//for (j = 0;j < i;j++)
// cl.frames[(cls.netcon->qw.incoming_acknowledged-1-j)&QW_UPDATE_MASK].receivedtime = -2;
break;
case qw_svc_maxspeed:
- cl.movevars_maxspeed = MSG_ReadFloat();
+ cl.movevars_maxspeed = MSG_ReadFloat(&cl_message);
break;
case qw_svc_entgravity:
- cl.movevars_entgravity = MSG_ReadFloat();
+ cl.movevars_entgravity = MSG_ReadFloat(&cl_message);
if (!cl.movevars_entgravity)
cl.movevars_entgravity = 1.0f;
break;
case qw_svc_setpause:
- cl.paused = MSG_ReadByte () != 0;
+ cl.paused = MSG_ReadByte(&cl_message) != 0;
if (cl.paused)
CDAudio_Pause ();
else
{
while (1)
{
- if (msg_badread)
+ if (cl_message.badread)
Host_Error ("CL_ParseServerMessage: Bad server message");
- cmd = MSG_ReadByte ();
+ cmd = MSG_ReadByte(&cl_message);
if (cmd == -1)
{
break;
case svc_time:
- CL_NetworkTimeReceived(MSG_ReadFloat());
+ CL_NetworkTimeReceived(MSG_ReadFloat(&cl_message));
break;
case svc_clientdata:
break;
case svc_version:
- i = MSG_ReadLong ();
+ i = MSG_ReadLong(&cl_message);
protocol = Protocol_EnumForNumber(i);
if (protocol == PROTOCOL_UNKNOWN)
Host_Error("CL_ParseServerMessage: Server is unrecognized protocol number (%i)", i);
break;
case svc_print:
- temp = MSG_ReadString();
+ temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports
CSQC_AddPrintText(temp); //[515]: csqc
break;
case svc_centerprint:
- CL_VM_Parse_CenterPrint(MSG_ReadString ()); //[515]: csqc
+ CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc
break;
case svc_stufftext:
- temp = MSG_ReadString();
+ temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
/* if(utf8_enable.integer)
{
strip_pqc = true;
case svc_setangle:
for (i=0 ; i<3 ; i++)
- cl.viewangles[i] = MSG_ReadAngle (cls.protocol);
+ cl.viewangles[i] = MSG_ReadAngle(&cl_message, cls.protocol);
if (!cls.demoplayback)
{
cl.fixangle[0] = true;
break;
case svc_setview:
- cl.viewentity = (unsigned short)MSG_ReadShort ();
+ cl.viewentity = (unsigned short)MSG_ReadShort(&cl_message);
if (cl.viewentity >= MAX_EDICTS)
Host_Error("svc_setview >= MAX_EDICTS");
if (cl.viewentity >= cl.max_entities)
break;
case svc_lightstyle:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.max_lightstyle)
{
Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES");
break;
}
- strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map));
+ strlcpy (cl.lightstyle[i].map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.lightstyle[i].map));
cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map);
break;
}
else
{
- int i = (unsigned short)MSG_ReadShort();
- char *s = MSG_ReadString();
+ int i = (unsigned short)MSG_ReadShort(&cl_message);
+ char *s = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
if (i < 32768)
{
if (i >= 1 && i < MAX_MODELS)
break;
case svc_stopsound:
- i = (unsigned short) MSG_ReadShort();
+ i = (unsigned short) MSG_ReadShort(&cl_message);
S_StopSound(i>>3, i&7);
break;
case svc_updatename:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
- strlcpy (cl.scores[i].name, MSG_ReadString (), sizeof (cl.scores[i].name));
+ strlcpy (cl.scores[i].name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.scores[i].name));
break;
case svc_updatefrags:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
- cl.scores[i].frags = (signed short) MSG_ReadShort ();
+ cl.scores[i].frags = (signed short) MSG_ReadShort(&cl_message);
break;
case svc_updatecolors:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
- cl.scores[i].colors = MSG_ReadByte ();
+ cl.scores[i].colors = MSG_ReadByte(&cl_message);
break;
case svc_particle:
break;
case svc_spawnbaseline:
- i = (unsigned short) MSG_ReadShort ();
+ i = (unsigned short) MSG_ReadShort(&cl_message);
if (i < 0 || i >= MAX_EDICTS)
Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
if (i >= cl.max_entities)
CL_ParseBaseline (cl.entities + i, false);
break;
case svc_spawnbaseline2:
- i = (unsigned short) MSG_ReadShort ();
+ i = (unsigned short) MSG_ReadShort(&cl_message);
if (i < 0 || i >= MAX_EDICTS)
Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
if (i >= cl.max_entities)
break;
case svc_setpause:
- cl.paused = MSG_ReadByte () != 0;
+ cl.paused = MSG_ReadByte(&cl_message) != 0;
if (cl.paused)
CDAudio_Pause ();
else
break;
case svc_signonnum:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
// LordHavoc: it's rude to kick off the client if they missed the
// reconnect somehow, so allow signon 1 even if at signon 1
if (i <= cls.signon && i != 1)
break;
case svc_updatestat:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i < 0 || i >= MAX_CL_STATS)
Host_Error ("svc_updatestat: %i is invalid", i);
- cl.stats[i] = MSG_ReadLong ();
+ cl.stats[i] = MSG_ReadLong(&cl_message);
break;
case svc_updatestatubyte:
- i = MSG_ReadByte ();
+ i = MSG_ReadByte(&cl_message);
if (i < 0 || i >= MAX_CL_STATS)
Host_Error ("svc_updatestat: %i is invalid", i);
- cl.stats[i] = MSG_ReadByte ();
+ cl.stats[i] = MSG_ReadByte(&cl_message);
break;
case svc_spawnstaticsound:
break;
case svc_cdtrack:
- cl.cdtrack = MSG_ReadByte ();
- cl.looptrack = MSG_ReadByte ();
+ cl.cdtrack = MSG_ReadByte(&cl_message);
+ cl.looptrack = MSG_ReadByte(&cl_message);
if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
CDAudio_Play ((unsigned char)cls.forcetrack, true);
else
cl.completed_time = cl.time;
cl.intermission = 2;
CL_VM_UpdateIntermissionState(cl.intermission);
- SCR_CenterPrint(MSG_ReadString ());
+ SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
break;
case svc_cutscene:
cl.completed_time = cl.time;
cl.intermission = 3;
CL_VM_UpdateIntermissionState(cl.intermission);
- SCR_CenterPrint(MSG_ReadString ());
+ SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
break;
case svc_sellscreen:
- Cmd_ExecuteString ("help", src_command);
+ Cmd_ExecuteString ("help", src_command, true);
break;
case svc_hidelmp:
if (gamemode == GAME_TENEBRAE)
{
// repeating particle effect
- MSG_ReadCoord(cls.protocol);
- MSG_ReadCoord(cls.protocol);
- MSG_ReadCoord(cls.protocol);
- MSG_ReadCoord(cls.protocol);
- MSG_ReadCoord(cls.protocol);
- MSG_ReadCoord(cls.protocol);
- (void) MSG_ReadByte();
- MSG_ReadLong();
- MSG_ReadLong();
- MSG_ReadString();
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ (void) MSG_ReadByte(&cl_message);
+ MSG_ReadLong(&cl_message);
+ MSG_ReadLong(&cl_message);
+ MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
}
else
SHOWLMP_decodehide();
if (gamemode == GAME_TENEBRAE)
{
// particle effect
- MSG_ReadCoord(cls.protocol);
- MSG_ReadCoord(cls.protocol);
- MSG_ReadCoord(cls.protocol);
- (void) MSG_ReadByte();
- MSG_ReadString();
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ MSG_ReadCoord(&cl_message, cls.protocol);
+ (void) MSG_ReadByte(&cl_message);
+ MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
}
else
SHOWLMP_decodeshow();
break;
case svc_skybox:
- R_SetSkyBox(MSG_ReadString());
+ R_SetSkyBox(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
break;
case svc_entities:
if (cls.signon == SIGNONS - 1)
// implemented
if (cls.demorecording)
{
- CL_WriteDemoMessage (&net_message);
+ CL_WriteDemoMessage (&cl_message);
// R_TimeReport("WriteDemo");
}
}
if (!parsingerror)
return;
Con_Print("Packet dump:\n");
- SZ_HexDumpToConsole(&net_message);
+ SZ_HexDumpToConsole(&cl_message);
parsingerror = false;
}
float stretchfactor;
// stretch velocity factor (used for sparks)
float originoffset[3];
+ float relativeoriginoffset[3];
float velocityoffset[3];
+ float relativevelocityoffset[3];
float originjitter[3];
float velocityjitter[3];
float velocitymultiplier;
1.0f, //float stretchfactor;
// stretch velocity factor (used for sparks)
{0.0f, 0.0f, 0.0f}, //float originoffset[3];
+ {0.0f, 0.0f, 0.0f}, //float relativeoriginoffset[3];
{0.0f, 0.0f, 0.0f}, //float velocityoffset[3];
+ {0.0f, 0.0f, 0.0f}, //float relativevelocityoffset[3];
{0.0f, 0.0f, 0.0f}, //float originjitter[3];
{0.0f, 0.0f, 0.0f}, //float velocityjitter[3];
0.0f, //float velocitymultiplier;
cvar_t cl_decals_max = {CVAR_SAVE, "cl_decals_max", "4096", "maximum number of decals allowed to exist in the world at once"};
-void CL_Particles_ParseEffectInfo(const char *textstart, const char *textend, const char *filename)
+static void CL_Particles_ParseEffectInfo(const char *textstart, const char *textend, const char *filename)
{
int arrayindex;
int argc;
argv[arrayindex][0] = 0;
for (;;)
{
- if (!COM_ParseToken_Simple(&text, true, false))
+ if (!COM_ParseToken_Simple(&text, true, false, true))
return;
if (!strcmp(com_token, "\n"))
break;
else if (!strcmp(argv[0], "airfriction")) {readfloat(info->airfriction);}
else if (!strcmp(argv[0], "liquidfriction")) {readfloat(info->liquidfriction);}
else if (!strcmp(argv[0], "originoffset")) {readfloats(info->originoffset, 3);}
+ else if (!strcmp(argv[0], "relativeoriginoffset")) {readfloats(info->relativeoriginoffset, 3);}
else if (!strcmp(argv[0], "velocityoffset")) {readfloats(info->velocityoffset, 3);}
+ else if (!strcmp(argv[0], "relativevelocityoffset")) {readfloats(info->relativevelocityoffset, 3);}
else if (!strcmp(argv[0], "originjitter")) {readfloats(info->originjitter, 3);}
else if (!strcmp(argv[0], "velocityjitter")) {readfloats(info->velocityjitter, 3);}
else if (!strcmp(argv[0], "velocitymultiplier")) {readfloat(info->velocitymultiplier);}
"SVC_PARTICLE"
};
-void CL_Particles_LoadEffectInfo(void)
+static void CL_Particles_LoadEffectInfo(void)
{
int i;
int filepass;
part->color[2] = ((((pcolor1 >> 0) & 0xFF) * l1 + ((pcolor2 >> 0) & 0xFF) * l2) >> 8) & 0xFF;
if (vid.sRGB3D)
{
- part->color[0] = (unsigned char)(Image_LinearFloatFromsRGB(part->color[0]) * 256.0f);
- part->color[1] = (unsigned char)(Image_LinearFloatFromsRGB(part->color[1]) * 256.0f);
- part->color[2] = (unsigned char)(Image_LinearFloatFromsRGB(part->color[2]) * 256.0f);
+ part->color[0] = (unsigned char)floor(Image_LinearFloatFromsRGB(part->color[0]) * 255.0f + 0.5f);
+ part->color[1] = (unsigned char)floor(Image_LinearFloatFromsRGB(part->color[1]) * 255.0f + 0.5f);
+ part->color[2] = (unsigned char)floor(Image_LinearFloatFromsRGB(part->color[2]) * 255.0f + 0.5f);
}
part->alpha = palpha;
part->alphafade = palphafade;
static void CL_Sparks(const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, float sparkcount);
static void CL_Smoke(const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, float smokecount);
-void CL_ParticleEffect_Fallback(int effectnameindex, float count, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor, qboolean spawndlight, qboolean spawnparticles)
+static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor, qboolean spawndlight, qboolean spawnparticles)
{
vec3_t center;
matrix4x4_t tempmatrix;
void CL_ParticleTrail(int effectnameindex, float pcount, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor, qboolean spawndlight, qboolean spawnparticles, float tintmins[4], float tintmaxs[4])
{
qboolean found = false;
+ char vabuf[1024];
if (effectnameindex < 1 || effectnameindex >= MAX_PARTICLEEFFECTNAME || !particleeffectname[effectnameindex][0])
{
Con_DPrintf("Unknown effect number %i received from server\n", effectnameindex);
vec3_t traildir;
vec3_t trailpos;
vec3_t rvec;
+ vec3_t angles;
+ vec3_t velocity;
+ vec3_t forward;
+ vec3_t right;
+ vec3_t up;
vec_t traillen;
vec_t trailstep;
qboolean underwater;
rvec[0] = info->lightcolor[0]*avgtint[0]*avgtint[3];
rvec[1] = info->lightcolor[1]*avgtint[1]*avgtint[3];
rvec[2] = info->lightcolor[2]*avgtint[2]*avgtint[3];
- R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &tempmatrix, rvec, -1, info->lightcubemapnum > 0 ? va("cubemaps/%i", info->lightcubemapnum) : NULL, info->lightshadow, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+ R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &tempmatrix, rvec, -1, info->lightcubemapnum > 0 ? va(vabuf, sizeof(vabuf), "cubemaps/%i", info->lightcubemapnum) : NULL, info->lightshadow, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++;
}
}
staintex = min(staintex, info->staintex[1] - 1);
}
if (info->particletype == pt_decal)
- CL_SpawnDecalParticleForPoint(center, info->originjitter[0], lhrandom(info->size[0], info->size[1]), lhrandom(info->alpha[0], info->alpha[1])*avgtint[3], tex, info->color[0], info->color[1]);
+ {
+ VectorMAM(0.5f, velocitymins, 0.5f, velocitymaxs, velocity);
+ AnglesFromVectors(angles, velocity, NULL, false);
+ AngleVectors(angles, forward, right, up);
+ VectorMAMAMAM(1.0f, center, info->relativeoriginoffset[0], forward, info->relativeoriginoffset[1], right, info->relativeoriginoffset[2], up, trailpos);
+
+ CL_SpawnDecalParticleForPoint(trailpos, info->originjitter[0], lhrandom(info->size[0], info->size[1]), lhrandom(info->alpha[0], info->alpha[1])*avgtint[3], tex, info->color[0], info->color[1]);
+ }
else if (info->orientation == PARTICLE_HBEAM)
- CL_NewParticle(center, info->particletype, info->color[0], info->color[1], tex, lhrandom(info->size[0], info->size[1]), info->size[2], lhrandom(info->alpha[0], info->alpha[1]), info->alpha[2], 0, 0, originmins[0], originmins[1], originmins[2], originmaxs[0], originmaxs[1], originmaxs[2], 0, 0, 0, 0, false, lhrandom(info->time[0], info->time[1]), info->stretchfactor, info->blendmode, info->orientation, info->staincolor[0], info->staincolor[1], staintex, lhrandom(info->stainalpha[0], info->stainalpha[1]), lhrandom(info->stainsize[0], info->stainsize[1]), 0, 0, tintmins ? avgtint : NULL);
+ {
+ AnglesFromVectors(angles, traildir, NULL, false);
+ AngleVectors(angles, forward, right, up);
+ VectorMAMAM(info->relativeoriginoffset[0], forward, info->relativeoriginoffset[1], right, info->relativeoriginoffset[2], up, trailpos);
+
+ CL_NewParticle(center, info->particletype, info->color[0], info->color[1], tex, lhrandom(info->size[0], info->size[1]), info->size[2], lhrandom(info->alpha[0], info->alpha[1]), info->alpha[2], 0, 0, originmins[0] + trailpos[0], originmins[1] + trailpos[1], originmins[2] + trailpos[2], originmaxs[0], originmaxs[1], originmaxs[2], 0, 0, 0, 0, false, lhrandom(info->time[0], info->time[1]), info->stretchfactor, info->blendmode, info->orientation, info->staincolor[0], info->staincolor[1], staintex, lhrandom(info->stainalpha[0], info->stainalpha[1]), lhrandom(info->stainsize[0], info->stainsize[1]), 0, 0, tintmins ? avgtint : NULL);
+ }
else
{
if (!cl_particles.integer)
info->particleaccumulator += traillen / info->trailspacing * cl_particles_quality.value * pcount;
trailstep = info->trailspacing / cl_particles_quality.value / max(0.001, pcount);
immediatebloodstain = false;
+
+ AnglesFromVectors(angles, traildir, NULL, false);
+ AngleVectors(angles, forward, right, up);
+ VectorMAMAMAM(1.0f, trailpos, info->relativeoriginoffset[0], forward, info->relativeoriginoffset[1], right, info->relativeoriginoffset[2], up, trailpos);
+ VectorMAMAM(info->relativevelocityoffset[0], forward, info->relativevelocityoffset[1], right, info->relativevelocityoffset[2], up, velocity);
}
else
{
((cl_decals_newsystem_immediatebloodstain.integer >= 1) && (info->particletype == pt_blood))
||
((cl_decals_newsystem_immediatebloodstain.integer >= 2) && staintex);
+
+ VectorMAM(0.5f, velocitymins, 0.5f, velocitymaxs, velocity);
+ AnglesFromVectors(angles, velocity, NULL, false);
+ AngleVectors(angles, forward, right, up);
+ VectorMAMAMAM(1.0f, trailpos, info->relativeoriginoffset[0], traildir, info->relativeoriginoffset[1], right, info->relativeoriginoffset[2], up, trailpos);
+ VectorMAMAM(info->relativevelocityoffset[0], traildir, info->relativevelocityoffset[1], right, info->relativevelocityoffset[2], up, velocity);
}
info->particleaccumulator = bound(0, info->particleaccumulator, 16384);
for (;info->particleaccumulator >= 1;info->particleaccumulator--)
Vector4Lerp(tintmins, tintlerp, tintmaxs, tint);
}
VectorRandom(rvec);
- part = CL_NewParticle(center, info->particletype, info->color[0], info->color[1], tex, lhrandom(info->size[0], info->size[1]), info->size[2], lhrandom(info->alpha[0], info->alpha[1]), info->alpha[2], info->gravity, info->bounce, trailpos[0] + info->originoffset[0] + info->originjitter[0] * rvec[0], trailpos[1] + info->originoffset[1] + info->originjitter[1] * rvec[1], trailpos[2] + info->originoffset[2] + info->originjitter[2] * rvec[2], lhrandom(velocitymins[0], velocitymaxs[0]) * info->velocitymultiplier + info->velocityoffset[0] + info->velocityjitter[0] * rvec[0], lhrandom(velocitymins[1], velocitymaxs[1]) * info->velocitymultiplier + info->velocityoffset[1] + info->velocityjitter[1] * rvec[1], lhrandom(velocitymins[2], velocitymaxs[2]) * info->velocitymultiplier + info->velocityoffset[2] + info->velocityjitter[2] * rvec[2], info->airfriction, info->liquidfriction, 0, 0, info->countabsolute <= 0, lhrandom(info->time[0], info->time[1]), info->stretchfactor, info->blendmode, info->orientation, info->staincolor[0], info->staincolor[1], staintex, lhrandom(info->stainalpha[0], info->stainalpha[1]), lhrandom(info->stainsize[0], info->stainsize[1]), lhrandom(info->rotate[0], info->rotate[1]), lhrandom(info->rotate[2], info->rotate[3]), tintmins ? tint : NULL);
+ part = CL_NewParticle(center, info->particletype, info->color[0], info->color[1], tex, lhrandom(info->size[0], info->size[1]), info->size[2], lhrandom(info->alpha[0], info->alpha[1]), info->alpha[2], info->gravity, info->bounce, trailpos[0] + info->originoffset[0] + info->originjitter[0] * rvec[0], trailpos[1] + info->originoffset[1] + info->originjitter[1] * rvec[1], trailpos[2] + info->originoffset[2] + info->originjitter[2] * rvec[2], lhrandom(velocitymins[0], velocitymaxs[0]) * info->velocitymultiplier + info->velocityoffset[0] + info->velocityjitter[0] * rvec[0] + velocity[0], lhrandom(velocitymins[1], velocitymaxs[1]) * info->velocitymultiplier + info->velocityoffset[1] + info->velocityjitter[1] * rvec[1] + velocity[1], lhrandom(velocitymins[2], velocitymaxs[2]) * info->velocitymultiplier + info->velocityoffset[2] + info->velocityjitter[2] * rvec[2] + velocity[2], info->airfriction, info->liquidfriction, 0, 0, info->countabsolute <= 0, lhrandom(info->time[0], info->time[1]), info->stretchfactor, info->blendmode, info->orientation, info->staincolor[0], info->staincolor[1], staintex, lhrandom(info->stainalpha[0], info->stainalpha[1]), lhrandom(info->stainsize[0], info->stainsize[1]), lhrandom(info->rotate[0], info->rotate[1]), lhrandom(info->rotate[2], info->rotate[3]), tintmins ? tint : NULL);
if (immediatebloodstain && part)
{
immediatebloodstain = false;
vec3_t org, dir;
int i, count, msgcount, color;
- MSG_ReadVector(org, cls.protocol);
+ MSG_ReadVector(&cl_message, org, cls.protocol);
for (i=0 ; i<3 ; i++)
- dir[i] = MSG_ReadChar () * (1.0 / 16.0);
- msgcount = MSG_ReadByte ();
- color = MSG_ReadByte ();
+ dir[i] = MSG_ReadChar(&cl_message) * (1.0 / 16.0);
+ msgcount = MSG_ReadByte(&cl_message);
+ color = MSG_ReadByte(&cl_message);
if (msgcount == 255)
count = 1024;
}
int particlefontwidth, particlefontheight, particlefontcellwidth, particlefontcellheight, particlefontrows, particlefontcols;
-void CL_Particle_PixelCoordsForTexnum(int texnum, int *basex, int *basey, int *width, int *height)
+static void CL_Particle_PixelCoordsForTexnum(int texnum, int *basex, int *basey, int *width, int *height)
{
*basex = (texnum % particlefontcols) * particlefontcellwidth;
*basey = ((texnum / particlefontcols) % particlefontrows) * particlefontcellheight;
memcpy(particletexturedata + ((basey + y) * PARTICLEFONTSIZE + basex) * 4, data + y * PARTICLETEXTURESIZE * 4, PARTICLETEXTURESIZE * 4);
}
-void particletextureblotch(unsigned char *data, float radius, float red, float green, float blue, float alpha)
+static void particletextureblotch(unsigned char *data, float radius, float red, float green, float blue, float alpha)
{
int x, y;
float cx, cy, dx, dy, f, iradius;
}
}
-void particletextureclamp(unsigned char *data, int minr, int ming, int minb, int maxr, int maxg, int maxb)
+#if 0
+static void particletextureclamp(unsigned char *data, int minr, int ming, int minb, int maxr, int maxg, int maxb)
{
int i;
for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4)
data[2] = bound(minr, data[2], maxr);
}
}
+#endif
-void particletextureinvert(unsigned char *data)
+static void particletextureinvert(unsigned char *data)
{
int i;
for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4)
bufptr = buf;
for(;;)
{
- if(!COM_ParseToken_Simple(&bufptr, true, false))
+ if(!COM_ParseToken_Simple(&bufptr, true, false, true))
break;
if(!strcmp(com_token, "\n"))
continue; // empty line
s2 = 1;
t2 = 1;
- if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n"))
+ if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n"))
{
strlcpy(texturename, com_token, sizeof(texturename));
s1 = atof(com_token);
- if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n"))
+ if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n"))
{
texturename[0] = 0;
t1 = atof(com_token);
- if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n"))
+ if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n"))
{
s2 = atof(com_token);
- if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n"))
+ if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n"))
{
t2 = atof(com_token);
strlcpy(texturename, "particles/particlefont.tga", sizeof(texturename));
- if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n"))
+ if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n"))
strlcpy(texturename, com_token, sizeof(texturename));
}
}
Con_Printf("particles/particlefont.txt: texnum %i outside valid range (0 to %i)\n", i, MAX_PARTICLETEXTURES);
continue;
}
- sf = R_SkinFrame_LoadExternal(texturename, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true);
+ sf = R_SkinFrame_LoadExternal(texturename, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true); // note: this loads as sRGB if sRGB is active!
if(!sf)
{
// R_SkinFrame_LoadExternal already complained
R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap, NULL, NULL);
}
-void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int surfacelistindex;
const decal_t *d;
// now render the decals all at once
// (this assumes they all use one particle font texture!)
GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- R_SetupShader_Generic(particletexture[63].texture, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic(particletexture[63].texture, NULL, GL_MODULATE, 1, false, false, true);
R_Mesh_PrepareVertices_Generic_Arrays(numsurfaces * 4, particle_vertex3f, particle_color4f, particle_texcoord2f);
R_Mesh_Draw(0, numsurfaces * 4, 0, numsurfaces * 2, NULL, NULL, 0, particle_elements, NULL, 0);
}
continue;
if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size))
- R_MeshQueue_AddTransparent(decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
continue;
killdecal:
decal->typeindex = 0;
r_refdef.stats.totaldecals = cl.num_decals;
}
-void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int surfacelistindex;
int batchstart, batchcount;
if (texture != particletexture[p->texnum].texture)
{
texture = particletexture[p->texnum].texture;
- R_SetupShader_Generic(texture, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic(texture, NULL, GL_MODULATE, 1, false, false, false);
}
if (p->blendmode == PBLEND_INVMOD)
{
case pt_beam:
// beams have no culling
- R_MeshQueue_AddTransparent(p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
break;
default:
if(cl_particles_visculling.integer)
}
// anything else just has to be in front of the viewer and visible at this distance
if (DotProduct(p->org, r_refdef.view.forward) >= minparticledist_start && VectorDistance2(p->org, r_refdef.view.origin) < drawdist2 * (p->size * p->size))
- R_MeshQueue_AddTransparent(p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL);
break;
}
cvar_t scr_screenshot_gammaboost = {CVAR_SAVE, "scr_screenshot_gammaboost","1", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
cvar_t scr_screenshot_hwgamma = {CVAR_SAVE, "scr_screenshot_hwgamma","1", "apply the video gamma ramp to saved screenshots and videos"};
cvar_t scr_screenshot_alpha = {CVAR_SAVE, "scr_screenshot_alpha","0", "try to write an alpha channel to screenshots (debugging feature)"};
+cvar_t scr_screenshot_timestamp = {CVAR_SAVE, "scr_screenshot_timestamp", "1", "use a timestamp based number of the type YYYYMMDDHHMMSSsss instead of sequential numbering"};
// scr_screenshot_name is defined in fs.c
cvar_t cl_capturevideo = {0, "cl_capturevideo", "0", "enables saving of video to a .avi file using uncompressed I420 colorspace and PCM audio, note that scr_screenshot_gammaboost affects the brightness of the output)"};
cvar_t cl_capturevideo_printfps = {CVAR_SAVE, "cl_capturevideo_printfps", "1", "prints the frames per second captured in capturevideo (is only written to the log file, not to the console, as that would be visible on the video)"};
cvar_t r_stereo_redcyan = {0, "r_stereo_redcyan", "0", "red/cyan anaglyph stereo glasses, the kind given away at drive-in movies like Creature From The Black Lagoon In 3D"};
cvar_t r_stereo_redgreen = {0, "r_stereo_redgreen", "0", "red/green anaglyph stereo glasses (for those who don't mind yellow)"};
cvar_t r_stereo_angle = {0, "r_stereo_angle", "0", "separation angle of eyes (makes the views look different directions, as an example, 90 gives a 90 degree separation where the views are 45 degrees left and 45 degrees right)"};
-cvar_t scr_zoomwindow = {CVAR_SAVE, "scr_zoomwindow", "0", "displays a zoomed in overlay window"};
-cvar_t scr_zoomwindow_viewsizex = {CVAR_SAVE, "scr_zoomwindow_viewsizex", "20", "horizontal viewsize of zoom window"};
-cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20", "vertical viewsize of zoom window"};
-cvar_t scr_zoomwindow_fov = {CVAR_SAVE, "scr_zoomwindow_fov", "20", "fov of zoom window"};
cvar_t scr_stipple = {0, "scr_stipple", "0", "interlacing-like stippling of the display"};
cvar_t scr_refresh = {0, "scr_refresh", "1", "allows you to completely shut off rendering for benchmarking purposes"};
cvar_t scr_screenshot_name_in_mapdir = {CVAR_SAVE, "scr_screenshot_name_in_mapdir", "0", "if set to 1, screenshots are placed in a subdirectory named like the map they are from"};
}
-void SCR_DrawCenterString (void)
+static void SCR_DrawCenterString (void)
{
char *start;
int x, y;
} while (1);
}
-void SCR_CheckDrawCenterString (void)
+static void SCR_CheckDrawCenterString (void)
{
if (scr_center_lines > scr_erase_lines)
scr_erase_lines = scr_center_lines;
SCR_DrawCenterString ();
}
-void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth, int graphheight, float graphscale, const char *label, float textsize, int packetcounter, netgraphitem_t *netgraph)
+static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth, int graphheight, float graphscale, const char *label, float textsize, int packetcounter, netgraphitem_t *netgraph)
{
netgraphitem_t *graph;
int j, x, y, numlines;
SCR_DrawNetGraph
==============
*/
-void SCR_DrawNetGraph (void)
+static void SCR_DrawNetGraph (void)
{
int i, separator1, separator2, graphwidth, graphheight, netgraph_x, netgraph_y, textsize, index, netgraphsperrow;
float graphscale;
netconn_t *c;
+ char vabuf[1024];
if (cls.state != ca_connected)
return;
continue;
netgraph_x = (vid_conwidth.integer + separator2) - (1 + (index % netgraphsperrow)) * (graphwidth * 2 + separator1 + separator2);
netgraph_y = (vid_conheight.integer - 48 + separator2) - (1 + (index / netgraphsperrow)) * (graphheight + textsize + separator2);
- SCR_DrawNetGraph_DrawGraph(netgraph_x , netgraph_y, graphwidth, graphheight, graphscale, va("%s", svs.clients[i].name), textsize, c->outgoing_packetcounter, c->outgoing_netgraph);
+ SCR_DrawNetGraph_DrawGraph(netgraph_x , netgraph_y, graphwidth, graphheight, graphscale, va(vabuf, sizeof(vabuf), "%s", svs.clients[i].name), textsize, c->outgoing_packetcounter, c->outgoing_netgraph);
SCR_DrawNetGraph_DrawGraph(netgraph_x + graphwidth + separator1, netgraph_y, graphwidth, graphheight, graphscale, "" , textsize, c->incoming_packetcounter, c->incoming_netgraph);
index++;
}
SCR_DrawTurtle
==============
*/
-void SCR_DrawTurtle (void)
+static void SCR_DrawTurtle (void)
{
static int count;
SCR_DrawNet
==============
*/
-void SCR_DrawNet (void)
+static void SCR_DrawNet (void)
{
if (cls.state != ca_connected)
return;
DrawPause
==============
*/
-void SCR_DrawPause (void)
+static void SCR_DrawPause (void)
{
cachepic_t *pic;
SCR_DrawBrand
==============
*/
-void SCR_DrawBrand (void)
+static void SCR_DrawBrand (void)
{
cachepic_t *pic;
float x, y;
float size = scr_infobar_height.value;
Curl_downloadinfo_t *downinfo;
char temp[256];
+ char addinfobuf[128];
const char *addinfo;
- downinfo = Curl_GetDownloadInfo(&nDownloads, &addinfo);
+ downinfo = Curl_GetDownloadInfo(&nDownloads, &addinfo, addinfobuf, sizeof(addinfobuf));
if(!downinfo)
return 0;
Curl_downloadinfo_t *downinfo;
const char *addinfo;
int nDownloads;
+ char addinfobuf[128];
if (cl.time > cl.oldtime)
scr_infobartime_off -= cl.time - cl.oldtime;
if(cls.qw_downloadname[0])
offset += 1;
- downinfo = Curl_GetDownloadInfo(&nDownloads, &addinfo);
+ downinfo = Curl_GetDownloadInfo(&nDownloads, &addinfo, addinfobuf, sizeof(addinfobuf));
if(downinfo)
{
offset += (nDownloads + (addinfo ? 1 : 0));
SCR_InfoBar_f
==============
*/
-void SCR_InfoBar_f(void)
+static void SCR_InfoBar_f(void)
{
if(Cmd_Argc() == 3)
{
SCR_SetUpToDrawConsole
==================
*/
-void SCR_SetUpToDrawConsole (void)
+static void SCR_SetUpToDrawConsole (void)
{
// lines of console to display
float conlines;
GL_Finish();
CHECKGLERROR
r_timereport_temp = r_timereport_current;
- r_timereport_current = Sys_DoubleTime();
+ r_timereport_current = Sys_DirtyTime();
t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0 + 0.5);
length = dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %s", t, desc);
speedstringcount += length;
}
-void R_TimeReport_BeginFrame(void)
+static void R_TimeReport_BeginFrame(void)
{
speedstringcount = 0;
r_speeds_timestring[0] = 0;
if (r_speeds.integer >= 2)
{
r_timereport_active = true;
- r_timereport_start = r_timereport_current = Sys_DoubleTime();
+ r_timereport_start = r_timereport_current = Sys_DirtyTime();
}
}
extern cvar_t r_viewscale;
extern float viewscalefpsadjusted;
-void R_TimeReport_EndFrame(void)
+static void R_TimeReport_EndFrame(void)
{
int i, j, lines, y;
cl_locnode_t *loc;
loc = CL_Locs_FindNearest(cl.movement_origin);
viewleaf = (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.PointInLeaf) ? r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, r_refdef.view.origin) : NULL;
dpsnprintf(string, sizeof(string),
-"%6.0fus rendertime %3.0f%% viewscale %s%s %.3f cl.time\n"
+"%6.0fus rendertime %3.0f%% viewscale %s%s %.3f cl.time%2.4f brightness\n"
"%3i renders org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n"
"%5i viewleaf%5i cluster%3i area%4i brushes%4i surfaces(%7i triangles)\n"
"%7i surfaces%7i triangles %5i entities (%7i surfaces%7i triangles)\n"
"%6i draws%8i vertices%8i triangles bloompixels%8i copied%8i drawn\n"
"updated%5i indexbuffers%8i bytes%5i vertexbuffers%8i bytes\n"
"%s"
-, r_refdef.lastdrawscreentime * 1000000.0, r_viewscale.value * sqrt(viewscalefpsadjusted) * 100.0f, loc ? "Location: " : "", loc ? loc->name : "", cl.time
+, r_refdef.lastdrawscreentime * 1000000.0, r_viewscale.value * sqrt(viewscalefpsadjusted) * 100.0f, loc ? "Location: " : "", loc ? loc->name : "", cl.time, r_refdef.view.colorscale
, r_refdef.stats.renders, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], r_refdef.view.forward[0], r_refdef.view.forward[1], r_refdef.view.forward[2]
, viewleaf ? (int)(viewleaf - r_refdef.scene.worldmodel->brush.data_leafs) : -1, viewleaf ? viewleaf->clusterindex : -1, viewleaf ? viewleaf->areaindex : -1, viewleaf ? viewleaf->numleafbrushes : 0, viewleaf ? viewleaf->numleafsurfaces : 0, viewleaf ? R_CountLeafTriangles(r_refdef.scene.worldmodel, viewleaf) : 0
, r_refdef.stats.world_surfaces, r_refdef.stats.world_triangles, r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles
if (r_speeds.integer >= 2)
{
r_timereport_active = true;
- r_timereport_start = r_timereport_current = Sys_DoubleTime();
+ r_timereport_start = r_timereport_current = Sys_DirtyTime();
}
}
Keybinding command
=================
*/
-void SCR_SizeUp_f (void)
+static void SCR_SizeUp_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value+10);
}
Keybinding command
=================
*/
-void SCR_SizeDown_f (void)
+static void SCR_SizeDown_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value-10);
}
Cvar_RegisterVariable (&scr_screenshot_hwgamma);
Cvar_RegisterVariable (&scr_screenshot_name_in_mapdir);
Cvar_RegisterVariable (&scr_screenshot_alpha);
+ Cvar_RegisterVariable (&scr_screenshot_timestamp);
Cvar_RegisterVariable (&cl_capturevideo);
Cvar_RegisterVariable (&cl_capturevideo_printfps);
Cvar_RegisterVariable (&cl_capturevideo_width);
Cvar_RegisterVariable(&r_stereo_redcyan);
Cvar_RegisterVariable(&r_stereo_redgreen);
Cvar_RegisterVariable(&r_stereo_angle);
- Cvar_RegisterVariable(&scr_zoomwindow);
- Cvar_RegisterVariable(&scr_zoomwindow_viewsizex);
- Cvar_RegisterVariable(&scr_zoomwindow_viewsizey);
- Cvar_RegisterVariable(&scr_zoomwindow_fov);
Cvar_RegisterVariable(&scr_stipple);
Cvar_RegisterVariable(&scr_refresh);
Cvar_RegisterVariable(&shownetgraph);
Cvar_RegisterVariable(&vid_touchscreen_outlinealpha);
Cvar_RegisterVariable(&vid_touchscreen_overlayalpha);
+ // if we want no console, turn it off here too
+ if (COM_CheckParm ("-noconsole"))
+ Cvar_SetQuick(&scr_conforcewhiledisconnected, "0");
+
Cmd_AddCommand ("sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
Cmd_AddCommand ("sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
Cmd_AddCommand ("screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
unsigned char *buffer2;
qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
qboolean png = (scr_screenshot_png.integer != 0) && !jpeg;
+ char vabuf[1024];
if (Cmd_Argc() == 2)
{
return;
}
}
+ else if (scr_screenshot_timestamp.integer)
+ {
+ int shotnumber100;
+
+ // TODO maybe make capturevideo and screenshot use similar name patterns?
+ if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0])
+ dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s%s", cl.worldbasename, scr_screenshot_name.string, Sys_TimeString("%Y%m%d%H%M%S"));
+ else
+ dpsnprintf(prefix_name, sizeof(prefix_name), "%s%s", scr_screenshot_name.string, Sys_TimeString("%Y%m%d%H%M%S"));
+
+ // find a file name to save it to
+ for (shotnumber100 = 0;shotnumber100 < 100;shotnumber100++)
+ if (!FS_SysFileExists(va(vabuf, sizeof(vabuf), "%s/screenshots/%s-%02d.tga", fs_gamedir, prefix_name, shotnumber100))
+ && !FS_SysFileExists(va(vabuf, sizeof(vabuf), "%s/screenshots/%s-%02d.jpg", fs_gamedir, prefix_name, shotnumber100))
+ && !FS_SysFileExists(va(vabuf, sizeof(vabuf), "%s/screenshots/%s-%02d.png", fs_gamedir, prefix_name, shotnumber100)))
+ break;
+ if (shotnumber100 >= 100)
+ {
+ Con_Print("Couldn't create the image file - already 100 shots taken this second!\n");
+ return;
+ }
+
+ dpsnprintf(filename, sizeof(filename), "screenshots/%s-%02d.%s", prefix_name, shotnumber100, jpeg ? "jpg" : png ? "png" : "tga");
+ }
else
{
// TODO maybe make capturevideo and screenshot use similar name patterns?
if (scr_screenshot_name_in_mapdir.integer && cl.worldbasename[0])
- dpsnprintf (prefix_name, sizeof(prefix_name), "%s/%s", cl.worldbasename, Sys_TimeString(scr_screenshot_name.string));
+ dpsnprintf(prefix_name, sizeof(prefix_name), "%s/%s", cl.worldbasename, Sys_TimeString(scr_screenshot_name.string));
else
- dpsnprintf (prefix_name, sizeof(prefix_name), "%s", Sys_TimeString(scr_screenshot_name.string));
+ dpsnprintf(prefix_name, sizeof(prefix_name), "%s", Sys_TimeString(scr_screenshot_name.string));
+ // if prefix changed, gamedir or map changed, reset the shotnumber so
+ // we scan again
+ // FIXME: should probably do this whenever FS_Rescan or something like that occurs?
if (strcmp(old_prefix_name, prefix_name))
{
dpsnprintf(old_prefix_name, sizeof(old_prefix_name), "%s", prefix_name );
// find a file name to save it to
for (;shotnumber < 1000000;shotnumber++)
- if (!FS_SysFileExists(va("%s/screenshots/%s%06d.tga", fs_gamedir, prefix_name, shotnumber)) && !FS_SysFileExists(va("%s/screenshots/%s%06d.jpg", fs_gamedir, prefix_name, shotnumber)) && !FS_SysFileExists(va("%s/screenshots/%s%06d.png", fs_gamedir, prefix_name, shotnumber)))
+ if (!FS_SysFileExists(va(vabuf, sizeof(vabuf), "%s/screenshots/%s%06d.tga", fs_gamedir, prefix_name, shotnumber))
+ && !FS_SysFileExists(va(vabuf, sizeof(vabuf), "%s/screenshots/%s%06d.jpg", fs_gamedir, prefix_name, shotnumber))
+ && !FS_SysFileExists(va(vabuf, sizeof(vabuf), "%s/screenshots/%s%06d.png", fs_gamedir, prefix_name, shotnumber)))
break;
if (shotnumber >= 1000000)
{
- Con_Print("Couldn't create the image file\n");
+ Con_Print("Couldn't create the image file - you already have 1000000 screenshots!\n");
return;
}
dpsnprintf(filename, sizeof(filename), "screenshots/%s%06d.%s", prefix_name, shotnumber, jpeg ? "jpg" : png ? "png" : "tga");
+
+ shotnumber++;
}
buffer1 = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 4);
Mem_Free (buffer1);
Mem_Free (buffer2);
-
- shotnumber++;
}
-void SCR_CaptureVideo_BeginVideo(void)
+static void SCR_CaptureVideo_BeginVideo(void)
{
double r, g, b;
unsigned int i;
cls.capturevideo.soundchannels = S_GetSoundChannels();
cls.capturevideo.startrealtime = realtime;
cls.capturevideo.frame = cls.capturevideo.lastfpsframe = 0;
- cls.capturevideo.starttime = cls.capturevideo.lastfpstime = Sys_DoubleTime();
+ cls.capturevideo.starttime = cls.capturevideo.lastfpstime = realtime;
cls.capturevideo.soundsampleframe = 0;
cls.capturevideo.realtime = cl_capturevideo_realtime.integer != 0;
cls.capturevideo.screenbuffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 4);
}
}
-void SCR_CaptureVideo_VideoFrame(int newframestepframenum)
+static void SCR_CaptureVideo_VideoFrame(int newframestepframenum)
{
int x = 0, y = 0;
int width = cls.capturevideo.width, height = cls.capturevideo.height;
if(cl_capturevideo_printfps.integer)
{
char buf[80];
- double t = Sys_DoubleTime();
+ double t = realtime;
if(t > cls.capturevideo.lastfpstime + 1)
{
double fps1 = (cls.capturevideo.frame - cls.capturevideo.lastfpsframe) / (t - cls.capturevideo.lastfpstime + 0.0000001);
cls.capturevideo.soundframe(paintbuffer, length);
}
-void SCR_CaptureVideo(void)
+static void SCR_CaptureVideo(void)
{
int newframenum;
if (cl_capturevideo.integer)
r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
+ r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
+ r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 4);
buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
{
int i;
char *lmplabel;
- lmplabel = MSG_ReadString();
+ lmplabel = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
for (i = 0;i < cl.num_showlmps;i++)
if (cl.showlmps[i].isactive && strcmp(cl.showlmps[i].label, lmplabel) == 0)
{
int k;
char lmplabel[256], picname[256];
float x, y;
- strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel));
- strlcpy (picname, MSG_ReadString(), sizeof (picname));
+ strlcpy (lmplabel,MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (lmplabel));
+ strlcpy (picname, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (picname));
if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
{
- x = MSG_ReadByte();
- y = MSG_ReadByte();
+ x = MSG_ReadByte(&cl_message);
+ y = MSG_ReadByte(&cl_message);
}
else
{
- x = MSG_ReadShort();
- y = MSG_ReadShort();
+ x = MSG_ReadShort(&cl_message);
+ y = MSG_ReadShort(&cl_message);
}
if (!cl.showlmps || cl.num_showlmps >= cl.max_showlmps)
{
}
}
-extern void R_UpdateFogColor(void);
void R_ClearScreen(qboolean fogcolor)
{
float clearcolor[4];
// clear to black
Vector4Clear(clearcolor);
- if (fogcolor)
+ if (fogcolor && r_fog_clear.integer)
{
- R_UpdateFogColor();
- if (r_fog_clear.integer)
- VectorCopy(r_refdef.fogcolor, clearcolor);
+ R_UpdateFog();
+ VectorCopy(r_refdef.fogcolor, clearcolor);
}
// clear depth is 1.0
// LordHavoc: we use a stencil centered around 128 instead of 0,
GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (vid.stencil ? GL_STENCIL_BUFFER_BIT : 0), clearcolor, 1.0f, 128);
}
-qboolean CL_VM_UpdateView (void);
-void SCR_DrawConsole (void);
-void R_Shadow_EditLights_DrawSelectedLightProperties(void);
-
int r_stereo_side;
-extern void Sbar_ShowFPS(void);
-void SCR_DrawScreen (void)
+static void SCR_DrawScreen (void)
{
Draw_Frame();
r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
+ r_refdef.view.ortho_x = atan(r_refdef.view.frustum_x) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView
+ r_refdef.view.ortho_y = atan(r_refdef.view.frustum_y) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView
if(!CL_VM_UpdateView())
R_RenderView();
-
- if (scr_zoomwindow.integer)
- {
- float sizex = bound(10, scr_zoomwindow_viewsizex.value, 100) / 100.0;
- float sizey = bound(10, scr_zoomwindow_viewsizey.value, 100) / 100.0;
- r_refdef.view.width = (int)(vid.width * sizex);
- r_refdef.view.height = (int)(vid.height * sizey);
- r_refdef.view.depth = 1;
- r_refdef.view.x = (int)((vid.width - r_refdef.view.width)/2);
- r_refdef.view.y = 0;
- r_refdef.view.z = 0;
-
- r_refdef.view.useperspective = true;
- r_refdef.view.frustum_y = tan(scr_zoomwindow_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
- r_refdef.view.frustum_x = r_refdef.view.frustum_y * vid_pixelheight.value * (float)r_refdef.view.width / (float)r_refdef.view.height;
-
- r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
- r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
-
- if(!CL_VM_UpdateView())
- R_RenderView();
- }
}
if (!r_stereo_sidebyside.integer && !r_stereo_horizontal.integer && !r_stereo_vertical.integer)
sscanf(scr_loadingscreen_barcolor.string, "%f %f %f", &colors[12], &colors[13], &colors[14]); colors[15] = 1;
R_Mesh_PrepareVertices_Generic_Arrays(4, verts, colors, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture(true, true);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
// make sure everything is cleared, including the progress indicator
{
r_viewport_t viewport;
float x, y, w, h, sw, sh, f;
+ char vabuf[1024];
// release mouse grab while loading
if (!vid.fullscreen)
VID_SetMouse(false, false, false);
// CHECKGLERROR
r_refdef.draw2dstage = true;
R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.width, vid.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
- R_Mesh_ResetRenderTargets();
+ R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
R_SetViewport(&viewport);
GL_ColorMask(1,1,1,1);
// when starting up a new video mode, make sure the screen is cleared to black
R_Mesh_Start();
R_EntityMatrix(&identitymatrix);
// draw the loading plaque
- loadingscreenpic = Draw_CachePic_Flags (loadingscreenpic_number ? va("gfx/loading%d", loadingscreenpic_number+1) : "gfx/loading", loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
+ loadingscreenpic = Draw_CachePic_Flags (loadingscreenpic_number ? va(vabuf, sizeof(vabuf), "gfx/loading%d", loadingscreenpic_number+1) : "gfx/loading", loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
w = loadingscreenpic->width;
h = loadingscreenpic->height;
if(loadingscreentexture)
{
R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreentexture_vertex3f, NULL, loadingscreentexture_texcoord2f);
- R_SetupShader_Generic(loadingscreentexture, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(loadingscreentexture, NULL, GL_MODULATE, 1, true, true, true);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
R_Mesh_PrepareVertices_Generic_Arrays(4, loadingscreenpic_vertex3f, NULL, loadingscreenpic_texcoord2f);
- R_SetupShader_Generic(Draw_GetPicTexture(loadingscreenpic), NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(Draw_GetPicTexture(loadingscreenpic), NULL, GL_MODULATE, 1, true, true, false);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
SCR_DrawLoadingStack();
}
}
loadingscreencleared = clear;
+#ifdef USE_GLES2
+ SCR_DrawLoadingScreen_SharedSetup(clear);
+ SCR_DrawLoadingScreen(clear);
+#else
if (qglDrawBuffer)
qglDrawBuffer(GL_BACK);
SCR_DrawLoadingScreen_SharedSetup(clear);
qglDrawBuffer(GL_BACK);
SCR_DrawLoadingScreen(clear);
}
+#endif
SCR_DrawLoadingScreen_SharedFinish(clear);
// this goes into the event loop, and should prevent unresponsive cursor on vista
extern cvar_t r_viewscale_fpsscaling;
static double cl_updatescreen_rendertime = 0;
static double cl_updatescreen_quality = 1;
-extern void Sbar_ShowFPS_Update(void);
void CL_UpdateScreen(void)
{
vec3_t vieworigin;
return;
}
- rendertime1 = Sys_DoubleTime();
+ rendertime1 = Sys_DirtyTime();
conwidth = bound(160, vid_conwidth.value, 32768);
conheight = bound(90, vid_conheight.value, 24576);
SCR_SetUpToDrawConsole();
+#ifndef USE_GLES2
if (qglDrawBuffer)
{
CHECKGLERROR
qglDisable(GL_DITHER);CHECKGLERROR
}
}
+#endif
R_Viewport_InitOrtho(&viewport, &identitymatrix, 0, 0, vid.width, vid.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
- R_Mesh_ResetRenderTargets();
+ R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
R_SetViewport(&viewport);
GL_ScissorTest(false);
GL_ColorMask(1,1,1,1);
f = pow((float)cl_updatescreen_quality, cl_minfps_qualitypower.value) * cl_minfps_qualityscale.value;
r_refdef.view.quality = bound(cl_minfps_qualitymin.value, f, cl_minfps_qualitymax.value);
+#ifndef USE_GLES2
if (qglPolygonStipple)
{
if(scr_stipple.integer)
qglDisable(GL_POLYGON_STIPPLE);CHECKGLERROR
}
}
+#endif
if (r_viewscale_fpsscaling.integer)
GL_Finish();
- drawscreenstart = Sys_DoubleTime();
+ drawscreenstart = Sys_DirtyTime();
+#ifndef USE_GLES2
if (R_Stereo_Active())
{
r_stereo_side = 0;
SCR_DrawScreen();
r_stereo_side = 1;
+ r_refdef.view.clear = true;
if (r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer)
{
SCR_DrawScreen();
}
else
+#endif
SCR_DrawScreen();
if (r_viewscale_fpsscaling.integer)
GL_Finish();
- r_refdef.lastdrawscreentime = Sys_DoubleTime() - drawscreenstart;
+ r_refdef.lastdrawscreentime = Sys_DirtyTime() - drawscreenstart;
SCR_CaptureVideo();
qglFlush(); // FIXME: should we really be using qglFlush here?
// quality adjustment according to render time
- cl_updatescreen_rendertime += ((Sys_DoubleTime() - rendertime1) - cl_updatescreen_rendertime) * bound(0, cl_minfps_fade.value, 1);
+ cl_updatescreen_rendertime += ((Sys_DirtyTime() - rendertime1) - cl_updatescreen_rendertime) * bound(0, cl_minfps_fade.value, 1);
if (cl_minfps.value > 0 && cl_updatescreen_rendertime > 0 && !cls.timedemo && (!cls.capturevideo.active || !cls.capturevideo.realtime))
cl_updatescreen_quality = 1 / (cl_updatescreen_rendertime * cl_minfps.value);
else
}
cl_video_subtitle_info_t;
-float CL_DrawVideo_WordWidthFunc(void *passthrough, const char *w, size_t *length, float maxWidth)
+static float CL_DrawVideo_WordWidthFunc(void *passthrough, const char *w, size_t *length, float maxWidth)
{
cl_video_subtitle_info_t *si = (cl_video_subtitle_info_t *) passthrough;
return 0;
}
-int CL_DrawVideo_DisplaySubtitleLine(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
+static int CL_DrawVideo_DisplaySubtitleLine(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
{
cl_video_subtitle_info_t *si = (cl_video_subtitle_info_t *) passthrough;
if (cl_video_stipple.integer || px != 0 || py != 0 || sx != vid_conwidth.integer || sy != vid_conheight.integer)
DrawQ_Fill(0, 0, vid_conwidth.integer, vid_conheight.integer, 0, 0, 0, 1, 0);
+#ifndef USE_GLES2
// enable video-only polygon stipple (of global stipple is not active)
if (qglPolygonStipple && !scr_stipple.integer && cl_video_stipple.integer)
{
}
qglPolygonStipple(stipple);CHECKGLERROR
}
+#endif
// draw video
DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, 0);
+#ifndef USE_GLES2
// disable video-only stipple
if (qglPolygonStipple && !scr_stipple.integer && cl_video_stipple.integer)
qglDisable(GL_POLYGON_STIPPLE);CHECKGLERROR
+#endif
// VorteX: draw subtitle_text
if (!video->subtitles || !cl_video_subtitles.integer)
void CL_VideoStart(char *filename, const char *subtitlesfile)
{
+ char vabuf[1024];
Host_StartVideo();
if( cl_videos->state != CLVIDEO_UNUSED )
CL_CloseVideo( cl_videos );
// already contains video/
- if( !OpenVideo( cl_videos, filename, va( CLDYNTEXTUREPREFIX "%s", filename ), 0, subtitlesfile ) )
+ if( !OpenVideo( cl_videos, filename, va(vabuf, sizeof(vabuf), CLDYNTEXTUREPREFIX "%s", filename ), 0, subtitlesfile ) )
return;
// expand the active range to include the new entry
cl_num_videos = max(cl_num_videos, 1);
unsigned int jam_getheight(void *stream);
double jam_getframerate(void *stream);
int jam_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow);
-void *jam_open(clvideo_t *video, char *filename, const char **errorstring)
+static void *jam_open(clvideo_t *video, char *filename, const char **errorstring)
{
unsigned char jamHead[16];
char *wavename;
// decode JAM frame
-void jam_decodeframe(unsigned char *inbuf, unsigned char *outbuf, unsigned char *prevbuf, int outsize, int frametype)
+static void jam_decodeframe(unsigned char *inbuf, unsigned char *outbuf, unsigned char *prevbuf, int outsize, int frametype)
{
unsigned char *srcptr, *destptr, *prevptr;
int bytesleft;
const char *formatextension;
qfile_t *videofile;
// always use this:
- // cls.capturevideo.videofile = FS_OpenRealFile(va("%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
+ // cls.capturevideo.videofile = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
void (*endvideo) (void);
void (*videoframes) (int num);
void (*soundframe) (const portable_sampleframe_t *paintbuffer, size_t length);
fs_offset_t demo_lastcsprogssize;
int demo_lastcsprogscrc;
qboolean demoplayback;
+ qboolean demostarting; // set if currently starting a demo, to stop -demo from quitting when switching to another demo
qboolean timedemo;
// -1 = use normal cd track
int forcetrack;
float CL_KeyState (kbutton_t *key);
-const char *Key_KeynumToString (int keynum);
+const char *Key_KeynumToString (int keynum, char *buf, size_t buflength);
int Key_StringToKeynum (const char *str);
//
// which color components to allow (for anaglyph glasses)
int colormask[4];
- // global RGB color multiplier for rendering, this is required by HDR
+ // global RGB color multiplier for rendering
float colorscale;
// whether to call R_ClearScreen before rendering stuff
qboolean clear;
// if true, don't clear or do any post process effects (bloom, etc)
qboolean isoverlay;
+ // if true, this is the MAIN view (which is, after CSQC, copied into the scene for use e.g. by r_speeds 1, showtex, prydon cursor)
+ qboolean ismain;
// whether to draw r_showtris and such, this is only true for the main
- // view render, all secondary renders (HDR, mirrors, portals, cameras,
+ // view render, all secondary renders (mirrors, portals, cameras,
// distortion effects, etc) omit such debugging information
qboolean showdebug;
extern r_refdef_t r_refdef;
+typedef enum waterlevel_e
+{
+ WATERLEVEL_NONE,
+ WATERLEVEL_WETFEET,
+ WATERLEVEL_SWIMMING,
+ WATERLEVEL_SUBMERGED
+}
+waterlevel_t;
+
+typedef struct cl_clientmovement_state_s
+{
+ // position
+ vec3_t origin;
+ vec3_t velocity;
+ // current bounding box (different if crouched vs standing)
+ vec3_t mins;
+ vec3_t maxs;
+ // currently on the ground
+ qboolean onground;
+ // currently crouching
+ qboolean crouched;
+ // what kind of water (SUPERCONTENTS_LAVA for instance)
+ int watertype;
+ // how deep
+ waterlevel_t waterlevel;
+ // weird hacks when jumping out of water
+ // (this is in seconds and counts down to 0)
+ float waterjumptime;
+
+ // user command
+ usercmd_t cmd;
+}
+cl_clientmovement_state_t;
+void CL_ClientMovement_PlayerMove(cl_clientmovement_state_t *s);
+
// warpzone prediction hack (CSQC builtin)
void CL_RotateMoves(const matrix4x4_t *m);
+void CL_NewFrameReceived(int num);
+void CL_ParseEntityLump(char *entitystring);
+void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
+void CL_RelinkLightFlashes(void);
+void Sbar_ShowFPS(void);
+void Sbar_ShowFPS_Update(void);
+void Host_SaveConfig(void);
+void Host_LoadConfig_f(void);
+void CL_UpdateMoveVars(void);
+void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length);
+void V_DriftPitch(void);
+void V_FadeViewFlashs(void);
+void V_CalcViewBlend(void);
+void V_CalcRefdefUsing(const matrix4x4_t *entrendermatrix, const vec3_t clviewangles, qboolean teleported, qboolean clonground, qboolean clcmdjump);
+void V_CalcRefdef(void);
+void CL_Locs_Reload_f(void);
+
#endif
extern cvar_t v_flipped;
extern cvar_t r_equalize_entities_fullbright;
-sfx_t *S_FindName(const char *name);
-int Sbar_GetSortedPlayerIndex (int index);
-void Sbar_SortFrags (void);
-void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
-void CSQC_RelinkAllEntities (int drawmask);
-void CSQC_RelinkCSQCEntities (void);
+r_refdef_view_t csqc_original_r_refdef_view;
+r_refdef_view_t csqc_main_r_refdef_view;
// #1 void(vector ang) makevectors
-static void VM_CL_makevectors (void)
+static void VM_CL_makevectors (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_makevectors);
AngleVectors (PRVM_G_VECTOR(OFS_PARM0), PRVM_clientglobalvector(v_forward), PRVM_clientglobalvector(v_right), PRVM_clientglobalvector(v_up));
}
// #2 void(entity e, vector o) setorigin
-void VM_CL_setorigin (void)
+static void VM_CL_setorigin (prvm_prog_t *prog)
{
prvm_edict_t *e;
float *org;
e = PRVM_G_EDICT(OFS_PARM0);
if (e == prog->edicts)
{
- VM_Warning("setorigin: can not modify world entity\n");
+ VM_Warning(prog, "setorigin: can not modify world entity\n");
return;
}
if (e->priv.required->free)
{
- VM_Warning("setorigin: can not modify free entity\n");
+ VM_Warning(prog, "setorigin: can not modify free entity\n");
return;
}
org = PRVM_G_VECTOR(OFS_PARM1);
VectorCopy (org, PRVM_clientedictvector(e, origin));
+ if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
+ e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
CL_LinkEdict(e);
}
-static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max)
+static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max)
{
int i;
for (i=0 ; i<3 ; i++)
if (min[i] > max[i])
- PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
+ prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
// set derived values
VectorCopy (min, PRVM_clientedictvector(e, mins));
}
// #3 void(entity e, string m) setmodel
-void VM_CL_setmodel (void)
+static void VM_CL_setmodel (prvm_prog_t *prog)
{
prvm_edict_t *e;
const char *m;
if (!strcmp(cl.csqc_model_precache[i]->name, m))
{
mod = cl.csqc_model_precache[i];
- PRVM_clientedictstring(e, model) = PRVM_SetEngineString(mod->name);
+ PRVM_clientedictstring(e, model) = PRVM_SetEngineString(prog, mod->name);
PRVM_clientedictfloat(e, modelindex) = -(i+1);
break;
}
mod = cl.model_precache[i];
if (mod && !strcmp(mod->name, m))
{
- PRVM_clientedictstring(e, model) = PRVM_SetEngineString(mod->name);
+ PRVM_clientedictstring(e, model) = PRVM_SetEngineString(prog, mod->name);
PRVM_clientedictfloat(e, modelindex) = i;
break;
}
}
else
{
- SetMinMaxSize (e, vec3_origin, vec3_origin);
- VM_Warning ("setmodel: model '%s' not precached\n", m);
+ SetMinMaxSize (prog, e, vec3_origin, vec3_origin);
+ VM_Warning(prog, "setmodel: model '%s' not precached\n", m);
}
}
// #4 void(entity e, vector min, vector max) setsize
-static void VM_CL_setsize (void)
+static void VM_CL_setsize (prvm_prog_t *prog)
{
prvm_edict_t *e;
float *min, *max;
e = PRVM_G_EDICT(OFS_PARM0);
if (e == prog->edicts)
{
- VM_Warning("setsize: can not modify world entity\n");
+ VM_Warning(prog, "setsize: can not modify world entity\n");
return;
}
if (e->priv.server->free)
{
- VM_Warning("setsize: can not modify free entity\n");
+ VM_Warning(prog, "setsize: can not modify free entity\n");
return;
}
min = PRVM_G_VECTOR(OFS_PARM1);
max = PRVM_G_VECTOR(OFS_PARM2);
- SetMinMaxSize( e, min, max );
+ SetMinMaxSize( prog, e, min, max );
CL_LinkEdict(e);
}
// #8 void(entity e, float chan, string samp, float volume, float atten) sound
-static void VM_CL_sound (void)
+static void VM_CL_sound (prvm_prog_t *prog)
{
const char *sample;
int channel;
if (volume < 0 || volume > 1)
{
- VM_Warning("VM_CL_sound: volume must be in range 0-1\n");
+ VM_Warning(prog, "VM_CL_sound: volume must be in range 0-1\n");
return;
}
if (attenuation < 0 || attenuation > 4)
{
- VM_Warning("VM_CL_sound: attenuation must be in range 0-4\n");
+ VM_Warning(prog, "VM_CL_sound: attenuation must be in range 0-4\n");
return;
}
if (!IS_CHAN(channel))
{
- VM_Warning("VM_CL_sound: channel must be in range 0-127\n");
+ VM_Warning(prog, "VM_CL_sound: channel must be in range 0-127\n");
return;
}
CL_VM_GetEntitySoundOrigin(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), org);
- S_StartSound(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), org, volume, attenuation);
+ S_StartSound_StartPosition_Flags(MAX_EDICTS + PRVM_NUM_FOR_EDICT(entity), channel, S_FindName(sample), org, volume, attenuation, 0, flags, pitchchange > 0.0f ? pitchchange * 0.01f : 1.0f);
}
// #483 void(vector origin, string sample, float volume, float attenuation) pointsound
-static void VM_CL_pointsound(void)
+static void VM_CL_pointsound(prvm_prog_t *prog)
{
const char *sample;
float volume;
if (volume < 0 || volume > 1)
{
- VM_Warning("VM_CL_pointsound: volume must be in range 0-1\n");
+ VM_Warning(prog, "VM_CL_pointsound: volume must be in range 0-1\n");
return;
}
if (attenuation < 0 || attenuation > 4)
{
- VM_Warning("VM_CL_pointsound: attenuation must be in range 0-4\n");
+ VM_Warning(prog, "VM_CL_pointsound: attenuation must be in range 0-4\n");
return;
}
}
// #14 entity() spawn
-static void VM_CL_spawn (void)
+static void VM_CL_spawn (prvm_prog_t *prog)
{
prvm_edict_t *ed;
- ed = PRVM_ED_Alloc();
+ ed = PRVM_ED_Alloc(prog);
VM_RETURN_EDICT(ed);
}
-void CL_VM_SetTraceGlobals(const trace_t *trace, int svent)
+static void CL_VM_SetTraceGlobals(prvm_prog_t *prog, const trace_t *trace, int svent)
{
- VM_SetTraceGlobals(trace);
+ VM_SetTraceGlobals(prog, trace);
PRVM_clientglobalfloat(trace_networkentity) = svent;
}
#define CL_HitNetworkPlayers(move) !((move) == MOVE_WORLDONLY || (move) == MOVE_NOMONSTERS)
// #16 void(vector v1, vector v2, float movetype, entity ignore) traceline
-static void VM_CL_traceline (void)
+static void VM_CL_traceline (prvm_prog_t *prog)
{
float *v1, *v2;
trace_t trace;
ent = PRVM_G_EDICT(OFS_PARM3);
if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
- PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
+ prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = CL_TraceLine(v1, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true, false);
- CL_VM_SetTraceGlobals(&trace, svent);
+ CL_VM_SetTraceGlobals(prog, &trace, svent);
// R_TimeReport("traceline");
}
=================
*/
// LordHavoc: added this for my own use, VERY useful, similar to traceline
-static void VM_CL_tracebox (void)
+static void VM_CL_tracebox (prvm_prog_t *prog)
{
float *v1, *v2, *m1, *m2;
trace_t trace;
ent = PRVM_G_EDICT(OFS_PARM5);
if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
- PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
+ prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = CL_TraceBox(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true);
- CL_VM_SetTraceGlobals(&trace, svent);
+ CL_VM_SetTraceGlobals(prog, &trace, svent);
// R_TimeReport("tracebox");
}
-trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
+static trace_t CL_Trace_Toss (prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent)
{
int i;
float gravity;
return trace;
}
-static void VM_CL_tracetoss (void)
+static void VM_CL_tracetoss (prvm_prog_t *prog)
{
trace_t trace;
prvm_edict_t *ent;
ent = PRVM_G_EDICT(OFS_PARM0);
if (ent == prog->edicts)
{
- VM_Warning("tracetoss: can not use world entity\n");
+ VM_Warning(prog, "tracetoss: can not use world entity\n");
return;
}
ignore = PRVM_G_EDICT(OFS_PARM1);
- trace = CL_Trace_Toss (ent, ignore, &svent);
+ trace = CL_Trace_Toss (prog, ent, ignore, &svent);
- CL_VM_SetTraceGlobals(&trace, svent);
+ CL_VM_SetTraceGlobals(prog, &trace, svent);
}
// #20 void(string s) precache_model
-void VM_CL_precache_model (void)
+static void VM_CL_precache_model (prvm_prog_t *prog)
{
const char *name;
int i;
return;
}
}
- VM_Warning("VM_CL_precache_model: no free models\n");
+ VM_Warning(prog, "VM_CL_precache_model: no free models\n");
return;
}
- VM_Warning("VM_CL_precache_model: model \"%s\" not found\n", name);
+ VM_Warning(prog, "VM_CL_precache_model: model \"%s\" not found\n", name);
}
-int CSQC_EntitiesInBox (vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
+static int CSQC_EntitiesInBox (prvm_prog_t *prog, vec3_t mins, vec3_t maxs, int maxlist, prvm_edict_t **list)
{
prvm_edict_t *ent;
int i, k;
}
// #22 entity(vector org, float rad) findradius
-static void VM_CL_findradius (void)
+static void VM_CL_findradius (prvm_prog_t *prog)
{
prvm_edict_t *ent, *chain;
vec_t radius, radius2;
else
chainfield = prog->fieldoffsets.chain;
if(chainfield < 0)
- PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
+ prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
chain = (prvm_edict_t *)prog->edicts;
maxs[0] = org[0] + (radius + 1);
maxs[1] = org[1] + (radius + 1);
maxs[2] = org[2] + (radius + 1);
- numtouchedicts = CSQC_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = CSQC_EntitiesInBox(prog, mins, maxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens //[515]: for what then ?
}
// #34 float() droptofloor
-static void VM_CL_droptofloor (void)
+static void VM_CL_droptofloor (prvm_prog_t *prog)
{
prvm_edict_t *ent;
vec3_t end;
ent = PRVM_PROG_TO_EDICT(PRVM_clientglobaledict(self));
if (ent == prog->edicts)
{
- VM_Warning("droptofloor: can not modify world entity\n");
+ VM_Warning(prog, "droptofloor: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("droptofloor: can not modify free entity\n");
+ VM_Warning(prog, "droptofloor: can not modify free entity\n");
return;
}
}
// #35 void(float style, string value) lightstyle
-static void VM_CL_lightstyle (void)
+static void VM_CL_lightstyle (prvm_prog_t *prog)
{
int i;
const char *c;
c = PRVM_G_STRING(OFS_PARM1);
if (i >= cl.max_lightstyle)
{
- VM_Warning("VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
+ VM_Warning(prog, "VM_CL_lightstyle >= MAX_LIGHTSTYLES\n");
return;
}
strlcpy (cl.lightstyle[i].map, c, sizeof (cl.lightstyle[i].map));
}
// #40 float(entity e) checkbottom
-static void VM_CL_checkbottom (void)
+static void VM_CL_checkbottom (prvm_prog_t *prog)
{
static int cs_yes, cs_no;
prvm_edict_t *ent;
}
// #41 float(vector v) pointcontents
-static void VM_CL_pointcontents (void)
+static void VM_CL_pointcontents (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_pointcontents);
PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, CL_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
}
// #48 void(vector o, vector d, float color, float count) particle
-static void VM_CL_particle (void)
+static void VM_CL_particle (prvm_prog_t *prog)
{
float *org, *dir;
int count;
}
// #74 void(vector pos, string samp, float vol, float atten) ambientsound
-static void VM_CL_ambientsound (void)
+static void VM_CL_ambientsound (prvm_prog_t *prog)
{
float *f;
sfx_t *s;
}
// #92 vector(vector org[, float lpflag]) getlight (DP_QC_GETLIGHT)
-static void VM_CL_getlight (void)
+static void VM_CL_getlight (prvm_prog_t *prog)
{
vec3_t ambientcolor, diffusecolor, diffusenormal;
vec_t *p;
- VM_SAFEPARMCOUNTRANGE(1, 2, VM_CL_getlight);
+ VM_SAFEPARMCOUNTRANGE(1, 3, VM_CL_getlight);
p = PRVM_G_VECTOR(OFS_PARM0);
VectorClear(ambientcolor);
else if (cl.worldmodel && cl.worldmodel->brush.LightPoint)
cl.worldmodel->brush.LightPoint(cl.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
+ if (PRVM_clientglobalvector(getlight_ambient))
+ VectorCopy(ambientcolor, PRVM_clientglobalvector(getlight_ambient));
+ if (PRVM_clientglobalvector(getlight_diffuse))
+ VectorCopy(diffusecolor, PRVM_clientglobalvector(getlight_diffuse));
+ if (PRVM_clientglobalvector(getlight_dir))
+ VectorCopy(diffusenormal, PRVM_clientglobalvector(getlight_dir));
}
//============================================================================
//[515]: SCENE MANAGER builtins
-extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed, int edictnum);//csprogs.c
void CSQC_R_RecalcView (void)
{
Matrix4x4_Concat(&viewmodelmatrix_withbob, &r_refdef.view.matrix, &cl.csqc_viewmodelmatrixfromengine);
}
-void CL_RelinkLightFlashes(void);
//#300 void() clearscene (EXT_CSQC)
-void VM_CL_R_ClearScene (void)
+static void VM_CL_R_ClearScene (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
// clear renderable entity and light lists
r_refdef.scene.numentities = 0;
r_refdef.scene.numlights = 0;
- // FIXME: restore these to the values from VM_CL_UpdateView
- r_refdef.view.x = 0;
- r_refdef.view.y = 0;
- r_refdef.view.z = 0;
- r_refdef.view.width = vid.width;
- r_refdef.view.height = vid.height;
- r_refdef.view.depth = 1;
- // FIXME: restore frustum_x/frustum_y
- r_refdef.view.useperspective = true;
- r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
- r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
- r_refdef.view.frustum_x *= r_refdef.frustumscale_x;
- r_refdef.view.frustum_y *= r_refdef.frustumscale_y;
- r_refdef.view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
- r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0);
- r_refdef.view.clear = true;
- r_refdef.view.isoverlay = false;
+ // restore the view settings to the values that VM_CL_UpdateView received from the client code
+ r_refdef.view = csqc_original_r_refdef_view;
VectorCopy(cl.csqc_vieworiginfromengine, cl.csqc_vieworigin);
VectorCopy(cl.csqc_viewanglesfromengine, cl.csqc_viewangles);
cl.csqc_vidvars.drawworld = r_drawworld.integer != 0;
}
//#301 void(float mask) addentities (EXT_CSQC)
-extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
-extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
-void VM_CL_R_AddEntities (void)
+static void VM_CL_R_AddEntities (prvm_prog_t *prog)
{
- double t = Sys_DoubleTime();
+ double t = Sys_DirtyTime();
int i, drawmask;
prvm_edict_t *ed;
VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities);
}
// callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView
- prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
+ t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+ prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
}
//#302 void(entity ent) addentity (EXT_CSQC)
-void VM_CL_R_AddEntity (void)
+static void VM_CL_R_AddEntity (prvm_prog_t *prog)
{
- double t = Sys_DoubleTime();
+ double t = Sys_DirtyTime();
VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0), 0);
- prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
+ t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+ prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
}
//#303 float(float property, ...) setproperty (EXT_CSQC)
//#303 float(float property) getproperty
//#303 vector(float property) getpropertyvec
+//#309 float(float property) getproperty
+//#309 vector(float property) getpropertyvec
// VorteX: make this function be able to return previously set property if new value is not given
-void VM_CL_R_SetView (void)
+static void VM_CL_R_SetView (prvm_prog_t *prog)
{
int c;
float *f;
PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.height;
break;
case VF_VIEWPORT:
- VM_Warning("VM_CL_R_GetView : VF_VIEWPORT can't be retrieved, use VF_MIN/VF_SIZE instead\n");
+ VM_Warning(prog, "VM_CL_R_GetView : VF_VIEWPORT can't be retrieved, use VF_MIN/VF_SIZE instead\n");
break;
case VF_FOV:
VectorSet(PRVM_G_VECTOR(OFS_RETURN), r_refdef.view.ortho_x, r_refdef.view.ortho_y, 0);
case VF_CLEARSCREEN:
PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.isoverlay;
break;
+ case VF_MAINVIEW:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.ismain;
+ break;
+ case VF_FOG_DENSITY:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_density;
+ break;
+ case VF_FOG_COLOR:
+ PRVM_G_VECTOR(OFS_RETURN)[0] = r_refdef.fog_red;
+ PRVM_G_VECTOR(OFS_RETURN)[1] = r_refdef.fog_green;
+ PRVM_G_VECTOR(OFS_RETURN)[2] = r_refdef.fog_blue;
+ break;
+ case VF_FOG_COLOR_R:
+ PRVM_G_VECTOR(OFS_RETURN)[0] = r_refdef.fog_red;
+ break;
+ case VF_FOG_COLOR_G:
+ PRVM_G_VECTOR(OFS_RETURN)[1] = r_refdef.fog_green;
+ break;
+ case VF_FOG_COLOR_B:
+ PRVM_G_VECTOR(OFS_RETURN)[2] = r_refdef.fog_blue;
+ break;
+ case VF_FOG_ALPHA:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_alpha;
+ break;
+ case VF_FOG_START:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_start;
+ break;
+ case VF_FOG_END:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_end;
+ break;
+ case VF_FOG_HEIGHT:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_height;
+ break;
+ case VF_FOG_FADEDEPTH:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_fadedepth;
+ break;
default:
PRVM_G_FLOAT(OFS_RETURN) = 0;
- VM_Warning("VM_CL_R_GetView : unknown parm %i\n", c);
+ VM_Warning(prog, "VM_CL_R_GetView : unknown parm %i\n", c);
return;
}
return;
case VF_CLEARSCREEN:
r_refdef.view.isoverlay = !k;
break;
+ case VF_MAINVIEW:
+ PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.ismain;
+ break;
+ case VF_FOG_DENSITY:
+ r_refdef.fog_density = k;
+ break;
+ case VF_FOG_COLOR:
+ r_refdef.fog_red = f[0];
+ r_refdef.fog_green = f[1];
+ r_refdef.fog_blue = f[2];
+ break;
+ case VF_FOG_COLOR_R:
+ r_refdef.fog_red = k;
+ break;
+ case VF_FOG_COLOR_G:
+ r_refdef.fog_green = k;
+ break;
+ case VF_FOG_COLOR_B:
+ r_refdef.fog_blue = k;
+ break;
+ case VF_FOG_ALPHA:
+ r_refdef.fog_alpha = k;
+ break;
+ case VF_FOG_START:
+ r_refdef.fog_start = k;
+ break;
+ case VF_FOG_END:
+ r_refdef.fog_end = k;
+ break;
+ case VF_FOG_HEIGHT:
+ r_refdef.fog_height = k;
+ break;
+ case VF_FOG_FADEDEPTH:
+ r_refdef.fog_fadedepth = k;
+ break;
default:
PRVM_G_FLOAT(OFS_RETURN) = 0;
- VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
+ VM_Warning(prog, "VM_CL_R_SetView : unknown parm %i\n", c);
return;
}
PRVM_G_FLOAT(OFS_RETURN) = 1;
}
//#305 void(vector org, float radius, vector lightcolours[, float style, string cubemapname, float pflags]) adddynamiclight (EXT_CSQC)
-void VM_CL_R_AddDynamicLight (void)
+static void VM_CL_R_AddDynamicLight (prvm_prog_t *prog)
{
- double t = Sys_DoubleTime();
+ double t = Sys_DirtyTime();
vec_t *org;
float radius = 300;
vec_t *col;
R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++;
- prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
+ t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+ prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
}
//============================================================================
//#310 vector (vector v) cs_unproject (EXT_CSQC)
-static void VM_CL_unproject (void)
+static void VM_CL_unproject (prvm_prog_t *prog)
{
float *f;
vec3_t temp;
}
//#311 vector (vector v) cs_project (EXT_CSQC)
-static void VM_CL_project (void)
+static void VM_CL_project (prvm_prog_t *prog)
{
float *f;
vec3_t v;
}
//#330 float(float stnum) getstatf (EXT_CSQC)
-static void VM_CL_getstatf (void)
+static void VM_CL_getstatf (prvm_prog_t *prog)
{
int i;
union
i = (int)PRVM_G_FLOAT(OFS_PARM0);
if(i < 0 || i >= MAX_CL_STATS)
{
- VM_Warning("VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
+ VM_Warning(prog, "VM_CL_getstatf: index>=MAX_CL_STATS or index<0\n");
return;
}
dat.l = cl.stats[i];
}
//#331 float(float stnum) getstati (EXT_CSQC)
-static void VM_CL_getstati (void)
+static void VM_CL_getstati (prvm_prog_t *prog)
{
int i, index;
int firstbit, bitcount;
if(index < 0 || index >= MAX_CL_STATS)
{
- VM_Warning("VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
+ VM_Warning(prog, "VM_CL_getstati: index>=MAX_CL_STATS or index<0\n");
return;
}
i = cl.stats[index];
}
//#332 string(float firststnum) getstats (EXT_CSQC)
-static void VM_CL_getstats (void)
+static void VM_CL_getstats (prvm_prog_t *prog)
{
int i;
char t[17];
if(i < 0 || i > MAX_CL_STATS-4)
{
PRVM_G_INT(OFS_RETURN) = OFS_NULL;
- VM_Warning("VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
+ VM_Warning(prog, "VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
return;
}
strlcpy(t, (char*)&cl.stats[i], sizeof(t));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
}
//#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
-static void VM_CL_setmodelindex (void)
+static void VM_CL_setmodelindex (prvm_prog_t *prog)
{
int i;
prvm_edict_t *t;
model = CL_GetModelByIndex(i);
if (!model)
{
- VM_Warning("VM_CL_setmodelindex: null model\n");
+ VM_Warning(prog, "VM_CL_setmodelindex: null model\n");
return;
}
- PRVM_clientedictstring(t, model) = PRVM_SetEngineString(model->name);
+ PRVM_clientedictstring(t, model) = PRVM_SetEngineString(prog, model->name);
PRVM_clientedictfloat(t, modelindex) = i;
// TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black]
if (model)
{
- SetMinMaxSize (t, model->normalmins, model->normalmaxs);
+ SetMinMaxSize (prog, t, model->normalmins, model->normalmaxs);
}
else
- SetMinMaxSize (t, vec3_origin, vec3_origin);
+ SetMinMaxSize (prog, t, vec3_origin, vec3_origin);
}
//#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
-static void VM_CL_modelnameforindex (void)
+static void VM_CL_modelnameforindex (prvm_prog_t *prog)
{
dp_model_t *model;
PRVM_G_INT(OFS_RETURN) = OFS_NULL;
model = CL_GetModelByIndex((int)PRVM_G_FLOAT(OFS_PARM0));
- PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(model->name) : 0;
+ PRVM_G_INT(OFS_RETURN) = model ? PRVM_SetEngineString(prog, model->name) : 0;
}
//#335 float(string effectname) particleeffectnum (EXT_CSQC)
-static void VM_CL_particleeffectnum (void)
+static void VM_CL_particleeffectnum (prvm_prog_t *prog)
{
int i;
VM_SAFEPARMCOUNT(1, VM_CL_particleeffectnum);
}
// #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC)
-static void VM_CL_trailparticles (void)
+static void VM_CL_trailparticles (prvm_prog_t *prog)
{
int i;
float *start, *end;
}
//#337 void(float effectnum, vector origin, vector dir, float count[, float color]) pointparticles (EXT_CSQC)
-static void VM_CL_pointparticles (void)
+static void VM_CL_pointparticles (prvm_prog_t *prog)
{
int i;
float n;
}
//#502 void(float effectnum, entity own, vector origin_from, vector origin_to, vector dir_from, vector dir_to, float count, float extflags) boxparticles (DP_CSQC_BOXPARTICLES)
-static void VM_CL_boxparticles (void)
+static void VM_CL_boxparticles (prvm_prog_t *prog)
{
int effectnum;
// prvm_edict_t *own;
}
//#531 void(float pause) setpause
-static void VM_CL_setpause(void)
+static void VM_CL_setpause(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_setpause);
if ((int)PRVM_G_FLOAT(OFS_PARM0) != 0)
cl.csqc_paused = false;
}
-//#343 void(float usecursor) setcursormode (EXT_CSQC)
-static void VM_CL_setcursormode (void)
+//#343 void(float usecursor) setcursormode (DP_CSQC)
+static void VM_CL_setcursormode (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_setcursormode);
cl.csqc_wantsmousemove = PRVM_G_FLOAT(OFS_PARM0) != 0;
cl_ignoremousemoves = 2;
}
-//#344 vector() getmousepos (EXT_CSQC)
-static void VM_CL_getmousepos(void)
+//#344 vector() getmousepos (DP_CSQC)
+static void VM_CL_getmousepos(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_CL_getmousepos);
}
//#345 float(float framenum) getinputstate (EXT_CSQC)
-static void VM_CL_getinputstate (void)
+static void VM_CL_getinputstate (prvm_prog_t *prog)
{
int i, frame;
VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
PRVM_clientglobalvector(input_movevalues)[1] = cl.movecmd[i].sidemove;
PRVM_clientglobalvector(input_movevalues)[2] = cl.movecmd[i].upmove;
PRVM_clientglobalfloat(input_timelength) = cl.movecmd[i].frametime;
+ // this probably shouldn't be here
if(cl.movecmd[i].crouch)
{
VectorCopy(cl.playercrouchmins, PRVM_clientglobalvector(pmove_mins));
}
//#346 void(float sens) setsensitivityscaler (EXT_CSQC)
-static void VM_CL_setsensitivityscale (void)
+static void VM_CL_setsensitivityscale (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_setsensitivityscale);
cl.sensitivityscale = PRVM_G_FLOAT(OFS_PARM0);
}
//#347 void() runstandardplayerphysics (EXT_CSQC)
-static void VM_CL_runplayerphysics (void)
+#define PMF_JUMP_HELD 1
+#define PMF_LADDER 2 // not used by DP
+#define PMF_DUCKED 4 // FIXME FTEQW doesn't have this for Q1 like movement
+static void VM_CL_runplayerphysics (prvm_prog_t *prog)
{
+ cl_clientmovement_state_t s;
+ prvm_edict_t *ent;
+
+ VM_SAFEPARMCOUNT(1, VM_CL_runplayerphysics);
+
+ ent = PRVM_G_EDICT(OFS_PARM0);
+ VectorCopy(PRVM_clientedictvector(ent, origin), s.origin);
+ VectorCopy(PRVM_clientedictvector(ent, velocity), s.velocity);
+ VectorCopy(PRVM_clientedictvector(ent, mins), s.mins);
+ VectorCopy(PRVM_clientedictvector(ent, maxs), s.maxs);
+ s.crouched = ((int)PRVM_clientedictfloat(ent, pmove_flags) & PMF_DUCKED) != 0;
+ s.waterjumptime = 0; // FIXME where do we get this from? FTEQW lacks support for this too
+ VectorCopy(PRVM_clientglobalvector(input_angles), s.cmd.viewangles);
+ s.cmd.forwardmove = PRVM_clientglobalvector(input_movevalues)[0];
+ s.cmd.sidemove = PRVM_clientglobalvector(input_movevalues)[1];
+ s.cmd.upmove = PRVM_clientglobalvector(input_movevalues)[2];
+ s.cmd.buttons = PRVM_clientglobalfloat(input_buttons);
+ s.cmd.frametime = PRVM_clientglobalfloat(input_timelength);
+ s.cmd.canjump = ((int)PRVM_clientedictfloat(ent, pmove_flags) & PMF_JUMP_HELD) == 0;
+ s.cmd.jump = (s.cmd.buttons & 2) != 0;
+ s.cmd.crouch = (s.cmd.buttons & 16) != 0;
+
+ CL_ClientMovement_PlayerMove(&s);
+
+ VectorCopy(s.origin, PRVM_clientedictvector(ent, origin));
+ VectorCopy(s.velocity, PRVM_clientedictvector(ent, velocity));
+ PRVM_clientedictfloat(ent, pmove_flags) =
+ (s.crouched ? PMF_DUCKED : 0) |
+ (s.cmd.canjump ? 0 : PMF_JUMP_HELD);
}
//#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
-static void VM_CL_getplayerkey (void)
+static void VM_CL_getplayerkey (prvm_prog_t *prog)
{
int i;
char t[128];
}
if(!t[0])
return;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
}
//#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
-static void VM_CL_setlistener (void)
+static void VM_CL_setlistener (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(4, VM_CL_setlistener);
Matrix4x4_FromVectors(&cl.csqc_listenermatrix, PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), PRVM_G_VECTOR(OFS_PARM3), PRVM_G_VECTOR(OFS_PARM0));
}
//#352 void(string cmdname) registercommand (EXT_CSQC)
-static void VM_CL_registercmd (void)
+static void VM_CL_registercmd (prvm_prog_t *prog)
{
char *t;
VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
}
//#360 float() readbyte (EXT_CSQC)
-static void VM_CL_ReadByte (void)
+static void VM_CL_ReadByte (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadByte);
- PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte();
+ PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadByte(&cl_message);
}
//#361 float() readchar (EXT_CSQC)
-static void VM_CL_ReadChar (void)
+static void VM_CL_ReadChar (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadChar);
- PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar();
+ PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadChar(&cl_message);
}
//#362 float() readshort (EXT_CSQC)
-static void VM_CL_ReadShort (void)
+static void VM_CL_ReadShort (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadShort);
- PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort();
+ PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadShort(&cl_message);
}
//#363 float() readlong (EXT_CSQC)
-static void VM_CL_ReadLong (void)
+static void VM_CL_ReadLong (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadLong);
- PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong();
+ PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadLong(&cl_message);
}
//#364 float() readcoord (EXT_CSQC)
-static void VM_CL_ReadCoord (void)
+static void VM_CL_ReadCoord (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadCoord);
- PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(cls.protocol);
+ PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(&cl_message, cls.protocol);
}
//#365 float() readangle (EXT_CSQC)
-static void VM_CL_ReadAngle (void)
+static void VM_CL_ReadAngle (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadAngle);
- PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(cls.protocol);
+ PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(&cl_message, cls.protocol);
}
//#366 string() readstring (EXT_CSQC)
-static void VM_CL_ReadString (void)
+static void VM_CL_ReadString (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadString);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(MSG_ReadString());
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
}
//#367 float() readfloat (EXT_CSQC)
-static void VM_CL_ReadFloat (void)
+static void VM_CL_ReadFloat (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ReadFloat);
- PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
+ PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat(&cl_message);
}
//#501 string() readpicture (DP_CSQC_READWRITEPICTURE)
extern cvar_t cl_readpicture_force;
-static void VM_CL_ReadPicture (void)
+static void VM_CL_ReadPicture (prvm_prog_t *prog)
{
const char *name;
unsigned char *data;
VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture);
- name = MSG_ReadString();
- size = MSG_ReadShort();
+ name = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+ size = MSG_ReadShort(&cl_message);
// check if a texture of that name exists
// if yes, it is used and the data is discarded
// texture found and loaded
// skip over the jpeg as we don't need it
for(i = 0; i < size; ++i)
- (void) MSG_ReadByte();
+ (void) MSG_ReadByte(&cl_message);
}
else
{
// texture not found
// use the attached jpeg as texture
buf = (unsigned char *) Mem_Alloc(tempmempool, size);
- MSG_ReadBytes(size, buf);
+ MSG_ReadBytes(&cl_message, size, buf);
data = JPEG_LoadImage_BGRA(buf, size, NULL);
Mem_Free(buf);
Draw_NewPic(name, image_width, image_height, false, data);
}
}
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(name);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, name);
}
//////////////////////////////////////////////////////////
-static void VM_CL_makestatic (void)
+static void VM_CL_makestatic (prvm_prog_t *prog)
{
prvm_edict_t *ent;
ent = PRVM_G_EDICT(OFS_PARM0);
if (ent == prog->edicts)
{
- VM_Warning("makestatic: can not modify world entity\n");
+ VM_Warning(prog, "makestatic: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("makestatic: can not modify free entity\n");
+ VM_Warning(prog, "makestatic: can not modify free entity\n");
return;
}
Con_Printf("Too many static entities");
// throw the entity away now
- PRVM_ED_Free (ent);
+ PRVM_ED_Free(prog, ent);
}
//=================================================================//
copyentity(src, dst)
=================
*/
-static void VM_CL_copyentity (void)
+static void VM_CL_copyentity (prvm_prog_t *prog)
{
prvm_edict_t *in, *out;
VM_SAFEPARMCOUNT(2, VM_CL_copyentity);
in = PRVM_G_EDICT(OFS_PARM0);
if (in == prog->edicts)
{
- VM_Warning("copyentity: can not read world entity\n");
+ VM_Warning(prog, "copyentity: can not read world entity\n");
return;
}
if (in->priv.server->free)
{
- VM_Warning("copyentity: can not read free entity\n");
+ VM_Warning(prog, "copyentity: can not read free entity\n");
return;
}
out = PRVM_G_EDICT(OFS_PARM1);
if (out == prog->edicts)
{
- VM_Warning("copyentity: can not modify world entity\n");
+ VM_Warning(prog, "copyentity: can not modify world entity\n");
return;
}
if (out->priv.server->free)
{
- VM_Warning("copyentity: can not modify free entity\n");
+ VM_Warning(prog, "copyentity: can not modify free entity\n");
return;
}
memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
//=================================================================//
// #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
-static void VM_CL_effect (void)
+static void VM_CL_effect (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(5, VM_CL_effect);
CL_Effect(PRVM_G_VECTOR(OFS_PARM0), (int)PRVM_G_FLOAT(OFS_PARM1), (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
}
// #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
-static void VM_CL_te_blood (void)
+static void VM_CL_te_blood (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
-static void VM_CL_te_bloodshower (void)
+static void VM_CL_te_bloodshower (prvm_prog_t *prog)
{
vec_t speed;
vec3_t vel1, vel2;
}
// #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
-static void VM_CL_te_explosionrgb (void)
+static void VM_CL_te_explosionrgb (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
-static void VM_CL_te_particlecube (void)
+static void VM_CL_te_particlecube (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(7, VM_CL_te_particlecube);
CL_ParticleCube(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), PRVM_G_FLOAT(OFS_PARM5), PRVM_G_FLOAT(OFS_PARM6));
}
// #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
-static void VM_CL_te_particlerain (void)
+static void VM_CL_te_particlerain (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(5, VM_CL_te_particlerain);
CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 0);
}
// #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
-static void VM_CL_te_particlesnow (void)
+static void VM_CL_te_particlesnow (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(5, VM_CL_te_particlesnow);
CL_ParticleRain(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4), 1);
}
// #411 void(vector org, vector vel, float howmany) te_spark
-static void VM_CL_te_spark (void)
+static void VM_CL_te_spark (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
extern cvar_t cl_sound_ric_gunshot;
// #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
-static void VM_CL_te_gunshotquad (void)
+static void VM_CL_te_gunshotquad (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
-static void VM_CL_te_spikequad (void)
+static void VM_CL_te_spikequad (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
-static void VM_CL_te_superspikequad (void)
+static void VM_CL_te_superspikequad (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
-static void VM_CL_te_explosionquad (void)
+static void VM_CL_te_explosionquad (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
-static void VM_CL_te_smallflash (void)
+static void VM_CL_te_smallflash (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
-static void VM_CL_te_customflash (void)
+static void VM_CL_te_customflash (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_gunshot (void)
+static void VM_CL_te_gunshot (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_spike (void)
+static void VM_CL_te_spike (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_superspike (void)
+static void VM_CL_te_superspike (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_explosion (void)
+static void VM_CL_te_explosion (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_tarexplosion (void)
+static void VM_CL_te_tarexplosion (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_wizspike (void)
+static void VM_CL_te_wizspike (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_knightspike (void)
+static void VM_CL_te_knightspike (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_lavasplash (void)
+static void VM_CL_te_lavasplash (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_te_lavasplash);
CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
}
// #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_teleport (void)
+static void VM_CL_te_teleport (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_te_teleport);
CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM0), vec3_origin, vec3_origin, NULL, 0);
}
// #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_explosion2 (void)
+static void VM_CL_te_explosion2 (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2, color;
// #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_lightning1 (void)
+static void VM_CL_te_lightning1 (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1);
CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true);
}
// #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_lightning2 (void)
+static void VM_CL_te_lightning2 (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2);
CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true);
}
// #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_lightning3 (void)
+static void VM_CL_te_lightning3 (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3);
CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false);
}
// #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
-static void VM_CL_te_beam (void)
+static void VM_CL_te_beam (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_CL_te_beam);
CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false);
}
// #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
-static void VM_CL_te_plasmaburn (void)
+static void VM_CL_te_plasmaburn (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
}
// #457 void(vector org, vector velocity, float howmany) te_flamejet (DP_TE_FLAMEJET)
-static void VM_CL_te_flamejet (void)
+static void VM_CL_te_flamejet (prvm_prog_t *prog)
{
float *pos;
vec3_t pos2;
// #443 void(entity e, entity tagentity, string tagname) setattachment
-void VM_CL_setattachment (void)
+static void VM_CL_setattachment (prvm_prog_t *prog)
{
prvm_edict_t *e;
prvm_edict_t *tagentity;
if (e == prog->edicts)
{
- VM_Warning("setattachment: can not modify world entity\n");
+ VM_Warning(prog, "setattachment: can not modify world entity\n");
return;
}
if (e->priv.server->free)
{
- VM_Warning("setattachment: can not modify free entity\n");
+ VM_Warning(prog, "setattachment: can not modify free entity\n");
return;
}
/////////////////////////////////////////
// DP_MD3_TAGINFO extension coded by VorteX
-int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
+static int CL_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
{
dp_model_t *model = CL_GetModelFromEdict(e);
if (model)
return -1;
}
-int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+static int CL_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
{
int r;
dp_model_t *model;
return 1;
}
-int CL_GetPitchSign(prvm_edict_t *ent)
+int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
{
dp_model_t *model;
if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias)
return 1;
}
-void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
+void CL_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
{
float scale;
float pitchsign = 1;
}
else
{
- pitchsign = CL_GetPitchSign(ent);
+ pitchsign = CL_GetPitchSign(prog, ent);
Matrix4x4_CreateFromQuakeEntity(out, PRVM_clientedictvector(ent, origin)[0], PRVM_clientedictvector(ent, origin)[1], PRVM_clientedictvector(ent, origin)[2], pitchsign * PRVM_clientedictvector(ent, angles)[0], PRVM_clientedictvector(ent, angles)[1], PRVM_clientedictvector(ent, angles)[2], scale);
}
}
-int CL_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
+static int CL_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
{
dp_model_t *model;
if (tagindex >= 0
&& (model = CL_GetModelFromEdict(ent))
&& model->animscenes)
{
- VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
+ VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
}
*out = identitymatrix;
extern cvar_t cl_bob;
extern cvar_t cl_bobcycle;
extern cvar_t cl_bobup;
-int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
+int CL_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
{
int ret;
int attachloop;
return 5;
// apply transformation by child's tagindex on parent entity and then
// by parent entity itself
- ret = CL_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
+ ret = CL_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
if(ret && attachloop == 0)
return ret;
- CL_GetEntityMatrix(ent, &entitymatrix, false);
+ CL_GetEntityMatrix(prog, ent, &entitymatrix, false);
Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
// next iteration we process the parent entity
{
Matrix4x4_Copy(&tagmatrix, out);
- CL_GetEntityMatrix(prog->edicts, &entitymatrix, true);
+ CL_GetEntityMatrix(prog, prog->edicts, &entitymatrix, true);
Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
/*
}
// #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
-void VM_CL_gettagindex (void)
+static void VM_CL_gettagindex (prvm_prog_t *prog)
{
prvm_edict_t *ent;
const char *tag_name;
tag_name = PRVM_G_STRING(OFS_PARM1);
if (ent == prog->edicts)
{
- VM_Warning("VM_CL_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
+ VM_Warning(prog, "VM_CL_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
return;
}
if (ent->priv.server->free)
{
- VM_Warning("VM_CL_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
+ VM_Warning(prog, "VM_CL_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
return;
}
Con_DPrintf("VM_CL_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
else
{
- tag_index = CL_GetTagIndex(ent, tag_name);
+ tag_index = CL_GetTagIndex(prog, ent, tag_name);
if (tag_index == 0)
Con_DPrintf("VM_CL_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
}
}
// #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
-void VM_CL_gettaginfo (void)
+static void VM_CL_gettaginfo (prvm_prog_t *prog)
{
prvm_edict_t *e;
int tagindex;
e = PRVM_G_EDICT(OFS_PARM0);
tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
- returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex);
+ returncode = CL_GetTagMatrix(prog, &tag_matrix, e, tagindex);
Matrix4x4_ToVectors(&tag_matrix, PRVM_clientglobalvector(v_forward), le, PRVM_clientglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
VectorScale(le, -1, PRVM_clientglobalvector(v_right));
model = CL_GetModelFromEdict(e);
- VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
+ VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
- CL_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
+ VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
+ CL_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
PRVM_clientglobalfloat(gettaginfo_parent) = parentindex;
- PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
+ PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
VectorCopy(trans, PRVM_clientglobalvector(gettaginfo_offset));
VectorCopy(fo, PRVM_clientglobalvector(gettaginfo_forward));
VectorScale(le, -1, PRVM_clientglobalvector(gettaginfo_right));
switch(returncode)
{
case 1:
- VM_Warning("gettagindex: can't affect world entity\n");
+ VM_Warning(prog, "gettagindex: can't affect world entity\n");
break;
case 2:
- VM_Warning("gettagindex: can't affect free entity\n");
+ VM_Warning(prog, "gettagindex: can't affect free entity\n");
break;
case 3:
Con_DPrintf("CL_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
vmparticlespawner_t vmpartspawner;
// TODO: automatic max_themes grow
-static void VM_InitParticleSpawner (int maxthemes)
+static void VM_InitParticleSpawner (prvm_prog_t *prog, int maxthemes)
{
// bound max themes to not be an insane value
if (maxthemes < 4)
}
// particle theme -> QC globals
-void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme)
+static void VM_CL_ParticleThemeToGlobals(vmparticletheme_t *theme)
{
*vmpartspawner.particle_type = theme->typeindex;
*vmpartspawner.particle_blendmode = theme->blendmode;
}
// QC globals -> particle theme
-void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme)
+static void VM_CL_ParticleThemeFromGlobals(vmparticletheme_t *theme)
{
theme->typeindex = (unsigned short)*vmpartspawner.particle_type;
theme->blendmode = (pblend_t)(int)*vmpartspawner.particle_blendmode;
// init particle spawner interface
// # float(float max_themes) initparticlespawner
-void VM_CL_InitParticleSpawner (void)
+static void VM_CL_InitParticleSpawner (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_InitParticleSpawner);
- VM_InitParticleSpawner((int)PRVM_G_FLOAT(OFS_PARM0));
+ VM_InitParticleSpawner(prog, (int)PRVM_G_FLOAT(OFS_PARM0));
vmpartspawner.themes[0].initialized = true;
VM_ResetParticleTheme(&vmpartspawner.themes[0]);
PRVM_G_FLOAT(OFS_RETURN) = (vmpartspawner.verified == true) ? 1 : 0;
}
// void() resetparticle
-void VM_CL_ResetParticle (void)
+static void VM_CL_ResetParticle (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_ResetParticle);
if (vmpartspawner.verified == false)
{
- VM_Warning("VM_CL_ResetParticle: particle spawner not initialized\n");
+ VM_Warning(prog, "VM_CL_ResetParticle: particle spawner not initialized\n");
return;
}
VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
}
// void(float themenum) particletheme
-void VM_CL_ParticleTheme (void)
+static void VM_CL_ParticleTheme (prvm_prog_t *prog)
{
int themenum;
VM_SAFEPARMCOUNT(1, VM_CL_ParticleTheme);
if (vmpartspawner.verified == false)
{
- VM_Warning("VM_CL_ParticleTheme: particle spawner not initialized\n");
+ VM_Warning(prog, "VM_CL_ParticleTheme: particle spawner not initialized\n");
return;
}
themenum = (int)PRVM_G_FLOAT(OFS_PARM0);
if (themenum < 0 || themenum >= vmpartspawner.max_themes)
{
- VM_Warning("VM_CL_ParticleTheme: bad theme number %i\n", themenum);
+ VM_Warning(prog, "VM_CL_ParticleTheme: bad theme number %i\n", themenum);
VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
return;
}
if (vmpartspawner.themes[themenum].initialized == false)
{
- VM_Warning("VM_CL_ParticleTheme: theme #%i not exists\n", themenum);
+ VM_Warning(prog, "VM_CL_ParticleTheme: theme #%i not exists\n", themenum);
VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
return;
}
// float() saveparticletheme
// void(float themenum) updateparticletheme
-void VM_CL_ParticleThemeSave (void)
+static void VM_CL_ParticleThemeSave (prvm_prog_t *prog)
{
int themenum;
VM_SAFEPARMCOUNTRANGE(0, 1, VM_CL_ParticleThemeSave);
if (vmpartspawner.verified == false)
{
- VM_Warning("VM_CL_ParticleThemeSave: particle spawner not initialized\n");
+ VM_Warning(prog, "VM_CL_ParticleThemeSave: particle spawner not initialized\n");
return;
}
// allocate new theme, save it and return
if (themenum >= vmpartspawner.max_themes)
{
if (vmpartspawner.max_themes == 2048)
- VM_Warning("VM_CL_ParticleThemeSave: no free theme slots\n");
+ VM_Warning(prog, "VM_CL_ParticleThemeSave: no free theme slots\n");
else
- VM_Warning("VM_CL_ParticleThemeSave: no free theme slots, try initparticlespawner() with highter max_themes\n");
+ VM_Warning(prog, "VM_CL_ParticleThemeSave: no free theme slots, try initparticlespawner() with highter max_themes\n");
PRVM_G_FLOAT(OFS_RETURN) = -1;
return;
}
themenum = (int)PRVM_G_FLOAT(OFS_PARM0);
if (themenum < 0 || themenum >= vmpartspawner.max_themes)
{
- VM_Warning("VM_CL_ParticleThemeSave: bad theme number %i\n", themenum);
+ VM_Warning(prog, "VM_CL_ParticleThemeSave: bad theme number %i\n", themenum);
return;
}
vmpartspawner.themes[themenum].initialized = true;
}
// void(float themenum) freeparticletheme
-void VM_CL_ParticleThemeFree (void)
+static void VM_CL_ParticleThemeFree (prvm_prog_t *prog)
{
int themenum;
VM_SAFEPARMCOUNT(1, VM_CL_ParticleThemeFree);
if (vmpartspawner.verified == false)
{
- VM_Warning("VM_CL_ParticleThemeFree: particle spawner not initialized\n");
+ VM_Warning(prog, "VM_CL_ParticleThemeFree: particle spawner not initialized\n");
return;
}
themenum = (int)PRVM_G_FLOAT(OFS_PARM0);
// check parms
if (themenum <= 0 || themenum >= vmpartspawner.max_themes)
{
- VM_Warning("VM_CL_ParticleThemeFree: bad theme number %i\n", themenum);
+ VM_Warning(prog, "VM_CL_ParticleThemeFree: bad theme number %i\n", themenum);
return;
}
if (vmpartspawner.themes[themenum].initialized == false)
{
- VM_Warning("VM_CL_ParticleThemeFree: theme #%i already freed\n", themenum);
+ VM_Warning(prog, "VM_CL_ParticleThemeFree: theme #%i already freed\n", themenum);
VM_CL_ParticleThemeToGlobals(&vmpartspawner.themes[0]);
return;
}
// float(vector org, vector dir, [float theme]) particle
// returns 0 if failed, 1 if succesful
-void VM_CL_SpawnParticle (void)
+static void VM_CL_SpawnParticle (prvm_prog_t *prog)
{
float *org, *dir;
vmparticletheme_t *theme;
VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_SpawnParticle2);
if (vmpartspawner.verified == false)
{
- VM_Warning("VM_CL_SpawnParticle: particle spawner not initialized\n");
+ VM_Warning(prog, "VM_CL_SpawnParticle: particle spawner not initialized\n");
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
themenum = (int)PRVM_G_FLOAT(OFS_PARM2);
if (themenum <= 0 || themenum >= vmpartspawner.max_themes)
{
- VM_Warning("VM_CL_SpawnParticle: bad theme number %i\n", themenum);
+ VM_Warning(prog, "VM_CL_SpawnParticle: bad theme number %i\n", themenum);
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
// float(vector org, vector dir, float spawndelay, float collisiondelay, [float theme]) delayedparticle
// returns 0 if failed, 1 if success
-void VM_CL_SpawnParticleDelayed (void)
+static void VM_CL_SpawnParticleDelayed (prvm_prog_t *prog)
{
float *org, *dir;
vmparticletheme_t *theme;
VM_SAFEPARMCOUNTRANGE(4, 5, VM_CL_SpawnParticle2);
if (vmpartspawner.verified == false)
{
- VM_Warning("VM_CL_SpawnParticle: particle spawner not initialized\n");
+ VM_Warning(prog, "VM_CL_SpawnParticle: particle spawner not initialized\n");
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
themenum = (int)PRVM_G_FLOAT(OFS_PARM4);
if (themenum <= 0 || themenum >= vmpartspawner.max_themes)
{
- VM_Warning("VM_CL_SpawnParticle: bad theme number %i\n", themenum);
+ VM_Warning(prog, "VM_CL_SpawnParticle: bad theme number %i\n", themenum);
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
// vector(float entitynum, float whatfld) getentityvec;
// querying engine-drawn entity
// VorteX: currently it's only tested with whatfld = 1..7
-void VM_CL_GetEntity (void)
+static void VM_CL_GetEntity (prvm_prog_t *prog)
{
int entnum, fieldnum;
float org[3], v1[3], v2[3];
//QC POLYGON functions
//====================
-#define VMPOLYGONS_MAXPOINTS 64
-
-typedef struct vmpolygons_triangle_s
-{
- rtexture_t *texture;
- int drawflag;
- qboolean hasalpha;
- unsigned short elements[3];
-}vmpolygons_triangle_t;
-
-typedef struct vmpolygons_s
-{
- mempool_t *pool;
- qboolean initialized;
- double progstarttime;
-
- int max_vertices;
- int num_vertices;
- float *data_vertex3f;
- float *data_color4f;
- float *data_texcoord2f;
-
- int max_triangles;
- int num_triangles;
- vmpolygons_triangle_t *data_triangles;
- unsigned short *data_sortedelement3s;
-
- qboolean begin_active;
- int begin_draw2d;
- rtexture_t *begin_texture;
- int begin_drawflag;
- int begin_vertices;
- float begin_vertex[VMPOLYGONS_MAXPOINTS][3];
- float begin_color[VMPOLYGONS_MAXPOINTS][4];
- float begin_texcoord[VMPOLYGONS_MAXPOINTS][2];
- qboolean begin_texture_hasalpha;
-} vmpolygons_t;
-
-// FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
-vmpolygons_t vmpolygons[PRVM_MAXPROGS];
-
//#304 void() renderscene (EXT_CSQC)
// moved that here to reset the polygons,
// resetting them earlier causes R_Mesh_Draw to be called with numvertices = 0
// --blub
-void VM_CL_R_RenderScene (void)
+static void VM_CL_R_RenderScene (prvm_prog_t *prog)
{
- double t = Sys_DoubleTime();
- vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ double t = Sys_DirtyTime();
+ vmpolygons_t *polys = &prog->vmpolygons;
VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
+ // update the views
+ if(r_refdef.view.ismain)
+ {
+ // set the main view
+ csqc_main_r_refdef_view = r_refdef.view;
+
+ // clear the flags so no other view becomes "main" unless CSQC sets VF_MAINVIEW
+ r_refdef.view.ismain = false;
+ csqc_original_r_refdef_view.ismain = false;
+ }
+
// we need to update any RENDER_VIEWMODEL entities at this point because
// csqc supplies its own view matrix
CL_UpdateViewEntities();
+
// now draw stuff!
R_RenderView();
polys->num_vertices = polys->num_triangles = 0;
- polys->progstarttime = prog->starttime;
// callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView
- prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= Sys_DoubleTime() - t;
+ t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0;
+ prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t;
}
static void VM_ResizePolygons(vmpolygons_t *polys)
static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int surfacelistindex;
- vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
- if(polys->progstarttime != prog->starttime) // from other progs? won't draw these (this can cause crashes!)
- return;
+ vmpolygons_t *polys = (vmpolygons_t *)ent;
// R_Mesh_ResetTextureState();
R_EntityMatrix(&identitymatrix);
GL_CullFace(GL_NONE);
rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture;
int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag;
DrawQ_ProcessDrawFlag(drawflag, polys->data_triangles[surfacelist[surfacelistindex]].hasalpha);
- R_SetupShader_Generic(tex, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic(tex, NULL, GL_MODULATE, 1, false, false, false);
numtriangles = 0;
for (;surfacelistindex < numsurfaces;surfacelistindex++)
{
}
}
-void VMPolygons_Store(vmpolygons_t *polys)
+static void VMPolygons_Store(vmpolygons_t *polys)
{
qboolean hasalpha;
int i;
// TODO: move this into the client code and clean-up everything else, too! [1/6/2008 Black]
// LordHavoc: agreed, this is a mess
-void VM_CL_AddPolygonsToMeshQueue (void)
+void VM_CL_AddPolygonsToMeshQueue (prvm_prog_t *prog)
{
int i;
- vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ vmpolygons_t *polys = &prog->vmpolygons;
vec3_t center;
// only add polygons of the currently active prog to the queue - if there is none, we're done
for (i = 0;i < polys->num_triangles;i++)
{
VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center);
- R_MeshQueue_AddTransparent(center, VM_DrawPolygonCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, VM_DrawPolygonCallback, (entity_render_t *)polys, i, NULL);
}
/*polys->num_triangles = 0; // now done after rendering the scene,
}
//void(string texturename, float flag[, float is2d]) R_BeginPolygon
-void VM_CL_R_PolygonBegin (void)
+static void VM_CL_R_PolygonBegin (prvm_prog_t *prog)
{
const char *picname;
skinframe_t *sf;
- vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ vmpolygons_t *polys = &prog->vmpolygons;
int tf;
// TODO instead of using skinframes here (which provides the benefit of
if (!polys->initialized)
VM_InitPolygons(polys);
- if(polys->progstarttime != prog->starttime)
- {
- // from another progs? then reset the polys first (fixes crashes on map change, because that can make skinframe textures invalid)
- polys->num_vertices = polys->num_triangles = 0;
- polys->progstarttime = prog->starttime;
- }
if (polys->begin_active)
{
- VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n");
+ VM_Warning(prog, "VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n");
return;
}
picname = PRVM_G_STRING(OFS_PARM0);
}
//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
-void VM_CL_R_PolygonVertex (void)
+static void VM_CL_R_PolygonVertex (prvm_prog_t *prog)
{
- vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ vmpolygons_t *polys = &prog->vmpolygons;
VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
if (!polys->begin_active)
{
- VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
+ VM_Warning(prog, "VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
return;
}
if (polys->begin_vertices >= VMPOLYGONS_MAXPOINTS)
{
- VM_Warning("VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
+ VM_Warning(prog, "VM_CL_R_PolygonVertex: may have %i vertices max\n", VMPOLYGONS_MAXPOINTS);
return;
}
}
//void() R_EndPolygon
-void VM_CL_R_PolygonEnd (void)
+static void VM_CL_R_PolygonEnd (prvm_prog_t *prog)
{
- vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ vmpolygons_t *polys = &prog->vmpolygons;
VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
if (!polys->begin_active)
{
- VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
+ VM_Warning(prog, "VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
return;
}
polys->begin_active = false;
if (polys->begin_vertices >= 3)
VMPolygons_Store(polys);
else
- VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->begin_vertices);
+ VM_Warning(prog, "VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->begin_vertices);
}
static vmpolygons_t debugPolys;
=============
*/
-qboolean CL_CheckBottom (prvm_edict_t *ent)
+static qboolean CL_CheckBottom (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = CLVM_prog;
vec3_t mins, maxs, start, stop;
trace_t trace;
int x, y;
possible, no move is done and false is returned
=============
*/
-qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
+static qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
{
+ prvm_prog_t *prog = CLVM_prog;
float dz;
vec3_t oldorg, neworg, end, traceendpos;
trace_t trace;
}
trace = CL_TraceBox(PRVM_clientedictvector(ent, origin), PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
if (settrace)
- CL_VM_SetTraceGlobals(&trace, svent);
+ CL_VM_SetTraceGlobals(prog, &trace, svent);
if (trace.fraction == 1)
{
trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
if (settrace)
- CL_VM_SetTraceGlobals(&trace, svent);
+ CL_VM_SetTraceGlobals(prog, &trace, svent);
if (trace.startsolid)
{
neworg[2] -= sv_stepheight.value;
trace = CL_TraceBox(neworg, PRVM_clientedictvector(ent, mins), PRVM_clientedictvector(ent, maxs), end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true);
if (settrace)
- CL_VM_SetTraceGlobals(&trace, svent);
+ CL_VM_SetTraceGlobals(prog, &trace, svent);
if (trace.startsolid)
return false;
}
float(float yaw, float dist[, settrace]) walkmove
===============
*/
-static void VM_CL_walkmove (void)
+static void VM_CL_walkmove (prvm_prog_t *prog)
{
prvm_edict_t *ent;
float yaw, dist;
ent = PRVM_PROG_TO_EDICT(PRVM_clientglobaledict(self));
if (ent == prog->edicts)
{
- VM_Warning("walkmove: can not modify world entity\n");
+ VM_Warning(prog, "walkmove: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("walkmove: can not modify free entity\n");
+ VM_Warning(prog, "walkmove: can not modify free entity\n");
return;
}
yaw = PRVM_G_FLOAT(OFS_PARM0);
string(string key) serverkey
===============
*/
-void VM_CL_serverkey(void)
+static void VM_CL_serverkey(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
}
/*
float checkpvs(vector viewpos, entity viewee) = #240;
=================
*/
-static void VM_CL_checkpvs (void)
+static void VM_CL_checkpvs (prvm_prog_t *prog)
{
vec3_t viewpos;
prvm_edict_t *viewee;
if(viewee->priv.required->free)
{
- VM_Warning("checkpvs: can not check free entity\n");
+ VM_Warning(prog, "checkpvs: can not check free entity\n");
PRVM_G_FLOAT(OFS_RETURN) = 4;
return;
}
}
// #263 float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
-static void VM_CL_skel_create(void)
+static void VM_CL_skel_create(prvm_prog_t *prog)
{
int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
dp_model_t *model = CL_GetModelByIndex(modelindex);
}
// #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
-static void VM_CL_skel_build(void)
+static void VM_CL_skel_build(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
skeleton_t *skeleton;
firstbone = max(0, firstbone);
lastbone = min(lastbone, model->num_bones - 1);
lastbone = min(lastbone, skeleton->model->num_bones - 1);
- VM_GenerateFrameGroupBlend(framegroupblend, ed);
+ VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
blendfrac = 1.0f - retainfrac;
for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
}
// #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
-static void VM_CL_skel_get_numbones(void)
+static void VM_CL_skel_get_numbones(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
skeleton_t *skeleton;
}
// #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
-static void VM_CL_skel_get_bonename(void)
+static void VM_CL_skel_get_bonename(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
return;
if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
return;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
}
// #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
-static void VM_CL_skel_get_boneparent(void)
+static void VM_CL_skel_get_boneparent(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #268 float(float skel, string tagname) skel_find_bone = #268; // (FTE_CSQC_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
-static void VM_CL_skel_find_bone(void)
+static void VM_CL_skel_find_bone(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
const char *tagname = PRVM_G_STRING(OFS_PARM1);
}
// #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
-static void VM_CL_skel_get_bonerel(void)
+static void VM_CL_skel_get_bonerel(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
-static void VM_CL_skel_get_boneabs(void)
+static void VM_CL_skel_get_boneabs(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-static void VM_CL_skel_set_bone(void)
+static void VM_CL_skel_set_bone(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-static void VM_CL_skel_mul_bone(void)
+static void VM_CL_skel_mul_bone(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
-static void VM_CL_skel_mul_bones(void)
+static void VM_CL_skel_mul_bones(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
-static void VM_CL_skel_copybones(void)
+static void VM_CL_skel_copybones(prvm_prog_t *prog)
{
int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #275 void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
-static void VM_CL_skel_delete(void)
+static void VM_CL_skel_delete(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
skeleton_t *skeleton;
}
// #276 float(float modlindex, string framename) frameforname = #276; // (FTE_CSQC_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
-static void VM_CL_frameforname(void)
+static void VM_CL_frameforname(prvm_prog_t *prog)
{
int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
dp_model_t *model = CL_GetModelByIndex(modelindex);
}
// #277 float(float modlindex, float framenum) frameduration = #277; // (FTE_CSQC_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
-static void VM_CL_frameduration(void)
+static void VM_CL_frameduration(prvm_prog_t *prog)
{
int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
dp_model_t *model = CL_GetModelByIndex(modelindex);
PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
}
-void VM_CL_RotateMoves(void)
+static void VM_CL_RotateMoves(prvm_prog_t *prog)
{
/*
* Obscure builtin used by GAME_XONOTIC.
}
// #358 void(string cubemapname) loadcubemap
-static void VM_CL_loadcubemap(void)
+static void VM_CL_loadcubemap(prvm_prog_t *prog)
{
const char *name;
VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag, float is2d[NYI: , float lines]) R_BeginPolygon
VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon
-NULL /* R_LoadWorldModel in menu VM, should stay unassigned in client*/, // #309
+VM_CL_R_SetView, // #309 float(float property) getproperty (EXT_CSQC)
VM_CL_unproject, // #310 vector (vector v) cs_unproject (EXT_CSQC)
VM_CL_project, // #311 vector (vector v) cs_project (EXT_CSQC)
NULL, // #312
VM_getimagesize, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
VM_freepic, // #319 void(string name) freepic (EXT_CSQC)
VM_drawcharacter, // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
-VM_drawstring, // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
-VM_drawpic, // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
+VM_drawstring, // #321 float(vector position, string text, vector scale, vector rgb, float alpha[, float flag]) drawstring (EXT_CSQC, DP_CSQC)
+VM_drawpic, // #322 float(vector position, string pic, vector size, vector rgb, float alpha[, float flag]) drawpic (EXT_CSQC)
VM_drawfill, // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
VM_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea
VM_drawresetcliparea, // #325 void(void) drawresetcliparea
VM_keynumtostring, // #340 string(float keynum) keynumtostring (EXT_CSQC)
VM_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
VM_getkeybind, // #342 string(float keynum[, float bindmap]) getkeybind (EXT_CSQC)
-VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (EXT_CSQC)
-VM_CL_getmousepos, // #344 vector() getmousepos (EXT_CSQC)
+VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (DP_CSQC)
+VM_CL_getmousepos, // #344 vector() getmousepos (DP_CSQC)
VM_CL_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC)
VM_CL_setsensitivityscale, // #346 void(float sens) setsensitivityscale (EXT_CSQC)
VM_CL_runplayerphysics, // #347 void() runstandardplayerphysics (EXT_CSQC)
NULL, // #636
NULL, // #637
VM_CL_RotateMoves, // #638
-NULL, // #639
+VM_digest_hex, // #639
+NULL, // #640
};
const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
-void VM_Polygons_Reset(void)
+void VM_Polygons_Reset(prvm_prog_t *prog)
{
- vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ vmpolygons_t *polys = &prog->vmpolygons;
// TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
if(polys->initialized)
}
}
-void VM_CL_Cmd_Init(void)
+void CLVM_init_cmd(prvm_prog_t *prog)
{
- VM_Cmd_Init();
- VM_Polygons_Reset();
+ VM_Cmd_Init(prog);
+ VM_Polygons_Reset(prog);
}
-void VM_CL_Cmd_Reset(void)
+void CLVM_reset_cmd(prvm_prog_t *prog)
{
World_End(&cl.world);
- VM_Cmd_Reset();
- VM_Polygons_Reset();
+ VM_Cmd_Reset(prog);
+ VM_Polygons_Reset(prog);
}
-
-
#ifndef __CLVM_CMDS_H__
#define __CLVM_CMDS_H__
-int CL_GetPitchSign(prvm_edict_t *ent);
-int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex);
-void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix);
-
/* These are VM built-ins that originate in the client-side programs support
but are reused by the other programs (usually the menu). */
void VM_CL_R_PolygonBegin (void);
void VM_CL_R_PolygonVertex (void);
void VM_CL_R_PolygonEnd (void);
-/* VMs exposing the polygon calls must call this on Init/Reset */
-void VM_Polygons_Reset(void);
void VM_CL_setattachment(void);
void VM_CL_gettagindex(void);
// cmd.c -- Quake script command processing module
#include "quakedef.h"
+#include "thread.h"
typedef struct cmdalias_s
{
{
struct cmddeferred_s *next;
char *value;
- double time;
+ double delay;
} cmddeferred_t;
static cmddeferred_t *cmd_deferred_list = NULL;
{
if(Cmd_Argc() == 1)
{
- double time = Sys_DoubleTime();
cmddeferred_t *next = cmd_deferred_list;
if(!next)
Con_Printf("No commands are pending.\n");
while(next)
{
- Con_Printf("-> In %9.2f: %s\n", next->time-time, next->value);
+ Con_Printf("-> In %9.2f: %s\n", next->delay, next->value);
next = next->next;
}
} else if(Cmd_Argc() == 2 && !strcasecmp("clear", Cmd_Argv(1)))
cmddeferred_t *defcmd = (cmddeferred_t*)Mem_Alloc(tempmempool, sizeof(*defcmd));
size_t len = strlen(value);
- defcmd->time = Sys_DoubleTime() + atof(Cmd_Argv(1));
+ defcmd->delay = atof(Cmd_Argv(1));
defcmd->value = (char*)Mem_Alloc(tempmempool, len+1);
memcpy(defcmd->value, value, len+1);
defcmd->next = NULL;
static sizebuf_t cmd_text;
static unsigned char cmd_text_buf[CMDBUFSIZE];
+void *cmd_text_mutex = NULL;
+
+#define Cbuf_LockThreadMutex() (cmd_text_mutex ? Thread_LockMutex(cmd_text_mutex),1 : 0)
+#define Cbuf_UnlockThreadMutex() (cmd_text_mutex ? Thread_UnlockMutex(cmd_text_mutex),1 : 0)
/*
============
{
int l;
- l = (int)strlen (text);
+ l = (int)strlen(text);
+ Cbuf_LockThreadMutex();
if (cmd_text.cursize + l >= cmd_text.maxsize)
- {
Con_Print("Cbuf_AddText: overflow\n");
- return;
- }
-
- SZ_Write (&cmd_text, (const unsigned char *)text, (int)strlen (text));
+ else
+ SZ_Write(&cmd_text, (const unsigned char *)text, l);
+ Cbuf_UnlockThreadMutex();
}
*/
void Cbuf_InsertText (const char *text)
{
- char *temp;
- int templen;
-
- // copy off any commands still remaining in the exec buffer
- templen = cmd_text.cursize;
- if (templen)
- {
- temp = (char *)Mem_Alloc (tempmempool, templen);
- memcpy (temp, cmd_text.data, templen);
- SZ_Clear (&cmd_text);
- }
+ size_t l = strlen(text);
+ Cbuf_LockThreadMutex();
+ // we need to memmove the existing text and stuff this in before it...
+ if (cmd_text.cursize + l >= (size_t)cmd_text.maxsize)
+ Con_Print("Cbuf_InsertText: overflow\n");
else
- temp = NULL;
-
- // add the entire text of the file
- Cbuf_AddText (text);
-
- // add the copied off data
- if (temp != NULL)
{
- SZ_Write (&cmd_text, (const unsigned char *)temp, templen);
- Mem_Free (temp);
+ // we don't have a SZ_Prepend, so...
+ memmove(cmd_text.data + l, cmd_text.data, cmd_text.cursize);
+ cmd_text.cursize += l;
+ memcpy(cmd_text.data, text, l);
}
+ Cbuf_UnlockThreadMutex();
}
/*
Cbuf_Execute_Deferred --blub
============
*/
-void Cbuf_Execute_Deferred (void)
+static void Cbuf_Execute_Deferred (void)
{
+ static double oldrealtime = 0;
cmddeferred_t *cmd, *prev;
- double time = Sys_DoubleTime();
+ double eat;
+ if (realtime - oldrealtime < 0 || realtime - oldrealtime > 1800) oldrealtime = realtime;
+ eat = realtime - oldrealtime;
+ if (eat < (1.0 / 120.0))
+ return;
+ oldrealtime = realtime;
prev = NULL;
cmd = cmd_deferred_list;
while(cmd)
{
- if(cmd->time <= time)
+ cmd->delay -= eat;
+ if(cmd->delay <= 0)
{
Cbuf_AddText(cmd->value);
Cbuf_AddText(";\n");
// LordHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
cmd_tokenizebufferpos = 0;
- Cbuf_Execute_Deferred();
while (cmd_text.cursize)
{
// find a \n or ; line break
)
{
Cmd_PreprocessString( line, preprocessed, sizeof(preprocessed), NULL );
- Cmd_ExecuteString (preprocessed, src_command);
+ Cmd_ExecuteString (preprocessed, src_command, false);
}
else
{
- Cmd_ExecuteString (line, src_command);
+ Cmd_ExecuteString (line, src_command, false);
}
if (cmd_wait)
}
}
+void Cbuf_Frame(void)
+{
+ Cbuf_Execute_Deferred();
+ if (cmd_text.cursize)
+ {
+ SV_LockThreadMutex();
+ Cbuf_Execute();
+ SV_UnlockThreadMutex();
+ }
+}
+
/*
==============================================================================
===============
*/
qboolean host_stuffcmdsrun = false;
-void Cmd_StuffCmds_f (void)
+static void Cmd_StuffCmds_f (void)
{
int i, j, l;
// this is for all commandline options combined (and is bounds checked)
static void Cmd_Exec(const char *filename)
{
char *f;
+ qboolean isdefaultcfg = strlen(filename) >= 11 && !strcmp(filename + strlen(filename) - 11, "default.cfg");
if (!strcmp(filename, "config.cfg"))
{
// if executing default.cfg for the first time, lock the cvar defaults
// it may seem backwards to insert this text BEFORE the default.cfg
// but Cbuf_InsertText inserts before, so this actually ends up after it.
- if (strlen(filename) >= 11 && !strcmp(filename + strlen(filename) - 11, "default.cfg"))
+ if (isdefaultcfg)
Cbuf_InsertText("\ncvar_lockdefaults\n");
// insert newline after the text to make sure the last line is terminated (some text editors omit the trailing newline)
Cbuf_InsertText (f);
Mem_Free(f);
- // special defaults for specific games go here, these execute before default.cfg
- // Nehahra pushable crates malfunction in some levels if this is on
- // Nehahra NPC AI is confused by blowupfallenzombies
- if (gamemode == GAME_NEHAHRA)
- Cbuf_InsertText("\nsv_gameplayfix_upwardvelocityclearsongroundflag 0\nsv_gameplayfix_blowupfallenzombies 0\n\n");
- // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
- // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
- // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
- if (gamemode == GAME_HIPNOTIC)
- Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n");
- // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
- if (gamemode == GAME_ROGUE)
- Cbuf_InsertText("\nsv_gameplayfix_findradiusdistancetobox 0\n\n");
- if (gamemode == GAME_NEXUIZ)
- Cbuf_InsertText("\nsv_gameplayfix_q2airaccelerate 1\nsv_gameplayfix_stepmultipletimes 1\n\n");
- if (gamemode == GAME_TENEBRAE)
- Cbuf_InsertText("\nr_shadow_gloss 2\nr_shadow_bumpscale_basetexture 4\n\n");
+ if (isdefaultcfg)
+ {
+ // special defaults for specific games go here, these execute before default.cfg
+ // Nehahra pushable crates malfunction in some levels if this is on
+ // Nehahra NPC AI is confused by blowupfallenzombies
+ if (gamemode == GAME_NEHAHRA)
+ Cbuf_InsertText("\nsv_gameplayfix_upwardvelocityclearsongroundflag 0\nsv_gameplayfix_blowupfallenzombies 0\n\n");
+ // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
+ // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
+ // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
+ if (gamemode == GAME_HIPNOTIC)
+ Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n");
+ // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
+ if (gamemode == GAME_ROGUE)
+ Cbuf_InsertText("\nsv_gameplayfix_findradiusdistancetobox 0\n\n");
+ if (gamemode == GAME_NEXUIZ)
+ Cbuf_InsertText("\nsv_gameplayfix_q2airaccelerate 1\nsv_gameplayfix_stepmultipletimes 1\n\n");
+ if (gamemode == GAME_TENEBRAE)
+ Cbuf_InsertText("\nr_shadow_gloss 2\nr_shadow_bumpscale_basetexture 4\n\n");
+ // Steel Storm: Burning Retribution csqc misinterprets CSQC_InputEvent if type is a value other than 0 or 1
+ if (gamemode == GAME_STEELSTORM)
+ Cbuf_InsertText("\ncl_csqc_generatemousemoveevents 0\n\n");
+ }
}
/*
cvar_t *cvar;
long argno;
char *endptr;
+ char vabuf[1024];
if(is_multiple)
*is_multiple = false;
}
else if(!strcmp(varname, "#"))
{
- return va("%d", Cmd_Argc());
+ return va(vabuf, sizeof(vabuf), "%d", Cmd_Argc());
}
else if(varname[strlen(varname) - 1] == '-')
{
static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t *alias)
{
- static char varname[MAX_INPUTLINE];
- static char varval[MAX_INPUTLINE];
+ static char varname[MAX_INPUTLINE]; // cmd_mutex
+ static char varval[MAX_INPUTLINE]; // cmd_mutex
const char *varstr;
char *varfunc;
static char asis[] = "asis"; // just to suppress const char warnings
*/
static void Cmd_ExecuteAlias (cmdalias_t *alias)
{
- static char buffer[ MAX_INPUTLINE ];
- static char buffer2[ MAX_INPUTLINE ];
+ static char buffer[ MAX_INPUTLINE ]; // cmd_mutex
+ static char buffer2[ MAX_INPUTLINE ]; // cmd_mutex
Cmd_PreprocessString( alias->value, buffer, sizeof(buffer) - 2, alias );
// insert at start of command buffer, so that aliases execute in order
// (fixes bug introduced by Black on 20050705)
const char *partial;
int count;
qboolean ispattern;
+ char vabuf[1024];
if (Cmd_Argc() > 1)
partial = Cmd_Args();
ispattern = partial && (strchr(partial, '*') || strchr(partial, '?'));
if(!ispattern)
- partial = va("*%s*", partial);
+ partial = va(vabuf, sizeof(vabuf), "*%s*", partial);
count = 0;
for (cvar = cvar_vars; cvar; cvar = cvar->next)
cmd_text.data = cmd_text_buf;
cmd_text.maxsize = sizeof(cmd_text_buf);
cmd_text.cursize = 0;
+
+ if (Thread_HasThreads())
+ cmd_text_mutex = Thread_CreateMutex();
}
void Cmd_Init_Commands (void)
*/
void Cmd_Shutdown(void)
{
+ if (cmd_text_mutex)
+ {
+ // we usually have this locked when we get here from Host_Quit_f
+ Cbuf_UnlockThreadMutex();
+ Thread_DestroyMutex(cmd_text_mutex);
+ }
+ cmd_text_mutex = NULL;
+
Mem_FreePool(&cmd_mempool);
}
cmd->csqcfunc = false;
}
-qboolean CL_VM_ConsoleCommand (const char *cmd);
/*
============
Cmd_ExecuteString
FIXME: lookupnoadd the token to speed search?
============
*/
-void Cmd_ExecuteString (const char *text, cmd_source_t src)
+void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex)
{
int oldpos;
int found;
// execute the command line
if (!Cmd_Argc())
- {
- cmd_tokenizebufferpos = oldpos;
- return; // no tokens
- }
+ goto done; // no tokens
// check functions
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
if (!strcasecmp (cmd_argv[0],cmd->name))
{
if (cmd->csqcfunc && CL_VM_ConsoleCommand (text)) //[515]: csqc
- return;
+ goto done;
switch (src)
{
case src_command:
if (cmd->clientfunction)
{
cmd->clientfunction ();
- cmd_tokenizebufferpos = oldpos;
- return;
+ goto done;
}
break;
}
if (cmd_source == src_client)
{
Con_Printf("player \"%s\" tried to %s\n", host_client->name, text);
- cmd_tokenizebufferpos = oldpos;
- return;
+ goto done;
}
// check alias
if (!strcasecmp (cmd_argv[0], a->name))
{
Cmd_ExecuteAlias(a);
- cmd_tokenizebufferpos = oldpos;
- return;
+ goto done;
}
}
if(found) // if the command was hooked and found, all is good
- {
- cmd_tokenizebufferpos = oldpos;
- return;
- }
+ goto done;
// check cvars
if (!Cvar_Command () && host_framecount > 0)
Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(0));
+done:
cmd_tokenizebufferpos = oldpos;
}
void Cmd_ForwardToServer (void)
{
const char *s;
+ char vabuf[1024];
if (!strcasecmp(Cmd_Argv(0), "cmd"))
{
// we want to strip off "cmd", so just send the args
else
{
// we need to keep the command name, so send Cmd_Argv(0), a space and then Cmd_Args()
- s = va("%s %s", Cmd_Argv(0), Cmd_Argc() > 1 ? Cmd_Args() : "");
+ s = va(vabuf, sizeof(vabuf), "%s %s", Cmd_Argv(0), Cmd_Argc() > 1 ? Cmd_Args() : "");
}
// don't send an empty forward message if the user tries "cmd" by itself
if (!s || !*s)
* \note Do not call inside a command function!
*/
void Cbuf_Execute (void);
+/*! Performs deferred commands and runs Cbuf_Execute, called by Host_Main */
+void Cbuf_Frame (void);
//===========================================================================
/// Parses a single line of text into arguments and tries to execute it.
/// The text can come from the command buffer, a remote client, or stdin.
-void Cmd_ExecuteString (const char *text, cmd_source_t src);
+void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex);
/// adds the string as a clc_stringcmd to the client message.
/// (used when there is no reason to generate a local command to do it)
/// enclosing quote marks are also put.
qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset, qboolean putquotes);
+void Cmd_ClearCsqcFuncs (void);
+
#endif
-void Collision_PrintBrushAsQHull(colbrushf_t *brush, const char *name)
+static void Collision_PrintBrushAsQHull(colbrushf_t *brush, const char *name)
{
int i;
Con_Printf("3 %s\n%i\n", name, brush->numpoints);
Con_Printf("%f %f %f %f\n", brush->planes[i].normal[0], brush->planes[i].normal[1], brush->planes[i].normal[2], brush->planes[i].dist);
}
-void Collision_ValidateBrush(colbrushf_t *brush)
+static void Collision_ValidateBrush(colbrushf_t *brush)
{
int j, k, pointsoffplanes, pointonplanes, pointswithinsufficientplanes, printbrush;
float d;
Collision_PrintBrushAsQHull(brush, "unnamed");
}
-float nearestplanedist_float(const float *normal, const colpointf_t *points, int numpoints)
+static float nearestplanedist_float(const float *normal, const colpointf_t *points, int numpoints)
{
float dist, bestdist;
if (!numpoints)
return bestdist;
}
-float furthestplanedist_float(const float *normal, const colpointf_t *points, int numpoints)
+static float furthestplanedist_float(const float *normal, const colpointf_t *points, int numpoints)
{
float dist, bestdist;
if (!numpoints)
return bestdist;
}
-void Collision_CalcEdgeDirsForPolygonBrushFloat(colbrushf_t *brush)
+static void Collision_CalcEdgeDirsForPolygonBrushFloat(colbrushf_t *brush)
{
int i, j;
for (i = 0, j = brush->numpoints - 1;i < brush->numpoints;j = i, i++)
}
}
-void Collision_SnapCopyPoints(int numpoints, const colpointf_t *in, colpointf_t *out, float fractionprecision, float invfractionprecision)
+static void Collision_SnapCopyPoints(int numpoints, const colpointf_t *in, colpointf_t *out, float fractionprecision, float invfractionprecision)
{
int i;
for (i = 0;i < numpoints;i++)
//Collision_ValidateBrush(&boxbrush->brush);
}
-void Collision_ClipTrace_BrushBox(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int supercontents, int q3surfaceflags, texture_t *texture)
-{
- colboxbrushf_t boxbrush, thisbrush_start, thisbrush_end;
- vec3_t startmins, startmaxs, endmins, endmaxs;
-
- // create brushes for the collision
- VectorAdd(start, mins, startmins);
- VectorAdd(start, maxs, startmaxs);
- VectorAdd(end, mins, endmins);
- VectorAdd(end, maxs, endmaxs);
- Collision_BrushForBox(&boxbrush, cmins, cmaxs, supercontents, q3surfaceflags, texture);
- Collision_BrushForBox(&thisbrush_start, startmins, startmaxs, 0, 0, NULL);
- Collision_BrushForBox(&thisbrush_end, endmins, endmaxs, 0, 0, NULL);
-
- memset(trace, 0, sizeof(trace_t));
- trace->hitsupercontentsmask = hitsupercontentsmask;
- trace->fraction = 1;
- trace->realfraction = 1;
- trace->allsolid = true;
- Collision_TraceBrushBrushFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, &boxbrush.brush, &boxbrush.brush);
-}
-
//pseudocode for detecting line/sphere overlap without calculating an impact point
//linesphereorigin = sphereorigin - linestart;linediff = lineend - linestart;linespherefrac = DotProduct(linesphereorigin, linediff) / DotProduct(linediff, linediff);return VectorLength2(linesphereorigin - bound(0, linespherefrac, 1) * linediff) >= sphereradius*sphereradius;
// all the results are correct (impactpoint, impactnormal, and fraction)
float Collision_ClipTrace_Line_Sphere(double *linestart, double *lineend, double *sphereorigin, double sphereradius, double *impactpoint, double *impactnormal)
{
- double dir[3], scale, v[3], deviationdist, impactdist, linelength;
+ double dir[3], scale, v[3], deviationdist2, impactdist, linelength;
// make sure the impactpoint and impactnormal are valid even if there is
// no collision
VectorCopy(lineend, impactpoint);
// of the line from the sphereorigin (deviation, how off-center it is)
VectorMA(linestart, impactdist, dir, v);
VectorSubtract(v, sphereorigin, v);
- deviationdist = VectorLength2(v);
- // if outside the radius, it's a miss for sure
- // (we do this comparison using squared radius to avoid a sqrt)
- if (deviationdist > sphereradius*sphereradius)
+ deviationdist2 = sphereradius * sphereradius - VectorLength2(v);
+ // if squared offset length is outside the squared sphere radius, miss
+ if (deviationdist2 < 0)
return 1; // miss (off to the side)
// nudge back to find the correct impact distance
- impactdist -= sphereradius - deviationdist/sphereradius;
+ impactdist -= sqrt(deviationdist2);
if (impactdist >= linelength)
return 1; // miss (not close enough)
if (impactdist < 0)
#endif
}
-typedef struct colbspnode_s
-{
- mplane_t plane;
- struct colbspnode_s *children[2];
- // the node is reallocated or split if max is reached
- int numcolbrushf;
- int maxcolbrushf;
- colbrushf_t **colbrushflist;
- //int numcolbrushd;
- //int maxcolbrushd;
- //colbrushd_t **colbrushdlist;
-}
-colbspnode_t;
-
-typedef struct colbsp_s
-{
- mempool_t *mempool;
- colbspnode_t *nodes;
-}
-colbsp_t;
-
-colbsp_t *Collision_CreateCollisionBSP(mempool_t *mempool)
-{
- colbsp_t *bsp;
- bsp = (colbsp_t *)Mem_Alloc(mempool, sizeof(colbsp_t));
- bsp->mempool = mempool;
- bsp->nodes = (colbspnode_t *)Mem_Alloc(bsp->mempool, sizeof(colbspnode_t));
- return bsp;
-}
-
-void Collision_FreeCollisionBSPNode(colbspnode_t *node)
-{
- if (node->children[0])
- Collision_FreeCollisionBSPNode(node->children[0]);
- if (node->children[1])
- Collision_FreeCollisionBSPNode(node->children[1]);
- while (--node->numcolbrushf)
- Mem_Free(node->colbrushflist[node->numcolbrushf]);
- //while (--node->numcolbrushd)
- // Mem_Free(node->colbrushdlist[node->numcolbrushd]);
- Mem_Free(node);
-}
-
-void Collision_FreeCollisionBSP(colbsp_t *bsp)
-{
- Collision_FreeCollisionBSPNode(bsp->nodes);
- Mem_Free(bsp);
-}
-
void Collision_BoundingBoxOfBrushTraceSegment(const colbrushf_t *start, const colbrushf_t *end, vec3_t mins, vec3_t maxs, float startfrac, float endfrac)
{
int i;
//===========================================
-void Collision_TranslateBrush(const vec3_t shift, colbrushf_t *brush)
+static void Collision_TranslateBrush(const vec3_t shift, colbrushf_t *brush)
{
int i;
// now we can transform the data
VectorAdd(brush->maxs, shift, brush->maxs);
}
-void Collision_TransformBrush(const matrix4x4_t *matrix, colbrushf_t *brush)
+static void Collision_TransformBrush(const matrix4x4_t *matrix, colbrushf_t *brush)
{
int i;
vec3_t v;
dp_model_t *model;
vec3_t end;
vec3_t start;
- vec3_t mins;
- vec3_t maxs;
-// const frameblend_t *frameblend;
-// const skeleton_t *skeleton;
-// matrix4x4_t inversematrix;
int hitsupercontentsmask;
- int type; // which type of query produced this cache entry
matrix4x4_t matrix;
- vec3_t bodymins;
- vec3_t bodymaxs;
- int bodysupercontents;
}
collision_cachedtrace_parameters_t;
Collision_Cache_Reset(true);
}
-void Collision_Cache_RebuildHash(void)
+static void Collision_Cache_RebuildHash(void)
{
int index;
int range = collision_cachedtrace_lastused + 1;
return hashindex;
}
-static collision_cachedtrace_t *Collision_Cache_Lookup(int type, dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask)
+static collision_cachedtrace_t *Collision_Cache_Lookup(dp_model_t *model, const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
{
int hashindex = 0;
unsigned int fullhashindex;
collision_cachedtrace_t *cached = collision_cachedtrace_array + index;
collision_cachedtrace_parameters_t params;
// all non-cached traces use the same index
- if ((frameblend && frameblend[0].lerp != 1) || (skeleton && skeleton->relativetransforms))
- r_refdef.stats.collisioncache_animated++;
- else if (!collision_cache.integer)
+ if (!collision_cache.integer)
r_refdef.stats.collisioncache_traced++;
else
{
// cached trace lookup
memset(¶ms, 0, sizeof(params));
- params.type = type;
params.model = model;
- VectorCopy(bodymins, params.bodymins);
- VectorCopy(bodymaxs, params.bodymaxs);
- params.bodysupercontents = bodysupercontents;
VectorCopy(start, params.start);
- VectorCopy(mins, params.mins);
- VectorCopy(maxs, params.maxs);
VectorCopy(end, params.end);
params.hitsupercontentsmask = hitsupercontentsmask;
params.matrix = *matrix;
- //params.inversematrix = *inversematrix;
fullhashindex = Collision_Cache_HashIndexForArray((unsigned int *)¶ms, sizeof(params) / sizeof(unsigned int));
- //fullhashindex = Collision_Cache_HashIndexForArray((unsigned int *)¶ms, 10);
hashindex = (int)(fullhashindex % (unsigned int)collision_cachedtrace_hashsize);
for (index = hash[hashindex];index;index = arraynext[index])
{
|| cached->p.start[0] != params.start[0]
|| cached->p.start[1] != params.start[1]
|| cached->p.start[2] != params.start[2]
- || cached->p.mins[0] != params.mins[0]
- || cached->p.mins[1] != params.mins[1]
- || cached->p.mins[2] != params.mins[2]
- || cached->p.maxs[0] != params.maxs[0]
- || cached->p.maxs[1] != params.maxs[1]
- || cached->p.maxs[2] != params.maxs[2]
- || cached->p.type != params.type
- || cached->p.bodysupercontents != params.bodysupercontents
- || cached->p.bodymins[0] != params.bodymins[0]
- || cached->p.bodymins[1] != params.bodymins[1]
- || cached->p.bodymins[2] != params.bodymins[2]
- || cached->p.bodymaxs[0] != params.bodymaxs[0]
- || cached->p.bodymaxs[1] != params.bodymaxs[1]
- || cached->p.bodymaxs[2] != params.bodymaxs[2]
|| cached->p.hitsupercontentsmask != params.hitsupercontentsmask
|| cached->p.matrix.m[0][0] != params.matrix.m[0][0]
|| cached->p.matrix.m[0][1] != params.matrix.m[0][1]
return cached;
}
-void Collision_ClipToGenericEntity(trace_t *trace, dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask)
+void Collision_Cache_ClipLineToGenericEntitySurfaces(trace_t *trace, dp_model_t *model, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
{
- float starttransformed[3], endtransformed[3];
- collision_cachedtrace_t *cached = Collision_Cache_Lookup(3, model, frameblend, skeleton, bodymins, bodymaxs, bodysupercontents, matrix, inversematrix, start, mins, maxs, end, hitsupercontentsmask);
+ collision_cachedtrace_t *cached = Collision_Cache_Lookup(model, matrix, inversematrix, start, end, hitsupercontentsmask);
if (cached->valid)
{
*trace = cached->result;
return;
}
+ Collision_ClipLineToGenericEntity(trace, model, NULL, NULL, vec3_origin, vec3_origin, 0, matrix, inversematrix, start, end, hitsupercontentsmask, true);
+
+ cached->result = *trace;
+}
+
+void Collision_Cache_ClipLineToWorldSurfaces(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents)
+{
+ collision_cachedtrace_t *cached = Collision_Cache_Lookup(model, &identitymatrix, &identitymatrix, start, end, hitsupercontents);
+ if (cached->valid)
+ {
+ *trace = cached->result;
+ return;
+ }
+
+ Collision_ClipLineToWorld(trace, model, start, end, hitsupercontents, true);
+
+ cached->result = *trace;
+}
+
+void Collision_ClipToGenericEntity(trace_t *trace, dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask)
+{
+ float starttransformed[3], endtransformed[3];
+
memset(trace, 0, sizeof(*trace));
trace->fraction = trace->realfraction = 1;
// transform plane
// NOTE: this relies on plane.dist being directly after plane.normal
Matrix4x4_TransformPositivePlane(matrix, trace->plane.normal[0], trace->plane.normal[1], trace->plane.normal[2], trace->plane.dist, trace->plane.normal);
-
- cached->result = *trace;
}
void Collision_ClipToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontents)
{
- collision_cachedtrace_t *cached = Collision_Cache_Lookup(3, model, NULL, NULL, vec3_origin, vec3_origin, 0, &identitymatrix, &identitymatrix, start, mins, maxs, end, hitsupercontents);
- if (cached->valid)
- {
- *trace = cached->result;
- return;
- }
-
memset(trace, 0, sizeof(*trace));
trace->fraction = trace->realfraction = 1;
// ->TraceBox: TraceBrush not needed here, as worldmodel is never rotated
trace->fraction = bound(0, trace->fraction, 1);
trace->realfraction = bound(0, trace->realfraction, 1);
VectorLerp(start, trace->fraction, end, trace->endpos);
-
- cached->result = *trace;
}
void Collision_ClipLineToGenericEntity(trace_t *trace, dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask, qboolean hitsurfaces)
{
float starttransformed[3], endtransformed[3];
- collision_cachedtrace_t *cached = Collision_Cache_Lookup(2, model, frameblend, skeleton, bodymins, bodymaxs, bodysupercontents, matrix, inversematrix, start, vec3_origin, vec3_origin, end, hitsupercontentsmask);
- if (cached->valid)
- {
- *trace = cached->result;
- return;
- }
-
memset(trace, 0, sizeof(*trace));
trace->fraction = trace->realfraction = 1;
// transform plane
// NOTE: this relies on plane.dist being directly after plane.normal
Matrix4x4_TransformPositivePlane(matrix, trace->plane.normal[0], trace->plane.normal[1], trace->plane.normal[2], trace->plane.dist, trace->plane.normal);
-
- cached->result = *trace;
}
void Collision_ClipLineToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents, qboolean hitsurfaces)
{
- collision_cachedtrace_t *cached = Collision_Cache_Lookup(2, model, NULL, NULL, vec3_origin, vec3_origin, 0, &identitymatrix, &identitymatrix, start, vec3_origin, vec3_origin, end, hitsupercontents);
- if (cached->valid)
- {
- *trace = cached->result;
- return;
- }
-
memset(trace, 0, sizeof(*trace));
trace->fraction = trace->realfraction = 1;
if (model && model->TraceLineAgainstSurfaces && hitsurfaces)
trace->fraction = bound(0, trace->fraction, 1);
trace->realfraction = bound(0, trace->realfraction, 1);
VectorLerp(start, trace->fraction, end, trace->endpos);
-
- cached->result = *trace;
}
void Collision_ClipPointToGenericEntity(trace_t *trace, dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, int hitsupercontentsmask)
{
float starttransformed[3];
- collision_cachedtrace_t *cached = Collision_Cache_Lookup(1, model, frameblend, skeleton, bodymins, bodymaxs, bodysupercontents, matrix, inversematrix, start, vec3_origin, vec3_origin, start, hitsupercontentsmask);
- if (cached->valid)
- {
- *trace = cached->result;
- return;
- }
-
memset(trace, 0, sizeof(*trace));
trace->fraction = trace->realfraction = 1;
// transform plane
// NOTE: this relies on plane.dist being directly after plane.normal
Matrix4x4_TransformPositivePlane(matrix, trace->plane.normal[0], trace->plane.normal[1], trace->plane.normal[2], trace->plane.dist, trace->plane.normal);
-
- cached->result = *trace;
}
void Collision_ClipPointToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, int hitsupercontents)
{
- collision_cachedtrace_t *cached = Collision_Cache_Lookup(1, model, NULL, NULL, vec3_origin, vec3_origin, 0, &identitymatrix, &identitymatrix, start, vec3_origin, vec3_origin, start, hitsupercontents);
- if (cached->valid)
- {
- *trace = cached->result;
- return;
- }
-
memset(trace, 0, sizeof(*trace));
trace->fraction = trace->realfraction = 1;
if (model && model->TracePoint)
model->TracePoint(model, NULL, NULL, trace, start, hitsupercontents);
VectorCopy(start, trace->endpos);
-
- cached->result = *trace;
}
void Collision_CombineTraces(trace_t *cliptrace, const trace_t *trace, void *touch, qboolean isbmodel)
void Collision_ClipToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontents);
void Collision_ClipLineToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents, qboolean hitsurfaces);
void Collision_ClipPointToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, int hitsupercontents);
+// caching surface trace for renderer (NOT THREAD SAFE)
+void Collision_Cache_ClipLineToGenericEntitySurfaces(trace_t *trace, dp_model_t *model, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask);
+void Collision_Cache_ClipLineToWorldSurfaces(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents);
// combines data from two traces:
// merges contents flags, startsolid, allsolid, inwater
// updates fraction, endpos, plane and surface info if new fraction is shorter
//
// reading functions
//
-int msg_readcount;
-qboolean msg_badread;
-void MSG_BeginReading (void)
+void MSG_BeginReading(sizebuf_t *sb)
{
- msg_readcount = 0;
- msg_badread = false;
+ sb->readcount = 0;
+ sb->badread = false;
}
-int MSG_ReadLittleShort (void)
+int MSG_ReadLittleShort(sizebuf_t *sb)
{
- if (msg_readcount+2 > net_message.cursize)
+ if (sb->readcount+2 > sb->cursize)
{
- msg_badread = true;
+ sb->badread = true;
return -1;
}
- msg_readcount += 2;
- return (short)(net_message.data[msg_readcount-2] | (net_message.data[msg_readcount-1]<<8));
+ sb->readcount += 2;
+ return (short)(sb->data[sb->readcount-2] | (sb->data[sb->readcount-1]<<8));
}
-int MSG_ReadBigShort (void)
+int MSG_ReadBigShort (sizebuf_t *sb)
{
- if (msg_readcount+2 > net_message.cursize)
+ if (sb->readcount+2 > sb->cursize)
{
- msg_badread = true;
+ sb->badread = true;
return -1;
}
- msg_readcount += 2;
- return (short)((net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1]);
+ sb->readcount += 2;
+ return (short)((sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1]);
}
-int MSG_ReadLittleLong (void)
+int MSG_ReadLittleLong (sizebuf_t *sb)
{
- if (msg_readcount+4 > net_message.cursize)
+ if (sb->readcount+4 > sb->cursize)
{
- msg_badread = true;
+ sb->badread = true;
return -1;
}
- msg_readcount += 4;
- return net_message.data[msg_readcount-4] | (net_message.data[msg_readcount-3]<<8) | (net_message.data[msg_readcount-2]<<16) | (net_message.data[msg_readcount-1]<<24);
+ sb->readcount += 4;
+ return sb->data[sb->readcount-4] | (sb->data[sb->readcount-3]<<8) | (sb->data[sb->readcount-2]<<16) | (sb->data[sb->readcount-1]<<24);
}
-int MSG_ReadBigLong (void)
+int MSG_ReadBigLong (sizebuf_t *sb)
{
- if (msg_readcount+4 > net_message.cursize)
+ if (sb->readcount+4 > sb->cursize)
{
- msg_badread = true;
+ sb->badread = true;
return -1;
}
- msg_readcount += 4;
- return (net_message.data[msg_readcount-4]<<24) + (net_message.data[msg_readcount-3]<<16) + (net_message.data[msg_readcount-2]<<8) + net_message.data[msg_readcount-1];
+ sb->readcount += 4;
+ return (sb->data[sb->readcount-4]<<24) + (sb->data[sb->readcount-3]<<16) + (sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1];
}
-float MSG_ReadLittleFloat (void)
+float MSG_ReadLittleFloat (sizebuf_t *sb)
{
union
{
float f;
int l;
} dat;
- if (msg_readcount+4 > net_message.cursize)
+ if (sb->readcount+4 > sb->cursize)
{
- msg_badread = true;
+ sb->badread = true;
return -1;
}
- msg_readcount += 4;
- dat.l = net_message.data[msg_readcount-4] | (net_message.data[msg_readcount-3]<<8) | (net_message.data[msg_readcount-2]<<16) | (net_message.data[msg_readcount-1]<<24);
+ sb->readcount += 4;
+ dat.l = sb->data[sb->readcount-4] | (sb->data[sb->readcount-3]<<8) | (sb->data[sb->readcount-2]<<16) | (sb->data[sb->readcount-1]<<24);
return dat.f;
}
-float MSG_ReadBigFloat (void)
+float MSG_ReadBigFloat (sizebuf_t *sb)
{
union
{
float f;
int l;
} dat;
- if (msg_readcount+4 > net_message.cursize)
+ if (sb->readcount+4 > sb->cursize)
{
- msg_badread = true;
+ sb->badread = true;
return -1;
}
- msg_readcount += 4;
- dat.l = (net_message.data[msg_readcount-4]<<24) | (net_message.data[msg_readcount-3]<<16) | (net_message.data[msg_readcount-2]<<8) | net_message.data[msg_readcount-1];
+ sb->readcount += 4;
+ dat.l = (sb->data[sb->readcount-4]<<24) | (sb->data[sb->readcount-3]<<16) | (sb->data[sb->readcount-2]<<8) | sb->data[sb->readcount-1];
return dat.f;
}
-char *MSG_ReadString (void)
+char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring)
{
- static char string[MAX_INPUTLINE];
- const int maxstring = sizeof(string);
- int l = 0,c;
- // read string into buffer, but only store as many characters as will fit
- while ((c = MSG_ReadByte()) > 0)
+ int c;
+ size_t l = 0;
+ // read string into sbfer, but only store as many characters as will fit
+ while ((c = MSG_ReadByte(sb)) > 0)
if (l < maxstring - 1)
string[l++] = c;
string[l] = 0;
return string;
}
-int MSG_ReadBytes (int numbytes, unsigned char *out)
+int MSG_ReadBytes (sizebuf_t *sb, int numbytes, unsigned char *out)
{
int l, c;
- for (l = 0;l < numbytes && (c = MSG_ReadByte()) != -1;l++)
+ for (l = 0;l < numbytes && (c = MSG_ReadByte(sb)) != -1;l++)
out[l] = c;
return l;
}
-float MSG_ReadCoord13i (void)
+float MSG_ReadCoord13i (sizebuf_t *sb)
{
- return MSG_ReadLittleShort() * (1.0/8.0);
+ return MSG_ReadLittleShort(sb) * (1.0/8.0);
}
-float MSG_ReadCoord16i (void)
+float MSG_ReadCoord16i (sizebuf_t *sb)
{
- return (signed short) MSG_ReadLittleShort();
+ return (signed short) MSG_ReadLittleShort(sb);
}
-float MSG_ReadCoord32f (void)
+float MSG_ReadCoord32f (sizebuf_t *sb)
{
- return MSG_ReadLittleFloat();
+ return MSG_ReadLittleFloat(sb);
}
-float MSG_ReadCoord (protocolversion_t protocol)
+float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol)
{
if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
- return MSG_ReadCoord13i();
+ return MSG_ReadCoord13i(sb);
else if (protocol == PROTOCOL_DARKPLACES1)
- return MSG_ReadCoord32f();
+ return MSG_ReadCoord32f(sb);
else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
- return MSG_ReadCoord16i();
+ return MSG_ReadCoord16i(sb);
else
- return MSG_ReadCoord32f();
+ return MSG_ReadCoord32f(sb);
}
-void MSG_ReadVector (float *v, protocolversion_t protocol)
+void MSG_ReadVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
{
- v[0] = MSG_ReadCoord(protocol);
- v[1] = MSG_ReadCoord(protocol);
- v[2] = MSG_ReadCoord(protocol);
+ v[0] = MSG_ReadCoord(sb, protocol);
+ v[1] = MSG_ReadCoord(sb, protocol);
+ v[2] = MSG_ReadCoord(sb, protocol);
}
// LordHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
-float MSG_ReadAngle8i (void)
+float MSG_ReadAngle8i (sizebuf_t *sb)
{
- return (signed char) MSG_ReadByte () * (360.0/256.0);
+ return (signed char) MSG_ReadByte (sb) * (360.0/256.0);
}
-float MSG_ReadAngle16i (void)
+float MSG_ReadAngle16i (sizebuf_t *sb)
{
- return (signed short)MSG_ReadShort () * (360.0/65536.0);
+ return (signed short)MSG_ReadShort (sb) * (360.0/65536.0);
}
-float MSG_ReadAngle32f (void)
+float MSG_ReadAngle32f (sizebuf_t *sb)
{
- return MSG_ReadFloat ();
+ return MSG_ReadFloat (sb);
}
-float MSG_ReadAngle (protocolversion_t protocol)
+float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol)
{
if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
- return MSG_ReadAngle8i ();
+ return MSG_ReadAngle8i (sb);
else
- return MSG_ReadAngle16i ();
+ return MSG_ReadAngle16i (sb);
}
Parse a token out of a string
==============
*/
-int COM_ParseToken_Simple(const char **datapointer, qboolean returnnewline, qboolean parsebackslash)
+int COM_ParseToken_Simple(const char **datapointer, qboolean returnnewline, qboolean parsebackslash, qboolean parsecomments)
{
int len;
int c;
if (data[0] == '\r' && data[1] == '\n')
data++;
- if (data[0] == '/' && data[1] == '/')
+ if (parsecomments && data[0] == '/' && data[1] == '/')
{
// comment
while (*data && *data != '\n' && *data != '\r')
data++;
goto skipwhite;
}
- else if (data[0] == '/' && data[1] == '*')
+ else if (parsecomments && data[0] == '/' && data[1] == '*')
{
// comment
data++;
{ GAME_BATTLEMECH, GAME_BATTLEMECH, "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" }, // COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech
{ GAME_ZYMOTIC, GAME_ZYMOTIC, "zymotic", "-zymotic", "Zymotic", "basezym", NULL, "zymotic", "zymotic" }, // COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic
{ GAME_SETHERAL, GAME_SETHERAL, "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" }, // COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral
-{ GAME_SOM, GAME_NORMAL, "som", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" }, // COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man
+{ GAME_SOM, GAME_NORMAL, "sonofman", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" }, // COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man
{ GAME_TENEBRAE, GAME_NORMAL, "tenebrae", "-tenebrae", "DarkPlaces-Tenebrae", "id1", "tenebrae", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented)
{ GAME_NEOTERIC, GAME_NORMAL, "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" }, // COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric
{ GAME_OPENQUARTZ, GAME_NORMAL, "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces" }, // COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content
int i;
int index = 0;
- FS_StripExtension (com_argv[0], name, sizeof (name));
- COM_ToLowerString (name, name, sizeof (name));
-
- // check executable filename for keywords
+ // check executable filename for keywords, but do it SMARTLY - only check the last path element
+ FS_StripExtension(FS_FileWithoutPath(com_argv[0]), name, sizeof (name));
+ COM_ToLowerString(name, name, sizeof (name));
for (i = 1;i < (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0]));i++)
if (gamemode_info[i].prog_name && gamemode_info[i].prog_name[0] && strstr (name, gamemode_info[i].prog_name))
{
============
va
-does a varargs printf into a temp buffer, so I don't need to have
-varargs versions of all text functions.
-FIXME: make this buffer size safe someday
+varargs print into provided buffer, returns buffer (so that it can be called in-line, unlike dpsnprintf)
============
*/
-char *va(const char *format, ...)
+char *va(char *buf, size_t buflen, const char *format, ...)
{
va_list argptr;
- // LordHavoc: now cycles through 8 buffers to avoid problems in most cases
- static char string[8][1024], *s;
- static int stringindex = 0;
- s = string[stringindex];
- stringindex = (stringindex + 1) & 7;
va_start (argptr, format);
- dpvsnprintf (s, sizeof (string[0]), format,argptr);
+ dpvsnprintf (buf, buflen, format,argptr);
va_end (argptr);
- return s;
+ return buf;
}
if(utf8_enable.integer)
{
+ *out = 0;
while(*in && size_out > 1)
{
int n;
if(utf8_enable.integer)
{
+ *out = 0;
while(*in && size_out > 1)
{
int n;
#undef APPEND
}
-// written by Elric, thanks Elric!
-char *SearchInfostring(const char *infostring, const char *key)
-{
- static char value [MAX_INPUTLINE];
- char crt_key [MAX_INPUTLINE];
- size_t value_ind, key_ind;
- char c;
-
- if (*infostring++ != '\\')
- return NULL;
-
- value_ind = 0;
- for (;;)
- {
- key_ind = 0;
-
- // Get the key name
- for (;;)
- {
- c = *infostring++;
-
- if (c == '\0')
- return NULL;
- if (c == '\\' || key_ind == sizeof (crt_key) - 1)
- {
- crt_key[key_ind] = '\0';
- break;
- }
-
- crt_key[key_ind++] = c;
- }
-
- // If it's the key we are looking for, save it in "value"
- if (!strcmp(crt_key, key))
- {
- for (;;)
- {
- c = *infostring++;
-
- if (c == '\0' || c == '\\' || value_ind == sizeof (value) - 1)
- {
- value[value_ind] = '\0';
- return value;
- }
-
- value[value_ind++] = c;
- }
- }
-
- // Else, skip the value
- for (;;)
- {
- c = *infostring++;
-
- if (c == '\0')
- return NULL;
- if (c == '\\')
- break;
- }
- }
-}
-
-void InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength)
+char *InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength)
{
int pos = 0, j;
size_t keylength;
if (valuelength < 1 || !value)
{
Con_Printf("InfoString_GetValue: no room in value\n");
- return;
+ return NULL;
}
value[0] = 0;
if (strchr(key, '\\'))
{
Con_Printf("InfoString_GetValue: key name \"%s\" contains \\ which is not possible in an infostring\n", key);
- return;
+ return NULL;
}
if (strchr(key, '\"'))
{
Con_Printf("InfoString_SetValue: key name \"%s\" contains \" which is not allowed in an infostring\n", key);
- return;
+ return NULL;
}
if (!key[0])
{
Con_Printf("InfoString_GetValue: can not look up a key with no name\n");
- return;
+ return NULL;
}
while (buffer[pos] == '\\')
{
for (j = 0;buffer[pos+j] && buffer[pos+j] != '\\' && j < (int)valuelength - 1;j++)
value[j] = buffer[pos+j];
value[j] = 0;
- return;
+ return value;
}
for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
}
// if we reach this point the key was not found
+ return NULL;
}
void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value)
if (value && value[0])
{
// set the key/value and append the remaining text
- char tempbuffer[4096];
+ char tempbuffer[MAX_INPUTLINE];
strlcpy(tempbuffer, buffer + pos2, sizeof(tempbuffer));
dpsnprintf(buffer + pos, bufferlength - pos, "\\%s\\%s%s", key, value, tempbuffer);
}
void InfoString_Print(char *buffer)
{
int i;
- char key[2048];
- char value[2048];
+ char key[MAX_INPUTLINE];
+ char value[MAX_INPUTLINE];
while (*buffer)
{
if (*buffer != '\\')
unsigned char *data;
int maxsize;
int cursize;
+ int readcount;
+ qboolean badread; // set if a read goes beyond end of message
} sizebuf_t;
void SZ_Clear (sizebuf_t *buf);
unsigned Com_BlockChecksum (void *buffer, int length);
void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf);
+void COM_Init_Commands(void);
+
//============================================================================
// Endianess handling
void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol);
void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol);
-extern int msg_readcount;
-extern qboolean msg_badread; // set if a read goes beyond end of message
-
-void MSG_BeginReading (void);
-int MSG_ReadLittleShort (void);
-int MSG_ReadBigShort (void);
-int MSG_ReadLittleLong (void);
-int MSG_ReadBigLong (void);
-float MSG_ReadLittleFloat (void);
-float MSG_ReadBigFloat (void);
-char *MSG_ReadString (void);
-int MSG_ReadBytes (int numbytes, unsigned char *out);
-
-#define MSG_ReadChar() (msg_readcount >= net_message.cursize ? (msg_badread = true, -1) : (signed char)net_message.data[msg_readcount++])
-#define MSG_ReadByte() (msg_readcount >= net_message.cursize ? (msg_badread = true, -1) : (unsigned char)net_message.data[msg_readcount++])
+void MSG_BeginReading (sizebuf_t *sb);
+int MSG_ReadLittleShort (sizebuf_t *sb);
+int MSG_ReadBigShort (sizebuf_t *sb);
+int MSG_ReadLittleLong (sizebuf_t *sb);
+int MSG_ReadBigLong (sizebuf_t *sb);
+float MSG_ReadLittleFloat (sizebuf_t *sb);
+float MSG_ReadBigFloat (sizebuf_t *sb);
+char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring);
+int MSG_ReadBytes (sizebuf_t *sb, int numbytes, unsigned char *out);
+
+#define MSG_ReadChar(sb) ((sb)->readcount >= (sb)->cursize ? ((sb)->badread = true, -1) : (signed char)(sb)->data[(sb)->readcount++])
+#define MSG_ReadByte(sb) ((sb)->readcount >= (sb)->cursize ? ((sb)->badread = true, -1) : (unsigned char)(sb)->data[(sb)->readcount++])
#define MSG_ReadShort MSG_ReadLittleShort
#define MSG_ReadLong MSG_ReadLittleLong
#define MSG_ReadFloat MSG_ReadLittleFloat
-float MSG_ReadAngle8i (void);
-float MSG_ReadAngle16i (void);
-float MSG_ReadAngle32f (void);
-float MSG_ReadCoord13i (void);
-float MSG_ReadCoord16i (void);
-float MSG_ReadCoord32f (void);
-float MSG_ReadCoord (protocolversion_t protocol);
-void MSG_ReadVector (float *v, protocolversion_t protocol);
-float MSG_ReadAngle (protocolversion_t protocol);
+float MSG_ReadAngle8i (sizebuf_t *sb);
+float MSG_ReadAngle16i (sizebuf_t *sb);
+float MSG_ReadAngle32f (sizebuf_t *sb);
+float MSG_ReadCoord13i (sizebuf_t *sb);
+float MSG_ReadCoord16i (sizebuf_t *sb);
+float MSG_ReadCoord32f (sizebuf_t *sb);
+float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol);
+void MSG_ReadVector (sizebuf_t *sb, float *v, protocolversion_t protocol);
+float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol);
//@}
//============================================================================
extern char com_token[MAX_INPUTLINE];
-int COM_ParseToken_Simple(const char **datapointer, qboolean returnnewline, qboolean parsebackslash);
+int COM_ParseToken_Simple(const char **datapointer, qboolean returnnewline, qboolean parsebackslash, qboolean parsecomments);
int COM_ParseToken_QuakeC(const char **datapointer, qboolean returnnewline);
int COM_ParseToken_VM_Tokenize(const char **datapointer, qboolean returnnewline);
int COM_ParseToken_Console(const char **datapointer);
void COM_Shutdown (void);
void COM_InitGameType (void);
-char *va(const char *format, ...) DP_FUNC_PRINTF(1);
-// does a varargs printf into a temp buffer
+char *va(char *buf, size_t buflen, const char *format, ...) DP_FUNC_PRINTF(3);
+// does a varargs printf into provided buffer, returns buffer (so it can be called in-line unlike dpsnprintf)
// snprintf and vsnprintf are NOT portable. Use their DP counterparts instead
void stringlistsort(stringlist_t *list, qboolean uniq);
void listdirectory(stringlist_t *list, const char *basepath, const char *path);
-char *SearchInfostring(const char *infostring, const char *key);
-
-void InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength);
+char *InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength);
void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value);
void InfoString_Print(char *buffer);
#include <time.h>
#include "quakedef.h"
+#include "thread.h"
// for u8_encodech
#include "ft2.h"
int con_backscroll;
conbuffer_t con;
+void *con_mutex = NULL;
#define CON_LINES(i) CONBUFFER_LINES(&con, i)
#define CON_LINES_LAST CONBUFFER_LINES_LAST(&con)
return -1;
}
-int Con_FindNextLine(conbuffer_t *buf, int mask_must, int mask_mustnot, int start)
-{
- int i;
- for(i = start + 1; i < buf->lines_count; ++i)
- {
- con_lineinfo_t *l = &CONBUFFER_LINES(buf, i);
-
- if((l->mask & mask_must) != mask_must)
- continue;
- if(l->mask & mask_mustnot)
- continue;
-
- return i;
- }
-
- return -1;
-}
-
const char *ConBuffer_GetLine(conbuffer_t *buf, int i)
{
- static char copybuf[MAX_INPUTLINE];
+ static char copybuf[MAX_INPUTLINE]; // client only
con_lineinfo_t *l = &CONBUFFER_LINES(buf, i);
size_t sz = l->len+1 > sizeof(copybuf) ? sizeof(copybuf) : l->len+1;
strlcpy(copybuf, l->start, sz);
void Log_ConPrint (const char *msg);
//@}
-/*
-====================
-Log_DestBuffer_Init
-====================
-*/
static void Log_DestBuffer_Init(void)
{
memcpy(log_dest_buffer, "\377\377\377\377n", 5); // QW rcon print
log_dest_buffer_pos = 5;
}
-/*
-====================
-Log_DestBuffer_Flush
-====================
-*/
-void Log_DestBuffer_Flush(void)
+static void Log_DestBuffer_Flush_NoLock(void)
{
lhnetaddress_t log_dest_addr;
lhnetsocket_t *log_dest_socket;
/*
====================
-Log_Timestamp
+Log_DestBuffer_Flush
====================
*/
-const char* Log_Timestamp (const char *desc)
+void Log_DestBuffer_Flush(void)
{
- static char timestamp [128];
+ if (con_mutex)
+ Thread_LockMutex(con_mutex);
+ Log_DestBuffer_Flush_NoLock();
+ if (con_mutex)
+ Thread_UnlockMutex(con_mutex);
+}
+
+static const char* Log_Timestamp (const char *desc)
+{
+ static char timestamp [128]; // init/shutdown only
time_t crt_time;
#if _MSC_VER >= 1400
struct tm crt_tm;
return timestamp;
}
-
-/*
-====================
-Log_Open
-====================
-*/
-void Log_Open (void)
+static void Log_Open (void)
{
if (logfile != NULL || log_file.string[0] == '\0')
return;
}
}
-
/*
====================
Log_Close
n = min(sizeof(log_dest_buffer) - log_dest_buffer_pos - 1, logq_ind - pos);
memcpy(log_dest_buffer + log_dest_buffer_pos, temp + pos, n);
log_dest_buffer_pos += n;
- Log_DestBuffer_Flush();
+ Log_DestBuffer_Flush_NoLock();
pos += n;
}
}
*/
void Con_ToggleConsole_f (void)
{
+ if (COM_CheckParm ("-noconsole"))
+ if (!(key_consoleactive & KEY_CONSOLEACTIVE_USER))
+ return; // only allow the key bind to turn off console
+
// toggle the 'user wants console' bit
key_consoleactive ^= KEY_CONSOLEACTIVE_USER;
Con_ClearNotify();
Con_MessageMode_f
================
*/
-void Con_MessageMode_f (void)
+static void Con_MessageMode_f (void)
{
key_dest = key_message;
chat_mode = 0; // "say"
- chat_bufferlen = 0;
- chat_buffer[0] = 0;
+ if(Cmd_Argc() > 1)
+ {
+ dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args());
+ chat_bufferlen = strlen(chat_buffer);
+ }
}
Con_MessageMode2_f
================
*/
-void Con_MessageMode2_f (void)
+static void Con_MessageMode2_f (void)
{
key_dest = key_message;
chat_mode = 1; // "say_team"
- chat_bufferlen = 0;
- chat_buffer[0] = 0;
+ if(Cmd_Argc() > 1)
+ {
+ dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args());
+ chat_bufferlen = strlen(chat_buffer);
+ }
}
/*
Con_CommandMode_f
================
*/
-void Con_CommandMode_f (void)
+static void Con_CommandMode_f (void)
{
key_dest = key_message;
if(Cmd_Argc() > 1)
GetMapList("", NULL, 0);
}
-void Con_ConDump_f (void)
+static void Con_ConDump_f (void)
{
int i;
qfile_t *file;
Con_Printf("condump: unable to write file \"%s\"\n", Cmd_Argv(1));
return;
}
+ if (con_mutex) Thread_LockMutex(con_mutex);
for(i = 0; i < CON_LINES_COUNT; ++i)
{
FS_Write(file, CON_LINES(i).start, CON_LINES(i).len);
FS_Write(file, "\n", 1);
}
+ if (con_mutex) Thread_UnlockMutex(con_mutex);
FS_Close(file);
}
void Con_Clear_f (void)
{
+ if (con_mutex) Thread_LockMutex(con_mutex);
ConBuffer_Clear(&con);
+ if (con_mutex) Thread_UnlockMutex(con_mutex);
}
/*
{
con_linewidth = 80;
ConBuffer_Init(&con, CON_TEXTSIZE, CON_MAXLINES, zonemempool);
+ if (Thread_HasThreads())
+ con_mutex = Thread_CreateMutex();
// Allocate a log queue, this will be freed after configs are parsed
logq_size = MAX_INPUTLINE;
void Con_Shutdown (void)
{
+ if (con_mutex) Thread_LockMutex(con_mutex);
ConBuffer_Shutdown(&con);
+ if (con_mutex) Thread_UnlockMutex(con_mutex);
+ if (con_mutex) Thread_DestroyMutex(con_mutex);con_mutex = NULL;
}
/*
If no console is visible, the notify window will pop up.
================
*/
-void Con_PrintToHistory(const char *txt, int mask)
+static void Con_PrintToHistory(const char *txt, int mask)
{
// process:
// \n goes to next line
// \r deletes current line and makes a new one
static int cr_pending = 0;
- static char buf[CON_TEXTSIZE];
+ static char buf[CON_TEXTSIZE]; // con_mutex
static int bufpos = 0;
if(!con.text) // FIXME uses a non-abstracted property of con
rcon_redirect_bufferpos = 5;
}
-void Con_Rcon_Redirect_Flush(void)
+static void Con_Rcon_Redirect_Flush(void)
{
rcon_redirect_buffer[rcon_redirect_bufferpos] = 0;
if (rcon_redirect_proquakeprotocol)
================
*/
/// Adds a character to the rcon buffer.
-void Con_Rcon_AddChar(int c)
+static void Con_Rcon_AddChar(int c)
{
if(log_dest_buffer_appending)
return;
Log_DestBuffer_Init();
log_dest_buffer[log_dest_buffer_pos++] = c;
if(log_dest_buffer_pos >= sizeof(log_dest_buffer) - 1) // minus one, to allow for terminating zero
- Log_DestBuffer_Flush();
+ Log_DestBuffer_Flush_NoLock();
}
else
log_dest_buffer_pos = 0;
static int index = 0;
static char line[MAX_INPUTLINE];
+ if (con_mutex)
+ Thread_LockMutex(con_mutex);
+
for (;*msg;msg++)
{
Con_Rcon_AddChar(*msg);
mask = 0;
}
}
+
+ if (con_mutex)
+ Thread_UnlockMutex(con_mutex);
}
/*
================
*/
extern cvar_t r_font_disable_freetype;
-void Con_DrawInput (void)
+static void Con_DrawInput (void)
{
int y;
int i;
int ofs = u8_bytelen(text + key_linepos, 1);
size_t len;
const char *curbuf;
- curbuf = u8_encodech(0xE000 + 11 + 130 * key_insert, &len);
+ char charbuf16[16];
+ curbuf = u8_encodech(0xE000 + 11 + 130 * key_insert, &len, charbuf16);
if (curbuf)
{
{
size_t len;
const char *curbuf;
- curbuf = u8_encodech(0xE000 + 11 + 130 * key_insert, &len);
+ char charbuf16[16];
+ curbuf = u8_encodech(0xE000 + 11 + 130 * key_insert, &len, charbuf16);
memcpy(text, curbuf, len);
text[len] = 0;
}
}
con_text_info_t;
-float Con_WordWidthFunc(void *passthrough, const char *w, size_t *length, float maxWidth)
+static float Con_WordWidthFunc(void *passthrough, const char *w, size_t *length, float maxWidth)
{
con_text_info_t *ti = (con_text_info_t *) passthrough;
if(w == NULL)
return DrawQ_TextWidth(w, *length, ti->fontsize, ti->fontsize, false, ti->font);
else
{
- printf("Con_WordWidthFunc: can't get here (maxWidth should never be %f)\n", maxWidth);
+ Sys_PrintfToTerminal("Con_WordWidthFunc: can't get here (maxWidth should never be %f)\n", maxWidth);
// Note: this is NOT a Con_Printf, as it could print recursively
return 0;
}
}
-int Con_CountLineFunc(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
+static int Con_CountLineFunc(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
{
(void) passthrough;
(void) line;
return 1;
}
-int Con_DisplayLineFunc(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
+static int Con_DisplayLineFunc(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
{
con_text_info_t *ti = (con_text_info_t *) passthrough;
return 1;
}
-int Con_DrawNotifyRect(int mask_must, int mask_mustnot, float maxage, float x, float y, float width, float height, float fontsize, float alignment_x, float alignment_y, const char *continuationString)
+static int Con_DrawNotifyRect(int mask_must, int mask_mustnot, float maxage, float x, float y, float width, float height, float fontsize, float alignment_x, float alignment_y, const char *continuationString)
{
int i;
int lines = 0;
int numChatlines;
int chatpos;
+ if (con_mutex) Thread_LockMutex(con_mutex);
ConBuffer_FixTimes(&con);
numChatlines = con_chat.integer;
//static char *cursor[2] = { "\xee\x80\x8a", "\xee\x80\x8b" }; // { off, on }
int colorindex = -1;
const char *cursor;
- cursor = u8_encodech(0xE00A + ((int)(realtime * con_cursorspeed)&1), NULL);
+ char charbuf16[16];
+ cursor = u8_encodech(0xE00A + ((int)(realtime * con_cursorspeed)&1), NULL, charbuf16);
// LordHavoc: speedup, and other improvements
if (chat_mode < 0)
x = min(xr, x);
DrawQ_String(x, v, temptext, 0, inputsize, inputsize, 1.0, 1.0, 1.0, 1.0, 0, &colorindex, false, FONT_CHAT);
}
+ if (con_mutex) Thread_UnlockMutex(con_mutex);
}
/*
Returns the height of a given console line; calculates it if necessary.
================
*/
-int Con_LineHeight(int lineno)
+static int Con_LineHeight(int lineno)
{
con_lineinfo_t *li = &CON_LINES(lineno);
if(li->height == -1)
returned.
================
*/
-int Con_DrawConsoleLine(int mask_must, int mask_mustnot, float y, int lineno, float ymin, float ymax)
+static int Con_DrawConsoleLine(int mask_must, int mask_mustnot, float y, int lineno, float ymin, float ymax)
{
float width = vid_conwidth.value;
con_text_info_t ti;
if (lines <= 0)
return;
+ if (con_mutex) Thread_LockMutex(con_mutex);
+
if (con_backscroll < 0)
con_backscroll = 0;
Con_DrawInput ();
r_draw2d_force = false;
+ if (con_mutex) Thread_UnlockMutex(con_mutex);
}
/*
for (;;)
{
int l;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break;
if (com_token[0] == '{')
continue;
for (l = 0;l < (int)sizeof(keyname) - 1 && com_token[k+l] && !ISWHITESPACE(com_token[k+l]);l++)
keyname[l] = com_token[k+l];
keyname[l] = 0;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break;
if (developer_extra.integer)
Con_DPrintf("key: %s %s\n", keyname, com_token);
SanitizeString strips color tags from the string in
and writes the result on string out
*/
-void SanitizeString(char *in, char *out)
+static void SanitizeString(char *in, char *out)
{
while(*in)
{
static int Nicks_matchpos;
// co against <<:BLASTER:>> is true!?
-int Nicks_strncasecmp_nospaces(char *a, char *b, unsigned int a_len)
+static int Nicks_strncasecmp_nospaces(char *a, char *b, unsigned int a_len)
{
while(a_len)
{
}
return 0;
}
-int Nicks_strncasecmp(char *a, char *b, unsigned int a_len)
+static int Nicks_strncasecmp(char *a, char *b, unsigned int a_len)
{
char space_char;
if(!(con_nickcompletion_flags.integer & NICKS_ALPHANUMERICS_ONLY))
Count the number of possible nicks to complete
*/
-int Nicks_CompleteCountPossible(char *line, int pos, char *s, qboolean isCon)
+static int Nicks_CompleteCountPossible(char *line, int pos, char *s, qboolean isCon)
{
char name[128];
int i, p;
return count;
}
-void Cmd_CompleteNicksPrint(int count)
+static void Cmd_CompleteNicksPrint(int count)
{
int i;
for(i = 0; i < count; ++i)
Con_Printf("%s\n", Nicks_list[i]);
}
-void Nicks_CutMatchesNormal(int count)
+static void Nicks_CutMatchesNormal(int count)
{
// cut match 0 down to the longest possible completion
int i;
//Con_Printf("List0: %s\n", Nicks_sanlist[0]);
}
-unsigned int Nicks_strcleanlen(const char *s)
+static unsigned int Nicks_strcleanlen(const char *s)
{
unsigned int l = 0;
while(*s)
return l;
}
-void Nicks_CutMatchesAlphaNumeric(int count)
+static void Nicks_CutMatchesAlphaNumeric(int count)
{
// cut match 0 down to the longest possible completion
int i;
}
}
-void Nicks_CutMatchesNoSpaces(int count)
+static void Nicks_CutMatchesNoSpaces(int count)
{
// cut match 0 down to the longest possible completion
int i;
}
}
-void Nicks_CutMatches(int count)
+static void Nicks_CutMatches(int count)
{
if(con_nickcompletion_flags.integer & NICKS_ALPHANUMERICS_ONLY)
Nicks_CutMatchesAlphaNumeric(count);
Nicks_CutMatchesNormal(count);
}
-const char **Nicks_CompleteBuildList(int count)
+static const char **Nicks_CompleteBuildList(int count)
{
const char **buf;
int bpos = 0;
Nicks_AddLastColor
Restores the previous used color, after the autocompleted name.
*/
-int Nicks_AddLastColor(char *buffer, int pos)
+static int Nicks_AddLastColor(char *buffer, int pos)
{
qboolean quote_added = false;
int match;
int c, v, a, i, cmd_len, pos, k;
int n; // nicks --blub
const char *space, *patterns;
+ char vabuf[1024];
//find what we want to complete
pos = key_linepos;
{
strlcpy(command, key_line + 1, min(sizeof(command), (unsigned int)(space - key_line)));
- patterns = Cvar_VariableString(va("con_completion_%s", command)); // TODO maybe use a better place for this?
+ patterns = Cvar_VariableString(va(vabuf, sizeof(vabuf), "con_completion_%s", command)); // TODO maybe use a better place for this?
if(patterns && !*patterns)
patterns = NULL; // get rid of the empty string
stringlistinit(&resultbuf);
stringlistinit(&dirbuf);
- while(COM_ParseToken_Simple(&patterns, false, false))
+ while(COM_ParseToken_Simple(&patterns, false, false, true))
{
fssearch_t *search;
if(strchr(com_token, '/'))
void Con_ClearNotify (void);
void Con_ToggleConsole_f (void);
+int Nicks_CompleteChatLine(char *buffer, size_t size, unsigned int pos);
+
qboolean GetMapList (const char *s, char *completedname, int completednamebufferlength);
/// wrapper function to attempt to either complete the command line
#include "quakedef.h"
#include "crypto.h"
#include "common.h"
+#include "thread.h"
#include "hmac.h"
#include "libcurl.h"
#define qd0_blind_id_util_sha256 d0_blind_id_util_sha256
#define qd0_blind_id_sign_with_private_id_sign d0_blind_id_sign_with_private_id_sign
#define qd0_blind_id_sign_with_private_id_sign_detached d0_blind_id_sign_with_private_id_sign_detached
+#define qd0_blind_id_setmallocfuncs d0_blind_id_setmallocfuncs
+#define qd0_blind_id_setmutexfuncs d0_blind_id_setmutexfuncs
#else
#endif
#define D0_BOOL int
+typedef void *(d0_malloc_t)(size_t len);
+typedef void (d0_free_t)(void *p);
+typedef void *(d0_createmutex_t)(void);
+typedef void (d0_destroymutex_t)(void *);
+typedef int (d0_lockmutex_t)(void *); // zero on success
+typedef int (d0_unlockmutex_t)(void *); // zero on success
+
typedef struct d0_blind_id_s d0_blind_id_t;
typedef D0_BOOL (*d0_fastreject_function) (const d0_blind_id_t *ctx, void *pass);
static D0_EXPORT D0_WARN_UNUSED_RESULT d0_blind_id_t *(*qd0_blind_id_new) (void);
static D0_EXPORT void (*qd0_blind_id_util_sha256) (char *out, const char *in, size_t n);
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL (*qd0_blind_id_sign_with_private_id_sign) (d0_blind_id_t *ctx, D0_BOOL is_first, D0_BOOL send_modulus, const char *message, size_t msglen, char *outbuf, size_t *outbuflen);
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL (*qd0_blind_id_sign_with_private_id_sign_detached) (d0_blind_id_t *ctx, D0_BOOL is_first, D0_BOOL send_modulus, const char *message, size_t msglen, char *outbuf, size_t *outbuflen);
+static D0_EXPORT void (*qd0_blind_id_setmallocfuncs)(d0_malloc_t *m, d0_free_t *f);
+static D0_EXPORT void (*qd0_blind_id_setmutexfuncs)(d0_createmutex_t *c, d0_destroymutex_t *d, d0_lockmutex_t *l, d0_unlockmutex_t *u);
static dllfunction_t d0_blind_id_funcs[] =
{
{"d0_blind_id_new", (void **) &qd0_blind_id_new},
{"d0_blind_id_util_sha256", (void **) &qd0_blind_id_util_sha256},
{"d0_blind_id_sign_with_private_id_sign", (void **) &qd0_blind_id_sign_with_private_id_sign},
{"d0_blind_id_sign_with_private_id_sign_detached", (void **) &qd0_blind_id_sign_with_private_id_sign_detached},
+ {"d0_blind_id_setmallocfuncs", (void **) &qd0_blind_id_setmallocfuncs},
+ {"d0_blind_id_setmutexfuncs", (void **) &qd0_blind_id_setmutexfuncs},
{NULL, NULL}
};
// end of d0_blind_id interface
qd0_blind_id_util_sha256((char *) out, (const char *) in, n);
}
-static size_t Crypto_LoadFile(const char *path, char *buf, size_t nmax)
+static size_t Crypto_LoadFile(const char *path, char *buf, size_t nmax, qboolean inuserdir)
{
+ char vabuf[1024];
qfile_t *f = NULL;
fs_offset_t n;
- if(*fs_userdir)
- f = FS_SysOpen(va("%s%s", fs_userdir, path), "rb", false);
- if(!f)
- f = FS_SysOpen(va("%s%s", fs_basedir, path), "rb", false);
+ if(inuserdir)
+ f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%s%s", *fs_userdir ? fs_userdir : fs_basedir, path), "rb", false);
+ else
+ f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%s%s", fs_basedir, path), "rb", false);
if(!f)
return 0;
n = FS_Read(f, buf, nmax);
challenge_append_length = p - challenge_append;
}
-static void Crypto_LoadKeys(void)
+void Crypto_LoadKeys(void)
{
char buf[8192];
size_t len, len2;
int i;
+ char vabuf[1024];
+
+ if(!d0_blind_id_dll) // don't if we can't
+ return;
+
+ if(crypto_idstring) // already loaded? then not
+ return;
+
+ Host_LockSession(); // we use the session ID here
// load keys
// note: we are just a CLIENT
memset(pubkeys_fp64[i], 0, sizeof(pubkeys_fp64[i]));
memset(pubkeys_priv_fp64[i], 0, sizeof(pubkeys_fp64[i]));
pubkeys_havepriv[i] = false;
- len = Crypto_LoadFile(va("key_%d.d0pk", i), buf, sizeof(buf));
+ len = Crypto_LoadFile(va(vabuf, sizeof(vabuf), "key_%d.d0pk", i), buf, sizeof(buf), false);
if((pubkeys[i] = Crypto_ReadPublicKey(buf, len)))
{
len2 = FP64_SIZE;
if(qd0_blind_id_fingerprint64_public_key(pubkeys[i], pubkeys_fp64[i], &len2)) // keeps final NUL
{
Con_Printf("Loaded public key key_%d.d0pk (fingerprint: %s)\n", i, pubkeys_fp64[i]);
- len = Crypto_LoadFile(va("key_%d.d0si", i), buf, sizeof(buf));
+ len = Crypto_LoadFile(va(vabuf, sizeof(vabuf), "key_%d.d0si%s", i, sessionid.string), buf, sizeof(buf), true);
if(len)
{
if(Crypto_AddPrivateKey(pubkeys[i], buf, len))
len2 = FP64_SIZE;
if(qd0_blind_id_fingerprint64_public_id(pubkeys[i], pubkeys_priv_fp64[i], &len2)) // keeps final NUL
{
- Con_Printf("Loaded private ID key_%d.d0si for key_%d.d0pk (fingerprint: %s)\n", i, i, pubkeys_priv_fp64[i]);
+ Con_Printf("Loaded private ID key_%d.d0si%s for key_%d.d0pk (public key fingerprint: %s)\n", i, sessionid.string, i, pubkeys_priv_fp64[i]);
pubkeys_havepriv[i] = true;
- strlcat(crypto_idstring_buf, va(" %s@%s", pubkeys_priv_fp64[i], pubkeys_fp64[i]), sizeof(crypto_idstring_buf));
+ strlcat(crypto_idstring_buf, va(vabuf, sizeof(vabuf), " %s@%s", pubkeys_priv_fp64[i], pubkeys_fp64[i]), sizeof(crypto_idstring_buf));
}
else
{
static void Crypto_UnloadKeys(void)
{
int i;
+
keygen_i = -1;
for(i = 0; i < MAX_PUBKEYS; ++i)
{
crypto_idstring = NULL;
}
+static mempool_t *cryptomempool;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+static void *Crypto_d0_malloc(size_t len)
+{
+ return Mem_Alloc(cryptomempool, len);
+}
+
+static void Crypto_d0_free(void *p)
+{
+ Mem_Free(p);
+}
+
+static void *Crypto_d0_createmutex(void)
+{
+ return Thread_CreateMutex();
+}
+
+static void Crypto_d0_destroymutex(void *m)
+{
+ Thread_DestroyMutex(m);
+}
+
+static int Crypto_d0_lockmutex(void *m)
+{
+ return Thread_LockMutex(m);
+}
+
+static int Crypto_d0_unlockmutex(void *m)
+{
+ return Thread_UnlockMutex(m);
+}
+#ifdef __cplusplus
+}
+#endif
+
void Crypto_Shutdown(void)
{
crypto_t *crypto;
Crypto_CloseLibrary();
}
+
+ Mem_FreePool(&cryptomempool);
}
void Crypto_Init(void)
{
+ cryptomempool = Mem_AllocPool("crypto", 0, NULL);
+
if(!Crypto_OpenLibrary())
return;
+ qd0_blind_id_setmallocfuncs(Crypto_d0_malloc, Crypto_d0_free);
+ if (Thread_HasThreads())
+ qd0_blind_id_setmutexfuncs(Crypto_d0_createmutex, Crypto_d0_destroymutex, Crypto_d0_lockmutex, Crypto_d0_unlockmutex);
+
if(!qd0_blind_id_INITIALIZE())
{
Crypto_Rijndael_CloseLibrary();
Crypto_Rijndael_OpenLibrary(); // if this fails, it's uncritical
Crypto_InitHostKeys();
- Crypto_LoadKeys();
}
// end
+qboolean Crypto_Available(void)
+{
+ if(!d0_blind_id_dll)
+ return false;
+ return true;
+}
+
// keygen code
static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned char *buffer, void *cbdata)
{
d0_blind_id_t *ctx, *ctx2;
D0_BOOL status;
size_t len2;
+ char vabuf[1024];
+
+ SV_LockThreadMutex();
if(!d0_blind_id_dll)
{
Con_Print("libd0_blind_id DLL not found, this command is inactive.\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
{
Con_Printf("overflow of keygen_i\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(keygen_i < 0)
{
Con_Printf("Unexpected response from keygen server:\n");
Com_HexDumpToConsole(buffer, length_received);
+ SV_UnlockThreadMutex();
return;
}
if(!Crypto_ParsePack((const char *) buffer, length_received, FOURCC_D0IR, p, l, 1))
Com_HexDumpToConsole(buffer, length_received);
}
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!qd0_blind_id_finish_private_id_request(pubkeys[keygen_i], p[0], l[0]))
{
Con_Printf("d0_blind_id_finish_private_id_request failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
{
Con_Printf("d0_blind_id_new failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
ctx2 = qd0_blind_id_new();
Con_Printf("d0_blind_id_new failed\n");
qd0_blind_id_free(ctx);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!qd0_blind_id_copy(ctx, pubkeys[keygen_i]))
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!qd0_blind_id_copy(ctx2, pubkeys[keygen_i]))
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
bufsize = sizeof(buf);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2size = sizeof(buf2);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
bufsize = sizeof(buf);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2size = sizeof(buf2);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
qd0_blind_id_free(ctx);
len2 = FP64_SIZE;
if(qd0_blind_id_fingerprint64_public_id(pubkeys[keygen_i], pubkeys_priv_fp64[keygen_i], &len2)) // keeps final NUL
{
- Con_Printf("Received private ID key_%d.d0pk (fingerprint: %s)\n", keygen_i, pubkeys_priv_fp64[keygen_i]);
+ Con_Printf("Received private ID key_%d.d0pk (public key fingerprint: %s)\n", keygen_i, pubkeys_priv_fp64[keygen_i]);
pubkeys_havepriv[keygen_i] = true;
- strlcat(crypto_idstring_buf, va(" %s@%s", pubkeys_priv_fp64[keygen_i], pubkeys_fp64[keygen_i]), sizeof(crypto_idstring_buf));
+ strlcat(crypto_idstring_buf, va(vabuf, sizeof(vabuf), " %s@%s", pubkeys_priv_fp64[keygen_i], pubkeys_fp64[keygen_i]), sizeof(crypto_idstring_buf));
crypto_idstring = crypto_idstring_buf;
Crypto_BuildChallengeAppend();
}
{
Con_Printf("d0_blind_id_write_private_id failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!(buf2size = Crypto_UnParsePack(buf2, sizeof(buf2), FOURCC_D0SI, p, l, 1)))
{
Con_Printf("Crypto_UnParsePack failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
- if(*fs_userdir)
- {
- FS_CreatePath(va("%skey_%d.d0si", fs_userdir, keygen_i));
- f = FS_SysOpen(va("%skey_%d.d0si", fs_userdir, keygen_i), "wb", false);
- }
- if(!f)
- {
- FS_CreatePath(va("%skey_%d.d0si", fs_basedir, keygen_i));
- f = FS_SysOpen(va("%skey_%d.d0si", fs_basedir, keygen_i), "wb", false);
- }
+ FS_CreatePath(va(vabuf, sizeof(vabuf), "%skey_%d.d0si%s", *fs_userdir ? fs_userdir : fs_basedir, keygen_i, sessionid.string));
+ f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%skey_%d.d0si%s", *fs_userdir ? fs_userdir : fs_basedir, keygen_i, sessionid.string), "wb", false);
if(!f)
{
- Con_Printf("Cannot open key_%d.d0si\n", keygen_i);
+ Con_Printf("Cannot open key_%d.d0si%s\n", keygen_i, sessionid.string);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
FS_Write(f, buf2, buf2size);
FS_Close(f);
- Con_Printf("Saved to key_%d.d0si\n", keygen_i);
+ Con_Printf("Saved to key_%d.d0si%s\n", keygen_i, sessionid.string);
keygen_i = -1;
+ SV_UnlockThreadMutex();
}
static void Crypto_KeyGen_f(void)
Con_Printf("usage:\n%s id url\n", Cmd_Argv(0));
return;
}
+ SV_LockThreadMutex();
+ Crypto_LoadKeys();
i = atoi(Cmd_Argv(1));
if(!pubkeys[i])
{
Con_Printf("there is no public key %d\n", i);
+ SV_UnlockThreadMutex();
return;
}
if(pubkeys_havepriv[i])
{
Con_Printf("there is already a private key for %d\n", i);
+ SV_UnlockThreadMutex();
return;
}
if(keygen_i >= 0)
{
Con_Printf("there is already a keygen run on the way\n");
+ SV_UnlockThreadMutex();
return;
}
keygen_i = i;
{
Con_Printf("d0_blind_id_start failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
p[0] = buf;
{
Con_Printf("d0_blind_id_generate_private_id_request failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2pos = strlen(Cmd_Argv(2));
{
Con_Printf("Crypto_UnParsePack failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!(buf2l = base64_encode((unsigned char *) (buf2 + buf2pos), buf2l, sizeof(buf2) - buf2pos - 1)))
{
Con_Printf("base64_encode failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2l += buf2pos;
{
Con_Printf("curl failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
Con_Printf("key generation in progress\n");
+ SV_UnlockThreadMutex();
}
// end
{
Con_Printf("%2d: public key key_%d.d0pk (fingerprint: %s)\n", i, i, pubkeys_fp64[i]);
if(pubkeys_havepriv[i])
- Con_Printf(" private ID key_%d.d0si (fingerprint: %s)\n", i, pubkeys_priv_fp64[i]);
+ Con_Printf(" private ID key_%d.d0si%s (public key fingerprint: %s)\n", i, sessionid.string, pubkeys_priv_fp64[i]);
}
}
}
int aeslevel;
D0_BOOL aes;
D0_BOOL status;
+ char infostringvalue[MAX_INPUTLINE];
+ char vabuf[1024];
if(!d0_blind_id_dll)
return CRYPTO_NOMATCH; // no support
int i;
// sorry, we have to verify the challenge here to not reflect network spam
- if (!(s = SearchInfostring(string + 4, "challenge")))
+ if (!(s = InfoString_GetValue(string + 4, "challenge", infostringvalue, sizeof(infostringvalue))))
return CRYPTO_NOMATCH; // will be later accepted if encryption was set up
// validate the challenge
for (i = 0;i < MAX_CHALLENGES;i++)
const char *cnt, *s, *p;
int id;
int clientid = -1, serverid = -1;
- cnt = SearchInfostring(string + 4, "id");
+ cnt = InfoString_GetValue(string + 4, "id", infostringvalue, sizeof(infostringvalue));
id = (cnt ? atoi(cnt) : -1);
- cnt = SearchInfostring(string + 4, "cnt");
+ cnt = InfoString_GetValue(string + 4, "cnt", infostringvalue, sizeof(infostringvalue));
if(!cnt)
return CRYPTO_DISCARD; // pre-challenge: rather be silent
GetUntilNul(&data_in, &len_in);
if(!strcmp(cnt, "0"))
{
int i;
- if (!(s = SearchInfostring(string + 4, "challenge")))
+ if (!(s = InfoString_GetValue(string + 4, "challenge", infostringvalue, sizeof(infostringvalue))))
return CRYPTO_DISCARD; // pre-challenge: rather be silent
// validate the challenge
for (i = 0;i < MAX_CHALLENGES;i++)
if (i == MAX_CHALLENGES) // challenge mismatch is silent
return CRYPTO_DISCARD; // pre-challenge: rather be silent
- if (!(s = SearchInfostring(string + 4, "aeslevel")))
+ if (!(s = InfoString_GetValue(string + 4, "aeslevel", infostringvalue, sizeof(infostringvalue))))
aeslevel = 0; // not supported
else
aeslevel = bound(0, atoi(s), 3);
CLEAR_CDATA;
return Crypto_ServerError(data_out, len_out, "d0_blind_id_copy failed", "Internal error");
}
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\1\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\1\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
if(!qd0_blind_id_authenticate_with_private_id_start(CDATA->id, true, false, "XONOTIC", 8, data_out_p, len_out)) // len_out receives used size by this op
{
CLEAR_CDATA;
CLEAR_CDATA;
return Crypto_ServerError(data_out, len_out, "d0_blind_id_copy failed", "Internal error");
}
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\5\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\5\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
if(!qd0_blind_id_authenticate_with_private_id_challenge(CDATA->id, true, false, data_in, len_in, data_out_p, len_out, &status))
{
CLEAR_CDATA;
return CRYPTO_NOMATCH; // pre-challenge, rather be silent
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 2)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\3\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\3\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_response(CDATA->id, data_in, len_in, data_out_p, len_out))
{
CLEAR_CDATA;
return CRYPTO_NOMATCH; // pre-challenge, rather be silent
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 4)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\5\\id\\%d", CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\5\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_challenge(CDATA->id, true, false, data_in, len_in, data_out_p, len_out, &status))
{
CLEAR_CDATA;
return CRYPTO_NOMATCH; // pre-challenge, rather be silent
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 6)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
if(!qd0_blind_id_authenticate_with_private_id_verify(CDATA->id, data_in, len_in, msgbuf, &msgbuflen, &status))
{
const char *cnt;
qboolean do_time = false;
qboolean do_reject = false;
+ char infostringvalue[MAX_INPUTLINE];
if(crypto_servercpupercent.value > 0 || crypto_servercpumaxtime.value > 0)
if(len_in > 5 && !memcmp(data_in, "d0pk\\", 5))
{
do_time = true;
- cnt = SearchInfostring(data_in + 4, "cnt");
+ cnt = InfoString_GetValue(data_in + 4, "cnt", infostringvalue, sizeof(infostringvalue));
if(cnt)
if(!strcmp(cnt, "0"))
do_reject = true;
*len_out = 0;
return CRYPTO_DISCARD;
}
- t = Sys_DoubleTime();
+ t = Sys_DirtyTime();
}
ret = Crypto_ServerParsePacket_Internal(data_in, len_in, data_out, len_out, peeraddress);
if(do_time)
{
- t = Sys_DoubleTime() - t;
+ t = Sys_DirtyTime() - t;if (t < 0.0) t = 0.0; // dirtytime can step backwards
if(crypto_servercpudebug.integer)
Con_Printf("crypto: accumulator was %.1f ms, used %.1f ms for crypto, ", crypto_servercpu_accumulator * 1000, t * 1000);
crypto_servercpu_accumulator -= t;
D0_BOOL aes;
char *data_out_p = data_out;
D0_BOOL status;
+ char infostringvalue[MAX_INPUTLINE];
+ char vabuf[1024];
if(!d0_blind_id_dll)
return CRYPTO_NOMATCH; // no support
}
else if (len_in >= 13 && !memcmp(string, "infoResponse\x0A", 13))
{
- s = SearchInfostring(string + 13, "d0_blind_id");
+ s = InfoString_GetValue(string + 13, "d0_blind_id", infostringvalue, sizeof(infostringvalue));
if(s)
Crypto_StoreHostKey(peeraddress, s, true);
return CRYPTO_NOMATCH;
save = *p;
* (char *) p = 0; // cut off the string there
}
- s = SearchInfostring(string + 15, "d0_blind_id");
+ s = InfoString_GetValue(string + 15, "d0_blind_id", infostringvalue, sizeof(infostringvalue));
if(s)
Crypto_StoreHostKey(peeraddress, s, true);
if(p)
// build outgoing message
// append regular stuff
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\0\\id\\%d\\aeslevel\\%d\\challenge\\%s", CDATA->cdata_id, d0_rijndael_dll ? crypto_aeslevel.integer : 0, challenge));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\0\\id\\%d\\aeslevel\\%d\\challenge\\%s", CDATA->cdata_id, d0_rijndael_dll ? crypto_aeslevel.integer : 0, challenge));
PutWithNul(&data_out_p, len_out, serverid >= 0 ? pubkeys_fp64[serverid] : "");
PutWithNul(&data_out_p, len_out, clientid >= 0 ? pubkeys_fp64[clientid] : "");
{
const char *cnt;
int id;
- cnt = SearchInfostring(string + 4, "id");
+ cnt = InfoString_GetValue(string + 4, "id", infostringvalue, sizeof(infostringvalue));
id = (cnt ? atoi(cnt) : -1);
- cnt = SearchInfostring(string + 4, "cnt");
+ cnt = InfoString_GetValue(string + 4, "cnt", infostringvalue, sizeof(infostringvalue));
if(!cnt)
return Crypto_ClientError(data_out, len_out, "d0pk\\ message without cnt");
GetUntilNul(&data_in, &len_in);
{
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 1)
- return Crypto_SoftClientError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftClientError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
cls.connect_nextsendtime = max(cls.connect_nextsendtime, realtime + 1); // prevent "hammering"
- if((s = SearchInfostring(string + 4, "aes")))
+ if((s = InfoString_GetValue(string + 4, "aes", infostringvalue, sizeof(infostringvalue))))
aes = atoi(s);
else
aes = false;
}
crypto->use_aes = aes != 0;
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\2\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\2\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_challenge(CDATA->id, true, false, data_in, len_in, data_out_p, len_out, &status))
{
CLEAR_CDATA;
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 3)
- return Crypto_SoftClientError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftClientError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
cls.connect_nextsendtime = max(cls.connect_nextsendtime, realtime + 1); // prevent "hammering"
}
// cache the server key
- Crypto_StoreHostKey(&cls.connect_address, va("%d %s@%s", crypto->use_aes ? 1 : 0, crypto->server_idfp, pubkeys_fp64[CDATA->s]), false);
+ Crypto_StoreHostKey(&cls.connect_address, va(vabuf, sizeof(vabuf), "%d %s@%s", crypto->use_aes ? 1 : 0, crypto->server_idfp, pubkeys_fp64[CDATA->s]), false);
if(CDATA->c >= 0)
{
// client will auth next
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\4\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\4\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_copy(CDATA->id, pubkeys[CDATA->c]))
{
CLEAR_CDATA;
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 5)
- return Crypto_SoftClientError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftClientError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
cls.connect_nextsendtime = max(cls.connect_nextsendtime, realtime + 1); // prevent "hammering"
if(CDATA->s < 0) // only if server didn't auth
{
- if((s = SearchInfostring(string + 4, "aes")))
+ if((s = InfoString_GetValue(string + 4, "aes", infostringvalue, sizeof(infostringvalue))))
aes = atoi(s);
else
aes = false;
crypto->use_aes = aes != 0;
}
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\6\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\6\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_response(CDATA->id, data_in, len_in, data_out_p, len_out))
{
CLEAR_CDATA;
void Crypto_Init(void);
void Crypto_Init_Commands(void);
+void Crypto_LoadKeys(void); // NOTE: when this is called, the SV_LockThreadMutex MUST be active
void Crypto_Shutdown(void);
+qboolean Crypto_Available(void);
+void sha256(unsigned char *out, const unsigned char *in, int n); // may ONLY be called if Crypto_Available()
const void *Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len);
const void *Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len);
#define CRYPTO_NOMATCH 0 // process as usual (packet was not used)
//[515]: omg !!! optimize it ! a lot of hacks here and there also :P
#define CSQC_RETURNVAL prog->globals.generic[OFS_RETURN]
-#define CSQC_BEGIN csqc_tmpprog=prog;prog=0;PRVM_SetProg(PRVM_CLIENTPROG);
-#define CSQC_END prog=csqc_tmpprog;
-
-static prvm_prog_t *csqc_tmpprog;
+#define CSQC_BEGIN
+#define CSQC_END
void CL_VM_PreventInformationLeaks(void)
{
+ prvm_prog_t *prog = CLVM_prog;
if(!cl.csqc_loaded)
return;
CSQC_BEGIN
- VM_ClearTraceGlobals();
+ VM_ClearTraceGlobals(prog);
PRVM_clientglobalfloat(trace_networkentity) = 0;
CSQC_END
}
#undef PRVM_DECLARE_function
};
-void CL_VM_Error (const char *format, ...) DP_FUNC_PRINTF(1);
-void CL_VM_Error (const char *format, ...) //[515]: hope it will be never executed =)
-{
- char errorstring[4096];
- va_list argptr;
-
- va_start (argptr, format);
- dpvsnprintf (errorstring, sizeof(errorstring), format, argptr);
- va_end (argptr);
-// Con_Printf( "CL_VM_Error: %s\n", errorstring );
-
- PRVM_Crash();
- cl.csqc_loaded = false;
-
- Cvar_SetValueQuick(&csqc_progcrc, -1);
- Cvar_SetValueQuick(&csqc_progsize, -1);
-
-// Host_AbortCurrentFrame(); //[515]: hmmm... if server says it needs csqc then client MUST disconnect
- Host_Error("CL_VM_Error: %s", errorstring);
-}
void CL_VM_UpdateDmgGlobals (int dmg_take, int dmg_save, vec3_t dmg_origin)
{
+ prvm_prog_t *prog = CLVM_prog;
if(cl.csqc_loaded)
{
CSQC_BEGIN
void CSQC_UpdateNetworkTimes(double newtime, double oldtime)
{
+ prvm_prog_t *prog = CLVM_prog;
if(!cl.csqc_loaded)
return;
CSQC_BEGIN
}
//[515]: set globals before calling R_UpdateView, WEIRD CRAP
-void CSQC_R_RecalcView (void);
static void CSQC_SetGlobals (void)
{
+ prvm_prog_t *prog = CLVM_prog;
CSQC_BEGIN
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobalfloat(frametime) = max(0, cl.time - cl.oldtime);
void CSQC_Predraw (prvm_edict_t *ed)
{
+ prvm_prog_t *prog = CLVM_prog;
int b;
if(!PRVM_clientedictfunction(ed, predraw))
return;
b = PRVM_clientglobaledict(self);
PRVM_clientglobaledict(self) = PRVM_EDICT_TO_PROG(ed);
- PRVM_ExecuteProgram(PRVM_clientedictfunction(ed, predraw), "CSQC_Predraw: NULL function\n");
+ prog->ExecuteProgram(prog, PRVM_clientedictfunction(ed, predraw), "CSQC_Predraw: NULL function\n");
PRVM_clientglobaledict(self) = b;
}
void CSQC_Think (prvm_edict_t *ed)
{
+ prvm_prog_t *prog = CLVM_prog;
int b;
if(PRVM_clientedictfunction(ed, think))
if(PRVM_clientedictfloat(ed, nextthink) && PRVM_clientedictfloat(ed, nextthink) <= PRVM_clientglobalfloat(time))
PRVM_clientedictfloat(ed, nextthink) = 0;
b = PRVM_clientglobaledict(self);
PRVM_clientglobaledict(self) = PRVM_EDICT_TO_PROG(ed);
- PRVM_ExecuteProgram(PRVM_clientedictfunction(ed, think), "CSQC_Think: NULL function\n");
+ prog->ExecuteProgram(prog, PRVM_clientedictfunction(ed, think), "CSQC_Think: NULL function\n");
PRVM_clientglobaledict(self) = b;
}
}
extern cvar_t r_equalize_entities_fullbright;
qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum)
{
+ prvm_prog_t *prog = CLVM_prog;
int renderflags;
int c;
float scale;
entrender->entitynumber = edictnum + MAX_EDICTS;
//entrender->shadertime = 0; // shadertime was set by spawn()
entrender->flags = 0;
+ entrender->effects = 0;
entrender->alpha = 1;
entrender->scale = 1;
VectorSet(entrender->colormod, 1, 1, 1);
VectorSet(entrender->glowmod, 1, 1, 1);
// LordHavoc: use the CL_GetTagMatrix function on self to ensure consistent behavior (duplicate code would be bad)
- CL_GetTagMatrix(&entrender->matrix, ed, 0);
+ CL_GetTagMatrix(prog, &entrender->matrix, ed, 0);
// set up the animation data
- VM_GenerateFrameGroupBlend(ed->priv.server->framegroupblend, ed);
+ VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed);
VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(ed, model, ed->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, ed, model, ed->priv.server->frameblend);
if (PRVM_clientedictfloat(ed, shadertime)) // hack for csprogs.dat files that do not set shadertime, leaves the value at entity spawn time
entrender->shadertime = PRVM_clientedictfloat(ed, shadertime);
if (renderflags & RF_USETRANSPARENTOFFSET)
entrender->transparent_offset = PRVM_clientglobalfloat(transparent_offset);
+ // model light
+ if (renderflags & RF_MODELLIGHT)
+ {
+ if(PRVM_clientedictvector(ed, modellight_ambient)) VectorCopy(PRVM_clientedictvector(ed, modellight_ambient), entrender->modellight_ambient);
+ if(PRVM_clientedictvector(ed, modellight_diffuse)) VectorCopy(PRVM_clientedictvector(ed, modellight_diffuse), entrender->modellight_diffuse);
+ if(PRVM_clientedictvector(ed, modellight_dir)) VectorCopy(PRVM_clientedictvector(ed, modellight_dir), entrender->modellight_lightdir);
+ entrender->flags |= RENDER_CUSTOMIZEDMODELLIGHT;
+ }
+
if(renderflags)
{
- if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL | RENDER_NODEPTHTEST;
- if(renderflags & RF_EXTERNALMODEL)entrender->flags |= RENDER_EXTERIORMODEL;
- if(renderflags & RF_NOCULL) entrender->flags |= RENDER_NOCULL;
- if(renderflags & RF_DEPTHHACK) entrender->flags |= RENDER_NODEPTHTEST;
- if(renderflags & RF_ADDITIVE) entrender->flags |= RENDER_ADDITIVE;
+ if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL | RENDER_NODEPTHTEST;
+ if(renderflags & RF_EXTERNALMODEL) entrender->flags |= RENDER_EXTERIORMODEL;
+ if(renderflags & RF_WORLDOBJECT) entrender->flags |= RENDER_WORLDOBJECT;
+ if(renderflags & RF_DEPTHHACK) entrender->flags |= RENDER_NODEPTHTEST;
+ if(renderflags & RF_ADDITIVE) entrender->flags |= RENDER_ADDITIVE;
}
c = (int)PRVM_clientedictfloat(ed, colormap);
return true;
}
-qboolean CL_VM_InputEvent (qboolean down, int key, int ascii)
+// 0 = keydown, key, character (EXT_CSQC)
+// 1 = keyup, key, character (EXT_CSQC)
+// 2 = mousemove relative, x, y (EXT_CSQC)
+// 3 = mousemove absolute, x, y (DP_CSQC)
+qboolean CL_VM_InputEvent (int eventtype, int x, int y)
{
+ prvm_prog_t *prog = CLVM_prog;
qboolean r;
if(!cl.csqc_loaded)
{
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
- PRVM_G_FLOAT(OFS_PARM0) = !down; // 0 is down, 1 is up
- PRVM_G_FLOAT(OFS_PARM1) = key;
- PRVM_G_FLOAT(OFS_PARM2) = ascii;
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_InputEvent), "QC function CSQC_InputEvent is missing");
+ PRVM_G_FLOAT(OFS_PARM0) = eventtype;
+ PRVM_G_FLOAT(OFS_PARM1) = x; // key or x
+ PRVM_G_FLOAT(OFS_PARM2) = y; // ascii or y
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_InputEvent), "QC function CSQC_InputEvent is missing");
r = CSQC_RETURNVAL != 0;
}
CSQC_END
return r;
}
+extern r_refdef_view_t csqc_original_r_refdef_view;
+extern r_refdef_view_t csqc_main_r_refdef_view;
qboolean CL_VM_UpdateView (void)
{
+ prvm_prog_t *prog = CLVM_prog;
vec3_t emptyvector;
emptyvector[0] = 0;
emptyvector[1] = 0;
return false;
R_TimeReport("pre-UpdateView");
CSQC_BEGIN
+ r_refdef.view.ismain = true;
+ csqc_original_r_refdef_view = r_refdef.view;
+ csqc_main_r_refdef_view = r_refdef.view;
//VectorCopy(cl.viewangles, oldangles);
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
// pass in width and height as parameters (EXT_CSQC_1)
PRVM_G_FLOAT(OFS_PARM0) = vid.width;
PRVM_G_FLOAT(OFS_PARM1) = vid.height;
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_UpdateView), "QC function CSQC_UpdateView is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_UpdateView), "QC function CSQC_UpdateView is missing");
//VectorCopy(oldangles, cl.viewangles);
// Dresk : Reset Dmg Globals Here
CL_VM_UpdateDmgGlobals(0, 0, emptyvector);
+ r_refdef.view = csqc_main_r_refdef_view;
+ R_RenderView_UpdateViewVectors(); // we have to do this, as we undid the scene render doing this for us
CSQC_END
+
R_TimeReport("UpdateView");
return true;
}
-extern sizebuf_t vm_tempstringsbuf;
qboolean CL_VM_ConsoleCommand (const char *cmd)
{
+ prvm_prog_t *prog = CLVM_prog;
int restorevm_tempstringsbuf_cursize;
qboolean r = false;
if(!cl.csqc_loaded)
{
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
- PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(cmd);
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_ConsoleCommand), "QC function CSQC_ConsoleCommand is missing");
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, cmd);
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_ConsoleCommand), "QC function CSQC_ConsoleCommand is missing");
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
r = CSQC_RETURNVAL != 0;
}
CSQC_END
qboolean CL_VM_Parse_TempEntity (void)
{
+ prvm_prog_t *prog = CLVM_prog;
int t;
qboolean r = false;
if(!cl.csqc_loaded)
CSQC_BEGIN
if(PRVM_clientfunction(CSQC_Parse_TempEntity))
{
- t = msg_readcount;
+ t = cl_message.readcount;
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_TempEntity), "QC function CSQC_Parse_TempEntity is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Parse_TempEntity), "QC function CSQC_Parse_TempEntity is missing");
r = CSQC_RETURNVAL != 0;
if(!r)
{
- msg_readcount = t;
- msg_badread = false;
+ cl_message.readcount = t;
+ cl_message.badread = false;
}
}
CSQC_END
void CL_VM_Parse_StuffCmd (const char *msg)
{
+ prvm_prog_t *prog = CLVM_prog;
int restorevm_tempstringsbuf_cursize;
if(msg[0] == 'c')
if(msg[1] == 's')
int sizeflags = csqc_progcrc.flags;
csqc_progcrc.flags &= ~CVAR_READONLY;
csqc_progsize.flags &= ~CVAR_READONLY;
- Cmd_ExecuteString (msg, src_command);
+ Cmd_ExecuteString (msg, src_command, true);
csqc_progcrc.flags = crcflags;
csqc_progsize.flags = sizeflags;
return;
l = sizeof(buf) - 1;
strlcpy(buf, p, l + 1); // strlcpy needs a + 1 as it includes the newline!
- Cmd_ExecuteString(buf, src_command);
+ Cmd_ExecuteString(buf, src_command, true);
p += l;
if(*p == '\n')
else
break; // end of string or overflow
}
- Cmd_ExecuteString("curl --clear_autodownload", src_command); // don't inhibit CSQC loading
+ Cmd_ExecuteString("curl --clear_autodownload", src_command, true); // don't inhibit CSQC loading
return;
}
{
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
- PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg);
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_StuffCmd), "QC function CSQC_Parse_StuffCmd is missing");
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg);
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Parse_StuffCmd), "QC function CSQC_Parse_StuffCmd is missing");
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
}
else
Cbuf_AddText(msg);
static void CL_VM_Parse_Print (const char *msg)
{
+ 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 = vm_tempstringsbuf.cursize;
- PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg);
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_Print), "QC function CSQC_Parse_Print is missing");
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg);
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Parse_Print), "QC function CSQC_Parse_Print is missing");
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
}
void CSQC_AddPrintText (const char *msg)
{
+ prvm_prog_t *prog = CLVM_prog;
size_t i;
if(!cl.csqc_loaded)
{
void CL_VM_Parse_CenterPrint (const char *msg)
{
+ prvm_prog_t *prog = CLVM_prog;
int restorevm_tempstringsbuf_cursize;
if(!cl.csqc_loaded)
{
{
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
- PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(msg);
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Parse_CenterPrint), "QC function CSQC_Parse_CenterPrint is missing");
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg);
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Parse_CenterPrint), "QC function CSQC_Parse_CenterPrint is missing");
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
}
else
SCR_CenterPrint(msg);
void CL_VM_UpdateIntermissionState (int intermission)
{
+ prvm_prog_t *prog = CLVM_prog;
if(cl.csqc_loaded)
{
CSQC_BEGIN
}
void CL_VM_UpdateShowingScoresState (int showingscores)
{
+ prvm_prog_t *prog = CLVM_prog;
if(cl.csqc_loaded)
{
CSQC_BEGIN
CSQC_END
}
}
-qboolean CL_VM_Event_Sound(int sound_num, float volume, int channel, float attenuation, int ent, vec3_t pos)
+qboolean CL_VM_Event_Sound(int sound_num, float volume, int channel, float attenuation, int ent, vec3_t pos, int flags, float speed)
{
+ prvm_prog_t *prog = CLVM_prog;
qboolean r = false;
if(cl.csqc_loaded)
{
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
PRVM_G_FLOAT(OFS_PARM0) = ent;
PRVM_G_FLOAT(OFS_PARM1) = CHAN_ENGINE2USER(channel);
- PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(cl.sound_name[sound_num] );
+ PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(prog, cl.sound_name[sound_num] );
PRVM_G_FLOAT(OFS_PARM3) = volume;
PRVM_G_FLOAT(OFS_PARM4) = attenuation;
VectorCopy(pos, PRVM_G_VECTOR(OFS_PARM5) );
- PRVM_G_FLOAT(OFS_PARM6) = 0; // pitch shift not supported yet
- PRVM_G_FLOAT(OFS_PARM7) = 0; // flags - none can come in at this point yet
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Event_Sound), "QC function CSQC_Event_Sound is missing");
+ PRVM_G_FLOAT(OFS_PARM6) = speed * 100.0f;
+ PRVM_G_FLOAT(OFS_PARM7) = flags; // flags
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Event_Sound), "QC function CSQC_Event_Sound is missing");
r = CSQC_RETURNVAL != 0;
}
CSQC_END
return r;
}
-void CL_VM_UpdateCoopDeathmatchGlobals (int gametype)
+static void CL_VM_UpdateCoopDeathmatchGlobals (int gametype)
{
+ prvm_prog_t *prog = CLVM_prog;
// Avoid global names for clean(er) coding
int localcoop;
int localdeathmatch;
CSQC_END
}
}
-float CL_VM_Event (float event) //[515]: needed ? I'd say "YES", but don't know for what :D
+#if 0
+static float CL_VM_Event (float event) //[515]: needed ? I'd say "YES", but don't know for what :D
{
+ prvm_prog_t *prog = CLVM_prog;
float r = 0;
if(!cl.csqc_loaded)
return 0;
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
PRVM_G_FLOAT(OFS_PARM0) = event;
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Event), "QC function CSQC_Event is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Event), "QC function CSQC_Event is missing");
r = CSQC_RETURNVAL;
}
CSQC_END
return r;
}
+#endif
void CSQC_ReadEntities (void)
{
+ prvm_prog_t *prog = CLVM_prog;
unsigned short entnum, oldself, realentnum;
if(!cl.csqc_loaded)
{
oldself = PRVM_clientglobaledict(self);
while(1)
{
- entnum = MSG_ReadShort();
- if(!entnum || msg_badread)
+ entnum = MSG_ReadShort(&cl_message);
+ if(!entnum || cl_message.badread)
break;
realentnum = entnum & 0x7FFF;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[realentnum];
{
if(PRVM_clientglobaledict(self))
{
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Remove), "QC function CSQC_Ent_Remove is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Ent_Remove), "QC function CSQC_Ent_Remove is missing");
cl.csqc_server2csqcentitynumber[realentnum] = 0;
}
else
if(!PRVM_clientfunction(CSQC_Ent_Spawn))
{
prvm_edict_t *ed;
- ed = PRVM_ED_Alloc();
+ ed = PRVM_ED_Alloc(prog);
PRVM_clientedictfloat(ed, entnum) = realentnum;
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT_TO_PROG(ed);
}
PRVM_G_FLOAT(OFS_PARM0) = (float) realentnum;
// make sure no one gets wrong ideas
PRVM_clientglobaledict(self) = 0;
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Spawn), "QC function CSQC_Ent_Spawn is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Ent_Spawn), "QC function CSQC_Ent_Spawn is missing");
PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[realentnum] = PRVM_EDICT( PRVM_G_INT( OFS_RETURN ) );
}
PRVM_G_FLOAT(OFS_PARM0) = 1;
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Update), "QC function CSQC_Ent_Update is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Ent_Update), "QC function CSQC_Ent_Update is missing");
}
else {
PRVM_G_FLOAT(OFS_PARM0) = 0;
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Ent_Update), "QC function CSQC_Ent_Update is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Ent_Update), "QC function CSQC_Ent_Update is missing");
}
}
}
CSQC_END
}
-void CL_VM_CB_BeginIncreaseEdicts(void)
+static void CLVM_begin_increase_edicts(prvm_prog_t *prog)
{
// links don't survive the transition, so unlink everything
World_UnlinkAll(&cl.world);
}
-void CL_VM_CB_EndIncreaseEdicts(void)
+static void CLVM_end_increase_edicts(prvm_prog_t *prog)
{
int i;
prvm_edict_t *ent;
CL_LinkEdict(ent);
}
-void CL_VM_CB_InitEdict(prvm_edict_t *e)
+static void CLVM_init_edict(prvm_prog_t *prog, prvm_edict_t *e)
{
int edictnum = PRVM_NUM_FOR_EDICT(e);
entity_render_t *entrender;
entrender->shadertime = cl.time;
}
-extern void R_DecalSystem_Reset(decalsystem_t *decalsystem);
-
-void CL_VM_CB_FreeEdict(prvm_edict_t *ed)
+static void CLVM_free_edict(prvm_prog_t *prog, prvm_edict_t *ed)
{
entity_render_t *entrender = cl.csqcrenderentities + PRVM_NUM_FOR_EDICT(ed);
R_DecalSystem_Reset(&entrender->decalsystem);
memset(entrender, 0, sizeof(*entrender));
World_UnlinkEdict(ed);
memset(ed->fields.vp, 0, prog->entityfields * 4);
- VM_RemoveEdictSkeleton(ed);
+ VM_RemoveEdictSkeleton(prog, ed);
World_Physics_RemoveFromEntity(&cl.world, ed);
World_Physics_RemoveJointFromEntity(&cl.world, ed);
}
-void CL_VM_CB_CountEdicts(void)
+static void CLVM_count_edicts(prvm_prog_t *prog)
{
int i;
prvm_edict_t *ent;
Con_Printf("touch :%3i\n", solid);
}
-qboolean CL_VM_CB_LoadEdict(prvm_edict_t *ent)
+static qboolean CLVM_load_edict(prvm_prog_t *prog, prvm_edict_t *ent)
{
return true;
}
-void Cmd_ClearCsqcFuncs (void);
-
// returns true if the packet is valid, false if end of file is reached
// used for dumping the CSQC download into demo files
qboolean MakeDownloadPacket(const char *filename, unsigned char *data, size_t len, int crc, int cnt, sizebuf_t *buf, int protocol)
{
int packetsize = buf->maxsize - 7; // byte short long
int npackets = (len + packetsize - 1) / (packetsize);
+ char vabuf[1024];
if(protocol == PROTOCOL_QUAKEWORLD)
return false; // CSQC can't run in QW anyway
if(cnt == 0)
{
MSG_WriteByte(buf, svc_stufftext);
- MSG_WriteString(buf, va("\ncl_downloadbegin %lu %s\n", (unsigned long)len, filename));
+ MSG_WriteString(buf, va(vabuf, sizeof(vabuf), "\ncl_downloadbegin %lu %s\n", (unsigned long)len, filename));
return true;
}
else if(cnt >= 1 && cnt <= npackets)
else if(cnt == npackets + 1)
{
MSG_WriteByte(buf, svc_stufftext);
- MSG_WriteString(buf, va("\ncl_downloadfinished %lu %d\n", (unsigned long)len, crc));
+ MSG_WriteString(buf, va(vabuf, sizeof(vabuf), "\ncl_downloadfinished %lu %d\n", (unsigned long)len, crc));
return true;
}
return false;
}
+extern cvar_t csqc_usedemoprogs;
void CL_VM_Init (void)
{
- const char* csprogsfn;
- unsigned char *csprogsdata;
- fs_offset_t csprogsdatasize;
+ prvm_prog_t *prog = CLVM_prog;
+ const char* csprogsfn = NULL;
+ unsigned char *csprogsdata = NULL;
+ fs_offset_t csprogsdatasize = 0;
int csprogsdatacrc, requiredcrc;
int requiredsize;
+ char vabuf[1024];
// reset csqc_progcrc after reading it, so that changing servers doesn't
// expect csqc on the next server
// see if the requested csprogs.dat file matches the requested crc
csprogsdatacrc = -1;
- csprogsfn = va("dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc);
- csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize);
+ if (!cls.demoplayback || csqc_usedemoprogs.integer)
+ {
+ csprogsfn = va(vabuf, sizeof(vabuf), "dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc);
+ csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize);
+ }
if (!csprogsdata)
{
csprogsfn = csqc_progname.string;
return;
}
- PRVM_Begin;
- PRVM_InitProg(PRVM_CLIENTPROG);
+ PRVM_Prog_Init(prog);
// allocate the mempools
prog->progs_mempool = Mem_AllocPool(csqc_progname.string, 0, NULL);
prog->edictprivate_size = 0; // no private struct used
- prog->name = CL_NAME;
+ prog->name = "client";
prog->num_edicts = 1;
prog->max_edicts = 512;
prog->limit_edicts = CL_MAX_EDICTS;
prog->extensionstring = vm_sv_extensions;
prog->builtins = vm_cl_builtins;
prog->numbuiltins = vm_cl_numbuiltins;
- prog->begin_increase_edicts = CL_VM_CB_BeginIncreaseEdicts;
- prog->end_increase_edicts = CL_VM_CB_EndIncreaseEdicts;
- prog->init_edict = CL_VM_CB_InitEdict;
- prog->free_edict = CL_VM_CB_FreeEdict;
- prog->count_edicts = CL_VM_CB_CountEdicts;
- prog->load_edict = CL_VM_CB_LoadEdict;
- prog->init_cmd = VM_CL_Cmd_Init;
- prog->reset_cmd = VM_CL_Cmd_Reset;
- prog->error_cmd = CL_VM_Error;
- prog->ExecuteProgram = CLVM_ExecuteProgram;
-
- PRVM_LoadProgs(csprogsfn, cl_numrequiredfunc, cl_required_func, CL_REQFIELDS, cl_reqfields, CL_REQGLOBALS, cl_reqglobals);
+
+ // all callbacks must be defined (pointers are not checked before calling)
+ prog->begin_increase_edicts = CLVM_begin_increase_edicts;
+ prog->end_increase_edicts = CLVM_end_increase_edicts;
+ prog->init_edict = CLVM_init_edict;
+ prog->free_edict = CLVM_free_edict;
+ prog->count_edicts = CLVM_count_edicts;
+ prog->load_edict = CLVM_load_edict;
+ prog->init_cmd = CLVM_init_cmd;
+ prog->reset_cmd = CLVM_reset_cmd;
+ prog->error_cmd = Host_Error;
+ prog->ExecuteProgram = CLVM_ExecuteProgram;
+
+ PRVM_Prog_Load(prog, csprogsfn, cl_numrequiredfunc, cl_required_func, CL_REQFIELDS, cl_reqfields, CL_REQGLOBALS, cl_reqglobals);
if (!prog->loaded)
{
- CL_VM_Error("CSQC %s ^2failed to load\n", csprogsfn);
+ Host_Error("CSQC %s ^2failed to load\n", csprogsfn);
if(!sv.active)
CL_Disconnect();
Mem_Free(csprogsdata);
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = 0;
- PRVM_clientglobalstring(mapname) = PRVM_SetEngineString(cl.worldname);
+ PRVM_clientglobalstring(mapname) = PRVM_SetEngineString(prog, cl.worldname);
PRVM_clientglobalfloat(player_localentnum) = cl.playerentity;
// set map description (use world entity 0)
- PRVM_clientedictstring(prog->edicts, message) = PRVM_SetEngineString(cl.worldmessage);
+ PRVM_clientedictstring(prog->edicts, message) = PRVM_SetEngineString(prog, cl.worldmessage);
VectorCopy(cl.world.mins, PRVM_clientedictvector(prog->edicts, mins));
VectorCopy(cl.world.maxs, PRVM_clientedictvector(prog->edicts, maxs));
// call the prog init
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Init), "QC function CSQC_Init is missing");
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Init), "QC function CSQC_Init is missing");
- PRVM_End;
cl.csqc_loaded = true;
cl.csqc_vidvars.drawcrosshair = false;
void CL_VM_ShutDown (void)
{
+ prvm_prog_t *prog = CLVM_prog;
Cmd_ClearCsqcFuncs();
//Cvar_SetValueQuick(&csqc_progcrc, -1);
//Cvar_SetValueQuick(&csqc_progsize, -1);
PRVM_clientglobalfloat(time) = cl.time;
PRVM_clientglobaledict(self) = 0;
if (PRVM_clientfunction(CSQC_Shutdown))
- PRVM_ExecuteProgram(PRVM_clientfunction(CSQC_Shutdown), "QC function CSQC_Shutdown is missing");
- PRVM_ResetProg();
+ prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Shutdown), "QC function CSQC_Shutdown is missing");
+ PRVM_Prog_Reset(prog);
CSQC_END
Con_DPrint("CSQC ^1unloaded\n");
cl.csqc_loaded = false;
qboolean CL_VM_GetEntitySoundOrigin(int entnum, vec3_t out)
{
+ prvm_prog_t *prog = CLVM_prog;
prvm_edict_t *ed;
dp_model_t *mod;
matrix4x4_t matrix;
{
mod = CL_GetModelFromEdict(ed);
VectorCopy(PRVM_clientedictvector(ed, origin), out);
- if(CL_GetTagMatrix (&matrix, ed, 0) == 0)
+ if(CL_GetTagMatrix(prog, &matrix, ed, 0) == 0)
Matrix4x4_OriginFromMatrix(&matrix, out);
if (mod && mod->soundfromcenter)
VectorMAMAM(1.0f, out, 0.5f, mod->normalmins, 0.5f, mod->normalmaxs, out);
qboolean CL_VM_TransformView(int entnum, matrix4x4_t *viewmatrix, mplane_t *clipplane, vec3_t visorigin)
{
+ prvm_prog_t *prog = CLVM_prog;
qboolean ret = false;
prvm_edict_t *ed;
vec3_t forward, left, up, origin, ang;
VectorScale(left, -1, PRVM_clientglobalvector(v_right));
VectorCopy(up, PRVM_clientglobalvector(v_up));
VectorCopy(origin, PRVM_clientglobalvector(trace_endpos));
- PRVM_ExecuteProgram(PRVM_clientedictfunction(ed, camera_transform), "QC function e.camera_transform is missing");
+ prog->ExecuteProgram(prog, PRVM_clientedictfunction(ed, camera_transform), "QC function e.camera_transform is missing");
VectorCopy(PRVM_G_VECTOR(OFS_RETURN), origin);
VectorCopy(PRVM_clientglobalvector(v_forward), forward);
VectorScale(PRVM_clientglobalvector(v_right), -1, left);
#ifndef CSPROGS_H
#define CSPROGS_H
-#define CL_NAME "client"
-
// LordHavoc: changed to match MAX_EDICTS
#define CL_MAX_EDICTS MAX_EDICTS
#define VF_PERSPECTIVE 200 //(float)
#define VF_CLEARSCREEN 201 //(float)
+#define VF_FOG_DENSITY 202 //(float)
+#define VF_FOG_COLOR 203 //(vector)
+#define VF_FOG_COLOR_R 204 //(float)
+#define VF_FOG_COLOR_G 205 //(float)
+#define VF_FOG_COLOR_B 206 //(float)
+#define VF_FOG_ALPHA 207 //(float)
+#define VF_FOG_START 208 //(float)
+#define VF_FOG_END 209 //(float)
+#define VF_FOG_HEIGHT 210 //(float)
+#define VF_FOG_FADEDEPTH 211 //(float)
+
+#define VF_MAINVIEW 212 //(float)
+
#define RF_VIEWMODEL 1 // The entity is never drawn in mirrors. In engines with realtime lighting, it casts no shadows.
#define RF_EXTERNALMODEL 2 // The entity is appears in mirrors but not in the normal view. It does still cast shadows in engines with realtime lighting.
#define RF_DEPTHHACK 4 // The entity appears closer to the view than normal, either by scaling it wierdly or by just using a depthrange. This will usually be found in conjunction with RF_VIEWMODEL
#define RF_USEAXIS 16 // When set, the entity will use the v_forward, v_right and v_up globals instead of it's angles field for orientation. Angles will be ignored compleatly.
// Note that to use this properly, you'll NEED to use the predraw function to set the globals.
//#define RF_DOUBLESIDED 32
-#define RF_USETRANSPARENTOFFSET 64 // Allows QC to customize origin used for transparent sorting via transparent_origin global, helps to fix transparent sorting bugs on a very large entities
-#define RF_NOCULL 128 // do not cull this entity using r_cullentities, for large outdoor entities (asteroids on the sky. etc)
+#define RF_USETRANSPARENTOFFSET 64 // Allows QC to customize origin used for transparent sorting via transparent_origin global, helps to fix transparent sorting bugs on a very large entities
+#define RF_WORLDOBJECT 128 // for large outdoor entities that should not be culled
+#define RF_MODELLIGHT 4096 // CSQC-set model light
#define RF_FULLBRIGHT 256
#define RF_NOSHADOW 512
qboolean CL_VM_TransformView(int entnum, matrix4x4_t *viewmatrix, mplane_t *clipplane, vec3_t visorigin);
+void CL_VM_Init(void);
+void CL_VM_ShutDown(void);
+void CL_VM_UpdateIntermissionState(int intermission);
+void CL_VM_UpdateShowingScoresState(int showingscores);
+qboolean CL_VM_InputEvent(int eventtype, int x, int y);
+qboolean CL_VM_ConsoleCommand(const char *cmd);
+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);
+qboolean CL_VM_Parse_TempEntity(void);
+void CL_VM_Parse_StuffCmd(const char *msg);
+void CL_VM_Parse_CenterPrint(const char *msg);
+int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent);
+int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex);
+void CL_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix);
+/* VMs exposing the polygon calls must call this on Init/Reset */
+void VM_Polygons_Reset(prvm_prog_t *prog);
+void QW_CL_StartUpload(unsigned char *data, int size);
+
+void CSQC_UpdateNetworkTimes(double newtime, double oldtime);
+void CSQC_AddPrintText(const char *msg);
+void CSQC_ReadEntities(void);
+void CSQC_RelinkAllEntities(int drawmask);
+void CSQC_RelinkCSQCEntities(void);
+void CSQC_Predraw(prvm_edict_t *ed);
+void CSQC_Think(prvm_edict_t *ed);
+qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum);//csprogs.c
+void CSQC_R_RecalcView(void);
+
+dp_model_t *CL_GetModelByIndex(int modelindex);
+
#endif
// maps [4..8[ to 4
}
-float Squared3xCurveArea(const float *a, const float *control, const float *b, int components)
+static float Squared3xCurveArea(const float *a, const float *control, const float *b, int components)
{
#if 0
// mimicing the old behaviour with the new code...
return var;
}
-cvar_t *Cvar_FindVarLink (const char *var_name, cvar_t **parent, cvar_t ***link, cvar_t **prev_alpha)
+static cvar_t *Cvar_FindVarLink (const char *var_name, cvar_t **parent, cvar_t ***link, cvar_t **prev_alpha)
{
int hashindex;
cvar_t *var;
static void Cvar_UpdateAutoCvar(cvar_t *var)
{
int i;
- if(!prog)
- Host_Error("Cvar_UpdateAutoCvar: no prog set");
- i = PRVM_GetProgNr();
- if(var->globaldefindex_progid[i] == prog->id)
+ int j;
+ const char *s;
+ vec3_t v;
+ prvm_prog_t *prog;
+ for (i = 0;i < PRVM_PROG_MAX;i++)
{
- // MUST BE SYNCED WITH prvm_edict.c PRVM_LoadProgs
- int j;
- const char *s;
- vec3_t v;
- switch(prog->globaldefs[var->globaldefindex[i]].type & ~DEF_SAVEGLOBAL)
+ prog = &prvm_prog_list[i];
+ if (prog->loaded && var->globaldefindex_progid[i] == prog->id)
{
+ // MUST BE SYNCED WITH prvm_edict.c PRVM_LoadProgs
+ switch(prog->globaldefs[var->globaldefindex[i]].type & ~DEF_SAVEGLOBAL)
+ {
case ev_float:
PRVM_GLOBALFIELDFLOAT(prog->globaldefs[var->globaldefindex[i]].ofs) = var->value;
break;
VectorCopy(v, PRVM_GLOBALFIELDVECTOR(prog->globaldefs[var->globaldefindex[i]].ofs));
break;
case ev_string:
- PRVM_ChangeEngineString(var->globaldefindex_stringno[i], var->string);
+ PRVM_ChangeEngineString(prog, var->globaldefindex_stringno[i], var->string);
PRVM_GLOBALFIELDSTRING(prog->globaldefs[var->globaldefindex[i]].ofs) = var->globaldefindex_stringno[i];
break;
+ }
}
}
}
Cvar_Set
============
*/
-void Cvar_SetQuick_Internal (cvar_t *var, const char *value)
+extern cvar_t sv_disablenotify;
+static void Cvar_SetQuick_Internal (cvar_t *var, const char *value)
{
qboolean changed;
size_t valuelen;
- prvm_prog_t *tmpprog;
- int i;
+ char vabuf[1024];
changed = strcmp(var->string, value) != 0;
// LordHavoc: don't reallocate when there is no change
memcpy ((char *)var->string, value, valuelen + 1);
var->value = atof (var->string);
var->integer = (int) var->value;
- if ((var->flags & CVAR_NOTIFY) && changed && sv.active)
+ if ((var->flags & CVAR_NOTIFY) && changed && sv.active && !sv_disablenotify.integer)
SV_BroadcastPrintf("\"%s\" changed to \"%s\"\n", var->name, var->string);
#if 0
// TODO: add infostring support to the server?
if (!strcmp(var->name, "_cl_color"))
{
int top = (var->integer >> 4) & 15, bottom = var->integer & 15;
- CL_SetInfo("topcolor", va("%i", top), true, false, false, false);
- CL_SetInfo("bottomcolor", va("%i", bottom), true, false, false, false);
+ CL_SetInfo("topcolor", va(vabuf, sizeof(vabuf), "%i", top), true, false, false, false);
+ CL_SetInfo("bottomcolor", va(vabuf, sizeof(vabuf), "%i", bottom), true, false, false, false);
if (cls.protocol != PROTOCOL_QUAKEWORLD && cls.netcon)
{
MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, va("color %i %i", top, bottom));
+ MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "color %i %i", top, bottom));
}
}
else if (!strcmp(var->name, "_cl_rate"))
- CL_SetInfo("rate", va("%i", var->integer), true, false, false, false);
+ CL_SetInfo("rate", va(vabuf, sizeof(vabuf), "%i", var->integer), true, false, false, false);
else if (!strcmp(var->name, "_cl_playerskin"))
CL_SetInfo("playerskin", var->string, true, false, false, false);
else if (!strcmp(var->name, "_cl_playermodel"))
NetConn_UpdateFavorites();
}
- tmpprog = prog;
- for(i = 0; i < PRVM_MAXPROGS; ++i)
- {
- if(PRVM_ProgLoaded(i))
- {
- PRVM_SetProg(i);
- Cvar_UpdateAutoCvar(var);
- }
- }
- prog = tmpprog;
+ Cvar_UpdateAutoCvar(var);
}
void Cvar_SetQuick (cvar_t *var, const char *value)
// don't save cvars that match their default value
for (var = cvar_vars ; var ; var = var->next)
- if ((var->flags & CVAR_SAVE) && (strcmp(var->string, var->defstring) || !(var->flags & CVAR_DEFAULTSET)))
+ if ((var->flags & CVAR_SAVE) && (strcmp(var->string, var->defstring) || ((var->flags & CVAR_ALLOCATED) && !(var->flags & CVAR_DEFAULTSET))))
{
Cmd_QuoteString(buf1, sizeof(buf1), var->name, "\"\\$", false);
Cmd_QuoteString(buf2, sizeof(buf2), var->string, "\"\\$", false);
-[Project]\r
-FileName=darkplaces-dedicated.dev\r
-Name=DarkPlaces\r
-UnitCount=165\r
-Type=1\r
-Ver=1\r
-ObjFiles=\r
-Includes=\r
-Libs=\r
-PrivateResource=darkplaces-dedicated_private.rc\r
-ResourceIncludes=\r
-MakeIncludes=\r
-Compiler=-Wall -O2 -fno-strict-aliasing -ffast-math -funroll-loops -D_FILE_OFFSET_BITS=64 -D__KERNEL_STRICT_NAMES_@@_\r
-CppCompiler=\r
-Linker=-lwinmm -lws2_32_@@_\r
-IsCpp=0\r
-Icon=darkplaces.ico\r
-ExeOutput=\r
-ObjectOutput=\r
-OverrideOutput=1\r
-OverrideOutputName=darkplaces-dedicated.exe\r
-HostApplication=\r
-Folders="Header Files","Source Files"\r
-CommandLine=\r
-UseCustomMakefile=0\r
-CustomMakefile=\r
-IncludeVersionInfo=1\r
-SupportXPThemes=0\r
-CompilerSet=0\r
-CompilerSettings=0000000000000000000100\r
-\r
-[Unit1]\r
-FileName=dpvsimpledecode.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit2]\r
-FileName=cdaudio.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit3]\r
-FileName=cl_collision.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit4]\r
-FileName=cl_screen.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit5]\r
-FileName=cl_video.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit6]\r
-FileName=client.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit7]\r
-FileName=clprogdefs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit8]\r
-FileName=cmd.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit9]\r
-FileName=collision.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit10]\r
-FileName=common.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit11]\r
-FileName=console.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit12]\r
-FileName=curves.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit13]\r
-FileName=cvar.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit16]\r
-FileName=fs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit17]\r
-FileName=gl_backend.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit18]\r
-FileName=polygon.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit19]\r
-FileName=glquake.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit20]\r
-FileName=image.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit21]\r
-FileName=input.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit22]\r
-FileName=jpeg.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit23]\r
-FileName=keys.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit24]\r
-FileName=lhnet.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit25]\r
-FileName=mathlib.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit26]\r
-FileName=matrixlib.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit27]\r
-FileName=menu.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit28]\r
-FileName=meshqueue.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit29]\r
-FileName=model_alias.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit30]\r
-FileName=model_brush.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit31]\r
-FileName=model_shared.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit32]\r
-FileName=model_sprite.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit33]\r
-FileName=model_zymotic.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit34]\r
-FileName=modelgen.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit35]\r
-FileName=mprogdefs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit36]\r
-FileName=netconn.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit37]\r
-FileName=palette.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit38]\r
-FileName=portals.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit39]\r
-FileName=pr_comp.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit40]\r
-FileName=progdefs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit41]\r
-FileName=progs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit42]\r
-FileName=progsvm.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit43]\r
-FileName=protocol.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit44]\r
-FileName=prvm_execprogram.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit45]\r
-FileName=qtypes.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit46]\r
-FileName=quakedef.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit47]\r
-FileName=r_lerpanim.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit48]\r
-FileName=r_modules.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit49]\r
-FileName=r_shadow.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit50]\r
-FileName=r_textures.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit51]\r
-FileName=render.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit52]\r
-FileName=resource.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit53]\r
-FileName=sbar.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit54]\r
-FileName=screen.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit55]\r
-FileName=server.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit56]\r
-FileName=sound.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit57]\r
-FileName=spritegn.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit58]\r
-FileName=sys.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit59]\r
-FileName=vid.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit60]\r
-FileName=wad.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit62]\r
-FileName=zone.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit63]\r
-FileName=zone.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit64]\r
-FileName=cd_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit65]\r
-FileName=cd_null.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit66]\r
-FileName=cl_collision.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit67]\r
-FileName=cl_demo.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit68]\r
-FileName=cl_input.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit69]\r
-FileName=cl_main.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit70]\r
-FileName=cl_parse.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit71]\r
-FileName=cl_particles.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit72]\r
-FileName=cl_screen.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit73]\r
-FileName=cl_video.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit74]\r
-FileName=cmd.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit75]\r
-FileName=collision.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit76]\r
-FileName=common.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit77]\r
-FileName=console.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit78]\r
-FileName=polygon.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit79]\r
-FileName=curves.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit80]\r
-FileName=cvar.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit81]\r
-FileName=dpvsimpledecode.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit82]\r
-FileName=filematch.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit83]\r
-FileName=fractalnoise.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit84]\r
-FileName=fs.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit85]\r
-FileName=gl_backend.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit86]\r
-FileName=gl_draw.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit87]\r
-FileName=gl_rmain.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit88]\r
-FileName=gl_rsurf.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit89]\r
-FileName=gl_textures.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit91]\r
-FileName=host_cmd.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit92]\r
-FileName=image.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit93]\r
-FileName=jpeg.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit94]\r
-FileName=keys.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit95]\r
-FileName=lhnet.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit96]\r
-FileName=mathlib.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit97]\r
-FileName=matrixlib.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit98]\r
-FileName=menu.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit99]\r
-FileName=meshqueue.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit100]\r
-FileName=model_alias.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit101]\r
-FileName=model_brush.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit102]\r
-FileName=model_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit103]\r
-FileName=model_sprite.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit104]\r
-FileName=netconn.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit105]\r
-FileName=palette.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit106]\r
-FileName=portals.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit107]\r
-FileName=protocol.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit108]\r
-FileName=prvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit109]\r
-FileName=prvm_edict.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit110]\r
-FileName=prvm_exec.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit111]\r
-FileName=builddate.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit113]\r
-FileName=r_lerpanim.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit114]\r
-FileName=r_lightning.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit115]\r
-FileName=r_modules.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit116]\r
-FileName=r_shadow.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit118]\r
-FileName=r_sprites.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit119]\r
-FileName=sbar.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit120]\r
-FileName=snd_null.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit121]\r
-FileName=sv_main.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit122]\r
-FileName=sv_move.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit123]\r
-FileName=sv_phys.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit124]\r
-FileName=sv_user.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit125]\r
-FileName=sys_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit126]\r
-FileName=sys_linux.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit127]\r
-FileName=vid_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit128]\r
-FileName=vid_null.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit133]\r
-FileName=image_png.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit134]\r
-FileName=lhfont.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit135]\r
-FileName=mdfour.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit136]\r
-FileName=model_dpmodel.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit137]\r
-FileName=model_psk.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit139]\r
-FileName=csprogs.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit140]\r
-FileName=mdfour.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit141]\r
-FileName=image_png.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit143]\r
-FileName=wad.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit145]\r
-FileName=cl_dyntexture.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit148]\r
-FileName=cl_gecko.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit149]\r
-FileName=clvm_cmds.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit150]\r
-FileName=libcurl.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit151]\r
-FileName=libcurl.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit152]\r
-FileName=sv_demo.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit153]\r
-FileName=sv_demo.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit154]\r
-FileName=svbsp.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit155]\r
-FileName=svbsp.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit156]\r
-FileName=timing.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit157]\r
-FileName=hmac.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit112]\r
-FileName=r_explosion.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[VersionInfo]\r
-Major=1\r
-Minor=0\r
-Release=0\r
-Build=0\r
-LanguageID=1033\r
-CharsetID=1252\r
-CompanyName=Forest Hale Digital Services\r
-FileVersion=1.0\r
-FileDescription=DarkPlaces Game Engine\r
-InternalName=darkplaces.exe\r
-LegalCopyright=id Software, Forest Hale, and contributors\r
-LegalTrademarks=\r
-OriginalFilename=darkplaces.exe\r
-ProductName=DarkPlaces\r
-ProductVersion=1.0\r
-AutoIncBuildNr=0\r
-\r
-[Unit90]\r
-FileName=host.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit138]\r
-FileName=clvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit14]\r
-FileName=bspfile.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit15]\r
-FileName=draw.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit61]\r
-FileName=world.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit117]\r
-FileName=r_sky.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit158]\r
-FileName=hmac.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit159]\r
-FileName=cap_avi.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit160]\r
-FileName=cap_avi.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit161]\r
-FileName=cap_ogg.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit162]\r
-FileName=cap_ogg.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit163]\r
-FileName=utf8lib.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit164]\r
-FileName=ft2.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit165]\r
-FileName=bih.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit129]\r
-FileName=svvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit130]\r
-FileName=mvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit131]\r
-FileName=prvm_cmds.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit132]\r
-FileName=csprogs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit144]\r
-FileName=world.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit146]\r
-FileName=cl_dyntexture.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit147]\r
-FileName=cl_gecko.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit142]\r
-FileName=view.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
+[Project]
+FileName=darkplaces-dedicated.dev
+Name=DarkPlaces
+UnitCount=165
+Type=1
+Ver=1
+ObjFiles=
+Includes=
+Libs=
+PrivateResource=darkplaces-dedicated_private.rc
+ResourceIncludes=
+MakeIncludes=
+Compiler=-Wall -O2 -fno-strict-aliasing -ffast-math -funroll-loops -D_FILE_OFFSET_BITS=64 -D__KERNEL_STRICT_NAMES_@@_
+CppCompiler=
+Linker=-lwinmm -lws2_32_@@_
+IsCpp=0
+Icon=darkplaces.ico
+ExeOutput=
+ObjectOutput=
+OverrideOutput=1
+OverrideOutputName=darkplaces-dedicated.exe
+HostApplication=
+Folders="Header Files","Source Files"
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=1
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000000000000000100
+
+[Unit1]
+FileName=dpvsimpledecode.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit2]
+FileName=cdaudio.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=cl_collision.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=cl_screen.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=cl_video.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=client.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit7]
+FileName=clprogdefs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit8]
+FileName=cmd.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit9]
+FileName=collision.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit10]
+FileName=common.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit11]
+FileName=console.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit12]
+FileName=curves.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit13]
+FileName=cvar.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit16]
+FileName=fs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit17]
+FileName=gl_backend.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit18]
+FileName=polygon.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit19]
+FileName=glquake.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit20]
+FileName=image.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit21]
+FileName=input.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit22]
+FileName=jpeg.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit23]
+FileName=keys.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit24]
+FileName=lhnet.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit25]
+FileName=mathlib.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit26]
+FileName=matrixlib.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit27]
+FileName=menu.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit28]
+FileName=meshqueue.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit29]
+FileName=model_alias.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit30]
+FileName=model_brush.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit31]
+FileName=model_shared.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit32]
+FileName=model_sprite.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit33]
+FileName=model_zymotic.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit34]
+FileName=modelgen.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit35]
+FileName=mprogdefs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit36]
+FileName=netconn.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit37]
+FileName=palette.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit38]
+FileName=portals.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit39]
+FileName=pr_comp.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit40]
+FileName=progdefs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit41]
+FileName=progs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit42]
+FileName=progsvm.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit43]
+FileName=protocol.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit44]
+FileName=prvm_execprogram.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit45]
+FileName=qtypes.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit46]
+FileName=quakedef.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit47]
+FileName=r_lerpanim.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit48]
+FileName=r_modules.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit49]
+FileName=r_shadow.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit50]
+FileName=r_textures.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit51]
+FileName=render.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit52]
+FileName=resource.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit53]
+FileName=sbar.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit54]
+FileName=screen.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit55]
+FileName=server.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit56]
+FileName=sound.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit57]
+FileName=spritegn.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit58]
+FileName=sys.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit59]
+FileName=vid.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit60]
+FileName=wad.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit62]
+FileName=zone.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit63]
+FileName=zone.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit64]
+FileName=cd_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit65]
+FileName=cd_null.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit66]
+FileName=cl_collision.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit67]
+FileName=cl_demo.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit68]
+FileName=cl_input.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit69]
+FileName=cl_main.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit70]
+FileName=cl_parse.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit71]
+FileName=cl_particles.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit72]
+FileName=cl_screen.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit73]
+FileName=cl_video.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit74]
+FileName=cmd.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit75]
+FileName=collision.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit76]
+FileName=common.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit77]
+FileName=console.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit78]
+FileName=polygon.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit79]
+FileName=curves.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit80]
+FileName=cvar.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit81]
+FileName=dpvsimpledecode.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit82]
+FileName=filematch.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit83]
+FileName=fractalnoise.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit84]
+FileName=fs.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit85]
+FileName=gl_backend.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit86]
+FileName=gl_draw.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit87]
+FileName=gl_rmain.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit88]
+FileName=gl_rsurf.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit89]
+FileName=gl_textures.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit91]
+FileName=host_cmd.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit92]
+FileName=image.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit93]
+FileName=jpeg.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit94]
+FileName=keys.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit95]
+FileName=lhnet.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit96]
+FileName=mathlib.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit97]
+FileName=matrixlib.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit98]
+FileName=menu.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit99]
+FileName=meshqueue.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit100]
+FileName=model_alias.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit101]
+FileName=model_brush.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit102]
+FileName=model_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit103]
+FileName=model_sprite.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit104]
+FileName=netconn.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit105]
+FileName=palette.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit106]
+FileName=portals.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit107]
+FileName=protocol.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit108]
+FileName=prvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit109]
+FileName=prvm_edict.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit110]
+FileName=prvm_exec.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit111]
+FileName=builddate.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit113]
+FileName=r_lerpanim.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit114]
+FileName=r_lightning.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit115]
+FileName=r_modules.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit116]
+FileName=r_shadow.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit118]
+FileName=r_sprites.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit119]
+FileName=sbar.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit120]
+FileName=snd_null.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit121]
+FileName=sv_main.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit122]
+FileName=sv_move.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit123]
+FileName=sv_phys.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit124]
+FileName=sv_user.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit125]
+FileName=sys_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit126]
+FileName=sys_linux.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit127]
+FileName=vid_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit128]
+FileName=vid_null.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit133]
+FileName=image_png.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit134]
+FileName=lhfont.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit135]
+FileName=mdfour.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit136]
+FileName=model_dpmodel.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit137]
+FileName=model_psk.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit139]
+FileName=csprogs.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit140]
+FileName=mdfour.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit141]
+FileName=image_png.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit143]
+FileName=wad.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit145]
+FileName=cl_dyntexture.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit148]
+FileName=cl_gecko.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit149]
+FileName=clvm_cmds.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit150]
+FileName=libcurl.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit151]
+FileName=libcurl.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit152]
+FileName=sv_demo.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit153]
+FileName=sv_demo.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit154]
+FileName=svbsp.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit155]
+FileName=svbsp.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit156]
+FileName=timing.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit157]
+FileName=hmac.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit112]
+FileName=r_explosion.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=1
+Minor=0
+Release=0
+Build=0
+LanguageID=1033
+CharsetID=1252
+CompanyName=Forest Hale Digital Services
+FileVersion=1.0
+FileDescription=DarkPlaces Game Engine
+InternalName=darkplaces.exe
+LegalCopyright=id Software, Forest Hale, and contributors
+LegalTrademarks=
+OriginalFilename=darkplaces.exe
+ProductName=DarkPlaces
+ProductVersion=1.0
+AutoIncBuildNr=0
+
+[Unit90]
+FileName=host.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit138]
+FileName=clvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit14]
+FileName=bspfile.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit15]
+FileName=draw.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit61]
+FileName=world.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit117]
+FileName=r_sky.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit158]
+FileName=hmac.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit159]
+FileName=cap_avi.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit160]
+FileName=cap_avi.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit161]
+FileName=cap_ogg.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit162]
+FileName=cap_ogg.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit163]
+FileName=utf8lib.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit164]
+FileName=ft2.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit165]
+FileName=bih.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit129]
+FileName=svvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit130]
+FileName=mvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit131]
+FileName=prvm_cmds.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit132]
+FileName=csprogs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit144]
+FileName=world.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit146]
+FileName=cl_dyntexture.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit147]
+FileName=cl_gecko.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit142]
+FileName=view.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
RelativePath=".\cl_dyntexture.c"\r
>\r
</File>\r
- <File\r
- RelativePath=".\cl_gecko.c"\r
- >\r
- </File>\r
<File\r
RelativePath=".\cl_input.c"\r
>\r
RelativePath=".\cl_dyntexture.c"\r
>\r
</File>\r
- <File\r
- RelativePath=".\cl_gecko.c"\r
- >\r
- </File>\r
<File\r
RelativePath=".\cl_input.c"\r
>\r
RelativePath=".\cl_dyntexture.c"\r
>\r
</File>\r
- <File\r
- RelativePath=".\cl_gecko.c"\r
- >\r
- </File>\r
<File\r
RelativePath=".\cl_input.c"\r
>\r
-[Project]\r
-FileName=darkplaces.dev\r
-Name=DarkPlaces\r
-UnitCount=175\r
-Type=0\r
-Ver=1\r
-ObjFiles=\r
-Includes=\r
-Libs=\r
-PrivateResource=darkplaces_private.rc\r
-ResourceIncludes=\r
-MakeIncludes=\r
-Compiler=-Wall -O2 -fno-strict-aliasing -ffast-math -funroll-loops -D_FILE_OFFSET_BITS=64 -D__KERNEL_STRICT_NAMES_@@_\r
-CppCompiler=\r
-Linker=-lwinmm -lws2_32 -luser32 -lgdi32 -ldxguid -ldinput -lcomctl32 -Wl,--large-address-aware_@@_\r
-IsCpp=0\r
-Icon=darkplaces.ico\r
-ExeOutput=\r
-ObjectOutput=\r
-OverrideOutput=1\r
-OverrideOutputName=darkplaces.exe\r
-HostApplication=\r
-Folders="Header Files","Source Files"\r
-CommandLine=\r
-UseCustomMakefile=0\r
-CustomMakefile=\r
-IncludeVersionInfo=1\r
-SupportXPThemes=0\r
-CompilerSet=0\r
-CompilerSettings=0000000000000000000100\r
-\r
-[Unit1]\r
-FileName=dpvsimpledecode.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit2]\r
-FileName=cdaudio.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit3]\r
-FileName=cl_collision.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit4]\r
-FileName=cl_screen.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit5]\r
-FileName=cl_video.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit6]\r
-FileName=client.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit7]\r
-FileName=clprogdefs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit8]\r
-FileName=cmd.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit9]\r
-FileName=collision.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit10]\r
-FileName=common.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit11]\r
-FileName=conproc.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit12]\r
-FileName=console.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit13]\r
-FileName=snd_main.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit14]\r
-FileName=curves.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit15]\r
-FileName=cvar.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit16]\r
-FileName=bspfile.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit17]\r
-FileName=draw.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit18]\r
-FileName=fs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit19]\r
-FileName=gl_backend.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit20]\r
-FileName=polygon.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit21]\r
-FileName=glquake.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit22]\r
-FileName=image.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit23]\r
-FileName=input.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit24]\r
-FileName=jpeg.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit25]\r
-FileName=keys.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit26]\r
-FileName=lhnet.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit27]\r
-FileName=mathlib.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit28]\r
-FileName=matrixlib.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit29]\r
-FileName=menu.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit30]\r
-FileName=meshqueue.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit31]\r
-FileName=model_alias.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit32]\r
-FileName=model_brush.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit33]\r
-FileName=model_shared.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit34]\r
-FileName=model_sprite.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit35]\r
-FileName=model_zymotic.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit36]\r
-FileName=modelgen.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit37]\r
-FileName=mprogdefs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit38]\r
-FileName=netconn.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit39]\r
-FileName=palette.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit40]\r
-FileName=portals.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit41]\r
-FileName=pr_comp.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit42]\r
-FileName=progdefs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit43]\r
-FileName=progs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit44]\r
-FileName=progsvm.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit45]\r
-FileName=protocol.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit46]\r
-FileName=prvm_execprogram.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit47]\r
-FileName=qtypes.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit48]\r
-FileName=quakedef.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit49]\r
-FileName=r_lerpanim.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit50]\r
-FileName=r_modules.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit51]\r
-FileName=r_shadow.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit52]\r
-FileName=r_textures.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit53]\r
-FileName=render.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit54]\r
-FileName=resource.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit55]\r
-FileName=sbar.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit56]\r
-FileName=screen.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit57]\r
-FileName=server.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit58]\r
-FileName=snd_ogg.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit59]\r
-FileName=snd_wav.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit60]\r
-FileName=sound.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit61]\r
-FileName=spritegn.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit62]\r
-FileName=sys.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit63]\r
-FileName=vid.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit64]\r
-FileName=wad.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit65]\r
-FileName=world.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit66]\r
-FileName=zone.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit67]\r
-FileName=zone.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit68]\r
-FileName=cd_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit69]\r
-FileName=cd_win.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit70]\r
-FileName=cl_collision.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit71]\r
-FileName=cl_demo.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit72]\r
-FileName=cl_input.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit73]\r
-FileName=cl_main.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit74]\r
-FileName=cl_parse.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit75]\r
-FileName=cl_particles.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit76]\r
-FileName=cl_screen.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit77]\r
-FileName=cl_video.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit78]\r
-FileName=cmd.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit79]\r
-FileName=collision.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit80]\r
-FileName=common.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit81]\r
-FileName=conproc.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit82]\r
-FileName=console.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit83]\r
-FileName=polygon.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit84]\r
-FileName=curves.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit85]\r
-FileName=cvar.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit86]\r
-FileName=dpvsimpledecode.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit87]\r
-FileName=filematch.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit88]\r
-FileName=fractalnoise.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit89]\r
-FileName=fs.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit90]\r
-FileName=gl_backend.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit91]\r
-FileName=gl_draw.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit92]\r
-FileName=gl_rmain.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit93]\r
-FileName=gl_rsurf.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit94]\r
-FileName=gl_textures.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit95]\r
-FileName=host.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit96]\r
-FileName=host_cmd.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit97]\r
-FileName=image.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit98]\r
-FileName=jpeg.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit99]\r
-FileName=keys.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit100]\r
-FileName=lhnet.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit101]\r
-FileName=mathlib.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit102]\r
-FileName=matrixlib.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit103]\r
-FileName=menu.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit104]\r
-FileName=meshqueue.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit105]\r
-FileName=model_alias.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit106]\r
-FileName=model_brush.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit107]\r
-FileName=model_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit108]\r
-FileName=model_sprite.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit109]\r
-FileName=netconn.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit110]\r
-FileName=palette.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit111]\r
-FileName=portals.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit112]\r
-FileName=protocol.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit113]\r
-FileName=prvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit114]\r
-FileName=prvm_edict.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit115]\r
-FileName=prvm_exec.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit116]\r
-FileName=builddate.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit118]\r
-FileName=r_lerpanim.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit119]\r
-FileName=r_lightning.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit120]\r
-FileName=r_modules.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit121]\r
-FileName=r_shadow.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit123]\r
-FileName=r_sprites.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit124]\r
-FileName=sbar.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit125]\r
-FileName=snd_main.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit126]\r
-FileName=snd_mem.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit127]\r
-FileName=snd_mix.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit128]\r
-FileName=snd_ogg.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit129]\r
-FileName=snd_wav.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit130]\r
-FileName=snd_win.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit131]\r
-FileName=sv_main.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit132]\r
-FileName=sv_move.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit133]\r
-FileName=sv_phys.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit134]\r
-FileName=sv_user.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit135]\r
-FileName=sys_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit136]\r
-FileName=sys_win.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit137]\r
-FileName=vid_shared.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit138]\r
-FileName=vid_wgl.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit139]\r
-FileName=view.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit140]\r
-FileName=wad.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit141]\r
-FileName=world.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit142]\r
-FileName=svvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit143]\r
-FileName=mvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit145]\r
-FileName=csprogs.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit146]\r
-FileName=image_png.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit147]\r
-FileName=lhfont.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit148]\r
-FileName=mdfour.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit149]\r
-FileName=model_dpmodel.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit150]\r
-FileName=model_psk.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit151]\r
-FileName=csprogs.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit152]\r
-FileName=image_png.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit153]\r
-FileName=mdfour.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit154]\r
-FileName=libcurl.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit155]\r
-FileName=libcurl.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit156]\r
-FileName=clvm_cmds.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit157]\r
-FileName=svbsp.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit117]\r
-FileName=r_explosion.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[VersionInfo]\r
-Major=1\r
-Minor=0\r
-Release=0\r
-Build=0\r
-LanguageID=1033\r
-CharsetID=1252\r
-CompanyName=Forest Hale Digital Services\r
-FileVersion=1.0\r
-FileDescription=DarkPlaces Game Engine\r
-InternalName=darkplaces.exe\r
-LegalCopyright=id Software, Forest Hale, and contributors\r
-LegalTrademarks=\r
-OriginalFilename=darkplaces.exe\r
-ProductName=DarkPlaces\r
-ProductVersion=1.0\r
-AutoIncBuildNr=0\r
-\r
-[Unit122]\r
-FileName=r_sky.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit144]\r
-FileName=prvm_cmds.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit158]\r
-FileName=svbsp.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit159]\r
-FileName=sv_demo.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit160]\r
-FileName=sv_demo.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit161]\r
-FileName=snd_modplug.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit162]\r
-FileName=snd_modplug.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit163]\r
-FileName=cl_gecko.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit164]\r
-FileName=cl_gecko.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit165]\r
-FileName=cl_dyntexture.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit166]\r
-FileName=cl_dyntexture.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit167]\r
-FileName=hmac.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit168]\r
-FileName=hmac.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit169]\r
-FileName=cap_avi.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit170]\r
-FileName=cap_avi.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit171]\r
-FileName=cap_ogg.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit172]\r
-FileName=cap_ogg.h\r
-CompileCpp=0\r
-Folder=Header Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit173]\r
-FileName=utf8lib.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit174]\r
-FileName=ft2.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
-[Unit175]\r
-FileName=bih.c\r
-CompileCpp=0\r
-Folder=Source Files\r
-Compile=1\r
-Link=1\r
-Priority=1000\r
-OverrideBuildCmd=0\r
-BuildCmd=\r
-\r
+[Project]
+FileName=darkplaces.dev
+Name=DarkPlaces
+UnitCount=175
+Type=0
+Ver=1
+ObjFiles=
+Includes=
+Libs=
+PrivateResource=darkplaces_private.rc
+ResourceIncludes=
+MakeIncludes=
+Compiler=-Wall -O2 -fno-strict-aliasing -ffast-math -funroll-loops -D_FILE_OFFSET_BITS=64 -D__KERNEL_STRICT_NAMES_@@_
+CppCompiler=
+Linker=-lwinmm -lws2_32 -luser32 -lgdi32 -ldxguid -ldinput -lcomctl32 -Wl,--large-address-aware_@@_
+IsCpp=0
+Icon=darkplaces.ico
+ExeOutput=
+ObjectOutput=
+OverrideOutput=1
+OverrideOutputName=darkplaces.exe
+HostApplication=
+Folders="Header Files","Source Files"
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=1
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000000000000000100
+
+[Unit1]
+FileName=dpvsimpledecode.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit2]
+FileName=cdaudio.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=cl_collision.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=cl_screen.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=cl_video.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=client.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit7]
+FileName=clprogdefs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit8]
+FileName=cmd.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit9]
+FileName=collision.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit10]
+FileName=common.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit11]
+FileName=conproc.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit12]
+FileName=console.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit13]
+FileName=snd_main.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit14]
+FileName=curves.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit15]
+FileName=cvar.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit16]
+FileName=bspfile.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit17]
+FileName=draw.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit18]
+FileName=fs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit19]
+FileName=gl_backend.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit20]
+FileName=polygon.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit21]
+FileName=glquake.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit22]
+FileName=image.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit23]
+FileName=input.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit24]
+FileName=jpeg.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit25]
+FileName=keys.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit26]
+FileName=lhnet.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit27]
+FileName=mathlib.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit28]
+FileName=matrixlib.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit29]
+FileName=menu.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit30]
+FileName=meshqueue.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit31]
+FileName=model_alias.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit32]
+FileName=model_brush.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit33]
+FileName=model_shared.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit34]
+FileName=model_sprite.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit35]
+FileName=model_zymotic.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit36]
+FileName=modelgen.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit37]
+FileName=mprogdefs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit38]
+FileName=netconn.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit39]
+FileName=palette.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit40]
+FileName=portals.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit41]
+FileName=pr_comp.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit42]
+FileName=progdefs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit43]
+FileName=progs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit44]
+FileName=progsvm.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit45]
+FileName=protocol.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit46]
+FileName=prvm_execprogram.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit47]
+FileName=qtypes.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit48]
+FileName=quakedef.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit49]
+FileName=r_lerpanim.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit50]
+FileName=r_modules.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit51]
+FileName=r_shadow.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit52]
+FileName=r_textures.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit53]
+FileName=render.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit54]
+FileName=resource.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit55]
+FileName=sbar.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit56]
+FileName=screen.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit57]
+FileName=server.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit58]
+FileName=snd_ogg.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit59]
+FileName=snd_wav.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit60]
+FileName=sound.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit61]
+FileName=spritegn.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit62]
+FileName=sys.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit63]
+FileName=vid.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit64]
+FileName=wad.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit65]
+FileName=world.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit66]
+FileName=zone.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit67]
+FileName=zone.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit68]
+FileName=cd_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit69]
+FileName=cd_win.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit70]
+FileName=cl_collision.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit71]
+FileName=cl_demo.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit72]
+FileName=cl_input.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit73]
+FileName=cl_main.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit74]
+FileName=cl_parse.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit75]
+FileName=cl_particles.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit76]
+FileName=cl_screen.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit77]
+FileName=cl_video.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit78]
+FileName=cmd.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit79]
+FileName=collision.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit80]
+FileName=common.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit81]
+FileName=conproc.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit82]
+FileName=console.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit83]
+FileName=polygon.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit84]
+FileName=curves.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit85]
+FileName=cvar.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit86]
+FileName=dpvsimpledecode.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit87]
+FileName=filematch.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit88]
+FileName=fractalnoise.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit89]
+FileName=fs.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit90]
+FileName=gl_backend.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit91]
+FileName=gl_draw.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit92]
+FileName=gl_rmain.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit93]
+FileName=gl_rsurf.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit94]
+FileName=gl_textures.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit95]
+FileName=host.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit96]
+FileName=host_cmd.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit97]
+FileName=image.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit98]
+FileName=jpeg.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit99]
+FileName=keys.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit100]
+FileName=lhnet.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit101]
+FileName=mathlib.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit102]
+FileName=matrixlib.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit103]
+FileName=menu.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit104]
+FileName=meshqueue.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit105]
+FileName=model_alias.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit106]
+FileName=model_brush.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit107]
+FileName=model_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit108]
+FileName=model_sprite.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit109]
+FileName=netconn.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit110]
+FileName=palette.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit111]
+FileName=portals.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit112]
+FileName=protocol.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit113]
+FileName=prvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit114]
+FileName=prvm_edict.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit115]
+FileName=prvm_exec.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit116]
+FileName=builddate.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit118]
+FileName=r_lerpanim.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit119]
+FileName=r_lightning.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit120]
+FileName=r_modules.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit121]
+FileName=r_shadow.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit123]
+FileName=r_sprites.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit124]
+FileName=sbar.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit125]
+FileName=snd_main.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit126]
+FileName=snd_mem.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit127]
+FileName=snd_mix.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit128]
+FileName=snd_ogg.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit129]
+FileName=snd_wav.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit130]
+FileName=snd_win.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit131]
+FileName=sv_main.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit132]
+FileName=sv_move.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit133]
+FileName=sv_phys.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit134]
+FileName=sv_user.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit135]
+FileName=sys_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit136]
+FileName=sys_win.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit137]
+FileName=vid_shared.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit138]
+FileName=vid_wgl.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit139]
+FileName=view.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit140]
+FileName=wad.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit141]
+FileName=world.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit142]
+FileName=svvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit143]
+FileName=mvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit145]
+FileName=csprogs.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit146]
+FileName=image_png.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit147]
+FileName=lhfont.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit148]
+FileName=mdfour.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit149]
+FileName=model_dpmodel.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit150]
+FileName=model_psk.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit151]
+FileName=csprogs.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit152]
+FileName=image_png.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit153]
+FileName=mdfour.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit154]
+FileName=libcurl.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit155]
+FileName=libcurl.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit156]
+FileName=clvm_cmds.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit157]
+FileName=svbsp.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit117]
+FileName=r_explosion.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=1
+Minor=0
+Release=0
+Build=0
+LanguageID=1033
+CharsetID=1252
+CompanyName=Forest Hale Digital Services
+FileVersion=1.0
+FileDescription=DarkPlaces Game Engine
+InternalName=darkplaces.exe
+LegalCopyright=id Software, Forest Hale, and contributors
+LegalTrademarks=
+OriginalFilename=darkplaces.exe
+ProductName=DarkPlaces
+ProductVersion=1.0
+AutoIncBuildNr=0
+
+[Unit122]
+FileName=r_sky.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit144]
+FileName=prvm_cmds.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit158]
+FileName=svbsp.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit159]
+FileName=sv_demo.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit160]
+FileName=sv_demo.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit161]
+FileName=snd_modplug.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit162]
+FileName=snd_modplug.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit163]
+FileName=cl_gecko.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit164]
+FileName=cl_gecko.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit165]
+FileName=cl_dyntexture.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit166]
+FileName=cl_dyntexture.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit167]
+FileName=hmac.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit168]
+FileName=hmac.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit169]
+FileName=cap_avi.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit170]
+FileName=cap_avi.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit171]
+FileName=cap_ogg.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit172]
+FileName=cap_ogg.h
+CompileCpp=0
+Folder=Header Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit173]
+FileName=utf8lib.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit174]
+FileName=ft2.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit175]
+FileName=bih.c
+CompileCpp=0
+Folder=Source Files
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
*/
// Additional OPTIONAL Fields and Globals
-float intermission;
+float intermission; // indicates intermission state (0 = normal, 1 = scores, 2 = finale text)
vector view_angles; // same as input_angles
-vector view_punchangle;
-vector view_punchvector;
+vector view_punchangle; // from server
+vector view_punchvector; // from server
/*
==============================================================================
vector() randomvec = #91;
vector(vector org) getlight = #92;
vector(vector org, float lpflags) getlight2 = #92;
+vector getlight_dir;
+vector getlight_ambient;
+vector getlight_diffuse;
const float LP_LIGHTMAP = 1;
const float LP_RTWORLD = 2;
const float LP_DYNLIGHT = 4;
void(float mask) addentities = #301;
void(entity ent) addentity = #302;
float(float property, ...) setproperty = #303;
+float(float property) getproperty = #309;
+vector(float property) getpropertyvec = #309;
void() renderscene = #304;
void(vector org, float radius, vector lightcolours) adddynamiclight = #305;
void(vector org, float radius, vector lightcolours, float style, string cubemapname, float pflags) adddynamiclight2 = #305;
// example: transparent_offset = 1000000; // entity always appear on background of other transparents
// note: offset is done in view forward axis
-// DP_CSQC_ENTITYNOCULL
+// DP_CSQC_ENTITYWORLDOBJECT
// idea: VorteX
// darkplaces implementation: VorteX
-const float RF_NOCULL = 128;
+const float RF_WORLDOBJECT = 128;
// description: when renderflag is set, engine will not use culling methods for this entity, e.g. it will always be drawn
-// useful for large outdoor objects (like asteriods on sky horizont or sky models)
-// also useful when culling is done at CSQC side
+// useful for large outdoor objects (like asteroids on sky horizon or sky models)
+
+// DP_CSQC_ENTITYMODELLIGHT
+// idea: VorteX
+// darkplaces implementation: VorteX
+const float RF_MODELLIGHT = 4096;
+.vector modellight_ambient;
+.vector modellight_diffuse;
+.vector modellight_dir;
+// description: allows CSQC to override directional model lightning on entity
// DP_CSQC_SETPAUSE
// idea: VorteX
float(string url, float id, string content_type, string delim, float buf, float keyid) crypto_uri_postbuf = #513;
//description:
//use -1 as buffer handle to justs end delim as postdata
+
+//DP_CSQC_MAINVIEW
+//idea: divVerent
+//darkplaces implementation: divVerent
+//constant definitions:
+const float VF_MAINVIEW = 212;
+//use setproperty(VF_MAINVIEW, 1); before calling R_RenderView for the render
+//that shall become the "main" view, which is e.g. used by PRYDON_CLIENTCURSOR
+//this flag is set for the first scene, and not cleared by R_ClearScene
+//this flag is automatically cleared by R_RenderView
+//so when not using this extension, the first view rendered is the main view
//description:
//MOVETYPE_BOUNCE but without gravity, and with full reflection (no speed loss like grenades have), in other words - bouncing laser bolts.
+//DP_MOVETYPEFLYWORLDONLY
+//idea: Samual
+//darkplaces implementation: Samual
+//movetype definitions:
+float MOVETYPE_FLY_WORLDONLY = 33;
+//description:
+//like MOVETYPE_FLY, but does all traces with MOVE_WORLDONLY, and is ignored by MOVETYPE_PUSH. Should only be combined with SOLID_NOT and SOLID_TRIGGER.
+
//DP_NULL_MODEL
//idea: Chris
//darkplaces implementation: divVerent
//description:
//copies all data in the entity to another entity.
+//DP_QC_CRC16
+//idea: divVerent
+//darkplaces implementation: divVerent
+//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
+//When caseinsensitive is set, the CRC is calculated of the lower cased string.
+float(float caseinsensitive, string s, ...) crc16 = #494;
+
//DP_QC_CVAR_DEFSTRING
//idea: id Software (Doom3), LordHavoc
//darkplaces implementation: LordHavoc
float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
float CVAR_TYPEFLAG_READONLY = 32;
+//DP_QC_DIGEST
+//idea: motorsep, Spike
+//DarkPlaces implementation: divVerent
+//builtin definitions:
+string(string digest, string data, ...) digest_hex = #639;
+//description:
+//returns a given hex digest of given data
+//the returned digest is always encoded in hexadecimal
+//only the "MD4" digest is always supported!
+//if the given digest is not supported, string_null is returned
+//the digest string is matched case sensitively, use "MD4", not "md4"!
+
+//DP_QC_DIGEST_SHA256
+//idea: motorsep, Spike
+//DarkPlaces implementation: divVerent
+//description:
+//"SHA256" is also an allowed digest type
+
//DP_QC_EDICT_NUM
//idea: 515
//DarkPlaces implementation: LordHavoc
//returns the playing time of the current cdtrack when passed to gettime()
//see DP_END_GETSOUNDTIME for similar functionality but for entity sound channels
+//DP_QC_I18N
+//idea: divVerent
+//darkplaces implementation: divVerent
+//description:
+//
+//The engine supports translating by gettext compatible .po files.
+//progs.dat uses progs.dat.<LANGUAGE>.po
+//menu.dat uses menu.dat.<LANGUAGE>.po
+//csprogs.dat uses csprogs.dat.<LANGUAGE>.po
+//
+//To create a string that can be translated, define it as
+// string dotranslate_FILENOTFOUND = "File not found";
+//Note: if the compiler does constant folding, this will only work if there is
+//no other "File not found" string in the progs!
+//
+//Alternatively, if using the Xonotic patched fteqcc compiler, you can simplify
+//this by using _("File not found") directly in the source code.
+//
+//The language is set by the "prvm_language" cvar: if prvm_language is set to
+//"de", it will read progs.dat.de.po for translating strings in progs.dat.
+//
+//If prvm_language is set to the special name "dump", progs.dat.pot will be
+//written, which is a translation template to be edited by filling out the
+//msgstr entries.
+
//DP_QC_LOG
//darkplaces implementation: divVerent
//builtin definitions:
//DP_SND_FAKETRACKS
//idea: requested
+
//darkplaces implementation: Elric
//description:
//the engine plays sound/cdtracks/track001.wav instead of cd track 1 and so on if found, this allows games and mods to have music tracks without using ambientsound.
//Note: also plays .ogg with DP_SND_OGGVORBIS extension.
//DP_SND_SOUND7_WIP1
+//DP_SND_SOUND7_WIP2
//idea: divVerent
//darkplaces implementation: divVerent
//builtin definitions:
//extensions to sound():
//- channel may be in the range from -128 to 127; channels -128 to 0 are "auto",
// i.e. support multiple sounds at once, but cannot be stopped/restarted
-//- a speed parameter has been reserved for later addition of pitch shifting.
-// it MUST be set to 0 for now, meaning "no pitch change"
+//- a value 0 in the speed parameter means no change; otherwise, it is a
+// percentage of playback speed ("pitch shifting"). 100 is normal pitch, 50 is
+// half speed, 200 is double speed, etc. (DP_SND_SOUND7_WIP2)
//- the flag SOUNDFLAG_RELIABLE can be specified, which makes the sound send
// to MSG_ALL (reliable) instead of MSG_BROADCAST (unreliable, default);
// similarily, SOUNDFLAG_RELIABLE_TO_ONE sends to MSG_ONE
const float SOLID_PHYSICS_BOX = 32;
const float SOLID_PHYSICS_SPHERE = 33;
const float SOLID_PHYSICS_CAPSULE = 34;
+const float SOLID_PHYSICS_TRIMESH = 35;
+const float SOLID_PHYSICS_CYLINDER = 36;
//SOLID_BSP;
//joint types:
const float JOINTTYPE_POINT = 1;
// note that ODE does not support both in one anyway
//field definitions:
.float mass; // ODE mass, standart value is 1
+.vector massofs; // offsets a mass center out of object center, if not set a center of model bounds is used
+.float friction;
.float bouncefactor;
.float bouncestop;
.float jointtype;
//description: provides Open Dynamics Engine support, requires extenal dll to be present or engine compiled with statical link option
//be sure to checkextension for it to know if library is loaded and ready, also to enable physics set "physics_ode" cvar to 1
//note: this extension is highly experimental and may be unstable
-//note: use SOLID_BSP on entities to get a trimesh collision models on them
//DP_SV_PRINT
//idea: id Software (QuakeWorld Server)
//description:
//strreplace replaces all occurrences of 'search' with 'replace' in the string 'subject', and returns the result as a tempstring.
//strireplace does the same but uses case-insensitive matching of the 'search' term
-//
-//DP_QC_CRC16
-//idea: divVerent
-//darkplaces implementation: divVerent
-//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
-//When caseinsensitive is set, the CRC is calculated of the lower cased string.
-float(float caseinsensitive, string s, ...) crc16 = #494;
//DP_SV_SHUTDOWN
//idea: divVerent
#endif
#define ALIGN_SIZE 16
-#define ATOMIC_SIZE 32
+#define ATOMIC_SIZE 4
#ifdef SSE_POSSIBLE
#if defined(__APPLE__)
#include <libkern/OSAtomic.h>
#define ALIGN(var) var __attribute__((__aligned__(16)))
- #define ATOMIC(var) var __attribute__((__aligned__(32)))
+ #define ATOMIC(var) var __attribute__((__aligned__(4)))
#define MEMORY_BARRIER (_mm_sfence())
#define ATOMIC_COUNTER volatile int32_t
#define ATOMIC_INCREMENT(counter) (OSAtomicIncrement32Barrier(&(counter)))
#define ATOMIC_ADD(counter, val) ((void)OSAtomicAdd32Barrier((val), &(counter)))
#elif defined(__GNUC__) && defined(WIN32)
#define ALIGN(var) var __attribute__((__aligned__(16)))
- #define ATOMIC(var) var __attribute__((__aligned__(32)))
+ #define ATOMIC(var) var __attribute__((__aligned__(4)))
#define MEMORY_BARRIER (_mm_sfence())
//(__sync_synchronize())
#define ATOMIC_COUNTER volatile LONG
#define ATOMIC_ADD(counter, val) ((void)InterlockedExchangeAdd((LONG *) &(counter), (val)))
#elif defined(__GNUC__)
#define ALIGN(var) var __attribute__((__aligned__(16)))
- #define ATOMIC(var) var __attribute__((__aligned__(32)))
+ #define ATOMIC(var) var __attribute__((__aligned__(4)))
#define MEMORY_BARRIER (_mm_sfence())
//(__sync_synchronize())
#define ATOMIC_COUNTER volatile int
#define ATOMIC_ADD(counter, val) ((void)__sync_fetch_and_add(&(counter), (val)))
#elif defined(_MSC_VER)
#define ALIGN(var) __declspec(align(16)) var
- #define ATOMIC(var) __declspec(align(32)) var
+ #define ATOMIC(var) __declspec(align(4)) var
#define MEMORY_BARRIER (_mm_sfence())
//(MemoryBarrier())
#define ATOMIC_COUNTER volatile LONG
#define _mm_cvtss_f32(val) (__builtin_ia32_vec_ext_v4sf ((__v4sf)(val), 0))
#endif
-#define MM_MALLOC(size) _mm_malloc(size, ATOMIC_SIZE)
+#define MM_MALLOC(size) _mm_malloc(size, ALIGN_SIZE)
static void *MM_CALLOC(size_t nmemb, size_t size)
{
- void *ptr = _mm_malloc(nmemb*size, ATOMIC_SIZE);
+ void *ptr = _mm_malloc(nmemb*size, ALIGN_SIZE);
if (ptr != NULL) memset(ptr, 0, nmemb*size);
return ptr;
}
#define DPSOFTRAST_DRAW_MAXCOMMANDPOOL 2097152
#define DPSOFTRAST_DRAW_MAXCOMMANDSIZE 16384
-typedef ATOMIC(struct DPSOFTRAST_State_Command_Pool_s
+typedef ALIGN(struct DPSOFTRAST_State_Command_Pool_s
{
int freecommand;
int usedcommands;
- ATOMIC(unsigned char commands[DPSOFTRAST_DRAW_MAXCOMMANDPOOL]);
+ ALIGN(unsigned char commands[DPSOFTRAST_DRAW_MAXCOMMANDPOOL]);
}
DPSOFTRAST_State_Command_Pool);
-typedef ATOMIC(struct DPSOFTRAST_State_Triangle_s
+typedef ALIGN(struct DPSOFTRAST_State_Triangle_s
{
unsigned char mip[DPSOFTRAST_MAXTEXTUREUNITS]; // texcoord to screen space density values (for picking mipmap of textures)
float w[3];
}
DPSOFTRAST_BLENDMODE;
-typedef ATOMIC(struct DPSOFTRAST_State_Thread_s
+typedef ALIGN(struct DPSOFTRAST_State_Thread_s
{
void *thread;
int index;
}
DPSOFTRAST_State_Thread);
-typedef ATOMIC(struct DPSOFTRAST_State_s
+typedef ALIGN(struct DPSOFTRAST_State_s
{
int fb_width;
int fb_height;
}
}
-DPSOFTRAST_Texture *DPSOFTRAST_Texture_GetByIndex(int index)
+static DPSOFTRAST_Texture *DPSOFTRAST_Texture_GetByIndex(int index)
{
if (index >= 1 && index < dpsoftrast.texture_end && dpsoftrast.texture[index].bytes)
return &dpsoftrast.texture[index];
while (dpsoftrast.texture_end > 0 && dpsoftrast.texture[dpsoftrast.texture_end-1].bytes == NULL)
dpsoftrast.texture_end--;
}
-void DPSOFTRAST_Texture_CalculateMipmaps(int index)
+static void DPSOFTRAST_Texture_CalculateMipmaps(int index)
{
int i, x, y, z, w, layer0, layer1, row0, row1;
unsigned char *o, *i0, *i1, *i2, *i3;
}
#endif
-void DPSOFTRAST_Vertex_Transform(float *out4f, const float *in4f, int numitems, const float *inmatrix16f)
+static void DPSOFTRAST_Vertex_Transform(float *out4f, const float *in4f, int numitems, const float *inmatrix16f)
{
#ifdef SSE_POSSIBLE
static const float identitymatrix[4][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
#endif
}
-void DPSOFTRAST_Vertex_Copy(float *out4f, const float *in4f, int numitems)
+#if 0
+static void DPSOFTRAST_Vertex_Copy(float *out4f, const float *in4f, int numitems)
{
memcpy(out4f, in4f, numitems * sizeof(float[4]));
}
+#endif
#ifdef SSE_POSSIBLE
#define DPSOFTRAST_PROJECTVERTEX(out, in, viewportcenter, viewportscale) \
#endif
}
-void DPSOFTRAST_Draw_Span_Begin(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *zf)
+static void DPSOFTRAST_Draw_Span_Begin(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *zf)
{
int x;
int startx = span->startx;
}
}
-void DPSOFTRAST_Draw_Span_FinishBGRA8(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, const unsigned char* RESTRICT in4ub)
+static void DPSOFTRAST_Draw_Span_FinishBGRA8(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, const unsigned char* RESTRICT in4ub)
{
#ifdef SSE_POSSIBLE
int x;
}
}
-void DPSOFTRAST_Draw_Span_Texture2DVarying(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float * RESTRICT out4f, int texunitindex, int arrayindex, const float * RESTRICT zf)
+#if 0
+static void DPSOFTRAST_Draw_Span_Texture2DVarying(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float * RESTRICT out4f, int texunitindex, int arrayindex, const float * RESTRICT zf)
{
int x;
int startx = span->startx;
}
}
}
+#endif
-void DPSOFTRAST_Draw_Span_Texture2DVaryingBGRA8(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char * RESTRICT out4ub, int texunitindex, int arrayindex, const float * RESTRICT zf)
+static void DPSOFTRAST_Draw_Span_Texture2DVaryingBGRA8(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char * RESTRICT out4ub, int texunitindex, int arrayindex, const float * RESTRICT zf)
{
#ifdef SSE_POSSIBLE
int x;
#endif
}
-void DPSOFTRAST_Draw_Span_TextureCubeVaryingBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char * RESTRICT out4ub, int texunitindex, int arrayindex, const float * RESTRICT zf)
+static void DPSOFTRAST_Draw_Span_TextureCubeVaryingBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char * RESTRICT out4ub, int texunitindex, int arrayindex, const float * RESTRICT zf)
{
// TODO: IMPLEMENT
memset(out4ub + span->startx*4, 255, (span->startx - span->endx)*4);
}
-float DPSOFTRAST_SampleShadowmap(const float *vector)
+static float DPSOFTRAST_SampleShadowmap(const float *vector)
{
// TODO: IMPLEMENT
return 1.0f;
}
-void DPSOFTRAST_Draw_Span_MultiplyVarying(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *in4f, int arrayindex, const float *zf)
+#if 0
+static void DPSOFTRAST_Draw_Span_MultiplyVarying(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *in4f, int arrayindex, const float *zf)
{
int x;
int startx = span->startx;
out4f[x*4+3] = in4f[x*4+3] * c[3];
}
}
+#endif
-void DPSOFTRAST_Draw_Span_Varying(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, int arrayindex, const float *zf)
+#if 0
+static void DPSOFTRAST_Draw_Span_Varying(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, int arrayindex, const float *zf)
{
int x;
int startx = span->startx;
out4f[x*4+3] = c[3];
}
}
+#endif
-void DPSOFTRAST_Draw_Span_AddBloom(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f, const float *subcolor)
+#if 0
+static void DPSOFTRAST_Draw_Span_AddBloom(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f, const float *subcolor)
{
int x, startx = span->startx, endx = span->endx;
float c[4], localcolor[4];
out4f[x*4+3] = ina4f[x*4+3] + c[3];
}
}
+#endif
-void DPSOFTRAST_Draw_Span_MultiplyBuffers(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f)
+#if 0
+static void DPSOFTRAST_Draw_Span_MultiplyBuffers(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f)
{
int x, startx = span->startx, endx = span->endx;
for (x = startx;x < endx;x++)
out4f[x*4+3] = ina4f[x*4+3] * inb4f[x*4+3];
}
}
+#endif
-void DPSOFTRAST_Draw_Span_AddBuffers(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f)
+#if 0
+static void DPSOFTRAST_Draw_Span_AddBuffers(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f)
{
int x, startx = span->startx, endx = span->endx;
for (x = startx;x < endx;x++)
out4f[x*4+3] = ina4f[x*4+3] + inb4f[x*4+3];
}
}
+#endif
-void DPSOFTRAST_Draw_Span_MixBuffers(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f)
+#if 0
+static void DPSOFTRAST_Draw_Span_MixBuffers(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *ina4f, const float *inb4f)
{
int x, startx = span->startx, endx = span->endx;
float a, b;
out4f[x*4+3] = ina4f[x*4+3] * a + inb4f[x*4+3] * b;
}
}
+#endif
-void DPSOFTRAST_Draw_Span_MixUniformColor(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *in4f, const float *color)
+#if 0
+static void DPSOFTRAST_Draw_Span_MixUniformColor(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, float *out4f, const float *in4f, const float *color)
{
int x, startx = span->startx, endx = span->endx;
float localcolor[4], ilerp, lerp;
out4f[x*4+3] = in4f[x*4+3] * ilerp + localcolor[3] * lerp;
}
}
+#endif
-void DPSOFTRAST_Draw_Span_MultiplyVaryingBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *in4ub, int arrayindex, const float *zf)
+static void DPSOFTRAST_Draw_Span_MultiplyVaryingBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *in4ub, int arrayindex, const float *zf)
{
#ifdef SSE_POSSIBLE
int x;
#endif
}
-void DPSOFTRAST_Draw_Span_VaryingBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, int arrayindex, const float *zf)
+static void DPSOFTRAST_Draw_Span_VaryingBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, int arrayindex, const float *zf)
{
#ifdef SSE_POSSIBLE
int x;
#endif
}
-void DPSOFTRAST_Draw_Span_AddBloomBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub, const float *subcolor)
+static void DPSOFTRAST_Draw_Span_AddBloomBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub, const float *subcolor)
{
#ifdef SSE_POSSIBLE
int x, startx = span->startx, endx = span->endx;
#endif
}
-void DPSOFTRAST_Draw_Span_MultiplyBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub)
+static void DPSOFTRAST_Draw_Span_MultiplyBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub)
{
#ifdef SSE_POSSIBLE
int x, startx = span->startx, endx = span->endx;
#endif
}
-void DPSOFTRAST_Draw_Span_AddBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub)
+static void DPSOFTRAST_Draw_Span_AddBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub)
{
#ifdef SSE_POSSIBLE
int x, startx = span->startx, endx = span->endx;
#endif
}
-void DPSOFTRAST_Draw_Span_TintedAddBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub, const float *inbtintbgra)
+#if 0
+static void DPSOFTRAST_Draw_Span_TintedAddBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub, const float *inbtintbgra)
{
#ifdef SSE_POSSIBLE
int x, startx = span->startx, endx = span->endx;
}
#endif
}
+#endif
-void DPSOFTRAST_Draw_Span_MixBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub)
+static void DPSOFTRAST_Draw_Span_MixBuffersBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *ina4ub, const unsigned char *inb4ub)
{
#ifdef SSE_POSSIBLE
int x, startx = span->startx, endx = span->endx;
#endif
}
-void DPSOFTRAST_Draw_Span_MixUniformColorBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *in4ub, const float *color)
+static void DPSOFTRAST_Draw_Span_MixUniformColorBGRA8(const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span, unsigned char *out4ub, const unsigned char *in4ub, const float *color)
{
#ifdef SSE_POSSIBLE
int x, startx = span->startx, endx = span->endx;
-void DPSOFTRAST_VertexShader_Generic(void)
+static void DPSOFTRAST_VertexShader_Generic(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_COLOR, DPSOFTRAST_ARRAY_COLOR);
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_TEXCOORD1, DPSOFTRAST_ARRAY_TEXCOORD1);
}
-void DPSOFTRAST_PixelShader_Generic(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_Generic(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
unsigned char buffer_texture_colorbgra8[DPSOFTRAST_DRAW_MAXSPANLENGTH*4];
-void DPSOFTRAST_VertexShader_PostProcess(void)
+static void DPSOFTRAST_VertexShader_PostProcess(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD0);
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_TEXCOORD1, DPSOFTRAST_ARRAY_TEXCOORD4);
}
-void DPSOFTRAST_PixelShader_PostProcess(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_PostProcess(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
// TODO: optimize!! at the very least there is no reason to use texture sampling on the frame texture
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
-void DPSOFTRAST_VertexShader_Depth_Or_Shadow(void)
+static void DPSOFTRAST_VertexShader_Depth_Or_Shadow(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
}
-void DPSOFTRAST_PixelShader_Depth_Or_Shadow(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_Depth_Or_Shadow(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
// this is never called (because colormask is off when this shader is used)
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
-void DPSOFTRAST_VertexShader_FlatColor(void)
+static void DPSOFTRAST_VertexShader_FlatColor(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
DPSOFTRAST_Array_Transform(DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD0, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_TexMatrixM1);
}
-void DPSOFTRAST_PixelShader_FlatColor(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_FlatColor(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
#ifdef SSE_POSSIBLE
unsigned char * RESTRICT pixelmask = span->pixelmask;
-void DPSOFTRAST_VertexShader_VertexColor(void)
+static void DPSOFTRAST_VertexShader_VertexColor(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_COLOR, DPSOFTRAST_ARRAY_COLOR);
DPSOFTRAST_Array_Transform(DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD0, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_TexMatrixM1);
}
-void DPSOFTRAST_PixelShader_VertexColor(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_VertexColor(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
#ifdef SSE_POSSIBLE
unsigned char * RESTRICT pixelmask = span->pixelmask;
-void DPSOFTRAST_VertexShader_Lightmap(void)
+static void DPSOFTRAST_VertexShader_Lightmap(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
DPSOFTRAST_Array_Transform(DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD0, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_TexMatrixM1);
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_TEXCOORD4, DPSOFTRAST_ARRAY_TEXCOORD4);
}
-void DPSOFTRAST_PixelShader_Lightmap(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_Lightmap(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
#ifdef SSE_POSSIBLE
unsigned char * RESTRICT pixelmask = span->pixelmask;
void DPSOFTRAST_VertexShader_LightDirection(void);
void DPSOFTRAST_PixelShader_LightDirection(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span);
-void DPSOFTRAST_VertexShader_FakeLight(void)
+static void DPSOFTRAST_VertexShader_FakeLight(void)
{
DPSOFTRAST_VertexShader_LightDirection();
}
-void DPSOFTRAST_PixelShader_FakeLight(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_FakeLight(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
DPSOFTRAST_PixelShader_LightDirection(thread, triangle, span);
}
-void DPSOFTRAST_VertexShader_LightDirectionMap_ModelSpace(void)
+static void DPSOFTRAST_VertexShader_LightDirectionMap_ModelSpace(void)
{
DPSOFTRAST_VertexShader_LightDirection();
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_TEXCOORD4, DPSOFTRAST_ARRAY_TEXCOORD4);
}
-void DPSOFTRAST_PixelShader_LightDirectionMap_ModelSpace(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_LightDirectionMap_ModelSpace(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
DPSOFTRAST_PixelShader_LightDirection(thread, triangle, span);
}
-void DPSOFTRAST_VertexShader_LightDirectionMap_TangentSpace(void)
+static void DPSOFTRAST_VertexShader_LightDirectionMap_TangentSpace(void)
{
DPSOFTRAST_VertexShader_LightDirection();
DPSOFTRAST_Array_Load(DPSOFTRAST_ARRAY_TEXCOORD4, DPSOFTRAST_ARRAY_TEXCOORD4);
}
-void DPSOFTRAST_PixelShader_LightDirectionMap_TangentSpace(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_LightDirectionMap_TangentSpace(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
DPSOFTRAST_PixelShader_LightDirection(thread, triangle, span);
}
specular = DPSOFTRAST_Vector3Dot(surfacenormal, specularnormal);if (specular < 0.0f) specular = 0.0f;
}
+ specular = pow(specular, 1.0f + SpecularPower * glosstex[3]);
- specular = pow(specular, SpecularPower * glosstex[3]);
if (thread->shader_permutation & SHADERPERMUTATION_GLOW)
{
d[0] = (int)(buffer_texture_glowbgra8[x*4+0] * Color_Glow[0] + diffusetex[0] * Color_Ambient[0] + (diffusetex[0] * Color_Diffuse[0] * diffuse + glosstex[0] * Color_Specular[0] * specular) * LightColor[0]);if (d[0] > 255) d[0] = 255;
-void DPSOFTRAST_VertexShader_LightSource(void)
+static void DPSOFTRAST_VertexShader_LightSource(void)
{
int i;
int numvertices = dpsoftrast.numvertices;
DPSOFTRAST_Array_Transform(DPSOFTRAST_ARRAY_TEXCOORD3, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelToLightM1);
}
-void DPSOFTRAST_PixelShader_LightSource(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_LightSource(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
#ifdef SSE_POSSIBLE
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
specular = DPSOFTRAST_Vector3Dot(surfacenormal, specularnormal);if (specular < 0.0f) specular = 0.0f;
}
- specular = pow(specular, SpecularPower * glosstex[3]);
+ specular = pow(specular, 1.0f + SpecularPower * glosstex[3]);
if (thread->shader_permutation & SHADERPERMUTATION_CUBEFILTER)
{
-void DPSOFTRAST_VertexShader_Refraction(void)
+static void DPSOFTRAST_VertexShader_Refraction(void)
{
DPSOFTRAST_Array_Transform(DPSOFTRAST_ARRAY_TEXCOORD4, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
DPSOFTRAST_Array_Transform(DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD0, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_TexMatrixM1);
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
}
-void DPSOFTRAST_PixelShader_Refraction(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_Refraction(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
float z;
-void DPSOFTRAST_VertexShader_Water(void)
+static void DPSOFTRAST_VertexShader_Water(void)
{
int i;
int numvertices = dpsoftrast.numvertices;
}
-void DPSOFTRAST_PixelShader_Water(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_Water(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
float z;
-void DPSOFTRAST_VertexShader_ShowDepth(void)
+static void DPSOFTRAST_VertexShader_ShowDepth(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
}
-void DPSOFTRAST_PixelShader_ShowDepth(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_ShowDepth(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
// TODO: IMPLEMENT
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
-void DPSOFTRAST_VertexShader_DeferredGeometry(void)
+static void DPSOFTRAST_VertexShader_DeferredGeometry(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
}
-void DPSOFTRAST_PixelShader_DeferredGeometry(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_DeferredGeometry(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
// TODO: IMPLEMENT
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
-void DPSOFTRAST_VertexShader_DeferredLightSource(void)
+static void DPSOFTRAST_VertexShader_DeferredLightSource(void)
{
DPSOFTRAST_Array_TransformProject(DPSOFTRAST_ARRAY_POSITION, DPSOFTRAST_ARRAY_POSITION, dpsoftrast.uniform4f + 4*DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1);
}
-void DPSOFTRAST_PixelShader_DeferredLightSource(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
+static void DPSOFTRAST_PixelShader_DeferredLightSource(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_State_Triangle * RESTRICT triangle, const DPSOFTRAST_State_Span * RESTRICT span)
{
// TODO: IMPLEMENT
float buffer_z[DPSOFTRAST_DRAW_MAXSPANLENGTH];
{2, DPSOFTRAST_VertexShader_FakeLight, DPSOFTRAST_PixelShader_FakeLight, {DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD1, DPSOFTRAST_ARRAY_TEXCOORD2, DPSOFTRAST_ARRAY_TEXCOORD3, DPSOFTRAST_ARRAY_TEXCOORD5, DPSOFTRAST_ARRAY_TEXCOORD6, ~0}, {GL20TU_COLOR, GL20TU_PANTS, GL20TU_SHIRT, GL20TU_GLOW, GL20TU_NORMAL, GL20TU_GLOSS, ~0}},
{2, DPSOFTRAST_VertexShader_LightDirectionMap_ModelSpace, DPSOFTRAST_PixelShader_LightDirectionMap_ModelSpace, {DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD1, DPSOFTRAST_ARRAY_TEXCOORD2, DPSOFTRAST_ARRAY_TEXCOORD3, DPSOFTRAST_ARRAY_TEXCOORD4, DPSOFTRAST_ARRAY_TEXCOORD5, DPSOFTRAST_ARRAY_TEXCOORD6, ~0}, {GL20TU_COLOR, GL20TU_PANTS, GL20TU_SHIRT, GL20TU_GLOW, GL20TU_NORMAL, GL20TU_GLOSS, GL20TU_LIGHTMAP, GL20TU_DELUXEMAP, ~0}},
{2, DPSOFTRAST_VertexShader_LightDirectionMap_TangentSpace, DPSOFTRAST_PixelShader_LightDirectionMap_TangentSpace, {DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD1, DPSOFTRAST_ARRAY_TEXCOORD2, DPSOFTRAST_ARRAY_TEXCOORD3, DPSOFTRAST_ARRAY_TEXCOORD4, DPSOFTRAST_ARRAY_TEXCOORD5, DPSOFTRAST_ARRAY_TEXCOORD6, ~0}, {GL20TU_COLOR, GL20TU_PANTS, GL20TU_SHIRT, GL20TU_GLOW, GL20TU_NORMAL, GL20TU_GLOSS, GL20TU_LIGHTMAP, GL20TU_DELUXEMAP, ~0}},
+ {2, DPSOFTRAST_VertexShader_Lightmap, DPSOFTRAST_PixelShader_Lightmap, {DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD4, ~0}, {GL20TU_COLOR, GL20TU_LIGHTMAP, GL20TU_GLOW, ~0}},
+ {2, DPSOFTRAST_VertexShader_VertexColor, DPSOFTRAST_PixelShader_VertexColor, {DPSOFTRAST_ARRAY_COLOR, DPSOFTRAST_ARRAY_TEXCOORD0, ~0}, {GL20TU_COLOR, ~0}},
{2, DPSOFTRAST_VertexShader_LightDirection, DPSOFTRAST_PixelShader_LightDirection, {DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD1, DPSOFTRAST_ARRAY_TEXCOORD2, DPSOFTRAST_ARRAY_TEXCOORD3, DPSOFTRAST_ARRAY_TEXCOORD5, DPSOFTRAST_ARRAY_TEXCOORD6, ~0}, {GL20TU_COLOR, GL20TU_PANTS, GL20TU_SHIRT, GL20TU_GLOW, GL20TU_NORMAL, GL20TU_GLOSS, ~0}},
{2, DPSOFTRAST_VertexShader_LightSource, DPSOFTRAST_PixelShader_LightSource, {DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD1, DPSOFTRAST_ARRAY_TEXCOORD2, DPSOFTRAST_ARRAY_TEXCOORD3, DPSOFTRAST_ARRAY_TEXCOORD4, ~0}, {GL20TU_COLOR, GL20TU_PANTS, GL20TU_SHIRT, GL20TU_GLOW, GL20TU_NORMAL, GL20TU_GLOSS, GL20TU_CUBE, ~0}},
{2, DPSOFTRAST_VertexShader_Refraction, DPSOFTRAST_PixelShader_Refraction, {DPSOFTRAST_ARRAY_TEXCOORD0, DPSOFTRAST_ARRAY_TEXCOORD4, ~0}, {GL20TU_NORMAL, GL20TU_REFRACTION, ~0}},
}
}
-void DPSOFTRAST_Draw_ProcessSpans(DPSOFTRAST_State_Thread *thread)
+static void DPSOFTRAST_Draw_ProcessSpans(DPSOFTRAST_State_Thread *thread)
{
int i;
DPSOFTRAST_State_Triangle *triangle;
thread->numspans = 0;
}
-DEFCOMMAND(22, Draw, int datasize; int starty; int endy; ATOMIC_COUNTER refcount; int clipped; int firstvertex; int numvertices; int numtriangles; float *arrays; int *element3i; unsigned short *element3s;);
+DEFCOMMAND(22, Draw, int datasize; int starty; int endy; ATOMIC_COUNTER refcount; int clipped; int firstvertex; int numvertices; int numtriangles; float *arrays; int *element3i; unsigned short *element3s;)
static void DPSOFTRAST_Interpret_Draw(DPSOFTRAST_State_Thread *thread, DPSOFTRAST_Command_Draw *command)
{
}
}
-DEFCOMMAND(23, SetRenderTargets, int width; int height;);
+DEFCOMMAND(23, SetRenderTargets, int width; int height;)
static void DPSOFTRAST_Interpret_SetRenderTargets(DPSOFTRAST_State_Thread *thread, const DPSOFTRAST_Command_SetRenderTargets *command)
{
thread->validate |= DPSOFTRAST_VALIDATE_FB;
GL20TU_SHADOWMAP2D = 15,
GL20TU_CUBEPROJECTION = 12,
// rtlight prepass data (screenspace depth and normalmap)
- GL20TU_SCREENDEPTH = 13,
+// GL20TU_UNUSED1 = 13,
GL20TU_SCREENNORMALMAP = 14,
// lightmap prepass data (screenspace diffuse and specular from lights)
GL20TU_SCREENDIFFUSE = 11,
SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
+ SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP, // forced deluxemapping for lightmapped surfaces
+ SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR, // forced deluxemapping for vertexlit surfaces
SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
SHADERPERMUTATION_BOUNCEGRID = 1<<28, ///< (lightmap) use Texture_BounceGrid as an additional source of ambient light
SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL = 1<<29, ///< (lightmap) use 16-component pixels in bouncegrid texture for directional lighting rather than standard 4-component
SHADERPERMUTATION_TRIPPY = 1<<30, ///< use trippy vertex shader effect
- SHADERPERMUTATION_LIMIT = 1<<31, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 31 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_DEPTHRGB = 1<<31, ///< read/write depth values in RGB color coded format for older hardware without depth samplers
+ SHADERPERMUTATION_COUNT = 32 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
DPSOFTRAST_UNIFORM_Texture_Reflection,
DPSOFTRAST_UNIFORM_Texture_ShadowMap2D,
DPSOFTRAST_UNIFORM_Texture_CubeProjection,
- DPSOFTRAST_UNIFORM_Texture_ScreenDepth,
DPSOFTRAST_UNIFORM_Texture_ScreenNormalMap,
DPSOFTRAST_UNIFORM_Texture_ScreenDiffuse,
DPSOFTRAST_UNIFORM_Texture_ScreenSpecular,
DPSOFTRAST_UNIFORM_ShadowMapMatrixM4,
DPSOFTRAST_UNIFORM_BloomColorSubtract,
DPSOFTRAST_UNIFORM_NormalmapScrollBlend,
+ DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance,
+ DPSOFTRAST_UNIFORM_OffsetMapping_Bias,
DPSOFTRAST_UNIFORM_TOTAL
}
DPSOFTRAST_UNIFORM;
}
hz_bitstream_readblocks_t;
-hz_bitstream_read_t *hz_bitstream_read_open(char *filename)
+static hz_bitstream_read_t *hz_bitstream_read_open(char *filename)
{
qfile_t *file;
hz_bitstream_read_t *stream;
return NULL;
}
-void hz_bitstream_read_close(hz_bitstream_read_t *stream)
+static void hz_bitstream_read_close(hz_bitstream_read_t *stream)
{
if (stream)
{
}
}
-hz_bitstream_readblocks_t *hz_bitstream_read_blocks_new(void)
+static hz_bitstream_readblocks_t *hz_bitstream_read_blocks_new(void)
{
hz_bitstream_readblocks_t *blocks;
blocks = (hz_bitstream_readblocks_t *)Z_Malloc(sizeof(hz_bitstream_readblocks_t));
return blocks;
}
-void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
+static void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
{
hz_bitstream_readblock_t *b, *n;
if (blocks == NULL)
Z_Free(blocks);
}
-void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
+static void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
{
blocks->store = 0;
blocks->count = 0;
}
-int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
+static int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
{
int s;
hz_bitstream_readblock_t *b, *p;
return HZREADERROR_OK;
}
-unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
+static unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
{
while (blocks->current != NULL && blocks->position >= blocks->current->size)
{
return blocks->current->data[blocks->position++];
}
-int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
+static int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
{
if (!blocks->count)
{
return (blocks->store >> blocks->count) & 1;
}
-unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
+static unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
{
unsigned int num = 0;
// we can only handle about 24 bits at a time safely
return num;
}
-unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
+static unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
{
return hz_bitstream_read_blocks_getbyte(blocks);
}
-unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
+static unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
{
return (hz_bitstream_read_byte(blocks) << 8)
| (hz_bitstream_read_byte(blocks));
}
-unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
+static unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
{
return (hz_bitstream_read_byte(blocks) << 24)
| (hz_bitstream_read_byte(blocks) << 16)
| (hz_bitstream_read_byte(blocks));
}
-void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
+static void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
{
unsigned char *out;
out = (unsigned char *)outdata;
qboolean hasalpha;
// name of pic
char name[MAX_QPATH];
+ // allow to override/free the texture
+ qboolean allow_free_tex;
}
cachepic_t;
DRAWFLAG_MASK = 0xFF, // ONLY R_BeginPolygon()
DRAWFLAG_MIPMAP = 0x100 // ONLY R_BeginPolygon()
};
+#define DRAWFLAGS_BLEND (DRAWFLAG_ADDITIVE + DRAWFLAG_MODULATE + DRAWFLAG_2XMODULATE + DRAWFLAG_SCREEN)
typedef struct ft2_settings_s
{
# include <direct.h>
# include <io.h>
# include <shlobj.h>
+# include <sys/stat.h>
+# include <share.h>
#else
# include <pwd.h>
# include <sys/stat.h>
#endif
#include "quakedef.h"
+#include "thread.h"
#include "fs.h"
#include "wad.h"
# define lseek _lseeki64
#endif
-#if _MSC_VER >= 1400
// suppress deprecated warnings
-# include <sys/stat.h>
-# include <share.h>
+#if _MSC_VER >= 1400
# define read _read
# define write _write
# define close _close
*/
mempool_t *fs_mempool;
+void *fs_mutex = NULL;
searchpath_t *fs_searchpaths = NULL;
const char *const fs_checkgamedir_missing = "missing";
Unload the Zlib DLL
====================
*/
-void PK3_CloseLibrary (void)
+static void PK3_CloseLibrary (void)
{
#ifndef LINK_TO_ZLIB
Sys_UnloadLibrary (&zlib_dll);
Try to load the Zlib DLL
====================
*/
-qboolean PK3_OpenLibrary (void)
+static qboolean PK3_OpenLibrary (void)
{
#ifdef LINK_TO_ZLIB
return true;
Extract the end of the central directory from a PK3 package
====================
*/
-qboolean PK3_GetEndOfCentralDir (const char *packfile, int packhandle, pk3_endOfCentralDir_t *eocd)
+static qboolean PK3_GetEndOfCentralDir (const char *packfile, int packhandle, pk3_endOfCentralDir_t *eocd)
{
fs_offset_t filesize, maxsize;
unsigned char *buffer, *ptr;
Extract the file list from a PK3 file
====================
*/
-int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd)
+static int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd)
{
unsigned char *central_dir, *ptr;
unsigned int ind;
Create a package entry associated with a PK3 file
====================
*/
-pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qboolean silent)
+static pack_t *FS_LoadPackPK3FromFD (const char *packfile, int packhandle, qboolean silent)
{
pk3_endOfCentralDir_t eocd;
pack_t *pack;
Con_DPrintf("Added packfile %s (%i files)\n", packfile, real_nb_files);
return pack;
}
-pack_t *FS_LoadPackPK3 (const char *packfile)
+static pack_t *FS_LoadPackPK3 (const char *packfile)
{
int packhandle;
-#if _MSC_VER >= 1400
- _sopen_s(&packhandle, packfile, O_RDONLY | O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE);
-#else
- packhandle = open (packfile, O_RDONLY | O_BINARY);
-#endif
+ packhandle = FS_SysOpenFD (packfile, "rb", false);
if (packhandle < 0)
return NULL;
return FS_LoadPackPK3FromFD(packfile, packhandle, false);
Find where the true file data offset is
====================
*/
-qboolean PK3_GetTrueFileOffset (packfile_t *pfile, pack_t *pack)
+static qboolean PK3_GetTrueFileOffset (packfile_t *pfile, pack_t *pack)
{
unsigned char buffer [ZIP_LOCAL_CHUNK_BASE_SIZE];
fs_offset_t count;
============
*/
-void FS_Path_f (void)
+static void FS_Path_f (void)
{
searchpath_t *s;
*Loads the header and directory, adding the files at the beginning
*of the list so they override previous pack files.
*/
-pack_t *FS_LoadPackPAK (const char *packfile)
+static pack_t *FS_LoadPackPAK (const char *packfile)
{
dpackheader_t header;
int i, numpackfiles;
pack_t *pack;
dpackfile_t *info;
-#if _MSC_VER >= 1400
- _sopen_s(&packhandle, packfile, O_RDONLY | O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE);
-#else
- packhandle = open (packfile, O_RDONLY | O_BINARY);
-#endif
+ packhandle = FS_SysOpenFD(packfile, "rb", false);
if (packhandle < 0)
return NULL;
if(read (packhandle, (void *)&header, sizeof(header)) != sizeof(header))
Create a package entry associated with a directory file
====================
*/
-pack_t *FS_LoadPackVirtual (const char *dirname)
+static pack_t *FS_LoadPackVirtual (const char *dirname)
{
pack_t *pack;
pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
then loads and adds pak1.pak pak2.pak ...
================
*/
-void FS_AddGameDirectory (const char *dir)
+static void FS_AddGameDirectory (const char *dir)
{
int i;
stringlist_t list;
FS_AddGameHierarchy
================
*/
-void FS_AddGameHierarchy (const char *dir)
+static void FS_AddGameHierarchy (const char *dir)
{
+ char vabuf[1024];
// Add the common game directory
- FS_AddGameDirectory (va("%s%s/", fs_basedir, dir));
+ FS_AddGameDirectory (va(vabuf, sizeof(vabuf), "%s%s/", fs_basedir, dir));
if (*fs_userdir)
- FS_AddGameDirectory(va("%s%s/", fs_userdir, dir));
+ FS_AddGameDirectory(va(vabuf, sizeof(vabuf), "%s%s/", fs_userdir, dir));
}
FS_ClearSearchPath
================
*/
-void FS_ClearSearchPath (void)
+static void FS_ClearSearchPath (void)
{
// unload all packs and directory information, close all pack files
// (if a qfile is still reading a pack it won't be harmed because it used
qboolean fs_modified = false;
qboolean reset = false;
char gamedirbuf[MAX_INPUTLINE];
+ char vabuf[1024];
if (fs_searchpaths)
reset = true;
// update the com_modname (used server info)
strlcpy (com_modname, fs_gamedirs[i], sizeof (com_modname));
if(i)
- strlcat(gamedirbuf, va(" %s", fs_gamedirs[i]), sizeof(gamedirbuf));
+ strlcat(gamedirbuf, va(vabuf, sizeof(vabuf), " %s", fs_gamedirs[i]), sizeof(gamedirbuf));
else
strlcpy(gamedirbuf, fs_gamedirs[i], sizeof(gamedirbuf));
}
// If "-condebug" is in the command line, remove the previous log file
if (COM_CheckParm ("-condebug") != 0)
- unlink (va("%s/qconsole.log", fs_gamedir));
+ unlink (va(vabuf, sizeof(vabuf), "%s/qconsole.log", fs_gamedir));
// look for the pop.lmp file and set registered to true if it is found
if (FS_FileExists("gfx/pop.lmp"))
W_UnloadAll();
}
-void FS_Rescan_f(void)
+static void FS_Rescan_f(void)
{
FS_Rescan();
}
FS_ChangeGameDirs
================
*/
-extern void Host_SaveConfig (void);
-extern void Host_LoadConfig_f (void);
extern qboolean vid_opened;
-extern void VID_Stop(void);
qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean complain, qboolean failmissing)
{
int i;
FS_GameDir_f
================
*/
-void FS_GameDir_f (void)
+static void FS_GameDir_f (void)
{
int i;
int numgamedirs;
FS_ChangeGameDirs(numgamedirs, gamedirs, true, true);
}
-static const char *FS_SysCheckGameDir(const char *gamedir)
+static const char *FS_SysCheckGameDir(const char *gamedir, char *buf, size_t buflength)
{
- static char buf[8192];
qboolean success;
qfile_t *f;
stringlist_t list;
fs_offset_t n;
+ char vabuf[1024];
stringlistinit(&list);
listdirectory(&list, gamedir, "");
if(success)
{
- f = FS_SysOpen(va("%smodinfo.txt", gamedir), "r", false);
+ f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%smodinfo.txt", gamedir), "r", false);
if(f)
{
- n = FS_Read (f, buf, sizeof(buf) - 1);
+ n = FS_Read (f, buf, buflength - 1);
if(n >= 0)
buf[n] = 0;
else
const char *FS_CheckGameDir(const char *gamedir)
{
const char *ret;
+ char buf[8192];
+ char vabuf[1024];
if (FS_CheckNastyPath(gamedir, true))
return NULL;
- ret = FS_SysCheckGameDir(va("%s%s/", fs_userdir, gamedir));
+ ret = FS_SysCheckGameDir(va(vabuf, sizeof(vabuf), "%s%s/", fs_userdir, gamedir), buf, sizeof(buf));
if(ret)
{
if(!*ret)
{
// get description from basedir
- ret = FS_SysCheckGameDir(va("%s%s/", fs_basedir, gamedir));
+ ret = FS_SysCheckGameDir(va(vabuf, sizeof(vabuf), "%s%s/", fs_basedir, gamedir), buf, sizeof(buf));
if(ret)
return ret;
return "";
return ret;
}
- ret = FS_SysCheckGameDir(va("%s%s/", fs_basedir, gamedir));
+ ret = FS_SysCheckGameDir(va(vabuf, sizeof(vabuf), "%s%s/", fs_basedir, gamedir), buf, sizeof(buf));
if(ret)
return ret;
stringlist_t list, list2;
int i, j;
const char *info;
+ char vabuf[1024];
fs_all_gamedirs_count = 0;
if(fs_all_gamedirs)
Mem_Free(fs_all_gamedirs);
stringlistinit(&list);
- listdirectory(&list, va("%s/", fs_basedir), "");
- listdirectory(&list, va("%s/", fs_userdir), "");
+ listdirectory(&list, va(vabuf, sizeof(vabuf), "%s/", fs_basedir), "");
+ listdirectory(&list, va(vabuf, sizeof(vabuf), "%s/", fs_userdir), "");
stringlistsort(&list, false);
stringlistinit(&list2);
}
}
-int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t userdirsize)
+static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t userdirsize)
{
#if defined(__IPHONEOS__)
if (userdirmode == USERDIRMODE_HOME)
wchar_t *savedgamesdirw;
char savedgamesdir[MAX_OSPATH];
int fd;
-
+ char vabuf[1024];
+
userdir[0] = 0;
switch(userdirmode)
{
#else
int fd;
char *homedir;
+ char vabuf[1024];
userdir[0] = 0;
switch(userdirmode)
{
if (userdirmode == USERDIRMODE_NOHOME && strcmp(gamedirname1, "id1"))
return 0; // don't bother checking if the basedir folder is writable, it's annoying... unless it is Quake on Windows where NOHOME is the default preferred and we have to check for an error case
#endif
+
// see if we can write to this path (note: won't create path)
-#if _MSC_VER >= 1400
- _sopen_s(&fd, va("%s%s/config.cfg", userdir, gamedirname1), O_WRONLY | O_CREAT, _SH_DENYNO, _S_IREAD | _S_IWRITE); // note: no O_TRUNC here!
+#ifdef WIN32
+ // no access() here, we must try to open the file for appending
+ fd = FS_SysOpenFD(va(vabuf, sizeof(vabuf), "%s%s/config.cfg", userdir, gamedirname1), "a", false);
+ if(fd >= 0)
+ close(fd);
#else
- fd = open (va("%s%s/config.cfg", userdir, gamedirname1), O_WRONLY | O_CREAT, 0666); // note: no O_TRUNC here!
+ // on Unix, we don't need to ACTUALLY attempt to open the file
+ if(access(va(vabuf, sizeof(vabuf), "%s%s/", userdir, gamedirname1), W_OK | X_OK) >= 0)
+ fd = 1;
+ else
+ fd = 0;
#endif
if(fd >= 0)
{
- close(fd);
return 1; // good choice - the path exists and is writable
}
else
- return 0; // probably good - failed to write but maybe we need to create path
+ {
+ if (userdirmode == USERDIRMODE_NOHOME)
+ return -1; // path usually already exists, we lack permissions
+ else
+ return 0; // probably good - failed to write but maybe we need to create path
+ }
}
/*
if (split)
{
struct stat statresult;
+ char vabuf[1024];
// truncate to just after the .app/
split[5] = 0;
// see if gamedir exists in Resources
- if (stat(va("%s/Contents/Resources/%s", fs_basedir, gamedirname1), &statresult) == 0)
+ if (stat(va(vabuf, sizeof(vabuf), "%s/Contents/Resources/%s", fs_basedir, gamedirname1), &statresult) == 0)
{
// found gamedir inside Resources, use it
strlcat(fs_basedir, "Contents/Resources/", sizeof(fs_basedir));
// generate the searchpath
FS_Rescan();
+
+ if (Thread_HasThreads())
+ fs_mutex = Thread_CreateMutex();
}
void FS_Init_Commands(void)
// by the OS anyway)
FS_ClearSearchPath();
Mem_FreePool (&fs_mempool);
+ PK3_CloseLibrary ();
#ifdef WIN32
Sys_UnloadLibrary (&shfolder_dll);
Sys_UnloadLibrary (&shell32_dll);
Sys_UnloadLibrary (&ole32_dll);
#endif
+
+ if (fs_mutex)
+ Thread_DestroyMutex(fs_mutex);
}
int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking)
{
- int handle;
+ int handle = -1;
int mod, opt;
unsigned int ind;
+ qboolean dolock = false;
// Parse the mode string
switch (mode[0])
case 'b':
opt |= O_BINARY;
break;
+ case 'l':
+ dolock = true;
+ break;
default:
Con_Printf ("FS_SysOpen(%s, %s): unknown character in mode (%c)\n",
filepath, mode, mode[ind]);
if (nonblocking)
opt |= O_NONBLOCK;
-#if _MSC_VER >= 1400
- _sopen_s(&handle, filepath, mod | opt, _SH_DENYNO, _S_IREAD | _S_IWRITE);
+#ifdef WIN32
+# if _MSC_VER >= 1400
+ _sopen_s(&handle, filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
+# else
+ handle = _sopen (filepath, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
+# endif
#else
handle = open (filepath, mod | opt, 0666);
+ if(handle >= 0 && dolock)
+ {
+ struct flock l;
+ l.l_type = ((mod == O_RDONLY) ? F_RDLCK : F_WRLCK);
+ l.l_whence = SEEK_SET;
+ l.l_start = 0;
+ l.l_len = 0;
+ if(fcntl(handle, F_SETLK, &l) == -1)
+ {
+ close(handle);
+ handle = -1;
+ }
+ }
#endif
+
return handle;
}
Open a packed file using its package file descriptor
===========
*/
-qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
+static qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind)
{
packfile_t *pfile;
int dup_handle;
Look for a file in the search paths and open it in read-only mode
===========
*/
-qfile_t *FS_OpenReadFile (const char *filename, qboolean quiet, qboolean nonblocking, int symlinkLevels)
+static qfile_t *FS_OpenReadFile (const char *filename, qboolean quiet, qboolean nonblocking, int symlinkLevels)
{
searchpath_t *search;
int pack_ind;
*/
qfile_t* FS_OpenVirtualFile (const char* filepath, qboolean quiet)
{
+ qfile_t *result = NULL;
if (FS_CheckNastyPath(filepath, false))
{
Con_Printf("FS_OpenVirtualFile(\"%s\", %s): nasty filename rejected\n", filepath, quiet ? "true" : "false");
return NULL;
}
- return FS_OpenReadFile (filepath, quiet, false, 16);
+ if (fs_mutex) Thread_LockMutex(fs_mutex);
+ result = FS_OpenReadFile (filepath, quiet, false, 16);
+ if (fs_mutex) Thread_UnlockMutex(fs_mutex);
+ return result;
}
}
extern int con_linewidth;
-int FS_ListDirectory(const char *pattern, int oneperline)
+static int FS_ListDirectory(const char *pattern, int oneperline)
{
int numfiles;
int numcolumns;
qboolean FS_HasZlib(void);
+void FS_Init_SelfPack(void);
+void FS_Init(void);
+void FS_Shutdown(void);
+void FS_Init_Commands(void);
+
#endif
return (ft2_font_t *)Mem_Alloc(font_mempool, sizeof(ft2_font_t));
}
-qboolean Font_Attach(ft2_font_t *font, ft2_attachment_t *attachment)
+static qboolean Font_Attach(ft2_font_t *font, ft2_attachment_t *attachment)
{
ft2_attachment_t *na;
{
int s, count, i;
ft2_font_t *ft2, *fbfont, *fb;
+ char vabuf[1024];
ft2 = Font_Alloc();
if (!ft2)
if (!Font_LoadFile(dpfnt->fallbacks[i], dpfnt->fallback_faces[i], &dpfnt->settings, fb))
{
- if(!FS_FileExists(va("%s.tga", dpfnt->fallbacks[i])))
- if(!FS_FileExists(va("%s.png", dpfnt->fallbacks[i])))
- if(!FS_FileExists(va("%s.jpg", dpfnt->fallbacks[i])))
- if(!FS_FileExists(va("%s.pcx", dpfnt->fallbacks[i])))
+ if(!FS_FileExists(va(vabuf, sizeof(vabuf), "%s.tga", dpfnt->fallbacks[i])))
+ if(!FS_FileExists(va(vabuf, sizeof(vabuf), "%s.png", dpfnt->fallbacks[i])))
+ if(!FS_FileExists(va(vabuf, sizeof(vabuf), "%s.jpg", dpfnt->fallbacks[i])))
+ if(!FS_FileExists(va(vabuf, sizeof(vabuf), "%s.pcx", dpfnt->fallbacks[i])))
Con_Printf("Failed to load font %s for fallback %i of font %s\n", dpfnt->fallbacks[i], i, name);
Mem_Free(fb);
continue;
return true;
}
-void Font_Postprocess_Update(ft2_font_t *fnt, int bpp, int w, int h)
+static void Font_Postprocess_Update(ft2_font_t *fnt, int bpp, int w, int h)
{
int needed, x, y;
float gausstable[2*POSTPROCESS_MAXRADIUS+1];
}
}
-void Font_Postprocess(ft2_font_t *fnt, unsigned char *imagedata, int pitch, int bpp, int w, int h, int *pad_l, int *pad_r, int *pad_t, int *pad_b)
+static void Font_Postprocess(ft2_font_t *fnt, unsigned char *imagedata, int pitch, int bpp, int w, int h, int *pad_l, int *pad_r, int *pad_t, int *pad_b)
{
int x, y;
int tp;
FT_Int32 load_flags;
int gpad_l, gpad_r, gpad_t, gpad_b;
+ char vabuf[1024];
int pitch;
int gR, gC; // glyph position: row and column
data[x*4+0] = data[x*4+2];
data[x*4+2] = b;
}
- Image_WriteTGABGRA(va("%s.tga", map_identifier), w, h, data);
+ Image_WriteTGABGRA(va(vabuf, sizeof(vabuf), "%s.tga", map_identifier), w, h, data);
+#ifndef USE_GLES2
if (r_font_compress.integer && qglGetCompressedTexImageARB && tex)
- R_SaveTextureDDSFile(tex, va("dds/%s.dds", map_identifier), r_texture_dds_save.integer < 2, true);
+ R_SaveTextureDDSFile(tex, va(vabuf, sizeof(vabuf), "dds/%s.dds", map_identifier), r_texture_dds_save.integer < 2, true);
+#endif
}
}
extern D3DCAPS9 vid_d3d9caps;
#endif
+// on GLES we have to use some proper #define's
+#ifndef GL_FRAMEBUFFER
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#endif
+#ifndef GL_COLOR_ATTACHMENT1
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#endif
+#ifndef GL_ARRAY_BUFFER
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#endif
+//#ifndef GL_VERTEX_ARRAY
+//#define GL_VERTEX_ARRAY 0x8074
+//#define GL_COLOR_ARRAY 0x8076
+//#define GL_TEXTURE_COORD_ARRAY 0x8078
+//#endif
+#ifndef GL_TEXTURE0
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#endif
+
+#ifndef GL_TEXTURE_3D
+#define GL_TEXTURE_3D 0x806F
+#endif
+#ifndef GL_TEXTURE_CUBE_MAP
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#endif
+//#ifndef GL_MODELVIEW
+//#define GL_MODELVIEW 0x1700
+//#endif
+//#ifndef GL_PROJECTION
+//#define GL_PROJECTION 0x1701
+//#endif
+//#ifndef GL_DECAL
+//#define GL_DECAL 0x2101
+//#endif
+//#ifndef GL_INTERPOLATE
+//#define GL_INTERPOLATE 0x8575
+//#endif
+
+
#define MAX_RENDERTARGETS 4
cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
break;
#endif
-#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
- case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
+#ifdef GL_INVALID_FRAMEBUFFER_OPERATION
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
break;
#endif
int quadelement3i[QUADELEMENTS_MAXQUADS*6];
unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
-void GL_VBOStats_f(void)
+static void GL_VBOStats_f(void)
{
GL_Mesh_ListVBOs(true);
}
case RENDERPATH_GLES2:
// fetch current fbo here (default fbo is not 0 on some GLES devices)
if (vid.support.ext_framebuffer_object)
- qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
+ qglGetIntegerv(GL_FRAMEBUFFER_BINDING, &gl_state.defaultframebufferobject);
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
case RENDERPATH_GL13:
case RENDERPATH_GL11:
case RENDERPATH_GLES1:
+#ifdef GL_PROJECTION
CHECKGLERROR
qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
// Load the projection matrix into OpenGL
Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
qglLoadMatrixf(m);CHECKGLERROR
qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+#endif
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
{
gl_state.vertexbufferobject = bufferobject;
CHECKGLERROR
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
+ qglBindBufferARB(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR
}
}
{
gl_state.elementbufferobject = bufferobject;
CHECKGLERROR
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
+ qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, bufferobject);CHECKGLERROR
}
}
+static const GLuint drawbuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
{
- int temp;
switch(vid.renderpath)
{
case RENDERPATH_GL11:
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
- if (!vid.support.ext_framebuffer_object)
- return 0;
- qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
- R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
- if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
- if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
- if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
- if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
- if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
- return temp;
+ if (vid.support.arb_framebuffer_object)
+ {
+ int temp;
+ GLuint status;
+ qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
+ R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
+ // GL_ARB_framebuffer_object (GL3-class hardware) - depth stencil attachment
+ if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
+ if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
+ if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
+ if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
+ if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
+ if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
+ if (colortexture && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
+ if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
+ if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
+ if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
+
+ if (colortexture4 && qglDrawBuffersARB)
+ {
+ qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ else if (colortexture3 && qglDrawBuffersARB)
+ {
+ qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ else if (colortexture2 && qglDrawBuffersARB)
+ {
+ qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ else if (colortexture && qglDrawBuffer)
+ {
+ qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
+ qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
+ }
+ else if (qglDrawBuffer)
+ {
+ qglDrawBuffer(GL_NONE);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
+ qglDeleteFramebuffers(1, (GLuint*)&temp);
+ temp = 0;
+ }
+ return temp;
+ }
+ else if (vid.support.ext_framebuffer_object)
+ {
+ int temp;
+ GLuint status;
+ qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
+ R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
+ // GL_EXT_framebuffer_object (GL2-class hardware) - no depth stencil attachment, let it break stencil
+ if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
+ if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
+ if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
+ if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
+ if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
+ if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
+ if (colortexture && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
+ if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
+ if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
+ if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
+
+ if (colortexture4 && qglDrawBuffersARB)
+ {
+ qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ else if (colortexture3 && qglDrawBuffersARB)
+ {
+ qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ else if (colortexture2 && qglDrawBuffersARB)
+ {
+ qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ else if (colortexture && qglDrawBuffer)
+ {
+ qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
+ qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
+ }
+ else if (qglDrawBuffer)
+ {
+ qglDrawBuffer(GL_NONE);CHECKGLERROR
+ qglReadBuffer(GL_NONE);CHECKGLERROR
+ }
+ status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
+ qglDeleteFramebuffers(1, (GLuint*)&temp);
+ temp = 0;
+ }
+ return temp;
+ }
+ return 0;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
if (fbo)
- qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
+ qglDeleteFramebuffers(1, (GLuint*)&fbo);
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
#ifdef SUPPORTD3D
void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
{
-// LordHavoc: for some weird reason the redundant SetDepthStencilSurface calls are necessary (otherwise the lights fail depth test, as if they were using the shadowmap depth surface and render target still)
- if (gl_state.d3drt_depthsurface == depthsurface && gl_state.d3drt_colorsurfaces[0] == colorsurface0 && gl_state.d3drt_colorsurfaces[1] == colorsurface1 && gl_state.d3drt_colorsurfaces[2] == colorsurface2 && gl_state.d3drt_colorsurfaces[3] == colorsurface3)
- return;
-
gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
if (gl_state.d3drt_depthsurface != depthsurface)
{
}
#endif
-void R_Mesh_ResetRenderTargets(void)
-{
- switch(vid.renderpath)
- {
- case RENDERPATH_GL11:
- case RENDERPATH_GL13:
- case RENDERPATH_GL20:
- case RENDERPATH_GLES1:
- case RENDERPATH_GLES2:
- if (gl_state.framebufferobject)
- {
- gl_state.framebufferobject = 0;
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
- }
- break;
- case RENDERPATH_D3D9:
-#ifdef SUPPORTD3D
- R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
-#endif
- break;
- case RENDERPATH_D3D10:
- Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
- case RENDERPATH_D3D11:
- Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
- case RENDERPATH_SOFT:
- DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
- break;
- }
-}
-
void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
{
unsigned int i;
if (gl_state.framebufferobject != fbo)
{
gl_state.framebufferobject = fbo;
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
+ qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
}
break;
case RENDERPATH_D3D9:
// TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
if (fbo)
{
- IDirect3DSurface9 *colorsurfaces[4];
- for (i = 0;i < 4;i++)
+ IDirect3DSurface9 *surfaces[5];
+ for (i = 0;i < 5;i++)
{
- colorsurfaces[i] = NULL;
+ surfaces[i] = NULL;
if (textures[i])
- IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
+ {
+ if (textures[i]->d3dsurface)
+ surfaces[i] = (IDirect3DSurface9 *)textures[i]->d3dsurface;
+ else
+ IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &surfaces[i]);
+ }
}
// set the render targets for real
- R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
+ R_Mesh_SetRenderTargetsD3D9(surfaces[4], surfaces[0], surfaces[1], surfaces[2], surfaces[3]);
// release the texture surface levels (they won't be lost while bound...)
- for (i = 0;i < 4;i++)
- if (textures[i])
- IDirect3DSurface9_Release(colorsurfaces[i]);
+ for (i = 0;i < 5;i++)
+ if (textures[i] && !textures[i]->d3dsurface)
+ IDirect3DSurface9_Release(surfaces[i]);
}
else
R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
}
#endif
-extern cvar_t r_transparent_alphatocoverage;
-
static void GL_Backend_ResetState(void)
{
unsigned int i;
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+#ifdef GL_ALPHA_TEST
CHECKGLERROR
qglColorMask(1, 1, 1, 1);CHECKGLERROR
if (vid.support.arb_vertex_buffer_object)
{
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ qglBindBufferARB(GL_ARRAY_BUFFER, 0);
+ qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
}
if (vid.support.ext_framebuffer_object)
{
- //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ //qglBindRenderbuffer(GL_RENDERBUFFER, 0);
+ qglBindFramebuffer(GL_FRAMEBUFFER, 0);
}
qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
qglColor4f(1, 1, 1, 1);CHECKGLERROR
if (vid.support.ext_framebuffer_object)
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
+ qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject);
gl_state.unit = MAX_TEXTUREUNITS;
gl_state.clientunit = MAX_TEXTUREUNITS;
}
if (vid.support.arb_texture_cube_map)
{
- qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
- qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
+ qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
+ qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
}
GL_BindVBO(0);
qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
}
CHECKGLERROR
+#endif
break;
case RENDERPATH_SOFT:
DPSOFTRAST_ColorMask(1,1,1,1);
qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
if (vid.support.arb_vertex_buffer_object)
{
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ qglBindBufferARB(GL_ARRAY_BUFFER, 0);
+ qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
}
if (vid.support.ext_framebuffer_object)
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
+ qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.defaultframebufferobject);
qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
}
if (vid.support.arb_texture_cube_map)
{
- qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
+ qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
}
}
for (i = 0;i < vid.texarrayunits;i++)
if (qglActiveTexture)
{
CHECKGLERROR
- qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
+ qglActiveTexture(GL_TEXTURE0 + gl_state.unit);
CHECKGLERROR
}
break;
if (qglActiveTexture)
{
CHECKGLERROR
- qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
+ qglClientActiveTexture(GL_TEXTURE0 + gl_state.clientunit);
CHECKGLERROR
}
break;
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef USE_GLES2
+ qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]);
+#else
qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
+#endif
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
qglStencilMask(writemask);CHECKGLERROR
qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
- qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
+ qglStencilFuncSeparate(GL_FRONT, frontcompare, comparereference, comparereference);CHECKGLERROR
+ qglStencilFuncSeparate(GL_BACK, backcompare, comparereference, comparereference);CHECKGLERROR
}
else if (vid.support.ext_stencil_two_side)
{
+#ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
qglStencilMask(writemask);CHECKGLERROR
qglStencilMask(writemask);CHECKGLERROR
qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
+#endif
}
break;
case RENDERPATH_D3D9:
}
if (vid.support.ext_stencil_two_side)
{
+#ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
+#endif
}
qglStencilMask(writemask);CHECKGLERROR
qglStencilOp(fail, zfail, zpass);CHECKGLERROR
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+#ifdef GL_ALPHA_TEST
// only fixed function uses alpha test, other paths use pixel kill capability in shaders
CHECKGLERROR
if (gl_state.alphatest)
{
qglDisable(GL_ALPHA_TEST);CHECKGLERROR
}
+#endif
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_SOFT:
break;
case RENDERPATH_GL20:
+#ifdef GL_SAMPLE_ALPHA_TO_COVERAGE_ARB
// alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
CHECKGLERROR
if (gl_state.alphatocoverage)
qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
// qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
}
+#endif
break;
}
}
}
if (mask & GL_DEPTH_BUFFER_BIT)
{
+#ifdef USE_GLES2
+ qglClearDepthf(depthvalue);CHECKGLERROR
+#else
qglClearDepth(depthvalue);CHECKGLERROR
+#endif
}
if (mask & GL_STENCIL_BUFFER_BIT)
{
void R_Mesh_Start(void)
{
BACKENDACTIVECHECK
- R_Mesh_ResetRenderTargets();
+ R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
R_Mesh_SetUseVBO();
if (gl_printcheckerror.integer && !gl_paranoid.integer)
{
}
}
-qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
+static qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
{
int shaderobject;
int shadercompiled;
qglCompileShader(shaderobject);CHECKGLERROR
qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
- if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
+ if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning") || developer_extra.integer))
{
int i, j, pretextlines = 0;
for (i = 0;i < numstrings - 1;i++)
qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
+#ifndef USE_GLES2
if(vid.support.gl20shaders130)
qglBindFragDataLocation(programobject, 0, "dp_FragColor");
+#endif
if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
goto cleanup;
qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
if (linklog[0])
{
- if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
+ if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer)
Con_DPrintf("program link log:\n%s\n", linklog);
// software vertex shader is ok but software fragment shader is WAY
// too slow, fail program if so.
CHECKGLERROR
}
-void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
-{
- int i;
- if (offset)
- {
- for (i = 0;i < count;i++)
- *out++ = *in++ + offset;
- }
- else
- memcpy(out, in, sizeof(*out) * count);
-}
-
// renders triangles using vertices from the active arrays
int paranoidblah = 0;
void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset)
CHECKGLERROR
if (gl_mesh_testmanualfeeding.integer)
{
+#ifndef USE_GLES2
unsigned int i, j, element;
const GLfloat *p;
qglBegin(GL_TRIANGLES);
if (vid.texarrayunits > 1)
{
if (gl_state.units[j].pointer_texcoord_components == 4)
- qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
+ qglMultiTexCoord4f(GL_TEXTURE0 + j, p[0], p[1], p[2], p[3]);
else if (gl_state.units[j].pointer_texcoord_components == 3)
- qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
+ qglMultiTexCoord3f(GL_TEXTURE0 + j, p[0], p[1], p[2]);
else if (gl_state.units[j].pointer_texcoord_components == 2)
- qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
+ qglMultiTexCoord2f(GL_TEXTURE0 + j, p[0], p[1]);
else
- qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
+ qglMultiTexCoord1f(GL_TEXTURE0 + j, p[0]);
}
else
{
if (vid.texarrayunits > 1)
{
if (gl_state.units[j].pointer_texcoord_components == 4)
- qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
+ qglMultiTexCoord4f(GL_TEXTURE0 + j, s[0], s[1], s[2], s[3]);
else if (gl_state.units[j].pointer_texcoord_components == 3)
- qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
+ qglMultiTexCoord3f(GL_TEXTURE0 + j, s[0], s[1], s[2]);
else if (gl_state.units[j].pointer_texcoord_components == 2)
- qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
+ qglMultiTexCoord2f(GL_TEXTURE0 + j, s[0], s[1]);
else if (gl_state.units[j].pointer_texcoord_components == 1)
- qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
+ qglMultiTexCoord1f(GL_TEXTURE0 + j, s[0]);
}
else
{
if (vid.texarrayunits > 1)
{
if (gl_state.units[j].pointer_texcoord_components == 4)
- qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
+ qglMultiTexCoord4f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2], sb[3]);
else if (gl_state.units[j].pointer_texcoord_components == 3)
- qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
+ qglMultiTexCoord3f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2]);
else if (gl_state.units[j].pointer_texcoord_components == 2)
- qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
+ qglMultiTexCoord2f(GL_TEXTURE0 + j, sb[0], sb[1]);
else if (gl_state.units[j].pointer_texcoord_components == 1)
- qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
+ qglMultiTexCoord1f(GL_TEXTURE0 + j, sb[0]);
}
else
{
}
qglEnd();
CHECKGLERROR
+#endif
}
else if (bufferobject3s)
{
GL_BindEBO(bufferobject3s);
+#ifndef USE_GLES2
if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
{
qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
CHECKGLERROR
}
else
+#endif
{
qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
CHECKGLERROR
else if (bufferobject3i)
{
GL_BindEBO(bufferobject3i);
+#ifndef USE_GLES2
if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
{
qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
CHECKGLERROR
}
else
+#endif
{
qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
CHECKGLERROR
else if (element3s)
{
GL_BindEBO(0);
+#ifndef USE_GLES2
if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
{
qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
CHECKGLERROR
}
else
+#endif
{
qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
CHECKGLERROR
else if (element3i)
{
GL_BindEBO(0);
+#ifndef USE_GLES2
if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
{
qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
CHECKGLERROR
}
else
+#endif
{
qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
CHECKGLERROR
GLint attribsize;
GLenum attribtype;
GLchar attribname[1024];
- r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
+ r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
+ if (r != GL_FRAMEBUFFER_COMPLETE)
Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
#ifndef GL_CURRENT_PROGRAM
#define GL_CURRENT_PROGRAM 0x8B8D
// restores backend state, used when done with 3D rendering
void R_Mesh_Finish(void)
{
- R_Mesh_ResetRenderTargets();
+ R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
}
r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
GL_BindEBO(buffer->bufferobject);
else
GL_BindVBO(buffer->bufferobject);
- qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
+ qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+#ifdef GL_MODELVIEW
CHECKGLERROR
if (pointer)
{
qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
}
}
+#endif
break;
case RENDERPATH_GL20:
case RENDERPATH_GLES2:
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+#ifdef GL_MODELVIEW
CHECKGLERROR
if (pointer)
{
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
}
}
+#endif
break;
case RENDERPATH_GL20:
case RENDERPATH_GLES2:
return unit->t2d;
if (id == GL_TEXTURE_3D)
return unit->t3d;
- if (id == GL_TEXTURE_CUBE_MAP_ARB)
+ if (id == GL_TEXTURE_CUBE_MAP)
return unit->tcubemap;
return 0;
}
{
case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
- case GL_TEXTURE_CUBE_MAP_ARB: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR}break;
+ case GL_TEXTURE_CUBE_MAP: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR}break;
}
break;
case RENDERPATH_GL11:
case GL_TEXTURE_3D:
tex3d = texnum;
break;
- case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_TEXTURE_CUBE_MAP:
texcubemap = texnum;
break;
}
{
if (unit->tcubemap == 0)
{
- qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ qglEnable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
}
}
else
{
if (unit->tcubemap)
{
- qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
+ qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
}
}
unit->tcubemap = texcubemap;
- qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
+ qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR
}
break;
case RENDERPATH_D3D9:
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef GL_MODELVIEW
if (matrix && matrix->m[3][3])
{
// texmatrix specified, check if it is different
qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
}
}
+#endif
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
break;
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+#ifdef GL_TEXTURE_ENV
// GL_ARB_texture_env_combine
if (!combinergb)
combinergb = GL_MODULATE;
if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
{
if (combinergb == GL_DECAL)
- combinergb = GL_INTERPOLATE_ARB;
- if (unit->combine != GL_COMBINE_ARB)
+ combinergb = GL_INTERPOLATE;
+ if (unit->combine != GL_COMBINE)
{
- unit->combine = GL_COMBINE_ARB;
+ unit->combine = GL_COMBINE;
GL_ActiveTexture(unitnum);
- qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
- qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
+ qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);CHECKGLERROR
+ qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE mode
}
if (unit->combinergb != combinergb)
{
unit->combinergb = combinergb;
GL_ActiveTexture(unitnum);
- qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, unit->combinergb);CHECKGLERROR
}
if (unit->combinealpha != combinealpha)
{
unit->combinealpha = combinealpha;
GL_ActiveTexture(unitnum);
- qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, unit->combinealpha);CHECKGLERROR
}
if (unit->rgbscale != rgbscale)
{
unit->rgbscale = rgbscale;
GL_ActiveTexture(unitnum);
- qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
+ qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, unit->rgbscale);CHECKGLERROR
}
if (unit->alphascale != alphascale)
{
qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
}
}
+#endif
break;
case RENDERPATH_GL11:
// normal GL texenv
+#ifdef GL_TEXTURE_ENV
if (!combinergb)
combinergb = GL_MODULATE;
if (unit->combine != combinergb)
GL_ActiveTexture(unitnum);
qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
}
+#endif
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
- qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+ qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT);
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
- qglBlendEquationEXT(GL_FUNC_ADD_EXT);
+ qglBlendEquationEXT(GL_FUNC_ADD);
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels);
int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4);
void R_Mesh_DestroyFramebufferObject(int fbo);
-void R_Mesh_ResetRenderTargets(void);
-void R_Mesh_SetMainRenderTargets(void);
void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4);
unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int geometrystrings_count, const char **geometrystrings_list, int fragmentstrings_count, const char **fragmentstrings_list);
qboolean ddshasalpha;
float ddsavgcolor[4];
qboolean loaded = false;
+ char vabuf[1024];
texflags = TEXF_ALPHA;
if (!(cachepicflags & CACHEPICFLAG_NOCLAMP))
return cachepics; // return the first one
}
pic = cachepics + (numcachepics++);
+ memset(pic, 0, sizeof(*pic));
strlcpy (pic->name, path, sizeof(pic->name));
// link into list
pic->chain = cachepichash[hashkey];
cachepichash[hashkey] = pic;
reload:
+ // TODO why does this crash?
+ if(pic->allow_free_tex && pic->tex)
+ R_PurgeTexture(pic->tex);
+
// check whether it is an dynamic texture (if so, we can directly use its texture handler)
pic->flags = cachepicflags;
pic->tex = CL_GetDynTexture( path );
// if so, set the width/height, too
if( pic->tex ) {
+ pic->allow_free_tex = false;
pic->width = R_TextureWidth(pic->tex);
pic->height = R_TextureHeight(pic->tex);
// we're done now (early-out)
return pic;
}
+ pic->allow_free_tex = true;
+
pic->hasalpha = true; // assume alpha unless we know it has none
pic->texflags = texflags;
pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT);
pic->lastusedframe = draw_frame;
// load a high quality image from disk if possible
- if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0)))
+ if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0)))
{
// note this loads even if autoload is true, otherwise we can't get the width/height
loaded = true;
if (!pic->autoload)
{
pic->tex = R_LoadTexture2D(drawtexturepool, pic->name, image_width, image_height, pixels, vid.sRGB2D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, pic->texflags & (pic->hasalpha ? ~0 : ~TEXF_ALPHA), -1, NULL);
+#ifndef USE_GLES2
if (r_texture_dds_save.integer && qglGetCompressedTexImageARB && pic->tex)
- R_SaveTextureDDSFile(pic->tex, va("dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+ R_SaveTextureDDSFile(pic->tex, va(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+#endif
}
}
if (!loaded)
pic->tex = draw_generatepic(pic->name, (cachepicflags & CACHEPICFLAG_QUIET) != 0);
pic->width = R_TextureWidth(pic->tex);
pic->height = R_TextureHeight(pic->tex);
+ pic->allow_free_tex = (pic->tex != r_texture_notexture);
}
return pic;
rtexture_t *Draw_GetPicTexture(cachepic_t *pic)
{
+ char vabuf[1024];
if (pic->autoload && !pic->tex)
{
if (pic->tex == NULL && r_texture_dds_load.integer != 0)
{
qboolean ddshasalpha;
float ddsavgcolor[4];
- pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0);
+ pic->tex = R_LoadTextureDDSFile(drawtexturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0);
}
if (pic->tex == NULL)
{
pic->tex = loadtextureimage(drawtexturepool, pic->name, false, pic->texflags, true, vid.sRGB2D);
+#ifndef USE_GLES2
if (r_texture_dds_save.integer && qglGetCompressedTexImageARB && pic->tex)
- R_SaveTextureDDSFile(pic->tex, va("dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+ R_SaveTextureDDSFile(pic->tex, va(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+#endif
}
if (pic->tex == NULL && !strncmp(pic->name, "gfx/", 4))
{
pic->tex = loadtextureimage(drawtexturepool, pic->name+4, false, pic->texflags, true, vid.sRGB2D);
+#ifndef USE_GLES2
if (r_texture_dds_save.integer && qglGetCompressedTexImageARB && pic->tex)
- R_SaveTextureDDSFile(pic->tex, va("dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+ R_SaveTextureDDSFile(pic->tex, va(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+#endif
}
if (pic->tex == NULL)
pic->tex = draw_generatepic(pic->name, true);
}
else
{
- if (pic == NULL)
+ if (numcachepics == MAX_CACHED_PICS)
{
- if (numcachepics == MAX_CACHED_PICS)
- {
- Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
- // FIXME: support NULL in callers?
- return cachepics; // return the first one
- }
- pic = cachepics + (numcachepics++);
- strlcpy (pic->name, picname, sizeof(pic->name));
- // link into list
- pic->chain = cachepichash[hashkey];
- cachepichash[hashkey] = pic;
+ Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
+ // FIXME: support NULL in callers?
+ return cachepics; // return the first one
}
+ pic = cachepics + (numcachepics++);
+ memset(pic, 0, sizeof(*pic));
+ strlcpy (pic->name, picname, sizeof(pic->name));
+ // link into list
+ pic->chain = cachepichash[hashkey];
+ cachepichash[hashkey] = pic;
}
pic->flags = CACHEPICFLAG_NEWPIC; // disable texflags checks in Draw_CachePic
pic->width = width;
pic->height = height;
- if (pic->tex)
+ if (pic->allow_free_tex && pic->tex)
R_FreeTexture(pic->tex);
pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels_bgra, TEXTYPE_BGRA, (alpha ? TEXF_ALPHA : 0), -1, NULL);
return pic;
ch = 0;
while(ch < 256)
{
- if(!COM_ParseToken_Simple(&p, false, false))
+ if(!COM_ParseToken_Simple(&p, false, false, true))
return;
switch(*com_token)
default:
if(!strcmp(com_token, "extraspacing"))
{
- if(!COM_ParseToken_Simple(&p, false, false))
+ if(!COM_ParseToken_Simple(&p, false, false, true))
return;
extraspacing = atof(com_token);
}
else if(!strcmp(com_token, "scale"))
{
- if(!COM_ParseToken_Simple(&p, false, false))
+ if(!COM_ParseToken_Simple(&p, false, false, true))
return;
fnt->settings.scale = atof(com_token);
}
else
{
Con_Printf("Warning: skipped unknown font property %s\n", com_token);
- if(!COM_ParseToken_Simple(&p, false, false))
+ if(!COM_ParseToken_Simple(&p, false, false, true))
return;
}
break;
static void gl_draw_start(void)
{
int i;
+ char vabuf[1024];
drawtexturepool = R_AllocTexturePool();
numcachepics = 0;
// load default font textures
for(i = 0; i < dp_fonts.maxsize; ++i)
if (dp_fonts.f[i].title[0])
- LoadFont(false, va("gfx/font_%s", dp_fonts.f[i].title), &dp_fonts.f[i], 1, 0);
+ LoadFont(false, va(vabuf, sizeof(vabuf), "gfx/font_%s", dp_fonts.f[i].title), &dp_fonts.f[i], 1, 0);
// draw the loading screen so people have something to see in the newly opened window
SCR_UpdateLoadingScreen(true);
R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap, NULL, NULL);
}
-static void _DrawQ_Setup(void)
+static void _DrawQ_Setup(void) // see R_ResetViewRendering2D
{
- r_viewport_t viewport;
if (r_refdef.draw2dstage == 1)
return;
r_refdef.draw2dstage = 1;
- CHECKGLERROR
- R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
- R_Mesh_ResetRenderTargets();
- R_SetViewport(&viewport);
- GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
- GL_DepthFunc(GL_LEQUAL);
- GL_PolygonOffset(0,0);
- GL_CullFace(GL_NONE);
- R_EntityMatrix(&identitymatrix);
- GL_DepthRange(0, 1);
- GL_PolygonOffset(0, 0);
- GL_DepthTest(false);
- GL_Color(1,1,1,1);
+ R_ResetViewRendering2D_Common(0, NULL, NULL, vid_conwidth.integer, vid_conheight.integer);
}
qboolean r_draw2d_force = false;
-void _DrawQ_SetupAndProcessDrawFlag(int flags, cachepic_t *pic, float alpha)
+static void _DrawQ_SetupAndProcessDrawFlag(int flags, cachepic_t *pic, float alpha)
{
_DrawQ_Setup();
- CHECKGLERROR
if(!r_draw2d.integer && !r_draw2d_force)
return;
DrawQ_ProcessDrawFlag(flags, (alpha < 1) || (pic && pic->hasalpha));
width = pic->width;
if (height == 0)
height = pic->height;
- R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
#if 0
// AK07: lets be texel correct on the corners
#endif
}
else
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
floats[0] = floats[9] = x;
width = pic->width;
if (height == 0)
height = pic->height;
- R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
}
else
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
return;
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
floats[0] = floats[9] = x;
// R_Mesh_ResetTextureState();
if (!fontmap)
R_Mesh_TexBind(0, fnt->tex);
- R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
ac = color4f;
at = texcoord2f;
at = texcoord2f;
av = vertex3f;
}
- R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
map = ft2_oldstyle_map;
}
}
break;
}
}
- R_SetupShader_Generic(map->pic->tex, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(map->pic->tex, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
}
mapch = ch - map->start;
width = pic->width;
if (height == 0)
height = pic->height;
- R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
}
else
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
floats[0] = floats[9] = x;
void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags, qboolean hasalpha)
{
_DrawQ_Setup();
- CHECKGLERROR
if(!r_draw2d.integer && !r_draw2d_force)
return;
DrawQ_ProcessDrawFlag(flags, hasalpha);
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(mesh->texture, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(mesh->texture, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
R_Mesh_PrepareVertices_Generic_Arrays(mesh->num_vertices, mesh->data_vertex3f, mesh->data_color4f, mesh->data_texcoord2f);
R_Mesh_Draw(0, mesh->num_vertices, 0, mesh->num_triangles, mesh->data_element3i, NULL, 0, mesh->data_element3s, NULL, 0);
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GL20:
+#ifndef USE_GLES2
CHECKGLERROR
qglBegin(GL_LINE_LOOP);
for (num = 0;num < mesh->num_vertices;num++)
}
qglEnd();
CHECKGLERROR
+#endif
break;
case RENDERPATH_D3D9:
//Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
if(!r_draw2d.integer && !r_draw2d_force)
return;
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
switch(vid.renderpath)
{
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GL20:
+#ifndef USE_GLES2
CHECKGLERROR
//qglLineWidth(width);CHECKGLERROR
qglVertex2f(x2, y2);
qglEnd();
CHECKGLERROR
+#endif
break;
case RENDERPATH_D3D9:
//Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
case RENDERPATH_GL20:
CHECKGLERROR
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
//qglLineWidth(width);CHECKGLERROR
}
// all the blends ignore depth
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture(true, true);
GL_DepthMask(true);
GL_DepthRange(0, 1);
GL_PolygonOffset(0, 0);
//
r_refdef_t r_refdef;
-cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
-cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
-cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
-cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
-cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
-cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
-cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
+cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
+cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
+cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
+cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
+cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
+cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
+cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
+cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
+cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
+cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
+cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
// TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
+cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
+cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
+cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
+cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
+cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
+cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
+cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
+cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
+cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
+
cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
-cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
-cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
-cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
+cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
+cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
+cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
extern cvar_t v_glslgamma;
+extern cvar_t v_glslgamma_2d;
extern qboolean v_flipped_state;
-static struct r_bloomstate_s
-{
- qboolean enabled;
- qboolean hdr;
-
- int bloomwidth, bloomheight;
-
- textype_t texturetype;
- int viewfbo; // used to check if r_viewfbo cvar has changed
-
- int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
- rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
- rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
-
- int screentexturewidth, screentextureheight;
- rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
-
- int bloomtexturewidth, bloomtextureheight;
- rtexture_t *texture_bloom;
-
- // arrays for rendering the screen passes
- float screentexcoord2f[8];
- float bloomtexcoord2f[8];
- float offsettexcoord2f[8];
-
- r_viewport_t viewport;
-}
-r_bloomstate;
-
-r_waterstate_t r_waterstate;
+r_framebufferstate_t r_fb;
/// shadow volume bsp struct with automatically growing nodes buffer
svbsp_t r_svbsp;
data[2] = 128; // normal X
data[1] = 128; // normal Y
data[0] = 255; // normal Z
- data[3] = 128; // height
+ data[3] = 255; // height
r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
data[0] = 255;
data[1] = 255;
{"#define USEOFFSETMAPPING\n", " offsetmapping"},
{"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
{"#define USESHADOWMAP2D\n", " shadowmap2d"},
- {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
- {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
- {"#define USESHADOWSAMPLER\n", " shadowsampler"},
- {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
+ {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"}, // TODO make this a static parm
+ {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, // TODO make this a static parm
+ {"#define USESHADOWSAMPLER\n", " shadowsampler"}, // TODO make this a static parm
+ {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
{"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
{"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
{"#define USEALPHAKILL\n", " alphakill"},
{"#define USEREFLECTCUBE\n", " reflectcube"},
{"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
{"#define USEBOUNCEGRID\n", " bouncegrid"},
- {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
+ {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
{"#define USETRIPPY\n", " trippy"},
+ {"#define USEDEPTHRGB\n", " depthrgb"},
};
// NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
{
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
- {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
+ {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
+ {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
+ {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
{"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
{"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
{"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
+ {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
+ {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
{"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
{"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
{"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
int tex_Texture_Reflection;
int tex_Texture_ShadowMap2D;
int tex_Texture_CubeProjection;
- int tex_Texture_ScreenDepth;
int tex_Texture_ScreenNormalMap;
int tex_Texture_ScreenDiffuse;
int tex_Texture_ScreenSpecular;
int loc_Texture_Reflection;
int loc_Texture_ShadowMap2D;
int loc_Texture_CubeProjection;
- int loc_Texture_ScreenDepth;
int loc_Texture_ScreenNormalMap;
int loc_Texture_ScreenDiffuse;
int loc_Texture_ScreenSpecular;
int loc_LightDir;
int loc_LightPosition;
int loc_OffsetMapping_ScaleSteps;
+ int loc_OffsetMapping_LodDistance;
+ int loc_OffsetMapping_Bias;
int loc_PixelSize;
int loc_ReflectColor;
int loc_ReflectFactor;
SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
- SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
+ SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
+ SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
};
-#define SHADERSTATICPARMS_COUNT 7
+#define SHADERSTATICPARMS_COUNT 8
static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
static int shaderstaticparms_count = 0;
static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
#define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
-qboolean R_CompileShader_CheckStaticParms(void)
+static qboolean R_CompileShader_CheckStaticParms(void)
{
static int r_compileshader_staticparms_save[1];
memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
if (r_glsl_postprocess_uservec4_enable.integer)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
}
+ if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
}
shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
else \
shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
-void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
+static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
{
shaderstaticparms_count = 0;
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
}
/// information about each possible shader permutation
int vertstrings_count = 0;
int geomstrings_count = 0;
int fragstrings_count = 0;
- const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
- const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
- const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
+ const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
+ const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
+ const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
if (p->compiled)
return;
p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
- p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
+ p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
+ p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
p->tex_Texture_Reflection = -1;
p->tex_Texture_ShadowMap2D = -1;
p->tex_Texture_CubeProjection = -1;
- p->tex_Texture_ScreenDepth = -1;
p->tex_Texture_ScreenNormalMap = -1;
p->tex_Texture_ScreenDiffuse = -1;
p->tex_Texture_ScreenSpecular = -1;
if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
- if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
Mem_Free(fragmentstring);
}
-void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
{
r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
if (r_glsl_permutation != perm)
D3DPSREGISTER_ViewToLight = 44, // float4x4
D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
D3DPSREGISTER_NormalmapScrollBlend = 52,
- // next at 53
+ D3DPSREGISTER_OffsetMapping_LodDistance = 53,
+ D3DPSREGISTER_OffsetMapping_Bias = 54,
+ // next at 54
}
D3DPSREGISTER_t;
int psresult = 0;
char temp[MAX_INPUTLINE];
const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
+ char vabuf[1024];
qboolean debugshader = gl_paranoid.integer != 0;
if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
if (!debugshader)
{
- vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
- psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
+ vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
+ psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
}
if ((!vsbin && vertstring) || (!psbin && fragstring))
{
if (debugshader)
{
// vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
-// FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
- FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
- vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
+// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
+ FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
+ vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
}
else
vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
if (vslog)
{
strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
- Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
+ Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
vslog->Release();
}
}
if (debugshader)
{
// psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
-// FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
- FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
- psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
+// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
+ FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
+ psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
}
else
psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
if (pslog)
{
strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
- Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
+ Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
pslog->Release();
}
}
Sys_UnloadLibrary(&d3dx9_dll);
}
else
- Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
+ Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
}
if (vsbin && psbin)
{
vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
if (FAILED(vsresult))
- Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
+ Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
if (FAILED(psresult))
- Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
+ Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
}
// free the shader data
vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
int vertstrings_count = 0;
int geomstrings_count = 0;
int fragstrings_count = 0;
- const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
- const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
- const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
+ const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
+ const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
+ const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
if (p->compiled)
return;
}
#endif
-void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
{
DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
}
-void R_GLSL_Restart_f(void)
+static void R_GLSL_Restart_f(void)
{
unsigned int i, limit;
if (glslshaderstring && glslshaderstring != builtinshaderstring)
}
}
-void R_GLSL_DumpShader_f(void)
+static void R_GLSL_DumpShader_f(void)
{
int i;
qfile_t *file;
Con_Printf("failed to write to hlsl/default.hlsl\n");
}
-void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
+void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
{
unsigned int permutation = 0;
if (r_trippy.integer && !notrippy)
permutation |= SHADERPERMUTATION_GLOW;
else if (texturemode == GL_DECAL)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
+ permutation |= SHADERPERMUTATION_GAMMARAMPS;
+ if (suppresstexalpha)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
if (!second)
texturemode = GL_MODULATE;
if (vid.allowalphatocoverage)
R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
R_Mesh_TexBind(GL20TU_FIRST , first );
R_Mesh_TexBind(GL20TU_SECOND, second);
+ if (permutation & SHADERPERMUTATION_GAMMARAMPS)
+ R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
#endif
break;
case RENDERPATH_D3D10:
R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
+ if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
+ R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
break;
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
}
}
-void R_SetupShader_DepthOrShadow(qboolean notrippy)
+void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
+{
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
+}
+
+void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
{
unsigned int permutation = 0;
if (r_trippy.integer && !notrippy)
permutation |= SHADERPERMUTATION_TRIPPY;
+ if (depthrgb)
+ permutation |= SHADERPERMUTATION_DEPTHRGB;
if (vid.allowalphatocoverage)
GL_AlphaToCoverage(false);
switch (vid.renderpath)
int permutation = 0;
if (r_trippy.integer && !notrippy)
permutation |= SHADERPERMUTATION_TRIPPY;
- if (r_trippy.integer)
- permutation |= SHADERPERMUTATION_TRIPPY;
if (vid.allowalphatocoverage)
GL_AlphaToCoverage(false);
switch (vid.renderpath)
}
extern qboolean r_shadow_usingdeferredprepass;
-extern cvar_t r_shadow_deferred_8bitrange;
extern rtexture_t *r_shadow_attenuationgradienttexture;
extern rtexture_t *r_shadow_attenuation2dtexture;
extern rtexture_t *r_shadow_attenuation3dtexture;
extern qboolean r_shadow_shadowmapvsdct;
extern qboolean r_shadow_shadowmapsampler;
extern int r_shadow_shadowmappcf;
-extern rtexture_t *r_shadow_shadowmap2dtexture;
-extern rtexture_t *r_shadow_shadowmap2dcolortexture;
+extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
+extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
extern rtexture_t *r_shadow_shadowmapvsdcttexture;
extern matrix4x4_t r_shadow_shadowmapmatrix;
extern int r_shadow_shadowmaplod; // changes for each light based on distance
extern int r_shadow_prepass_width;
extern int r_shadow_prepass_height;
-extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
+extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
-extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
extern rtexture_t *r_shadow_prepasslightingspeculartexture;
}
else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
}
else if (rsurfacepass == RSURFPASS_RTLIGHT)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ permutation |= SHADERPERMUTATION_DEPTHRGB;
}
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ permutation |= SHADERPERMUTATION_DEPTHRGB;
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ permutation |= SHADERPERMUTATION_DEPTHRGB;
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- if (r_shadow_bouncegridtexture)
+ if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
{
permutation |= SHADERPERMUTATION_BOUNCEGRID;
if (r_shadow_bouncegriddirectional)
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ permutation |= SHADERPERMUTATION_DEPTHRGB;
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- if (r_shadow_bouncegridtexture)
+ if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
{
permutation |= SHADERPERMUTATION_BOUNCEGRID;
if (r_shadow_bouncegriddirectional)
}
else
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ permutation |= SHADERPERMUTATION_DEPTHRGB;
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
if (specularscale > 0)
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
}
- else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
+ else if (r_glsl_deluxemapping.integer >= 2)
{
// fake deluxemapping (uniform light direction in tangentspace)
- mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
+ if (rsurface.uselightmaptexture)
+ mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
+ else
+ mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
// ordinary vertex coloring (q3bsp)
mode = SHADERMODE_VERTEXCOLOR;
}
- if (r_shadow_bouncegridtexture)
+ if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
{
permutation |= SHADERPERMUTATION_BOUNCEGRID;
if (r_shadow_bouncegriddirectional)
// additive passes are only darkened by fog, not tinted
hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
- hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
}
else
{
hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
- hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
- hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
+ hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
}
hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
- hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
- hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
+ hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
}
// additive passes are only darkened by fog, not tinted
if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
else
hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
- hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
- hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
+ hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
+ hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
- hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
if (mode == SHADERMODE_WATER)
hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
}
hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
- hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
+ hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
if (rsurface.texture->pantstexture)
hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
+ hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
{
if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
}
-// if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
// if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
+ R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
if (rsurface.rtlight)
{
if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
// additive passes are only darkened by fog, not tinted
if (r_glsl_permutation->loc_FogColor >= 0)
qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
- if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
}
else
{
if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
- if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
- if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
+ if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
}
if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
- if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
- if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
+ if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
}
// additive passes are only darkened by fog, not tinted
if (r_glsl_permutation->loc_FogColor >= 0)
qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
}
if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
- if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
- if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
+ if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
+ if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
- if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
}
if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
- if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
+ if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
if (r_glsl_permutation->loc_Color_Pants >= 0)
{
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
+ if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
{
if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
}
- if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
+ if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
if (rsurface.rtlight)
{
if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
// additive passes are only darkened by fog, not tinted
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
- DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
}
else
{
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
- DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
- DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
+ DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
}
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
- DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
- DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
+ DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
}
// additive passes are only darkened by fog, not tinted
if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
else
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
- DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
- DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
+ DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
+ DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
- DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
}
{Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
- DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
{
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
{
if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
}
-// if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
// if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
+ R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
if (rsurface.rtlight)
{
if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
matrix4x4_t viewtolight;
matrix4x4_t lighttoview;
float viewtolight16f[16];
- float range = 1.0f / r_shadow_deferred_8bitrange.value;
// light source
mode = SHADERMODE_DEFERREDLIGHTSOURCE;
if (rtlight->currentcubemap != r_texture_whitecube)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ permutation |= SHADERPERMUTATION_DEPTHRGB;
}
if (vid.allowalphatocoverage)
GL_AlphaToCoverage(false);
R_SetupShader_SetPermutationHLSL(mode, permutation);
hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
- hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
- hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
- hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
+ hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
+ hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
+ hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
- hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
- R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
- R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
+ R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
#endif
break;
R_SetupShader_SetPermutationGLSL(mode, permutation);
if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
- if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
- if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
- if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
+ if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
+ if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
+ if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
- if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
- if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
- if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
+ if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
break;
case RENDERPATH_GL11:
R_SetupShader_SetPermutationGLSL(mode, permutation);
DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
- DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
- DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
- DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
+ DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
+ DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
+ DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
- DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
+ DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
- R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
- R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
+ R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
break;
}
hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
for (item = r_skinframe.hash[hashindex];item;item = item->next)
- if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
+ if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
break;
if (!item) {
memset(item, 0, sizeof(*item));
strlcpy(item->basename, basename, sizeof(item->basename));
item->base = dyntexture; // either NULL or dyntexture handle
- item->textureflags = textureflags;
+ item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
item->comparewidth = comparewidth;
item->compareheight = compareheight;
item->comparecrc = comparecrc;
item->next = r_skinframe.hash[hashindex];
r_skinframe.hash[hashindex] = item;
}
+ else if (textureflags & TEXF_FORCE_RELOAD)
+ {
+ rtexture_t *dyntexture;
+ // check whether its a dynamic texture
+ dyntexture = CL_GetDynTexture( basename );
+ if (!add && !dyntexture)
+ return NULL;
+ if (item->merged == item->base)
+ item->merged = NULL;
+ // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
+ R_PurgeTexture(item->stain );item->stain = NULL;
+ R_PurgeTexture(item->merged);item->merged = NULL;
+ R_PurgeTexture(item->base );item->base = NULL;
+ R_PurgeTexture(item->pants );item->pants = NULL;
+ R_PurgeTexture(item->shirt );item->shirt = NULL;
+ R_PurgeTexture(item->nmap );item->nmap = NULL;
+ R_PurgeTexture(item->gloss );item->gloss = NULL;
+ R_PurgeTexture(item->glow );item->glow = NULL;
+ R_PurgeTexture(item->fog );item->fog = NULL;
+ R_PurgeTexture(item->reflect);item->reflect = NULL;
+ item->loadsequence = 0;
+ }
else if( item->base == NULL )
{
rtexture_t *dyntexture;
int miplevel = R_PicmipForFlags(textureflags);
int savemiplevel = miplevel;
int mymiplevel;
+ char vabuf[1024];
if (cls.state == ca_dedicated)
return NULL;
Image_StripImageExtension(name, basename, sizeof(basename));
// check for DDS texture file first
- if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
+ if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
{
basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
if (basepixels == NULL)
// we've got some pixels to store, so really allocate this new texture now
if (!skinframe)
skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
+ textureflags &= ~TEXF_FORCE_RELOAD;
skinframe->stain = NULL;
skinframe->merged = NULL;
skinframe->base = NULL;
skinframe->hasalpha = ddshasalpha;
VectorCopy(ddsavgcolor, skinframe->avgcolor);
if (r_loadfog && skinframe->hasalpha)
- skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
+ skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
//Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
}
else
pixels[j+2] = 255;
pixels[j+3] = basepixels[j+3];
}
- skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
+ skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
Mem_Free(pixels);
}
}
R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
+#ifndef USE_GLES2
//Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
- R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
+ R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
- R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+ R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+#endif
}
if (r_loaddds)
{
mymiplevel = savemiplevel;
if (r_loadnormalmap)
- skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
- skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
+ skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
+ skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
if (r_loadgloss)
- skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
- skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
- skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
- skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
+ skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+ skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+ skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
+ skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
}
// _norm is the name used by tenebrae and has been adopted as standard
if (r_loadnormalmap && skinframe->nmap == NULL)
{
mymiplevel = savemiplevel;
- if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
+ if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
{
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
Mem_Free(pixels);
pixels = NULL;
}
- else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
+ else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
Mem_Free(pixels);
Mem_Free(bumppixels);
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
Mem_Free(pixels);
}
+#ifndef USE_GLES2
if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
- R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+ R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+#endif
}
// _luma is supported only for tenebrae compatibility
// _glow is the preferred name
mymiplevel = savemiplevel;
- if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
+ if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
{
- skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+#ifndef USE_GLES2
if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
- R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+ R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+#endif
Mem_Free(pixels);pixels = NULL;
}
mymiplevel = savemiplevel;
- if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
+ if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
{
- skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+#ifndef USE_GLES2
if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
- R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+ R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+#endif
Mem_Free(pixels);
pixels = NULL;
}
mymiplevel = savemiplevel;
- if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
+ if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
{
- skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+#ifndef USE_GLES2
if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
- R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
+ R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
+#endif
Mem_Free(pixels);
pixels = NULL;
}
mymiplevel = savemiplevel;
- if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
+ if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
{
- skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+#ifndef USE_GLES2
if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
- R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
+ R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
+#endif
Mem_Free(pixels);
pixels = NULL;
}
mymiplevel = savemiplevel;
- if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
+ if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
{
- skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+#ifndef USE_GLES2
if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
- R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+ R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
+#endif
Mem_Free(pixels);
pixels = NULL;
}
int i;
unsigned char *temp1, *temp2;
skinframe_t *skinframe;
+ char vabuf[1024];
if (cls.state == ca_dedicated)
return NULL;
// if already loaded just return it, otherwise make a new skinframe
- skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
+ skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
if (skinframe && skinframe->base)
return skinframe;
+ textureflags &= ~TEXF_FORCE_RELOAD;
skinframe->stain = NULL;
skinframe->merged = NULL;
temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
temp2 = temp1 + width * height * 4;
Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
Mem_Free(temp1);
}
skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
memcpy(fogpixels, skindata, width * height * 4);
for (i = 0;i < width * height * 4;i += 4)
fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
- skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
Mem_Free(fogpixels);
}
}
skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
if (skinframe && skinframe->base)
return skinframe;
+ textureflags &= ~TEXF_FORCE_RELOAD;
skinframe->stain = NULL;
skinframe->merged = NULL;
int width;
int height;
unsigned char *skindata;
+ char vabuf[1024];
if (!skinframe->qpixels)
return;
// use either a custom palette or the quake palette
Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
Mem_Free(temp1);
}
if (skinframe->qgenerateglow)
{
skinframe->qgenerateglow = false;
- skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
+ skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
}
if (colormapped)
{
skinframe->qgeneratebase = false;
- skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
- skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
- skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
+ skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
+ skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
+ skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
}
else
{
{
int i;
skinframe_t *skinframe;
+ char vabuf[1024];
if (cls.state == ca_dedicated)
return NULL;
skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
if (skinframe && skinframe->base)
return skinframe;
+ textureflags &= ~TEXF_FORCE_RELOAD;
skinframe->stain = NULL;
skinframe->merged = NULL;
}
}
if (r_loadfog && skinframe->hasalpha)
- skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
}
R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
static int componentorder[4] = {0, 1, 2, 3};
-rtexture_t *R_LoadCubemap(const char *basename)
+static rtexture_t *R_LoadCubemap(const char *basename)
{
int i, j, cubemapsize;
unsigned char *cubemappixels, *image_buffer;
return r_texture_cubemaps[i]->texture;
}
-void R_FreeCubemap(const char *basename)
-{
- int i;
-
- for (i = 0;i < r_texture_numcubemaps;i++)
- {
- if (r_texture_cubemaps[i] != NULL)
- {
- if (r_texture_cubemaps[i]->texture)
- {
- if (developer_loading.integer)
- Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
- R_FreeTexture(r_texture_cubemaps[i]->texture);
- Mem_Free(r_texture_cubemaps[i]);
- r_texture_cubemaps[i] = NULL;
- }
- }
- }
-}
-
-void R_FreeCubemaps(void)
-{
- int i;
- for (i = 0;i < r_texture_numcubemaps;i++)
- {
- if (developer_loading.integer)
- Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
- if (r_texture_cubemaps[i] != NULL)
- {
- if (r_texture_cubemaps[i]->texture)
- R_FreeTexture(r_texture_cubemaps[i]->texture);
- Mem_Free(r_texture_cubemaps[i]);
- }
- }
- r_texture_numcubemaps = 0;
-}
-
-void R_Main_FreeViewCache(void)
+static void R_Main_FreeViewCache(void)
{
if (r_refdef.viewcache.entityvisible)
Mem_Free(r_refdef.viewcache.entityvisible);
memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
}
-void R_Main_ResizeViewCache(void)
+static void R_Main_ResizeViewCache(void)
{
int numentities = r_refdef.scene.numentities;
int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
}
extern rtexture_t *loadingscreentexture;
-void gl_main_start(void)
+static void gl_main_start(void)
{
loadingscreentexture = NULL;
r_texture_blanknormalmap = NULL;
r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
//r_texture_fogintensity = NULL;
- memset(&r_bloomstate, 0, sizeof(r_bloomstate));
- memset(&r_waterstate, 0, sizeof(r_waterstate));
+ memset(&r_fb, 0, sizeof(r_fb));
r_glsl_permutation = NULL;
memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
r_refdef.fogmasktable_density = 0;
}
-void gl_main_shutdown(void)
+static void gl_main_shutdown(void)
{
R_AnimCache_Free();
R_FrameData_Reset();
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef GL_SAMPLES_PASSED_ARB
if (r_maxqueries)
qglDeleteQueriesARB(r_maxqueries, r_queries);
+#endif
break;
case RENDERPATH_D3D9:
//Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
r_texture_gammaramps = NULL;
r_texture_numcubemaps = 0;
//r_texture_fogintensity = NULL;
- memset(&r_bloomstate, 0, sizeof(r_bloomstate));
- memset(&r_waterstate, 0, sizeof(r_waterstate));
+ memset(&r_fb, 0, sizeof(r_fb));
R_GLSL_Restart_f();
r_glsl_permutation = NULL;
hlslshaderstring = NULL;
}
-extern void CL_ParseEntityLump(char *entitystring);
-void gl_main_newmap(void)
+static void gl_main_newmap(void)
{
// FIXME: move this code to client
char *entities, entname[MAX_QPATH];
Cvar_RegisterVariable (&gl_skyclip);
}
Cvar_RegisterVariable(&r_motionblur);
- Cvar_RegisterVariable(&r_motionblur_maxblur);
- Cvar_RegisterVariable(&r_motionblur_bmin);
- Cvar_RegisterVariable(&r_motionblur_vmin);
- Cvar_RegisterVariable(&r_motionblur_vmax);
- Cvar_RegisterVariable(&r_motionblur_vcoeff);
- Cvar_RegisterVariable(&r_motionblur_randomize);
Cvar_RegisterVariable(&r_damageblur);
+ Cvar_RegisterVariable(&r_motionblur_averaging);
+ Cvar_RegisterVariable(&r_motionblur_randomize);
+ Cvar_RegisterVariable(&r_motionblur_minblur);
+ Cvar_RegisterVariable(&r_motionblur_maxblur);
+ Cvar_RegisterVariable(&r_motionblur_velocityfactor);
+ Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
+ Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
+ Cvar_RegisterVariable(&r_motionblur_mousefactor);
+ Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
+ Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
Cvar_RegisterVariable(&r_equalize_entities_fullbright);
Cvar_RegisterVariable(&r_equalize_entities_minambient);
Cvar_RegisterVariable(&r_equalize_entities_by);
Cvar_RegisterVariable(&r_deformvertexes);
Cvar_RegisterVariable(&r_transparent);
Cvar_RegisterVariable(&r_transparent_alphatocoverage);
+ Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
+ Cvar_RegisterVariable(&r_transparent_useplanardistance);
Cvar_RegisterVariable(&r_showoverdraw);
Cvar_RegisterVariable(&r_showbboxes);
Cvar_RegisterVariable(&r_showsurfaces);
Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
Cvar_RegisterVariable(&r_cullentities_trace_delay);
+ Cvar_RegisterVariable(&r_sortentities);
Cvar_RegisterVariable(&r_drawviewmodel);
Cvar_RegisterVariable(&r_drawexteriormodel);
Cvar_RegisterVariable(&r_speeds);
Cvar_RegisterVariable(&r_fog_clear);
Cvar_RegisterVariable(&r_drawfog);
Cvar_RegisterVariable(&r_transparentdepthmasking);
+ Cvar_RegisterVariable(&r_transparent_sortmindist);
Cvar_RegisterVariable(&r_transparent_sortmaxdist);
Cvar_RegisterVariable(&r_transparent_sortarraysize);
Cvar_RegisterVariable(&r_texture_dds_load);
Cvar_RegisterVariable(&r_texture_dds_save);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&gl_combine);
+ Cvar_RegisterVariable(&r_usedepthtextures);
Cvar_RegisterVariable(&r_viewfbo);
Cvar_RegisterVariable(&r_viewscale);
Cvar_RegisterVariable(&r_viewscale_fpsscaling);
Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
+ Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
+ Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
Cvar_RegisterVariable(&r_glsl_postprocess);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
Cvar_RegisterVariable(&r_water_reflectdistort);
Cvar_RegisterVariable(&r_water_scissormode);
Cvar_RegisterVariable(&r_water_lowquality);
+ Cvar_RegisterVariable(&r_water_hideplayer);
+ Cvar_RegisterVariable(&r_water_fbo);
Cvar_RegisterVariable(&r_lerpsprites);
Cvar_RegisterVariable(&r_lerpmodels);
Cvar_RegisterVariable(&r_bloom_resolution);
Cvar_RegisterVariable(&r_bloom_colorexponent);
Cvar_RegisterVariable(&r_bloom_colorsubtract);
- Cvar_RegisterVariable(&r_hdr);
Cvar_RegisterVariable(&r_hdr_scenebrightness);
Cvar_RegisterVariable(&r_hdr_glowintensity);
- Cvar_RegisterVariable(&r_hdr_range);
Cvar_RegisterVariable(&r_hdr_irisadaptation);
Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
- Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
+ Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
+ Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
+ Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
Cvar_RegisterVariable(&developer_texturelogging);
Cvar_RegisterVariable(&gl_lightmaps);
R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
}
-extern void R_Textures_Init(void);
-extern void GL_Draw_Init(void);
-extern void GL_Main_Init(void);
-extern void R_Shadow_Init(void);
-extern void R_Sky_Init(void);
-extern void GL_Surf_Init(void);
-extern void R_Particles_Init(void);
-extern void R_Explosion_Init(void);
-extern void gl_backend_init(void);
-extern void Sbar_Init(void);
-extern void R_LightningBeams_Init(void);
-extern void Mod_RenderInit(void);
-extern void Font_Init(void);
-
void Render_Init(void)
{
gl_backend_init();
GL_Init
===============
*/
+#ifndef USE_GLES2
extern char *ENGINE_EXTENSIONS;
void GL_Init (void)
{
// clear to black (loading plaque will be seen over this)
GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
}
+#endif
int R_CullBox(const vec3_t mins, const vec3_t maxs)
{
}
}
-void R_FrameData_Resize(void)
+static void R_FrameData_Resize(void)
{
size_t wantedsize;
wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
}
}
-void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
+static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
{
int i;
{
ent = r_refdef.scene.entities[i];
- // skip unseen models
- if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
+ // skip unseen models and models that updated by CSQC
+ if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
continue;
// skip bsp models
- if (ent->model && ent->model->brush.num_leafs)
+ if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
{
// TODO: use modellight for r_ambient settings on world?
VectorSet(ent->modellight_ambient, 0, 0, 0);
entity_render_t *ent;
renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
- : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
- : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
+ : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
+ : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
: RENDER_EXTERIORMODEL;
if (!r_drawviewmodel.integer)
renderimask |= RENDER_VIEWMODEL;
ent = r_refdef.scene.entities[i];
if (!(ent->flags & renderimask))
if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
- if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
+ if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
r_refdef.viewcache.entityvisible[i] = true;
}
}
if (!r_refdef.viewcache.entityvisible[i])
continue;
ent = r_refdef.scene.entities[i];
- if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
+ if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
{
samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
if (samples < 0)
}
/// only used if skyrendermasked, and normally returns false
-int R_DrawBrushModelsSky (void)
+static int R_DrawBrushModelsSky (void)
{
int i, sky;
entity_render_t *ent;
}
}
+static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
+
void R_HDR_UpdateIrisAdaptation(const vec3_t point)
{
if (r_hdr_irisadaptation.integer)
{
+ vec3_t p;
vec3_t ambient;
vec3_t diffuse;
vec3_t diffusenormal;
- vec_t brightness;
+ vec3_t forward;
+ vec_t brightness = 0.0f;
vec_t goal;
- vec_t adjust;
vec_t current;
- R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
- brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
- brightness = max(0.0000001f, brightness);
+ vec_t d;
+ int c;
+ VectorCopy(r_refdef.view.forward, forward);
+ for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
+ {
+ p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
+ p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
+ p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
+ R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+ d = DotProduct(forward, diffusenormal);
+ brightness += VectorLength(ambient);
+ if (d > 0)
+ brightness += d * VectorLength(diffuse);
+ }
+ brightness *= 1.0f / c;
+ brightness += 0.00001f; // make sure it's never zero
goal = r_hdr_irisadaptation_multiplier.value / brightness;
goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
- adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
current = r_hdr_irisadaptation_value.value;
if (current < goal)
- current = min(current + adjust, goal);
+ current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
else if (current > goal)
- current = max(current - adjust, goal);
+ current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
}
//PlaneClassify(&frustum[4]);
}
-void R_View_UpdateWithScissor(const int *myscissor)
+static void R_View_UpdateWithScissor(const int *myscissor)
{
R_Main_ResizeViewCache();
R_View_SetFrustum(myscissor);
R_View_WorldVisibility(r_refdef.view.useclipplane);
R_View_UpdateEntityVisible();
R_View_UpdateEntityLighting();
+ R_AnimCache_CacheVisibleEntities();
}
-void R_View_Update(void)
+static void R_View_Update(void)
{
R_Main_ResizeViewCache();
R_View_SetFrustum(NULL);
R_View_WorldVisibility(r_refdef.view.useclipplane);
R_View_UpdateEntityVisible();
R_View_UpdateEntityLighting();
+ R_AnimCache_CacheVisibleEntities();
}
float viewscalefpsadjusted = 1.0f;
-void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
+static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
{
float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
scale = bound(0.03125f, scale, 1.0f);
*outheight = (int)ceil(height * scale);
}
-void R_Mesh_SetMainRenderTargets(void)
-{
- if (r_bloomstate.fbo_framebuffer)
- R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
- else
- R_Mesh_ResetRenderTargets();
-}
-
-void R_SetupView(qboolean allowwaterclippingplane)
+void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
const float *customclipplane = NULL;
float plane[4];
- int scaledwidth, scaledheight;
+ int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
if (r_refdef.view.useclipplane && allowwaterclippingplane)
{
// LordHavoc: couldn't figure out how to make this approach the
if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
}
+ //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
+ rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
+
R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
if (!r_refdef.view.useperspective)
- R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
+ R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
else if (vid.stencil && r_useinfinitefarclip.integer)
- R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
+ R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
else
- R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
- R_Mesh_SetMainRenderTargets();
+ R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
+ R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
R_SetViewport(&r_refdef.view.viewport);
if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
{
}
}
-void R_ResetViewRendering2D(void)
+void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
{
r_viewport_t viewport;
- DrawQ_Finish();
+
+ CHECKGLERROR
// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
- R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
- R_Mesh_ResetRenderTargets();
+ R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
+ R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
R_SetViewport(&viewport);
GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
GL_Color(1, 1, 1, 1);
break;
}
GL_CullFace(GL_NONE);
+
+ CHECKGLERROR
+}
+
+void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
+{
+ DrawQ_Finish();
+
+ R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
}
-void R_ResetViewRendering3D(void)
+void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
DrawQ_Finish();
- R_SetupView(true);
+ R_SetupView(true, fbo, depthtexture, colortexture);
GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
R_RenderView_UpdateViewVectors
================
*/
-static void R_RenderView_UpdateViewVectors(void)
+void R_RenderView_UpdateViewVectors(void)
{
// break apart the view matrix into vectors for various purposes
// it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
}
-void R_RenderScene(void);
-void R_RenderWaterPlanes(void);
+void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
static void R_Water_StartFrame(void)
{
int i;
int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
r_waterstate_waterplane_t *p;
+ qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
return;
}
// allocate textures as needed
- if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
+ if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
{
- r_waterstate.maxwaterplanes = MAX_WATERPLANES;
- for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
+ r_fb.water.maxwaterplanes = MAX_WATERPLANES;
+ for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
{
if (p->texture_refraction)
R_FreeTexture(p->texture_refraction);
p->texture_refraction = NULL;
+ if (p->fbo_refraction)
+ R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
+ p->fbo_refraction = 0;
if (p->texture_reflection)
R_FreeTexture(p->texture_reflection);
p->texture_reflection = NULL;
+ if (p->fbo_reflection)
+ R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
+ p->fbo_reflection = 0;
if (p->texture_camera)
R_FreeTexture(p->texture_camera);
p->texture_camera = NULL;
+ if (p->fbo_camera)
+ R_Mesh_DestroyFramebufferObject(p->fbo_camera);
+ p->fbo_camera = 0;
}
- memset(&r_waterstate, 0, sizeof(r_waterstate));
- r_waterstate.texturewidth = texturewidth;
- r_waterstate.textureheight = textureheight;
- r_waterstate.camerawidth = camerawidth;
- r_waterstate.cameraheight = cameraheight;
+ memset(&r_fb.water, 0, sizeof(r_fb.water));
+ r_fb.water.texturewidth = texturewidth;
+ r_fb.water.textureheight = textureheight;
+ r_fb.water.camerawidth = camerawidth;
+ r_fb.water.cameraheight = cameraheight;
}
- if (r_waterstate.texturewidth)
+ if (r_fb.water.texturewidth)
{
int scaledwidth, scaledheight;
- r_waterstate.enabled = true;
+ r_fb.water.enabled = true;
- // when doing a reduced render (HDR) we want to use a smaller area
- r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
- r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
- R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
+ // water resolution is usually reduced
+ r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
+ r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
+ R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
// set up variables that will be used in shader setup
- r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
- r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
- r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
- r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
+ r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
+ r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
+ r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
+ r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
}
- r_waterstate.maxwaterplanes = MAX_WATERPLANES;
- r_waterstate.numwaterplanes = 0;
+ r_fb.water.maxwaterplanes = MAX_WATERPLANES;
+ r_fb.water.numwaterplanes = 0;
}
void R_Water_AddWaterPlane(msurface_t *surface, int entno)
{
- int triangleindex, planeindex;
- const int *e;
- vec3_t vert[3];
- vec3_t normal;
- vec3_t center;
+ int planeindex, bestplaneindex, vertexindex;
+ vec3_t mins, maxs, normal, center, v, n;
+ vec_t planescore, bestplanescore;
mplane_t plane;
r_waterstate_waterplane_t *p;
texture_t *t = R_GetCurrentTexture(surface->texture);
- // just use the first triangle with a valid normal for any decisions
- VectorClear(normal);
- for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
- {
- Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
- Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
- Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
- TriangleNormal(vert[0], vert[1], vert[2], normal);
- if (VectorLength2(normal) >= 0.001)
- break;
- }
+ rsurface.texture = t;
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
+ // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
+ if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
+ return;
+ // average the vertex normals, find the surface bounds (after deformvertexes)
+ Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
+ Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
+ VectorCopy(n, normal);
+ VectorCopy(v, mins);
+ VectorCopy(v, maxs);
+ for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
+ {
+ Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
+ Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
+ VectorAdd(normal, n, normal);
+ mins[0] = min(mins[0], v[0]);
+ mins[1] = min(mins[1], v[1]);
+ mins[2] = min(mins[2], v[2]);
+ maxs[0] = max(maxs[0], v[0]);
+ maxs[1] = max(maxs[1], v[1]);
+ maxs[2] = max(maxs[2], v[2]);
+ }
+ VectorNormalize(normal);
+ VectorMAM(0.5f, mins, 0.5f, maxs, center);
VectorCopy(normal, plane.normal);
VectorNormalize(plane.normal);
- plane.dist = DotProduct(vert[0], plane.normal);
+ plane.dist = DotProduct(center, plane.normal);
PlaneClassify(&plane);
if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
{
// skip backfaces (except if nocullface is set)
- if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
- return;
+// if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
+// return;
VectorNegate(plane.normal, plane.normal);
plane.dist *= -1;
PlaneClassify(&plane);
// find a matching plane if there is one
- for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
+ bestplaneindex = -1;
+ bestplanescore = 1048576.0f;
+ for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
+ {
if(p->camera_entity == t->camera_entity)
- if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
- break;
- if (planeindex >= r_waterstate.maxwaterplanes)
- return; // nothing we can do, out of planes
+ {
+ planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
+ if (bestplaneindex < 0 || bestplanescore > planescore)
+ {
+ bestplaneindex = planeindex;
+ bestplanescore = planescore;
+ }
+ }
+ }
+ planeindex = bestplaneindex;
+ p = r_fb.water.waterplanes + planeindex;
- // if this triangle does not fit any known plane rendered this frame, add one
- if (planeindex >= r_waterstate.numwaterplanes)
+ // if this surface does not fit any known plane rendered this frame, add one
+ if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
{
// store the new plane
- r_waterstate.numwaterplanes++;
+ planeindex = r_fb.water.numwaterplanes++;
+ p = r_fb.water.waterplanes + planeindex;
p->plane = plane;
// clear materialflags and pvs
p->materialflags = 0;
p->pvsvalid = false;
p->camera_entity = t->camera_entity;
- VectorCopy(surface->mins, p->mins);
- VectorCopy(surface->maxs, p->maxs);
+ VectorCopy(mins, p->mins);
+ VectorCopy(maxs, p->maxs);
}
else
{
- // merge mins/maxs
- p->mins[0] = min(p->mins[0], surface->mins[0]);
- p->mins[1] = min(p->mins[1], surface->mins[1]);
- p->mins[2] = min(p->mins[2], surface->mins[2]);
- p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
- p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
- p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
+ // merge mins/maxs when we're adding this surface to the plane
+ p->mins[0] = min(p->mins[0], mins[0]);
+ p->mins[1] = min(p->mins[1], mins[1]);
+ p->mins[2] = min(p->mins[2], mins[2]);
+ p->maxs[0] = max(p->maxs[0], maxs[0]);
+ p->maxs[1] = max(p->maxs[1], maxs[1]);
+ p->maxs[2] = max(p->maxs[2], maxs[2]);
}
// merge this surface's materialflags into the waterplane
p->materialflags |= t->currentmaterialflags;
if(!(p->materialflags & MATERIALFLAG_CAMERA))
{
// merge this surface's PVS into the waterplane
- VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
&& r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
{
extern cvar_t r_drawparticles;
extern cvar_t r_drawdecals;
-static void R_Water_ProcessPlanes(void)
+static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
int myscissor[4];
r_refdef_view_t originalview;
int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
r_waterstate_waterplane_t *p;
vec3_t visorigin;
+ qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
+ char vabuf[1024];
originalview = r_refdef.view;
}
// make sure enough textures are allocated
- for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
+ for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
{
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
{
if (!p->texture_refraction)
- p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+ p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
if (!p->texture_refraction)
goto error;
+ if (usewaterfbo)
+ {
+ if (r_fb.water.depthtexture == NULL)
+ r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
+ if (p->fbo_refraction == 0)
+ p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
+ }
}
else if (p->materialflags & MATERIALFLAG_CAMERA)
{
if (!p->texture_camera)
- p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
+ p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
if (!p->texture_camera)
goto error;
+ if (usewaterfbo)
+ {
+ if (r_fb.water.depthtexture == NULL)
+ r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
+ if (p->fbo_camera == 0)
+ p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
+ }
}
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
if (!p->texture_reflection)
- p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+ p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
if (!p->texture_reflection)
goto error;
+ if (usewaterfbo)
+ {
+ if (r_fb.water.depthtexture == NULL)
+ r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
+ if (p->fbo_reflection == 0)
+ p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
+ }
}
}
// render views
r_refdef.view = originalview;
r_refdef.view.showdebug = false;
- r_refdef.view.width = r_waterstate.waterwidth;
- r_refdef.view.height = r_waterstate.waterheight;
+ r_refdef.view.width = r_fb.water.waterwidth;
+ r_refdef.view.height = r_fb.water.waterheight;
r_refdef.view.useclipplane = true;
myview = r_refdef.view;
- r_waterstate.renderingscene = true;
- for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
+ r_fb.water.renderingscene = true;
+ for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
{
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
r_refdef.view = myview;
if(r_water_scissormode.integer)
{
- R_SetupView(true);
+ R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
}
memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
}
- R_ResetViewRendering3D();
+ r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
+ R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
R_ClearScreen(r_refdef.fogenabled);
if(r_water_scissormode.integer & 2)
R_View_UpdateWithScissor(myscissor);
R_View_Update();
if(r_water_scissormode.integer & 1)
GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
- R_RenderScene();
+ R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
- R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ if (!p->fbo_reflection)
+ R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_fb.water.hideplayer = false;
}
// render the normal view scene and copy into texture
r_refdef.view = myview;
if(r_water_scissormode.integer)
{
- R_SetupView(true);
+ R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
}
- r_waterstate.renderingrefraction = true;
+ r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
r_refdef.view.clipplane = p->plane;
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
{
// we need to perform a matrix transform to render the view... so let's get the transformation matrix
- r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
+ r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
R_RenderView_UpdateViewVectors();
if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
PlaneClassify(&r_refdef.view.clipplane);
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
R_ClearScreen(r_refdef.fogenabled);
if(r_water_scissormode.integer & 2)
R_View_UpdateWithScissor(myscissor);
R_View_Update();
if(r_water_scissormode.integer & 1)
GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
- R_RenderScene();
+ R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
- R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
- r_waterstate.renderingrefraction = false;
+ if (!p->fbo_refraction)
+ R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_fb.water.hideplayer = false;
}
else if (p->materialflags & MATERIALFLAG_CAMERA)
{
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
- r_refdef.view.width = r_waterstate.camerawidth;
- r_refdef.view.height = r_waterstate.cameraheight;
+ r_refdef.view.width = r_fb.water.camerawidth;
+ r_refdef.view.height = r_fb.water.cameraheight;
r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
+ r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
+ r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
if(p->camera_entity)
{
PlaneClassify(&r_refdef.view.clipplane);
- R_ResetViewRendering3D();
+ r_fb.water.hideplayer = false;
+
+ R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
R_ClearScreen(r_refdef.fogenabled);
R_View_Update();
- R_RenderScene();
+ R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
- R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
- r_waterstate.renderingrefraction = false;
+ if (!p->fbo_camera)
+ R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_fb.water.hideplayer = false;
}
}
if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
- r_waterstate.renderingscene = false;
+ r_fb.water.renderingscene = false;
r_refdef.view = originalview;
- R_ResetViewRendering3D();
- R_ClearScreen(r_refdef.fogenabled);
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ if (!r_fb.water.depthtexture)
+ R_ClearScreen(r_refdef.fogenabled);
R_View_Update();
goto finish;
error:
r_refdef.view = originalview;
- r_waterstate.renderingscene = false;
+ r_fb.water.renderingscene = false;
Cvar_SetValueQuick(&r_water, 0);
Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
finish:
}
}
-void R_Bloom_StartFrame(void)
+static void R_Bloom_StartFrame(void)
{
+ int i;
int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
int viewwidth, viewheight;
- textype_t textype;
+ qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
+ textype_t textype = TEXTYPE_COLORBUFFER;
+
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
+ if (vid.support.ext_framebuffer_object)
+ {
+ if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
+ if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
+ }
+ break;
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ case RENDERPATH_D3D9:
+ case RENDERPATH_D3D10:
+ case RENDERPATH_D3D11:
+ r_fb.usedepthtextures = false;
+ break;
+ case RENDERPATH_SOFT:
+ r_fb.usedepthtextures = true;
+ break;
+ }
if (r_viewscale_fpsscaling.integer)
{
// set bloomwidth and bloomheight to the bloom resolution that will be
// used (often less than the screen resolution for faster rendering)
- r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
- r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
- r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
- r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
- r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
+ r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
+ r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
+ r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
+ r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
+ r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
// calculate desired texture sizes
if (vid.support.arb_texture_non_power_of_two)
{
screentexturewidth = vid.width;
screentextureheight = vid.height;
- bloomtexturewidth = r_bloomstate.bloomwidth;
- bloomtextureheight = r_bloomstate.bloomheight;
+ bloomtexturewidth = r_fb.bloomwidth;
+ bloomtextureheight = r_fb.bloomheight;
}
else
{
- for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
- for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
- for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
- for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
+ for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
+ for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
+ for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
+ for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
}
- if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
+ if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
{
- Cvar_SetValueQuick(&r_hdr, 0);
Cvar_SetValueQuick(&r_bloom, 0);
Cvar_SetValueQuick(&r_motionblur, 0);
Cvar_SetValueQuick(&r_damageblur, 0);
}
- if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
+ if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
+ && !r_bloom.integer
+ && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
+ && !useviewfbo
+ && r_viewscale.value == 1.0f
+ && !r_viewscale_fpsscaling.integer)
screentexturewidth = screentextureheight = 0;
- if (!r_hdr.integer && !r_bloom.integer)
+ if (!r_bloom.integer)
bloomtexturewidth = bloomtextureheight = 0;
- textype = TEXTYPE_COLORBUFFER;
- switch (vid.renderpath)
+ // allocate textures as needed
+ if (r_fb.screentexturewidth != screentexturewidth
+ || r_fb.screentextureheight != screentextureheight
+ || r_fb.bloomtexturewidth != bloomtexturewidth
+ || r_fb.bloomtextureheight != bloomtextureheight
+ || r_fb.textype != textype
+ || useviewfbo != (r_fb.fbo != 0))
{
- case RENDERPATH_GL20:
- case RENDERPATH_GLES2:
- if (vid.support.ext_framebuffer_object)
+ for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
{
- if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
- if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
+ if (r_fb.bloomtexture[i])
+ R_FreeTexture(r_fb.bloomtexture[i]);
+ r_fb.bloomtexture[i] = NULL;
+
+ if (r_fb.bloomfbo[i])
+ R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
+ r_fb.bloomfbo[i] = 0;
}
- break;
- case RENDERPATH_GL11:
- case RENDERPATH_GL13:
- case RENDERPATH_GLES1:
- case RENDERPATH_D3D9:
- case RENDERPATH_D3D10:
- case RENDERPATH_D3D11:
- case RENDERPATH_SOFT:
- break;
- }
- // allocate textures as needed
- if (r_bloomstate.screentexturewidth != screentexturewidth
- || r_bloomstate.screentextureheight != screentextureheight
- || r_bloomstate.bloomtexturewidth != bloomtexturewidth
- || r_bloomstate.bloomtextureheight != bloomtextureheight
- || r_bloomstate.texturetype != textype
- || r_bloomstate.viewfbo != r_viewfbo.integer)
- {
- if (r_bloomstate.texture_bloom)
- R_FreeTexture(r_bloomstate.texture_bloom);
- r_bloomstate.texture_bloom = NULL;
- if (r_bloomstate.texture_screen)
- R_FreeTexture(r_bloomstate.texture_screen);
- r_bloomstate.texture_screen = NULL;
- if (r_bloomstate.fbo_framebuffer)
- R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
- r_bloomstate.fbo_framebuffer = 0;
- if (r_bloomstate.texture_framebuffercolor)
- R_FreeTexture(r_bloomstate.texture_framebuffercolor);
- r_bloomstate.texture_framebuffercolor = NULL;
- if (r_bloomstate.texture_framebufferdepth)
- R_FreeTexture(r_bloomstate.texture_framebufferdepth);
- r_bloomstate.texture_framebufferdepth = NULL;
- r_bloomstate.screentexturewidth = screentexturewidth;
- r_bloomstate.screentextureheight = screentextureheight;
- if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
- r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
- if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
- {
- // FIXME: choose depth bits based on a cvar
- r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
- r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
- r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
- R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
- // render depth into one texture and normalmap into the other
- if (qglDrawBuffer)
+ if (r_fb.fbo)
+ R_Mesh_DestroyFramebufferObject(r_fb.fbo);
+ r_fb.fbo = 0;
+
+ if (r_fb.colortexture)
+ R_FreeTexture(r_fb.colortexture);
+ r_fb.colortexture = NULL;
+
+ if (r_fb.depthtexture)
+ R_FreeTexture(r_fb.depthtexture);
+ r_fb.depthtexture = NULL;
+
+ if (r_fb.ghosttexture)
+ R_FreeTexture(r_fb.ghosttexture);
+ r_fb.ghosttexture = NULL;
+
+ r_fb.screentexturewidth = screentexturewidth;
+ r_fb.screentextureheight = screentextureheight;
+ r_fb.bloomtexturewidth = bloomtexturewidth;
+ r_fb.bloomtextureheight = bloomtextureheight;
+ r_fb.textype = textype;
+
+ if (r_fb.screentexturewidth && r_fb.screentextureheight)
+ {
+ if (r_motionblur.value > 0 || r_damageblur.value > 0)
+ r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+ r_fb.ghosttexture_valid = false;
+ r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+ if (useviewfbo)
{
- int status;
- qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
- qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
+ r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
+ r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
+ }
+ }
+
+ if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
+ {
+ for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
+ {
+ r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
+ if (useviewfbo)
+ r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
}
}
- r_bloomstate.bloomtexturewidth = bloomtexturewidth;
- r_bloomstate.bloomtextureheight = bloomtextureheight;
- if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
- r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
- r_bloomstate.viewfbo = r_viewfbo.integer;
- r_bloomstate.texturetype = textype;
}
- // when doing a reduced render (HDR) we want to use a smaller area
- r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
- r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
- r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
- r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
- r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
+ // bloom texture is a different resolution
+ r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
+ r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
+ r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
+ r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
+ r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
// set up a texcoord array for the full resolution screen image
// (we have to keep this around to copy back during final render)
- r_bloomstate.screentexcoord2f[0] = 0;
- r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
- r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
- r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
- r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
- r_bloomstate.screentexcoord2f[5] = 0;
- r_bloomstate.screentexcoord2f[6] = 0;
- r_bloomstate.screentexcoord2f[7] = 0;
+ r_fb.screentexcoord2f[0] = 0;
+ r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
+ r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
+ r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
+ r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
+ r_fb.screentexcoord2f[5] = 0;
+ r_fb.screentexcoord2f[6] = 0;
+ r_fb.screentexcoord2f[7] = 0;
// set up a texcoord array for the reduced resolution bloom image
// (which will be additive blended over the screen image)
- r_bloomstate.bloomtexcoord2f[0] = 0;
- r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
- r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
- r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
- r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
- r_bloomstate.bloomtexcoord2f[5] = 0;
- r_bloomstate.bloomtexcoord2f[6] = 0;
- r_bloomstate.bloomtexcoord2f[7] = 0;
+ r_fb.bloomtexcoord2f[0] = 0;
+ r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
+ r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
+ r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
+ r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
+ r_fb.bloomtexcoord2f[5] = 0;
+ r_fb.bloomtexcoord2f[6] = 0;
+ r_fb.bloomtexcoord2f[7] = 0;
switch(vid.renderpath)
{
int i;
for (i = 0;i < 4;i++)
{
- r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
- r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
- r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
- r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
+ r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
+ r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
+ r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
+ r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
}
}
break;
}
- if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
- {
- r_bloomstate.enabled = true;
- r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
- }
-
- R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
+ R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
- if (r_bloomstate.fbo_framebuffer)
+ if (r_fb.fbo)
r_refdef.view.clear = true;
}
-void R_Bloom_CopyBloomTexture(float colorscale)
+static void R_Bloom_MakeTexture(void)
{
+ int x, range, dir;
+ float xoffset, yoffset, r, brighten;
+ rtexture_t *intex;
+ float colorscale = r_bloom_colorscale.value;
+
r_refdef.stats.bloom++;
+ if (!r_fb.fbo)
+ {
+ R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
+ }
+
// scale down screen texture to the bloom texture size
CHECKGLERROR
- R_Mesh_SetMainRenderTargets();
- R_SetViewport(&r_bloomstate.viewport);
+ r_fb.bloomindex = 0;
+ R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
+ R_SetViewport(&r_fb.bloomviewport);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
// D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
case RENDERPATH_SOFT:
- R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
- R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
break;
}
// TODO: do boxfilter scale-down in shader?
- R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
- r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
-
- // we now have a bloom image in the framebuffer
- // copy it into the bloom image texture for later processing
- R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
- r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
-}
-
-void R_Bloom_CopyHDRTexture(void)
-{
- R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
- r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
-}
+ r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
-void R_Bloom_MakeTexture(void)
-{
- int x, range, dir;
- float xoffset, yoffset, r, brighten;
-
- r_refdef.stats.bloom++;
-
- R_ResetViewRendering2D();
-
- // we have a bloom image in the framebuffer
- CHECKGLERROR
- R_SetViewport(&r_bloomstate.viewport);
+ // we now have a properly scaled bloom image
+ if (!r_fb.bloomfbo[r_fb.bloomindex])
+ {
+ // copy it into the bloom texture
+ R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
+ r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
+ }
+ // multiply bloom image by itself as many times as desired
for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
{
+ intex = r_fb.bloomtexture[r_fb.bloomindex];
+ r_fb.bloomindex ^= 1;
+ R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
x *= 2;
r = bound(0, r_bloom_colorexponent.value / x, 1);
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
GL_Color(r,r,r,1);
- R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
- R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
+ R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
- r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
- // copy the vertically blurred bloom view to a texture
- R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
- r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
+ if (!r_fb.bloomfbo[r_fb.bloomindex])
+ {
+ // copy the darkened image to a texture
+ R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
+ r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
+ }
}
- range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
+ range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
brighten = r_bloom_brighten.value;
- if (r_bloomstate.hdr)
- brighten *= r_hdr_range.value;
brighten = sqrt(brighten);
if(range >= 1)
brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
- R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
for (dir = 0;dir < 2;dir++)
{
+ intex = r_fb.bloomtexture[r_fb.bloomindex];
+ r_fb.bloomindex ^= 1;
+ R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
// blend on at multiple vertical offsets to achieve a vertical blur
// TODO: do offset blends using GLSL
// TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
GL_BlendFunc(GL_ONE, GL_ZERO);
+ R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
for (x = -range;x <= range;x++)
{
if (!dir){xoffset = 0;yoffset = x;}
else {xoffset = x;yoffset = 0;}
- xoffset /= (float)r_bloomstate.bloomtexturewidth;
- yoffset /= (float)r_bloomstate.bloomtextureheight;
+ xoffset /= (float)r_fb.bloomtexturewidth;
+ yoffset /= (float)r_fb.bloomtextureheight;
// compute a texcoord array with the specified x and y offset
- r_bloomstate.offsettexcoord2f[0] = xoffset+0;
- r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
- r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
- r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
- r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
- r_bloomstate.offsettexcoord2f[5] = yoffset+0;
- r_bloomstate.offsettexcoord2f[6] = xoffset+0;
- r_bloomstate.offsettexcoord2f[7] = yoffset+0;
+ r_fb.offsettexcoord2f[0] = xoffset+0;
+ r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
+ r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
+ r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
+ r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
+ r_fb.offsettexcoord2f[5] = yoffset+0;
+ r_fb.offsettexcoord2f[6] = xoffset+0;
+ r_fb.offsettexcoord2f[7] = yoffset+0;
// this r value looks like a 'dot' particle, fading sharply to
// black at the edges
// (probably not realistic but looks good enough)
if(range >= 1)
r *= (1 - x*x/(float)(range*range));
GL_Color(r, r, r, 1);
- R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
- r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
GL_BlendFunc(GL_ONE, GL_ONE);
}
- // copy the vertically blurred bloom view to a texture
- R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
- r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
+ if (!r_fb.bloomfbo[r_fb.bloomindex])
+ {
+ // copy the vertically or horizontally blurred bloom view to a texture
+ R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
+ r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
+ }
}
}
-void R_HDR_RenderBloomTexture(void)
-{
- int oldwidth, oldheight;
- float oldcolorscale;
- qboolean oldwaterstate;
-
- oldwaterstate = r_waterstate.enabled;
- oldcolorscale = r_refdef.view.colorscale;
- oldwidth = r_refdef.view.width;
- oldheight = r_refdef.view.height;
- r_refdef.view.width = r_bloomstate.bloomwidth;
- r_refdef.view.height = r_bloomstate.bloomheight;
-
- if(r_hdr.integer < 2)
- r_waterstate.enabled = false;
-
- // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
- // TODO: add exposure compensation features
- // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
-
- r_refdef.view.showdebug = false;
- r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
-
- R_ResetViewRendering3D();
-
- R_ClearScreen(r_refdef.fogenabled);
- if (r_timereport_active)
- R_TimeReport("HDRclear");
-
- R_View_Update();
- if (r_timereport_active)
- R_TimeReport("visibility");
-
- // only do secondary renders with HDR if r_hdr is 2 or higher
- r_waterstate.numwaterplanes = 0;
- if (r_waterstate.enabled)
- R_RenderWaterPlanes();
-
- r_refdef.view.showdebug = true;
- R_RenderScene();
- r_waterstate.numwaterplanes = 0;
-
- R_ResetViewRendering2D();
-
- R_Bloom_CopyHDRTexture();
- R_Bloom_MakeTexture();
-
- // restore the view settings
- r_waterstate.enabled = oldwaterstate;
- r_refdef.view.width = oldwidth;
- r_refdef.view.height = oldheight;
- r_refdef.view.colorscale = oldcolorscale;
-
- R_ResetViewRendering3D();
-
- R_ClearScreen(r_refdef.fogenabled);
- if (r_timereport_active)
- R_TimeReport("viewclear");
-}
-
-static void R_BlendView(void)
+static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
unsigned int permutation;
float uservecs[4][4];
case RENDERPATH_SOFT:
case RENDERPATH_GLES2:
permutation =
- (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
+ (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
| (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
| ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
| (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
| ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
- if (r_bloomstate.texture_screen)
+ if (r_fb.colortexture)
{
- // make sure the buffer is available
- if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
-
- R_ResetViewRendering2D();
- R_Mesh_SetMainRenderTargets();
+ if (!r_fb.fbo)
+ {
+ R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
+ }
- if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
+ if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
{
// declare variables
- float speed;
- static float avgspeed;
+ float blur_factor, blur_mouseaccel, blur_velocity;
+ static float blur_average;
+ static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
+
+ // set a goal for the factoring
+ blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
+ / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
+ blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
+ / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
+ blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
+ + (blur_mouseaccel * r_motionblur_mousefactor.value));
- speed = VectorLength(cl.movement_velocity);
+ // from the goal, pick an averaged value between goal and last value
+ cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
+ blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
- cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
- avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
+ // enforce minimum amount of blur
+ blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
- speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
- speed = bound(0, speed, 1);
- speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
+ //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
// calculate values into a standard alpha
cl.motionbluralpha = 1 - exp(-
(
- (r_motionblur.value * speed / 80)
+ (r_motionblur.value * blur_factor / 80)
+
(r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
)
/
max(0.0001, cl.time - cl.oldtime) // fps independent
- );
+ );
+ // randomization for the blur value to combat persistent ghosting
cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
+
// apply the blur
- if (cl.motionbluralpha > 0 && !r_refdef.envmap)
+ R_ResetViewRendering2D(fbo, depthtexture, colortexture);
+ if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
{
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Color(1, 1, 1, cl.motionbluralpha);
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
case RENDERPATH_SOFT:
- R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
- R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
break;
}
- R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
- }
- // copy view into the screen texture
- R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
- r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
+ // updates old view angles for next pass
+ VectorCopy(cl.viewangles, blur_oldangles);
+
+ // copy view into the ghost texture
+ R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
+ r_fb.ghosttexture_valid = true;
+ }
}
- else if (!r_bloomstate.texture_bloom)
+ else
{
+ // no r_fb.colortexture means we're rendering to the real fb
// we may still have to do view tint...
if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
// apply a color tint to the whole view
- R_ResetViewRendering2D();
+ R_ResetViewRendering2D(0, NULL, NULL);
GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture(false, true);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
break; // no screen processing, no bloom, skip it
}
- if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
+ if (r_fb.bloomtexture[0])
{
- // render simple bloom effect
- // copy the screen and shrink it and darken it for the bloom process
- R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
// make the bloom texture
R_Bloom_MakeTexture();
}
if (r_glsl_postprocess_uservec4_enable.integer)
sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
- R_ResetViewRendering2D();
+ R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
GL_Color(1, 1, 1, 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
{
case RENDERPATH_GL20:
case RENDERPATH_GLES2:
- R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
+ R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
- if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
- if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
+ if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
+ if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
+ if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
// D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
- R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
+ R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
- R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
- R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
+ R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
+ R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
+ hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
case RENDERPATH_SOFT:
- R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
+ R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
- R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
- R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
+ R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
+ R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
+ DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
// apply a color tint to the whole view
- R_ResetViewRendering2D();
+ R_ResetViewRendering2D(0, NULL, NULL);
GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture(false, true);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
matrix4x4_t r_waterscrollmatrix;
-void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
+void R_UpdateFog(void)
{
- if (r_refdef.fog_density)
- {
- r_refdef.fogcolor[0] = r_refdef.fog_red;
- r_refdef.fogcolor[1] = r_refdef.fog_green;
- r_refdef.fogcolor[2] = r_refdef.fog_blue;
-
- Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
- r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
- r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
- r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
-
- {
- vec3_t fogvec;
- VectorCopy(r_refdef.fogcolor, fogvec);
- // color.rgb *= ContrastBoost * SceneBrightness;
- VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
- r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
- r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
- r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
- }
- }
-}
-
-void R_UpdateVariables(void)
-{
- R_Textures_Frame();
-
- r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
-
- r_refdef.farclip = r_farclip_base.value;
- if (r_refdef.scene.worldmodel)
- r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
- r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
-
- if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
- Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
- r_refdef.polygonfactor = 0;
- r_refdef.polygonoffset = 0;
- r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
- r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
-
- r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
- r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
- r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
- r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
- r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
- if (FAKELIGHT_ENABLED)
- {
- r_refdef.lightmapintensity *= r_fakelight_intensity.value;
- }
- if (r_showsurfaces.integer)
- {
- r_refdef.scene.rtworld = false;
- r_refdef.scene.rtworldshadows = false;
- r_refdef.scene.rtdlight = false;
- r_refdef.scene.rtdlightshadows = false;
- r_refdef.lightmapintensity = 0;
- }
-
+ // Nehahra fog
if (gamemode == GAME_NEHAHRA)
{
if (gl_fogenable.integer)
}
}
+ // fog parms
r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
r_refdef.fog_start = max(0, r_refdef.fog_start);
r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
- // R_UpdateFogColor(); // why? R_RenderScene does it anyway
-
if (r_refdef.fog_density && r_drawfog.integer)
{
r_refdef.fogenabled = true;
else
r_refdef.fogenabled = false;
+ // fog color
+ if (r_refdef.fog_density)
+ {
+ r_refdef.fogcolor[0] = r_refdef.fog_red;
+ r_refdef.fogcolor[1] = r_refdef.fog_green;
+ r_refdef.fogcolor[2] = r_refdef.fog_blue;
+
+ Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
+ r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
+ r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
+ r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
+
+ {
+ vec3_t fogvec;
+ VectorCopy(r_refdef.fogcolor, fogvec);
+ // color.rgb *= ContrastBoost * SceneBrightness;
+ VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
+ r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
+ r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
+ r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
+ }
+ }
+}
+
+void R_UpdateVariables(void)
+{
+ R_Textures_Frame();
+
+ r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
+
+ r_refdef.farclip = r_farclip_base.value;
+ if (r_refdef.scene.worldmodel)
+ r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
+ r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
+
+ if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
+ Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
+ r_refdef.polygonfactor = 0;
+ r_refdef.polygonoffset = 0;
+ r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+ r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+
+ r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
+ r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
+ r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
+ r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
+ r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+ if (FAKELIGHT_ENABLED)
+ {
+ r_refdef.lightmapintensity *= r_fakelight_intensity.value;
+ }
+ if (r_showsurfaces.integer)
+ {
+ r_refdef.scene.rtworld = false;
+ r_refdef.scene.rtworldshadows = false;
+ r_refdef.scene.rtdlight = false;
+ r_refdef.scene.rtdlightshadows = false;
+ r_refdef.lightmapintensity = 0;
+ }
+
switch(vid.renderpath)
{
case RENDERPATH_GL20:
}
}
+static int R_SortEntities_Compare(const void *ap, const void *bp)
+{
+ const entity_render_t *a = *(const entity_render_t **)ap;
+ const entity_render_t *b = *(const entity_render_t **)bp;
+
+ // 1. compare model
+ if(a->model < b->model)
+ return -1;
+ if(a->model > b->model)
+ return +1;
+
+ // 2. compare skin
+ // TODO possibly calculate the REAL skinnum here first using
+ // skinscenes?
+ if(a->skinnum < b->skinnum)
+ return -1;
+ if(a->skinnum > b->skinnum)
+ return +1;
+
+ // everything we compared is equal
+ return 0;
+}
+static void R_SortEntities(void)
+{
+ // below or equal 2 ents, sorting never gains anything
+ if(r_refdef.scene.numentities <= 2)
+ return;
+ // sort
+ qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
+}
+
/*
================
R_RenderView
================
*/
int dpsoftrast_test;
-extern void R_Shadow_UpdateBounceGridTexture(void);
extern cvar_t r_shadow_bouncegrid;
void R_RenderView(void)
{
matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
+ int fbo;
+ rtexture_t *depthtexture;
+ rtexture_t *colortexture;
dpsoftrast_test = r_test.integer;
if (!r_drawentities.integer)
r_refdef.scene.numentities = 0;
+ else if (r_sortentities.integer)
+ R_SortEntities();
R_AnimCache_ClearCache();
R_FrameData_NewFrame();
if (r_refdef.view.isoverlay)
{
// TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
+ R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
R_TimeReport("depthclear");
r_refdef.view.showdebug = false;
- r_waterstate.enabled = false;
- r_waterstate.numwaterplanes = 0;
+ r_fb.water.enabled = false;
+ r_fb.water.numwaterplanes = 0;
- R_RenderScene();
+ R_RenderScene(0, NULL, NULL);
r_refdef.view.matrix = originalmatrix;
if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
{
r_refdef.view.matrix = originalmatrix;
- return; //Host_Error ("R_RenderView: NULL worldmodel");
+ return;
}
r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ // in sRGB fallback, behave similar to true sRGB: convert this
+ // value from linear to sRGB
+ r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
+
R_RenderView_UpdateViewVectors();
R_Shadow_UpdateWorldLightSelection();
R_Bloom_StartFrame();
R_Water_StartFrame();
+ // now we probably have an fbo to render into
+ fbo = r_fb.fbo;
+ depthtexture = r_fb.depthtexture;
+ colortexture = r_fb.colortexture;
+
CHECKGLERROR
if (r_timereport_active)
R_TimeReport("viewsetup");
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
- if (r_refdef.view.clear || r_refdef.fogenabled)
+ if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
{
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
}
r_refdef.view.clear = true;
- // this produces a bloom texture to be used in R_BlendView() later
- if (r_bloomstate.hdr)
- {
- R_HDR_RenderBloomTexture();
- // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
- r_textureframe++; // used only by R_GetCurrentTexture
- }
-
r_refdef.view.showdebug = true;
R_View_Update();
if (r_timereport_active && r_shadow_bouncegrid.integer)
R_TimeReport("bouncegrid");
- r_waterstate.numwaterplanes = 0;
- if (r_waterstate.enabled)
- R_RenderWaterPlanes();
+ r_fb.water.numwaterplanes = 0;
+ if (r_fb.water.enabled)
+ R_RenderWaterPlanes(fbo, depthtexture, colortexture);
- R_RenderScene();
- r_waterstate.numwaterplanes = 0;
+ R_RenderScene(fbo, depthtexture, colortexture);
+ r_fb.water.numwaterplanes = 0;
- R_BlendView();
+ R_BlendView(fbo, depthtexture, colortexture);
if (r_timereport_active)
R_TimeReport("blendview");
CHECKGLERROR
}
-void R_RenderWaterPlanes(void)
+void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
{
if (r_timereport_active)
R_TimeReport("watermodels");
- if (r_waterstate.numwaterplanes)
+ if (r_fb.water.numwaterplanes)
{
- R_Water_ProcessPlanes();
+ R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
if (r_timereport_active)
R_TimeReport("waterscenes");
}
}
-extern void R_DrawLightningBeams (void);
-extern void VM_CL_AddPolygonsToMeshQueue (void);
-extern void R_DrawPortals (void);
extern cvar_t cl_locs_show;
static void R_DrawLocs(void);
static void R_DrawEntityBBoxes(void);
static void R_DrawModelDecals(void);
-extern void R_DrawModelShadows(void);
-extern void R_DrawModelShadowMaps(void);
extern cvar_t cl_decals_newsystem;
extern qboolean r_shadow_usingdeferredprepass;
-void R_RenderScene(void)
+void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
qboolean shadowmapping = false;
r_refdef.stats.renders++;
- R_UpdateFogColor();
+ R_UpdateFog();
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
if (skyrendermasked && skyrenderlater)
{
// we have to force off the water clipping plane while rendering sky
- R_SetupView(false);
+ R_SetupView(false, fbo, depthtexture, colortexture);
R_Sky();
- R_SetupView(true);
+ R_SetupView(true, fbo, depthtexture, colortexture);
if (r_timereport_active)
R_TimeReport("sky");
}
}
- R_AnimCache_CacheVisibleEntities();
- if (r_timereport_active)
- R_TimeReport("animation");
-
- R_Shadow_PrepareLights();
+ R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
R_Shadow_PrepareModelShadows();
if (r_timereport_active)
if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
{
- R_DrawModelShadowMaps();
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
- R_DrawModelShadows();
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_DrawModelShadows(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
- R_DrawModelShadows();
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
+ R_DrawModelShadows(fbo, depthtexture, colortexture);
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
R_TimeReport("lightning");
}
- VM_CL_AddPolygonsToMeshQueue();
+ if (cl.csqc_loaded)
+ VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
if (r_refdef.view.showdebug)
{
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
-
- R_ResetViewRendering2D();
}
static const unsigned short bboxelements[36] =
1, 0, 2, 1, 2, 3,
};
-void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
+static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
{
int i;
float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
}
R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
}
static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
float color[4];
prvm_edict_t *edict;
- prvm_prog_t *prog_save = prog;
// this function draws bounding boxes of server entities
if (!sv.active)
return;
GL_CullFace(GL_NONE);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
- prog = 0;
- SV_VM_Begin();
for (i = 0;i < numsurfaces;i++)
{
edict = PRVM_EDICT_NUM(surfacelist[i]);
GL_CullFace(r_refdef.view.cullface_front);
R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
}
- SV_VM_End();
- prog = prog_save;
}
static void R_DrawEntityBBoxes(void)
int i;
prvm_edict_t *edict;
vec3_t center;
- prvm_prog_t *prog_save = prog;
+ prvm_prog_t *prog = SVVM_prog;
// this function draws bounding boxes of server entities
if (!sv.active)
return;
- prog = 0;
- SV_VM_Begin();
for (i = 0;i < prog->num_edicts;i++)
{
edict = PRVM_EDICT_NUM(i);
if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
continue;
VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
- R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
}
- SV_VM_End();
- prog = prog_save;
}
static const int nomodelelement3i[24] =
0.5f, 0.0f, 0.0f, 1.0f
};
-void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int i;
float f1, f2, *c;
}
}
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
}
vec3_t org;
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
- R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
else
R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
}
vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
}
-int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
+static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
{
int i;
float *vertex3f;
}
}
-void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
+static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
{
int i;
int *e, element[3];
if(parms[0] == 0 && parms[1] == 0)
return false;
if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
- if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
+ if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
return false;
return true;
}
}
f = parms[0] + parms[1] * f;
if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
- f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
+ f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
return (float) f;
}
-void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
+static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
{
int w, h, idx;
double f;
Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
break;
case Q3TCMOD_ROTATE:
+ f = tcmod->parms[0] * rsurface.shadertime;
Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
- Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
+ Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
break;
case Q3TCMOD_SCALE:
Matrix4x4_Concat(texmatrix, &matrix, &temp);
}
-void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
+static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
{
int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
char name[MAX_QPATH];
t->currentalpha = rsurface.colormod[3];
if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
t->currentalpha *= r_wateralpha.value;
- if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
+ if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
- if(!r_waterstate.enabled || r_refdef.view.isoverlay)
+ if(!r_fb.water.enabled || r_refdef.view.isoverlay)
t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
if (!(rsurface.ent_flags & RENDER_LIGHT))
t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
else if (t->currentalpha < 1)
t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
+ // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
+ if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
+ t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
if (rsurface.ent_flags & RENDER_DOUBLESIDED)
t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
}
t->specularscale *= t->specularscalemod;
t->specularpower *= t->specularpowermod;
+ t->rtlightambient = 0;
// lightmaps mode looks bad with dlights using actual texturing, so turn
// off the colormap and glossmap, but leave the normalmap on as it still
return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
}
-void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
+static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
{
int i;
for (i = 0;i < numelements;i++)
r_waterstate_waterplane_t *p;
qboolean prepared = false;
bestd = 0;
- for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
+ for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
{
if(p->camera_entity != rsurface.texture->camera_entity)
continue;
// transparent sky would be ridiculous
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
return;
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
skyrenderlater = true;
RSurf_SetupDepthAndCulling();
GL_DepthMask(true);
R_Mesh_ResetTextureState();
if (skyrendermasked)
{
- R_SetupShader_DepthOrShadow(false);
+ R_SetupShader_DepthOrShadow(false, false);
// depth-only (masking)
GL_ColorMask(0,0,0,0);
// just to make sure that braindead drivers don't draw
}
else
{
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
// fog sky
GL_BlendFunc(GL_ONE, GL_ZERO);
RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
extern rtexture_t *r_shadow_prepasslightingspeculartexture;
static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
{
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
+ if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
return;
if (prepass)
{
GL_DepthMask(true);
R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
RSurf_DrawBatch();
+ return;
}
// bind lightmap texture
{
// render water or distortion background
GL_DepthMask(true);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
RSurf_DrawBatch();
// blend surface on top
GL_DepthMask(false);
{
// render surface with reflection texture as input
GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
RSurf_DrawBatch();
}
}
float c[4];
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
if(rsurface.texture && rsurface.texture->currentskinframe)
{
RSurf_DrawBatch_GL11_ClampColor();
R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
RSurf_DrawBatch();
}
else if (!r_refdef.view.showdebug)
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
// R_Mesh_ResetTextureState();
- R_SetupShader_DepthOrShadow(false);
+ R_SetupShader_DepthOrShadow(false, false);
}
RSurf_SetupDepthAndCulling();
RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
+static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
// transparent surfaces get pushed off into the transparent queue
int surfacelistindex;
for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
{
surface = texturesurfacelist[surfacelistindex];
- tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
- tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
- tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ if (r_transparent_sortsurfacesbynearest.integer)
+ {
+ tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
+ tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
+ tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
+ }
+ else
+ {
+ tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+ tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+ tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ }
Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
- if (queueentity->transparent_offset) // transparent offset
+ if (rsurface.entity->transparent_offset) // transparent offset
{
- center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
- center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
- center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
+ center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
+ center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
+ center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
}
- R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
}
{
if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
return;
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
+ if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
return;
RSurf_SetupDepthAndCulling();
RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
- const entity_render_t *queueentity = r_refdef.scene.worldentity;
CHECKGLERROR
if (depthonly)
R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
if (!rsurface.texture->currentnumlayers)
return;
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
else
R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
}
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
- else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
+ else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
{
// in the deferred case, transparent surfaces were queued during prepass
if (!r_shadow_usingdeferredprepass)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
}
else
{
CHECKGLERROR
}
-void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
+static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
int i, j;
texture_t *texture;
R_FrameData_ReturnToMark();
}
-static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
+static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
CHECKGLERROR
if (depthonly)
if (!rsurface.texture->currentnumlayers)
return;
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
else
R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
}
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
- else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
+ else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
{
// in the deferred case, transparent surfaces were queued during prepass
if (!r_shadow_usingdeferredprepass)
- R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
}
else
{
CHECKGLERROR
}
-void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
+static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
int i, j;
texture_t *texture;
;
}
// render the range of surfaces
- R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
+ R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
}
R_FrameData_ReturnToMark();
}
20,21,22, 20,22,23
};
-void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int i, j;
cl_locnode_t *loc = (cl_locnode_t *)ent;
vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
}
for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
{
VectorLerp(loc->mins, 0.5f, loc->maxs, center);
- R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
}
}
GL_DepthTest(true);
GL_CullFace(GL_NONE);
GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
}
}
}
extern cvar_t mod_collision_bih;
-void R_DrawDebugModel(void)
+static void R_DrawDebugModel(void)
{
entity_render_t *ent = rsurface.entity;
int i, j, k, l, flagsmask;
{
float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
GL_DepthTest(false);
GL_DepthMask(false);
GL_DepthRange(0, 1);
flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
GL_DepthRange(0, 1);
GL_DepthTest(!r_showdisabledepthtest.integer);
GL_DepthMask(false);
GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
+#ifndef USE_GLES2
if (r_showtris.integer && qglPolygonMode)
{
if (r_showdisabledepthtest.integer)
}
rsurface.texture = NULL;
}
+#endif
}
-extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
int r_maxsurfacelist = 0;
const msurface_t **r_surfacelist = NULL;
void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
#include "r_shadow.h"
#include "portals.h"
#include "csprogs.h"
+#include "image.h"
cvar_t r_ambient = {0, "r_ambient", "0", "brightens map, value is 0-128"};
cvar_t r_lockpvs = {0, "r_lockpvs", "0", "disables pvs switching, allows you to walk around and inspect what is visible from a given location in the map (anything not visible from your current location will not be drawn)"};
cvar_t r_lockvisibility = {0, "r_lockvisibility", "0", "disables visibility updates, allows you to walk around and inspect what is visible from a given viewpoint in the map (anything offscreen at the moment this is enabled will not be drawn)"};
cvar_t r_useportalculling = {0, "r_useportalculling", "2", "improve framerate with r_novis 1 by using portal culling - still not as good as compiled visibility data in the map, but it helps (a value of 2 forces use of this even with vis data, which improves framerates in maps without too much complexity, but hurts in extremely complex maps, which is why 2 is not the default mode)"};
-cvar_t r_usesurfaceculling = {0, "r_usesurfaceculling", "1", "improve framerate by culling offscreen surfaces"};
+cvar_t r_usesurfaceculling = {0, "r_usesurfaceculling", "1", "skip off-screen surfaces (1 = cull surfaces if the map is likely to benefit, 2 = always cull surfaces)"};
cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0", "draws sky depth masking in q3 maps (as in q1 maps), this means for example that sky polygons can hide other things"};
/*
}
}
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ Image_MakesRGBColorsFromLinear_Lightmap(templight, templight, size);
R_UpdateTexture(surface->lightmaptexture, templight, surface->lightmapinfo->lightmaporigin[0], surface->lightmapinfo->lightmaporigin[1], 0, smax, tmax, 1);
// update the surface's deluxemap if it has one
}
}
-void R_StainNode (mnode_t *node, dp_model_t *model, const vec3_t origin, float radius, const float fcolor[8])
+static void R_StainNode (mnode_t *node, dp_model_t *model, const vec3_t origin, float radius, const float fcolor[8])
{
float ndist, a, ratio, maxdist, maxdist2, maxdist3, invradius, sdtable[256], td, dist2;
msurface_t *surface, *endsurface;
for (i = 0, v = vertex3f;i < numpoints;i++, v += 3)
VectorCopy(portal->points[i].position, v);
R_Mesh_PrepareVertices_Generic_Arrays(numpoints, vertex3f, NULL, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
R_Mesh_Draw(0, numpoints, 0, numpoints - 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
VectorAdd(center, portal->points[i].position, center);
f = ixtable[portal->numpoints];
VectorScale(center, f, center);
- R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, rsurface.rtlight);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, rsurface.rtlight);
}
}
}
}
}
+static void R_View_WorldVisibility_CullSurfaces(void)
+{
+ int surfaceindex;
+ int surfaceindexstart;
+ int surfaceindexend;
+ unsigned char *surfacevisible;
+ msurface_t *surfaces;
+ dp_model_t *model = r_refdef.scene.worldmodel;
+ if (!model)
+ return;
+ if (r_trippy.integer)
+ return;
+ if (r_usesurfaceculling.integer < 1)
+ return;
+ surfaceindexstart = model->firstmodelsurface;
+ surfaceindexend = surfaceindexstart + model->nummodelsurfaces;
+ surfaces = model->data_surfaces;
+ surfacevisible = r_refdef.viewcache.world_surfacevisible;
+ for (surfaceindex = surfaceindexstart;surfaceindex < surfaceindexend;surfaceindex++)
+ if (surfacevisible[surfaceindex] && R_CullBox(surfaces[surfaceindex].mins, surfaces[surfaceindex].maxs))
+ surfacevisible[surfaceindex] = 0;
+}
+
void R_View_WorldVisibility(qboolean forcenovis)
{
int i, j, *mark;
r_refdef.viewcache.world_surfacevisible[*mark] = true;
}
}
+ R_View_WorldVisibility_CullSurfaces();
return;
}
}
}
- if (r_usesurfaceculling.integer)
- {
- int k = model->firstmodelsurface;
- int l = k + model->nummodelsurfaces;
- unsigned char *visible = r_refdef.viewcache.world_surfacevisible;
- msurface_t *surfaces = model->data_surfaces;
- msurface_t *surface;
- for (;k < l;k++)
- {
- if (visible[k])
- {
- surface = surfaces + k;
- if (R_CullBox(surface->mins, surface->maxs))
- visible[k] = false;
- }
- }
-}
+ R_View_WorldVisibility_CullSurfaces();
}
void R_Q1BSP_DrawSky(entity_render_t *ent)
R_DrawModelSurfaces(ent, true, true, false, false, false);
}
-extern void R_Water_AddWaterPlane(msurface_t *surface, int entno);
void R_Q1BSP_DrawAddWaterPlanes(entity_render_t *ent)
{
int i, j, n, flagsmask;
if (ent == r_refdef.scene.worldentity)
RSurf_ActiveWorldEntity();
else
- RSurf_ActiveModelEntity(ent, false, false, false);
+ RSurf_ActiveModelEntity(ent, true, false, false);
surfaces = model->data_surfaces;
flagsmask = MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA;
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
// R_Mesh_ResetTextureState();
- R_SetupShader_DepthOrShadow(false);
+ R_SetupShader_DepthOrShadow(false, false);
if (ent == r_refdef.scene.worldentity)
R_DrawWorldSurfaces(false, false, true, false, false);
else
static msurface_t *r_q1bsp_getlightinfo_surfaces;
-int R_Q1BSP_GetLightInfo_comparefunc(const void *ap, const void *bp)
+static int R_Q1BSP_GetLightInfo_comparefunc(const void *ap, const void *bp)
{
int a = *(int*)ap;
int b = *(int*)bp;
int surfacelistindex;
int sidetotals[6] = { 0, 0, 0, 0, 0, 0 }, sidemasks = 0;
int i;
+ if (!model->brush.shadowmesh)
+ return;
r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap = Mod_ShadowMesh_Begin(r_main_mempool, 32768, 32768, NULL, NULL, NULL, false, false, true);
R_Shadow_PrepareShadowSides(model->brush.shadowmesh->numtriangles);
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
;
// now figure out what to do with this particular range of surfaces
// VorteX: added MATERIALFLAG_NORTLIGHT
- if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WALL + MATERIALFLAG_NORTLIGHT)) != MATERIALFLAG_WALL)
+ if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NORTLIGHT)) != MATERIALFLAG_WALL)
continue;
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
+ if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
continue;
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
{
for (l = k;l < kend;l++)
{
surface = batchsurfacelist[l];
- tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
- tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
- tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ if (r_transparent_sortsurfacesbynearest.integer)
+ {
+ tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
+ tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
+ tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
+ }
+ else
+ {
+ tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+ tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+ tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ }
Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
- R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_Q1BSP_DrawLight_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ if (ent->transparent_offset) // transparent offset
+ {
+ center[0] += r_refdef.view.forward[0]*ent->transparent_offset;
+ center[1] += r_refdef.view.forward[1]*ent->transparent_offset;
+ center[2] += r_refdef.view.forward[2]*ent->transparent_offset;
+ }
+ R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_Q1BSP_DrawLight_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
}
continue;
}
}
//Made by [515]
-void R_ReplaceWorldTexture (void)
+static void R_ReplaceWorldTexture (void)
{
dp_model_t *m;
texture_t *t;
}
//Made by [515]
-void R_ListWorldTextures (void)
+static void R_ListWorldTextures (void)
{
dp_model_t *m;
texture_t *t;
#include "intoverflow.h"
#include "dpsoftrast.h"
+#ifndef GL_TEXTURE_3D
+#define GL_TEXTURE_3D 0x806F
+#endif
+
cvar_t gl_max_size = {CVAR_SAVE, "gl_max_size", "2048", "maximum allowed texture size, can be used to reduce video memory usage, limited by hardware capabilities (typically 2048, 4096, or 8192)"};
cvar_t gl_max_lightmapsize = {CVAR_SAVE, "gl_max_lightmapsize", "1024", "maximum allowed texture size for lightmap textures, use larger values to improve rendering speed, as long as there is enough video memory available (setting it too high for the hardware will cause very bad performance)"};
cvar_t gl_picmip = {CVAR_SAVE, "gl_picmip", "0", "reduces resolution of textures by powers of 2, for example 1 will halve width/height, reducing texture memory usage by 75%"};
}
textypeinfo_t;
+#ifdef USE_GLES2
+// framebuffer texture formats
+// GLES2 devices rarely support depth textures, so we actually use a renderbuffer there
+static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap16_raw = {"shadowmap16_raw", TEXTYPE_SHADOWMAP16_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap24_comp = {"shadowmap24_comp", TEXTYPE_SHADOWMAP24_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap24_raw = {"shadowmap24_raw", TEXTYPE_SHADOWMAP24_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_depth16 = {"depth16", TEXTYPE_DEPTHBUFFER16 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_depth24 = {"depth24", TEXTYPE_DEPTHBUFFER24 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_depth24stencil8 = {"depth24stencil8", TEXTYPE_DEPTHBUFFER24STENCIL8, 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 2, 2, 2.0f, GL_RGB565 , GL_RGBA , GL_UNSIGNED_SHORT_5_6_5};
+static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F , 2, 2, 2.0f, GL_RGB565 , GL_RGBA , GL_UNSIGNED_SHORT_5_6_5};
+static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F , 2, 2, 2.0f, GL_RGB565 , GL_RGBA , GL_UNSIGNED_SHORT_5_6_5};
+
+// image formats:
+static textypeinfo_t textype_alpha = {"alpha", TEXTYPE_ALPHA , 1, 4, 4.0f, GL_ALPHA , GL_ALPHA , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_palette = {"palette", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_palette_alpha = {"palette_alpha", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba = {"rgba", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_rgba_alpha = {"rgba_alpha", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_bgra = {"bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_bgra_alpha = {"bgra_alpha", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
+#else
// framebuffer texture formats
-static textypeinfo_t textype_shadowmap16 = {"shadowmap16", TEXTYPE_SHADOWMAP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
-static textypeinfo_t textype_shadowmap24 = {"shadowmap24", TEXTYPE_SHADOWMAP , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
-static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
-static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F, 8, 8, 8.0f, GL_RGBA16F_ARB , GL_RGBA , GL_FLOAT };
-static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F, 16, 16, 16.0f, GL_RGBA32F_ARB , GL_RGBA , GL_FLOAT };
+static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap16_raw = {"shadowmap16_raw", TEXTYPE_SHADOWMAP16_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap24_comp = {"shadowmap24_comp", TEXTYPE_SHADOWMAP24_COMP , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
+static textypeinfo_t textype_shadowmap24_raw = {"shadowmap24_raw", TEXTYPE_SHADOWMAP24_RAW , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
+static textypeinfo_t textype_depth16 = {"depth16", TEXTYPE_DEPTHBUFFER16 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_depth24 = {"depth24", TEXTYPE_DEPTHBUFFER24 , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
+static textypeinfo_t textype_depth24stencil8 = {"depth24stencil8", TEXTYPE_DEPTHBUFFER24STENCIL8, 4, 4, 4.0f, GL_DEPTH24_STENCIL8_EXT , GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT};
+static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
+static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F , 8, 8, 8.0f, GL_RGBA16F_ARB , GL_RGBA , GL_FLOAT };
+static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F , 16, 16, 16.0f, GL_RGBA32F_ARB , GL_RGBA , GL_FLOAT };
// image formats:
static textypeinfo_t textype_alpha = {"alpha", TEXTYPE_ALPHA , 1, 4, 4.0f, GL_ALPHA , GL_ALPHA , GL_UNSIGNED_BYTE };
static textypeinfo_t textype_sRGB_dxt1a = {"sRGB_dxt1a", TEXTYPE_DXT1A , 4, 0, 0.5f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0 , 0 };
static textypeinfo_t textype_sRGB_dxt3 = {"sRGB_dxt3", TEXTYPE_DXT3 , 4, 0, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0 , 0 };
static textypeinfo_t textype_sRGB_dxt5 = {"sRGB_dxt5", TEXTYPE_DXT5 , 4, 0, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0 , 0 };
+#endif
typedef enum gltexturetype_e
{
}
gltexturetype_t;
-static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB};
+static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP};
static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2};
static int cubemapside[6] =
{
- GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};
typedef struct gltexture_s
// this portion of the struct is exposed to the R_GetTexture macro for
// speed reasons, must be identical in rtexture_t!
int texnum; // GL texture slot number
+ int renderbuffernum; // GL renderbuffer slot number
qboolean dirty; // indicates that R_RealGetTexture should be called
+ qboolean glisdepthstencil; // indicates that FBO attachment has to be GL_DEPTH_STENCIL_ATTACHMENT
int gltexturetypeenum; // used by R_Mesh_TexBind
// d3d stuff the backend needs
void *d3dtexture;
+ void *d3dsurface;
#ifdef SUPPORTD3D
- qboolean d3disdepthsurface; // for depth/stencil surfaces
+ qboolean d3disrendertargetsurface;
+ qboolean d3disdepthstencilsurface;
int d3dformat;
int d3dusage;
int d3dpool;
case TEXTYPE_RGBA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_rgba_alpha_compress : &textype_rgba_compress) : ((flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba);
case TEXTYPE_BGRA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_bgra_alpha_compress : &textype_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra);
case TEXTYPE_ALPHA: return &textype_alpha;
- case TEXTYPE_SHADOWMAP: return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
case TEXTYPE_COLORBUFFER: return &textype_colorbuffer;
case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f;
case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f;
+ case TEXTYPE_DEPTHBUFFER16: return &textype_depth16;
+ case TEXTYPE_DEPTHBUFFER24: return &textype_depth24;
+ case TEXTYPE_DEPTHBUFFER24STENCIL8: return &textype_depth24stencil8;
+ case TEXTYPE_SHADOWMAP16_COMP: return &textype_shadowmap16_comp;
+ case TEXTYPE_SHADOWMAP16_RAW: return &textype_shadowmap16_raw;
+ case TEXTYPE_SHADOWMAP24_COMP: return &textype_shadowmap24_comp;
+ case TEXTYPE_SHADOWMAP24_RAW: return &textype_shadowmap24_raw;
case TEXTYPE_SRGB_DXT1: return &textype_sRGB_dxt1;
case TEXTYPE_SRGB_DXT1A: return &textype_sRGB_dxt1a;
case TEXTYPE_SRGB_DXT3: return &textype_sRGB_dxt3;
CHECKGLERROR
qglDeleteTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
}
+ if (glt->renderbuffernum)
+ {
+ CHECKGLERROR
+ qglDeleteRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
+ }
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
- if (glt->d3disdepthsurface)
- IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dtexture);
+ if (glt->d3dsurface)
+ IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dsurface);
else if (glt->tiledepth > 1)
IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
else if (glt->sides == 6)
else
IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
glt->d3dtexture = NULL;
+ glt->d3dsurface = NULL;
#endif
break;
case RENDERPATH_D3D10:
for (glt = pool->gltchain;glt;glt = glt->chain)
{
// only update already uploaded images
- if (glt->d3dtexture && !glt->d3disdepthsurface && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
+ if (glt->d3dtexture && !glt->d3dsurface && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
{
if (glt->flags & TEXF_MIPMAP)
{
for (glt = pool->gltchain;glt;glt = glt->chain)
{
glsize = R_CalcTexelDataSize(glt);
- isloaded = glt->texnum != 0;
+ isloaded = glt->texnum != 0 || glt->renderbuffernum != 0 || glt->d3dtexture || glt->d3dsurface;
pooltotal++;
pooltotalt += glsize;
pooltotalp += glt->inputdatasize;
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
- if (glt->d3disdepthsurface)
- IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dtexture);
+ if (glt->d3dsurface)
+ IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dsurface);
else if (glt->tiledepth > 1)
IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
else if (glt->sides == 6)
else
IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
glt->d3dtexture = NULL;
+ glt->d3dsurface = NULL;
#endif
break;
case RENDERPATH_D3D10:
#ifdef SUPPORTD3D
{
HRESULT d3dresult;
- if (glt->d3disdepthsurface)
+ if (glt->d3disrendertargetsurface)
+ {
+ if (FAILED(d3dresult = IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
+ Sys_Error("IDirect3DDevice9_CreateRenderTarget failed!");
+ }
+ else if (glt->d3disdepthstencilsurface)
{
- if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dtexture, NULL)))
+ if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
}
else if (glt->tiledepth > 1)
}
}
-void R_MakeResizeBufferBigger(int size)
+static void R_MakeResizeBufferBigger(int size)
{
if (resizebuffersize < size)
{
}
qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);CHECKGLERROR
qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);CHECKGLERROR
+#ifdef GL_TEXTURE_WRAP_R
if (gltexturetypedimensions[texturetype] >= 3)
{
qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode);CHECKGLERROR
}
+#endif
CHECKGLERROR
if (!gl_filter_force && flags & TEXF_FORCENEAREST)
qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR
}
- if (textype == TEXTYPE_SHADOWMAP)
+ switch(textype)
{
- if (vid.support.arb_shadow)
- {
- if (flags & TEXF_COMPARE)
- {
- qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
- }
- else
- {
- qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
- }
- qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
- }
+ case TEXTYPE_SHADOWMAP16_COMP:
+ case TEXTYPE_SHADOWMAP24_COMP:
+ qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
+ qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
+ break;
+ case TEXTYPE_SHADOWMAP16_RAW:
+ case TEXTYPE_SHADOWMAP24_RAW:
+ qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
+ qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
+ qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
+ break;
+ default:
+ break;
}
CHECKGLERROR
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
- CHECKGLERROR
-
- // we need to restore the texture binding after finishing the upload
- GL_ActiveTexture(0);
- oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
- qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
-
- if (qglGetCompressedTexImageARB)
+ if (glt->texnum) // not renderbuffers
{
- if (gl_texturecompression.integer >= 2)
- qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
- else
- qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST);
CHECKGLERROR
- }
- switch(glt->texturetype)
- {
- case GLTEXTURETYPE_2D:
- qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
- if (glt->flags & TEXF_MIPMAP)
- {
- while (width > 1 || height > 1 || depth > 1)
- {
- Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
- prevbuffer = resizebuffer;
- qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
- }
- }
- break;
- case GLTEXTURETYPE_3D:
- qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
- if (glt->flags & TEXF_MIPMAP)
+
+ // we need to restore the texture binding after finishing the upload
+ GL_ActiveTexture(0);
+ oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
+ qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
+
+#ifdef GL_TEXTURE_COMPRESSION_HINT_ARB
+ if (qglGetCompressedTexImageARB)
{
- while (width > 1 || height > 1 || depth > 1)
- {
- Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
- prevbuffer = resizebuffer;
- qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
- }
+ if (gl_texturecompression.integer >= 2)
+ qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
+ else
+ qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST);
+ CHECKGLERROR
}
- break;
- case GLTEXTURETYPE_CUBEMAP:
- // convert and upload each side in turn,
- // from a continuous block of input texels
- texturebuffer = (unsigned char *)prevbuffer;
- for (i = 0;i < 6;i++)
+#endif
+ switch(glt->texturetype)
{
- prevbuffer = texturebuffer;
- texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
- if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
- {
- Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
- prevbuffer = resizebuffer;
- }
- // picmip/max_size
- while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
+ case GLTEXTURETYPE_2D:
+ qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
+ if (glt->flags & TEXF_MIPMAP)
{
- Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
- prevbuffer = resizebuffer;
+ while (width > 1 || height > 1 || depth > 1)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
+ prevbuffer = resizebuffer;
+ qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
+ }
}
- mip = 0;
- qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
+ break;
+ case GLTEXTURETYPE_3D:
+#ifndef USE_GLES2
+ qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
if (glt->flags & TEXF_MIPMAP)
{
while (width > 1 || height > 1 || depth > 1)
{
Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
prevbuffer = resizebuffer;
- qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
+ qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
+ }
+ }
+#endif
+ break;
+ case GLTEXTURETYPE_CUBEMAP:
+ // convert and upload each side in turn,
+ // from a continuous block of input texels
+ texturebuffer = (unsigned char *)prevbuffer;
+ for (i = 0;i < 6;i++)
+ {
+ prevbuffer = texturebuffer;
+ texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
+ if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
+ {
+ Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
+ prevbuffer = resizebuffer;
+ }
+ // picmip/max_size
+ while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
+ prevbuffer = resizebuffer;
+ }
+ mip = 0;
+ qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
+ if (glt->flags & TEXF_MIPMAP)
+ {
+ while (width > 1 || height > 1 || depth > 1)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
+ prevbuffer = resizebuffer;
+ qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
+ }
}
}
+ break;
}
- break;
+ GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
+ qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
}
- GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
- qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
- if (!(glt->flags & TEXF_RENDERTARGET))
+ if (!(glt->flags & TEXF_RENDERTARGET) && glt->d3dtexture && !glt->d3dsurface)
{
D3DLOCKED_RECT d3dlockedrect;
D3DLOCKED_BOX d3dlockedbox;
return NULL;
// see if we need to swap red and blue (BGRA <-> RGBA conversion)
+ if (textype == TEXTYPE_PALETTE && vid.forcetextype == TEXTYPE_RGBA)
+ {
+ int numpixels = width * height * depth * sides;
+ size = numpixels * 4;
+ temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
+ if (data)
+ {
+ const unsigned char *p;
+ unsigned char *o = temppixels;
+ for (i = 0;i < numpixels;i++, o += 4)
+ {
+ p = (const unsigned char *)palette + 4*data[i];
+ o[0] = p[2];
+ o[1] = p[1];
+ o[2] = p[0];
+ o[3] = p[3];
+ }
+ }
+ data = temppixels;
+ textype = TEXTYPE_RGBA;
+ }
swaprb = false;
switch(textype)
{
static int rgbaswapindices[4] = {2, 1, 0, 3};
size = width * height * depth * sides * 4;
temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
- Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
+ if (data)
+ Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
data = temppixels;
}
{
temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
memcpy(temppixels, data, size);
+ data = temppixels;
}
Image_MakeLinearColorsFromsRGB(temppixels, temppixels, width*height*depth*sides);
}
}
}
break;
- case TEXTYPE_SHADOWMAP:
+ case TEXTYPE_SHADOWMAP16_COMP:
+ case TEXTYPE_SHADOWMAP16_RAW:
+ case TEXTYPE_SHADOWMAP24_COMP:
+ case TEXTYPE_SHADOWMAP24_RAW:
break;
case TEXTYPE_DXT1:
case TEXTYPE_SRGB_DXT1:
glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
glt->texnum = 0;
glt->dirty = false;
+ glt->glisdepthstencil = false;
glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
// init the dynamic texture attributes, too [11/22/2007 Black]
glt->updatecallback = NULL;
case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;break;
case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;break;
case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;break;
- case TEXTYPE_SHADOWMAP: d3dformat = D3DFMT_D16;d3dusage = D3DUSAGE_DEPTHSTENCIL;break; // note: can not use D3DUSAGE_RENDERTARGET here
case TEXTYPE_ALPHA: d3dformat = D3DFMT_A8;break;
default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTexture: unsupported texture type %i when picking D3DFMT", (int)textype);break;
}
glt->d3dformat = d3dformat;
glt->d3dusage = d3dusage;
glt->d3dpool = d3dpool;
- glt->d3disdepthsurface = textype == TEXTYPE_SHADOWMAP;
- if (glt->d3disdepthsurface)
- {
- if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dtexture, NULL)))
- Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
- }
- else if (glt->tiledepth > 1)
+ glt->d3disrendertargetsurface = false;
+ glt->d3disdepthstencilsurface = false;
+ if (glt->tiledepth > 1)
{
if (FAILED(d3dresult = IDirect3DDevice9_CreateVolumeTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->tiledepth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DVolumeTexture9 **)&glt->d3dtexture, NULL)))
Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F;break;
case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F;break;
- case TEXTYPE_SHADOWMAP: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
+ case TEXTYPE_SHADOWMAP16_COMP:
+ case TEXTYPE_SHADOWMAP16_RAW:
+ case TEXTYPE_SHADOWMAP24_COMP:
+ case TEXTYPE_SHADOWMAP24_RAW: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
+ case TEXTYPE_DEPTHBUFFER16:
+ case TEXTYPE_DEPTHBUFFER24:
+ case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
case TEXTYPE_ALPHA: tflags = DPSOFTRAST_TEXTURE_FORMAT_ALPHA8;break;
default: Sys_Error("R_LoadTexture: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
}
return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, miplevel, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
}
-static int R_ShadowMapTextureFlags(int precision, qboolean filter)
+rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype, qboolean filter)
{
- int flags = TEXF_RENDERTARGET | TEXF_CLAMP;
- if (filter)
- flags |= TEXF_FORCELINEAR | TEXF_COMPARE;
- else
- flags |= TEXF_FORCENEAREST;
- if (precision <= 16)
- flags |= TEXF_LOWPRECISION;
- return flags;
+ return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_RENDERTARGET | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR : TEXF_FORCENEAREST), -1, textype, GLTEXTURETYPE_2D, NULL, NULL);
}
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
+rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype)
{
- return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
+ gltexture_t *glt;
+ gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
+ textypeinfo_t *texinfo;
+
+ if (cls.state == ca_dedicated)
+ return NULL;
+
+ texinfo = R_GetTexTypeInfo(textype, TEXF_RENDERTARGET | TEXF_CLAMP);
+
+ glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
+ if (identifier)
+ strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
+ glt->pool = pool;
+ glt->chain = pool->gltchain;
+ pool->gltchain = glt;
+ glt->inputwidth = width;
+ glt->inputheight = height;
+ glt->inputdepth = 1;
+ glt->flags = TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_FORCENEAREST;
+ glt->miplevel = 0;
+ glt->textype = texinfo;
+ glt->texturetype = textype;
+ glt->inputdatasize = width*height*texinfo->internalbytesperpixel;
+ glt->palette = NULL;
+ glt->glinternalformat = texinfo->glinternalformat;
+ glt->glformat = texinfo->glformat;
+ glt->gltype = texinfo->gltype;
+ glt->bytesperpixel = texinfo->internalbytesperpixel;
+ glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
+ glt->texnum = 0;
+ glt->dirty = false;
+ glt->glisdepthstencil = glt->texturetype == TEXTYPE_DEPTHBUFFER24STENCIL8;
+ glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
+ // init the dynamic texture attributes, too [11/22/2007 Black]
+ glt->updatecallback = NULL;
+ glt->updatacallback_data = NULL;
+
+ GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels);
+
+ // upload the texture
+ // data may be NULL (blank texture for dynamic rendering)
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ qglGenRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
+ qglBindRenderbuffer(GL_RENDERBUFFER, glt->renderbuffernum);CHECKGLERROR
+ qglRenderbufferStorage(GL_RENDERBUFFER, glt->glinternalformat, glt->tilewidth, glt->tileheight);CHECKGLERROR
+ // note we can query the renderbuffer for info with glGetRenderbufferParameteriv for GL_WIDTH, GL_HEIGHt, GL_RED_SIZE, GL_GREEN_SIZE, GL_BLUE_SIZE, GL_GL_ALPHA_SIZE, GL_DEPTH_SIZE, GL_STENCIL_SIZE, GL_INTERNAL_FORMAT
+ qglBindRenderbuffer(GL_RENDERBUFFER, 0);CHECKGLERROR
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ {
+ D3DFORMAT d3dformat;
+ HRESULT d3dresult;
+ glt->d3disrendertargetsurface = false;
+ glt->d3disdepthstencilsurface = false;
+ switch(textype)
+ {
+ case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;glt->d3disrendertargetsurface = true;break;
+ case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;glt->d3disrendertargetsurface = true;break;
+ case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;glt->d3disrendertargetsurface = true;break;
+ case TEXTYPE_DEPTHBUFFER16: d3dformat = D3DFMT_D16;glt->d3disdepthstencilsurface = true;break;
+ case TEXTYPE_DEPTHBUFFER24: d3dformat = D3DFMT_D24X8;glt->d3disdepthstencilsurface = true;break;
+ case TEXTYPE_DEPTHBUFFER24STENCIL8: d3dformat = D3DFMT_D24S8;glt->d3disdepthstencilsurface = true;break;
+ default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking D3DFMT", (int)textype);break;
+ }
+ glt->d3dformat = d3dformat;
+ glt->d3dusage = 0;
+ glt->d3dpool = 0;
+ if (glt->d3disrendertargetsurface)
+ {
+ if (FAILED(d3dresult = IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
+ Sys_Error("IDirect3DDevice9_CreateRenderTarget failed!");
+ }
+ else if (glt->d3disdepthstencilsurface)
+ {
+ if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
+ Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
+ }
+ }
+#endif
+ break;
+ case RENDERPATH_D3D10:
+ Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ case RENDERPATH_D3D11:
+ Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ case RENDERPATH_SOFT:
+ {
+ int tflags = 0;
+ switch(textype)
+ {
+ case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8 | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
+ case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
+ case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
+ case TEXTYPE_DEPTHBUFFER16:
+ case TEXTYPE_DEPTHBUFFER24:
+ case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
+ default: Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
+ }
+ glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
+ }
+ break;
+ }
+
+ return (rtexture_t *)glt;
}
int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha)
{
+#ifdef USE_GLES2
+ return -1; // unsupported on this platform
+#else
gltexture_t *glt = (gltexture_t *)rt;
unsigned char *dds;
int oldbindtexnum;
mipinfo[0][0] = glt->tilewidth;
mipinfo[0][1] = glt->tileheight;
mipmaps = 1;
- if (glt->flags & TEXF_MIPMAP)
+ if ((glt->flags & TEXF_MIPMAP) && !(glt->tilewidth == 1 && glt->tilewidth == 1))
{
for (mip = 1;mip < 16;mip++)
{
if(hasalpha)
dds_format_flags |= 0x1; // DDPF_ALPHAPIXELS
memcpy(dds, "DDS ", 4);
- StoreLittleLong(dds+4, ddssize);
+ StoreLittleLong(dds+4, 124); // http://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx says so
StoreLittleLong(dds+8, dds_flags);
StoreLittleLong(dds+12, mipinfo[0][1]); // height
StoreLittleLong(dds+16, mipinfo[0][0]); // width
- StoreLittleLong(dds+24, 1); // depth
+ StoreLittleLong(dds+24, 0); // depth
StoreLittleLong(dds+28, mipmaps); // mipmaps
StoreLittleLong(dds+76, 32); // format size
StoreLittleLong(dds+80, dds_format_flags);
ret = FS_WriteFile(filename, dds, ddssize);
Mem_Free(dds);
return ret ? ddssize : -5;
+#endif
}
-rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint
+rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint
{
int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height;
//int dds_flags;
gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
textypeinfo_t *texinfo;
int mip, mipwidth, mipheight, mipsize, mipsize_total;
- unsigned int c;
+ unsigned int c, r, g, b;
GLint oldbindtexnum = 0;
- const unsigned char *mippixels, *ddspixels, *mippixels_start;
+ unsigned char *mippixels;
+ unsigned char *mippixels_start;
+ unsigned char *ddspixels;
unsigned char *dds;
fs_offset_t ddsfilesize;
unsigned int ddssize;
Con_Printf("^1%s: invalid DXT1 DDS image\n", filename);
return NULL;
}
- if(r_texture_dds_load_alphamode.integer && (flags & TEXF_ALPHA))
+ if (flags & TEXF_ALPHA)
{
- if(r_texture_dds_load_alphamode.integer == 1)
+ if (r_texture_dds_load_alphamode.integer == 1)
{
// check alpha
for (i = 0;i < size;i += bytesperblock)
else
flags &= ~TEXF_ALPHA;
}
+ else if (r_texture_dds_load_alphamode.integer == 0)
+ textype = TEXTYPE_DXT1A;
else
{
flags &= ~TEXF_ALPHA;
return NULL;
}
+ // when requesting a non-alpha texture and we have DXT3/5, convert to DXT1
+ if(!(flags & TEXF_ALPHA) && (textype == TEXTYPE_DXT3 || textype == TEXTYPE_DXT5))
+ {
+ textype = TEXTYPE_DXT1;
+ bytesperblock = 8;
+ ddssize -= 128;
+ ddssize /= 2;
+ for (i = 0;i < (int)ddssize;i += bytesperblock)
+ memcpy(&ddspixels[i], &ddspixels[(i<<1)+8], 8);
+ ddssize += 128;
+ }
+
force_swdecode = false;
if(bytesperblock)
{
}
}
+ // if we want sRGB, convert now
+ if(srgb)
+ {
+ if (vid.support.ext_texture_srgb)
+ {
+ switch(textype)
+ {
+ case TEXTYPE_DXT1: textype = TEXTYPE_SRGB_DXT1 ;break;
+ case TEXTYPE_DXT1A: textype = TEXTYPE_SRGB_DXT1A ;break;
+ case TEXTYPE_DXT3: textype = TEXTYPE_SRGB_DXT3 ;break;
+ case TEXTYPE_DXT5: textype = TEXTYPE_SRGB_DXT5 ;break;
+ case TEXTYPE_RGBA: textype = TEXTYPE_SRGB_RGBA ;break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch(textype)
+ {
+ case TEXTYPE_DXT1:
+ case TEXTYPE_DXT1A:
+ case TEXTYPE_DXT3:
+ case TEXTYPE_DXT5:
+ {
+ for (i = bytesperblock == 16 ? 8 : 0;i < mipsize_total;i += bytesperblock)
+ {
+ int c0, c1, c0new, c1new;
+ c0 = mippixels_start[i] + 256*mippixels_start[i+1];
+ r = ((c0 >> 11) & 0x1F);
+ g = ((c0 >> 5) & 0x3F);
+ b = ((c0 ) & 0x1F);
+ r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+ g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+ b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+ c0new = (r << 11) | (g << 5) | b;
+ c1 = mippixels_start[i+2] + 256*mippixels_start[i+3];
+ r = ((c1 >> 11) & 0x1F);
+ g = ((c1 >> 5) & 0x3F);
+ b = ((c1 ) & 0x1F);
+ r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+ g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+ b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
+ c1new = (r << 11) | (g << 5) | b;
+ // swap the colors if needed to fix order
+ if(c0 > c1) // thirds
+ {
+ if(c0new < c1new)
+ {
+ c = c0new;
+ c0new = c1new;
+ c1new = c;
+ if(c0new == c1new)
+ mippixels_start[i+4] ^= 0x55;
+ mippixels_start[i+5] ^= 0x55;
+ mippixels_start[i+6] ^= 0x55;
+ mippixels_start[i+7] ^= 0x55;
+ }
+ else if(c0new == c1new)
+ {
+ mippixels_start[i+4] = 0x00;
+ mippixels_start[i+5] = 0x00;
+ mippixels_start[i+6] = 0x00;
+ mippixels_start[i+7] = 0x00;
+ }
+ }
+ else // half + transparent
+ {
+ if(c0new > c1new)
+ {
+ c = c0new;
+ c0new = c1new;
+ c1new = c;
+ mippixels_start[i+4] ^= (~mippixels_start[i+4] >> 1) & 0x55;
+ mippixels_start[i+5] ^= (~mippixels_start[i+5] >> 1) & 0x55;
+ mippixels_start[i+6] ^= (~mippixels_start[i+6] >> 1) & 0x55;
+ mippixels_start[i+7] ^= (~mippixels_start[i+7] >> 1) & 0x55;
+ }
+ }
+ mippixels_start[i] = c0new & 255;
+ mippixels_start[i+1] = c0new >> 8;
+ mippixels_start[i+2] = c1new & 255;
+ mippixels_start[i+3] = c1new >> 8;
+ }
+ }
+ break;
+ case TEXTYPE_RGBA:
+ Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
// when not requesting mipmaps, do not load them
if(!(flags & TEXF_MIPMAP))
dds_miplevels = 0;
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef GL_TEXTURE_MAX_LEVEL
if (dds_miplevels >= 1 && !mipcomplete)
{
// need to set GL_TEXTURE_MAX_LEVEL
qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
}
+#endif
GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
break;
return rt ? ((gltexture_t *)rt)->inputheight : 0;
}
+int R_TextureFlags(rtexture_t *rt)
+{
+ return rt ? ((gltexture_t *)rt)->flags : 0;
+}
+
void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int z, int width, int height, int depth)
{
gltexture_t *glt = (gltexture_t *)rt;
#ifndef GLQUAKE_H
#define GLQUAKE_H
+#ifdef USE_GLES2
+#ifdef __IPHONEOS__
+#include <OpenGLES/ES2/gl.h>
+#else
+#include <SDL_opengles2.h>
+#endif
+// used in R_SetupShader_Generic calls, not actually passed to GL
+#ifndef GL_MODULATE
+#define GL_MODULATE 0x2100
+#define GL_DECAL 0x2101
+#define GL_ADD 0x0104
+#endif
+#endif
+
// disable data conversion warnings
#ifdef _MSC_VER
//====================================================
+#ifndef USE_GLES2
// wgl uses APIENTRY
#ifndef APIENTRY
#define APIENTRY
extern void (GLAPIENTRY *qglMultiTexCoord4f) (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
extern void (GLAPIENTRY *qglActiveTexture) (GLenum);
extern void (GLAPIENTRY *qglClientActiveTexture) (GLenum);
-#ifndef GL_ACTIVE_TEXTURE_ARB
-#define GL_ACTIVE_TEXTURE_ARB 0x84E0
-#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
-#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
-#define GL_TEXTURE0_ARB 0x84C0
-#define GL_TEXTURE1_ARB 0x84C1
-#define GL_TEXTURE2_ARB 0x84C2
-#define GL_TEXTURE3_ARB 0x84C3
-#define GL_TEXTURE4_ARB 0x84C4
-#define GL_TEXTURE5_ARB 0x84C5
-#define GL_TEXTURE6_ARB 0x84C6
-#define GL_TEXTURE7_ARB 0x84C7
-#define GL_TEXTURE8_ARB 0x84C8
-#define GL_TEXTURE9_ARB 0x84C9
-#define GL_TEXTURE10_ARB 0x84CA
-#define GL_TEXTURE11_ARB 0x84CB
-#define GL_TEXTURE12_ARB 0x84CC
-#define GL_TEXTURE13_ARB 0x84CD
-#define GL_TEXTURE14_ARB 0x84CE
-#define GL_TEXTURE15_ARB 0x84CF
-#define GL_TEXTURE16_ARB 0x84D0
-#define GL_TEXTURE17_ARB 0x84D1
-#define GL_TEXTURE18_ARB 0x84D2
-#define GL_TEXTURE19_ARB 0x84D3
-#define GL_TEXTURE20_ARB 0x84D4
-#define GL_TEXTURE21_ARB 0x84D5
-#define GL_TEXTURE22_ARB 0x84D6
-#define GL_TEXTURE23_ARB 0x84D7
-#define GL_TEXTURE24_ARB 0x84D8
-#define GL_TEXTURE25_ARB 0x84D9
-#define GL_TEXTURE26_ARB 0x84DA
-#define GL_TEXTURE27_ARB 0x84DB
-#define GL_TEXTURE28_ARB 0x84DC
-#define GL_TEXTURE29_ARB 0x84DD
-#define GL_TEXTURE30_ARB 0x84DE
-#define GL_TEXTURE31_ARB 0x84DF
+#ifndef GL_ACTIVE_TEXTURE
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
#endif
// GL_ARB_texture_env_combine
-#ifndef GL_COMBINE_ARB
-#define GL_COMBINE_ARB 0x8570
-#define GL_COMBINE_RGB_ARB 0x8571
-#define GL_COMBINE_ALPHA_ARB 0x8572
-#define GL_SOURCE0_RGB_ARB 0x8580
-#define GL_SOURCE1_RGB_ARB 0x8581
-#define GL_SOURCE2_RGB_ARB 0x8582
-#define GL_SOURCE0_ALPHA_ARB 0x8588
-#define GL_SOURCE1_ALPHA_ARB 0x8589
-#define GL_SOURCE2_ALPHA_ARB 0x858A
-#define GL_OPERAND0_RGB_ARB 0x8590
-#define GL_OPERAND1_RGB_ARB 0x8591
-#define GL_OPERAND2_RGB_ARB 0x8592
-#define GL_OPERAND0_ALPHA_ARB 0x8598
-#define GL_OPERAND1_ALPHA_ARB 0x8599
-#define GL_OPERAND2_ALPHA_ARB 0x859A
-#define GL_RGB_SCALE_ARB 0x8573
-#define GL_ADD_SIGNED_ARB 0x8574
-#define GL_INTERPOLATE_ARB 0x8575
-#define GL_SUBTRACT_ARB 0x84E7
-#define GL_CONSTANT_ARB 0x8576
-#define GL_PRIMARY_COLOR_ARB 0x8577
-#define GL_PREVIOUS_ARB 0x8578
+#ifndef GL_COMBINE
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
#endif
#ifndef GL_MAX_ELEMENTS_VERTICES
extern void (GLAPIENTRY *qglCopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
#endif
-#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
-#define GL_NORMAL_MAP_ARB 0x8511
-#define GL_REFLECTION_MAP_ARB 0x8512
-#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
-#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
-#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
-#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
#endif
#ifndef GL_DEPTH_COMPONENT16_ARB
extern void (GLAPIENTRY *qglActiveStencilFaceEXT)(GLenum);
//GL_EXT_blend_minmax
-#ifndef GL_FUNC_ADD_EXT
-#define GL_FUNC_ADD_EXT 0x8006 // also supplied by GL_EXT_blend_subtract
-#define GL_MIN_EXT 0x8007
-#define GL_MAX_EXT 0x8008
-#define GL_BLEND_EQUATION_EXT 0x8009 // also supplied by GL_EXT_blend_subtract
-extern void (GLAPIENTRY *qglBlendEquationEXT)(GLenum); // also supplied by GL_EXT_blend_subtract
+#ifndef GL_FUNC_ADD
+#define GL_FUNC_ADD 0x8006 // also supplied by GL_blend_subtract
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BLEND_EQUATION 0x8009 // also supplied by GL_blend_subtract
+extern void (GLAPIENTRY *qglBlendEquationEXT)(GLenum); // also supplied by GL_blend_subtract
#endif
//GL_EXT_blend_subtract
-#ifndef GL_FUNC_SUBTRACT_EXT
-#define GL_FUNC_SUBTRACT_EXT 0x800A
-#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
-extern void (GLAPIENTRY *qglBlendEquationEXT)(GLenum); // also supplied by GL_EXT_blend_subtract
+#ifndef GL_FUNC_SUBTRACT
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+extern void (GLAPIENTRY *qglBlendEquationEXT)(GLenum); // also supplied by GL_blend_subtract
#endif
//GL_ARB_texture_non_power_of_two
//GL_ARB_vertex_buffer_object
-#ifndef GL_ARRAY_BUFFER_ARB
-#define GL_ARRAY_BUFFER_ARB 0x8892
-#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
-#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
-#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
-#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
-#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
-#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
-#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
-#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
-#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
-#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
-#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
-#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
-#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
-#define GL_STREAM_DRAW_ARB 0x88E0
-#define GL_STREAM_READ_ARB 0x88E1
-#define GL_STREAM_COPY_ARB 0x88E2
-#define GL_STATIC_DRAW_ARB 0x88E4
-#define GL_STATIC_READ_ARB 0x88E5
-#define GL_STATIC_COPY_ARB 0x88E6
-#define GL_DYNAMIC_DRAW_ARB 0x88E8
-#define GL_DYNAMIC_READ_ARB 0x88E9
-#define GL_DYNAMIC_COPY_ARB 0x88EA
-#define GL_READ_ONLY_ARB 0x88B8
-#define GL_WRITE_ONLY_ARB 0x88B9
-#define GL_READ_WRITE_ARB 0x88BA
-#define GL_BUFFER_SIZE_ARB 0x8764
-#define GL_BUFFER_USAGE_ARB 0x8765
-#define GL_BUFFER_ACCESS_ARB 0x88BB
-#define GL_BUFFER_MAPPED_ARB 0x88BC
-#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#ifndef GL_ARRAY_BUFFER
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
#endif
extern void (GLAPIENTRY *qglBindBufferARB) (GLenum target, GLuint buffer);
extern void (GLAPIENTRY *qglDeleteBuffersARB) (GLsizei n, const GLuint *buffers);
extern void (GLAPIENTRY *qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
extern void (GLAPIENTRY *qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
-//GL_EXT_framebuffer_object
-#ifndef GL_FRAMEBUFFER_EXT
-#define GL_FRAMEBUFFER_EXT 0x8D40
-#define GL_RENDERBUFFER_EXT 0x8D41
-#define GL_STENCIL_INDEX1_EXT 0x8D46
-#define GL_STENCIL_INDEX4_EXT 0x8D47
-#define GL_STENCIL_INDEX8_EXT 0x8D48
-#define GL_STENCIL_INDEX16_EXT 0x8D49
-#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
-#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
-#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
-#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
-#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
-#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
-#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
-#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
-#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
-#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
-#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
-#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
-#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
-#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
-#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
-#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
-#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
-#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
-#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
-#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
-#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
-#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
-#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
-#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
-#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
-#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
-#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
-#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
-#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
-#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
-#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
-#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
-#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
-#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
-#endif
-extern GLboolean (GLAPIENTRY *qglIsRenderbufferEXT)(GLuint renderbuffer);
-extern void (GLAPIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint renderbuffer);
-extern void (GLAPIENTRY *qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint *renderbuffers);
-extern void (GLAPIENTRY *qglGenRenderbuffersEXT)(GLsizei n, GLuint *renderbuffers);
-extern void (GLAPIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-extern void (GLAPIENTRY *qglGetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint *params);
-extern GLboolean (GLAPIENTRY *qglIsFramebufferEXT)(GLuint framebuffer);
-extern void (GLAPIENTRY *qglBindFramebufferEXT)(GLenum target, GLuint framebuffer);
-extern void (GLAPIENTRY *qglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers);
-extern void (GLAPIENTRY *qglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers);
-extern GLenum (GLAPIENTRY *qglCheckFramebufferStatusEXT)(GLenum target);
-//extern void (GLAPIENTRY *qglFramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-extern void (GLAPIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-extern void (GLAPIENTRY *qglFramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-extern void (GLAPIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-extern void (GLAPIENTRY *qglGetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-extern void (GLAPIENTRY *qglGenerateMipmapEXT)(GLenum target);
+//GL_ARB_framebuffer_object
+// (slight differences from GL_EXT_framebuffer_object as this integrates GL_EXT_packed_depth_stencil)
+#ifndef GL_FRAMEBUFFER
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_RENDERBUFFER 0x8D41
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_SRGB 0x8C40
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_INDEX 0x8222
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_BINDING 0x8CA6 // alias DRAW_FRAMEBUFFER_BINDING
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#endif
+extern GLboolean (GLAPIENTRY *qglIsRenderbuffer)(GLuint renderbuffer);
+extern GLvoid (GLAPIENTRY *qglBindRenderbuffer)(GLenum target, GLuint renderbuffer);
+extern GLvoid (GLAPIENTRY *qglDeleteRenderbuffers)(GLsizei n, const GLuint *renderbuffers);
+extern GLvoid (GLAPIENTRY *qglGenRenderbuffers)(GLsizei n, GLuint *renderbuffers);
+extern GLvoid (GLAPIENTRY *qglRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+extern GLvoid (GLAPIENTRY *qglRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+extern GLvoid (GLAPIENTRY *qglGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint *params);
+extern GLboolean (GLAPIENTRY *qglIsFramebuffer)(GLuint framebuffer);
+extern GLvoid (GLAPIENTRY *qglBindFramebuffer)(GLenum target, GLuint framebuffer);
+extern GLvoid (GLAPIENTRY *qglDeleteFramebuffers)(GLsizei n, const GLuint *framebuffers);
+extern GLvoid (GLAPIENTRY *qglGenFramebuffers)(GLsizei n, GLuint *framebuffers);
+extern GLenum (GLAPIENTRY *qglCheckFramebufferStatus)(GLenum target);
+extern GLvoid (GLAPIENTRY *qglFramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+extern GLvoid (GLAPIENTRY *qglFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+extern GLvoid (GLAPIENTRY *qglFramebufferTexture3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer);
+extern GLvoid (GLAPIENTRY *qglFramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+extern GLvoid (GLAPIENTRY *qglFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+extern GLvoid (GLAPIENTRY *qglGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
+extern GLvoid (GLAPIENTRY *qglBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+extern GLvoid (GLAPIENTRY *qglGenerateMipmap)(GLenum target);
// GL_ARB_draw_buffers
#ifndef GL_MAX_DRAW_BUFFERS_ARB
extern void (GLAPIENTRY *qglDepthFunc)(GLenum func);
extern void (GLAPIENTRY *qglDepthMask)(GLboolean flag);
extern void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val);
+extern void (GLAPIENTRY *qglDepthRangef)(GLclampf near_val, GLclampf far_val);
extern void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
extern void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
extern void (GLAPIENTRY *qglPointSize)(GLfloat size);
+//GL_EXT_packed_depth_stencil
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+
+#endif
+
#define DEBUGGL
#ifdef DEBUGGL
#define CHECKGLERROR
#endif
+#ifdef USE_GLES2
+#define qglIsBufferARB glIsBuffer
+#define qglIsEnabled glIsEnabled
+#define qglIsFramebufferEXT glIsFramebuffer
+//#define qglIsQueryARB glIsQuery
+#define qglIsRenderbufferEXT glIsRenderbuffer
+//#define qglUnmapBufferARB glUnmapBuffer
+#define qglCheckFramebufferStatusEXT glCheckFramebufferStatus
+#define qglGetError glGetError
+#define qglCreateProgram glCreateProgram
+#define qglCreateShader glCreateShader
+//#define qglGetHandleARB glGetHandle
+#define qglGetAttribLocation glGetAttribLocation
+#define qglGetUniformLocation glGetUniformLocation
+//#define qglMapBufferARB glMapBuffer
+#define qglGetString glGetString
+//#define qglActiveStencilFaceEXT glActiveStencilFace
+#define qglActiveTexture glActiveTexture
+#define qglAlphaFunc glAlphaFunc
+#define qglArrayElement glArrayElement
+#define qglAttachShader glAttachShader
+//#define qglBegin glBegin
+//#define qglBeginQueryARB glBeginQuery
+#define qglBindAttribLocation glBindAttribLocation
+//#define qglBindFragDataLocation glBindFragDataLocation
+#define qglBindBufferARB glBindBuffer
+#define qglBindFramebufferEXT glBindFramebuffer
+#define qglBindRenderbufferEXT glBindRenderbuffer
+#define qglBindTexture glBindTexture
+#define qglBlendEquationEXT glBlendEquation
+#define qglBlendFunc glBlendFunc
+#define qglBufferDataARB glBufferData
+#define qglBufferSubDataARB glBufferSubData
+#define qglClear glClear
+#define qglClearColor glClearColor
+#define qglClearDepthf glClearDepthf
+#define qglClearStencil glClearStencil
+#define qglClientActiveTexture glClientActiveTexture
+#define qglColor4f glColor4f
+#define qglColor4ub glColor4ub
+#define qglColorMask glColorMask
+#define qglColorPointer glColorPointer
+#define qglCompileShader glCompileShader
+#define qglCompressedTexImage2DARB glCompressedTexImage2D
+#define qglCompressedTexImage3DARB glCompressedTexImage3D
+#define qglCompressedTexSubImage2DARB glCompressedTexSubImage2D
+#define qglCompressedTexSubImage3DARB glCompressedTexSubImage3D
+#define qglCopyTexImage2D glCopyTexImage2D
+#define qglCopyTexSubImage2D glCopyTexSubImage2D
+#define qglCopyTexSubImage3D glCopyTexSubImage3D
+#define qglCullFace glCullFace
+#define qglDeleteBuffersARB glDeleteBuffers
+#define qglDeleteFramebuffersEXT glDeleteFramebuffers
+#define qglDeleteProgram glDeleteProgram
+#define qglDeleteShader glDeleteShader
+//#define qglDeleteQueriesARB glDeleteQueries
+#define qglDeleteRenderbuffersEXT glDeleteRenderbuffers
+#define qglDeleteTextures glDeleteTextures
+#define qglDepthFunc glDepthFunc
+#define qglDepthMask glDepthMask
+#define qglDepthRangef glDepthRangef
+#define qglDetachShader glDetachShader
+#define qglDisable glDisable
+#define qglDisableClientState glDisableClientState
+#define qglDisableVertexAttribArray glDisableVertexAttribArray
+#define qglDrawArrays glDrawArrays
+//#define qglDrawBuffer glDrawBuffer
+//#define qglDrawBuffersARB glDrawBuffers
+#define qglDrawElements glDrawElements
+//#define qglDrawRangeElements glDrawRangeElements
+#define qglEnable glEnable
+#define qglEnableClientState glEnableClientState
+#define qglEnableVertexAttribArray glEnableVertexAttribArray
+//#define qglEnd glEnd
+//#define qglEndQueryARB glEndQuery
+#define qglFinish glFinish
+#define qglFlush glFlush
+#define qglFramebufferRenderbuffer glFramebufferRenderbuffer
+#define qglFramebufferTexture2D glFramebufferTexture2D
+#define qglFramebufferTexture3DEXT glFramebufferTexture3D
+#define qglGenBuffersARB glGenBuffers
+#define qglGenFramebuffersEXT glGenFramebuffers
+//#define qglGenQueriesARB glGenQueries
+#define qglGenRenderbuffersEXT glGenRenderbuffers
+#define qglGenTextures glGenTextures
+#define qglGenerateMipmapEXT glGenerateMipmap
+#define qglGetActiveAttrib glGetActiveAttrib
+#define qglGetActiveUniform glGetActiveUniform
+#define qglGetAttachedShaders glGetAttachedShaders
+#define qglGetBooleanv glGetBooleanv
+//#define qglGetCompressedTexImageARB glGetCompressedTexImage
+#define qglGetDoublev glGetDoublev
+#define qglGetFloatv glGetFloatv
+#define qglGetFramebufferAttachmentParameterivEXT glGetFramebufferAttachmentParameteriv
+#define qglGetProgramInfoLog glGetProgramInfoLog
+#define qglGetShaderInfoLog glGetShaderInfoLog
+#define qglGetIntegerv glGetIntegerv
+#define qglGetShaderiv glGetShaderiv
+#define qglGetProgramiv glGetProgramiv
+//#define qglGetQueryObjectivARB glGetQueryObjectiv
+//#define qglGetQueryObjectuivARB glGetQueryObjectuiv
+//#define qglGetQueryivARB glGetQueryiv
+#define qglGetRenderbufferParameterivEXT glGetRenderbufferParameteriv
+#define qglGetShaderSource glGetShaderSource
+#define qglGetTexImage glGetTexImage
+#define qglGetTexLevelParameterfv glGetTexLevelParameterfv
+#define qglGetTexLevelParameteriv glGetTexLevelParameteriv
+#define qglGetTexParameterfv glGetTexParameterfv
+#define qglGetTexParameteriv glGetTexParameteriv
+#define qglGetUniformfv glGetUniformfv
+#define qglGetUniformiv glGetUniformiv
+#define qglHint glHint
+#define qglLineWidth glLineWidth
+#define qglLinkProgram glLinkProgram
+#define qglLoadIdentity glLoadIdentity
+#define qglLoadMatrixf glLoadMatrixf
+#define qglMatrixMode glMatrixMode
+#define qglMultiTexCoord1f glMultiTexCoord1f
+#define qglMultiTexCoord2f glMultiTexCoord2f
+#define qglMultiTexCoord3f glMultiTexCoord3f
+#define qglMultiTexCoord4f glMultiTexCoord4f
+#define qglNormalPointer glNormalPointer
+#define qglPixelStorei glPixelStorei
+#define qglPointSize glPointSize
+//#define qglPolygonMode glPolygonMode
+#define qglPolygonOffset glPolygonOffset
+//#define qglPolygonStipple glPolygonStipple
+#define qglReadBuffer glReadBuffer
+#define qglReadPixels glReadPixels
+#define qglRenderbufferStorageEXT glRenderbufferStorage
+#define qglScissor glScissor
+#define qglShaderSource glShaderSource
+#define qglStencilFunc glStencilFunc
+#define qglStencilFuncSeparate glStencilFuncSeparate
+#define qglStencilMask glStencilMask
+#define qglStencilOp glStencilOp
+#define qglStencilOpSeparate glStencilOpSeparate
+#define qglTexCoord1f glTexCoord1f
+#define qglTexCoord2f glTexCoord2f
+#define qglTexCoord3f glTexCoord3f
+#define qglTexCoord4f glTexCoord4f
+#define qglTexCoordPointer glTexCoordPointer
+#define qglTexEnvf glTexEnvf
+#define qglTexEnvfv glTexEnvfv
+#define qglTexEnvi glTexEnvi
+#define qglTexImage2D glTexImage2D
+#define qglTexImage3D glTexImage3D
+#define qglTexParameterf glTexParameterf
+#define qglTexParameterfv glTexParameterfv
+#define qglTexParameteri glTexParameteri
+#define qglTexSubImage2D glTexSubImage2D
+#define qglTexSubImage3D glTexSubImage3D
+#define qglUniform1f glUniform1f
+#define qglUniform1fv glUniform1fv
+#define qglUniform1i glUniform1i
+#define qglUniform1iv glUniform1iv
+#define qglUniform2f glUniform2f
+#define qglUniform2fv glUniform2fv
+#define qglUniform2i glUniform2i
+#define qglUniform2iv glUniform2iv
+#define qglUniform3f glUniform3f
+#define qglUniform3fv glUniform3fv
+#define qglUniform3i glUniform3i
+#define qglUniform3iv glUniform3iv
+#define qglUniform4f glUniform4f
+#define qglUniform4fv glUniform4fv
+#define qglUniform4i glUniform4i
+#define qglUniform4iv glUniform4iv
+#define qglUniformMatrix2fv glUniformMatrix2fv
+#define qglUniformMatrix3fv glUniformMatrix3fv
+#define qglUniformMatrix4fv glUniformMatrix4fv
+#define qglUseProgram glUseProgram
+#define qglValidateProgram glValidateProgram
+#define qglVertex2f glVertex2f
+#define qglVertex3f glVertex3f
+#define qglVertex4f glVertex4f
+#define qglVertexAttribPointer glVertexAttribPointer
+#define qglVertexPointer glVertexPointer
+#define qglViewport glViewport
+#define qglVertexAttrib1f glVertexAttrib1f
+//#define qglVertexAttrib1s glVertexAttrib1s
+//#define qglVertexAttrib1d glVertexAttrib1d
+#define qglVertexAttrib2f glVertexAttrib2f
+//#define qglVertexAttrib2s glVertexAttrib2s
+//#define qglVertexAttrib2d glVertexAttrib2d
+#define qglVertexAttrib3f glVertexAttrib3f
+//#define qglVertexAttrib3s glVertexAttrib3s
+//#define qglVertexAttrib3d glVertexAttrib3d
+#define qglVertexAttrib4f glVertexAttrib4f
+//#define qglVertexAttrib4s glVertexAttrib4s
+//#define qglVertexAttrib4d glVertexAttrib4d
+//#define qglVertexAttrib4Nub glVertexAttrib4Nub
+#define qglVertexAttrib1fv glVertexAttrib1fv
+//#define qglVertexAttrib1sv glVertexAttrib1sv
+//#define qglVertexAttrib1dv glVertexAttrib1dv
+#define qglVertexAttrib2fv glVertexAttrib2fv
+//#define qglVertexAttrib2sv glVertexAttrib2sv
+//#define qglVertexAttrib2dv glVertexAttrib2dv
+#define qglVertexAttrib3fv glVertexAttrib3fv
+//#define qglVertexAttrib3sv glVertexAttrib3sv
+//#define qglVertexAttrib3dv glVertexAttrib3dv
+#define qglVertexAttrib4fv glVertexAttrib4fv
+//#define qglVertexAttrib4sv glVertexAttrib4sv
+//#define qglVertexAttrib4dv glVertexAttrib4dv
+//#define qglVertexAttrib4iv glVertexAttrib4iv
+//#define qglVertexAttrib4bv glVertexAttrib4bv
+//#define qglVertexAttrib4ubv glVertexAttrib4ubv
+//#define qglVertexAttrib4usv glVertexAttrib4usv
+//#define qglVertexAttrib4uiv glVertexAttrib4uiv
+//#define qglVertexAttrib4Nbv glVertexAttrib4Nbv
+//#define qglVertexAttrib4Nsv glVertexAttrib4Nsv
+//#define qglVertexAttrib4Niv glVertexAttrib4Niv
+//#define qglVertexAttrib4Nubv glVertexAttrib4Nubv
+//#define qglVertexAttrib4Nusv glVertexAttrib4Nusv
+//#define qglVertexAttrib4Nuiv glVertexAttrib4Nuiv
+//#define qglGetVertexAttribdv glGetVertexAttribdv
+#define qglGetVertexAttribfv glGetVertexAttribfv
+#define qglGetVertexAttribiv glGetVertexAttribiv
+#define qglGetVertexAttribPointerv glGetVertexAttribPointerv
+#endif
+
#endif
const unsigned char *key, int k
)
{
- static unsigned char hashbuf[32];
- static unsigned char k_xor_ipad[128];
- static unsigned char k_xor_opad[128];
- static unsigned char catbuf[65600]; // 65535 bytes max quake packet size + 64 for the hash
+ unsigned char hashbuf[32];
+ unsigned char k_xor_ipad[128];
+ unsigned char k_xor_opad[128];
+ unsigned char *catbuf;
int i;
if(sizeof(hashbuf) < (size_t) hlen)
return false;
if(sizeof(k_xor_ipad) < (size_t) hlen)
return false;
- if(sizeof(catbuf) < (size_t) hblock + (size_t) hlen)
- return false;
- if(sizeof(catbuf) < (size_t) hblock + (size_t) n)
- return false;
+
+ catbuf = (unsigned char *)Mem_Alloc(tempmempool, (size_t) hblock + max((size_t) hlen, (size_t) n));
if(k > hblock)
{
memcpy(catbuf, k_xor_opad, hblock);
memcpy(catbuf + hblock, hashbuf, hlen);
hfunc(out, catbuf, hblock + hlen);
+
+ Mem_Free(catbuf);
+
return true;
}
#include <time.h>
#include "libcurl.h"
#include "cdaudio.h"
-#include "cl_gecko.h"
#include "cl_video.h"
#include "progsvm.h"
#include "csprogs.h"
#include "sv_demo.h"
#include "snd_main.h"
#include "thread.h"
+#include "utf8lib.h"
/*
// LordHavoc: set when quit is executed
qboolean host_shuttingdown = false;
-// the real time since application started, without any slowmo or clamping
+// the accumulated mainloop time since application started (with filtering), without any slowmo or clamping
double realtime;
+// the main loop wall time for this frame
+double host_dirtytime;
// current client
client_t *host_client;
jmp_buf host_abortframe;
-double host_starttime = 0;
// pretend frames take this amount of time (in seconds), 0 = realtime
cvar_t host_framerate = {0, "host_framerate","0", "locks frame timing to this value in seconds, 0.05 is 20fps for example, note that this can easily run too fast, use cl_maxfps if you want to limit your framerate instead, or sys_ticrate to limit server speed"};
+cvar_t cl_maxphysicsframesperserverframe = {0, "cl_maxphysicsframesperserverframe","10", "maximum number of physics frames per server frame"};
// shows time used by certain subsystems
cvar_t host_speeds = {0, "host_speeds","0", "reports how much time is used in server/graphics/sound"};
cvar_t host_maxwait = {0, "host_maxwait","1000", "maximum sleep time requested from the operating system in millisecond. Larger sleeps will be done using multiple host_maxwait length sleeps. Lowering this value will increase CPU load, but may help working around problems with accuracy of sleep times."};
cvar_t timestamps = {CVAR_SAVE, "timestamps", "0", "prints timestamps on console messages"};
cvar_t timeformat = {CVAR_SAVE, "timeformat", "[%Y-%m-%d %H:%M:%S] ", "time format to use on timestamped console messages"};
+cvar_t sessionid = {CVAR_READONLY, "sessionid", "", "ID of the current session (use the -sessionid parameter to set it); this is always either empty or begins with a dot (.)"};
+cvar_t locksession = {0, "locksession", "0", "Lock the session? 0 = no, 1 = yes and abort on failure, 2 = yes and continue on failure"};
+
/*
================
Host_AbortCurrentFrame
*/
void Host_AbortCurrentFrame(void)
{
+ // in case we were previously nice, make us mean again
+ Sys_MakeProcessMean();
+
longjmp (host_abortframe, 1);
}
*/
void Host_Error (const char *error, ...)
{
- static char hosterrorstring1[MAX_INPUTLINE];
- static char hosterrorstring2[MAX_INPUTLINE];
+ static char hosterrorstring1[MAX_INPUTLINE]; // THREAD UNSAFE
+ static char hosterrorstring2[MAX_INPUTLINE]; // THREAD UNSAFE
static qboolean hosterror = false;
va_list argptr;
//PR_Crash();
// print out where the crash happened, if it was caused by QC (and do a cleanup)
- PRVM_Crash();
+ PRVM_Crash(SVVM_prog);
+ PRVM_Crash(CLVM_prog);
+ PRVM_Crash(MVM_prog);
+ cl.csqc_loaded = false;
+ Cvar_SetValueQuick(&csqc_progcrc, -1);
+ Cvar_SetValueQuick(&csqc_progsize, -1);
+ SV_LockThreadMutex();
Host_ShutdownServer ();
+ SV_UnlockThreadMutex();
if (cls.state == ca_dedicated)
Sys_Error ("Host_Error: %s",hosterrorstring2); // dedicated servers exit
Host_AbortCurrentFrame();
}
-void Host_ServerOptions (void)
+static void Host_ServerOptions (void)
{
int i;
Cmd_AddCommand("saveconfig", Host_SaveConfig_f, "save settings to config.cfg (or a specified filename) immediately (also automatic when quitting)");
Cmd_AddCommand("loadconfig", Host_LoadConfig_f, "reset everything and reload configs");
+ Cvar_RegisterVariable (&cl_maxphysicsframesperserverframe);
Cvar_RegisterVariable (&host_framerate);
Cvar_RegisterVariable (&host_speeds);
Cvar_RegisterVariable (&host_maxwait);
Writes key bindings and archived cvars to config.cfg
===============
*/
-void Host_SaveConfig_to(const char *file)
+static void Host_SaveConfig_to(const char *file)
{
qfile_t *f;
Host_SaveConfig_to(file);
}
-void Host_AddConfigText(void)
+static void Host_AddConfigText(void)
{
// set up the default startmap_sp and startmap_dm aliases (mods can
// override these) and then execute the quake.rc startup script
*/
void SV_DropClient(qboolean crash)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
Con_Printf("Client \"%s\" dropped\n", host_client->name);
// this will set the body to a dead frame, among other things
int saveSelf = PRVM_serverglobaledict(self);
host_client->clientconnectcalled = false;
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram(PRVM_serverfunction(ClientDisconnect), "QC function ClientDisconnect is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(ClientDisconnect), "QC function ClientDisconnect is missing");
PRVM_serverglobaledict(self) = saveSelf;
}
if (sv.active)
{
// clear a fields that matter to DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS, and also frags
- PRVM_ED_ClearEdict(host_client->edict);
+ PRVM_ED_ClearEdict(prog, host_client->edict);
}
// clear the client struct (this sets active to false)
*/
void Host_ShutdownServer(void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
Con_DPrintf("Host_ShutdownServer\n");
NetConn_Heartbeat(2);
// make sure all the clients know we're disconnecting
- SV_VM_Begin();
World_End(&sv.world);
if(prog->loaded)
+ {
if(PRVM_serverfunction(SV_Shutdown))
{
func_t s = PRVM_serverfunction(SV_Shutdown);
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
- PRVM_ExecuteProgram(s,"SV_Shutdown() required");
+ prog->ExecuteProgram(prog, s,"SV_Shutdown() required");
}
+ }
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
if (host_client->active)
SV_DropClient(false); // server shutdown
- SV_VM_End();
NetConn_CloseServerPorts();
//
memset(&sv, 0, sizeof(sv));
memset(svs.clients, 0, svs.maxclients*sizeof(client_t));
+
+ cl.islocalgame = false;
}
Add them exactly as if they had been typed at the console
===================
*/
-void Host_GetConsoleCommands (void)
+static void Host_GetConsoleCommands (void)
{
char *cmd;
Returns a time report string, for example for
==================
*/
-const char *Host_TimingReport(void)
+const char *Host_TimingReport(char *buf, size_t buflen)
{
- return va("%.1f%% CPU, %.2f%% lost, offset avg %.1fms, max %.1fms, sdev %.1fms", svs.perf_cpuload * 100, svs.perf_lost * 100, svs.perf_offset_avg * 1000, svs.perf_offset_max * 1000, svs.perf_offset_sdev * 1000);
+ return va(buf, buflen, "%.1f%% CPU, %.2f%% lost, offset avg %.1fms, max %.1fms, sdev %.1fms", svs.perf_cpuload * 100, svs.perf_lost * 100, svs.perf_offset_avg * 1000, svs.perf_offset_max * 1000, svs.perf_offset_sdev * 1000);
}
/*
double time1 = 0;
double time2 = 0;
double time3 = 0;
- double cl_timer, sv_timer;
- double clframetime, deltarealtime, oldrealtime;
+ double cl_timer = 0, sv_timer = 0;
+ double clframetime, deltacleantime, olddirtytime, dirtytime;
double wait;
int pass1, pass2, pass3, i;
+ char vabuf[1024];
Host_Init();
- cl_timer = 0;
- sv_timer = 0;
-
- realtime = host_starttime = Sys_DoubleTime();
+ realtime = 0;
+ dirtytime = Sys_DirtyTime();
for (;;)
{
if (setjmp(host_abortframe))
continue; // something bad happened, or the server disconnected
}
- oldrealtime = realtime;
- realtime = Sys_DoubleTime();
-
- deltarealtime = realtime - oldrealtime;
- cl_timer += deltarealtime;
- sv_timer += deltarealtime;
-
- svs.perf_acc_realtime += deltarealtime;
-
- // Look for clients who have spawned
- for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
- if(host_client->spawned)
- if(host_client->netconnection)
- break;
- if(i == svs.maxclients)
+ olddirtytime = host_dirtytime;
+ dirtytime = Sys_DirtyTime();
+ deltacleantime = dirtytime - olddirtytime;
+ if (deltacleantime < 0)
{
- // Nobody is looking? Then we won't do timing...
- // Instead, reset it to zero
- svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
+ // warn if it's significant
+ if (deltacleantime < -0.01)
+ Con_Printf("Host_Mingled: time stepped backwards (went from %f to %f, difference %f)\n", olddirtytime, dirtytime, deltacleantime);
+ deltacleantime = 0;
}
- else if(svs.perf_acc_realtime > 5)
+ else if (deltacleantime >= 1800)
{
- svs.perf_cpuload = 1 - svs.perf_acc_sleeptime / svs.perf_acc_realtime;
- svs.perf_lost = svs.perf_acc_lost / svs.perf_acc_realtime;
- if(svs.perf_acc_offset_samples > 0)
+ Con_Printf("Host_Mingled: time stepped forward (went from %f to %f, difference %f)\n", olddirtytime, dirtytime, deltacleantime);
+ deltacleantime = 0;
+ }
+ realtime += deltacleantime;
+ host_dirtytime = dirtytime;
+
+ cl_timer += deltacleantime;
+ sv_timer += deltacleantime;
+
+ if (!svs.threaded)
+ {
+ svs.perf_acc_realtime += deltacleantime;
+
+ // Look for clients who have spawned
+ for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
+ if(host_client->spawned)
+ if(host_client->netconnection)
+ break;
+ if(i == svs.maxclients)
+ {
+ // Nobody is looking? Then we won't do timing...
+ // Instead, reset it to zero
+ svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
+ }
+ else if(svs.perf_acc_realtime > 5)
{
- svs.perf_offset_max = svs.perf_acc_offset_max;
- svs.perf_offset_avg = svs.perf_acc_offset / svs.perf_acc_offset_samples;
- svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg);
+ svs.perf_cpuload = 1 - svs.perf_acc_sleeptime / svs.perf_acc_realtime;
+ svs.perf_lost = svs.perf_acc_lost / svs.perf_acc_realtime;
+ if(svs.perf_acc_offset_samples > 0)
+ {
+ svs.perf_offset_max = svs.perf_acc_offset_max;
+ svs.perf_offset_avg = svs.perf_acc_offset / svs.perf_acc_offset_samples;
+ svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg);
+ }
+ if(svs.perf_lost > 0 && developer_extra.integer)
+ Con_DPrintf("Server can't keep up: %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
+ svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
}
- if(svs.perf_lost > 0 && developer_extra.integer)
- Con_DPrintf("Server can't keep up: %s\n", Host_TimingReport());
- svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
}
if (slowmo.value < 0.00001 && slowmo.value != 0)
if(!*sv_random_seed.string && !cls.demoplayback)
rand();
- cl.islocalgame = NetConn_IsLocalGame();
-
// get new key events
Key_EventQueue_Unblock();
SndSys_SendKeyEvents();
// receive packets on each main loop iteration, as the main loop may
// be undersleeping due to select() detecting a new packet
- if (sv.active)
+ if (sv.active && !svs.threaded)
NetConn_ServerFrame();
Curl_Run();
// process console commands
// R_TimeReport("preconsole");
CL_VM_PreventInformationLeaks();
- Cbuf_Execute();
+ Cbuf_Frame();
// R_TimeReport("console");
}
// if the accumulators haven't become positive yet, wait a while
if (cls.state == ca_dedicated)
wait = sv_timer * -1000000.0;
- else if (!sv.active)
+ else if (!sv.active || svs.threaded)
wait = cl_timer * -1000000.0;
else
wait = max(cl_timer, sv_timer) * -1000000.0;
if (!cls.timedemo && wait >= 1)
{
- double time0;
+ double time0, delta;
if(host_maxwait.value <= 0)
wait = min(wait, 1000000.0);
if(wait < 1)
wait = 1; // because we cast to int
- time0 = Sys_DoubleTime();
- if (sv_checkforpacketsduringsleep.integer && !sys_usenoclockbutbenchmark.integer)
+ time0 = Sys_DirtyTime();
+ if (sv_checkforpacketsduringsleep.integer && !sys_usenoclockbutbenchmark.integer && !svs.threaded)
NetConn_SleepMicroseconds((int)wait);
else
Sys_Sleep((int)wait);
- svs.perf_acc_sleeptime += Sys_DoubleTime() - time0;
+ delta = Sys_DirtyTime() - time0;
+ if (delta < 0 || delta >= 1800) delta = 0;
+ if (!svs.threaded)
+ svs.perf_acc_sleeptime += delta;
// R_TimeReport("sleep");
continue;
}
+ // limit the frametime steps to no more than 100ms each
+ if (cl_timer > 0.1)
+ cl_timer = 0.1;
+ if (sv_timer > 0.1)
+ {
+ if (!svs.threaded)
+ svs.perf_acc_lost += (sv_timer - 0.1);
+ sv_timer = 0.1;
+ }
+
R_TimeReport("---");
//-------------------
//-------------------
// limit the frametime steps to no more than 100ms each
- if (cl_timer > 0.1)
- cl_timer = 0.1;
- if (sv_timer > 0.1)
- {
- svs.perf_acc_lost += (sv_timer - 0.1);
- sv_timer = 0.1;
- }
-
- if (sv.active && sv_timer > 0)
+ if (sv.active && sv_timer > 0 && !svs.threaded)
{
// execute one or more server frames, with an upper limit on how much
// execution time to spend on server frames to avoid freezing the game if
int framecount, framelimit = 1;
double advancetime, aborttime = 0;
float offset;
-
- if (cls.state == ca_dedicated)
- Collision_Cache_NewFrame();
+ prvm_prog_t *prog = SVVM_prog;
// run the world state
// don't allow simulation to run too fast or too slow or logic glitches can occur
advancetime = sv_timer;
else if (cl.islocalgame && !sv_fixedframeratesingleplayer.integer)
{
- // synchronize to the client frametime, but no less than 10ms and no more than sys_ticrate
- advancetime = bound(0.01, cl_timer, sys_ticrate.value);
- framelimit = 10;
- aborttime = realtime + 0.1;
+ // synchronize to the client frametime, but no less than 10ms and no more than 100ms
+ advancetime = bound(0.01, cl_timer, 0.1);
}
else
{
advancetime = sys_ticrate.value;
// listen servers can run multiple server frames per client frame
- if (cls.state == ca_connected)
- {
- framelimit = 10;
- aborttime = realtime + 0.1;
- }
+ framelimit = cl_maxphysicsframesperserverframe.integer;
+ aborttime = Sys_DirtyTime() + 0.1;
}
if(slowmo.value > 0 && slowmo.value < 1)
advancetime = min(advancetime, 0.1 / slowmo.value);
if(advancetime > 0)
{
- offset = sv_timer + (Sys_DoubleTime() - realtime);
+ offset = Sys_DirtyTime() - dirtytime;if (offset < 0 || offset >= 1800) offset = 0;
+ offset += sv_timer;
++svs.perf_acc_offset_samples;
svs.perf_acc_offset += offset;
svs.perf_acc_offset_squared += offset * offset;
if (sv.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused)))
sv.frametime = 0;
- // setup the VM frame
- SV_VM_Begin();
-
for (framecount = 0;framecount < framelimit && sv_timer > 0;framecount++)
{
sv_timer -= advancetime;
SV_Physics();
// if this server frame took too long, break out of the loop
- if (framelimit > 1 && Sys_DoubleTime() >= aborttime)
+ if (framelimit > 1 && Sys_DirtyTime() >= aborttime)
break;
}
R_TimeReport("serverphysics");
// send all messages to the clients
SV_SendClientMessages();
-
+
if (sv.paused == 1 && realtime > sv.pausedstart && sv.pausedstart > 0) {
prog->globals.generic[OFS_PARM0] = realtime - sv.pausedstart;
- PRVM_ExecuteProgram(PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing");
+ PRVM_serverglobalfloat(time) = sv.time;
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing");
}
- // end the server VM frame
- SV_VM_End();
-
// send an heartbeat if enough time has passed since the last one
NetConn_Heartbeat(0);
R_TimeReport("servernetwork");
}
- else
+ else if (!svs.threaded)
{
// don't let r_speeds display jump around
R_TimeReport("serverphysics");
// update video
if (host_speeds.integer)
- time1 = Sys_DoubleTime();
+ time1 = Sys_DirtyTime();
R_TimeReport("pre-input");
// Collect input into cmd
R_TimeReport("lerpworld");
CL_Video_Frame();
- CL_Gecko_Frame();
R_TimeReport("client");
R_TimeReport("render");
if (host_speeds.integer)
- time2 = Sys_DoubleTime();
+ time2 = Sys_DirtyTime();
// update audio
if(cl.csqc_usecsqclistener)
if (host_speeds.integer)
{
pass1 = (int)((time1 - time3)*1000000);
- time3 = Sys_DoubleTime();
+ time3 = Sys_DirtyTime();
pass2 = (int)((time2 - time1)*1000000);
pass3 = (int)((time3 - time2)*1000000);
Con_Printf("%6ius total %6ius server %6ius gfx %6ius snd\n",
cl_timer = 0;
if (sv_timer >= 0)
{
- svs.perf_acc_lost += sv_timer;
+ if (!svs.threaded)
+ svs.perf_acc_lost += sv_timer;
sv_timer = 0;
}
qboolean sys_nostdout = false;
-extern void u8_Init(void);
-extern void Render_Init(void);
-extern void Mathlib_Init(void);
-extern void FS_Init_SelfPack(void);
-extern void FS_Init(void);
-extern void FS_Shutdown(void);
-extern void PR_Cmd_Init(void);
-extern void COM_Init_Commands(void);
-extern void FS_Init_Commands(void);
extern qboolean host_stuffcmdsrun;
+static qfile_t *locksession_fh = NULL;
+static qboolean locksession_run = false;
+static void Host_InitSession(void)
+{
+ int i;
+ Cvar_RegisterVariable(&sessionid);
+ Cvar_RegisterVariable(&locksession);
+
+ // load the session ID into the read-only cvar
+ if ((i = COM_CheckParm("-sessionid")) && (i + 1 < com_argc))
+ {
+ char vabuf[1024];
+ if(com_argv[i+1][0] == '.')
+ Cvar_SetQuick(&sessionid, com_argv[i+1]);
+ else
+ Cvar_SetQuick(&sessionid, va(vabuf, sizeof(vabuf), ".%s", com_argv[i+1]));
+ }
+}
+void Host_LockSession(void)
+{
+ if(locksession_run)
+ return;
+ locksession_run = true;
+ if(locksession.integer != 0)
+ {
+ char vabuf[1024];
+ locksession_fh = FS_SysOpen(va(vabuf, sizeof(vabuf), "%slock%s", *fs_userdir ? fs_userdir : fs_basedir, sessionid.string), "wl", false);
+ // TODO maybe write the pid into the lockfile, while we are at it? may help server management tools
+ if(!locksession_fh)
+ {
+ if(locksession.integer == 2)
+ {
+ Con_Printf("WARNING: session lock %slock%s could not be acquired. Please run with -sessionid and an unique session name. Continuing anyway.\n", *fs_userdir ? fs_userdir : fs_basedir, sessionid.string);
+ }
+ else
+ {
+ Sys_Error("session lock %slock%s could not be acquired. Please run with -sessionid and an unique session name.\n", *fs_userdir ? fs_userdir : fs_basedir, sessionid.string);
+ }
+ }
+ }
+}
+void Host_UnlockSession(void)
+{
+ if(!locksession_run)
+ return;
+ locksession_run = false;
+
+ if(locksession_fh)
+ {
+ FS_Close(locksession_fh);
+ // NOTE: we can NOT unlink the lock here, as doing so would
+ // create a race condition if another process created it
+ // between our close and our unlink
+ locksession_fh = NULL;
+ }
+}
+
/*
====================
Host_Init
{
int i;
const char* os;
+ char vabuf[1024];
if (COM_CheckParm("-profilegameonly"))
Sys_AllowProfiling(false);
developer.string = "1";
}
- if (COM_CheckParm("-developer2"))
+ if (COM_CheckParm("-developer2") || COM_CheckParm("-developer3"))
{
developer.value = developer.integer = 1;
developer.string = "1";
developer_memorydebug.string = "1";
}
+ if (COM_CheckParm("-developer3"))
+ {
+ gl_paranoid.integer = 1;gl_paranoid.string = "1";
+ gl_printcheckerror.integer = 1;gl_printcheckerror.string = "1";
+ }
+
// COMMANDLINEOPTION: Console: -nostdout disables text output to the terminal the game was launched from
if (COM_CheckParm("-nostdout"))
sys_nostdout = 1;
dpsnprintf (engineversion, sizeof (engineversion), "%s %s %s", gamename, os, buildstring);
Con_Printf("%s\n", engineversion);
+ // initialize process nice level
+ Sys_InitProcessNice();
+
// initialize ixtable
Mathlib_Init();
// initialize filesystem (including fs_basedir, fs_gamedir, -game, scr_screenshot_name)
FS_Init();
+ // register the cvars for session locking
+ Host_InitSession();
+
// must be after FS_Init
Crypto_Init();
Crypto_Init_Commands();
Host_InitLocal();
Host_ServerOptions();
+ Thread_Init();
+
if (cls.state == ca_dedicated)
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server (or disconnect all clients if running a server)");
else
R_Modules_Init();
Palette_Init();
MR_Init_Commands();
- Thread_Init();
VID_Shared_Init();
VID_Init();
Render_Init();
if (i && i + 1 < com_argc)
if (!sv.active && !cls.demoplayback && !cls.connect_trying)
{
- Cbuf_AddText(va("timedemo %s\n", com_argv[i + 1]));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "timedemo %s\n", com_argv[i + 1]));
Cbuf_Execute();
}
if (i && i + 1 < com_argc)
if (!sv.active && !cls.demoplayback && !cls.connect_trying)
{
- Cbuf_AddText(va("playdemo %s\n", com_argv[i + 1]));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "playdemo %s\n", com_argv[i + 1]));
Cbuf_Execute();
}
if (i && i + 1 < com_argc)
if (!sv.active && !cls.demoplayback && !cls.connect_trying)
{
- Cbuf_AddText(va("playdemo %s\ncl_capturevideo 1\n", com_argv[i + 1]));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "playdemo %s\ncl_capturevideo 1\n", com_argv[i + 1]));
Cbuf_Execute();
}
Con_DPrint("========Initialized=========\n");
//Host_StartVideo();
+
+ if (cls.state != ca_dedicated)
+ SV_StartThread();
}
// be quiet while shutting down
S_StopAllSounds();
+ // end the server thread
+ if (svs.threaded)
+ SV_StopThread();
+
// disconnect client from server if active
CL_Disconnect();
// shut down local server if active
+ SV_LockThreadMutex();
Host_ShutdownServer ();
+ SV_UnlockThreadMutex();
// Shutdown menu
if(MR_Shutdown)
// AK shutdown PRVM
// AK hmm, no PRVM_Shutdown(); yet
- CL_Gecko_Shutdown();
CL_Video_Shutdown();
Host_SaveConfig();
{
R_Modules_Shutdown();
VID_Shutdown();
- Thread_Shutdown();
}
+ SV_StopThread();
+ Thread_Shutdown();
Cmd_Shutdown();
Key_Shutdown();
CL_Shutdown();
Sys_Shutdown();
Log_Close();
Crypto_Shutdown();
- FS_Shutdown();
+
+ Host_UnlockSession();
+
+ S_Shutdown();
Con_Shutdown();
Memory_Shutdown();
}
cvar_t sv_adminnick = {CVAR_SAVE, "sv_adminnick", "", "nick name to use for admin messages instead of host name"};
cvar_t sv_status_privacy = {CVAR_SAVE, "sv_status_privacy", "0", "do not show IP addresses in 'status' replies to clients"};
cvar_t sv_status_show_qcstatus = {CVAR_SAVE, "sv_status_show_qcstatus", "0", "show the 'qcstatus' field in status replies, not the 'frags' field. Turn this on if your mod uses this field, and the 'frags' field on the other hand has no meaningful value."};
+cvar_t sv_namechangetimer = {CVAR_SAVE, "sv_namechangetimer", "5", "how often to allow name changes, in seconds (prevents people from using animated names and other tricks"};
cvar_t rcon_password = {CVAR_PRIVATE, "rcon_password", "", "password to authenticate rcon commands; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password; may be set to a string of the form user1:pass1 user2:pass2 user3:pass3 to allow multiple user accounts - the client then has to specify ONE of these combinations"};
cvar_t rcon_secure = {CVAR_NQUSERINFOHACK, "rcon_secure", "0", "force secure rcon authentication (1 = time based, 2 = challenge based); NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
cvar_t rcon_secure_challengetimeout = {0, "rcon_secure_challengetimeout", "5", "challenge-based secure rcon: time out requests if no challenge came within this time interval"};
Host_Status_f
==================
*/
-void Host_Status_f (void)
+static void Host_Status_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
char qcstatus[256];
client_t *client;
int seconds = 0, minutes = 0, hours = 0, i, j, k, in, players, ping = 0, packetloss = 0;
void (*print) (const char *fmt, ...);
char ip[48]; // can contain a full length v6 address with [] and a port
int frags;
+ char vabuf[1024];
if (cmd_source == src_command)
{
if (!sv.active)
return;
-
- if(cmd_source == src_command)
- SV_VM_Begin();
-
+
in = 0;
if (Cmd_Argc() == 2)
{
print ("version: %s build %s\n", gamename, buildstring);
print ("protocol: %i (%s)\n", Protocol_NumberForEnum(sv.protocol), Protocol_NameForEnum(sv.protocol));
print ("map: %s\n", sv.name);
- print ("timing: %s\n", Host_TimingReport());
+ print ("timing: %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
print ("players: %i active (%i max)\n\n", players, svs.maxclients);
if (in == 1)
if(sv_status_show_qcstatus.integer)
{
prvm_edict_t *ed = PRVM_EDICT_NUM(i + 1);
- const char *str = PRVM_GetString(PRVM_serveredictstring(ed, clientstatus));
+ const char *str = PRVM_GetString(prog, PRVM_serveredictstring(ed, clientstatus));
if(str && *str)
{
char *p;
print ("%s%-47s #%-3u ^7%s\n", k%2 ? "^3" : "^7", ip, i+1, client->name);
}
}
-
- if(cmd_source == src_command)
- SV_VM_End();
}
Sets client to godmode
==================
*/
-void Host_God_f (void)
+static void Host_God_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
SV_ClientPrint("godmode ON\n");
}
-void Host_Notarget_f (void)
+static void Host_Notarget_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
qboolean noclip_anglehack;
-void Host_Noclip_f (void)
+static void Host_Noclip_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
Sets client to flymode
==================
*/
-void Host_Fly_f (void)
+static void Host_Fly_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
==================
*/
void Host_Pings_f (void); // called by Host_Ping_f
-void Host_Ping_f (void)
+static void Host_Ping_f (void)
{
int i;
client_t *client;
command from the console. Active clients are kicked off.
======================
*/
-void Host_Map_f (void)
+static void Host_Map_f (void)
{
char level[MAX_QPATH];
Goes to a new map, taking all clients along
==================
*/
-void Host_Changelevel_f (void)
+static void Host_Changelevel_f (void)
{
char level[MAX_QPATH];
MR_ToggleMenu(0);
key_dest = key_game;
- SV_VM_Begin();
SV_SaveSpawnparms ();
- SV_VM_End();
allowcheats = sv_cheats.integer != 0;
strlcpy(level, Cmd_Argv(1), sizeof(level));
SV_SpawnServer(level);
Restarts the current server for a dead player
==================
*/
-void Host_Restart_f (void)
+static void Host_Restart_f (void)
{
char mapname[MAX_QPATH];
User command to connect to server
=====================
*/
-void Host_Connect_f (void)
+static void Host_Connect_f (void)
{
if (Cmd_Argc() < 2)
{
#define SAVEGAME_VERSION 5
-void Host_Savegame_to (const char *name)
+void Host_Savegame_to(prvm_prog_t *prog, const char *name)
{
qfile_t *f;
int i, k, l, lightstyles = 64;
if (sv.lightstyles[i][0])
lightstyles = i+1;
- isserver = !strcmp(PRVM_NAME, "server");
+ isserver = prog == SVVM_prog;
Con_Printf("Saving game to %s...\n", name);
f = FS_OpenRealFile(name, "wb", false);
memset(comment, 0, sizeof(comment));
if(isserver)
- dpsnprintf(comment, sizeof(comment), "%-21.21s kills:%3i/%3i", PRVM_GetString(PRVM_serveredictstring(prog->edicts, message)), (int)PRVM_serverglobalfloat(killed_monsters), (int)PRVM_serverglobalfloat(total_monsters));
+ dpsnprintf(comment, sizeof(comment), "%-21.21s kills:%3i/%3i", PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message)), (int)PRVM_serverglobalfloat(killed_monsters), (int)PRVM_serverglobalfloat(total_monsters));
else
- dpsnprintf(comment, sizeof(comment), "(crash dump of %s progs)", PRVM_NAME);
+ dpsnprintf(comment, sizeof(comment), "(crash dump of %s progs)", prog->name);
// convert space to _ to make stdio happy
// LordHavoc: convert control characters to _ as well
for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
FS_Print(f,"m\n");
}
- PRVM_ED_WriteGlobals (f);
+ PRVM_ED_WriteGlobals (prog, f);
for (i=0 ; i<prog->num_edicts ; i++)
{
FS_Printf(f,"// edict %d\n", i);
//Con_Printf("edict %d...\n", i);
- PRVM_ED_Write (f, PRVM_EDICT_NUM(i));
+ PRVM_ED_Write (prog, f, PRVM_EDICT_NUM(i));
}
#if 1
Host_Savegame_f
===============
*/
-void Host_Savegame_f (void)
+static void Host_Savegame_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
char name[MAX_QPATH];
qboolean deadflag = false;
return;
}
- SV_VM_Begin();
deadflag = cl.islocalgame && svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag);
- SV_VM_End();
if (cl.islocalgame)
{
strlcpy (name, Cmd_Argv(1), sizeof (name));
FS_DefaultExtension (name, ".sav", sizeof (name));
- SV_VM_Begin();
- Host_Savegame_to(name);
- SV_VM_End();
+ Host_Savegame_to(prog, name);
}
===============
*/
-void Host_Loadgame_f (void)
+static void Host_Loadgame_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
char filename[MAX_QPATH];
char mapname[MAX_QPATH];
float time;
Con_Printf("Host_Loadgame_f: loading version\n");
// version
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
version = atoi(com_token);
if (version != SAVEGAME_VERSION)
{
Con_Printf("Host_Loadgame_f: loading description\n");
// description
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
for (i = 0;i < NUM_SPAWN_PARMS;i++)
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
spawn_parms[i] = atof(com_token);
}
// skill
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
// this silliness is so we can load 1.06 save files, which have float skill values
current_skill = (int)(atof(com_token) + 0.5);
Cvar_SetValue ("skill", (float)current_skill);
Con_Printf("Host_Loadgame_f: loading mapname\n");
// mapname
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
strlcpy (mapname, com_token, sizeof(mapname));
if(developer_entityparsing.integer)
Con_Printf("Host_Loadgame_f: loading time\n");
// time
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
time = atof(com_token);
allowcheats = sv_cheats.integer != 0;
// load the light styles
- SV_VM_Begin();
// -1 is the globals
entnum = -1;
{
// light style
start = t;
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
// if this is a 64 lightstyle savegame produced by Quake, stop now
// we have to check this because darkplaces may save more than 64
if (com_token[0] == '{')
for (;;)
{
start = t;
- if (!COM_ParseToken_Simple(&t, false, false))
+ if (!COM_ParseToken_Simple(&t, false, false, true))
break;
if (com_token[0] == '{')
{
for (;;)
{
start = t;
- while (COM_ParseToken_Simple(&t, false, false))
+ while (COM_ParseToken_Simple(&t, false, false, true))
if (!strcmp(com_token, "}"))
break;
- if (!COM_ParseToken_Simple(&start, false, false))
+ if (!COM_ParseToken_Simple(&start, false, false, true))
{
// end of file
break;
Con_Printf("Host_Loadgame_f: loading globals\n");
// parse the global vars
- PRVM_ED_ParseGlobals (start);
+ PRVM_ED_ParseGlobals (prog, start);
// restore the autocvar globals
Cvar_UpdateAllAutoCvars();
Host_Error("Host_PerformLoadGame: too many edicts in save file (reached MAX_EDICTS %i)", MAX_EDICTS);
}
while (entnum >= prog->max_edicts)
- PRVM_MEM_IncreaseEdicts();
+ PRVM_MEM_IncreaseEdicts(prog);
ent = PRVM_EDICT_NUM(entnum);
memset(ent->fields.vp, 0, prog->entityfields * 4);
ent->priv.server->free = false;
if(developer_entityparsing.integer)
Con_Printf("Host_Loadgame_f: loading edict %d\n", entnum);
- PRVM_ED_ParseEdict (start, ent);
+ PRVM_ED_ParseEdict (prog, start, ent);
// link it into the bsp tree
if (!ent->priv.server->free)
memset(sv.lightstyles[0], 0, sizeof(sv.lightstyles));
memset(sv.model_precache[0], 0, sizeof(sv.model_precache));
memset(sv.sound_precache[0], 0, sizeof(sv.sound_precache));
- while (COM_ParseToken_Simple(&t, false, false))
+ while (COM_ParseToken_Simple(&t, false, false, true))
{
if (!strcmp(com_token, "sv.lightstyles"))
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
if (i >= 0 && i < MAX_LIGHTSTYLES)
strlcpy(sv.lightstyles[i], com_token, sizeof(sv.lightstyles[i]));
else
}
else if (!strcmp(com_token, "sv.model_precache"))
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
if (i >= 0 && i < MAX_MODELS)
{
strlcpy(sv.model_precache[i], com_token, sizeof(sv.model_precache[i]));
}
else if (!strcmp(com_token, "sv.sound_precache"))
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
if (i >= 0 && i < MAX_SOUNDS)
strlcpy(sv.sound_precache[i], com_token, sizeof(sv.sound_precache[i]));
else
}
else if (!strcmp(com_token, "sv.bufstr"))
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
k = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
// VorteX: nasty code, cleanup required
// create buffer at this index
}
}
// skip any trailing text or unrecognized commands
- while (COM_ParseToken_Simple(&t, true, false) && strcmp(com_token, "\n"))
+ while (COM_ParseToken_Simple(&t, true, false, true) && strcmp(com_token, "\n"))
;
}
}
if(developer_entityparsing.integer)
Con_Printf("Host_Loadgame_f: finished\n");
- SV_VM_End();
-
// make sure we're connected to loopback
if (sv.active && cls.state == ca_disconnected)
CL_EstablishConnection("local:1", -2);
======================
*/
cvar_t cl_name = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_name", "player", "internal storage cvar for current player name (changed by name command)"};
-void Host_Name_f (void)
+static void Host_Name_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
qboolean valid_colors;
const char *newNameSource;
if (realtime < host_client->nametime)
{
- SV_ClientPrintf("You can't change name more than once every 5 seconds!\n");
+ SV_ClientPrintf("You can't change name more than once every %.1f seconds!\n", max(0.0f, sv_namechangetimer.value));
return;
}
- host_client->nametime = realtime + 5;
+ host_client->nametime = realtime + max(0.0f, sv_namechangetimer.value);
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->name, newName, sizeof (host_client->name));
if (j >= 0 && strlen(host_client->name) < sizeof(host_client->name) - 2)
memcpy(host_client->name + strlen(host_client->name), STRING_COLOR_DEFAULT_STR, strlen(STRING_COLOR_DEFAULT_STR) + 1);
- PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(host_client->name);
+ PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
if (host_client->spawned)
*/
cvar_t cl_playermodel = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playermodel", "", "internal storage cvar for current player model in Nexuiz/Xonotic (changed by playermodel command)"};
// the old cl_playermodel in cl_main has been renamed to __cl_playermodel
-void Host_Playermodel_f (void)
+static void Host_Playermodel_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
char newPath[sizeof(host_client->playermodel)];
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->playermodel, newPath, sizeof (host_client->playermodel));
- PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(host_client->playermodel);
+ PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(prog, host_client->playermodel);
if (strcmp(host_client->old_model, host_client->playermodel))
{
strlcpy(host_client->old_model, host_client->playermodel, sizeof(host_client->old_model));
======================
*/
cvar_t cl_playerskin = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playerskin", "", "internal storage cvar for current player skin in Nexuiz/Xonotic (changed by playerskin command)"};
-void Host_Playerskin_f (void)
+static void Host_Playerskin_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
char newPath[sizeof(host_client->playerskin)];
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->playerskin, newPath, sizeof (host_client->playerskin));
- PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(host_client->playerskin);
+ PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(prog, host_client->playerskin);
if (strcmp(host_client->old_skin, host_client->playerskin))
{
//if (host_client->spawned)
}
}
-void Host_Version_f (void)
+static void Host_Version_f (void)
{
Con_Printf("Version: %s build %s\n", gamename, buildstring);
}
-void Host_Say(qboolean teamonly)
+static void Host_Say(qboolean teamonly)
{
+ prvm_prog_t *prog = SVVM_prog;
client_t *save;
int j, quoted;
const char *p1;
}
-void Host_Say_f(void)
+static void Host_Say_f(void)
{
Host_Say(false);
}
-void Host_Say_Team_f(void)
+static void Host_Say_Team_f(void)
{
Host_Say(true);
}
-void Host_Tell_f(void)
+static void Host_Tell_f(void)
{
const char *playername_start = NULL;
size_t playername_length = 0;
==================
*/
cvar_t cl_color = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_color", "0", "internal storage cvar for current player colors (changed by color command)"};
-void Host_Color(int changetop, int changebottom)
+static void Host_Color(int changetop, int changebottom)
{
+ prvm_prog_t *prog = SVVM_prog;
int top, bottom, playercolor;
// get top and bottom either from the provided values or the current values
if (cls.protocol == PROTOCOL_QUAKEWORLD)
return;
- if (host_client->edict && PRVM_clientfunction(SV_ChangeTeam))
+ if (host_client->edict && PRVM_serverfunction(SV_ChangeTeam))
{
Con_DPrint("Calling SV_ChangeTeam\n");
- PRVM_serverglobalfloat(time) = sv.time;
prog->globals.generic[OFS_PARM0] = playercolor;
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram(PRVM_clientfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
}
else
{
}
}
-void Host_Color_f(void)
+static void Host_Color_f(void)
{
int top, bottom;
Host_Color(top, bottom);
}
-void Host_TopColor_f(void)
+static void Host_TopColor_f(void)
{
if (Cmd_Argc() == 1)
{
Host_Color(atoi(Cmd_Argv(1)), -1);
}
-void Host_BottomColor_f(void)
+static void Host_BottomColor_f(void)
{
if (Cmd_Argc() == 1)
{
}
cvar_t cl_rate = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_rate", "20000", "internal storage cvar for current rate (changed by rate command)"};
-void Host_Rate_f(void)
+static void Host_Rate_f(void)
{
int rate;
Host_Kill_f
==================
*/
-void Host_Kill_f (void)
+static void Host_Kill_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (PRVM_serveredictfloat(host_client->edict, health) <= 0)
{
SV_ClientPrint("Can't suicide -- already dead!\n");
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (PRVM_serverfunction(ClientKill), "QC function ClientKill is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(ClientKill), "QC function ClientKill is missing");
}
Host_Pause_f
==================
*/
-void Host_Pause_f (void)
+static void Host_Pause_f (void)
{
- if (!pausable.integer)
- SV_ClientPrint("Pause not allowed.\n");
+ void (*print) (const char *fmt, ...);
+ if (cmd_source == src_command)
+ {
+ // if running a client, try to send over network so the pause is handled by the server
+ if (cls.state == ca_connected)
+ {
+ Cmd_ForwardToServer ();
+ return;
+ }
+ print = Con_Printf;
+ }
else
+ print = SV_ClientPrintf;
+
+ if (!pausable.integer)
{
- sv.paused ^= 1;
- SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
- // send notification to all clients
- MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
- MSG_WriteByte(&sv.reliable_datagram, sv.paused);
+ if (cmd_source == src_client)
+ {
+ if(cls.state == ca_dedicated || host_client == &svs.clients[0]) // non-admin
+ {
+ print("Pause not allowed.\n");
+ return;
+ }
+ }
}
+
+ sv.paused ^= 1;
+ SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
+ // send notification to all clients
+ MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
+ MSG_WriteByte(&sv.reliable_datagram, sv.paused);
}
/*
cvar_t cl_pmodel = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_pmodel", "0", "internal storage cvar for current player model number in nehahra (changed by pmodel command)"};
static void Host_PModel_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
if (Cmd_Argc () == 1)
Host_PreSpawn_f
==================
*/
-void Host_PreSpawn_f (void)
+static void Host_PreSpawn_f (void)
{
if (host_client->spawned)
{
Host_Spawn_f
==================
*/
-void Host_Spawn_f (void)
+static void Host_Spawn_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
client_t *client;
int stats[MAX_CL_STATS];
Con_DPrint("Calling RestoreGame\n");
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram(PRVM_serverfunction(RestoreGame), "QC function RestoreGame is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(RestoreGame), "QC function RestoreGame is missing");
}
}
else
host_client->clientconnectcalled = true;
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
if (cls.state == ca_dedicated)
Con_Printf("%s connected\n", host_client->name);
- PRVM_ExecuteProgram (PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
+ PRVM_serverglobalfloat(time) = sv.time;
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
}
if (!host_client->netconnection)
Host_Begin_f
==================
*/
-void Host_Begin_f (void)
+static void Host_Begin_f (void)
{
host_client->spawned = true;
Kicks a user off of the server
==================
*/
-void Host_Kick_f (void)
+static void Host_Kick_f (void)
{
const char *who;
const char *message = NULL;
if (!sv.active)
return;
- SV_VM_Begin();
save = host_client;
if (Cmd_Argc() > 2 && strcmp(Cmd_Argv(1), "#") == 0)
if (Cmd_Argc() > 2)
{
message = Cmd_Args();
- COM_ParseToken_Simple(&message, false, false);
+ COM_ParseToken_Simple(&message, false, false, true);
if (byNumber)
{
message++; // skip the #
}
host_client = save;
- SV_VM_End();
}
/*
Host_Give_f
==================
*/
-void Host_Give_f (void)
+static void Host_Give_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
const char *t;
int v;
}
}
-prvm_edict_t *FindViewthing (void)
+static prvm_edict_t *FindViewthing(prvm_prog_t *prog)
{
int i;
prvm_edict_t *e;
for (i=0 ; i<prog->num_edicts ; i++)
{
e = PRVM_EDICT_NUM(i);
- if (!strcmp (PRVM_GetString(PRVM_serveredictstring(e, classname)), "viewthing"))
+ if (!strcmp (PRVM_GetString(prog, PRVM_serveredictstring(e, classname)), "viewthing"))
return e;
}
Con_Print("No viewthing on map\n");
Host_Viewmodel_f
==================
*/
-void Host_Viewmodel_f (void)
+static void Host_Viewmodel_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
-
- m = Mod_ForName (Cmd_Argv(1), false, true, NULL);
- if (!m || !m->loaded || !m->Draw)
+ e = FindViewthing(prog);
+ if (e)
{
- Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(1));
- return;
+ m = Mod_ForName (Cmd_Argv(1), false, true, NULL);
+ if (m && m->loaded && m->Draw)
+ {
+ PRVM_serveredictfloat(e, frame) = 0;
+ cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)] = m;
+ }
+ else
+ Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(1));
}
-
- PRVM_serveredictfloat(e, frame) = 0;
- cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)] = m;
}
/*
Host_Viewframe_f
==================
*/
-void Host_Viewframe_f (void)
+static void Host_Viewframe_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
int f;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
- m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
+ e = FindViewthing(prog);
+ if (e)
+ {
+ m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
- f = atoi(Cmd_Argv(1));
- if (f >= m->numframes)
- f = m->numframes-1;
+ f = atoi(Cmd_Argv(1));
+ if (f >= m->numframes)
+ f = m->numframes-1;
- PRVM_serveredictfloat(e, frame) = f;
+ PRVM_serveredictfloat(e, frame) = f;
+ }
}
-void PrintFrameName (dp_model_t *m, int frame)
+static void PrintFrameName (dp_model_t *m, int frame)
{
if (m->animscenes)
Con_Printf("frame %i: %s\n", frame, m->animscenes[frame].name);
Host_Viewnext_f
==================
*/
-void Host_Viewnext_f (void)
+static void Host_Viewnext_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
- m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
+ e = FindViewthing(prog);
+ if (e)
+ {
+ m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
- PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) + 1;
- if (PRVM_serveredictfloat(e, frame) >= m->numframes)
- PRVM_serveredictfloat(e, frame) = m->numframes - 1;
+ PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) + 1;
+ if (PRVM_serveredictfloat(e, frame) >= m->numframes)
+ PRVM_serveredictfloat(e, frame) = m->numframes - 1;
- PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+ PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+ }
}
/*
Host_Viewprev_f
==================
*/
-void Host_Viewprev_f (void)
+static void Host_Viewprev_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
-
- m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
+ e = FindViewthing(prog);
+ if (e)
+ {
+ m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
- PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) - 1;
- if (PRVM_serveredictfloat(e, frame) < 0)
- PRVM_serveredictfloat(e, frame) = 0;
+ PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) - 1;
+ if (PRVM_serveredictfloat(e, frame) < 0)
+ PRVM_serveredictfloat(e, frame) = 0;
- PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+ PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+ }
}
/*
Host_Startdemos_f
==================
*/
-void Host_Startdemos_f (void)
+static void Host_Startdemos_f (void)
{
int i, c;
Return to looping demos
==================
*/
-void Host_Demos_f (void)
+static void Host_Demos_f (void)
{
if (cls.state == ca_dedicated)
return;
Return to looping demos
==================
*/
-void Host_Stopdemo_f (void)
+static void Host_Stopdemo_f (void)
{
if (!cls.demoplayback)
return;
Host_ShutdownServer ();
}
-void Host_SendCvar_f (void)
+static void Host_SendCvar_f (void)
{
int i;
cvar_t *c;
const char *cvarname;
client_t *old;
+ char vabuf[1024];
if(Cmd_Argc() != 2)
return;
// LordHavoc: if there is no such cvar or if it is private, send a
// reply indicating that it has no value
if(!c || (c->flags & CVAR_PRIVATE))
- Cmd_ForwardStringToServer(va("sentcvar %s", cvarname));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "sentcvar %s", cvarname));
else
- Cmd_ForwardStringToServer(va("sentcvar %s \"%s\"", c->name, c->string));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "sentcvar %s \"%s\"", c->name, c->string));
return;
}
if(!sv.active)// || !PRVM_serverfunction(SV_ParseClientCommand))
ProQuake rcon support
=====================
*/
-void Host_PQRcon_f (void)
+static void Host_PQRcon_f (void)
{
int n;
const char *e;
mysocket = NetConn_ChooseClientSocketForAddress(&to);
if (mysocket)
{
- SZ_Clear(&net_message);
- MSG_WriteLong (&net_message, 0);
- MSG_WriteByte (&net_message, CCREQ_RCON);
- SZ_Write(&net_message, (const unsigned char*)rcon_password.string, n);
- MSG_WriteByte (&net_message, 0); // terminate the (possibly partial) string
- MSG_WriteString (&net_message, Cmd_Args());
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, &to);
- SZ_Clear (&net_message);
+ sizebuf_t buf;
+ unsigned char bufdata[64];
+ buf.data = bufdata;
+ SZ_Clear(&buf);
+ MSG_WriteLong(&buf, 0);
+ MSG_WriteByte(&buf, CCREQ_RCON);
+ SZ_Write(&buf, (const unsigned char*)rcon_password.string, n);
+ MSG_WriteByte(&buf, 0); // terminate the (possibly partial) string
+ MSG_WriteString(&buf, Cmd_Args());
+ StoreBigLong(buf.data, NETFLAG_CTL | (buf.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, buf.data, buf.cursize, &to);
+ SZ_Clear(&buf);
}
}
an unconnected command.
=====================
*/
-void Host_Rcon_f (void) // credit: taken from QuakeWorld
+static void Host_Rcon_f (void) // credit: taken from QuakeWorld
{
int i, n;
const char *e;
lhnetaddress_t to;
lhnetsocket_t *mysocket;
+ char vabuf[1024];
if (!rcon_password.string || !rcon_password.string[0])
{
}
else
{
- NetConn_WriteString(mysocket, va("\377\377\377\377rcon %.*s %s", n, rcon_password.string, Cmd_Args()), &to);
+ NetConn_WriteString(mysocket, va(vabuf, sizeof(vabuf), "\377\377\377\377rcon %.*s %s", n, rcon_password.string, Cmd_Args()), &to);
}
}
}
Dump userdata / masterdata for a user
====================
*/
-void Host_User_f (void) // credit: taken from QuakeWorld
+static void Host_User_f (void) // credit: taken from QuakeWorld
{
int uid;
int i;
Dump userids for all current players
====================
*/
-void Host_Users_f (void) // credit: taken from QuakeWorld
+static void Host_Users_f (void) // credit: taken from QuakeWorld
{
int i;
int c;
==================
*/
// TODO: shouldn't this be a cvar instead?
-void Host_FullServerinfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullServerinfo_f (void) // credit: taken from QuakeWorld
{
char temp[512];
if (Cmd_Argc() != 2)
==================
Casey was here :)
*/
-void Host_FullInfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullInfo_f (void) // credit: taken from QuakeWorld
{
char key[512];
char value[512];
Allow clients to change userinfo
==================
*/
-void Host_SetInfo_f (void) // credit: taken from QuakeWorld
+static void Host_SetInfo_f (void) // credit: taken from QuakeWorld
{
if (Cmd_Argc() == 1)
{
Contents allows \n escape character
====================
*/
-void Host_Packet_f (void) // credit: taken from QuakeWorld
+static void Host_Packet_f (void) // credit: taken from QuakeWorld
{
char send[2048];
int i, l;
MSG_WriteString(&host_client->netconnection->message, "\n");
}
-void Host_PingPLReport_f(void)
+static void Host_PingPLReport_f(void)
{
char *errbyte;
int i;
Cmd_AddCommand_WithClientCommand ("say_team", Host_Say_Team_f, Host_Say_Team_f, "send a chat message to your team on the server");
Cmd_AddCommand_WithClientCommand ("tell", Host_Tell_f, Host_Tell_f, "send a chat message to only one person on the server");
Cmd_AddCommand_WithClientCommand ("kill", NULL, Host_Kill_f, "die instantly");
- Cmd_AddCommand_WithClientCommand ("pause", NULL, Host_Pause_f, "pause the game (if the server allows pausing)");
+ Cmd_AddCommand_WithClientCommand ("pause", Host_Pause_f, Host_Pause_f, "pause the game (if the server allows pausing)");
Cmd_AddCommand ("kick", Host_Kick_f, "kick a player off the server by number or name");
Cmd_AddCommand_WithClientCommand ("ping", Host_Ping_f, Host_Ping_f, "print ping times of all players on the server");
Cmd_AddCommand ("load", Host_Loadgame_f, "load a saved game file");
Cvar_RegisterVariable(&sv_adminnick);
Cvar_RegisterVariable(&sv_status_privacy);
Cvar_RegisterVariable(&sv_status_show_qcstatus);
+ Cvar_RegisterVariable(&sv_namechangetimer);
}
void Host_NoOperation_f(void)
int image_width;
int image_height;
-void Image_CopyAlphaFromBlueBGRA(unsigned char *outpixels, const unsigned char *inpixels, int w, int h)
+static void Image_CopyAlphaFromBlueBGRA(unsigned char *outpixels, const unsigned char *inpixels, int w, int h)
{
int i, n;
n = w * h;
LoadPCX
============
*/
-unsigned char* LoadPCX_BGRA (const unsigned char *f, int filesize, int *miplevel)
+static unsigned char* LoadPCX_BGRA (const unsigned char *f, int filesize, int *miplevel)
{
pcx_t pcx;
unsigned char *a, *b, *image_buffer, *pbuf;
}
TargaHeader;
-void PrintTargaHeader(TargaHeader *t)
+static void PrintTargaHeader(TargaHeader *t)
{
Con_Printf("TargaHeader:\nuint8 id_length = %i;\nuint8 colormap_type = %i;\nuint8 image_type = %i;\nuint16 colormap_index = %i;\nuint16 colormap_length = %i;\nuint8 colormap_size = %i;\nuint16 x_origin = %i;\nuint16 y_origin = %i;\nuint16 width = %i;\nuint16 height = %i;\nuint8 pixel_size = %i;\nuint8 attributes = %i;\n", t->id_length, t->colormap_type, t->image_type, t->colormap_index, t->colormap_length, t->colormap_size, t->x_origin, t->y_origin, t->width, t->height, t->pixel_size, t->attributes);
}
int value;
} q2wal_t;
-unsigned char *LoadWAL_BGRA (const unsigned char *f, int filesize, int *miplevel)
+static unsigned char *LoadWAL_BGRA (const unsigned char *f, int filesize, int *miplevel)
{
unsigned char *image_buffer;
const q2wal_t *inwal = (const q2wal_t *)f;
}
static unsigned char image_linearfromsrgb[256];
+static unsigned char image_srgbfromlinear_lightmap[256];
void Image_MakeLinearColorsFromsRGB(unsigned char *pout, const unsigned char *pin, int numpixels)
{
// this math from http://www.opengl.org/registry/specs/EXT/texture_sRGB.txt
if (!image_linearfromsrgb[255])
for (i = 0;i < 256;i++)
- image_linearfromsrgb[i] = (unsigned char)(Image_LinearFloatFromsRGB(i) * 256.0f);
+ image_linearfromsrgb[i] = (unsigned char)floor(Image_LinearFloatFromsRGB(i) * 255.0f + 0.5f);
for (i = 0;i < numpixels;i++)
{
pout[i*4+0] = image_linearfromsrgb[pin[i*4+0]];
}
}
+void Image_MakesRGBColorsFromLinear_Lightmap(unsigned char *pout, const unsigned char *pin, int numpixels)
+{
+ int i;
+ // this math from http://www.opengl.org/registry/specs/EXT/texture_sRGB.txt
+ if (!image_srgbfromlinear_lightmap[255])
+ for (i = 0;i < 256;i++)
+ image_srgbfromlinear_lightmap[i] = (unsigned char)floor(bound(0.0f, Image_sRGBFloatFromLinear_Lightmap(i), 1.0f) * 255.0f + 0.5f);
+ for (i = 0;i < numpixels;i++)
+ {
+ pout[i*4+0] = image_srgbfromlinear_lightmap[pin[i*4+0]];
+ pout[i*4+1] = image_srgbfromlinear_lightmap[pin[i*4+1]];
+ pout[i*4+2] = image_srgbfromlinear_lightmap[pin[i*4+2]];
+ pout[i*4+3] = pin[i*4+3];
+ }
+}
+
typedef struct imageformat_s
{
const char *formatstring;
imageformat_t *firstformat, *format;
unsigned char *f, *data = NULL, *data2 = NULL;
char basename[MAX_QPATH], name[MAX_QPATH], name2[MAX_QPATH], *c;
+ char vabuf[1024];
//if (developer_memorydebug.integer)
// Mem_CheckSentinelsGlobal();
if (developer_texturelogging.integer)
{
if(format->loadfunc == JPEG_LoadImage_BGRA) // jpeg can't do alpha, so let's simulate it by loading another jpeg
{
- dpsnprintf (name2, sizeof(name2), format->formatstring, va("%s_alpha", basename));
+ dpsnprintf (name2, sizeof(name2), format->formatstring, va(vabuf, sizeof(vabuf), "%s_alpha", basename));
f = FS_LoadFile(name2, tempmempool, true, &filesize);
if(f)
{
}
#define LERPBYTE(i) r = resamplerow1[i];out[i] = (unsigned char) ((((resamplerow2[i] - r) * lerp) >> 16) + r)
-void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
+static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
{
int i, j, r, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth4 = inwidth*4, outwidth4 = outwidth*4;
unsigned char *out;
resamplerow2 = NULL;
}
-void Image_Resample32Nolerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
+static void Image_Resample32Nolerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
{
int i, j;
unsigned frac, fracstep;
void Image_FixTransparentPixels_f(void);
extern cvar_t r_fixtrans_auto;
-#define Image_LinearFloatFromsRGB(c) (((c) < 11) ? (c) * 0.000302341331f : (float)pow(((c)*(1.0f/256.0f) + 0.055f)*(1.0f/1.0555f), 2.4f))
+#define Image_LinearFloatFromsRGBFloat(c) (((c) <= 0.04045f) ? (c) * (1.0f / 12.92f) : (float)pow(((c) + 0.055f)*(1.0f/1.055f), 2.4f))
+#define Image_sRGBFloatFromLinearFloat(c) (((c) < 0.0031308f) ? (c) * 12.92f : 1.055f * (float)pow((c), 1.0f/2.4f) - 0.055f)
+#define Image_LinearFloatFromsRGB(c) Image_LinearFloatFromsRGBFloat((c) * (1.0f / 255.0f))
+#define Image_sRGBFloatFromLinear(c) Image_sRGBFloatFromLinearFloat((c) * (1.0f / 255.0f))
+#define Image_sRGBFloatFromLinear_Lightmap(c) Image_sRGBFloatFromLinearFloat((c) * (2.0f / 255.0f)) * 0.5f
void Image_MakeLinearColorsFromsRGB(unsigned char *pout, const unsigned char *pin, int numpixels);
+void Image_MakesRGBColorsFromLinear_Lightmap(unsigned char *pout, const unsigned char *pin, int numpixels);
#endif
} my_png;
//LordHavoc: removed __cdecl prefix, added overrun protection, and rewrote this to be more efficient
-void PNG_fReadData(void *png, unsigned char *data, size_t length)
+static void PNG_fReadData(void *png, unsigned char *data, size_t length)
{
size_t l;
l = my_png.tmpBuflength - my_png.tmpi;
//Com_HexDumpToConsole(data, (int)length);
}
-void PNG_fWriteData(void *png, unsigned char *data, size_t length)
+static void PNG_fWriteData(void *png, unsigned char *data, size_t length)
{
FS_Write(my_png.outfile, data, length);
}
-void PNG_fFlushData(void *png)
+static void PNG_fFlushData(void *png)
{
}
-void PNG_error_fn(void *png, const char *message)
+static void PNG_error_fn(void *png, const char *message)
{
Con_Printf("PNG_LoadImage: error: %s\n", message);
}
-void PNG_warning_fn(void *png, const char *message)
+static void PNG_warning_fn(void *png, const char *message)
{
Con_Printf("PNG_LoadImage: warning: %s\n", message);
}
static void CompressedImageCache_Add(const char *imagename, size_t maxsize, void *compressed, size_t compressed_size)
{
- const char *hashkey = va("%s:%d", imagename, (int) maxsize);
+ char vabuf[1024];
+ const char *hashkey = va(vabuf, sizeof(vabuf), "%s:%d", imagename, (int) maxsize);
int hashindex = CRC_Block((unsigned char *) hashkey, strlen(hashkey)) % COMPRESSEDIMAGECACHE_SIZE;
CompressedImageCacheItem *i;
static CompressedImageCacheItem *CompressedImageCache_Find(const char *imagename, size_t maxsize)
{
- const char *hashkey = va("%s:%d", imagename, (int) maxsize);
+ char vabuf[1024];
+ const char *hashkey = va(vabuf, sizeof(vabuf), "%s:%d", imagename, (int) maxsize);
int hashindex = CRC_Block((unsigned char *) hashkey, strlen(hashkey)) % COMPRESSEDIMAGECACHE_SIZE;
CompressedImageCacheItem *i = CompressedImageCache[hashindex];
#include "quakedef.h"
#include "cl_video.h"
#include "utf8lib.h"
+#include "csprogs.h"
cvar_t con_closeontoggleconsole = {CVAR_SAVE, "con_closeontoggleconsole","1", "allows toggleconsole binds to close the console as well; when set to 2, this even works when not at the start of the line in console input; when set to 3, this works even if the toggleconsole key is the color tag"};
history_matchfound = false;
}
-qboolean Key_History_Get_foundCommand(void)
+static qboolean Key_History_Get_foundCommand(void)
{
if (!history_matchfound)
return false;
{
int i;
const char *partial = key_line + 1;
- size_t digits = strlen(va("%i", HIST_MAXLINES));
+ char vabuf[1024];
+ size_t digits = strlen(va(vabuf, sizeof(vabuf), "%i", HIST_MAXLINES));
if (history_line == -1) // editing the "new" line
strlcpy(history_savedline, key_line + 1, sizeof(history_savedline));
if (!*partial)
partial = "*";
else if (!( strchr(partial, '*') || strchr(partial, '?') )) // no pattern?
- partial = va("*%s*", partial);
+ partial = va(vabuf, sizeof(vabuf), "*%s*", partial);
for ( ; i >= 0; i--)
if (matchpattern_with_separator(ConBuffer_GetLine(&history, i), partial, true, "", false))
{
int i;
const char *partial = key_line + 1;
- size_t digits = strlen(va("%i", HIST_MAXLINES));
+ char vabuf[1024];
+ size_t digits = strlen(va(vabuf, sizeof(vabuf), "%i", HIST_MAXLINES));
if (history_line == -1) // editing the "new" line
return;
if (!*partial)
partial = "*";
else if (!( strchr(partial, '*') || strchr(partial, '?') )) // no pattern?
- partial = va("*%s*", partial);
+ partial = va(vabuf, sizeof(vabuf), "*%s*", partial);
for ( ; i < CONBUFFER_LINES_COUNT(&history); i++)
if (matchpattern_with_separator(ConBuffer_GetLine(&history, i), partial, true, "", false))
{
const char *partial = key_line + 1;
int i, count = 0;
- size_t digits = strlen(va("%i", HIST_MAXLINES));
+ char vabuf[1024];
+ size_t digits = strlen(va(vabuf, sizeof(vabuf), "%i", HIST_MAXLINES));
Con_Printf("History commands containing \"%s\":\n", key_line + 1);
if (!*partial)
partial = "*";
else if (!( strchr(partial, '*') || strchr(partial, '?') )) // no pattern?
- partial = va("*%s*", partial);
+ partial = va(vabuf, sizeof(vabuf), "*%s*", partial);
for (i=0; i<CONBUFFER_LINES_COUNT(&history); i++)
if (matchpattern_with_separator(ConBuffer_GetLine(&history, i), partial, true, "", false))
{
char *errchar = NULL;
int i = 0;
- size_t digits = strlen(va("%i", HIST_MAXLINES));
+ char vabuf[1024];
+ size_t digits = strlen(va(vabuf, sizeof(vabuf), "%i", HIST_MAXLINES));
if (Cmd_Argc () > 1)
{
char chat_buffer[MAX_INPUTLINE];
unsigned int chat_bufferlen = 0;
-extern int Nicks_CompleteChatLine(char *buffer, size_t size, unsigned int pos);
-
static void
Key_Message (int key, int ascii)
{
+ char vabuf[1024];
if (key == K_ENTER || ascii == 10 || ascii == 13)
{
if(chat_mode < 0)
- Cmd_ExecuteString(chat_buffer, src_command); // not Cbuf_AddText to allow semiclons in args; however, this allows no variables then. Use aliases!
+ Cmd_ExecuteString(chat_buffer, src_command, true); // not Cbuf_AddText to allow semiclons in args; however, this allows no variables then. Use aliases!
else
- Cmd_ForwardStringToServer(va("%s %s", chat_mode ? "say_team" : "say ", chat_buffer));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "%s %s", chat_mode ? "say_team" : "say ", chat_buffer));
key_dest = key_game;
chat_bufferlen = 0;
===================
*/
const char *
-Key_KeynumToString (int keynum)
+Key_KeynumToString (int keynum, char *tinystr, size_t tinystrlength)
{
const keyname_t *kn;
- static char tinystr[2];
// -1 is an invalid code
if (keynum < 0)
// if it is printable, output it as a single character
if (keynum > 32 && keynum < 256)
{
- tinystr[0] = keynum;
- tinystr[1] = 0;
+ if (tinystrlength >= 2)
+ {
+ tinystr[0] = keynum;
+ tinystr[1] = 0;
+ }
return tinystr;
}
Key_PrintBindList(int j)
{
char bindbuf[MAX_INPUTLINE];
+ char tinystr[2];
const char *p;
int i;
{
Cmd_QuoteString(bindbuf, sizeof(bindbuf), p, "\"\\", false);
if (j == 0)
- Con_Printf("^2%s ^7= \"%s\"\n", Key_KeynumToString (i), bindbuf);
+ Con_Printf("^2%s ^7= \"%s\"\n", Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf);
else
- Con_Printf("^3bindmap %d: ^2%s ^7= \"%s\"\n", j, Key_KeynumToString (i), bindbuf);
+ Con_Printf("^3bindmap %d: ^2%s ^7= \"%s\"\n", j, Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf);
}
}
}
{
int i, j;
char bindbuf[MAX_INPUTLINE];
+ char tinystr[2];
const char *p;
for (j = 0; j < MAX_BINDMAPS; j++)
{
Cmd_QuoteString(bindbuf, sizeof(bindbuf), p, "\"\\", false); // don't need to escape $ because cvars are not expanded inside bind
if (j == 0)
- FS_Printf(f, "bind %s \"%s\"\n", Key_KeynumToString (i), bindbuf);
+ FS_Printf(f, "bind %s \"%s\"\n", Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf);
else
- FS_Printf(f, "in_bind %d %s \"%s\"\n", j, Key_KeynumToString (i), bindbuf);
+ FS_Printf(f, "in_bind %d %s \"%s\"\n", j, Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf);
}
}
}
}
}
-qboolean CL_VM_InputEvent (qboolean down, int key, int ascii);
-
/*
===================
Called by the system between frames for both key up and key down events
const char *bind;
qboolean q;
keydest_t keydest = key_dest;
+ char vabuf[1024];
if (key < 0 || key >= MAX_KEYS)
return;
case key_game:
// csqc has priority over toggle menu if it wants to (e.g. handling escape for UI stuff in-game.. :sick:)
- q = CL_VM_InputEvent(down, key, ascii);
+ q = CL_VM_InputEvent(down ? 0 : 1, key, ascii);
if (!q && down)
MR_ToggleMenu(1);
break;
{
// button commands add keynum as a parm
if (bind[0] == '+')
- Cbuf_AddText (va("%s %i\n", bind, key));
+ Cbuf_AddText (va(vabuf, sizeof(vabuf), "%s %i\n", bind, key));
else
{
Cbuf_AddText (bind);
Cbuf_AddText ("\n");
}
} else if(bind[0] == '+' && !down && keydown[key] == 0)
- Cbuf_AddText(va("-%s %i\n", bind + 1, key));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "-%s %i\n", bind + 1, key));
}
return;
}
Con_ToggleConsole_f ();
return;
}
+
+ if (COM_CheckParm ("-noconsole"))
+ return; // only allow the key bind to turn off console
+
Key_Console (key, ascii);
return;
}
MR_KeyEvent (key, ascii, down);
break;
case key_game:
- q = CL_VM_InputEvent(down, key, ascii);
+ q = CL_VM_InputEvent(down ? 0 : 1, key, ascii);
// ignore key repeats on binds and only send the bind if the event hasnt been already processed by csqc
if (!q && bind)
{
{
// button commands add keynum as a parm
if (bind[0] == '+')
- Cbuf_AddText (va("%s %i\n", bind, key));
+ Cbuf_AddText (va(vabuf, sizeof(vabuf), "%s %i\n", bind, key));
else
{
Cbuf_AddText (bind);
Cbuf_AddText ("\n");
}
} else if(bind[0] == '+' && !down && keydown[key] == 0)
- Cbuf_AddText(va("-%s %i\n", bind + 1, key));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "-%s %i\n", bind + 1, key));
}
break;
default:
}
}
+// a helper to simulate release of ALL keys
+void
+Key_ReleaseAll (void)
+{
+ int key;
+ // clear the event queue first
+ eventqueue_idx = 0;
+ // then send all down events (possibly into the event queue)
+ for(key = 0; key < MAX_KEYS; ++key)
+ if(keydown[key])
+ Key_Event(key, 0, false);
+ // now all keys are guaranteed down (once the event queue is unblocked)
+ // and only future events count
+}
+
/*
===================
Key_ClearStates
extern int key_consoleactive;
extern char *keybindings[MAX_BINDMAPS][MAX_KEYS];
-extern void Key_ClearEditLine(int edit_line);
extern int chat_mode; // 0 for say, 1 for say_team, -1 for command
extern char chat_buffer[MAX_INPUTLINE];
extern unsigned int chat_bufferlen;
+void Key_ClearEditLine(int edit_line);
void Key_WriteBindings(qfile_t *f);
void Key_Init(void);
void Key_Shutdown(void);
void Key_Init_Cvars(void);
void Key_Event(int key, int ascii, qboolean down);
-void Key_ClearStates (void);
+void Key_ReleaseAll (void);
+void Key_ClearStates (void); // FIXME: should this function still exist? Or should Key_ReleaseAll be used instead when shutting down a vid driver?
void Key_EventQueue_Block(void);
void Key_EventQueue_Unblock(void);
{ 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */
};
+extern long keysym2ucs(KeySym keysym); // LordHavoc: suppress warning just in this case, it's not worth having a header file for this...
long keysym2ucs(KeySym keysym)
{
int min = 0;
return LHNETADDRESSTYPE_NONE;
}
-const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress)
+const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
{
#ifdef SUPPORTIPV6
lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
{
#ifndef _WIN32
- static char ifname [IF_NAMESIZE];
-
if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
return ifname;
// The Win32 API doesn't have if_indextoname() until Windows Vista,
// but luckily it just uses the interface ID as the interface name
- static char ifname [16];
-
- if (dpsnprintf(ifname, sizeof(ifname), "%lu", address->addr.in6.sin6_scope_id) > 0)
+ if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0)
return ifname;
#endif
int LHNETADDRESS_FromString(lhnetaddress_t *address, const char *string, int defaultport);
int LHNETADDRESS_ToString(const lhnetaddress_t *address, char *string, int stringbuffersize, int includeport);
int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address);
-const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *address);
+const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *address, char *ifname, size_t ifnamelength);
int LHNETADDRESS_GetPort(const lhnetaddress_t *address);
int LHNETADDRESS_SetPort(lhnetaddress_t *address, int port);
int LHNETADDRESS_Compare(const lhnetaddress_t *address1, const lhnetaddress_t *address2);
#include "quakedef.h"
#include "fs.h"
#include "libcurl.h"
+#include "thread.h"
static cvar_t cl_curl_maxdownloads = {CVAR_SAVE, "cl_curl_maxdownloads","1", "maximum number of concurrent HTTP/FTP downloads"};
static cvar_t cl_curl_maxspeed = {CVAR_SAVE, "cl_curl_maxspeed","300", "maximum download speed (KiB/s)"};
static dllhandle_t curl_dll = NULL;
// will be checked at many places to find out if qcurl calls are allowed
+void *curl_mutex = NULL;
+
typedef struct downloadinfo_s
{
char filename[MAX_OSPATH];
Setting the command to NULL clears it.
====================
*/
-void Curl_CommandWhenDone(const char *cmd)
+static void Curl_CommandWhenDone(const char *cmd)
{
if(!curl_dll)
return;
Problem: what counts as an error?
*/
-void Curl_CommandWhenError(const char *cmd)
+static void Curl_CommandWhenError(const char *cmd)
{
if(!curl_dll)
return;
downloadinfo *di;
if(noclear)
return;
+ if (curl_mutex) Thread_LockMutex(curl_mutex);
for(di = downloads; di; di = di->next)
di->forthismap = false;
Curl_CommandWhenError(NULL);
numdownloads_fail = 0;
numdownloads_success = 0;
numdownloads_added = 0;
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
}
/*
void Curl_Register_predownload(void)
{
+ if (curl_mutex) Thread_LockMutex(curl_mutex);
Curl_CommandWhenDone("cl_begindownloads");
Curl_CommandWhenError("cl_begindownloads");
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
}
/*
{
if(!curl_dll)
return;
- if(numdownloads_added && (numdownloads_success == numdownloads_added) && *command_when_done)
+ if(numdownloads_added && ((numdownloads_success + numdownloads_fail) == numdownloads_added))
{
- Con_DPrintf("cURL downloads occurred, executing %s\n", command_when_done);
- Cbuf_AddText("\n");
- Cbuf_AddText(command_when_done);
- Cbuf_AddText("\n");
- Curl_Clear_forthismap();
- }
- else if(numdownloads_added && numdownloads_fail && *command_when_error)
- {
- Con_DPrintf("cURL downloads FAILED, executing %s\n", command_when_error);
- Cbuf_AddText("\n");
- Cbuf_AddText(command_when_error);
- Cbuf_AddText("\n");
+ if(numdownloads_fail == 0)
+ {
+ Con_DPrintf("cURL downloads occurred, executing %s\n", command_when_done);
+ Cbuf_AddText("\n");
+ Cbuf_AddText(command_when_done);
+ Cbuf_AddText("\n");
+ }
+ else
+ {
+ Con_DPrintf("cURL downloads FAILED, executing %s\n", command_when_error);
+ Cbuf_AddText("\n");
+ Cbuf_AddText(command_when_error);
+ Cbuf_AddText("\n");
+ }
Curl_Clear_forthismap();
}
}
}
}
-static void curl_quiet_callback(int status, size_t length_received, unsigned char *buffer, void *cbdata)
-{
- curl_default_callback(status, length_received, buffer, cbdata);
-}
-
/*
====================
Curl_EndDownload
Returns a "cleaned up" URL for display (to strip login data)
====================
*/
-static const char *CleanURL(const char *url)
+static const char *CleanURL(const char *url, char *urlbuf, size_t urlbuflength)
{
- static char urlbuf[1024];
const char *p, *q, *r;
// if URL is of form anything://foo-without-slash@rest, replace by anything://rest
r = strchr(p + 3, '/');
if(!r || q < r)
{
- dpsnprintf(urlbuf, sizeof(urlbuf), "%.*s%s", (int)(p - url + 3), url, q + 1);
+ dpsnprintf(urlbuf, urlbuflength, "%.*s%s", (int)(p - url + 3), url, q + 1);
return urlbuf;
}
}
static void CheckPendingDownloads(void)
{
const char *h;
+ char urlbuf[1024];
+ char vabuf[1024];
if(!curl_dll)
return;
if(numdownloads < cl_curl_maxdownloads.integer)
{
if(!di->buffer)
{
- Con_Printf("Downloading %s -> %s", CleanURL(di->url), di->filename);
+ Con_Printf("Downloading %s -> %s", CleanURL(di->url, urlbuf, sizeof(urlbuf)), di->filename);
di->stream = FS_OpenRealFile(di->filename, "ab", false);
if(!di->stream)
}
else
{
- Con_DPrintf("Downloading %s -> memory\n", CleanURL(di->url));
+ Con_DPrintf("Downloading %s -> memory\n", CleanURL(di->url, urlbuf, sizeof(urlbuf)));
di->startpos = 0;
}
qcurl_easy_setopt(di->curle, CURLOPT_POST, 1);
qcurl_easy_setopt(di->curle, CURLOPT_POSTFIELDS, di->postbuf);
qcurl_easy_setopt(di->curle, CURLOPT_POSTFIELDSIZE, di->postbufsize);
- di->slist = qcurl_slist_append(di->slist, va("Content-Type: %s", di->post_content_type));
+ di->slist = qcurl_slist_append(di->slist, va(vabuf, sizeof(vabuf), "Content-Type: %s", di->post_content_type));
}
// parse extra headers into slist
}
qcurl_easy_setopt(di->curle, CURLOPT_HTTPHEADER, di->slist);
-
qcurl_multi_add_handle(curlm, di->curle);
di->started = true;
CURL_OpenLibrary();
if(!curl_dll)
return;
+ if (Thread_HasThreads()) curl_mutex = Thread_CreateMutex();
qcurl_global_init(CURL_GLOBAL_NOTHING);
curlm = qcurl_multi_init();
}
return;
Curl_ClearRequirements();
Curl_CancelAll();
+ if (curl_mutex) Thread_DestroyMutex(curl_mutex);
CURL_CloseLibrary();
curl_dll = NULL;
}
return NULL;
}
-void Curl_Cancel_ToMemory(curl_callback_t callback, void *cbdata)
-{
- downloadinfo *di;
- if(!curl_dll)
- return;
- for(di = downloads; di; )
- {
- if(di->callback == callback && di->callback_data == cbdata)
- {
- di->callback = curl_quiet_callback; // do NOT call the callback
- Curl_EndDownload(di, CURL_DOWNLOAD_ABORTED, CURLE_OK);
- di = downloads;
- }
- else
- di = di->next;
- }
-}
-
/*
====================
Curl_Begin
// 141.2.16.3 - - [17/Mar/2006:22:32:43 +0100] "GET /maps/tznex07.pk3 HTTP/1.1" 200 1077455 "dp://141.2.16.7:26000/" "Nexuiz Linux 22:07:43 Mar 17 2006"
if(!name)
- name = CleanURL(URL);
+ name = CleanURL(URL, urlbuf, sizeof(urlbuf));
+
+ if (curl_mutex) Thread_LockMutex(curl_mutex);
if(!buf)
{
downloadinfo *di = Curl_Find(fn);
if(di)
{
- Con_Printf("Can't download %s, already getting it from %s!\n", fn, CleanURL(di->url));
+ Con_Printf("Can't download %s, already getting it from %s!\n", fn, CleanURL(di->url, urlbuf, sizeof(urlbuf)));
// however, if it was not for this map yet...
if(forthismap && !di->forthismap)
if(strncmp(URL, "http://", 7) && strncmp(URL, "ftp://", 6) && strncmp(URL, "https://", 8))
{
Con_Printf("Curl_Begin(\"%s\"): nasty URL scheme rejected\n", URL);
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
return false;
}
}
downloads = di;
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
return true;
}
}
if(!curl_dll)
return;
+ if (curl_mutex) Thread_LockMutex(curl_mutex);
+
Curl_CheckCommandWhenDone();
if(!downloads)
+ {
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
return;
+ }
if(realtime < curltime) // throttle
+ {
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
return;
+ }
{
int remaining;
for(di = downloads; di; di = di->next)
{
double b = 0;
- qcurl_easy_getinfo(di->curle, CURLINFO_SIZE_UPLOAD, &b);
- bytes_sent += (b - di->bytes_sent_curl);
- di->bytes_sent_curl = b;
- qcurl_easy_getinfo(di->curle, CURLINFO_SIZE_DOWNLOAD, &b);
- bytes_sent += (b - di->bytes_received_curl);
- di->bytes_received_curl = b;
+ if(di->curle)
+ {
+ qcurl_easy_getinfo(di->curle, CURLINFO_SIZE_UPLOAD, &b);
+ bytes_sent += (b - di->bytes_sent_curl);
+ di->bytes_sent_curl = b;
+ qcurl_easy_getinfo(di->curle, CURLINFO_SIZE_DOWNLOAD, &b);
+ bytes_sent += (b - di->bytes_received_curl);
+ di->bytes_received_curl = b;
+ }
}
for(;;)
}
else
curltime = realtime;
+
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
}
/*
if(!curl_dll)
return;
+ if (curl_mutex) Thread_LockMutex(curl_mutex);
+
while(downloads)
{
Curl_EndDownload(downloads, CURL_DOWNLOAD_ABORTED, CURLE_OK);
// INVARIANT: downloads will point to the next download after that!
}
+
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
}
/*
static void Curl_Info_f(void)
{
downloadinfo *di;
+ char urlbuf[1024];
if(!curl_dll)
return;
if(Curl_Running())
{
+ if (curl_mutex) Thread_LockMutex(curl_mutex);
Con_Print("Currently running downloads:\n");
for(di = downloads; di; di = di->next)
{
double speed, percent;
- Con_Printf(" %s -> %s ", CleanURL(di->url), di->filename);
+ Con_Printf(" %s -> %s ", CleanURL(di->url, urlbuf, sizeof(urlbuf)), di->filename);
percent = 100.0 * Curl_GetDownloadAmount(di);
speed = Curl_GetDownloadSpeed(di);
if(percent >= 0)
else
Con_Print("(queued)\n");
}
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
}
else
{
once the last download completes successfully, reconnect to the current server
====================
*/
-void Curl_Curl_f(void)
+static void Curl_Curl_f(void)
{
double maxspeed = 0;
int i;
array must be freed later using Z_Free.
====================
*/
-Curl_downloadinfo_t *Curl_GetDownloadInfo(int *nDownloads, const char **additional_info)
+Curl_downloadinfo_t *Curl_GetDownloadInfo(int *nDownloads, const char **additional_info, char *addinfo, size_t addinfolength)
{
int i;
downloadinfo *di;
Curl_downloadinfo_t *downinfo;
- static char addinfo[128];
if(!curl_dll)
{
return NULL;
}
+ if (curl_mutex) Thread_LockMutex(curl_mutex);
+
i = 0;
for(di = downloads; di; di = di->next)
++i;
if(*command_when_done && !numdownloads_fail && numdownloads_added)
{
if(!strncmp(command_when_done, "connect ", 8))
- dpsnprintf(addinfo, sizeof(addinfo), "(will join %s when done)", command_when_done + 8);
+ dpsnprintf(addinfo, addinfolength, "(will join %s when done)", command_when_done + 8);
else if(!strcmp(command_when_done, "cl_begindownloads"))
- dpsnprintf(addinfo, sizeof(addinfo), "(will enter the game when done)");
+ dpsnprintf(addinfo, addinfolength, "(will enter the game when done)");
else
- dpsnprintf(addinfo, sizeof(addinfo), "(will do '%s' when done)", command_when_done);
+ dpsnprintf(addinfo, addinfolength, "(will do '%s' when done)", command_when_done);
*additional_info = addinfo;
}
else
}
*nDownloads = i;
+ if (curl_mutex) Thread_UnlockMutex(curl_mutex);
return downinfo;
}
*/
static const char *Curl_FindPackURL(const char *filename)
{
- static char foundurl[1024];
+ static char foundurl[1024]; // invoked only by server
fs_offset_t filesize;
char *buf = (char *) FS_LoadFile("curl_urls.txt", tempmempool, true, &filesize);
if(buf && filesize)
foundone = Curl_SendRequirement(req->filename, foundone, sendbuffer, sizeof(sendbuffer)) || foundone;
p = sv_curl_serverpackages.string;
- while(COM_ParseToken_Simple(&p, false, false))
+ while(COM_ParseToken_Simple(&p, false, false, true))
foundone = Curl_SendRequirement(com_token, foundone, sendbuffer, sizeof(sendbuffer)) || foundone;
if(foundone)
qboolean Curl_Begin_ToMemory(const char *URL, double maxspeed, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata);
qboolean Curl_Begin_ToMemory_POST(const char *URL, const char *extraheaders, double maxspeed, const char *post_content_type, const unsigned char *postbuf, size_t postbufsize, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata);
- // NOTE: if these return false, the callback will NOT get called, so free your buffer then!
-void Curl_Cancel_ToMemory(curl_callback_t callback, void *cbdata);
- // removes all downloads with the given callback and cbdata (this does NOT call the callbacks!)
void Curl_Init(void);
void Curl_Init_Commands(void);
qboolean queued;
}
Curl_downloadinfo_t;
-Curl_downloadinfo_t *Curl_GetDownloadInfo(int *nDownloads, const char **additional_info);
+Curl_downloadinfo_t *Curl_GetDownloadInfo(int *nDownloads, const char **additional_info, char *addinfo, size_t addinfolength);
// this may and should be Z_Free()ed
// the result is actually an array
// an additional info string may be returned in additional_info as a
LDFLAGS_D3D=-ld3d9
else
CFLAGS_D3D=
- CFLAGS_WARNINGS=-Wall -Wold-style-definition -Wstrict-prototypes -Wsign-compare -Wdeclaration-after-statement
+ CFLAGS_WARNINGS=-Wall -Wold-style-definition -Wstrict-prototypes -Wsign-compare -Wdeclaration-after-statement -Wmissing-prototypes
LDFLAGS_D3D=
endif
cl_collision.o \
cl_demo.o \
cl_dyntexture.o \
- cl_gecko.o \
cl_input.o \
cl_main.o \
cl_parse.o \
int LoopingFrameNumberFromDouble(double t, int loopframes);
+void Mathlib_Init(void);
+
#endif
M_ToggleMenu
================
*/
-void M_ToggleMenu(int mode)
+static void M_ToggleMenu(int mode)
{
m_entersound = true;
}
-void M_Menu_Demos_f (void)
+static void M_Menu_Demos_f (void)
{
key_dest = key_menu;
m_state = m_demo;
static void M_Demo_Key (int k, int ascii)
{
+ char vabuf[1024];
switch (k)
{
case K_ESCAPE:
S_LocalSound ("sound/misc/menu2.wav");
m_state = m_none;
key_dest = key_game;
- Cbuf_AddText (va ("playdemo %s\n", NehahraDemos[demo_cursor].name));
+ Cbuf_AddText (va(vabuf, sizeof(vabuf), "playdemo %s\n", NehahraDemos[demo_cursor].name));
return;
case K_UPARROW:
{
int f;
cachepic_t *p;
+ char vabuf[1024];
if (m_missingdata)
{
{
if (MAIN_ITEMS == 7 && y1 == 4)
y1++;
- M_DrawPic (0, y2, va("gfx/menu/mainmenu%i", y1));
+ M_DrawPic (0, y2, va(vabuf, sizeof(vabuf), "gfx/menu/mainmenu%i", y1));
y2 += 40;
}
if (MAIN_ITEMS == 7 && m_main_cursor > 2)
y3 = m_main_cursor + 2;
else
y3 = m_main_cursor + 1;
- M_DrawPic (0, 120 + m_main_cursor * 40, va("gfx/menu/mainmenu%iselected", y3));
+ M_DrawPic (0, 120 + m_main_cursor * 40, va(vabuf, sizeof(vabuf), "gfx/menu/mainmenu%iselected", y3));
return;
}
f = (int)(realtime * 10)%6;
- M_DrawPic (54, 32 + m_main_cursor * 20, va("gfx/menudot%i", f+1));
+ M_DrawPic (54, 32 + m_main_cursor * 20, va(vabuf, sizeof(vabuf), "gfx/menudot%i", f+1));
}
static void M_SinglePlayer_Draw (void)
{
cachepic_t *p;
+ char vabuf[1024];
M_Background(320, 200);
f = (int)(realtime * 10)%6;
- M_DrawPic (54, 32 + m_singleplayer_cursor * 20, va("gfx/menudot%i", f+1));
+ M_DrawPic (54, 32 + m_singleplayer_cursor * 20, va(vabuf, sizeof(vabuf), "gfx/menudot%i", f+1));
}
}
buf[len] = 0;
t = buf;
// version
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
//version = atoi(com_token);
// description
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
strlcpy (m_filenames[i], com_token, sizeof (m_filenames[i]));
// change _ back to space
static void M_Load_Key (int k, int ascii)
{
+ char vabuf[1024];
switch (k)
{
case K_ESCAPE:
key_dest = key_game;
// issue the load command
- Cbuf_AddText (va ("load s%i\n", load_cursor) );
+ Cbuf_AddText (va(vabuf, sizeof(vabuf), "load s%i\n", load_cursor) );
return;
case K_UPARROW:
static void M_Save_Key (int k, int ascii)
{
+ char vabuf[1024];
switch (k)
{
case K_ESCAPE:
case K_ENTER:
m_state = m_none;
key_dest = key_game;
- Cbuf_AddText (va("save s%i\n", load_cursor));
+ Cbuf_AddText (va(vabuf, sizeof(vabuf), "save s%i\n", load_cursor));
return;
case K_UPARROW:
{
int y;
cachepic_t *p;
+ char vabuf[1024];
M_Background(640, 480);
p = Draw_CachePic ("gfx/menu/tb-episodes");
M_DrawPic (640/2 - p->width/2, 40, "gfx/menu/tb-episodes");
for (y = 0; y < EPISODE_ITEMS; y++){
- M_DrawPic (0, 160 + y * 40, va("gfx/menu/episode%i", y+1));
+ M_DrawPic (0, 160 + y * 40, va(vabuf, sizeof(vabuf), "gfx/menu/episode%i", y+1));
}
- M_DrawPic (0, 120 + (m_episode_cursor + 1) * 40, va("gfx/menu/episode%iselected", m_episode_cursor + 1));
+ M_DrawPic (0, 120 + (m_episode_cursor + 1) * 40, va(vabuf, sizeof(vabuf), "gfx/menu/episode%iselected", m_episode_cursor + 1));
}
static void M_Transfusion_Episode_Key (int key, int ascii)
{
int y;
cachepic_t *p;
+ char vabuf[1024];
M_Background(640, 480);
p = Draw_CachePic ("gfx/menu/tb-difficulty");
for (y = 0; y < SKILL_ITEMS; y++)
{
- M_DrawPic (0, 180 + y * 40, va("gfx/menu/difficulty%i", y+1));
+ M_DrawPic (0, 180 + y * 40, va(vabuf, sizeof(vabuf), "gfx/menu/difficulty%i", y+1));
}
- M_DrawPic (0, 140 + (m_skill_cursor + 1) *40, va("gfx/menu/difficulty%iselected", m_skill_cursor + 1));
+ M_DrawPic (0, 140 + (m_skill_cursor + 1) *40, va(vabuf, sizeof(vabuf), "gfx/menu/difficulty%iselected", m_skill_cursor + 1));
}
static void M_Transfusion_Skill_Key (int key, int ascii)
{
int f;
cachepic_t *p;
+ char vabuf[1024];
if (gamemode == GAME_TRANSFUSION)
{
p = Draw_CachePic ("gfx/menu/tb-online");
M_DrawPic (640/2 - p->width/2, 140, "gfx/menu/tb-online");
for (f = 1; f <= MULTIPLAYER_ITEMS; f++)
- M_DrawPic (0, 180 + f*40, va("gfx/menu/online%i", f));
- M_DrawPic (0, 220 + m_multiplayer_cursor * 40, va("gfx/menu/online%iselected", m_multiplayer_cursor + 1));
+ M_DrawPic (0, 180 + f*40, va(vabuf, sizeof(vabuf), "gfx/menu/online%i", f));
+ M_DrawPic (0, 220 + m_multiplayer_cursor * 40, va(vabuf, sizeof(vabuf), "gfx/menu/online%iselected", m_multiplayer_cursor + 1));
return;
}
M_Background(320, 200);
f = (int)(realtime * 10)%6;
- M_DrawPic (54, 32 + m_multiplayer_cursor * 20, va("gfx/menudot%i", f+1));
+ M_DrawPic (54, 32 + m_multiplayer_cursor * 20, va(vabuf, sizeof(vabuf), "gfx/menudot%i", f+1));
}
{
int i, j;
cachepic_t *p;
+ char vabuf[1024];
M_Background(320, 200);
}
M_Print(64, 124-8, "Network speed limit");
- M_Print(168, 124, va("%i (%s)", setup_rate, setup_ratetable[setup_rateindex(setup_rate)].name));
+ M_Print(168, 124, va(vabuf, sizeof(vabuf), "%i (%s)", setup_rate, setup_ratetable[setup_rateindex(setup_rate)].name));
M_DrawTextBox (64, 140-8, 14, 1);
M_Print(72, 140, "Accept Changes");
static void M_Setup_Key (int k, int ascii)
{
int l;
+ char vabuf[1024];
switch (k)
{
// setup_cursor == 4 (Accept changes)
if (strcmp(cl_name.string, setup_myname) != 0)
- Cbuf_AddText ( va ("name \"%s\"\n", setup_myname) );
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "name \"%s\"\n", setup_myname) );
if (setup_top != setup_oldtop || setup_bottom != setup_oldbottom)
- Cbuf_AddText( va ("color %i %i\n", setup_top, setup_bottom) );
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "color %i %i\n", setup_top, setup_bottom) );
if (setup_rate != setup_oldrate)
- Cbuf_AddText(va("rate %i\n", setup_rate));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "rate %i\n", setup_rate));
m_entersound = true;
M_Menu_MultiPlayer_f ();
extern cvar_t r_bloom_blur;
extern cvar_t r_bloom_brighten;
extern cvar_t r_bloom_resolution;
-extern cvar_t r_hdr;
extern cvar_t r_hdr_scenebrightness;
extern cvar_t r_hdr_glowintensity;
-extern cvar_t r_hdr_range;
extern cvar_t gl_picmip;
static void M_Menu_Options_Graphics_AdjustSliders (int dir)
else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world, !r_shadow_realtime_world.integer);
else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world_lightmaps, bound(0, r_shadow_realtime_world_lightmaps.value + dir * 0.1, 1));
else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_shadow_realtime_world_shadows, !r_shadow_realtime_world_shadows.integer);
- else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_scenebrightness, bound(0.25, r_hdr_scenebrightness.value + dir * 0.125, 4));
else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom, !r_bloom.integer);
- else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr, !r_hdr.integer);
- else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_range, bound(1, r_hdr_range.value + dir * 0.25, 16));
+ else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_scenebrightness, bound(0.25, r_hdr_scenebrightness.value + dir * 0.125, 4));
else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_hdr_glowintensity, bound(0, r_hdr_glowintensity.value + dir * 0.25, 4));
else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_colorscale, bound(0.0625, r_bloom_colorscale.value + dir * 0.0625, 1));
else if (options_graphics_cursor == optnum++) Cvar_SetValueQuick (&r_bloom_colorsubtract, bound(0, r_bloom_colorsubtract.value + dir * 0.0625, 1-0.0625));
M_Options_PrintCheckbox(" RT World", true, r_shadow_realtime_world.integer);
M_Options_PrintSlider( " RT World Lightmaps", true, r_shadow_realtime_world_lightmaps.value, 0, 1);
M_Options_PrintCheckbox(" RT World Shadow", true, r_shadow_realtime_world_shadows.integer);
+ M_Options_PrintCheckbox(" Bloom Effect", true, r_bloom.integer);
M_Options_PrintSlider( " Scene Brightness", true, r_hdr_scenebrightness.value, 0.25, 4);
- M_Options_PrintCheckbox(" Bloom Effect", !r_hdr.integer, r_bloom.integer);
- M_Options_PrintCheckbox(" HDR Bloom Effect", true, r_hdr.integer);
- M_Options_PrintSlider( " HDR Dynamic Range", r_hdr.integer, r_hdr_range.value, 1, 16);
- M_Options_PrintSlider( " HDR Glow Intensity", r_hdr.integer, r_hdr_glowintensity.value, 0, 4);
- M_Options_PrintSlider( " Bloom Color Scale", r_hdr.integer || r_bloom.integer, r_bloom_colorscale.value, 0.0625, 1);
- M_Options_PrintSlider( " Bloom Color Subtract", r_hdr.integer || r_bloom.integer, r_bloom_colorsubtract.value, 0, 1-0.0625);
- M_Options_PrintSlider( " Bloom Color Exponent", r_hdr.integer || r_bloom.integer, r_bloom_colorexponent.value, 1, 8);
- M_Options_PrintSlider( " Bloom Intensity", r_hdr.integer || r_bloom.integer, r_bloom_brighten.value, 1, 4);
- M_Options_PrintSlider( " Bloom Blur", r_hdr.integer || r_bloom.integer, r_bloom_blur.value, 1, 16);
- M_Options_PrintSlider( " Bloom Resolution", r_hdr.integer || r_bloom.integer, r_bloom_resolution.value, 64, 2048);
+ M_Options_PrintSlider( " Glow Brightness", true, r_hdr_glowintensity.value, 0, 4);
+ M_Options_PrintSlider( " Bloom Color Scale", r_bloom.integer, r_bloom_colorscale.value, 0.0625, 1);
+ M_Options_PrintSlider( " Bloom Color Subtract", r_bloom.integer, r_bloom_colorsubtract.value, 0, 1-0.0625);
+ M_Options_PrintSlider( " Bloom Color Exponent", r_bloom.integer, r_bloom_colorexponent.value, 1, 8);
+ M_Options_PrintSlider( " Bloom Intensity", r_bloom.integer, r_bloom_brighten.value, 1, 4);
+ M_Options_PrintSlider( " Bloom Blur", r_bloom.integer, r_bloom_blur.value, 1, 16);
+ M_Options_PrintSlider( " Bloom Resolution", r_bloom.integer, r_bloom_resolution.value, 64, 2048);
M_Options_PrintCommand( " Restart Renderer", true);
}
strlcpy(keystring, "???", sizeof(keystring));
else
{
+ char tinystr[2];
keystring[0] = 0;
for (j = 0;j < NUMKEYS;j++)
{
{
if (j > 0)
strlcat(keystring, " or ", sizeof(keystring));
- strlcat(keystring, Key_KeynumToString (keys[j]), sizeof(keystring));
+ strlcat(keystring, Key_KeynumToString (keys[j], tinystr, sizeof(tinystr)), sizeof(keystring));
}
}
}
{
char cmd[80];
int keys[NUMKEYS];
+ char tinystr[2];
if (bind_grab)
{ // defining a key
}
else //if (k != '`')
{
- dpsnprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);
+ dpsnprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString (k, tinystr, sizeof(tinystr)), bindnames[keys_cursor][0]);
Cbuf_InsertText (cmd);
}
{
int t;
cachepic_t *p;
+ char vabuf[1024];
if(!!vid_fullscreen.integer != menu_video_resolutions_forfullscreen)
{
// Current and Proposed Resolution
M_Print(16, video_cursor_table[t] - 12, " Current Resolution");
if (vid_supportrefreshrate && vid.userefreshrate && vid.fullscreen)
- M_Print(220, video_cursor_table[t] - 12, va("%dx%d %.2fhz", vid.width, vid.height, vid.refreshrate));
+ M_Print(220, video_cursor_table[t] - 12, va(vabuf, sizeof(vabuf), "%dx%d %.2fhz", vid.width, vid.height, vid.refreshrate));
else
- M_Print(220, video_cursor_table[t] - 12, va("%dx%d", vid.width, vid.height));
+ M_Print(220, video_cursor_table[t] - 12, va(vabuf, sizeof(vabuf), "%dx%d", vid.width, vid.height));
M_Print(16, video_cursor_table[t], " New Resolution");
- M_Print(220, video_cursor_table[t], va("%dx%d", menu_video_resolutions[menu_video_resolution].width, menu_video_resolutions[menu_video_resolution].height));
- M_Print(96, video_cursor_table[t] + 8, va("Type: %s", menu_video_resolutions[menu_video_resolution].type));
+ M_Print(220, video_cursor_table[t], va(vabuf, sizeof(vabuf), "%dx%d", menu_video_resolutions[menu_video_resolution].width, menu_video_resolutions[menu_video_resolution].height));
+ M_Print(96, video_cursor_table[t] + 8, va(vabuf, sizeof(vabuf), "Type: %s", menu_video_resolutions[menu_video_resolution].type));
t++;
// Bits per pixel
static void M_Help_Draw (void)
{
+ char vabuf[1024];
M_Background(320, 200);
- M_DrawPic (0, 0, va("gfx/help%i", help_page));
+ M_DrawPic (0, 0, va(vabuf, sizeof(vabuf), "gfx/help%i", help_page));
}
int basex;
const char *startJoin;
const char *protocol;
+ char vabuf[1024];
M_Background(320, 200);
else
startJoin = "Join Game";
protocol = "TCP/IP";
- M_Print(basex, 32, va ("%s - %s", startJoin, protocol));
+ M_Print(basex, 32, va(vabuf, sizeof(vabuf), "%s - %s", startJoin, protocol));
basex += 8;
M_Print(basex, lanConfig_cursor_table[0], "Port");
static void M_LanConfig_Key (int key, int ascii)
{
int l;
+ char vabuf[1024];
switch (key)
{
}
if (lanConfig_cursor == 3)
- Cbuf_AddText ( va ("connect \"%s\"\n", lanConfig_joinname) );
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "connect \"%s\"\n", lanConfig_joinname) );
break;
case K_BACKSPACE:
{
cachepic_t *p;
int x;
+ char vabuf[1024];
M_Background(320, 200);
M_Print(160, 40, "begin game");
M_Print(0, 56, " Max players");
- M_Print(160, 56, va("%i", maxplayers) );
+ M_Print(160, 56, va(vabuf, sizeof(vabuf), "%i", maxplayers) );
if (gamemode != GAME_GOODVSBAD2)
{
if (fraglimit.integer == 0)
M_Print(160, 88, "none");
else
- M_Print(160, 88, va("%i frags", fraglimit.integer));
+ M_Print(160, 88, va(vabuf, sizeof(vabuf), "%i frags", fraglimit.integer));
M_Print(0, 96, " Time Limit");
if (timelimit.integer == 0)
M_Print(160, 96, "none");
else
- M_Print(160, 96, va("%i minutes", timelimit.integer));
+ M_Print(160, 96, va(vabuf, sizeof(vabuf), "%i minutes", timelimit.integer));
}
M_Print(0, 104, " Public server");
M_Print(160, 104, (sv_public.integer == 0) ? "no" : "yes");
M_Print(0, 112, " Server maxrate");
- M_Print(160, 112, va("%i", sv_maxrate.integer));
+ M_Print(160, 112, va(vabuf, sizeof(vabuf), "%i", sv_maxrate.integer));
M_Print(0, 128, " Server name");
M_DrawTextBox (0, 132, 38, 1);
{
int l;
char hostnamebuf[128];
+ char vabuf[1024];
switch (key)
{
if (gameoptions_cursor == 0)
{
if (sv.active)
- Cbuf_AddText ("disconnect\n");
- Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) );
+ Cbuf_AddText("disconnect\n");
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "maxplayers %u\n", maxplayers) );
- Cbuf_AddText ( va ("map %s\n", gameoptions_levels->levels[gameoptions_levels->episodes[startepisode].firstLevel + startlevel].name) );
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "map %s\n", gameoptions_levels->levels[gameoptions_levels->episodes[startepisode].firstLevel + startlevel].name) );
return;
}
int n, y, visible, start, end, numplayers, maxplayers;
cachepic_t *p;
const char *s;
+ char vabuf[1024];
// use as much vertical space as available
if (gamemode == GAME_TRANSFUSION)
M_Background(640, vid_conheight.integer);
// scroll the list as the cursor moves
ServerList_GetPlayerStatistics(&numplayers, &maxplayers);
- s = va("%i/%i masters %i/%i servers %i/%i players", masterreplycount, masterquerycount, serverreplycount, serverquerycount, numplayers, maxplayers);
+ s = va(vabuf, sizeof(vabuf), "%i/%i masters %i/%i servers %i/%i players", masterreplycount, masterquerycount, serverreplycount, serverquerycount, numplayers, maxplayers);
M_PrintRed((640 - strlen(s) * 8) / 2, 32, s);
if (*m_return_reason)
M_Print(16, menu_height - 8, m_return_reason);
static void M_ServerList_Key(int k, int ascii)
{
+ char vabuf[1024];
switch (k)
{
case K_ESCAPE:
case K_ENTER:
S_LocalSound ("sound/misc/menu2.wav");
if (serverlist_viewcount)
- Cbuf_AddText(va("connect \"%s\"\n", ServerList_GetViewEntry(slist_cursor)->info.cname));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "connect \"%s\"\n", ServerList_GetViewEntry(slist_cursor)->info.cname));
break;
default:
static int modlist_count = 0;
static modlist_entry_t modlist[MODLIST_TOTALSIZE];
-void ModList_RebuildList(void)
+static void ModList_RebuildList(void)
{
int i,j;
stringlist_t list;
stringlistfreecontents(&list);
}
-void ModList_Enable (void)
+static void ModList_Enable (void)
{
int i;
int numgamedirs;
void M_ToggleMenu(int mode);
static void M_Shutdown(void);
-void M_Init (void)
+static void M_Init (void)
{
menuplyr_load = true;
menuplyr_pixels = NULL;
void M_Draw (void)
{
+ char vabuf[1024];
if (key_dest != key_menu && key_dest != key_menu_grabbed)
m_state = m_none;
g = (int)(realtime * 64)%96;
scale_y_rate = (float)(g+1) / 96;
top_offset = (g+12)/12;
- p = Draw_CachePic (va("gfx/menu/blooddrip%i", top_offset));
+ p = Draw_CachePic (va(vabuf, sizeof(vabuf), "gfx/menu/blooddrip%i", top_offset));
drop1 = Draw_CachePic ("gfx/menu/blooddrop1");
drop2 = Draw_CachePic ("gfx/menu/blooddrop2");
drop3 = Draw_CachePic ("gfx/menu/blooddrop3");
DrawQ_Pic (scale_x + 557, scale_y_repeat * .9425 + scale_y + scale_y_rate * scale_y_repeat, drop1, 0, 0, 1, 1, 1, 1, 0);
DrawQ_Pic (scale_x + 606, scale_y_repeat * .5 + scale_y + scale_y_rate * scale_y_repeat, drop2, 0, 0, 1, 1, 1, 1, 0);
}
- DrawQ_Pic (scale_x, -1, Draw_CachePic (va("gfx/menu/blooddrip%i", top_offset)), 0, 0, 1, 1, 1, 1, 0);
+ DrawQ_Pic (scale_x, -1, Draw_CachePic (va(vabuf, sizeof(vabuf), "gfx/menu/blooddrip%i", top_offset)), 0, 0, 1, 1, 1, 1, 0);
}
}
}
}
-void M_NewMap(void)
+static void M_NewMap(void)
{
}
void MR_SetRouting (qboolean forceold);
-void MP_Error(const char *format, ...) DP_FUNC_PRINTF(1);
-void MP_Error(const char *format, ...)
+void MVM_error_cmd(const char *format, ...) DP_FUNC_PRINTF(1);
+void MVM_error_cmd(const char *format, ...)
{
+ prvm_prog_t *prog = MVM_prog;
static qboolean processingError = false;
char errorstring[MAX_INPUTLINE];
va_list argptr;
if( !processingError ) {
processingError = true;
- PRVM_Crash();
+ PRVM_Crash(prog);
processingError = false;
} else {
- Con_Printf( "Menu_Error: Recursive call to MP_Error (from PRVM_Crash)!\n" );
+ Con_Printf( "Menu_Error: Recursive call to MVM_error_cmd (from PRVM_Crash)!\n" );
}
// fall back to the normal menu
Host_AbortCurrentFrame();
}
-void MP_KeyEvent (int key, int ascii, qboolean downevent)
+static void MVM_begin_increase_edicts(prvm_prog_t *prog)
+{
+}
+
+static void MVM_end_increase_edicts(prvm_prog_t *prog)
+{
+}
+
+static void MVM_init_edict(prvm_prog_t *prog, prvm_edict_t *edict)
+{
+}
+
+static void MVM_free_edict(prvm_prog_t *prog, prvm_edict_t *ed)
+{
+}
+
+static void MVM_count_edicts(prvm_prog_t *prog)
+{
+ int i;
+ prvm_edict_t *ent;
+ int active;
+
+ active = 0;
+ for (i=0 ; i<prog->num_edicts ; i++)
+ {
+ ent = PRVM_EDICT_NUM(i);
+ if (ent->priv.required->free)
+ continue;
+ active++;
+ }
+
+ Con_Printf("num_edicts:%3i\n", prog->num_edicts);
+ Con_Printf("active :%3i\n", active);
+}
+
+static qboolean MVM_load_edict(prvm_prog_t *prog, prvm_edict_t *ent)
{
- PRVM_Begin;
- PRVM_SetProg(PRVM_MENUPROG);
+ return true;
+}
+
+static void MP_KeyEvent (int key, int ascii, qboolean downevent)
+{
+ prvm_prog_t *prog = MVM_prog;
// pass key
prog->globals.generic[OFS_PARM0] = (float) key;
prog->globals.generic[OFS_PARM1] = (float) ascii;
if (downevent)
- PRVM_ExecuteProgram(PRVM_menufunction(m_keydown),"m_keydown(float key, float ascii) required");
+ prog->ExecuteProgram(prog, PRVM_menufunction(m_keydown),"m_keydown(float key, float ascii) required");
else if (PRVM_menufunction(m_keyup))
- PRVM_ExecuteProgram(PRVM_menufunction(m_keyup),"m_keyup(float key, float ascii) required");
-
- PRVM_End;
+ prog->ExecuteProgram(prog, PRVM_menufunction(m_keyup),"m_keyup(float key, float ascii) required");
}
-void MP_Draw (void)
+static void MP_Draw (void)
{
+ prvm_prog_t *prog = MVM_prog;
// declarations that are needed right now
float oldquality;
// TODO: this needs to be exposed to R_SetView (or something similar) ASAP [2/5/2008 Andreas]
r_refdef.scene.time = realtime;
- PRVM_Begin;
- PRVM_SetProg(PRVM_MENUPROG);
-
// FIXME: this really shouldnt error out lest we have a very broken refdef state...?
// or does it kill the server too?
- PRVM_ExecuteProgram(PRVM_menufunction(m_draw),"m_draw() required");
-
- PRVM_End;
+ prog->ExecuteProgram(prog, PRVM_menufunction(m_draw),"m_draw() required");
// TODO: imo this should be moved into scene, too [1/27/2008 Andreas]
r_refdef.view.quality = oldquality;
R_SelectScene( RST_CLIENT );
}
-void MP_ToggleMenu(int mode)
+static void MP_ToggleMenu(int mode)
{
- PRVM_Begin;
- PRVM_SetProg(PRVM_MENUPROG);
+ prvm_prog_t *prog = MVM_prog;
prog->globals.generic[OFS_PARM0] = (float) mode;
- PRVM_ExecuteProgram(PRVM_menufunction(m_toggle),"m_toggle() required");
-
- PRVM_End;
+ prog->ExecuteProgram(prog, PRVM_menufunction(m_toggle),"m_toggle() required");
}
-void MP_NewMap(void)
+static void MP_NewMap(void)
{
- PRVM_Begin;
- PRVM_SetProg(PRVM_MENUPROG);
+ prvm_prog_t *prog = MVM_prog;
if (PRVM_menufunction(m_newmap))
- PRVM_ExecuteProgram(PRVM_menufunction(m_newmap),"m_newmap() required");
- PRVM_End;
+ prog->ExecuteProgram(prog, PRVM_menufunction(m_newmap),"m_newmap() required");
}
-void MP_Shutdown (void)
+static void MP_Shutdown (void)
{
- PRVM_Begin;
- PRVM_SetProg(PRVM_MENUPROG);
+ prvm_prog_t *prog = MVM_prog;
- PRVM_ExecuteProgram(PRVM_menufunction(m_shutdown),"m_shutdown() required");
+ prog->ExecuteProgram(prog, PRVM_menufunction(m_shutdown),"m_shutdown() required");
// reset key_dest
key_dest = key_game;
// AK not using this cause Im not sure whether this is useful at all instead :
- PRVM_ResetProg();
-
- PRVM_End;
+ PRVM_Prog_Reset(prog);
}
-void MP_Init (void)
+static void MP_Init (void)
{
- PRVM_Begin;
- PRVM_InitProg(PRVM_MENUPROG);
+ prvm_prog_t *prog = MVM_prog;
+ PRVM_Prog_Init(prog);
prog->edictprivate_size = 0; // no private struct used
- prog->name = M_NAME;
+ prog->name = "menu";
prog->num_edicts = 1;
prog->limit_edicts = M_MAX_EDICTS;
prog->extensionstring = vm_m_extensions;
prog->builtins = vm_m_builtins;
prog->numbuiltins = vm_m_numbuiltins;
- prog->init_cmd = VM_M_Cmd_Init;
- prog->reset_cmd = VM_M_Cmd_Reset;
- prog->error_cmd = MP_Error;
- prog->ExecuteProgram = MVM_ExecuteProgram;
+
+ // all callbacks must be defined (pointers are not checked before calling)
+ prog->begin_increase_edicts = MVM_begin_increase_edicts;
+ prog->end_increase_edicts = MVM_end_increase_edicts;
+ prog->init_edict = MVM_init_edict;
+ prog->free_edict = MVM_free_edict;
+ prog->count_edicts = MVM_count_edicts;
+ prog->load_edict = MVM_load_edict;
+ prog->init_cmd = MVM_init_cmd;
+ prog->reset_cmd = MVM_reset_cmd;
+ prog->error_cmd = MVM_error_cmd;
+ prog->ExecuteProgram = MVM_ExecuteProgram;
// allocate the mempools
prog->progs_mempool = Mem_AllocPool(M_PROG_FILENAME, 0, NULL);
- PRVM_LoadProgs(M_PROG_FILENAME, m_numrequiredfunc, m_required_func, m_numrequiredfields, m_required_fields, m_numrequiredglobals, m_required_globals);
+ PRVM_Prog_Load(prog, M_PROG_FILENAME, m_numrequiredfunc, m_required_func, m_numrequiredfields, m_required_fields, m_numrequiredglobals, m_required_globals);
// note: OP_STATE is not supported by menu qc, we don't even try to detect
// it here
in_client_mouse = true;
// call the prog init
- PRVM_ExecuteProgram(PRVM_menufunction(m_init),"m_init() required");
-
- PRVM_End;
+ prog->ExecuteProgram(prog, PRVM_menufunction(m_init),"m_init() required");
}
//============================================================================
MR_SetRouting (FALSE);
}
-void Call_MR_ToggleMenu_f(void)
+static void Call_MR_ToggleMenu_f(void)
{
int m;
m = ((Cmd_Argc() < 2) ? -1 : atoi(Cmd_Argv(1)));
#define MENU_H
#define M_PROG_FILENAME "menu.dat"
-#define M_NAME "menu"
enum m_state_e {
m_none,
int surfacenumber;
const rtlight_t *rtlight;
float dist;
+ meshqueue_sortcategory_t category;
}
meshqueue_t;
int trans_sortarraysize;
meshqueue_t **trans_hash = NULL;
meshqueue_t ***trans_hashpointer = NULL;
-extern cvar_t r_transparent_sortarraysize;
-extern cvar_t r_transparent_sortmaxdist;
float mqt_viewplanedist;
float mqt_viewmaxdist;
mqt_viewmaxdist = 0;
}
-void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_MeshQueue_AddTransparent(meshqueue_sortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
{
meshqueue_t *mq;
if (mqt_count >= mqt_total || !mqt_array)
mq->ent = ent;
mq->surfacenumber = surfacenumber;
mq->rtlight = rtlight;
- mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist;
+ mq->category = category;
+ if (r_transparent_useplanardistance.integer)
+ mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist;
+ else
+ mq->dist = VectorDistance(center, r_refdef.view.origin);
mq->next = NULL;
mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist);
}
// check for bad cvars
if (r_transparent_sortarraysize.integer < 1 || r_transparent_sortarraysize.integer > 32768)
Cvar_SetValueQuick(&r_transparent_sortarraysize, bound(1, r_transparent_sortarraysize.integer, 32768));
- if (r_transparent_sortmaxdist.integer < 1 || r_transparent_sortmaxdist.integer > 32768)
- Cvar_SetValueQuick(&r_transparent_sortmaxdist, bound(1, r_transparent_sortmaxdist.integer, 32768));
+ if (r_transparent_sortmindist.integer < 1 || r_transparent_sortmindist.integer >= r_transparent_sortmaxdist.integer)
+ Cvar_SetValueQuick(&r_transparent_sortmindist, 0);
+ if (r_transparent_sortmaxdist.integer < r_transparent_sortmindist.integer || r_transparent_sortmaxdist.integer > 32768)
+ Cvar_SetValueQuick(&r_transparent_sortmaxdist, bound(r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer, 32768));
// update hash array
if (trans_sortarraysize != r_transparent_sortarraysize.integer)
maxhashindex = trans_sortarraysize - 1;
for (i = 0, mqt = mqt_array; i < mqt_count; i++, mqt++)
{
- hashindex = bound(0, (int)(min(mqt->dist, r_transparent_sortmaxdist.integer) * distscale), maxhashindex);
+ switch(mqt->category)
+ {
+ default:
+ case MESHQUEUE_SORT_HUD:
+ hashindex = 0;
+ break;
+ case MESHQUEUE_SORT_DISTANCE:
+ // this could use a reduced range if we need more categories
+ hashindex = bound(0, (int)(bound(0, mqt->dist - r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer) * distscale), maxhashindex);
+ break;
+ case MESHQUEUE_SORT_SKY:
+ hashindex = maxhashindex;
+ break;
+ }
// link to tail of hash chain (to preserve render order)
mqt->next = NULL;
*trans_hashpointer[hashindex] = mqt;
// VorteX: seems this value is hardcoded in other several defines as it's changing makes mess
#define MESHQUEUE_TRANSPARENT_BATCHSIZE 256
+typedef enum meshqueue_sortcategory_e
+{
+ MESHQUEUE_SORT_SKY,
+ MESHQUEUE_SORT_DISTANCE,
+ MESHQUEUE_SORT_HUD,
+}
+meshqueue_sortcategory_t;
+
void R_MeshQueue_BeginScene(void);
-void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
+void R_MeshQueue_AddTransparent(meshqueue_sortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
void R_MeshQueue_RenderTransparent(void);
#endif
float m[12];
const blendweights_t * RESTRICT weights;
- if (!model->surfmesh.num_vertices)
- return;
-
//unsigned long long ts = rdtsc();
bonepose = (float12_t *) Mod_Skeletal_AnimateVertices_AllocBuffers(sizeof(float12_t) * (model->num_bones*2 + model->surfmesh.num_blends));
boneposerelative = bonepose + model->num_bones;
const blendweights_t * RESTRICT weights;
int num_vertices_minus_one;
- if (!model->surfmesh.num_vertices)
- return;
-
num_vertices_minus_one = model->surfmesh.num_vertices - 1;
//unsigned long long ts = rdtsc();
float mod_md3_sin[320];
-static size_t Mod_Skeltal_AnimateVertices_maxbonepose = 0;
-static void *Mod_Skeltal_AnimateVertices_bonepose = NULL;
+static size_t Mod_Skeletal_AnimateVertices_maxbonepose = 0;
+static void *Mod_Skeletal_AnimateVertices_bonepose = NULL;
void Mod_Skeletal_FreeBuffers(void)
{
- if(Mod_Skeltal_AnimateVertices_bonepose)
- Mem_Free(Mod_Skeltal_AnimateVertices_bonepose);
- Mod_Skeltal_AnimateVertices_maxbonepose = 0;
- Mod_Skeltal_AnimateVertices_bonepose = NULL;
+ if(Mod_Skeletal_AnimateVertices_bonepose)
+ Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
+ Mod_Skeletal_AnimateVertices_maxbonepose = 0;
+ Mod_Skeletal_AnimateVertices_bonepose = NULL;
}
void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
{
- if(Mod_Skeltal_AnimateVertices_maxbonepose < nbytes)
+ if(Mod_Skeletal_AnimateVertices_maxbonepose < nbytes)
{
- if(Mod_Skeltal_AnimateVertices_bonepose)
- Mem_Free(Mod_Skeltal_AnimateVertices_bonepose);
- Mod_Skeltal_AnimateVertices_bonepose = Z_Malloc(nbytes);
- Mod_Skeltal_AnimateVertices_maxbonepose = nbytes;
+ if(Mod_Skeletal_AnimateVertices_bonepose)
+ Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
+ Mod_Skeletal_AnimateVertices_bonepose = Z_Malloc(nbytes);
+ Mod_Skeletal_AnimateVertices_maxbonepose = nbytes;
}
- return Mod_Skeltal_AnimateVertices_bonepose;
+ return Mod_Skeletal_AnimateVertices_bonepose;
}
-void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
+static void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
{
+
+ if (!model->surfmesh.num_vertices)
+ return;
+
+ if (!model->num_bones)
+ {
+ if (vertex3f) memcpy(vertex3f, model->surfmesh.data_vertex3f, model->surfmesh.num_vertices*sizeof(float[3]));
+ if (normal3f) memcpy(normal3f, model->surfmesh.data_normal3f, model->surfmesh.num_vertices*sizeof(float[3]));
+ if (svector3f) memcpy(svector3f, model->surfmesh.data_svector3f, model->surfmesh.num_vertices*sizeof(float[3]));
+ if (tvector3f) memcpy(tvector3f, model->surfmesh.data_tvector3f, model->surfmesh.num_vertices*sizeof(float[3]));
+ return;
+ }
+
#ifdef SSE_POSSIBLE
if(r_skeletal_use_sse_defined)
if(r_skeletal_use_sse.integer)
#endif
}
-int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
+static int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
{
int i;
blendweights_t *weights;
return model->num_bones + i;
}
-int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
+static int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
{
int i, total;
float scale;
return Mod_Skeletal_AddBlend(model, &newweights);
}
-void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
+static void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
{
// vertex morph
int i, numblends, blendnum;
}
}
}
-void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
+static void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
{
// vertex morph
int i, numblends, blendnum;
qboolean firstvertex = true;
float dist, yawradius, radius;
float *v;
- float *vertex3f;
- frameblend_t frameblend[MAX_FRAMEBLENDS];
- memset(frameblend, 0, sizeof(frameblend));
- frameblend[0].lerp = 1;
- vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
VectorClear(loadmodel->normalmins);
VectorClear(loadmodel->normalmaxs);
yawradius = 0;
radius = 0;
- for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
+ if (loadmodel->AnimateVertices)
{
- loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
- for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
+ float *vertex3f;
+ frameblend_t frameblend[MAX_FRAMEBLENDS];
+ memset(frameblend, 0, sizeof(frameblend));
+ frameblend[0].lerp = 1;
+ vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
+ for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
+ {
+ loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
+ for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
+ {
+ if (firstvertex)
+ {
+ firstvertex = false;
+ VectorCopy(v, loadmodel->normalmins);
+ VectorCopy(v, loadmodel->normalmaxs);
+ }
+ else
+ {
+ if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
+ if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
+ if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
+ if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
+ if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
+ if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
+ }
+ dist = v[0] * v[0] + v[1] * v[1];
+ if (yawradius < dist)
+ yawradius = dist;
+ dist += v[2] * v[2];
+ if (radius < dist)
+ radius = dist;
+ }
+ }
+ if (vertex3f)
+ Mem_Free(vertex3f);
+ }
+ else
+ {
+ for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
{
if (firstvertex)
{
radius = dist;
}
}
- if (vertex3f)
- Mem_Free(vertex3f);
radius = sqrt(radius);
yawradius = sqrt(yawradius);
loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
int i;
float segmentmins[3], segmentmaxs[3];
msurface_t *surface;
- static int maxvertices = 0;
- static float *vertex3f = NULL;
+ float vertex3fbuf[1024*3];
+ float *vertex3f = vertex3fbuf;
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
- if (maxvertices < model->surfmesh.num_vertices)
- {
- if (vertex3f)
- Z_Free(vertex3f);
- maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
- vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
- }
+ if (model->surfmesh.num_vertices > 1024)
+ vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
segmentmins[0] = min(start[0], end[0]) - 1;
segmentmins[1] = min(start[1], end[1]) - 1;
segmentmins[2] = min(start[2], end[2]) - 1;
model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
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);
+ if (vertex3f != vertex3fbuf)
+ Mem_Free(vertex3f);
}
-static int maxvertices = 0;
-static float *vertex3f = NULL;
-
static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
{
int i;
vec3_t shiftstart, shiftend;
float segmentmins[3], segmentmaxs[3];
msurface_t *surface;
+ float vertex3fbuf[1024*3];
+ float *vertex3f = vertex3fbuf;
colboxbrushf_t thisbrush_start, thisbrush_end;
vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
trace->fraction = 1;
trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
- if (maxvertices < model->surfmesh.num_vertices)
- {
- if (vertex3f)
- Z_Free(vertex3f);
- maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
- vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
- }
+ if (model->surfmesh.num_vertices > 1024)
+ vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
VectorAdd(end, boxmaxs, boxendmaxs);
Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
- if (maxvertices < model->surfmesh.num_vertices)
- {
- if (vertex3f)
- Z_Free(vertex3f);
- maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
- vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
- }
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);
+ if (vertex3f != vertex3fbuf)
+ Mem_Free(vertex3f);
}
static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
texture->currentmaterialflags = texture->basematerialflags;
texture->offsetmapping = OFFSETMAPPING_DEFAULT;
texture->offsetscale = 1;
+ texture->offsetbias = 0;
texture->specularscalemod = 1;
texture->specularpowermod = 1;
texture->surfaceflags = 0;
void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
{
int i;
- static char stripbuf[MAX_QPATH];
+ char stripbuf[MAX_QPATH];
skinfileitem_t *skinfileitem;
if(developer_extra.integer)
Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
float *vertst;
int *vertonseam, *vertremap;
skinfile_t *skinfiles;
+ char vabuf[1024];
datapointer = (unsigned char *)buffer;
pinmodel = (mdl_t *)datapointer;
loadmodel->modeldatatypestring = "MDL";
loadmodel->type = mod_alias;
- loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
}
Mod_MDL_LoadFrames (startframes, numverts, vertremap);
+ loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
Mod_Alias_CalculateBoundingBox();
Mod_Alias_MorphMesh_CompileFrames();
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
Mem_Free(vertst);
Mem_Free(vertremap);
// check for skins that don't exist in the model, but do exist as external images
// (this was added because yummyluv kept pestering me about support for it)
// TODO: support shaders here?
- while ((tempskinframe = R_SkinFrame_LoadExternal(va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
+ while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
{
// expand the arrays to make room
tempskinscenes = loadmodel->skinscenes;
surface->num_firstvertex = 0;
surface->num_vertices = loadmodel->surfmesh.num_vertices;
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
+ loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
if (!loadmodel->surfmesh.isanimated)
{
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
+
+ // because shaders can do somewhat unexpected things, check for unusual features now
+ for (i = 0;i < loadmodel->num_textures;i++)
+ {
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
+ mod->DrawSky = R_Q1BSP_DrawSky;
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ }
}
void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
loadmodel->modeldatatypestring = "MD2";
loadmodel->type = mod_alias;
- loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
Mem_Free(vertremap);
+ loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
Mod_Alias_CalculateBoundingBox();
Mod_Alias_MorphMesh_CompileFrames();
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
surface = loadmodel->data_surfaces;
surface->texture = loadmodel->data_textures;
surface->num_firstvertex = 0;
surface->num_vertices = loadmodel->surfmesh.num_vertices;
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
-
if (!loadmodel->surfmesh.isanimated)
{
Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
+
+ // because shaders can do somewhat unexpected things, check for unusual features now
+ for (i = 0;i < loadmodel->num_textures;i++)
+ {
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
+ mod->DrawSky = R_Q1BSP_DrawSky;
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ }
}
void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
loadmodel->modeldatatypestring = "MD3";
loadmodel->type = mod_alias;
- loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
if (loadmodel->surfmesh.data_element3s)
for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
Mod_Alias_MorphMesh_CompileFrames();
Mod_Alias_CalculateBoundingBox();
Mod_FreeSkinFiles(skinfiles);
Mod_MakeSortedSurfaces(loadmodel);
-
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
- || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
if (!loadmodel->surfmesh.isanimated)
{
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
+
+ // because shaders can do somewhat unexpected things, check for unusual features now
+ for (i = 0;i < loadmodel->num_textures;i++)
+ {
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
+ mod->DrawSky = R_Q1BSP_DrawSky;
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ }
}
void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
return;
}
- loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
meshvertices = pheader->numverts;
meshtriangles = pheader->numtris;
+ loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
-
if (!loadmodel->surfmesh.isanimated)
{
Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
+
+ // because shaders can do somewhat unexpected things, check for unusual features now
+ for (i = 0;i < loadmodel->num_textures;i++)
+ {
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
+ mod->DrawSky = R_Q1BSP_DrawSky;
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ }
}
void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
return;
}
- loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
// do most allocations as one merged chunk
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
-
if (!loadmodel->surfmesh.isanimated)
{
Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
+
+ // because shaders can do somewhat unexpected things, check for unusual features now
+ for (i = 0;i < loadmodel->num_textures;i++)
+ {
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
+ mod->DrawSky = R_Q1BSP_DrawSky;
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ }
}
// no idea why PSK/PSA files contain weird quaternions but they do...
loadmodel->modeldatatypestring = "PSK";
loadmodel->type = mod_alias;
- loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
strlcat(animname, ".psa", sizeof(animname));
animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
- if (animbuffer == NULL)
- Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
+ if (!animbuffer)
+ animbufferend = animbuffer;
numpnts = 0;
pnts = NULL;
Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
}
- if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
+ if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
Host_Error("%s: missing required chunks", loadmodel->name);
- loadmodel->numframes = 0;
- for (index = 0;index < numanims;index++)
- loadmodel->numframes += anims[index].numframes;
-
- if (numanimkeys != numbones * loadmodel->numframes)
- Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
+ if (numanims)
+ {
+ loadmodel->numframes = 0;
+ for (index = 0;index < numanims;index++)
+ loadmodel->numframes += anims[index].numframes;
+ if (numanimkeys != numbones * loadmodel->numframes)
+ Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
+ }
+ else
+ loadmodel->numframes = loadmodel->num_poses = 1;
meshvertices = numvtxw;
meshtriangles = numfaces;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
+ loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
// do most allocations as one merged chunk
size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
}
+ // convert the basepose data
+ if (loadmodel->num_bones)
+ {
+ int boneindex;
+ matrix4x4_t *basebonepose;
+ float *outinvmatrix = loadmodel->data_baseboneposeinverse;
+ matrix4x4_t bonematrix;
+ matrix4x4_t tempbonematrix;
+ basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
+ for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
+ {
+ Matrix4x4_FromOriginQuat(&bonematrix, bones[boneindex].basepose.origin[0], bones[boneindex].basepose.origin[1], bones[boneindex].basepose.origin[2], bones[boneindex].basepose.quat[0], bones[boneindex].basepose.quat[1], bones[boneindex].basepose.quat[2], bones[boneindex].basepose.quat[3]);
+ if (loadmodel->data_bones[boneindex].parent >= 0)
+ {
+ tempbonematrix = bonematrix;
+ Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
+ }
+ basebonepose[boneindex] = bonematrix;
+ Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
+ Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
+ }
+ Mem_Free(basebonepose);
+ }
+
// sort the psk point weights into the vertex weight tables
// (which only accept up to 4 bones per vertex)
for (index = 0;index < numvtxw;index++)
loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
// set up the animscenes based on the anims
- for (index = 0, i = 0;index < numanims;index++)
+ if (numanims)
{
- for (j = 0;j < anims[index].numframes;j++, i++)
+ for (index = 0, i = 0;index < numanims;index++)
+ {
+ for (j = 0;j < anims[index].numframes;j++, i++)
+ {
+ dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
+ loadmodel->animscenes[i].firstframe = i;
+ loadmodel->animscenes[i].framecount = 1;
+ loadmodel->animscenes[i].loop = true;
+ loadmodel->animscenes[i].framerate = anims[index].fps;
+ }
+ }
+ // calculate the scaling value for bone origins so they can be compressed to short
+ biggestorigin = 0;
+ for (index = 0;index < numanimkeys;index++)
{
- dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
- loadmodel->animscenes[i].firstframe = i;
- loadmodel->animscenes[i].framecount = 1;
- loadmodel->animscenes[i].loop = true;
- loadmodel->animscenes[i].framerate = anims[index].fps;
+ pskanimkeys_t *k = animkeys + index;
+ biggestorigin = max(biggestorigin, fabs(k->origin[0]));
+ biggestorigin = max(biggestorigin, fabs(k->origin[1]));
+ biggestorigin = max(biggestorigin, fabs(k->origin[2]));
+ }
+ loadmodel->num_posescale = biggestorigin / 32767.0f;
+ loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+
+ // load the poses from the animkeys
+ for (index = 0;index < numanimkeys;index++)
+ {
+ pskanimkeys_t *k = animkeys + index;
+ float quat[4];
+ Vector4Copy(k->quat, quat);
+ if (quat[3] > 0)
+ Vector4Negate(quat, quat);
+ Vector4Normalize2(quat, quat);
+ // compress poses to the short[6] format for longterm storage
+ loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
+ loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
+ loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
}
}
-
- // calculate the scaling value for bone origins so they can be compressed to short
- biggestorigin = 0;
- for (index = 0;index < numanimkeys;index++)
+ else
{
- pskanimkeys_t *k = animkeys + index;
- biggestorigin = max(biggestorigin, fabs(k->origin[0]));
- biggestorigin = max(biggestorigin, fabs(k->origin[1]));
- biggestorigin = max(biggestorigin, fabs(k->origin[2]));
- }
- loadmodel->num_posescale = biggestorigin / 32767.0f;
- loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+ strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
+ loadmodel->animscenes[0].firstframe = 0;
+ loadmodel->animscenes[0].framecount = 1;
+ loadmodel->animscenes[0].loop = true;
+ loadmodel->animscenes[0].framerate = 10;
- // load the poses from the animkeys
- for (index = 0;index < numanimkeys;index++)
- {
- pskanimkeys_t *k = animkeys + index;
- float quat[4];
- Vector4Copy(k->quat, quat);
- if (quat[3] > 0)
- Vector4Negate(quat, quat);
- Vector4Normalize2(quat, quat);
- // compress poses to the short[6] format for longterm storage
- loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
- loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
- loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
- loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
- loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
- loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
+ // calculate the scaling value for bone origins so they can be compressed to short
+ biggestorigin = 0;
+ for (index = 0;index < numbones;index++)
+ {
+ pskboneinfo_t *p = bones + index;
+ biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
+ biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
+ biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
+ }
+ loadmodel->num_posescale = biggestorigin / 32767.0f;
+ loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+
+ // load the basepose as a frame
+ for (index = 0;index < numbones;index++)
+ {
+ pskboneinfo_t *p = bones + index;
+ float quat[4];
+ Vector4Copy(p->basepose.quat, quat);
+ if (quat[3] > 0)
+ Vector4Negate(quat, quat);
+ Vector4Normalize2(quat, quat);
+ // compress poses to the short[6] format for longterm storage
+ loadmodel->data_poses6s[index*6+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
+ loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
+ loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
+ }
}
+
Mod_FreeSkinFiles(skinfiles);
- Mem_Free(animfilebuffer);
+ if (animfilebuffer)
+ Mem_Free(animfilebuffer);
Mod_MakeSortedSurfaces(loadmodel);
// compute all the mesh information that was not loaded from the file
for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
- Mod_BuildBaseBonePoses();
Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
if (loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
Mod_Alias_CalculateBoundingBox();
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
-
if (!loadmodel->surfmesh.isanimated)
{
Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
+
+ // because shaders can do somewhat unexpected things, check for unusual features now
+ for (i = 0;i < loadmodel->num_textures;i++)
+ {
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
+ mod->DrawSky = R_Q1BSP_DrawSky;
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ }
}
void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
unsigned char *data;
const char *text;
- unsigned char *pbase, *pend;
- iqmheader_t *header;
+ const unsigned char *pbase, *pend;
+ iqmheader_t header;
skinfile_t *skinfiles;
int i, j, k, meshvertices, meshtriangles;
- float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
- unsigned char *vblendindexes = NULL, *vblendweights = NULL;
+ float biggestorigin;
+ const unsigned int *inelements;
+ int *outelements;
+ const int *inneighbors;
+ int *outneighbors;
+ float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
+ // this pointers into the file data are read only through Little* functions so they can be unaligned memory
+ const float *vnormal = NULL;
+ const float *vposition = NULL;
+ const float *vtangent = NULL;
+ const float *vtexcoord = NULL;
+ const float *vcolor4f = NULL;
+ const unsigned char *vblendindexes = NULL;
+ const unsigned char *vblendweights = NULL;
+ const unsigned char *vcolor4ub = NULL;
+ const unsigned short *framedata = NULL;
+ // temporary memory allocations (because the data in the file may be misaligned)
+ iqmanim_t *anims = NULL;
+ iqmbounds_t *bounds = NULL;
iqmjoint1_t *joint1 = NULL;
iqmjoint_t *joint = NULL;
+ iqmmesh_t *meshes = NULL;
iqmpose1_t *pose1 = NULL;
iqmpose_t *pose = NULL;
- iqmanim_t *anim;
- iqmmesh_t *mesh;
- iqmbounds_t *bounds;
- iqmvertexarray_t *va;
- unsigned short *framedata;
- float biggestorigin;
- const int *inelements;
- int *outelements;
- float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
+ iqmvertexarray_t *vas = NULL;
pbase = (unsigned char *)buffer;
pend = (unsigned char *)bufferend;
- header = (iqmheader_t *)buffer;
- if (memcmp(header->id, "INTERQUAKEMODEL", 16))
+
+ if (pbase + sizeof(iqmheader_t) > pend)
+ Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
+
+ // copy struct (otherwise it may be misaligned)
+ // LordHavoc: okay it's definitely not misaligned here, but for consistency...
+ memcpy(&header, pbase, sizeof(iqmheader_t));
+
+ if (memcmp(header.id, "INTERQUAKEMODEL", 16))
Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
- if (LittleLong(header->version) != 1 && LittleLong(header->version) != 2)
+ if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
loadmodel->modeldatatypestring = "IQM";
loadmodel->synctype = ST_RAND;
// byteswap header
- header->version = LittleLong(header->version);
- header->filesize = LittleLong(header->filesize);
- header->flags = LittleLong(header->flags);
- header->num_text = LittleLong(header->num_text);
- header->ofs_text = LittleLong(header->ofs_text);
- header->num_meshes = LittleLong(header->num_meshes);
- header->ofs_meshes = LittleLong(header->ofs_meshes);
- header->num_vertexarrays = LittleLong(header->num_vertexarrays);
- header->num_vertexes = LittleLong(header->num_vertexes);
- header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
- header->num_triangles = LittleLong(header->num_triangles);
- header->ofs_triangles = LittleLong(header->ofs_triangles);
- header->ofs_neighbors = LittleLong(header->ofs_neighbors);
- header->num_joints = LittleLong(header->num_joints);
- header->ofs_joints = LittleLong(header->ofs_joints);
- header->num_poses = LittleLong(header->num_poses);
- header->ofs_poses = LittleLong(header->ofs_poses);
- header->num_anims = LittleLong(header->num_anims);
- header->ofs_anims = LittleLong(header->ofs_anims);
- header->num_frames = LittleLong(header->num_frames);
- header->num_framechannels = LittleLong(header->num_framechannels);
- header->ofs_frames = LittleLong(header->ofs_frames);
- header->ofs_bounds = LittleLong(header->ofs_bounds);
- header->num_comment = LittleLong(header->num_comment);
- header->ofs_comment = LittleLong(header->ofs_comment);
- header->num_extensions = LittleLong(header->num_extensions);
- header->ofs_extensions = LittleLong(header->ofs_extensions);
-
- if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
- {
- Con_Printf("%s has no geometry\n", loadmodel->name);
- return;
+ header.version = LittleLong(header.version);
+ header.filesize = LittleLong(header.filesize);
+ header.flags = LittleLong(header.flags);
+ header.num_text = LittleLong(header.num_text);
+ header.ofs_text = LittleLong(header.ofs_text);
+ header.num_meshes = LittleLong(header.num_meshes);
+ header.ofs_meshes = LittleLong(header.ofs_meshes);
+ header.num_vertexarrays = LittleLong(header.num_vertexarrays);
+ header.num_vertexes = LittleLong(header.num_vertexes);
+ header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
+ header.num_triangles = LittleLong(header.num_triangles);
+ header.ofs_triangles = LittleLong(header.ofs_triangles);
+ header.ofs_neighbors = LittleLong(header.ofs_neighbors);
+ header.num_joints = LittleLong(header.num_joints);
+ header.ofs_joints = LittleLong(header.ofs_joints);
+ header.num_poses = LittleLong(header.num_poses);
+ header.ofs_poses = LittleLong(header.ofs_poses);
+ header.num_anims = LittleLong(header.num_anims);
+ header.ofs_anims = LittleLong(header.ofs_anims);
+ header.num_frames = LittleLong(header.num_frames);
+ header.num_framechannels = LittleLong(header.num_framechannels);
+ header.ofs_frames = LittleLong(header.ofs_frames);
+ header.ofs_bounds = LittleLong(header.ofs_bounds);
+ header.num_comment = LittleLong(header.num_comment);
+ header.ofs_comment = LittleLong(header.ofs_comment);
+ header.num_extensions = LittleLong(header.num_extensions);
+ header.ofs_extensions = LittleLong(header.ofs_extensions);
+
+ if (header.version == 1)
+ {
+ if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
+ pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
+ {
+ Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
+ return;
+ }
}
- if (header->num_frames < 1 || header->num_anims < 1)
+ else
{
- Con_Printf("%s has no animations\n", loadmodel->name);
- return;
+ if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
+ pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
+ {
+ Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
+ return;
+ }
}
-
- if (pbase + header->ofs_text + header->num_text > pend ||
- pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
- pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
- pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
- (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
- pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
- pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
- pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
- pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
- (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
- pbase + header->ofs_comment + header->num_comment > pend)
+ if (pbase + header.ofs_text + header.num_text > pend ||
+ pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
+ pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
+ pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
+ (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
+ pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
+ pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
+ (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
+ pbase + header.ofs_comment + header.num_comment > pend)
{
Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
return;
}
- va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
- for (i = 0;i < (int)header->num_vertexarrays;i++)
+ // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
+ if (header.num_vertexarrays)
+ vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
+ if (header.num_anims)
+ anims = (iqmanim_t *)(pbase + header.ofs_anims);
+ if (header.ofs_bounds)
+ bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
+ if (header.num_meshes)
+ meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
+
+ for (i = 0;i < (int)header.num_vertexarrays;i++)
{
+ iqmvertexarray_t va;
size_t vsize;
- va[i].type = LittleLong(va[i].type);
- va[i].flags = LittleLong(va[i].flags);
- va[i].format = LittleLong(va[i].format);
- va[i].size = LittleLong(va[i].size);
- va[i].offset = LittleLong(va[i].offset);
- vsize = header->num_vertexes*va[i].size;
- switch (va[i].format)
+ va.type = LittleLong(vas[i].type);
+ va.flags = LittleLong(vas[i].flags);
+ va.format = LittleLong(vas[i].format);
+ va.size = LittleLong(vas[i].size);
+ va.offset = LittleLong(vas[i].offset);
+ vsize = header.num_vertexes*va.size;
+ switch (va.format)
{
case IQM_FLOAT: vsize *= sizeof(float); break;
case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
default: continue;
}
- if (pbase + va[i].offset + vsize > pend)
- continue;
- switch (va[i].type)
+ if (pbase + va.offset + vsize > pend)
+ continue;
+ // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
+ switch (va.type)
{
case IQM_POSITION:
- if (va[i].format == IQM_FLOAT && va[i].size == 3)
- vposition = (float *)(pbase + va[i].offset);
+ if (va.format == IQM_FLOAT && va.size == 3)
+ vposition = (const float *)(pbase + va.offset);
break;
case IQM_TEXCOORD:
- if (va[i].format == IQM_FLOAT && va[i].size == 2)
- vtexcoord = (float *)(pbase + va[i].offset);
+ if (va.format == IQM_FLOAT && va.size == 2)
+ vtexcoord = (const float *)(pbase + va.offset);
break;
case IQM_NORMAL:
- if (va[i].format == IQM_FLOAT && va[i].size == 3)
- vnormal = (float *)(pbase + va[i].offset);
+ if (va.format == IQM_FLOAT && va.size == 3)
+ vnormal = (const float *)(pbase + va.offset);
break;
case IQM_TANGENT:
- if (va[i].format == IQM_FLOAT && va[i].size == 4)
- vtangent = (float *)(pbase + va[i].offset);
+ if (va.format == IQM_FLOAT && va.size == 4)
+ vtangent = (const float *)(pbase + va.offset);
break;
case IQM_BLENDINDEXES:
- if (va[i].format == IQM_UBYTE && va[i].size == 4)
- vblendindexes = (unsigned char *)(pbase + va[i].offset);
+ if (va.format == IQM_UBYTE && va.size == 4)
+ vblendindexes = (const unsigned char *)(pbase + va.offset);
break;
case IQM_BLENDWEIGHTS:
- if (va[i].format == IQM_UBYTE && va[i].size == 4)
- vblendweights = (unsigned char *)(pbase + va[i].offset);
+ if (va.format == IQM_UBYTE && va.size == 4)
+ vblendweights = (const unsigned char *)(pbase + va.offset);
+ break;
+ case IQM_COLOR:
+ if (va.format == IQM_FLOAT && va.size == 4)
+ vcolor4f = (const float *)(pbase + va.offset);
+ if (va.format == IQM_UBYTE && va.size == 4)
+ vcolor4ub = (const unsigned char *)(pbase + va.offset);
break;
}
}
- if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
+ if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
{
Con_Printf("%s is missing vertex array data\n", loadmodel->name);
return;
}
- text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
+ text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
- loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
loadmodel->DrawSky = NULL;
loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Q1BSP_Draw;
if (loadmodel->numskins < 1)
loadmodel->numskins = 1;
- loadmodel->numframes = header->num_anims;
- loadmodel->num_bones = header->num_joints;
- loadmodel->num_poses = header->num_frames;
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
+ loadmodel->numframes = max(header.num_anims, 1);
+ loadmodel->num_bones = header.num_joints;
+ loadmodel->num_poses = max(header.num_frames, 1);
+ loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
- meshvertices = header->num_vertexes;
- meshtriangles = header->num_triangles;
+ meshvertices = header.num_vertexes;
+ meshtriangles = header.num_triangles;
// do most allocations as one merged chunk
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+ if (vcolor4f || vcolor4ub)
+ {
+ loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
+ }
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
- loadmodel->surfmesh.num_blends = 0;
- loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
+ if (vblendindexes && vblendweights)
+ {
+ loadmodel->surfmesh.num_blends = 0;
+ loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
+ }
if (meshvertices <= 65536)
{
loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
}
loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
- loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
+ if (vblendindexes && vblendweights)
+ loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
for (i = 0;i < loadmodel->numskins;i++)
{
}
// load the bone info
- if (header->version == 1)
+ if (header.version == 1)
{
- joint1 = (iqmjoint1_t *) (pbase + header->ofs_joints);
+ iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
+ if (loadmodel->num_bones)
+ joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
for (i = 0;i < loadmodel->num_bones;i++)
{
matrix4x4_t relbase, relinvbase, pinvbase, invbase;
- joint1[i].name = LittleLong(joint1[i].name);
- joint1[i].parent = LittleLong(joint1[i].parent);
+ joint1[i].name = LittleLong(injoint1[i].name);
+ joint1[i].parent = LittleLong(injoint1[i].parent);
for (j = 0;j < 3;j++)
{
- joint1[i].origin[j] = LittleFloat(joint1[i].origin[j]);
- joint1[i].rotation[j] = LittleFloat(joint1[i].rotation[j]);
- joint1[i].scale[j] = LittleFloat(joint1[i].scale[j]);
+ joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
+ joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
+ joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
}
strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
loadmodel->data_bones[i].parent = joint1[i].parent;
}
else
{
- joint = (iqmjoint_t *) (pbase + header->ofs_joints);
+ iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
+ if (header.num_joints)
+ joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
for (i = 0;i < loadmodel->num_bones;i++)
{
matrix4x4_t relbase, relinvbase, pinvbase, invbase;
- joint[i].name = LittleLong(joint[i].name);
- joint[i].parent = LittleLong(joint[i].parent);
+ joint[i].name = LittleLong(injoint[i].name);
+ joint[i].parent = LittleLong(injoint[i].parent);
for (j = 0;j < 3;j++)
{
- joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
- joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
- joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
+ joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
+ joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
+ joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
}
- joint[i].rotation[3] = LittleFloat(joint[i].rotation[3]);
+ joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
loadmodel->data_bones[i].parent = joint[i].parent;
if (loadmodel->data_bones[i].parent >= i)
Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
- if (joint[i].rotation[3] > 0)
- Vector4Negate(joint[i].rotation, joint[i].rotation);
- Vector4Normalize2(joint[i].rotation, joint[i].rotation);
+ if (joint[i].rotation[3] > 0)
+ Vector4Negate(joint[i].rotation, joint[i].rotation);
+ Vector4Normalize2(joint[i].rotation, joint[i].rotation);
Matrix4x4_FromDoom3Joint(&relbase, joint[i].origin[0], joint[i].origin[1], joint[i].origin[2], joint[i].rotation[0], joint[i].rotation[1], joint[i].rotation[2]);
Matrix4x4_Invert_Simple(&relinvbase, &relbase);
if (loadmodel->data_bones[i].parent >= 0)
}
// set up the animscenes based on the anims
- anim = (iqmanim_t *) (pbase + header->ofs_anims);
- for (i = 0;i < (int)header->num_anims;i++)
- {
- anim[i].name = LittleLong(anim[i].name);
- anim[i].first_frame = LittleLong(anim[i].first_frame);
- anim[i].num_frames = LittleLong(anim[i].num_frames);
- anim[i].framerate = LittleFloat(anim[i].framerate);
- anim[i].flags = LittleLong(anim[i].flags);
- strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
- loadmodel->animscenes[i].firstframe = anim[i].first_frame;
- loadmodel->animscenes[i].framecount = anim[i].num_frames;
- loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
- loadmodel->animscenes[i].framerate = anim[i].framerate;
+ for (i = 0;i < (int)header.num_anims;i++)
+ {
+ iqmanim_t anim;
+ anim.name = LittleLong(anims[i].name);
+ anim.first_frame = LittleLong(anims[i].first_frame);
+ anim.num_frames = LittleLong(anims[i].num_frames);
+ anim.framerate = LittleFloat(anims[i].framerate);
+ anim.flags = LittleLong(anims[i].flags);
+ strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
+ loadmodel->animscenes[i].firstframe = anim.first_frame;
+ loadmodel->animscenes[i].framecount = anim.num_frames;
+ loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
+ loadmodel->animscenes[i].framerate = anim.framerate;
}
-
+ if (header.num_anims <= 0)
+ {
+ strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
+ loadmodel->animscenes[0].firstframe = 0;
+ loadmodel->animscenes[0].framecount = 1;
+ loadmodel->animscenes[0].loop = true;
+ loadmodel->animscenes[0].framerate = 10;
+ }
+
+ loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+ loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
+
biggestorigin = 0;
- if (header->version == 1)
+ if (header.version == 1)
{
- pose1 = (iqmpose1_t *) (pbase + header->ofs_poses);
- for (i = 0;i < (int)header->num_poses;i++)
+ iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
+ if (header.num_poses)
+ pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
+ for (i = 0;i < (int)header.num_poses;i++)
{
float f;
- pose1[i].parent = LittleLong(pose1[i].parent);
- pose1[i].channelmask = LittleLong(pose1[i].channelmask);
+ pose1[i].parent = LittleLong(inpose1[i].parent);
+ pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
for (j = 0;j < 9;j++)
{
- pose1[i].channeloffset[j] = LittleFloat(pose1[i].channeloffset[j]);
- pose1[i].channelscale[j] = LittleFloat(pose1[i].channelscale[j]);
+ pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
+ pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
}
f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
}
+ if (header.num_frames <= 0)
+ {
+ for (i = 0;i < loadmodel->num_bones;i++)
+ {
+ float f;
+ f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
+ f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
+ f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
+ }
+ }
}
else
{
- pose = (iqmpose_t *) (pbase + header->ofs_poses);
- for (i = 0;i < (int)header->num_poses;i++)
+ iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
+ if (header.num_poses)
+ pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
+ for (i = 0;i < (int)header.num_poses;i++)
{
float f;
- pose[i].parent = LittleLong(pose[i].parent);
- pose[i].channelmask = LittleLong(pose[i].channelmask);
+ pose[i].parent = LittleLong(inpose[i].parent);
+ pose[i].channelmask = LittleLong(inpose[i].channelmask);
for (j = 0;j < 10;j++)
{
- pose[i].channeloffset[j] = LittleFloat(pose[i].channeloffset[j]);
- pose[i].channelscale[j] = LittleFloat(pose[i].channelscale[j]);
+ pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
+ pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
}
f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
}
+ if (header.num_frames <= 0)
+ {
+ for (i = 0;i < loadmodel->num_bones;i++)
+ {
+ float f;
+ f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
+ f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
+ f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
+ }
+ }
}
loadmodel->num_posescale = biggestorigin / 32767.0f;
loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
// load the pose data
- framedata = (unsigned short *) (pbase + header->ofs_frames);
- if (header->version == 1)
+ // this unaligned memory access is safe (LittleShort reads as bytes)
+ framedata = (const unsigned short *)(pbase + header.ofs_frames);
+ if (header.version == 1)
{
- for (i = 0, k = 0;i < (int)header->num_frames;i++)
+ for (i = 0, k = 0;i < (int)header.num_frames;i++)
{
- for (j = 0;j < (int)header->num_poses;j++, k++)
+ for (j = 0;j < (int)header.num_poses;j++, k++)
{
loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
if(pose1[j].channelmask&256) framedata++;
}
}
+ if (header.num_frames <= 0)
+ {
+ for (i = 0;i < loadmodel->num_bones;i++)
+ {
+ loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
+ loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
+ loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
+ loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
+ loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
+ loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
+ }
+ }
}
else
{
- for (i = 0, k = 0;i < (int)header->num_frames;i++)
+ for (i = 0, k = 0;i < (int)header.num_frames;i++)
{
- for (j = 0;j < (int)header->num_poses;j++, k++)
+ for (j = 0;j < (int)header.num_poses;j++, k++)
{
float rot[4];
loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
if(pose[j].channelmask&512) framedata++;
}
}
+ if (header.num_frames <= 0)
+ {
+ for (i = 0;i < loadmodel->num_bones;i++)
+ {
+ loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
+ loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
+ loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
+ loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
+ loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
+ loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
+ }
+ }
}
// load bounding box data
- if (header->ofs_bounds)
+ if (header.ofs_bounds)
{
float xyradius = 0, radius = 0;
- bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
VectorClear(loadmodel->normalmins);
VectorClear(loadmodel->normalmaxs);
- for (i = 0; i < (int)header->num_frames;i++)
- {
- bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
- bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
- bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
- bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
- bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
- bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
- bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
- bounds[i].radius = LittleFloat(bounds[i].radius);
+ for (i = 0; i < (int)header.num_frames;i++)
+ {
+ iqmbounds_t bound;
+ bound.mins[0] = LittleFloat(bounds[i].mins[0]);
+ bound.mins[1] = LittleFloat(bounds[i].mins[1]);
+ bound.mins[2] = LittleFloat(bounds[i].mins[2]);
+ bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
+ bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
+ bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
+ bound.xyradius = LittleFloat(bounds[i].xyradius);
+ bound.radius = LittleFloat(bounds[i].radius);
if (!i)
{
- VectorCopy(bounds[i].mins, loadmodel->normalmins);
- VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
+ VectorCopy(bound.mins, loadmodel->normalmins);
+ VectorCopy(bound.maxs, loadmodel->normalmaxs);
}
else
{
- if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
- if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
- if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
- if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
- if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
- if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
+ if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
+ if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
+ if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
+ if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
+ if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
+ if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
}
- if (bounds[i].xyradius > xyradius)
- xyradius = bounds[i].xyradius;
- if (bounds[i].radius > radius)
- radius = bounds[i].radius;
+ if (bound.xyradius > xyradius)
+ xyradius = bound.xyradius;
+ if (bound.radius > radius)
+ radius = bound.radius;
}
loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
}
// load triangle data
- inelements = (const int *) (pbase + header->ofs_triangles);
+ // this unaligned memory access is safe (LittleLong reads as bytes)
+ inelements = (const unsigned int *)(pbase + header.ofs_triangles);
outelements = loadmodel->surfmesh.data_element3i;
- for (i = 0;i < (int)header->num_triangles;i++)
+ for (i = 0;i < (int)header.num_triangles;i++)
{
- outelements[0] = LittleLong(inelements[0]);
+ outelements[0] = LittleLong(inelements[0]);
outelements[1] = LittleLong(inelements[1]);
outelements[2] = LittleLong(inelements[2]);
outelements += 3;
inelements += 3;
}
- Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
+ Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
- if (header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
+ if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
{
- inelements = (const int *) (pbase + header->ofs_neighbors);
- outelements = loadmodel->surfmesh.data_neighbor3i;
- for (i = 0;i < (int)header->num_triangles;i++)
+ // this unaligned memory access is safe (LittleLong reads as bytes)
+ inneighbors = (const int *)(pbase + header.ofs_neighbors);
+ outneighbors = loadmodel->surfmesh.data_neighbor3i;
+ for (i = 0;i < (int)header.num_triangles;i++)
{
- outelements[0] = LittleLong(inelements[0]);
- outelements[1] = LittleLong(inelements[1]);
- outelements[2] = LittleLong(inelements[2]);
- outelements += 3;
- inelements += 3;
+ outneighbors[0] = LittleLong(inneighbors[0]);
+ outneighbors[1] = LittleLong(inneighbors[1]);
+ outneighbors[2] = LittleLong(inneighbors[2]);
+ outneighbors += 3;
+ inneighbors += 3;
}
}
// load vertex data
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
outvertex = loadmodel->surfmesh.data_vertex3f;
- for (i = 0;i < (int)header->num_vertexes;i++)
+ for (i = 0;i < (int)header.num_vertexes;i++)
{
outvertex[0] = LittleFloat(vposition[0]);
outvertex[1] = LittleFloat(vposition[1]);
}
outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
- for (i = 0;i < (int)header->num_vertexes;i++)
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
+ for (i = 0;i < (int)header.num_vertexes;i++)
{
outtexcoord[0] = LittleFloat(vtexcoord[0]);
outtexcoord[1] = LittleFloat(vtexcoord[1]);
outtexcoord += 2;
}
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
if(vnormal)
{
outnormal = loadmodel->surfmesh.data_normal3f;
- for (i = 0;i < (int)header->num_vertexes;i++)
+ for (i = 0;i < (int)header.num_vertexes;i++)
{
outnormal[0] = LittleFloat(vnormal[0]);
outnormal[1] = LittleFloat(vnormal[1]);
}
}
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
if(vnormal && vtangent)
{
outnormal = loadmodel->surfmesh.data_normal3f;
outsvector = loadmodel->surfmesh.data_svector3f;
outtvector = loadmodel->surfmesh.data_tvector3f;
- for (i = 0;i < (int)header->num_vertexes;i++)
+ for (i = 0;i < (int)header.num_vertexes;i++)
{
outsvector[0] = LittleFloat(vtangent[0]);
outsvector[1] = LittleFloat(vtangent[1]);
}
}
- for (i = 0; i < (int)header->num_vertexes;i++)
+ // this unaligned memory access is safe (all bytes)
+ if (vblendindexes && vblendweights)
+ {
+ for (i = 0; i < (int)header.num_vertexes;i++)
+ {
+ blendweights_t weights;
+ memcpy(weights.index, vblendindexes + i*4, 4);
+ memcpy(weights.influence, vblendweights + i*4, 4);
+ loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
+ }
+ }
+
+ if (vcolor4f)
+ {
+ outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
+ // this unaligned memory access is safe (LittleFloat reads as bytes)
+ for (i = 0;i < (int)header.num_vertexes;i++)
+ {
+ outcolor[0] = LittleFloat(vcolor4f[0]);
+ outcolor[1] = LittleFloat(vcolor4f[1]);
+ outcolor[2] = LittleFloat(vcolor4f[2]);
+ outcolor[3] = LittleFloat(vcolor4f[3]);
+ vcolor4f += 4;
+ outcolor += 4;
+ }
+ }
+ else if (vcolor4ub)
{
- blendweights_t weights;
- memcpy(weights.index, vblendindexes + i*4, 4);
- memcpy(weights.influence, vblendweights + i*4, 4);
- loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
+ outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
+ // this unaligned memory access is safe (all bytes)
+ for (i = 0;i < (int)header.num_vertexes;i++)
+ {
+ outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
+ outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
+ outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
+ outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
+ vcolor4ub += 4;
+ outcolor += 4;
+ }
}
// load meshes
- mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
- for (i = 0;i < (int)header->num_meshes;i++)
+ for (i = 0;i < (int)header.num_meshes;i++)
{
+ iqmmesh_t mesh;
msurface_t *surface;
- mesh[i].name = LittleLong(mesh[i].name);
- mesh[i].material = LittleLong(mesh[i].material);
- mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
- mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
- mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
- mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
+ mesh.name = LittleLong(meshes[i].name);
+ mesh.material = LittleLong(meshes[i].material);
+ mesh.first_vertex = LittleLong(meshes[i].first_vertex);
+ mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
+ mesh.first_triangle = LittleLong(meshes[i].first_triangle);
+ mesh.num_triangles = LittleLong(meshes[i].num_triangles);
loadmodel->sortedmodelsurfaces[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
- surface->num_firsttriangle = mesh[i].first_triangle;
- surface->num_triangles = mesh[i].num_triangles;
- surface->num_firstvertex = mesh[i].first_vertex;
- surface->num_vertices = mesh[i].num_vertexes;
+ surface->num_firsttriangle = mesh.first_triangle;
+ surface->num_triangles = mesh.num_triangles;
+ surface->num_firstvertex = mesh.first_vertex;
+ surface->num_vertices = mesh.num_vertexes;
- Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
}
Mod_FreeSkinFiles(skinfiles);
Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
if (!vnormal || !vtangent)
Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
- if (!header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
+ if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
- if (!header->ofs_bounds)
+ if (!header.ofs_bounds)
Mod_Alias_CalculateBoundingBox();
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
-
- if (!loadmodel->surfmesh.isanimated)
+ if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
{
Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
-}
-
+ if (joint ) Mem_Free(joint );joint = NULL;
+ if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
+ if (pose ) Mem_Free(pose );pose = NULL;
+ if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
+
+ // because shaders can do somewhat unexpected things, check for unusual features now
+ for (i = 0;i < loadmodel->num_textures;i++)
+ {
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
+ mod->DrawSky = R_Q1BSP_DrawSky;
+ if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ }
+}
cvar_t mod_q3bsp_lightmapmergepower = {CVAR_SAVE, "mod_q3bsp_lightmapmergepower", "4", "merges the quake3 128x128 lightmap textures into larger lightmap group textures to speed up rendering, 1 = 256x256, 2 = 512x512, 3 = 1024x1024, 4 = 2048x2048, 5 = 4096x4096, ..."};
cvar_t mod_q3bsp_nolightmaps = {CVAR_SAVE, "mod_q3bsp_nolightmaps", "0", "do not load lightmaps in Q3BSP maps (to save video RAM, but be warned: it looks ugly)"};
cvar_t mod_q3bsp_tracelineofsight_brushes = {0, "mod_q3bsp_tracelineofsight_brushes", "0", "enables culling of entities behind detail brushes, curves, etc"};
+cvar_t mod_q3bsp_sRGBlightmaps = {0, "mod_q3bsp_sRGBlightmaps", "0", "treat lightmaps from Q3 maps as sRGB when vid_sRGB is active"};
cvar_t mod_q3shader_default_offsetmapping = {CVAR_SAVE, "mod_q3shader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are using q3 shader files"};
+cvar_t mod_q3shader_default_offsetmapping_scale = {CVAR_SAVE, "mod_q3shader_default_offsetmapping_scale", "1", "default scale used for offsetmapping"};
+cvar_t mod_q3shader_default_offsetmapping_bias = {CVAR_SAVE, "mod_q3shader_default_offsetmapping_bias", "0", "default bias used for offsetmapping"};
cvar_t mod_q3shader_default_polygonfactor = {0, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};
cvar_t mod_q3shader_default_polygonoffset = {0, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};
-
+cvar_t mod_q3shader_force_addalpha = {0, "mod_q3shader_force_addalpha", "0", "treat GL_ONE GL_ONE (or add) blendfunc as GL_SRC_ALPHA GL_ONE for compatibility with older DarkPlaces releases"};
cvar_t mod_q1bsp_polygoncollisions = {0, "mod_q1bsp_polygoncollisions", "0", "disables use of precomputed cliphulls and instead collides with polygons (uses Bounding Interval Hierarchy optimizations)"};
cvar_t mod_collision_bih = {0, "mod_collision_bih", "1", "enables use of generated Bounding Interval Hierarchy tree instead of compiled bsp tree in collision code"};
cvar_t mod_recalculatenodeboxes = {0, "mod_recalculatenodeboxes", "1", "enables use of generated node bounding boxes based on BSP tree portal reconstruction, rather than the node boxes supplied by the map compiler"};
Cvar_RegisterVariable(&mod_q3bsp_debugtracebrush);
Cvar_RegisterVariable(&mod_q3bsp_lightmapmergepower);
Cvar_RegisterVariable(&mod_q3bsp_nolightmaps);
+ Cvar_RegisterVariable(&mod_q3bsp_sRGBlightmaps);
Cvar_RegisterVariable(&mod_q3bsp_tracelineofsight_brushes);
Cvar_RegisterVariable(&mod_q3shader_default_offsetmapping);
+ Cvar_RegisterVariable(&mod_q3shader_default_offsetmapping_scale);
+ Cvar_RegisterVariable(&mod_q3shader_default_offsetmapping_bias);
Cvar_RegisterVariable(&mod_q3shader_default_polygonfactor);
Cvar_RegisterVariable(&mod_q3shader_default_polygonoffset);
+ Cvar_RegisterVariable(&mod_q3shader_force_addalpha);
Cvar_RegisterVariable(&mod_q1bsp_polygoncollisions);
Cvar_RegisterVariable(&mod_collision_bih);
Cvar_RegisterVariable(&mod_recalculatenodeboxes);
+ // these games were made for older DP engines and are no longer
+ // maintained; use this hack to show their textures properly
+ if(gamemode == GAME_NEXUIZ)
+ Cvar_SetQuick(&mod_q3shader_force_addalpha, "1");
+
memset(&mod_q1bsp_texture_solid, 0, sizeof(mod_q1bsp_texture_solid));
strlcpy(mod_q1bsp_texture_solid.name, "solid" , sizeof(mod_q1bsp_texture_solid.name));
mod_q1bsp_texture_solid.surfaceflags = 0;
}
}
-void Mod_Q1BSP_LightPoint(dp_model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
+static void Mod_Q1BSP_LightPoint(dp_model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
{
// pretend lighting is coming down from above (due to lack of a lightgrid to know primary lighting direction)
VectorSet(diffusenormal, 0, 0, 1);
A sky texture is 256*128, with the right side being a masked overlay
==============
*/
-void R_Q1BSP_LoadSplitSky (unsigned char *src, int width, int height, int bytesperpixel)
+static void R_Q1BSP_LoadSplitSky (unsigned char *src, int width, int height, int bytesperpixel)
{
int x, y;
int w = width/2;
const char *s;
char mapname[MAX_QPATH], name[MAX_QPATH];
unsigned char zeroopaque[4], zerotrans[4];
+ char vabuf[1024];
Vector4Set(zeroopaque, 0, 0, 0, 255);
Vector4Set(zerotrans, 0, 0, 0, 128);
tx->r_water_wateralpha = 1;
tx->offsetmapping = OFFSETMAPPING_DEFAULT;
tx->offsetscale = 1;
+ tx->offsetbias = 0;
tx->specularscalemod = 1;
tx->specularpowermod = 1;
}
{
tx->supercontents = mod_q1bsp_texture_sky.supercontents;
tx->surfaceflags = mod_q1bsp_texture_sky.surfaceflags;
+ tx->supercontents |= SUPERCONTENTS_SOLID; // for the surface traceline we need to hit this surface as a solid...
}
else
{
// LordHavoc: HL sky textures are entirely different than quake
if (!loadmodel->brush.ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == mtheight * 2)
{
- data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s/%s", mapname, tx->name), false, false, false, NULL);
+ data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), false, false, false, NULL);
if (!data)
- data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), false, false, false, NULL);
+ data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s", tx->name), false, false, false, NULL);
if (data && image_width == image_height * 2)
{
R_Q1BSP_LoadSplitSky(data, image_width, image_height, 4);
}
else
{
- skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
+ skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
if (!skinframe)
- skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
+ skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
if (skinframe)
tx->offsetmapping = OFFSETMAPPING_DEFAULT; // allow offsetmapping on external textures without a q3 shader
if (!skinframe)
int i, j, k;
if (!data)
return;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
if (com_token[0] != '{')
return; // error
while (1)
{
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
if (com_token[0] == '}')
break; // end of worldspawn
strlcpy(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
dpsnprintf(value, sizeof(value), "%s", com_token);
if (!strcmp("wad", key)) // for HalfLife maps
// The following two functions should be removed and MSG_* or SZ_* function sets adjusted so they
// can be used for this
// REMOVEME
-int SB_ReadInt (unsigned char **buffer)
+static int SB_ReadInt (unsigned char **buffer)
{
int i;
i = ((*buffer)[0]) + 256*((*buffer)[1]) + 65536*((*buffer)[2]) + 16777216*((*buffer)[3]);
}
// REMOVEME
-float SB_ReadFloat (unsigned char **buffer)
+static float SB_ReadFloat (unsigned char **buffer)
{
union
{
int i, j, count, surfacenum, planenum, smax, tmax, ssize, tsize, firstedge, numedges, totalverts, totaltris, lightmapnumber, lightmapsize, totallightmapsamples;
float texmins[2], texmaxs[2], val;
rtexture_t *lightmaptexture, *deluxemaptexture;
+ char vabuf[1024];
in = (dface_t *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
loadmodel->brushq3.num_mergedlightmaps = lightmapnumber + 1;
loadmodel->brushq3.data_lightmaps = (rtexture_t **)Mem_Realloc(loadmodel->mempool, loadmodel->brushq3.data_lightmaps, loadmodel->brushq3.num_mergedlightmaps * sizeof(loadmodel->brushq3.data_lightmaps[0]));
loadmodel->brushq3.data_deluxemaps = (rtexture_t **)Mem_Realloc(loadmodel->mempool, loadmodel->brushq3.data_deluxemaps, loadmodel->brushq3.num_mergedlightmaps * sizeof(loadmodel->brushq3.data_deluxemaps[0]));
- loadmodel->brushq3.data_lightmaps[lightmapnumber] = lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
+ loadmodel->brushq3.data_lightmaps[lightmapnumber] = lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "lightmap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
if (loadmodel->brushq1.nmaplightdata)
- loadmodel->brushq3.data_deluxemaps[lightmapnumber] = deluxemaptexture = R_LoadTexture2D(loadmodel->texturepool, va("deluxemap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
+ loadmodel->brushq3.data_deluxemaps[lightmapnumber] = deluxemaptexture = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "deluxemap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
lightmapnumber++;
Mod_AllocLightmap_Reset(&allocState);
Mod_AllocLightmap_Block(&allocState, ssize, tsize, &lightmapx, &lightmapy);
}
}
-qboolean Mod_Q1BSP_CheckWaterAlphaSupport(void)
+static qboolean Mod_Q1BSP_CheckWaterAlphaSupport(void)
{
int i, j;
mleaf_t *leaf;
if (!maptext)
return;
text = maptext;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
submodel = 0;
for (;;)
{
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break;
if (com_token[0] != '{')
return; // error
brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t));
for (;;)
{
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
if (com_token[0] == '}')
break; // end of entity
}
for (;;)
{
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
return; // error
if (com_token[0] == '}')
break; // end of brush
// FIXME: support hl .map format
for (pointnum = 0;pointnum < 3;pointnum++)
{
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
for (componentnum = 0;componentnum < 3;componentnum++)
{
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
point[pointnum][componentnum] = atof(com_token);
}
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
}
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
strlcpy(facetexture, com_token, sizeof(facetexture));
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
//scroll_s = atof(com_token);
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
//scroll_t = atof(com_token);
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
//rotate = atof(com_token);
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
//scale_s = atof(com_token);
- COM_ParseToken_Simple(&data, false, false);
+ COM_ParseToken_Simple(&data, false, false, true);
//scale_t = atof(com_token);
TriangleNormal(point[0], point[1], point[2], planenormal);
VectorNormalizeDouble(planenormal);
*/
}
-void static Mod_Q2BSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
+static void Mod_Q2BSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i;
q2dheader_t *header;
// some Q3 maps override the lightgrid_cellsize with a worldspawn key
// VorteX: q3map2 FS-R generates tangentspace deluxemaps for q3bsp and sets 'deluxeMaps' key
loadmodel->brushq3.deluxemapping = false;
- if (data && COM_ParseToken_Simple(&data, false, false) && com_token[0] == '{')
+ if (data && COM_ParseToken_Simple(&data, false, false, true) && com_token[0] == '{')
{
while (1)
{
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break; // error
if (com_token[0] == '}')
break; // end of worldspawn
strlcpy(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break; // error
strlcpy(value, com_token, sizeof(value));
if (!strcasecmp("gridsize", key)) // this one is case insensitive to 100% match q3map2
loadmodel->brushq3.data_texcoordlightmap2f[i * 2 + 0] = LittleFloat(in->lightmap2f[0]);
loadmodel->brushq3.data_texcoordlightmap2f[i * 2 + 1] = LittleFloat(in->lightmap2f[1]);
// svector/tvector are calculated later in face loading
- loadmodel->brushq3.data_color4f[i * 4 + 0] = in->color4ub[0] * (1.0f / 255.0f);
- loadmodel->brushq3.data_color4f[i * 4 + 1] = in->color4ub[1] * (1.0f / 255.0f);
- loadmodel->brushq3.data_color4f[i * 4 + 2] = in->color4ub[2] * (1.0f / 255.0f);
+ if(mod_q3bsp_sRGBlightmaps.integer)
+ {
+ // if lightmaps are sRGB, vertex colors are sRGB too, so we need to linearize them
+ // note: when this is in use, lightmap color 128 is no longer neutral, but "sRGB half power" is
+ // working like this may be odd, but matches q3map2 -gamma 2.2
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ {
+ // actually we do: Image_sRGBFloatFromLinear_Lightmap(Image_LinearFloatFromsRGBFloat(x))
+ // neutral point is at Image_sRGBFloatFromLinearFloat(0.5)
+ // so we need to map Image_sRGBFloatFromLinearFloat(0.5) to 0.5
+ // factor is 0.5 / Image_sRGBFloatFromLinearFloat(0.5)
+ loadmodel->brushq3.data_color4f[i * 4 + 0] = in->color4ub[0] * (1.0f / 255.0f) * 0.679942f; // fixes neutral level
+ loadmodel->brushq3.data_color4f[i * 4 + 1] = in->color4ub[1] * (1.0f / 255.0f) * 0.679942f; // fixes neutral level
+ loadmodel->brushq3.data_color4f[i * 4 + 2] = in->color4ub[2] * (1.0f / 255.0f) * 0.679942f; // fixes neutral level
+ }
+ else
+ {
+ loadmodel->brushq3.data_color4f[i * 4 + 0] = Image_LinearFloatFromsRGB(in->color4ub[0]);
+ loadmodel->brushq3.data_color4f[i * 4 + 1] = Image_LinearFloatFromsRGB(in->color4ub[1]);
+ loadmodel->brushq3.data_color4f[i * 4 + 2] = Image_LinearFloatFromsRGB(in->color4ub[2]);
+ }
+ }
+ else
+ {
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ {
+ loadmodel->brushq3.data_color4f[i * 4 + 0] = Image_sRGBFloatFromLinear_Lightmap(in->color4ub[0]);
+ loadmodel->brushq3.data_color4f[i * 4 + 1] = Image_sRGBFloatFromLinear_Lightmap(in->color4ub[1]);
+ loadmodel->brushq3.data_color4f[i * 4 + 2] = Image_sRGBFloatFromLinear_Lightmap(in->color4ub[2]);
+ }
+ else
+ {
+ loadmodel->brushq3.data_color4f[i * 4 + 0] = in->color4ub[0] * (1.0f / 255.0f);
+ loadmodel->brushq3.data_color4f[i * 4 + 1] = in->color4ub[1] * (1.0f / 255.0f);
+ loadmodel->brushq3.data_color4f[i * 4 + 2] = in->color4ub[2] * (1.0f / 255.0f);
+ }
+ }
loadmodel->brushq3.data_color4f[i * 4 + 3] = in->color4ub[3] * (1.0f / 255.0f);
if(in->color4ub[0] != 255 || in->color4ub[1] != 255 || in->color4ub[2] != 255)
loadmodel->lit = true;
char mapname[MAX_QPATH];
qboolean external;
unsigned char *inpixels[10000]; // max count q3map2 can output (it uses 4 digits)
+ char vabuf[1024];
// defaults for q3bsp
size = 128;
if (developer_loading.integer)
Con_Printf("Using external lightmaps\n");
FS_StripExtension(loadmodel->name, mapname, sizeof(mapname));
- inpixels[0] = loadimagepixelsbgra(va("%s/lm_%04d", mapname, 0), false, false, false, NULL);
+ inpixels[0] = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s/lm_%04d", mapname, 0), false, false, false, NULL);
if(!inpixels[0])
return;
for(count = 1; ; ++count)
{
- inpixels[count] = loadimagepixelsbgra(va("%s/lm_%04d", mapname, count), false, false, false, NULL);
+ inpixels[count] = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s/lm_%04d", mapname, count), false, false, false, NULL);
if(!inpixels[count])
break; // we got all of them
if(image_width != size || image_height != size)
mergebuf = (loadmodel->brushq3.deluxemapping && (i & 1)) ? mergeddeluxepixels : mergedpixels;
mergebuf += 4 * (realindex & (mergedcolumns-1))*size + 4 * ((realindex >> powerx) & (mergedrows-1))*mergedwidth*size;
if ((i & 1) == 0 || !loadmodel->brushq3.deluxemapping)
- Con_Printf("copying original lightmap %i (%ix%i) to %i (at %i,%i)\n", i, size, size, lightmapindex, (realindex & (mergedcolumns-1))*size, ((realindex >> powerx) & (mergedrows-1))*size);
+ Con_DPrintf("copying original lightmap %i (%ix%i) to %i (at %i,%i)\n", i, size, size, lightmapindex, (realindex & (mergedcolumns-1))*size, ((realindex >> powerx) & (mergedrows-1))*size);
// convert pixels from RGB or BGRA while copying them into the destination rectangle
for (j = 0;j < size;j++)
if (((realindex + 1) & (mergedrowsxcolumns - 1)) == 0 || (realindex + 1) == realcount)
{
if (loadmodel->brushq3.deluxemapping && (i & 1))
- loadmodel->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va("deluxemap%04i", lightmapindex), mergedwidth, mergedheight, mergeddeluxepixels, TEXTYPE_BGRA, TEXF_FORCELINEAR | (gl_texturecompression_q3bspdeluxemaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
+ loadmodel->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "deluxemap%04i", lightmapindex), mergedwidth, mergedheight, mergeddeluxepixels, TEXTYPE_BGRA, TEXF_FORCELINEAR | (gl_texturecompression_q3bspdeluxemaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
else
- loadmodel->brushq3.data_lightmaps [lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%04i", lightmapindex), mergedwidth, mergedheight, mergedpixels, TEXTYPE_BGRA, TEXF_FORCELINEAR | (gl_texturecompression_q3bsplightmaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
+ {
+ if(mod_q3bsp_sRGBlightmaps.integer)
+ {
+ textype_t t;
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ {
+ // TODO (should we do this, or should we instead knowingly render brighter in sRGB fallback mode?)
+ int n = mergedwidth * mergedheight * 4;
+ int i;
+ for(i = 0; i < n; i += 4)
+ {
+ // actually we do: Image_sRGBFloatFromLinear_Lightmap(Image_LinearFloatFromsRGBFloat(x))
+ // neutral point is at Image_sRGBFloatFromLinearFloat(0.5)
+ // so we need to map Image_sRGBFloatFromLinearFloat(0.5) to 0.5
+ // factor is 0.5 / Image_sRGBFloatFromLinearFloat(0.5)
+ mergedpixels[i+0] = (mergedpixels[i+0] * (int)173 + 128) / 255;
+ mergedpixels[i+1] = (mergedpixels[i+1] * (int)173 + 128) / 255;
+ mergedpixels[i+2] = (mergedpixels[i+2] * (int)173 + 128) / 255;
+ }
+ t = TEXTYPE_BGRA; // in stupid fallback mode, we upload lightmaps in sRGB form and just fix their brightness
+ }
+ else
+ t = TEXTYPE_SRGB_BGRA; // normally, we upload lightmaps in sRGB form (possibly downconverted to linear)
+ loadmodel->brushq3.data_lightmaps [lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "lightmap%04i", lightmapindex), mergedwidth, mergedheight, mergedpixels, t, TEXF_FORCELINEAR | (gl_texturecompression_q3bsplightmaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
+ }
+ else
+ {
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ Image_MakesRGBColorsFromLinear_Lightmap(mergedpixels, mergedpixels, mergedwidth * mergedheight);
+ loadmodel->brushq3.data_lightmaps [lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "lightmap%04i", lightmapindex), mergedwidth, mergedheight, mergedpixels, TEXTYPE_BGRA, TEXF_FORCELINEAR | (gl_texturecompression_q3bsplightmaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
+ }
+ }
}
}
q3dlightgrid_t *in;
q3dlightgrid_t *out;
int count;
+ int i;
in = (q3dlightgrid_t *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
loadmodel->brushq3.num_lightgrid = count;
// no swapping or validation necessary
memcpy(out, in, count * (int)sizeof(*out));
+
+ if(mod_q3bsp_sRGBlightmaps.integer)
+ {
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ {
+ // TODO (should we do this, or should we instead knowingly render brighter in sRGB fallback mode?)
+ for(i = 0; i < count; ++i)
+ {
+ // actually we do: Image_sRGBFloatFromLinear_Lightmap(Image_LinearFloatFromsRGBFloat(x))
+ // neutral point is at Image_sRGBFloatFromLinearFloat(0.5)
+ // so we need to map Image_sRGBFloatFromLinearFloat(0.5) to 0.5
+ // factor is 0.5 / Image_sRGBFloatFromLinearFloat(0.5)
+ out[i].ambientrgb[0] = (out[i].ambientrgb[0] * (int)173 + 128) / 255; // fixes neutral level
+ out[i].ambientrgb[1] = (out[i].ambientrgb[1] * (int)173 + 128) / 255; // fixes neutral level
+ out[i].ambientrgb[2] = (out[i].ambientrgb[2] * (int)173 + 128) / 255; // fixes neutral level
+ out[i].diffusergb[0] = (out[i].diffusergb[0] * (int)173 + 128) / 255; // fixes neutral level
+ out[i].diffusergb[1] = (out[i].diffusergb[1] * (int)173 + 128) / 255; // fixes neutral level
+ out[i].diffusergb[2] = (out[i].diffusergb[2] * (int)173 + 128) / 255; // fixes neutral level
+ }
+ }
+ else
+ {
+ for(i = 0; i < count; ++i)
+ {
+ out[i].ambientrgb[0] = floor(Image_LinearFloatFromsRGB(out[i].ambientrgb[0]) * 255.0f + 0.5f);
+ out[i].ambientrgb[1] = floor(Image_LinearFloatFromsRGB(out[i].ambientrgb[1]) * 255.0f + 0.5f);
+ out[i].ambientrgb[2] = floor(Image_LinearFloatFromsRGB(out[i].ambientrgb[2]) * 255.0f + 0.5f);
+ out[i].diffusergb[0] = floor(Image_LinearFloatFromsRGB(out[i].diffusergb[0]) * 255.0f + 0.5f);
+ out[i].diffusergb[1] = floor(Image_LinearFloatFromsRGB(out[i].diffusergb[1]) * 255.0f + 0.5f);
+ out[i].diffusergb[2] = floor(Image_LinearFloatFromsRGB(out[i].diffusergb[2]) * 255.0f + 0.5f);
+ }
+ }
+ }
+ else
+ {
+ if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ {
+ for(i = 0; i < count; ++i)
+ {
+ out[i].ambientrgb[0] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].ambientrgb[0]) * 255.0f + 0.5f);
+ out[i].ambientrgb[1] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].ambientrgb[1]) * 255.0f + 0.5f);
+ out[i].ambientrgb[2] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].ambientrgb[2]) * 255.0f + 0.5f);
+ out[i].diffusergb[0] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].diffusergb[0]) * 255.0f + 0.5f);
+ out[i].diffusergb[1] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].diffusergb[1]) * 255.0f + 0.5f);
+ out[i].diffusergb[2] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].diffusergb[2]) * 255.0f + 0.5f);
+ }
+ }
+ else
+ {
+ // all is good
+ }
+ }
}
}
}
}
-void Mod_CollisionBIH_TraceLineShared(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, const bih_t *bih)
+static void Mod_CollisionBIH_TraceLineShared(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, const bih_t *bih)
{
const bih_leaf_t *leaf;
const bih_node_t *node;
}
-int Mod_CollisionBIH_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
+static int Mod_CollisionBIH_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
{
trace_t trace;
Mod_CollisionBIH_TracePoint(model, NULL, NULL, &trace, point, 0);
Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, end, 0, 1, start, end, ++markframe, segmentmins, segmentmaxs);
}
-void Mod_Q3BSP_TraceBrush(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *start, colbrushf_t *end, int hitsupercontentsmask)
+static void Mod_Q3BSP_TraceBrush(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *start, colbrushf_t *end, int hitsupercontentsmask)
{
float segmentmins[3], segmentmaxs[3];
int i;
q3mbrush_t *brush;
if (mod_collision_bih.integer)
{
- trace_t trace;
- Mod_Q3BSP_TracePoint(model, NULL, NULL, &trace, point, 0);
- supercontents = trace.startsupercontents;
+ supercontents = Mod_CollisionBIH_PointSuperContents(model, frame, point);
}
// test if the point is inside each brush
else if (model->brush.submodel)
return nativecontents;
}
-void Mod_Q3BSP_RecursiveFindNumLeafs(mnode_t *node)
+static void Mod_Q3BSP_RecursiveFindNumLeafs(mnode_t *node)
{
int numleafs;
while (node->plane)
loadmodel->brush.num_leafs = numleafs;
}
-void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
+static void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, lumps;
q3dheader_t *header;
Con_DPrintf("Stats for obj model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
}
-
-qboolean Mod_CanSeeBox_Trace(int numsamples, float t, dp_model_t *model, vec3_t eye, vec3_t minsX, vec3_t maxsX)
-{
- // we already have done PVS culling at this point...
- // so we don't need to do it again.
-
- int i;
- vec3_t testorigin, mins, maxs;
-
- testorigin[0] = (minsX[0] + maxsX[0]) * 0.5;
- testorigin[1] = (minsX[1] + maxsX[1]) * 0.5;
- testorigin[2] = (minsX[2] + maxsX[2]) * 0.5;
-
- if(model->brush.TraceLineOfSight(model, eye, testorigin))
- return 1;
-
- // expand the box a little
- mins[0] = (t+1) * minsX[0] - t * maxsX[0];
- maxs[0] = (t+1) * maxsX[0] - t * minsX[0];
- mins[1] = (t+1) * minsX[1] - t * maxsX[1];
- maxs[1] = (t+1) * maxsX[1] - t * minsX[1];
- mins[2] = (t+1) * minsX[2] - t * maxsX[2];
- maxs[2] = (t+1) * maxsX[2] - t * minsX[2];
-
- for(i = 0; i != numsamples; ++i)
- {
- testorigin[0] = lhrandom(mins[0], maxs[0]);
- testorigin[1] = lhrandom(mins[1], maxs[1]);
- testorigin[2] = lhrandom(mins[2], maxs[2]);
-
- if(model->brush.TraceLineOfSight(model, eye, testorigin))
- return 1;
- }
-
- return 0;
-}
-
#define Q3SURFACEFLAG_NODAMAGE 1
#define Q3SURFACEFLAG_SLICK 2
#define Q3SURFACEFLAG_SKY 4
-#define Q3SURFACEFLAG_LADDER 8
+#define Q3SURFACEFLAG_LADDER 8 // has no surfaceparm
#define Q3SURFACEFLAG_NOIMPACT 16
#define Q3SURFACEFLAG_NOMARKS 32
-#define Q3SURFACEFLAG_FLESH 64
+#define Q3SURFACEFLAG_FLESH 64 // has no surfaceparm
#define Q3SURFACEFLAG_NODRAW 128
#define Q3SURFACEFLAG_HINT 256
-#define Q3SURFACEFLAG_SKIP 512
+#define Q3SURFACEFLAG_SKIP 512 // has no surfaceparm
#define Q3SURFACEFLAG_NOLIGHTMAP 1024
#define Q3SURFACEFLAG_POINTLIGHT 2048
#define Q3SURFACEFLAG_METALSTEPS 4096
-#define Q3SURFACEFLAG_NOSTEPS 8192
+#define Q3SURFACEFLAG_NOSTEPS 8192 // has no surfaceparm
#define Q3SURFACEFLAG_NONSOLID 16384
#define Q3SURFACEFLAG_LIGHTFILTER 32768
#define Q3SURFACEFLAG_ALPHASHADOW 65536
mod->loaded = false;
}
-void R_Model_Null_Draw(entity_render_t *ent)
+static void R_Model_Null_Draw(entity_render_t *ent)
{
return;
}
-typedef void (*mod_framegroupify_parsegroups_t) (unsigned int i, int start, int len, float fps, qboolean loop, void *pass);
+typedef void (*mod_framegroupify_parsegroups_t) (unsigned int i, int start, int len, float fps, qboolean loop, const char *name, void *pass);
-int Mod_FrameGroupify_ParseGroups(const char *buf, mod_framegroupify_parsegroups_t cb, void *pass)
+static int Mod_FrameGroupify_ParseGroups(const char *buf, mod_framegroupify_parsegroups_t cb, void *pass)
{
const char *bufptr;
int start, len;
float fps;
unsigned int i;
qboolean loop;
+ char name[64];
bufptr = buf;
i = 0;
- for(;;)
+ while(bufptr)
{
// an anim scene!
- if (!COM_ParseToken_Simple(&bufptr, true, false))
- break;
+
+ // REQUIRED: fetch start
+ COM_ParseToken_Simple(&bufptr, true, false, true);
+ if (!bufptr)
+ break; // end of file
if (!strcmp(com_token, "\n"))
continue; // empty line
start = atoi(com_token);
- if (!COM_ParseToken_Simple(&bufptr, true, false))
- break;
- if (!strcmp(com_token, "\n"))
+
+ // REQUIRED: fetch length
+ COM_ParseToken_Simple(&bufptr, true, false, true);
+ if (!bufptr || !strcmp(com_token, "\n"))
{
Con_Printf("framegroups file: missing number of frames\n");
continue;
}
len = atoi(com_token);
- if (!COM_ParseToken_Simple(&bufptr, true, false))
- break;
- // we default to looping as it's usually wanted, so to NOT loop you append a 0
- if (strcmp(com_token, "\n"))
+
+ // OPTIONAL args start
+ COM_ParseToken_Simple(&bufptr, true, false, true);
+
+ // OPTIONAL: fetch fps
+ fps = 20;
+ if (bufptr && strcmp(com_token, "\n"))
{
fps = atof(com_token);
- if (!COM_ParseToken_Simple(&bufptr, true, false))
- break;
- if (strcmp(com_token, "\n"))
- loop = atoi(com_token) != 0;
- else
- loop = true;
+ COM_ParseToken_Simple(&bufptr, true, false, true);
}
- else
+
+ // OPTIONAL: fetch loopflag
+ loop = true;
+ if (bufptr && strcmp(com_token, "\n"))
+ {
+ loop = (atoi(com_token) != 0);
+ COM_ParseToken_Simple(&bufptr, true, false, true);
+ }
+
+ // OPTIONAL: fetch name
+ name[0] = 0;
+ if (bufptr && strcmp(com_token, "\n"))
{
- fps = 20;
- loop = true;
+ strlcpy(name, com_token, sizeof(name));
+ COM_ParseToken_Simple(&bufptr, true, false, true);
}
+ // OPTIONAL: remaining unsupported tokens (eat them)
+ while (bufptr && strcmp(com_token, "\n"))
+ COM_ParseToken_Simple(&bufptr, true, false, true);
+
+ //Con_Printf("data: %d %d %d %f %d (%s)\n", i, start, len, fps, loop, name);
+
if(cb)
- cb(i, start, len, fps, loop, pass);
+ cb(i, start, len, fps, loop, (name[0] ? name : NULL), pass);
++i;
}
return i;
}
-void Mod_FrameGroupify_ParseGroups_Count (unsigned int i, int start, int len, float fps, qboolean loop, void *pass)
-{
- unsigned int *cnt = (unsigned int *) pass;
- ++*cnt;
-}
-
-void Mod_FrameGroupify_ParseGroups_Store (unsigned int i, int start, int len, float fps, qboolean loop, void *pass)
+static void Mod_FrameGroupify_ParseGroups_Store (unsigned int i, int start, int len, float fps, qboolean loop, const char *name, void *pass)
{
dp_model_t *mod = (dp_model_t *) pass;
animscene_t *anim = &mod->animscenes[i];
- dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d_anim", i);
+ if(name)
+ strlcpy(anim->name, name, sizeof(anim[i].name));
+ else
+ dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d_anim", i);
anim->firstframe = bound(0, start, mod->num_poses - 1);
anim->framecount = bound(1, len, mod->num_poses - anim->firstframe);
anim->framerate = max(1, fps);
//Con_Printf("frame group %d is %d %d %f %d\n", i, start, len, fps, loop);
}
-void Mod_FrameGroupify(dp_model_t *mod, const char *buf)
+static void Mod_FrameGroupify(dp_model_t *mod, const char *buf)
{
unsigned int cnt;
Mod_FrameGroupify_ParseGroups(buf, Mod_FrameGroupify_ParseGroups_Store, mod);
}
-void Mod_FindPotentialDeforms(dp_model_t *mod)
+static void Mod_FindPotentialDeforms(dp_model_t *mod)
{
int i, j;
texture_t *texture;
unsigned int crc;
void *buf;
fs_offset_t filesize = 0;
+ char vabuf[1024];
mod->used = true;
Mem_Free(buf);
Mod_FindPotentialDeforms(mod);
-
- buf = FS_LoadFile (va("%s.framegroups", mod->name), tempmempool, false, &filesize);
+
+ buf = FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.framegroups", mod->name), tempmempool, false, &filesize);
if(buf)
{
Mod_FrameGroupify(mod, (const char *)buf);
VectorNormalize(vectorNormal);
}
-void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
+#if 0
+static void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
{
float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
// 79 add/sub/negate/multiply (1 cycle), 1 compare (3 cycle?), total cycles not counting load/store/exchange roughly 82 cycles
VectorNegate(tvector3f, tvector3f);
}
}
+#endif
// warning: this is a very expensive function!
void Mod_BuildTextureVectorsFromNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const float *normal3f, const int *elements, float *svector3f, float *tvector3f, qboolean areaweighting)
mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mempool, mod->brush.collisionmesh, false, false, false);
}
-void Mod_GetTerrainVertex3fTexCoord2fFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
+#if 0
+static void Mod_GetTerrainVertex3fTexCoord2fFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
{
float v[3], tc[3];
v[0] = ix;
texcoord2f[1] = tc[1];
}
-void Mod_GetTerrainVertexFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
+static void Mod_GetTerrainVertexFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
{
float vup[3], vdown[3], vleft[3], vright[3];
float tcup[3], tcdown[3], tcleft[3], tcright[3];
VectorAdd(normal3f, nl, normal3f);
}
-void Mod_ConstructTerrainPatchFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int x1, int y1, int width, int height, int *element3i, int *neighbor3i, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
+static void Mod_ConstructTerrainPatchFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int x1, int y1, int width, int height, int *element3i, int *neighbor3i, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
{
int x, y, ix, iy, *e;
e = element3i;
for (x = 0, ix = x1;x < width + 1;x++, ix++, vertex3f += 3, texcoord2f += 2, svector3f += 3, tvector3f += 3, normal3f += 3)
Mod_GetTerrainVertexFromBGRA(imagepixels, imagewidth, imageheight, ix, iy, vertex3f, texcoord2f, svector3f, tvector3f, normal3f, pixelstepmatrix, pixeltexturestepmatrix);
}
+#endif
#if 0
void Mod_Terrain_SurfaceRecurseChunk(dp_model_t *model, int stepsize, int x, int y)
}
#endif
-int Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
+static int Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
{
int offset = 0;
if (!strncasecmp(s, "user", 4)) // parse stuff like "user1sin", always user<n>func
{
if (strcasecmp (entry->shader.name, shader->name) == 0)
{
- unsigned char *start, *end, *start2;
- start = (unsigned char *) (&shader->Q3SHADERINFO_COMPARE_START);
- end = ((unsigned char *) (&shader->Q3SHADERINFO_COMPARE_END)) + sizeof(shader->Q3SHADERINFO_COMPARE_END);
- start2 = (unsigned char *) (&entry->shader.Q3SHADERINFO_COMPARE_START);
- if(memcmp(start, start2, end - start))
- Con_DPrintf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name);
+ // redeclaration
+ if(shader->dpshaderkill)
+ {
+ // killed shader is a redeclarion? we can safely ignore it
+ return;
+ }
+ else if(entry->shader.dpshaderkill)
+ {
+ // replace the old shader!
+ // this will skip the entry allocating part
+ // below and just replace the shader
+ break;
+ }
else
- Con_DPrintf("Shader '%s' already defined\n", shader->name);
- return;
+ {
+ unsigned char *start, *end, *start2;
+ start = (unsigned char *) (&shader->Q3SHADERINFO_COMPARE_START);
+ end = ((unsigned char *) (&shader->Q3SHADERINFO_COMPARE_END)) + sizeof(shader->Q3SHADERINFO_COMPARE_END);
+ start2 = (unsigned char *) (&entry->shader.Q3SHADERINFO_COMPARE_START);
+ if(memcmp(start, start2, end - start))
+ Con_DPrintf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name);
+ else
+ Con_DPrintf("Shader '%s' already defined\n", shader->name);
+ return;
+ }
}
lastEntry = entry;
entry = entry->chain;
extern cvar_t mod_noshader_default_offsetmapping;
extern cvar_t mod_q3shader_default_offsetmapping;
+extern cvar_t mod_q3shader_default_offsetmapping_scale;
+extern cvar_t mod_q3shader_default_offsetmapping_bias;
extern cvar_t mod_q3shader_default_polygonoffset;
extern cvar_t mod_q3shader_default_polygonfactor;
+extern cvar_t mod_q3shader_force_addalpha;
void Mod_LoadQ3Shaders(void)
{
int j;
char *custsurfaceparmnames[256]; // VorteX: q3map2 has 64 but well, someone will need more
unsigned long custsurfaceparms[256];
int numcustsurfaceparms;
+ qboolean dpshaderkill;
Mod_FreeQ3Shaders();
Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1);
shader.r_water_wateralpha = 1;
shader.offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
- shader.offsetscale = 1;
+ shader.offsetscale = mod_q3shader_default_offsetmapping_scale.value;
+ shader.offsetbias = mod_q3shader_default_offsetmapping_bias.value;
shader.specularscalemod = 1;
shader.specularpowermod = 1;
shader.biaspolygonoffset = mod_q3shader_default_polygonoffset.value;
layer->blendfunc[0] = GL_ONE;
layer->blendfunc[1] = GL_ONE;
}
+ else if (!strcasecmp(parameter[1], "addalpha"))
+ {
+ layer->blendfunc[0] = GL_SRC_ALPHA;
+ layer->blendfunc[1] = GL_ONE;
+ }
else if (!strcasecmp(parameter[1], "filter"))
{
layer->blendfunc[0] = GL_DST_COLOR;
else if (!strcasecmp(parameter[k+1], "GL_DST_COLOR"))
layer->blendfunc[k] = GL_DST_COLOR;
else if (!strcasecmp(parameter[k+1], "GL_DST_ALPHA"))
- layer->blendfunc[k] = GL_ONE_MINUS_DST_ALPHA;
+ layer->blendfunc[k] = GL_DST_ALPHA;
else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_COLOR"))
layer->blendfunc[k] = GL_ONE_MINUS_SRC_COLOR;
else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_ALPHA"))
shader.textureblendalpha = true;
}
}
- layer->texflags = TEXF_ALPHA;
+
+ if(mod_q3shader_force_addalpha.integer)
+ {
+ // for a long while, DP treated GL_ONE GL_ONE as GL_SRC_ALPHA GL_ONE
+ // this cvar brings back this behaviour
+ if(layer->blendfunc[0] == GL_ONE && layer->blendfunc[1] == GL_ONE)
+ layer->blendfunc[0] = GL_SRC_ALPHA;
+ }
+
+ layer->texflags = 0;
+ if (layer->alphatest)
+ layer->texflags |= TEXF_ALPHA;
+ switch(layer->blendfunc[0])
+ {
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ layer->texflags |= TEXF_ALPHA;
+ break;
+ }
+ switch(layer->blendfunc[1])
+ {
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ layer->texflags |= TEXF_ALPHA;
+ break;
+ }
if (!(shader.surfaceparms & Q3SURFACEPARM_NOMIPMAPS))
layer->texflags |= TEXF_MIPMAP;
if (!(shader.textureflags & Q3TEXTUREFLAG_NOPICMIP))
strlcpy(shader.dpreflectcube, parameter[1], sizeof(shader.dpreflectcube));
else if (!strcasecmp(parameter[0], "dpmeshcollisions"))
shader.dpmeshcollisions = true;
+ // this sets dpshaderkill to true if dpshaderkillifcvarzero was used, and to false if dpnoshaderkillifcvarzero was used
+ else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvarzero")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvarzero")) && numparameters >= 2)
+ {
+ if (Cvar_VariableValue(parameter[1]) == 0.0f)
+ shader.dpshaderkill = dpshaderkill;
+ }
+ // this sets dpshaderkill to true if dpshaderkillifcvar was used, and to false if dpnoshaderkillifcvar was used
+ else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvar")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvar")) && numparameters >= 2)
+ {
+ const char *op = NULL;
+ if (numparameters >= 3)
+ op = parameter[2];
+ if(!op)
+ {
+ if (Cvar_VariableValue(parameter[1]) != 0.0f)
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "=="))
+ {
+ if (Cvar_VariableValue(parameter[1]) == atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "!="))
+ {
+ if (Cvar_VariableValue(parameter[1]) != atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, ">"))
+ {
+ if (Cvar_VariableValue(parameter[1]) > atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "<"))
+ {
+ if (Cvar_VariableValue(parameter[1]) < atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, ">="))
+ {
+ if (Cvar_VariableValue(parameter[1]) >= atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "<="))
+ {
+ if (Cvar_VariableValue(parameter[1]) <= atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else
+ {
+ Con_DPrintf("%s parsing warning: unknown dpshaderkillifcvar op \"%s\", or not enough arguments\n", search->filenames[fileindex], op);
+ }
+ }
else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
{
// some q3 skies don't have the sky parm set
{
shader.specularpowermod = atof(parameter[1]);
}
- else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 3)
+ else if (!strcasecmp(parameter[0], "dprtlightambient") && numparameters >= 2)
+ {
+ shader.rtlightambient = atof(parameter[1]);
+ }
+ else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 2)
{
if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "off"))
shader.offsetmapping = OFFSETMAPPING_OFF;
- else if (!strcasecmp(parameter[1], "default"))
+ else if (!strcasecmp(parameter[1], "default") || !strcasecmp(parameter[1], "normal"))
shader.offsetmapping = OFFSETMAPPING_DEFAULT;
else if (!strcasecmp(parameter[1], "linear"))
shader.offsetmapping = OFFSETMAPPING_LINEAR;
else if (!strcasecmp(parameter[1], "relief"))
shader.offsetmapping = OFFSETMAPPING_RELIEF;
- shader.offsetscale = atof(parameter[2]);
+ if (numparameters >= 3)
+ shader.offsetscale = atof(parameter[2]);
+ if (numparameters >= 5)
+ {
+ if(!strcasecmp(parameter[3], "bias"))
+ shader.offsetbias = atof(parameter[4]);
+ else if(!strcasecmp(parameter[3], "match"))
+ shader.offsetbias = 1.0f - atof(parameter[4]);
+ else if(!strcasecmp(parameter[3], "match8"))
+ shader.offsetbias = 1.0f - atof(parameter[4]) / 255.0f;
+ else if(!strcasecmp(parameter[3], "match16"))
+ shader.offsetbias = 1.0f - atof(parameter[4]) / 65535.0f;
+ }
}
else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
{
}
}
}
+ // hide this shader if a cvar said it should be killed
+ if (shader.dpshaderkill)
+ shader.numlayers = 0;
// pick the primary layer to render with
if (shader.numlayers)
{
// unless later loaded from the shader
texture->offsetmapping = (mod_noshader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
texture->offsetscale = 1;
+ texture->offsetbias = 0;
texture->specularscalemod = 1;
texture->specularpowermod = 1;
+ texture->rtlightambient = 0;
// WHEN ADDING DEFAULTS HERE, REMEMBER TO SYNC TO SHADER LOADING ABOVE
// HERE, AND Q1BSP LOADING
// JUST GREP FOR "specularscalemod = 1".
{
if (developer_loading.integer)
Con_Printf("%s: loaded shader for %s\n", loadmodel->name, name);
- texture->surfaceparms = shader->surfaceparms;
// allow disabling of picmip or compression by defaulttexflags
texture->textureflags = (shader->textureflags & texflagsmask) | texflagsor;
Vector2Copy(shader->r_water_waterscroll, texture->r_water_waterscroll);
texture->offsetmapping = shader->offsetmapping;
texture->offsetscale = shader->offsetscale;
+ texture->offsetbias = shader->offsetbias;
texture->specularscalemod = shader->specularscalemod;
texture->specularpowermod = shader->specularpowermod;
+ texture->rtlightambient = shader->rtlightambient;
if (shader->dpreflectcube[0])
texture->reflectcubetexture = R_GetCubemap(shader->dpreflectcube);
// if (shader->surfaceparms & Q3SURFACEPARM_LIGHTGRID ) texture->supercontents |= SUPERCONTENTS_LIGHTGRID ;
// if (shader->surfaceparms & Q3SURFACEPARM_ANTIPORTAL ) texture->supercontents |= SUPERCONTENTS_ANTIPORTAL ;
+ texture->surfaceflags = 0;
+ if (shader->surfaceparms & Q3SURFACEPARM_ALPHASHADOW ) texture->surfaceflags |= Q3SURFACEFLAG_ALPHASHADOW ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_AREAPORTAL ) texture->surfaceflags |= Q3SURFACEFLAG_AREAPORTAL ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_CLUSTERPORTAL) texture->surfaceflags |= Q3SURFACEFLAG_CLUSTERPORTAL;
+ // if (shader->surfaceparms & Q3SURFACEPARM_DETAIL ) texture->surfaceflags |= Q3SURFACEFLAG_DETAIL ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_DONOTENTER ) texture->surfaceflags |= Q3SURFACEFLAG_DONOTENTER ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_FOG ) texture->surfaceflags |= Q3SURFACEFLAG_FOG ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_LAVA ) texture->surfaceflags |= Q3SURFACEFLAG_LAVA ;
+ if (shader->surfaceparms & Q3SURFACEPARM_LIGHTFILTER ) texture->surfaceflags |= Q3SURFACEFLAG_LIGHTFILTER ;
+ if (shader->surfaceparms & Q3SURFACEPARM_METALSTEPS ) texture->surfaceflags |= Q3SURFACEFLAG_METALSTEPS ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NODAMAGE ) texture->surfaceflags |= Q3SURFACEFLAG_NODAMAGE ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NODLIGHT ) texture->surfaceflags |= Q3SURFACEFLAG_NODLIGHT ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NODRAW ) texture->surfaceflags |= Q3SURFACEFLAG_NODRAW ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NODROP ) texture->surfaceflags |= Q3SURFACEFLAG_NODROP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NOIMPACT ) texture->surfaceflags |= Q3SURFACEFLAG_NOIMPACT ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NOLIGHTMAP ) texture->surfaceflags |= Q3SURFACEFLAG_NOLIGHTMAP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NOMARKS ) texture->surfaceflags |= Q3SURFACEFLAG_NOMARKS ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOMIPMAPS ) texture->surfaceflags |= Q3SURFACEFLAG_NOMIPMAPS ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NONSOLID ) texture->surfaceflags |= Q3SURFACEFLAG_NONSOLID ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_ORIGIN ) texture->surfaceflags |= Q3SURFACEFLAG_ORIGIN ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_PLAYERCLIP ) texture->surfaceflags |= Q3SURFACEFLAG_PLAYERCLIP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SKY ) texture->surfaceflags |= Q3SURFACEFLAG_SKY ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SLICK ) texture->surfaceflags |= Q3SURFACEFLAG_SLICK ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_SLIME ) texture->surfaceflags |= Q3SURFACEFLAG_SLIME ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_STRUCTURAL ) texture->surfaceflags |= Q3SURFACEFLAG_STRUCTURAL ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_TRANS ) texture->surfaceflags |= Q3SURFACEFLAG_TRANS ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_WATER ) texture->surfaceflags |= Q3SURFACEFLAG_WATER ;
+ if (shader->surfaceparms & Q3SURFACEPARM_POINTLIGHT ) texture->surfaceflags |= Q3SURFACEFLAG_POINTLIGHT ;
+ if (shader->surfaceparms & Q3SURFACEPARM_HINT ) texture->surfaceflags |= Q3SURFACEFLAG_HINT ;
+ if (shader->surfaceparms & Q3SURFACEPARM_DUST ) texture->surfaceflags |= Q3SURFACEFLAG_DUST ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_BOTCLIP ) texture->surfaceflags |= Q3SURFACEFLAG_BOTCLIP ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_LIGHTGRID ) texture->surfaceflags |= Q3SURFACEFLAG_LIGHTGRID ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_ANTIPORTAL ) texture->surfaceflags |= Q3SURFACEFLAG_ANTIPORTAL ;
+
if (shader->dpmeshcollisions)
texture->basematerialflags |= MATERIALFLAG_MESHCOLLISIONS;
+ if (shader->dpshaderkill && developer_extra.integer)
+ Con_DPrintf("^1%s:^7 killing shader ^3\"%s\" because of cvar\n", loadmodel->name, name);
}
else if (!strcmp(texture->name, "noshader") || !texture->name[0])
{
if (developer_extra.integer)
Con_DPrintf("^1%s:^7 using fallback noshader material for ^3\"%s\"\n", loadmodel->name, name);
- texture->surfaceparms = 0;
texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
}
else if (!strcmp(texture->name, "common/nodraw") || !strcmp(texture->name, "textures/common/nodraw"))
{
if (developer_extra.integer)
Con_DPrintf("^1%s:^7 using fallback nodraw material for ^3\"%s\"\n", loadmodel->name, name);
- texture->surfaceparms = 0;
texture->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
texture->supercontents = SUPERCONTENTS_SOLID;
}
{
if (developer_extra.integer)
Con_DPrintf("^1%s:^7 No shader found for texture ^3\"%s\"\n", loadmodel->name, texture->name);
- texture->surfaceparms = 0;
if (texture->surfaceflags & Q3SURFACEFLAG_NODRAW)
{
texture->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
skinfile_t *skinfile = NULL, *first = NULL;
skinfileitem_t *skinfileitem;
char word[10][MAX_QPATH];
+ char vabuf[1024];
/*
sample file:
tag_torso,
*/
memset(word, 0, sizeof(word));
- for (i = 0;i < 256 && (data = text = (char *)FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true, NULL));i++)
+ for (i = 0;i < 256 && (data = text = (char *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s_%i.skin", loadmodel->name, i), tempmempool, true, NULL));i++)
{
// If it's the first file we parse
if (skinfile == NULL)
int zymtextsize = 0;
int dpmtextsize = 0;
int framegroupstextsize = 0;
+ char vabuf[1024];
if (Cmd_Argc() != 2)
{
}
}
if (zymtextsize)
- FS_WriteFile(va("%s_decompiled/out_zym.txt", basename), zymtextbuffer, (fs_offset_t)zymtextsize);
+ FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_decompiled/out_zym.txt", basename), zymtextbuffer, (fs_offset_t)zymtextsize);
if (dpmtextsize)
- FS_WriteFile(va("%s_decompiled/out_dpm.txt", basename), dpmtextbuffer, (fs_offset_t)dpmtextsize);
+ FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_decompiled/out_dpm.txt", basename), dpmtextbuffer, (fs_offset_t)dpmtextsize);
if (framegroupstextsize)
- FS_WriteFile(va("%s_decompiled.framegroups", basename), framegroupstextbuffer, (fs_offset_t)framegroupstextsize);
+ FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_decompiled.framegroups", basename), framegroupstextbuffer, (fs_offset_t)framegroupstextsize);
}
}
static int mod_generatelightmaps_numlights;
static lightmaplight_t *mod_generatelightmaps_lightinfo;
-extern int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color);
extern cvar_t r_shadow_lightattenuationdividebias;
extern cvar_t r_shadow_lightattenuationlinearscale;
unsigned char *lightmappixels;
unsigned char *deluxemappixels;
mod_alloclightmap_state_t lmstate;
+ char vabuf[1024];
// generate lightmap projection information for all triangles
if (model->texturepool == NULL)
for (lightmapindex = 0;lightmapindex < model->brushq3.num_mergedlightmaps;lightmapindex++)
{
- model->brushq3.data_lightmaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va("lightmap%i", lightmapindex), lm_texturesize, lm_texturesize, lightmappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, -1, NULL);
- model->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va("deluxemap%i", lightmapindex), lm_texturesize, lm_texturesize, deluxemappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, -1, NULL);
+ model->brushq3.data_lightmaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va(vabuf, sizeof(vabuf), "lightmap%i", lightmapindex), lm_texturesize, lm_texturesize, lightmappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, -1, NULL);
+ model->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va(vabuf, sizeof(vabuf), "deluxemap%i", lightmapindex), lm_texturesize, lm_texturesize, deluxemappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, -1, NULL);
}
if (lightmappixels)
// add collisions to all triangles of the surface
qboolean dpmeshcollisions;
+ // kill shader based on cvar checks
+ qboolean dpshaderkill;
+
// fake reflection
char dpreflectcube[Q3PATHLENGTH];
// offsetmapping
dpoffsetmapping_technique_t offsetmapping;
float offsetscale;
+ float offsetbias; // 0 is normal, 1 leads to alpha 0 being neutral and alpha 1 pushing "out"
// polygonoffset (only used if Q3TEXTUREFLAG_POLYGONOFFSET)
float biaspolygonoffset, biaspolygonfactor;
// gloss
float specularscalemod;
float specularpowermod;
-#define Q3SHADERINFO_COMPARE_END specularpowermod
+
+ // rtlightning ambient addition
+ float rtlightambient;
+#define Q3SHADERINFO_COMPARE_END rtlightambient
}
q3shaderinfo_t;
char name[64];
int surfaceflags;
int supercontents;
- int surfaceparms;
int textureflags;
// reflection
// offsetmapping
dpoffsetmapping_technique_t offsetmapping;
float offsetscale;
+ float offsetbias;
// gloss
float specularscalemod;
float specularpowermod;
+
+ // diffuse and ambient
+ float rtlightambient;
}
texture_t;
skinframe = R_SkinFrame_LoadMissing();
texture->offsetmapping = OFFSETMAPPING_OFF;
texture->offsetscale = 1;
+ texture->offsetbias = 0;
texture->specularscalemod = 1;
texture->specularpowermod = 1;
texture->basematerialflags = MATERIALFLAG_WALL;
float modelradius, interval;
char name[MAX_QPATH], fogname[MAX_QPATH];
const void *startframes;
- int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | (gl_texturecompression_sprites.integer ? TEXF_COMPRESS : 0) | TEXF_ISSPRITE | TEXF_PICMIP | TEXF_ALPHA | TEXF_CLAMP;
+ int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | ((gl_texturecompression.integer && gl_texturecompression_sprites.integer) ? TEXF_COMPRESS : 0) | TEXF_ISSPRITE | TEXF_PICMIP | TEXF_ALPHA | TEXF_CLAMP;
modelradius = 0;
if (loadmodel->numframes < 1)
loadmodel->radius2 = modelradius * modelradius;
}
-extern void R_Model_Sprite_Draw(entity_render_t *ent);
void Mod_IDSP_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int version;
Host_Error("Mod_IDSP_Load: %s has wrong version number (%i). Only %i (quake), %i (HalfLife), and %i (sprite32) supported",
loadmodel->name, version, SPRITE_VERSION, SPRITEHL_VERSION, SPRITE32_VERSION);
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
+ loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
}
loadmodel->radius = modelradius;
loadmodel->radius2 = modelradius * modelradius;
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
+ loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
}
#include "prvm_cmds.h"
#include "clvm_cmds.h"
#include "menu.h"
+#include "csprogs.h"
// TODO check which strings really should be engine strings
"DP_GFX_FONTS_FREETYPE "
"DP_UTF8 "
"DP_FONT_VARIABLEWIDTH "
-"DP_GECKO_SUPPORT "
"DP_MENU_EXTRESPONSEPACKET "
"DP_QC_ASINACOSATANATAN2TAN "
"DP_QC_AUTOCVARS "
"DP_QC_CRC16 "
"DP_QC_CVAR_TYPE "
"DP_QC_CVAR_DESCRIPTION "
+"DP_QC_DIGEST "
+"DP_QC_DIGEST_SHA256 "
"DP_QC_FINDCHAIN_TOFIELD "
+"DP_QC_I18N "
"DP_QC_LOG "
"DP_QC_RENDER_SCENE "
"DP_QC_SPRINTF "
setmousetarget(float target)
=========
*/
-void VM_M_setmousetarget(void)
+static void VM_M_setmousetarget(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_setmousetarget);
in_client_mouse = true;
break;
default:
- PRVM_ERROR("VM_M_setmousetarget: wrong destination %f !",PRVM_G_FLOAT(OFS_PARM0));
+ prog->error_cmd("VM_M_setmousetarget: wrong destination %f !",PRVM_G_FLOAT(OFS_PARM0));
}
}
float getmousetarget
=========
*/
-void VM_M_getmousetarget(void)
+static void VM_M_getmousetarget(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_M_getmousetarget);
setkeydest(float dest)
=========
*/
-void VM_M_setkeydest(void)
+static void VM_M_setkeydest(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_M_setkeydest);
// key_dest = key_message
// break;
default:
- PRVM_ERROR("VM_M_setkeydest: wrong destination %f !", PRVM_G_FLOAT(OFS_PARM0));
+ prog->error_cmd("VM_M_setkeydest: wrong destination %f !", PRVM_G_FLOAT(OFS_PARM0));
}
}
float getkeydest
=========
*/
-void VM_M_getkeydest(void)
+static void VM_M_getkeydest(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_M_getkeydest);
vector getresolution(float number)
=========
*/
-void VM_M_getresolution(void)
+static void VM_M_getresolution(prvm_prog_t *prog)
{
int nr, fs;
VM_SAFEPARMCOUNTRANGE(1, 2, VM_getresolution);
}
}
-void VM_M_getgamedirinfo(void)
+static void VM_M_getgamedirinfo(prvm_prog_t *prog)
{
int nr, item;
VM_SAFEPARMCOUNT(2, VM_getgamedirinfo);
if(nr >= 0 && nr < fs_all_gamedirs_count)
{
if(item == 0)
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( fs_all_gamedirs[nr].name );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, fs_all_gamedirs[nr].name );
else if(item == 1)
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( fs_all_gamedirs[nr].description );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, fs_all_gamedirs[nr].description );
}
}
6 sortfield
7 sortflags
*/
-void VM_M_getserverliststat( void )
+static void VM_M_getserverliststat(prvm_prog_t *prog)
{
int type;
VM_SAFEPARMCOUNT ( 1, VM_M_getserverliststat );
PRVM_G_FLOAT ( OFS_RETURN ) = serverlist_sortflags;
return;
default:
- VM_Warning( "VM_M_getserverliststat: bad type %i!\n", type );
+ VM_Warning(prog, "VM_M_getserverliststat: bad type %i!\n", type );
}
}
resetserverlistmasks()
========================
*/
-void VM_M_resetserverlistmasks( void )
+static void VM_M_resetserverlistmasks(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_M_resetserverlistmasks);
ServerList_ResetMasks();
512 - 1024 or
========================
*/
-void VM_M_setserverlistmaskstring( void )
+static void VM_M_setserverlistmaskstring(prvm_prog_t *prog)
{
const char *str;
int masknr;
mask = &serverlist_ormasks[masknr - 512 ];
else
{
- VM_Warning( "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
+ VM_Warning(prog, "VM_M_setserverlistmaskstring: invalid mask number %i\n", masknr );
return;
}
strlcpy( mask->info.game, str, sizeof(mask->info.game) );
break;
default:
- VM_Warning( "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
+ VM_Warning(prog, "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
return;
}
512 - 1024 or
========================
*/
-void VM_M_setserverlistmasknumber( void )
+static void VM_M_setserverlistmasknumber(prvm_prog_t *prog)
{
int number;
serverlist_mask_t *mask;
mask = &serverlist_ormasks[masknr - 512 ];
else
{
- VM_Warning( "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
+ VM_Warning(prog, "VM_M_setserverlistmasknumber: invalid mask number %i\n", masknr );
return;
}
mask->info.isfavorite = number != 0;
break;
default:
- VM_Warning( "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
+ VM_Warning(prog, "VM_M_setserverlistmasknumber: Bad field number %i passed!\n", field );
return;
}
resortserverlist
========================
*/
-void VM_M_resortserverlist( void )
+static void VM_M_resortserverlist(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_M_resortserverlist);
ServerList_RebuildViewList();
string getserverliststring(float field, float hostnr)
=========
*/
-void VM_M_getserverliststring(void)
+static void VM_M_getserverliststring(prvm_prog_t *prog)
{
serverlist_entry_t *cache;
int hostnr;
cache = ServerList_GetViewEntry(hostnr);
switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
case SLIF_CNAME:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( cache->info.cname );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.cname );
break;
case SLIF_NAME:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( cache->info.name );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.name );
break;
case SLIF_QCSTATUS:
- PRVM_G_INT (OFS_RETURN ) = PRVM_SetTempString (cache->info.qcstatus );
+ PRVM_G_INT (OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.qcstatus );
break;
case SLIF_PLAYERS:
- PRVM_G_INT (OFS_RETURN ) = PRVM_SetTempString (cache->info.players );
+ PRVM_G_INT (OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.players );
break;
case SLIF_GAME:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( cache->info.game );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.game );
break;
case SLIF_MOD:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( cache->info.mod );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.mod );
break;
case SLIF_MAP:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( cache->info.map );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.map );
break;
// TODO remove this again
case 1024:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( cache->line1 );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->line1 );
break;
case 1025:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( cache->line2 );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->line2 );
break;
default:
Con_Print("VM_M_getserverliststring: bad field number passed!\n");
float getserverlistnumber(float field, float hostnr)
=========
*/
-void VM_M_getserverlistnumber(void)
+static void VM_M_getserverlistnumber(prvm_prog_t *prog)
{
serverlist_entry_t *cache;
int hostnr;
setserverlistsort(float field, float flags)
========================
*/
-void VM_M_setserverlistsort( void )
+static void VM_M_setserverlistsort(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT( 2, VM_M_setserverlistsort );
refreshserverlist()
========================
*/
-void VM_M_refreshserverlist( void )
+static void VM_M_refreshserverlist(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT( 0, VM_M_refreshserverlist );
ServerList_QueryList(false, true, false, false);
float getserverlistindexforkey(string key)
========================
*/
-void VM_M_getserverlistindexforkey( void )
+static void VM_M_getserverlistindexforkey(prvm_prog_t *prog)
{
const char *key;
VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
key = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( key );
+ VM_CheckEmptyString( prog, key );
if( !strcmp( key, "cname" ) )
PRVM_G_FLOAT( OFS_RETURN ) = SLIF_CNAME;
addwantedserverlistkey(string key)
========================
*/
-void VM_M_addwantedserverlistkey( void )
+static void VM_M_addwantedserverlistkey(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT( 1, VM_M_addwantedserverlistkey );
}
#define MSG_ALL 2 // reliable to all
#define MSG_INIT 3 // write to the init string
-sizebuf_t *VM_M_WriteDest (void)
+static sizebuf_t *VM_M_WriteDest (prvm_prog_t *prog)
{
int dest;
int destclient;
if(!sv.active)
- PRVM_ERROR("VM_M_WriteDest: game is not server (%s)", PRVM_NAME);
+ prog->error_cmd("VM_M_WriteDest: game is not server (%s)", prog->name);
dest = (int)PRVM_G_FLOAT(OFS_PARM1);
switch (dest)
case MSG_ONE:
destclient = (int) PRVM_G_FLOAT(OFS_PARM2);
if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active || !svs.clients[destclient].netconnection)
- PRVM_ERROR("VM_clientcommand: %s: invalid client !", PRVM_NAME);
+ prog->error_cmd("VM_clientcommand: %s: invalid client !", prog->name);
return &svs.clients[destclient].netconnection->message;
return &sv.signon;
default:
- PRVM_ERROR ("WriteDest: bad destination");
+ prog->error_cmd("WriteDest: bad destination");
break;
}
return NULL;
}
-void VM_M_WriteByte (void)
+static void VM_M_WriteByte (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteByte);
- MSG_WriteByte (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+ MSG_WriteByte (VM_M_WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM0));
}
-void VM_M_WriteChar (void)
+static void VM_M_WriteChar (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteChar);
- MSG_WriteChar (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+ MSG_WriteChar (VM_M_WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM0));
}
-void VM_M_WriteShort (void)
+static void VM_M_WriteShort (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteShort);
- MSG_WriteShort (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+ MSG_WriteShort (VM_M_WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM0));
}
-void VM_M_WriteLong (void)
+static void VM_M_WriteLong (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteLong);
- MSG_WriteLong (VM_M_WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM0));
+ MSG_WriteLong (VM_M_WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM0));
}
-void VM_M_WriteAngle (void)
+static void VM_M_WriteAngle (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteAngle);
- MSG_WriteAngle (VM_M_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
+ MSG_WriteAngle (VM_M_WriteDest(prog), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
}
-void VM_M_WriteCoord (void)
+static void VM_M_WriteCoord (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteCoord);
- MSG_WriteCoord (VM_M_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
+ MSG_WriteCoord (VM_M_WriteDest(prog), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
}
-void VM_M_WriteString (void)
+static void VM_M_WriteString (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteString);
- MSG_WriteString (VM_M_WriteDest(), PRVM_G_STRING(OFS_PARM0));
+ MSG_WriteString (VM_M_WriteDest(prog), PRVM_G_STRING(OFS_PARM0));
}
-void VM_M_WriteEntity (void)
+static void VM_M_WriteEntity (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_M_WriteEntity);
- MSG_WriteShort (VM_M_WriteDest(), PRVM_G_EDICTNUM(OFS_PARM0));
+ MSG_WriteShort (VM_M_WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM0));
}
/*
copyentity(entity src, entity dst)
=================
*/
-static void VM_M_copyentity (void)
+static void VM_M_copyentity (prvm_prog_t *prog)
{
prvm_edict_t *in, *out;
VM_SAFEPARMCOUNT(2,VM_M_copyentity);
}
//#66 vector() getmousepos (EXT_CSQC)
-static void VM_M_getmousepos(void)
+static void VM_M_getmousepos(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_M_getmousepos);
VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height, 0);
}
-void VM_M_crypto_getkeyfp(void)
+static void VM_M_crypto_getkeyfp(prvm_prog_t *prog)
{
lhnetaddress_t addr;
const char *s;
VM_SAFEPARMCOUNT(1,VM_M_crypto_getkeyfp);
s = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( s );
+ VM_CheckEmptyString( prog, s );
if(LHNETADDRESS_FromString(&addr, s, 26000) && Crypto_RetrieveHostKey(&addr, NULL, keyfp, sizeof(keyfp), NULL, 0, NULL))
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( keyfp );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, keyfp );
else
PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
}
-void VM_M_crypto_getidfp(void)
+static void VM_M_crypto_getidfp(prvm_prog_t *prog)
{
lhnetaddress_t addr;
const char *s;
VM_SAFEPARMCOUNT(1,VM_M_crypto_getidfp);
s = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( s );
+ VM_CheckEmptyString( prog, s );
if(LHNETADDRESS_FromString(&addr, s, 26000) && Crypto_RetrieveHostKey(&addr, NULL, NULL, 0, idfp, sizeof(idfp), NULL))
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( idfp );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, idfp );
else
PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
}
-void VM_M_crypto_getencryptlevel(void)
+static void VM_M_crypto_getencryptlevel(prvm_prog_t *prog)
{
lhnetaddress_t addr;
const char *s;
int aeslevel;
+ char vabuf[1024];
VM_SAFEPARMCOUNT(1,VM_M_crypto_getencryptlevel);
s = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( s );
+ VM_CheckEmptyString( prog, s );
if(LHNETADDRESS_FromString(&addr, s, 26000) && Crypto_RetrieveHostKey(&addr, NULL, NULL, 0, NULL, 0, &aeslevel))
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(aeslevel ? va("%d AES128", aeslevel) : "0");
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, aeslevel ? va(vabuf, sizeof(vabuf), "%d AES128", aeslevel) : "0");
else
PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
}
-void VM_M_crypto_getmykeyfp(void)
+static void VM_M_crypto_getmykeyfp(prvm_prog_t *prog)
{
int i;
char keyfp[FP64_SIZE + 1];
switch(Crypto_RetrieveLocalKey(i, keyfp, sizeof(keyfp), NULL, 0))
{
case -1:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString("");
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, "");
break;
case 0:
PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
break;
default:
case 1:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(keyfp);
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, keyfp);
break;
}
}
-void VM_M_crypto_getmyidfp(void)
+static void VM_M_crypto_getmyidfp(prvm_prog_t *prog)
{
int i;
char idfp[FP64_SIZE + 1];
switch(Crypto_RetrieveLocalKey(i, NULL, 0, idfp, sizeof(idfp)))
{
case -1:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString("");
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, "");
break;
case 0:
PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
break;
default:
case 1:
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(idfp);
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, idfp);
break;
}
}
VM_M_crypto_getencryptlevel, // #635 string(string addr) crypto_getencryptlevel
VM_M_crypto_getmykeyfp, // #636 string(float addr) crypto_getmykeyfp
VM_M_crypto_getmyidfp, // #637 string(float addr) crypto_getmyidfp
+NULL, // #638
+VM_digest_hex, // #639
NULL
};
const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
-void VM_M_Cmd_Init(void)
+void MVM_init_cmd(prvm_prog_t *prog)
{
r_refdef_scene_t *scene;
- VM_Cmd_Init();
- VM_Polygons_Reset();
+ VM_Cmd_Init(prog);
+ VM_Polygons_Reset(prog);
scene = R_GetScenePointer( RST_MENU );
scene->ambient = 32.0f;
}
-void VM_M_Cmd_Reset(void)
+void MVM_reset_cmd(prvm_prog_t *prog)
{
// note: the menu's render entities are automatically freed when the prog's pool is freed
//VM_Cmd_Init();
- VM_Cmd_Reset();
- VM_Polygons_Reset();
+ VM_Cmd_Reset(prog);
+ VM_Polygons_Reset(prog);
}
*/
#include "quakedef.h"
+#include "thread.h"
#include "lhnet.h"
// for secure rcon authentication
{0, "sv_qwmasterextra2", "asgaard.morphos-team.net:27000", "Global master server. (admin: unknown)"},
{0, "sv_qwmasterextra3", "qwmaster.ocrana.de:27000", "German master server. (admin: unknown)"},
{0, "sv_qwmasterextra4", "masterserver.exhale.de:27000", "German master server. (admin: unknown)"},
- {0, "sv_qwmasterextra5", "kubus.rulez.pl:27000", "Poland master server. (admin: unknown)"},
+ {0, "sv_qwmasterextra5", "qwmaster.fodquake.net:27000", "Global master server. (admin: unknown)"},
{0, NULL, NULL, NULL}
};
static double nextheartbeattime = 0;
-sizebuf_t net_message;
-static unsigned char net_message_buf[NET_MAXMESSAGE];
+sizebuf_t cl_message;
+sizebuf_t sv_message;
+static unsigned char cl_message_buf[NET_MAXMESSAGE];
+static unsigned char sv_message_buf[NET_MAXMESSAGE];
+char cl_readstring[MAX_INPUTLINE];
+char sv_readstring[MAX_INPUTLINE];
cvar_t net_messagetimeout = {0, "net_messagetimeout","300", "drops players who have not sent any packets for this many seconds"};
cvar_t net_connecttimeout = {0, "net_connecttimeout","15", "after requesting a connection, the client must reply within this many seconds or be dropped (cuts down on connect floods). Must be above 10 seconds."};
extern cvar_t rcon_secure;
extern cvar_t rcon_secure_challengetimeout;
-/* statistic counters */
-static int packetsSent = 0;
-static int packetsReSent = 0;
-static int packetsReceived = 0;
-static int receivedDuplicateCount = 0;
-static int droppedDatagrams = 0;
-
-static int unreliableMessagesSent = 0;
-static int unreliableMessagesReceived = 0;
-static int reliableMessagesSent = 0;
-static int reliableMessagesReceived = 0;
-
double masterquerytime = -1000;
int masterquerycount = 0;
int masterreplycount = 0;
/// flooding in (which would make a mess of the ping times)
static double serverlist_querywaittime = 0;
-static unsigned char sendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
-static unsigned char readbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
-static unsigned char cryptosendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE+CRYPTO_HEADERSIZE];
-static unsigned char cryptoreadbuffer[NET_HEADERSIZE+NET_MAXMESSAGE+CRYPTO_HEADERSIZE];
-
static int cl_numsockets;
static lhnetsocket_t *cl_sockets[16];
static int sv_numsockets;
netconn_t *netconn_list = NULL;
mempool_t *netconn_mempool = NULL;
+void *netconn_mutex = NULL;
cvar_t cl_netport = {0, "cl_port", "0", "forces client to use chosen port number if not 0"};
cvar_t sv_netport = {0, "port", "26000", "server port for players to connect to"};
!(
gameversion_min.integer >= 0 // min/max range set by user/mod?
&& gameversion_max.integer >= 0
- && gameversion_min.integer >= entry->info.gameversion // version of server in min/max range?
- && gameversion_max.integer <= entry->info.gameversion
+ && gameversion_min.integer <= entry->info.gameversion // version of server in min/max range?
+ && gameversion_max.integer >= entry->info.gameversion
)
)
return;
int NetConn_Read(lhnetsocket_t *mysocket, void *data, int maxlength, lhnetaddress_t *peeraddress)
{
- int length = LHNET_Read(mysocket, data, maxlength, peeraddress);
+ int length;
int i;
+ if (mysocket->address.addresstype == LHNETADDRESSTYPE_LOOP && netconn_mutex)
+ Thread_LockMutex(netconn_mutex);
+ length = LHNET_Read(mysocket, data, maxlength, peeraddress);
+ if (mysocket->address.addresstype == LHNETADDRESSTYPE_LOOP && netconn_mutex)
+ Thread_UnlockMutex(netconn_mutex);
if (length == 0)
return 0;
if (cl_netpacketloss_receive.integer)
for (i = 0;i < cl_numsockets;i++)
if (cl_sockets[i] == mysocket && (rand() % 100) < cl_netpacketloss_send.integer)
return length;
+ if (mysocket->address.addresstype == LHNETADDRESSTYPE_LOOP && netconn_mutex)
+ Thread_LockMutex(netconn_mutex);
ret = LHNET_Write(mysocket, data, length, peeraddress);
+ if (mysocket->address.addresstype == LHNETADDRESSTYPE_LOOP && netconn_mutex)
+ Thread_UnlockMutex(netconn_mutex);
if (developer_networking.integer)
{
char addressstring[128], addressstring2[128];
int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, qboolean quakesignon_suppressreliables)
{
int totallen = 0;
+ unsigned char sendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
+ unsigned char cryptosendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE+CRYPTO_HEADERSIZE];
// if this packet was supposedly choked, but we find ourselves sending one
// anyway, make sure the size counting starts at zero
NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress);
- packetsSent++;
- unreliableMessagesSent++;
+ conn->packetsSent++;
+ conn->unreliableMessagesSent++;
totallen += packetLen + 28;
}
if (sendme && NetConn_Write(conn->mysocket, sendme, sendmelen, &conn->peeraddress) == (int)sendmelen)
{
conn->lastSendTime = realtime;
- packetsReSent++;
+ conn->packetsReSent++;
}
totallen += sendmelen + 28;
NetConn_Write(conn->mysocket, sendme, sendmelen, &conn->peeraddress);
conn->lastSendTime = realtime;
- packetsSent++;
- reliableMessagesSent++;
+ conn->packetsSent++;
+ conn->reliableMessagesSent++;
totallen += sendmelen + 28;
}
if(sendme)
NetConn_Write(conn->mysocket, sendme, sendmelen, &conn->peeraddress);
- packetsSent++;
- unreliableMessagesSent++;
+ conn->packetsSent++;
+ conn->unreliableMessagesSent++;
totallen += sendmelen + 28;
}
LHNET_CloseSocket(cl_sockets[cl_numsockets - 1]);
}
-void NetConn_OpenClientPort(const char *addressstring, lhnetaddresstype_t addresstype, int defaultport)
+static void NetConn_OpenClientPort(const char *addressstring, lhnetaddresstype_t addresstype, int defaultport)
{
lhnetaddress_t address;
lhnetsocket_t *s;
{
int port;
NetConn_CloseClientPorts();
+
+ SV_LockThreadMutex(); // FIXME recursive?
+ Crypto_LoadKeys(); // client sockets
+ SV_UnlockThreadMutex();
+
port = bound(0, cl_netport.integer, 65535);
if (cl_netport.integer != port)
Cvar_SetValueQuick(&cl_netport, port);
LHNET_CloseSocket(sv_sockets[sv_numsockets - 1]);
}
-qboolean NetConn_OpenServerPort(const char *addressstring, lhnetaddresstype_t addresstype, int defaultport, int range)
+static qboolean NetConn_OpenServerPort(const char *addressstring, lhnetaddresstype_t addresstype, int defaultport, int range)
{
lhnetaddress_t address;
lhnetsocket_t *s;
{
int port;
NetConn_CloseServerPorts();
+
+ SV_LockThreadMutex(); // FIXME recursive?
+ Crypto_LoadKeys(); // server sockets
+ SV_UnlockThreadMutex();
+
NetConn_UpdateSockets();
port = bound(0, sv_netport.integer, 65535);
if (port == 0)
static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, size_t length, protocolversion_t protocol, double newtimeout)
{
int originallength = length;
+ unsigned char sendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
+ unsigned char cryptosendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE+CRYPTO_HEADERSIZE];
+ unsigned char cryptoreadbuffer[NET_HEADERSIZE+NET_MAXMESSAGE+CRYPTO_HEADERSIZE];
if (length < 8)
return 0;
length -= 2;
}
- packetsReceived++;
+ conn->packetsReceived++;
reliable_message = (sequence >> 31) & 1;
reliable_ack = (sequence_ack >> 31) & 1;
sequence &= ~(1<<31);
count = sequence - (conn->qw.incoming_sequence + 1);
if (count > 0)
{
- droppedDatagrams += count;
+ conn->droppedDatagrams += count;
//Con_DPrintf("Dropped %u datagram(s)\n", count);
while (count--)
{
{
// received, now we will be able to send another reliable message
conn->sendMessageLength = 0;
- reliableMessagesReceived++;
+ conn->reliableMessagesReceived++;
}
conn->qw.incoming_sequence = sequence;
if (conn == cls.netcon)
conn->qw.incoming_reliable_sequence ^= 1;
conn->lastMessageTime = realtime;
conn->timeout = realtime + newtimeout;
- unreliableMessagesReceived++;
- SZ_Clear(&net_message);
- SZ_Write(&net_message, data, length);
- MSG_BeginReading();
+ conn->unreliableMessagesReceived++;
+ if (conn == cls.netcon)
+ {
+ SZ_Clear(&cl_message);
+ SZ_Write(&cl_message, data, length);
+ MSG_BeginReading(&cl_message);
+ }
+ else
+ {
+ SZ_Clear(&sv_message);
+ SZ_Write(&sv_message, data, length);
+ MSG_BeginReading(&sv_message);
+ }
return 2;
}
else
if (!(flags & NETFLAG_CTL) && qlength == length)
{
sequence = BuffBigLong(data + 4);
- packetsReceived++;
+ conn->packetsReceived++;
data += 8;
length -= 8;
if (flags & NETFLAG_UNRELIABLE)
if (sequence > conn->nq.unreliableReceiveSequence)
{
count = sequence - conn->nq.unreliableReceiveSequence;
- droppedDatagrams += count;
+ conn->droppedDatagrams += count;
//Con_DPrintf("Dropped %u datagram(s)\n", count);
while (count--)
{
conn->nq.unreliableReceiveSequence = sequence + 1;
conn->lastMessageTime = realtime;
conn->timeout = realtime + newtimeout;
- unreliableMessagesReceived++;
+ conn->unreliableMessagesReceived++;
if (length > 0)
{
- SZ_Clear(&net_message);
- SZ_Write(&net_message, data, length);
- MSG_BeginReading();
+ if (conn == cls.netcon)
+ {
+ SZ_Clear(&cl_message);
+ SZ_Write(&cl_message, data, length);
+ MSG_BeginReading(&cl_message);
+ }
+ else
+ {
+ SZ_Clear(&sv_message);
+ SZ_Write(&sv_message, data, length);
+ MSG_BeginReading(&sv_message);
+ }
return 2;
}
}
if (sendme && NetConn_Write(conn->mysocket, sendme, sendmelen, &conn->peeraddress) == (int)sendmelen)
{
conn->lastSendTime = realtime;
- packetsSent++;
+ conn->packetsSent++;
}
}
else
}
if (flags & NETFLAG_EOM)
{
- reliableMessagesReceived++;
+ conn->reliableMessagesReceived++;
length = conn->receiveMessageLength;
conn->receiveMessageLength = 0;
if (length > 0)
{
- SZ_Clear(&net_message);
- SZ_Write(&net_message, conn->receiveMessage, length);
- MSG_BeginReading();
+ if (conn == cls.netcon)
+ {
+ SZ_Clear(&cl_message);
+ SZ_Write(&cl_message, conn->receiveMessage, length);
+ MSG_BeginReading(&cl_message);
+ }
+ else
+ {
+ SZ_Clear(&sv_message);
+ SZ_Write(&sv_message, conn->receiveMessage, length);
+ MSG_BeginReading(&sv_message);
+ }
return 2;
}
}
}
else
- receivedDuplicateCount++;
+ conn->receivedDuplicateCount++;
return 1;
}
}
return 0;
}
-void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, protocolversion_t initialprotocol)
+static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, protocolversion_t initialprotocol)
{
crypto_t *crypto;
cls.connect_trying = false;
CL_Disconnect();
// if we're connecting to a remote server, shut down any local server
if (LHNETADDRESS_GetAddressType(peeraddress) != LHNETADDRESSTYPE_LOOP && sv.active)
+ {
+ SV_LockThreadMutex();
Host_ShutdownServer ();
+ SV_UnlockThreadMutex();
+ }
// allocate a net connection to keep track of things
cls.netcon = NetConn_Open(mysocket, peeraddress);
crypto = &cls.crypto;
!(
gameversion_min.integer >= 0 // min/max range set by user/mod?
&& gameversion_max.integer >= 0
- && gameversion_min.integer >= info->gameversion // version of server in min/max range?
- && gameversion_max.integer <= info->gameversion
+ && gameversion_min.integer <= info->gameversion // version of server in min/max range?
+ && gameversion_max.integer >= info->gameversion
)
) ? '1' : '4',
info->mod, info->map);
{
#ifdef WHY_JUST_WHY
const char *ifname;
+ char ifnamebuf[16];
/// \TODO: make some basic checks of the IP address (broadcast, ...)
- ifname = LHNETADDRESS_GetInterfaceName(senderaddress);
+ ifname = LHNETADDRESS_GetInterfaceName(senderaddress, ifnamebuf, sizeof(ifnamebuf));
if (ifname != NULL)
{
dpsnprintf (ipstring, sizeof (ipstring), "[%x:%x:%x:%x:%x:%x:%x:%x%%%s]:%hu",
char stringbuf[16384];
char senddata[NET_HEADERSIZE+NET_MAXMESSAGE+CRYPTO_HEADERSIZE];
size_t sendlength;
+ char infostringvalue[MAX_INPUTLINE];
+ char vabuf[1024];
// quakeworld ingame packet
fromserver = cls.netcon && mysocket == cls.netcon->mysocket && !LHNETADDRESS_Compare(&cls.netcon->peeraddress, peeraddress);
// update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
// TODO: add userinfo stuff here instead of using NQ commands?
- NetConn_WriteString(mysocket, va("\377\377\377\377connect\\protocol\\darkplaces 3\\protocols\\%s%s\\challenge\\%s", protocolnames, cls.connect_userinfo, string + 10), peeraddress);
+ NetConn_WriteString(mysocket, va(vabuf, sizeof(vabuf), "\377\377\377\377connect\\protocol\\darkplaces 3\\protocols\\%s%s\\challenge\\%s", protocolnames, cls.connect_userinfo, string + 10), peeraddress);
return true;
}
if (length == 6 && !memcmp(string, "accept", 6) && cls.connect_trying)
else
Con_Printf("statusResponse without players block?\n");
- if ((s = SearchInfostring(string, "gamename" )) != NULL) strlcpy(info->game, s, sizeof (info->game));
- if ((s = SearchInfostring(string, "modname" )) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));
- if ((s = SearchInfostring(string, "mapname" )) != NULL) strlcpy(info->map , s, sizeof (info->map ));
- if ((s = SearchInfostring(string, "hostname" )) != NULL) strlcpy(info->name, s, sizeof (info->name));
- if ((s = SearchInfostring(string, "protocol" )) != NULL) info->protocol = atoi(s);
- if ((s = SearchInfostring(string, "clients" )) != NULL) info->numplayers = atoi(s);
- if ((s = SearchInfostring(string, "bots" )) != NULL) info->numbots = atoi(s);
- if ((s = SearchInfostring(string, "sv_maxclients")) != NULL) info->maxplayers = atoi(s);
- if ((s = SearchInfostring(string, "gameversion" )) != NULL) info->gameversion = atoi(s);
- if ((s = SearchInfostring(string, "qcstatus" )) != NULL) strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
- if (p != NULL) strlcpy(info->players, p, sizeof(info->players));
+ if ((s = InfoString_GetValue(string, "gamename" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->game, s, sizeof (info->game));
+ if ((s = InfoString_GetValue(string, "modname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));
+ if ((s = InfoString_GetValue(string, "mapname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->map , s, sizeof (info->map ));
+ if ((s = InfoString_GetValue(string, "hostname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->name, s, sizeof (info->name));
+ if ((s = InfoString_GetValue(string, "protocol" , infostringvalue, sizeof(infostringvalue))) != NULL) info->protocol = atoi(s);
+ if ((s = InfoString_GetValue(string, "clients" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numplayers = atoi(s);
+ if ((s = InfoString_GetValue(string, "bots" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numbots = atoi(s);
+ if ((s = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);
+ if ((s = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);
+ if ((s = InfoString_GetValue(string, "qcstatus" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
+ if (p != NULL) strlcpy(info->players, p, sizeof(info->players));
info->numhumans = info->numplayers - max(0, info->numbots);
info->freeslots = info->maxplayers - info->numplayers;
info->maxplayers = 0;
info->gameversion = 0;
- if ((s = SearchInfostring(string, "gamename" )) != NULL) strlcpy(info->game, s, sizeof (info->game));
- if ((s = SearchInfostring(string, "modname" )) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));
- if ((s = SearchInfostring(string, "mapname" )) != NULL) strlcpy(info->map , s, sizeof (info->map ));
- if ((s = SearchInfostring(string, "hostname" )) != NULL) strlcpy(info->name, s, sizeof (info->name));
- if ((s = SearchInfostring(string, "protocol" )) != NULL) info->protocol = atoi(s);
- if ((s = SearchInfostring(string, "clients" )) != NULL) info->numplayers = atoi(s);
- if ((s = SearchInfostring(string, "bots" )) != NULL) info->numbots = atoi(s);
- if ((s = SearchInfostring(string, "sv_maxclients")) != NULL) info->maxplayers = atoi(s);
- if ((s = SearchInfostring(string, "gameversion" )) != NULL) info->gameversion = atoi(s);
- if ((s = SearchInfostring(string, "qcstatus" )) != NULL) strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
+ if ((s = InfoString_GetValue(string, "gamename" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->game, s, sizeof (info->game));
+ if ((s = InfoString_GetValue(string, "modname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));
+ if ((s = InfoString_GetValue(string, "mapname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->map , s, sizeof (info->map ));
+ if ((s = InfoString_GetValue(string, "hostname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->name, s, sizeof (info->name));
+ if ((s = InfoString_GetValue(string, "protocol" , infostringvalue, sizeof(infostringvalue))) != NULL) info->protocol = atoi(s);
+ if ((s = InfoString_GetValue(string, "clients" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numplayers = atoi(s);
+ if ((s = InfoString_GetValue(string, "bots" , infostringvalue, sizeof(infostringvalue))) != NULL) info->numbots = atoi(s);
+ if ((s = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);
+ if ((s = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);
+ if ((s = InfoString_GetValue(string, "qcstatus" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
info->numhumans = info->numplayers - max(0, info->numbots);
info->freeslots = info->maxplayers - info->numplayers;
cls.qw_qport = qport.integer;
// update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command)
InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2);
- NetConn_WriteString(mysocket, va("\377\377\377\377connect %i %i %i \"%s%s\"\n", 28, cls.qw_qport, atoi(string + 1), cls.userinfo, cls.connect_userinfo), peeraddress);
+ NetConn_WriteString(mysocket, va(vabuf, sizeof(vabuf), "\377\377\377\377connect %i %i %i \"%s%s\"\n", 28, cls.qw_qport, atoi(string + 1), cls.userinfo, cls.connect_userinfo), peeraddress);
return true;
}
if (length >= 1 && string[0] == 'j' && cls.connect_trying)
info = &serverlist_cache[n].info;
strlcpy(info->game, "QuakeWorld", sizeof(info->game));
- if ((s = SearchInfostring(string, "*gamedir" )) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));else info->mod[0] = 0;
- if ((s = SearchInfostring(string, "map" )) != NULL) strlcpy(info->map , s, sizeof (info->map ));else info->map[0] = 0;
- if ((s = SearchInfostring(string, "hostname" )) != NULL) strlcpy(info->name, s, sizeof (info->name));else info->name[0] = 0;
+ if ((s = InfoString_GetValue(string, "*gamedir" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->mod , s, sizeof (info->mod ));else info->mod[0] = 0;
+ if ((s = InfoString_GetValue(string, "map" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->map , s, sizeof (info->map ));else info->map[0] = 0;
+ if ((s = InfoString_GetValue(string, "hostname" , infostringvalue, sizeof(infostringvalue))) != NULL) strlcpy(info->name, s, sizeof (info->name));else info->name[0] = 0;
info->protocol = 0;
info->numplayers = 0; // updated below
info->numhumans = 0; // updated below
- if ((s = SearchInfostring(string, "maxclients" )) != NULL) info->maxplayers = atoi(s);else info->maxplayers = 0;
- if ((s = SearchInfostring(string, "gameversion" )) != NULL) info->gameversion = atoi(s);else info->gameversion = 0;
+ if ((s = InfoString_GetValue(string, "maxclients" , infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);else info->maxplayers = 0;
+ if ((s = InfoString_GetValue(string, "gameversion" , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);else info->gameversion = 0;
// count active players on server
// (we could gather more info, but we're just after the number)
data += 4;
length -= 4;
- SZ_Clear(&net_message);
- SZ_Write(&net_message, data, length);
- MSG_BeginReading();
- c = MSG_ReadByte();
+ SZ_Clear(&cl_message);
+ SZ_Write(&cl_message, data, length);
+ MSG_BeginReading(&cl_message);
+ c = MSG_ReadByte(&cl_message);
switch (c)
{
case CCREP_ACCEPT:
{
lhnetaddress_t clientportaddress;
clientportaddress = *peeraddress;
- LHNETADDRESS_SetPort(&clientportaddress, MSG_ReadLong());
+ LHNETADDRESS_SetPort(&clientportaddress, MSG_ReadLong(&cl_message));
// extra ProQuake stuff
if (length >= 6)
- cls.proquake_servermod = MSG_ReadByte(); // MOD_PROQUAKE
+ cls.proquake_servermod = MSG_ReadByte(&cl_message); // MOD_PROQUAKE
else
cls.proquake_servermod = 0;
if (length >= 7)
- cls.proquake_serverversion = MSG_ReadByte(); // version * 10
+ cls.proquake_serverversion = MSG_ReadByte(&cl_message); // version * 10
else
cls.proquake_serverversion = 0;
if (length >= 8)
- cls.proquake_serverflags = MSG_ReadByte(); // flags (mainly PQF_CHEATFREE)
+ cls.proquake_serverflags = MSG_ReadByte(&cl_message); // flags (mainly PQF_CHEATFREE)
else
cls.proquake_serverflags = 0;
if (cls.proquake_servermod == 1)
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: received CCREP_REJECT from %s.\n", addressstring2);
cls.connect_trying = false;
- M_Update_Return_Reason((char *)MSG_ReadString());
+ M_Update_Return_Reason((char *)MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
break;
case CCREP_SERVER_INFO:
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: received CCREP_SERVER_INFO from %s.\n", addressstring2);
// LordHavoc: because the quake server may report weird addresses
// we just ignore it and keep the real address
- MSG_ReadString();
+ MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
// search the cache for this server and update it
n = NetConn_ClientParsePacket_ServerList_ProcessReply(addressstring2);
if (n < 0)
info = &serverlist_cache[n].info;
strlcpy(info->game, "Quake", sizeof(info->game));
strlcpy(info->mod , "", sizeof(info->mod)); // mod name is not specified
- strlcpy(info->name, MSG_ReadString(), sizeof(info->name));
- strlcpy(info->map , MSG_ReadString(), sizeof(info->map));
- info->numplayers = MSG_ReadByte();
- info->maxplayers = MSG_ReadByte();
- info->protocol = MSG_ReadByte();
+ strlcpy(info->name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->name));
+ strlcpy(info->map , MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->map));
+ info->numplayers = MSG_ReadByte(&cl_message);
+ info->maxplayers = MSG_ReadByte(&cl_message);
+ info->protocol = MSG_ReadByte(&cl_message);
NetConn_ClientParsePacket_ServerList_UpdateCache(n);
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: received CCREP_RCON from %s.\n", addressstring2);
- Con_Printf("%s\n", MSG_ReadString());
+ Con_Printf("%s\n", MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
break;
case CCREP_PLAYER_INFO:
// we got a CCREP_PLAYER_INFO??
default:
break;
}
- SZ_Clear(&net_message);
+ SZ_Clear(&cl_message);
// we may not have liked the packet, but it was a valid control
// packet, so we're done processing this packet now
return true;
{
int i, length;
lhnetaddress_t peeraddress;
+ unsigned char readbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
NetConn_UpdateSockets();
if (cls.connect_trying && cls.connect_nextsendtime < realtime)
{
// try challenge first (newer DP server or QW)
NetConn_WriteString(cls.connect_mysocket, "\377\377\377\377getchallenge", &cls.connect_address);
// then try netquake as a fallback (old server, or netquake)
- SZ_Clear(&net_message);
+ SZ_Clear(&cl_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREQ_CONNECT);
- MSG_WriteString(&net_message, "QUAKE");
- MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
+ MSG_WriteLong(&cl_message, 0);
+ MSG_WriteByte(&cl_message, CCREQ_CONNECT);
+ MSG_WriteString(&cl_message, "QUAKE");
+ MSG_WriteByte(&cl_message, NET_PROTOCOL_VERSION);
// extended proquake stuff
- MSG_WriteByte(&net_message, 1); // mod = MOD_PROQUAKE
+ MSG_WriteByte(&cl_message, 1); // mod = MOD_PROQUAKE
// this version matches ProQuake 3.40, the first version to support
// the NAT fix, and it only supports the NAT fix for ProQuake 3.40 or
// higher clients, so we pretend we are that version...
- MSG_WriteByte(&net_message, 34); // version * 10
- MSG_WriteByte(&net_message, 0); // flags
- MSG_WriteLong(&net_message, 0); // password
+ MSG_WriteByte(&cl_message, 34); // version * 10
+ MSG_WriteByte(&cl_message, 0); // flags
+ MSG_WriteLong(&cl_message, 0); // password
// write the packetsize now...
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(cls.connect_mysocket, net_message.data, net_message.cursize, &cls.connect_address);
- SZ_Clear(&net_message);
+ StoreBigLong(cl_message.data, NETFLAG_CTL | (cl_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(cls.connect_mysocket, cl_message.data, cl_message.cursize, &cls.connect_address);
+ SZ_Clear(&cl_message);
}
for (i = 0;i < cl_numsockets;i++)
{
{
Con_Print("Connection timed out\n");
CL_Disconnect();
+ SV_LockThreadMutex();
Host_ShutdownServer ();
+ SV_UnlockThreadMutex();
}
}
/// (div0) build the full response only if possible; better a getinfo response than no response at all if getstatus won't fit
static qboolean NetConn_BuildStatusResponse(const char* challenge, char* out_msg, size_t out_size, qboolean fullstatus)
{
+ prvm_prog_t *prog = SVVM_prog;
char qcstatus[256];
unsigned int nb_clients = 0, nb_bots = 0, i;
int length;
const char *crypto_idstring;
const char *str;
- SV_VM_Begin();
-
// How many clients are there?
for (i = 0;i < (unsigned int)svs.maxclients;i++)
{
}
*qcstatus = 0;
- str = PRVM_GetString(PRVM_serverglobalstring(worldstatus));
+ str = PRVM_GetString(prog, PRVM_serverglobalstring(worldstatus));
if(str && *str)
{
char *p;
const char *q;
p = qcstatus;
- for(q = str; *q && p - qcstatus < (ptrdiff_t)(sizeof(qcstatus)) - 1; ++q)
+ for(q = str; *q && (size_t)(p - qcstatus) < (sizeof(qcstatus) - 1); ++q)
if(*q != '\\' && *q != '\n')
*p++ = *q;
*p = 0;
*qcstatus = 0;
ed = PRVM_EDICT_NUM(i + 1);
- str = PRVM_GetString(PRVM_serveredictstring(ed, clientstatus));
+ str = PRVM_GetString(prog, PRVM_serveredictstring(ed, clientstatus));
if(str && *str)
{
char *p;
}
}
- SV_VM_End();
return true;
bad:
- SV_VM_End();
return false;
}
typedef qboolean (*rcon_matchfunc_t) (lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen);
-qboolean hmac_mdfour_time_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
+static qboolean hmac_mdfour_time_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
{
char mdfourbuf[16];
long t1, t2;
return !memcmp(mdfourbuf, hash, 16);
}
-qboolean hmac_mdfour_challenge_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
+static qboolean hmac_mdfour_challenge_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
{
char mdfourbuf[16];
int i;
return true;
}
-qboolean plaintext_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
+static qboolean plaintext_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen)
{
return !strcmp(password, hash);
}
/// returns a string describing the user level, or NULL for auth failure
-const char *RCon_Authenticate(lhnetaddress_t *peeraddress, const char *password, const char *s, const char *endpos, rcon_matchfunc_t comparator, const char *cs, int cslen)
+static const char *RCon_Authenticate(lhnetaddress_t *peeraddress, const char *password, const char *s, const char *endpos, rcon_matchfunc_t comparator, const char *cs, int cslen)
{
const char *text, *userpass_start, *userpass_end, *userpass_startpass;
static char buf[MAX_INPUTLINE];
qboolean hasquotes;
qboolean restricted = false;
qboolean have_usernames = false;
+ char vabuf[1024];
userpass_start = rcon_password.string;
while((userpass_end = strchr(userpass_start, ' ')))
{
if(!strcmp(com_token, s))
goto match;
- if(!memcmp(va("%s ", com_token), s, strlen(com_token) + 1))
+ if(!memcmp(va(vabuf, sizeof(vabuf), "%s ", com_token), s, strlen(com_token) + 1))
goto match;
}
}
allow:
userpass_startpass = strchr(userpass_start, ':');
if(have_usernames && userpass_startpass && userpass_startpass < userpass_end)
- return va("%srcon (username %.*s)", restricted ? "restricted " : "", (int)(userpass_startpass-userpass_start), userpass_start);
+ return va(vabuf, sizeof(vabuf), "%srcon (username %.*s)", restricted ? "restricted " : "", (int)(userpass_startpass-userpass_start), userpass_start);
- return va("%srcon", restricted ? "restricted " : "");
+ return va(vabuf, sizeof(vabuf), "%srcon", restricted ? "restricted " : "");
}
-void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const char *addressstring2, const char *userlevel, const char *s, const char *endpos, qboolean proquakeprotocol)
+static void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const char *addressstring2, const char *userlevel, const char *s, const char *endpos, qboolean proquakeprotocol)
{
if(userlevel)
{
if(l)
{
client_t *host_client_save = host_client;
- Cmd_ExecuteString(s, src_command);
+ Cmd_ExecuteString(s, src_command, true);
host_client = host_client_save;
// in case it is a command that changes host_client (like restart)
}
}
}
-extern void SV_SendServerinfo (client_t *client);
static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress)
{
int i, ret, clientnum, best;
double besttime;
client_t *client;
char *s, *string, response[1400], addressstring2[128];
- static char stringbuf[16384];
+ static char stringbuf[16384]; // server only
qboolean islocal = (LHNETADDRESS_GetAddressType(peeraddress) == LHNETADDRESSTYPE_LOOP);
char senddata[NET_HEADERSIZE+NET_MAXMESSAGE+CRYPTO_HEADERSIZE];
size_t sendlength, response_len;
+ char infostringvalue[MAX_INPUTLINE];
+ char vabuf[1024];
if (!sv.active)
return false;
}
else
{
- if ((s = SearchInfostring(string, "challenge")))
+ if ((s = InfoString_GetValue(string, "challenge", infostringvalue, sizeof(infostringvalue))))
{
// validate the challenge
for (i = 0;i < MAX_CHALLENGES;i++)
}
}
- if((s = SearchInfostring(string, "message")))
+ if((s = InfoString_GetValue(string, "message", infostringvalue, sizeof(infostringvalue))))
Con_DPrintf("Connecting client %s sent us the message: %s\n", addressstring2, s);
if(!(islocal || sv_public.integer > -2))
{
if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending \"reject %s\" to %s.\n", sv_public_rejectreason.string, addressstring2);
- NetConn_WriteString(mysocket, va("\377\377\377\377reject %s", sv_public_rejectreason.string), peeraddress);
+ NetConn_WriteString(mysocket, va(vabuf, sizeof(vabuf), "\377\377\377\377reject %s", sv_public_rejectreason.string), peeraddress);
return true;
}
// check engine protocol
- if(!(s = SearchInfostring(string, "protocol")) || strcmp(s, "darkplaces 3"))
+ if(!(s = InfoString_GetValue(string, "protocol", infostringvalue, sizeof(infostringvalue))) || strcmp(s, "darkplaces 3"))
{
if (developer_extra.integer)
Con_Printf("Datagram_ParseConnectionless: sending \"reject Wrong game protocol.\" to %s.\n", addressstring2);
NetConn_WriteString(mysocket, "\377\377\377\377accept", peeraddress);
if(crypto && crypto->authenticated)
Crypto_ServerFinishInstance(&client->netconnection->crypto, crypto);
- SV_VM_Begin();
SV_SendServerinfo(client);
- SV_VM_End();
}
else
{
// now set up the client
if(crypto && crypto->authenticated)
Crypto_ServerFinishInstance(&conn->crypto, crypto);
- SV_VM_Begin();
SV_ConnectClient(clientnum, conn);
- SV_VM_End();
NetConn_Heartbeat(1);
return true;
}
const char *protocolname;
data += 4;
length -= 4;
- SZ_Clear(&net_message);
- SZ_Write(&net_message, data, length);
- MSG_BeginReading();
- c = MSG_ReadByte();
+ SZ_Clear(&sv_message);
+ SZ_Write(&sv_message, data, length);
+ MSG_BeginReading(&sv_message);
+ c = MSG_ReadByte(&sv_message);
switch (c)
{
case CCREQ_CONNECT:
{
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"%s\" to %s.\n", sv_public_rejectreason.string, addressstring2);
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_REJECT);
- MSG_WriteString(&net_message, va("%s\n", sv_public_rejectreason.string));
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_REJECT);
+ MSG_WriteString(&sv_message, va(vabuf, sizeof(vabuf), "%s\n", sv_public_rejectreason.string));
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
break;
}
- protocolname = MSG_ReadString();
- protocolnumber = MSG_ReadByte();
+ protocolname = MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring));
+ protocolnumber = MSG_ReadByte(&sv_message);
if (strcmp(protocolname, "QUAKE") || protocolnumber != NET_PROTOCOL_VERSION)
{
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Incompatible version.\" to %s.\n", addressstring2);
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_REJECT);
- MSG_WriteString(&net_message, "Incompatible version.\n");
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_REJECT);
+ MSG_WriteString(&sv_message, "Incompatible version.\n");
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
break;
}
// send a reply
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: sending duplicate CCREP_ACCEPT to %s.\n", addressstring2);
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_ACCEPT);
- MSG_WriteLong(&net_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(client->netconnection->mysocket)));
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_ACCEPT);
+ MSG_WriteLong(&sv_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(client->netconnection->mysocket)));
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
// if client is already spawned, re-send the
// serverinfo message as they'll need it to play
if (client->spawned)
- {
- SV_VM_Begin();
SV_SendServerinfo(client);
- SV_VM_End();
- }
return true;
}
}
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2);
// send back the info about the server connection
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_ACCEPT);
- MSG_WriteLong(&net_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(conn->mysocket)));
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_ACCEPT);
+ MSG_WriteLong(&sv_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(conn->mysocket)));
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
// now set up the client struct
- SV_VM_Begin();
SV_ConnectClient(clientnum, conn);
- SV_VM_End();
NetConn_Heartbeat(1);
return true;
}
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Server is full.\" to %s.\n", addressstring2);
// no room; try to let player know
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_REJECT);
- MSG_WriteString(&net_message, "Server is full.\n");
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_REJECT);
+ MSG_WriteString(&sv_message, "Server is full.\n");
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
break;
case CCREQ_SERVER_INFO:
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2);
if(!(islocal || sv_public.integer > -1))
break;
- if (sv.active && !strcmp(MSG_ReadString(), "QUAKE"))
+ if (sv.active && !strcmp(MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)), "QUAKE"))
{
int numclients;
char myaddressstring[128];
if (developer_extra.integer)
Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_SERVER_INFO to %s.\n", addressstring2);
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_SERVER_INFO);
LHNETADDRESS_ToString(LHNET_AddressFromSocket(mysocket), myaddressstring, sizeof(myaddressstring), true);
- MSG_WriteString(&net_message, myaddressstring);
- MSG_WriteString(&net_message, hostname.string);
- MSG_WriteString(&net_message, sv.name);
+ MSG_WriteString(&sv_message, myaddressstring);
+ MSG_WriteString(&sv_message, hostname.string);
+ MSG_WriteString(&sv_message, sv.name);
// How many clients are there?
for (i = 0, numclients = 0;i < svs.maxclients;i++)
if (svs.clients[i].active)
numclients++;
- MSG_WriteByte(&net_message, numclients);
- MSG_WriteByte(&net_message, svs.maxclients);
- MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ MSG_WriteByte(&sv_message, numclients);
+ MSG_WriteByte(&sv_message, svs.maxclients);
+ MSG_WriteByte(&sv_message, NET_PROTOCOL_VERSION);
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
}
break;
case CCREQ_PLAYER_INFO:
int playerNumber, activeNumber, clientNumber;
client_t *client;
- playerNumber = MSG_ReadByte();
+ playerNumber = MSG_ReadByte(&sv_message);
activeNumber = -1;
for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
if (client->active && ++activeNumber == playerNumber)
break;
if (clientNumber != svs.maxclients)
{
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
- MSG_WriteByte(&net_message, playerNumber);
- MSG_WriteString(&net_message, client->name);
- MSG_WriteLong(&net_message, client->colors);
- MSG_WriteLong(&net_message, client->frags);
- MSG_WriteLong(&net_message, (int)(realtime - client->connecttime));
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_PLAYER_INFO);
+ MSG_WriteByte(&sv_message, playerNumber);
+ MSG_WriteString(&sv_message, client->name);
+ MSG_WriteLong(&sv_message, client->colors);
+ MSG_WriteLong(&sv_message, client->frags);
+ MSG_WriteLong(&sv_message, (int)(realtime - client->connecttime));
if(sv_status_privacy.integer)
- MSG_WriteString(&net_message, client->netconnection ? "hidden" : "botclient");
+ MSG_WriteString(&sv_message, client->netconnection ? "hidden" : "botclient");
else
- MSG_WriteString(&net_message, client->netconnection ? client->netconnection->address : "botclient");
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ MSG_WriteString(&sv_message, client->netconnection ? client->netconnection->address : "botclient");
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
}
}
break;
cvar_t *var;
// find the search start location
- prevCvarName = MSG_ReadString();
+ prevCvarName = MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring));
var = Cvar_FindVarAfter(prevCvarName, CVAR_NOTIFY);
// send the response
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREP_RULE_INFO);
+ MSG_WriteLong(&sv_message, 0);
+ MSG_WriteByte(&sv_message, CCREP_RULE_INFO);
if (var)
{
- MSG_WriteString(&net_message, var->name);
- MSG_WriteString(&net_message, var->string);
+ MSG_WriteString(&sv_message, var->name);
+ MSG_WriteString(&sv_message, var->string);
}
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress);
- SZ_Clear(&net_message);
+ StoreBigLong(sv_message.data, NETFLAG_CTL | (sv_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, sv_message.data, sv_message.cursize, peeraddress);
+ SZ_Clear(&sv_message);
}
break;
case CCREQ_RCON:
char *s;
char *endpos;
const char *userlevel;
- strlcpy(password, MSG_ReadString(), sizeof(password));
- strlcpy(cmd, MSG_ReadString(), sizeof(cmd));
+ strlcpy(password, MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)), sizeof(password));
+ strlcpy(cmd, MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)), sizeof(cmd));
s = cmd;
endpos = cmd + strlen(cmd) + 1; // one behind the NUL, so adding strlen+1 will eventually reach it
userlevel = RCon_Authenticate(peeraddress, password, s, endpos, plaintext_matching, NULL, 0);
default:
break;
}
- SZ_Clear(&net_message);
+ SZ_Clear(&sv_message);
// we may not have liked the packet, but it was a valid control
// packet, so we're done processing this packet now
return true;
{
if ((ret = NetConn_ReceivedMessage(host_client->netconnection, data, length, sv.protocol, host_client->spawned ? net_messagetimeout.value : net_connecttimeout.value)) == 2)
{
- SV_VM_Begin();
SV_ReadClientMessage();
- SV_VM_End();
return ret;
}
}
{
int i, length;
lhnetaddress_t peeraddress;
+ unsigned char readbuffer[NET_HEADERSIZE+NET_MAXMESSAGE];
for (i = 0;i < sv_numsockets;i++)
while (sv_sockets[i] && (length = NetConn_Read(sv_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0)
NetConn_ServerParsePacket(sv_sockets[i], readbuffer, length, &peeraddress);
if (host_client->netconnection && realtime > host_client->netconnection->timeout && LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) != LHNETADDRESSTYPE_LOOP)
{
Con_Printf("Client \"%s\" connection timed out\n", host_client->name);
- SV_VM_Begin();
SV_DropClient(false);
- SV_VM_End();
}
}
}
if(LHNETADDRESS_GetAddressType(&broadcastaddress) == af)
{
// search LAN for Quake servers
- SZ_Clear(&net_message);
+ SZ_Clear(&cl_message);
// save space for the header, filled in later
- MSG_WriteLong(&net_message, 0);
- MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
- MSG_WriteString(&net_message, "QUAKE");
- MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
- StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(cl_sockets[i], net_message.data, net_message.cursize, &broadcastaddress);
- SZ_Clear(&net_message);
+ MSG_WriteLong(&cl_message, 0);
+ MSG_WriteByte(&cl_message, CCREQ_SERVER_INFO);
+ MSG_WriteString(&cl_message, "QUAKE");
+ MSG_WriteByte(&cl_message, NET_PROTOCOL_VERSION);
+ StoreBigLong(cl_message.data, NETFLAG_CTL | (cl_message.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(cl_sockets[i], cl_message.data, cl_message.cursize, &broadcastaddress);
+ SZ_Clear(&cl_message);
// search LAN for DarkPlaces servers
NetConn_WriteString(cl_sockets[i], "\377\377\377\377getstatus", &broadcastaddress);
Con_Print("No server running, can not heartbeat to master server.\n");
}
-void PrintStats(netconn_t *conn)
+static void PrintStats(netconn_t *conn)
{
if ((cls.state == ca_connected && cls.protocol == PROTOCOL_QUAKEWORLD) || (sv.active && sv.protocol == PROTOCOL_QUAKEWORLD))
Con_Printf("address=%21s canSend=%u sendSeq=%6u recvSeq=%6u\n", conn->address, !conn->sendMessageLength, conn->outgoing_unreliable_sequence, conn->qw.incoming_sequence);
else
Con_Printf("address=%21s canSend=%u sendSeq=%6u recvSeq=%6u\n", conn->address, !conn->sendMessageLength, conn->nq.sendSequence, conn->nq.receiveSequence);
+ Con_Printf("unreliable messages sent = %i\n", conn->unreliableMessagesSent);
+ Con_Printf("unreliable messages recv = %i\n", conn->unreliableMessagesReceived);
+ Con_Printf("reliable messages sent = %i\n", conn->reliableMessagesSent);
+ Con_Printf("reliable messages received = %i\n", conn->reliableMessagesReceived);
+ Con_Printf("packetsSent = %i\n", conn->packetsSent);
+ Con_Printf("packetsReSent = %i\n", conn->packetsReSent);
+ Con_Printf("packetsReceived = %i\n", conn->packetsReceived);
+ Con_Printf("receivedDuplicateCount = %i\n", conn->receivedDuplicateCount);
+ Con_Printf("droppedDatagrams = %i\n", conn->droppedDatagrams);
}
void Net_Stats_f(void)
{
netconn_t *conn;
- Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent);
- Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived);
- Con_Printf("reliable messages sent = %i\n", reliableMessagesSent);
- Con_Printf("reliable messages received = %i\n", reliableMessagesReceived);
- Con_Printf("packetsSent = %i\n", packetsSent);
- Con_Printf("packetsReSent = %i\n", packetsReSent);
- Con_Printf("packetsReceived = %i\n", packetsReceived);
- Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount);
- Con_Printf("droppedDatagrams = %i\n", droppedDatagrams);
Con_Print("connections =\n");
for (conn = netconn_list;conn;conn = conn->next)
PrintStats(conn);
}
cl_numsockets = 0;
sv_numsockets = 0;
- net_message.data = net_message_buf;
- net_message.maxsize = sizeof(net_message_buf);
- net_message.cursize = 0;
+ cl_message.data = cl_message_buf;
+ cl_message.maxsize = sizeof(cl_message_buf);
+ cl_message.cursize = 0;
+ sv_message.data = sv_message_buf;
+ sv_message.maxsize = sizeof(sv_message_buf);
+ sv_message.cursize = 0;
LHNET_Init();
+ if (Thread_HasThreads())
+ netconn_mutex = Thread_CreateMutex();
}
void NetConn_Shutdown(void)
NetConn_CloseClientPorts();
NetConn_CloseServerPorts();
LHNET_Shutdown();
+ if (netconn_mutex)
+ Thread_DestroyMutex(netconn_mutex);
+ netconn_mutex = NULL;
}
char address[128];
crypto_t crypto;
+
+ // statistic counters
+ int packetsSent;
+ int packetsReSent;
+ int packetsReceived;
+ int receivedDuplicateCount;
+ int droppedDatagrams;
+ int unreliableMessagesSent;
+ int unreliableMessagesReceived;
+ int reliableMessagesSent;
+ int reliableMessagesReceived;
} netconn_t;
extern netconn_t *netconn_list;
extern cvar_t hostname;
extern cvar_t developer_networking;
-#define SERVERLIST_TOTALSIZE 2048
#define SERVERLIST_VIEWLISTSIZE SERVERLIST_TOTALSIZE
-#define SERVERLIST_ANDMASKCOUNT 5
-#define SERVERLIST_ORMASKCOUNT 5
typedef enum serverlist_maskop_e
{
extern int serverquerycount;
extern int serverreplycount;
-extern sizebuf_t net_message;
+extern sizebuf_t cl_message;
+extern sizebuf_t sv_message;
+extern char cl_readstring[MAX_INPUTLINE];
+extern char sv_readstring[MAX_INPUTLINE];
extern cvar_t sv_public;
139,0,0, 179,0,0, 215,0,0, 255,0,0, 255,243,147, 255,247,199, 255,255,255, 159,91,83
}; // 15 ^
-void Palette_SetupSpecialPalettes(void)
+static void Palette_SetupSpecialPalettes(void)
{
int i;
int fullbright_start, fullbright_end;
}
}
-void Palette_Shutdown(void)
+static void Palette_Shutdown(void)
{
}
-void Palette_NewMap(void)
+static void Palette_NewMap(void)
{
}
-void Palette_Load(void)
+static void Palette_Load(void)
{
int i;
unsigned char *out;
#include "quakedef.h"
#include "polygon.h"
+#include "portals.h"
#define MAXRECURSIVEPORTALPLANES 1024
#define MAXRECURSIVEPORTALS 256
vec3_t ode_mins;
vec3_t ode_maxs;
vec_t ode_mass;
+ float ode_friction;
vec3_t ode_origin;
vec3_t ode_velocity;
vec3_t ode_angles;
#define PROFILING
#endif
-// forward declaration of clgecko_t
-struct clgecko_s;
-
typedef struct prvm_stack_s
{
int s;
{
qboolean free;
float freetime;
- int mark;
+ int mark; // used during leaktest (0 = unref, >0 = referenced); special values during server physics:
+#define PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN -1
+#define PRVM_EDICT_MARK_SETORIGIN_CAUGHT -2
const char *allocation_origin;
} prvm_edict_private_t;
} fields;
} prvm_edict_t;
+#define VMPOLYGONS_MAXPOINTS 64
+
+typedef struct vmpolygons_triangle_s
+{
+ rtexture_t *texture;
+ int drawflag;
+ qboolean hasalpha;
+ unsigned short elements[3];
+} vmpolygons_triangle_t;
+
+typedef struct vmpolygons_s
+{
+ mempool_t *pool;
+ qboolean initialized;
+
+ int max_vertices;
+ int num_vertices;
+ float *data_vertex3f;
+ float *data_color4f;
+ float *data_texcoord2f;
+
+ int max_triangles;
+ int num_triangles;
+ vmpolygons_triangle_t *data_triangles;
+ unsigned short *data_sortedelement3s;
+
+ qboolean begin_active;
+ int begin_draw2d;
+ rtexture_t *begin_texture;
+ int begin_drawflag;
+ int begin_vertices;
+ float begin_vertex[VMPOLYGONS_MAXPOINTS][3];
+ float begin_color[VMPOLYGONS_MAXPOINTS][4];
+ float begin_texcoord[VMPOLYGONS_MAXPOINTS][2];
+ qboolean begin_texture_hasalpha;
+} vmpolygons_t;
+
extern prvm_eval_t prvm_badvalue;
#define PRVM_alledictfloat(ed, fieldname) (PRVM_EDICTFIELDFLOAT(ed, prog->fieldoffsets.fieldname))
#define PRVM_MAX_OPENFILES 16
#define PRVM_MAX_OPENSEARCHES 8
-#define PRVM_MAX_GECKOINSTANCES 1
#else
#define PRVM_MAX_STACK_DEPTH 1024
#define PRVM_LOCALSTACK_SIZE 16384
#define PRVM_MAX_OPENFILES 256
#define PRVM_MAX_OPENSEARCHES 128
-#define PRVM_MAX_GECKOINSTANCES 32
#endif
-typedef void (*prvm_builtin_t) (void);
+struct prvm_prog_s;
+typedef void (*prvm_builtin_t) (struct prvm_prog_s *prog);
// NOTE: field offsets use -1 for NULL
typedef struct prvm_prog_fieldoffsets_s
// NOTE: external code has to create and free the mempools but everything else is done by prvm !
typedef struct prvm_prog_s
{
- double starttime;
+ double starttime; // system time when PRVM_Prog_Load was called
+ double profiletime; // system time when last PRVM_CallProfile was called (or PRVM_Prog_Load initially)
unsigned int id; // increasing unique id of progs instance
mfunction_t *functions;
char *strings;
const char * openfiles_origin[PRVM_MAX_OPENFILES];
fssearch_t *opensearches[PRVM_MAX_OPENSEARCHES];
const char * opensearches_origin[PRVM_MAX_OPENSEARCHES];
- struct clgecko_s *opengeckoinstances[PRVM_MAX_GECKOINSTANCES];
skeleton_t *skeletons[MAX_EDICTS];
+ // buffer for storing all tempstrings created during one invocation of ExecuteProgram
+ sizebuf_t tempstringsbuf;
+
+ // LordHavoc: moved this here to clean up things that relied on prvm_prog_list too much
+ // FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
+ vmpolygons_t vmpolygons;
+
// copies of some vars that were former read from sv
int num_edicts;
// number of edicts for which space has been (should be) allocated
//============================================================================
// function pointers
- void (*begin_increase_edicts)(void); // [INIT] used by PRVM_MEM_Increase_Edicts
- void (*end_increase_edicts)(void); // [INIT]
+ void (*begin_increase_edicts)(struct prvm_prog_s *prog); // [INIT] used by PRVM_MEM_Increase_Edicts
+ void (*end_increase_edicts)(struct prvm_prog_s *prog); // [INIT]
- void (*init_edict)(prvm_edict_t *edict); // [INIT] used by PRVM_ED_ClearEdict
- void (*free_edict)(prvm_edict_t *ed); // [INIT] used by PRVM_ED_Free
+ void (*init_edict)(struct prvm_prog_s *prog, prvm_edict_t *edict); // [INIT] used by PRVM_ED_ClearEdict
+ void (*free_edict)(struct prvm_prog_s *prog, prvm_edict_t *ed); // [INIT] used by PRVM_ED_Free
- void (*count_edicts)(void); // [INIT] used by PRVM_ED_Count_f
+ void (*count_edicts)(struct prvm_prog_s *prog); // [INIT] used by PRVM_ED_Count_f
- qboolean (*load_edict)(prvm_edict_t *ent); // [INIT] used by PRVM_ED_LoadFromFile
+ qboolean (*load_edict)(struct prvm_prog_s *prog, prvm_edict_t *ent); // [INIT] used by PRVM_ED_LoadFromFile
- void (*init_cmd)(void); // [INIT] used by PRVM_InitProg
- void (*reset_cmd)(void); // [INIT] used by PRVM_ResetProg
+ void (*init_cmd)(struct prvm_prog_s *prog); // [INIT] used by PRVM_InitProg
+ void (*reset_cmd)(struct prvm_prog_s *prog); // [INIT] used by PRVM_ResetProg
void (*error_cmd)(const char *format, ...) DP_FUNC_PRINTF(1); // [INIT]
- void (*ExecuteProgram)(func_t fnum, const char *errormessage); // pointer to one of the *VM_ExecuteProgram functions
+ void (*ExecuteProgram)(struct prvm_prog_s *prog, func_t fnum, const char *errormessage); // pointer to one of the *VM_ExecuteProgram functions
} prvm_prog_t;
-extern prvm_prog_t * prog;
-
-#define PRVM_MAXPROGS 3
-#define PRVM_SERVERPROG 0 // actually not used at the moment
-#define PRVM_CLIENTPROG 1
-#define PRVM_MENUPROG 2
+typedef enum prvm_progindex_e
+{
+ PRVM_PROG_SERVER,
+ PRVM_PROG_CLIENT,
+ PRVM_PROG_MENU,
+ PRVM_PROG_MAX
+}
+prvm_progindex_t;
-extern prvm_prog_t prvm_prog_list[PRVM_MAXPROGS];
+extern prvm_prog_t prvm_prog_list[PRVM_PROG_MAX];
+prvm_prog_t *PRVM_ProgFromString(const char *str);
+prvm_prog_t *PRVM_FriendlyProgFromString(const char *str); // for console commands (prints error if name unknown and returns NULL, prints error if prog not loaded and returns NULL)
+#define PRVM_GetProg(n) (&prvm_prog_list[(n)])
+#define PRVM_ProgLoaded(n) (PRVM_GetProg(n)->loaded)
+#define SVVM_prog (&prvm_prog_list[PRVM_PROG_SERVER])
+#define CLVM_prog (&prvm_prog_list[PRVM_PROG_CLIENT])
+#define MVM_prog (&prvm_prog_list[PRVM_PROG_MENU])
//============================================================================
// prvm_cmds part
extern const char * vm_sv_extensions; // client also uses this
extern const char * vm_m_extensions;
-void VM_SV_Cmd_Init(void);
-void VM_SV_Cmd_Reset(void);
+void SVVM_init_cmd(prvm_prog_t *prog);
+void SVVM_reset_cmd(prvm_prog_t *prog);
-void VM_CL_Cmd_Init(void);
-void VM_CL_Cmd_Reset(void);
+void CLVM_init_cmd(prvm_prog_t *prog);
+void CLVM_reset_cmd(prvm_prog_t *prog);
-void VM_M_Cmd_Init(void);
-void VM_M_Cmd_Reset(void);
+void MVM_init_cmd(prvm_prog_t *prog);
+void MVM_reset_cmd(prvm_prog_t *prog);
-void VM_Cmd_Init(void);
-void VM_Cmd_Reset(void);
+void VM_Cmd_Init(prvm_prog_t *prog);
+void VM_Cmd_Reset(prvm_prog_t *prog);
//============================================================================
void PRVM_Init (void);
#ifdef PROFILING
-void MVM_ExecuteProgram (func_t fnum, const char *errormessage);
-void CLVM_ExecuteProgram (func_t fnum, const char *errormessage);
-void SVVM_ExecuteProgram (func_t fnum, const char *errormessage);
+void SVVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage);
+void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage);
+void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage);
#else
-#define MVM_ExecuteProgram SVVM_ExecuteProgram
-#define CLVM_ExecuteProgram SVVM_ExecuteProgram
-void SVVM_ExecuteProgram (func_t fnum, const char *errormessage);
+#define SVVM_ExecuteProgram PRVM_ExecuteProgram
+#define CLVM_ExecuteProgram PRVM_ExecuteProgram
+#define MVM_ExecuteProgram PRVM_ExecuteProgram
+void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage);
#endif
-#define PRVM_ExecuteProgram prog->ExecuteProgram
-#define PRVM_Alloc(buffersize) _PRVM_Alloc(buffersize, __FILE__, __LINE__)
-#define PRVM_Free(buffer) _PRVM_Free(buffer, __FILE__, __LINE__)
-#define PRVM_FreeAll() _PRVM_FreeAll(__FILE__, __LINE__)
-void *_PRVM_Alloc (size_t buffersize, const char *filename, int fileline);
-void _PRVM_Free (void *buffer, const char *filename, int fileline);
-void _PRVM_FreeAll (const char *filename, int fileline);
+#define PRVM_Alloc(buffersize) Mem_Alloc(prog->progs_mempool, buffersize)
+#define PRVM_Free(buffer) Mem_Free(buffer)
-void PRVM_Profile (int maxfunctions, double mintime, int sortby);
+void PRVM_Profile (prvm_prog_t *prog, int maxfunctions, double mintime, int sortby);
void PRVM_Profile_f (void);
void PRVM_ChildProfile_f (void);
void PRVM_CallProfile_f (void);
void PRVM_PrintFunction_f (void);
-void PRVM_PrintState(void);
-void PRVM_CrashAll (void);
-void PRVM_Crash (void);
-void PRVM_ShortStackTrace(char *buf, size_t bufsize);
-const char *PRVM_AllocationOrigin(void);
+void PRVM_PrintState(prvm_prog_t *prog);
+void PRVM_Crash(prvm_prog_t *prog);
+void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize);
+const char *PRVM_AllocationOrigin(prvm_prog_t *prog);
-ddef_t *PRVM_ED_FindField(const char *name);
-ddef_t *PRVM_ED_FindGlobal(const char *name);
-mfunction_t *PRVM_ED_FindFunction(const char *name);
+ddef_t *PRVM_ED_FindField(prvm_prog_t *prog, const char *name);
+ddef_t *PRVM_ED_FindGlobal(prvm_prog_t *prog, const char *name);
+mfunction_t *PRVM_ED_FindFunction(prvm_prog_t *prog, const char *name);
-int PRVM_ED_FindFieldOffset(const char *name);
-int PRVM_ED_FindGlobalOffset(const char *name);
-func_t PRVM_ED_FindFunctionOffset(const char *name);
+int PRVM_ED_FindFieldOffset(prvm_prog_t *prog, const char *name);
+int PRVM_ED_FindGlobalOffset(prvm_prog_t *prog, const char *name);
+func_t PRVM_ED_FindFunctionOffset(prvm_prog_t *prog, const char *name);
#define PRVM_ED_FindFieldOffset_FromStruct(st, field) prog->fieldoffsets . field = ((int *)(&((st *)NULL)-> field ) - ((int *)NULL))
#define PRVM_ED_FindGlobalOffset_FromStruct(st, field) prog->globaloffsets . field = ((int *)(&((st *)NULL)-> field ) - ((int *)NULL))
-void PRVM_MEM_IncreaseEdicts(void);
+void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog);
-qboolean PRVM_ED_CanAlloc(prvm_edict_t *e);
-prvm_edict_t *PRVM_ED_Alloc (void);
-void PRVM_ED_Free (prvm_edict_t *ed);
-void PRVM_ED_ClearEdict (prvm_edict_t *e);
+qboolean PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e);
+prvm_edict_t *PRVM_ED_Alloc(prvm_prog_t *prog);
+void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed);
+void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e);
-void PRVM_PrintFunctionStatements (const char *name);
-void PRVM_ED_Print(prvm_edict_t *ed, const char *wildcard_fieldname);
-void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed);
-const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent);
+void PRVM_PrintFunctionStatements(prvm_prog_t *prog, const char *name);
+void PRVM_ED_Print(prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname);
+void PRVM_ED_Write(prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed);
+const char *PRVM_ED_ParseEdict(prvm_prog_t *prog, const char *data, prvm_edict_t *ent);
-void PRVM_ED_WriteGlobals (qfile_t *f);
-void PRVM_ED_ParseGlobals (const char *data);
+void PRVM_ED_WriteGlobals(prvm_prog_t *prog, qfile_t *f);
+void PRVM_ED_ParseGlobals(prvm_prog_t *prog, const char *data);
-void PRVM_ED_LoadFromFile (const char *data);
+void PRVM_ED_LoadFromFile(prvm_prog_t *prog, const char *data);
-unsigned int PRVM_EDICT_NUM_ERROR(unsigned int n, const char *filename, int fileline);
-#define PRVM_EDICT(n) (((unsigned)(n) < (unsigned int)prog->max_edicts) ? (unsigned int)(n) : PRVM_EDICT_NUM_ERROR((unsigned int)(n), __FILE__, __LINE__))
+unsigned int PRVM_EDICT_NUM_ERROR(prvm_prog_t *prog, unsigned int n, const char *filename, int fileline);
+#define PRVM_EDICT(n) (((unsigned)(n) < (unsigned int)prog->max_edicts) ? (unsigned int)(n) : PRVM_EDICT_NUM_ERROR(prog, (unsigned int)(n), __FILE__, __LINE__))
#define PRVM_EDICT_NUM(n) (prog->edicts + PRVM_EDICT(n))
//int NUM_FOR_EDICT_ERROR(prvm_edict_t *e);
#define PRVM_G_EDICT(o) (PRVM_PROG_TO_EDICT(*(int *)&prog->globals.generic[o]))
#define PRVM_G_EDICTNUM(o) PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(o))
#define PRVM_G_VECTOR(o) (&prog->globals.generic[o])
-#define PRVM_G_STRING(o) (PRVM_GetString(*(string_t *)&prog->globals.generic[o]))
-//#define PRVM_G_FUNCTION(o) (*(func_t *)&prog->globals.generic[o])
+#define PRVM_G_STRING(o) (PRVM_GetString(prog, *(string_t *)&prog->globals.generic[o]))
+//#define PRVM_G_FUNCTION(prog, o) (*(func_t *)&prog->globals.generic[o])
// FIXME: make these go away?
#define PRVM_E_FLOAT(e,o) (((float*)e->fields.vp)[o])
#define PRVM_E_INT(e,o) (((int*)e->fields.vp)[o])
//#define PRVM_E_VECTOR(e,o) (&((float*)e->fields.vp)[o])
-#define PRVM_E_STRING(e,o) (PRVM_GetString(*(string_t *)&((float*)e->fields.vp)[o]))
+#define PRVM_E_STRING(e,o) (PRVM_GetString(prog, *(string_t *)&((float*)e->fields.vp)[o]))
extern int prvm_type_size[8]; // for consistency : I think a goal of this sub-project is to
// make the new vm mostly independent from the old one, thus if it's necessary, I copy everything
-void PRVM_Init_Exec(void);
+void PRVM_Init_Exec(prvm_prog_t *prog);
void PRVM_ED_PrintEdicts_f (void);
-void PRVM_ED_PrintNum (int ent, const char *wildcard_fieldname);
-
-const char *PRVM_GetString(int num);
-int PRVM_SetEngineString(const char *s);
-const char *PRVM_ChangeEngineString(int i, const char *s);
-int PRVM_SetTempString(const char *s);
-int PRVM_AllocString(size_t bufferlength, char **pointer);
-void PRVM_FreeString(int num);
+void PRVM_ED_PrintNum (prvm_prog_t *prog, int ent, const char *wildcard_fieldname);
-//============================================================================
-
-// used as replacement for a prog stack
-//#define PRVM_DEBUGPRSTACK
-
-#ifdef PRVM_DEBUGPRSTACK
-#define PRVM_Begin if(prog != 0) Con_Printf("prog not 0(prog = %i) in file: %s line: %i!\n", PRVM_GetProgNr(), __FILE__, __LINE__)
-#define PRVM_End prog = 0
-#else
-#define PRVM_Begin
-#define PRVM_End prog = 0
-#endif
-
-//#define PRVM_SAFENAME
-#ifndef PRVM_SAFENAME
-# define PRVM_NAME (prog->name)
-#else
-# define PRVM_NAME (prog->name ? prog->name : "Unknown prog name")
-#endif
-
-// helper macro to make function pointer calls easier
-#define PRVM_GCALL(func) if(prog->func) prog->func
+const char *PRVM_GetString(prvm_prog_t *prog, int num);
+int PRVM_SetEngineString(prvm_prog_t *prog, const char *s);
+const char *PRVM_ChangeEngineString(prvm_prog_t *prog, int i, const char *s);
+int PRVM_SetTempString(prvm_prog_t *prog, const char *s);
+int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer);
+void PRVM_FreeString(prvm_prog_t *prog, int num);
-#define PRVM_ERROR prog->error_cmd
+ddef_t *PRVM_ED_FieldAtOfs(prvm_prog_t *prog, int ofs);
+qboolean PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash);
+char *PRVM_UglyValueString(prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength);
+char *PRVM_GlobalString(prvm_prog_t *prog, int ofs, char *line, size_t linelength);
+char *PRVM_GlobalStringNoContents(prvm_prog_t *prog, int ofs, char *line, size_t linelength);
-// other prog handling functions
-qboolean PRVM_SetProgFromString(const char *str);
-void PRVM_SetProg(int prognr);
+//============================================================================
/*
Initializing a vm:
Set up the fields marked with [INIT] in the prog struct
Load a program with LoadProgs
*/
-void PRVM_InitProg(int prognr);
-// LoadProgs expects to be called right after InitProg
-void PRVM_LoadProgs (const char *filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global);
-void PRVM_ResetProg(void);
-
-qboolean PRVM_ProgLoaded(int prognr);
-
-int PRVM_GetProgNr(void);
+// Load expects to be called right after Init
+void PRVM_Prog_Init(prvm_prog_t *prog);
+void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global);
+void PRVM_Prog_Reset(prvm_prog_t *prog);
-void VM_Warning(const char *fmt, ...) DP_FUNC_PRINTF(1);
+void PRVM_StackTrace(prvm_prog_t *prog);
-// TODO: fill in the params
-//void PRVM_Create();
+void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) DP_FUNC_PRINTF(2);
-void VM_GenerateFrameGroupBlend(framegroupblend_t *framegroupblend, const prvm_edict_t *ed);
+void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroupblend, const prvm_edict_t *ed);
void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model);
-void VM_UpdateEdictSkeleton(prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend);
-void VM_RemoveEdictSkeleton(prvm_edict_t *ed);
+void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend);
+void VM_RemoveEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed);
#endif
if(developer_networkentities.integer >= 2) \
{ \
prvm_edict_t *ed = prog->edicts + num; \
- Con_Printf("sent entity update of size %d for a %s\n", (msg->cursize - entityprofiling_startsize), PRVM_serveredictstring(ed, classname) ? PRVM_GetString(PRVM_serveredictstring(ed, classname)) : "(no classname)"); \
+ Con_Printf("sent entity update of size %d for a %s\n", (msg->cursize - entityprofiling_startsize), PRVM_serveredictstring(ed, classname) ? PRVM_GetString(prog, PRVM_serveredictstring(ed, classname)) : "(no classname)"); \
}
// this is 88 bytes (must match entity_state_t in protocol.h)
entity_state_t s;
if (bits & U_MOREBITS)
- bits |= (MSG_ReadByte()<<8);
+ bits |= (MSG_ReadByte(&cl_message)<<8);
if ((bits & U_EXTEND1) && cls.protocol != PROTOCOL_NEHAHRAMOVIE)
{
- bits |= MSG_ReadByte() << 16;
+ bits |= MSG_ReadByte(&cl_message) << 16;
if (bits & U_EXTEND2)
- bits |= MSG_ReadByte() << 24;
+ bits |= MSG_ReadByte(&cl_message) << 24;
}
if (bits & U_LONGENTITY)
- num = (unsigned short) MSG_ReadShort ();
+ num = (unsigned short) MSG_ReadShort(&cl_message);
else
- num = MSG_ReadByte ();
+ num = MSG_ReadByte(&cl_message);
if (num >= MAX_EDICTS)
Host_Error("EntityFrameQuake_ReadEntity: entity number (%i) >= MAX_EDICTS (%i)", num, MAX_EDICTS);
if (bits & U_MODEL)
{
if (cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3)
- s.modelindex = (unsigned short) MSG_ReadShort();
+ s.modelindex = (unsigned short) MSG_ReadShort(&cl_message);
else
- s.modelindex = (s.modelindex & 0xFF00) | MSG_ReadByte();
- }
- if (bits & U_FRAME) s.frame = (s.frame & 0xFF00) | MSG_ReadByte();
- if (bits & U_COLORMAP) s.colormap = MSG_ReadByte();
- if (bits & U_SKIN) s.skin = MSG_ReadByte();
- if (bits & U_EFFECTS) s.effects = (s.effects & 0xFF00) | MSG_ReadByte();
- if (bits & U_ORIGIN1) s.origin[0] = MSG_ReadCoord(cls.protocol);
- if (bits & U_ANGLE1) s.angles[0] = MSG_ReadAngle(cls.protocol);
- if (bits & U_ORIGIN2) s.origin[1] = MSG_ReadCoord(cls.protocol);
- if (bits & U_ANGLE2) s.angles[1] = MSG_ReadAngle(cls.protocol);
- if (bits & U_ORIGIN3) s.origin[2] = MSG_ReadCoord(cls.protocol);
- if (bits & U_ANGLE3) s.angles[2] = MSG_ReadAngle(cls.protocol);
+ s.modelindex = (s.modelindex & 0xFF00) | MSG_ReadByte(&cl_message);
+ }
+ if (bits & U_FRAME) s.frame = (s.frame & 0xFF00) | MSG_ReadByte(&cl_message);
+ if (bits & U_COLORMAP) s.colormap = MSG_ReadByte(&cl_message);
+ if (bits & U_SKIN) s.skin = MSG_ReadByte(&cl_message);
+ if (bits & U_EFFECTS) s.effects = (s.effects & 0xFF00) | MSG_ReadByte(&cl_message);
+ if (bits & U_ORIGIN1) s.origin[0] = MSG_ReadCoord(&cl_message, cls.protocol);
+ if (bits & U_ANGLE1) s.angles[0] = MSG_ReadAngle(&cl_message, cls.protocol);
+ if (bits & U_ORIGIN2) s.origin[1] = MSG_ReadCoord(&cl_message, cls.protocol);
+ if (bits & U_ANGLE2) s.angles[1] = MSG_ReadAngle(&cl_message, cls.protocol);
+ if (bits & U_ORIGIN3) s.origin[2] = MSG_ReadCoord(&cl_message, cls.protocol);
+ if (bits & U_ANGLE3) s.angles[2] = MSG_ReadAngle(&cl_message, cls.protocol);
if (bits & U_STEP) s.flags |= RENDER_STEP;
- if (bits & U_ALPHA) s.alpha = MSG_ReadByte();
- if (bits & U_SCALE) s.scale = MSG_ReadByte();
- if (bits & U_EFFECTS2) s.effects = (s.effects & 0x00FF) | (MSG_ReadByte() << 8);
- if (bits & U_GLOWSIZE) s.glowsize = MSG_ReadByte();
- if (bits & U_GLOWCOLOR) s.glowcolor = MSG_ReadByte();
- if (bits & U_COLORMOD) {int c = MSG_ReadByte();s.colormod[0] = (unsigned char)(((c >> 5) & 7) * (32.0f / 7.0f));s.colormod[1] = (unsigned char)(((c >> 2) & 7) * (32.0f / 7.0f));s.colormod[2] = (unsigned char)((c & 3) * (32.0f / 3.0f));}
+ if (bits & U_ALPHA) s.alpha = MSG_ReadByte(&cl_message);
+ if (bits & U_SCALE) s.scale = MSG_ReadByte(&cl_message);
+ if (bits & U_EFFECTS2) s.effects = (s.effects & 0x00FF) | (MSG_ReadByte(&cl_message) << 8);
+ if (bits & U_GLOWSIZE) s.glowsize = MSG_ReadByte(&cl_message);
+ if (bits & U_GLOWCOLOR) s.glowcolor = MSG_ReadByte(&cl_message);
+ if (bits & U_COLORMOD) {int c = MSG_ReadByte(&cl_message);s.colormod[0] = (unsigned char)(((c >> 5) & 7) * (32.0f / 7.0f));s.colormod[1] = (unsigned char)(((c >> 2) & 7) * (32.0f / 7.0f));s.colormod[2] = (unsigned char)((c & 3) * (32.0f / 3.0f));}
if (bits & U_GLOWTRAIL) s.flags |= RENDER_GLOWTRAIL;
- if (bits & U_FRAME2) s.frame = (s.frame & 0x00FF) | (MSG_ReadByte() << 8);
- if (bits & U_MODEL2) s.modelindex = (s.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
+ if (bits & U_FRAME2) s.frame = (s.frame & 0x00FF) | (MSG_ReadByte(&cl_message) << 8);
+ if (bits & U_MODEL2) s.modelindex = (s.modelindex & 0x00FF) | (MSG_ReadByte(&cl_message) << 8);
if (bits & U_VIEWMODEL) s.flags |= RENDER_VIEWMODEL;
if (bits & U_EXTERIORMODEL) s.flags |= RENDER_EXTERIORMODEL;
if (cls.protocol == PROTOCOL_NEHAHRAMOVIE && (bits & U_EXTEND1))
{
// LordHavoc: evil format
- int i = (int)MSG_ReadFloat();
- int j = (int)(MSG_ReadFloat() * 255.0f);
+ int i = (int)MSG_ReadFloat(&cl_message);
+ int j = (int)(MSG_ReadFloat(&cl_message) * 255.0f);
if (i == 2)
{
- i = (int)MSG_ReadFloat();
+ i = (int)MSG_ReadFloat(&cl_message);
if (i)
s.effects |= EF_FULLBRIGHT;
}
cl.entities_active[ent->state_current.number] = true;
}
- if (msg_badread)
+ if (cl_message.badread)
Host_Error("EntityFrameQuake_ReadEntity: read error");
}
// Always use the DP5 protocol, or a higher one, when using CSQC entities.
static void EntityFrameCSQC_LostAllFrames(client_t *client)
{
+ prvm_prog_t *prog = SVVM_prog;
// mark ALL csqc entities as requiring a FULL resend!
// I know this is a bad workaround, but better than nothing.
int i, n;
int i, j;
qboolean valid;
int ringfirst, ringlast;
- static int recoversendflags[MAX_EDICTS];
+ static int recoversendflags[MAX_EDICTS]; // client only
csqcentityframedb_t *d;
if(client->csqcentityframe_lastreset < 0)
// amounts of csqc networked entities
qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers, const unsigned short *numbers, int framenum)
{
+ prvm_prog_t *prog = SVVM_prog;
int num, number, end, sendflags;
qboolean sectionstarted = false;
const unsigned short *n;
PRVM_G_INT(OFS_PARM0) = sv.writeentitiestoclient_cliententitynumber;
PRVM_G_FLOAT(OFS_PARM1) = sendflags;
PRVM_serverglobaledict(self) = number;
- PRVM_ExecuteProgram(PRVM_serveredictfunction(ed, SendEntity), "Null SendEntity\n");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ed, SendEntity), "Null SendEntity\n");
msg->allowoverflow = false;
if(PRVM_G_FLOAT(OFS_RETURN) && msg->cursize + 2 <= maxsize)
{
qboolean EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, const entity_state_t **states)
{
+ prvm_prog_t *prog = SVVM_prog;
const entity_state_t *s;
entity_state_t baseline;
int i, bits;
void EntityState_WriteUpdate(const entity_state_t *ent, sizebuf_t *msg, const entity_state_t *delta)
{
+ prvm_prog_t *prog = SVVM_prog;
unsigned int bits;
ENTITYSIZEPROFILING_START(msg, ent->number);
if (ent->active == ACTIVE_NETWORK)
int EntityState_ReadExtendBits(void)
{
unsigned int bits;
- bits = MSG_ReadByte();
+ bits = MSG_ReadByte(&cl_message);
if (bits & 0x00000080)
{
- bits |= MSG_ReadByte() << 8;
+ bits |= MSG_ReadByte(&cl_message) << 8;
if (bits & 0x00008000)
{
- bits |= MSG_ReadByte() << 16;
+ bits |= MSG_ReadByte(&cl_message) << 16;
if (bits & 0x00800000)
- bits |= MSG_ReadByte() << 24;
+ bits |= MSG_ReadByte(&cl_message) << 24;
}
}
return bits;
if (cls.protocol == PROTOCOL_DARKPLACES2)
{
if (bits & E_ORIGIN1)
- e->origin[0] = MSG_ReadCoord16i();
+ e->origin[0] = MSG_ReadCoord16i(&cl_message);
if (bits & E_ORIGIN2)
- e->origin[1] = MSG_ReadCoord16i();
+ e->origin[1] = MSG_ReadCoord16i(&cl_message);
if (bits & E_ORIGIN3)
- e->origin[2] = MSG_ReadCoord16i();
+ e->origin[2] = MSG_ReadCoord16i(&cl_message);
}
else
{
if (bits & E_FLAGS)
- e->flags = MSG_ReadByte();
+ e->flags = MSG_ReadByte(&cl_message);
if (e->flags & RENDER_LOWPRECISION)
{
if (bits & E_ORIGIN1)
- e->origin[0] = MSG_ReadCoord16i();
+ e->origin[0] = MSG_ReadCoord16i(&cl_message);
if (bits & E_ORIGIN2)
- e->origin[1] = MSG_ReadCoord16i();
+ e->origin[1] = MSG_ReadCoord16i(&cl_message);
if (bits & E_ORIGIN3)
- e->origin[2] = MSG_ReadCoord16i();
+ e->origin[2] = MSG_ReadCoord16i(&cl_message);
}
else
{
if (bits & E_ORIGIN1)
- e->origin[0] = MSG_ReadCoord32f();
+ e->origin[0] = MSG_ReadCoord32f(&cl_message);
if (bits & E_ORIGIN2)
- e->origin[1] = MSG_ReadCoord32f();
+ e->origin[1] = MSG_ReadCoord32f(&cl_message);
if (bits & E_ORIGIN3)
- e->origin[2] = MSG_ReadCoord32f();
+ e->origin[2] = MSG_ReadCoord32f(&cl_message);
}
}
if ((cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6) && !(e->flags & RENDER_LOWPRECISION))
{
if (bits & E_ANGLE1)
- e->angles[0] = MSG_ReadAngle16i();
+ e->angles[0] = MSG_ReadAngle16i(&cl_message);
if (bits & E_ANGLE2)
- e->angles[1] = MSG_ReadAngle16i();
+ e->angles[1] = MSG_ReadAngle16i(&cl_message);
if (bits & E_ANGLE3)
- e->angles[2] = MSG_ReadAngle16i();
+ e->angles[2] = MSG_ReadAngle16i(&cl_message);
}
else
{
if (bits & E_ANGLE1)
- e->angles[0] = MSG_ReadAngle8i();
+ e->angles[0] = MSG_ReadAngle8i(&cl_message);
if (bits & E_ANGLE2)
- e->angles[1] = MSG_ReadAngle8i();
+ e->angles[1] = MSG_ReadAngle8i(&cl_message);
if (bits & E_ANGLE3)
- e->angles[2] = MSG_ReadAngle8i();
+ e->angles[2] = MSG_ReadAngle8i(&cl_message);
}
if (bits & E_MODEL1)
- e->modelindex = (e->modelindex & 0xFF00) | (unsigned int) MSG_ReadByte();
+ e->modelindex = (e->modelindex & 0xFF00) | (unsigned int) MSG_ReadByte(&cl_message);
if (bits & E_MODEL2)
- e->modelindex = (e->modelindex & 0x00FF) | ((unsigned int) MSG_ReadByte() << 8);
+ e->modelindex = (e->modelindex & 0x00FF) | ((unsigned int) MSG_ReadByte(&cl_message) << 8);
if (bits & E_FRAME1)
- e->frame = (e->frame & 0xFF00) | (unsigned int) MSG_ReadByte();
+ e->frame = (e->frame & 0xFF00) | (unsigned int) MSG_ReadByte(&cl_message);
if (bits & E_FRAME2)
- e->frame = (e->frame & 0x00FF) | ((unsigned int) MSG_ReadByte() << 8);
+ e->frame = (e->frame & 0x00FF) | ((unsigned int) MSG_ReadByte(&cl_message) << 8);
if (bits & E_EFFECTS1)
- e->effects = (e->effects & 0xFF00) | (unsigned int) MSG_ReadByte();
+ e->effects = (e->effects & 0xFF00) | (unsigned int) MSG_ReadByte(&cl_message);
if (bits & E_EFFECTS2)
- e->effects = (e->effects & 0x00FF) | ((unsigned int) MSG_ReadByte() << 8);
+ e->effects = (e->effects & 0x00FF) | ((unsigned int) MSG_ReadByte(&cl_message) << 8);
if (bits & E_COLORMAP)
- e->colormap = MSG_ReadByte();
+ e->colormap = MSG_ReadByte(&cl_message);
if (bits & E_SKIN)
- e->skin = MSG_ReadByte();
+ e->skin = MSG_ReadByte(&cl_message);
if (bits & E_ALPHA)
- e->alpha = MSG_ReadByte();
+ e->alpha = MSG_ReadByte(&cl_message);
if (bits & E_SCALE)
- e->scale = MSG_ReadByte();
+ e->scale = MSG_ReadByte(&cl_message);
if (bits & E_GLOWSIZE)
- e->glowsize = MSG_ReadByte();
+ e->glowsize = MSG_ReadByte(&cl_message);
if (bits & E_GLOWCOLOR)
- e->glowcolor = MSG_ReadByte();
+ e->glowcolor = MSG_ReadByte(&cl_message);
if (cls.protocol == PROTOCOL_DARKPLACES2)
if (bits & E_FLAGS)
- e->flags = MSG_ReadByte();
+ e->flags = MSG_ReadByte(&cl_message);
if (bits & E_TAGATTACHMENT)
{
- e->tagentity = (unsigned short) MSG_ReadShort();
- e->tagindex = MSG_ReadByte();
+ e->tagentity = (unsigned short) MSG_ReadShort(&cl_message);
+ e->tagindex = MSG_ReadByte(&cl_message);
}
if (bits & E_LIGHT)
{
- e->light[0] = (unsigned short) MSG_ReadShort();
- e->light[1] = (unsigned short) MSG_ReadShort();
- e->light[2] = (unsigned short) MSG_ReadShort();
- e->light[3] = (unsigned short) MSG_ReadShort();
+ e->light[0] = (unsigned short) MSG_ReadShort(&cl_message);
+ e->light[1] = (unsigned short) MSG_ReadShort(&cl_message);
+ e->light[2] = (unsigned short) MSG_ReadShort(&cl_message);
+ e->light[3] = (unsigned short) MSG_ReadShort(&cl_message);
}
if (bits & E_LIGHTSTYLE)
- e->lightstyle = MSG_ReadByte();
+ e->lightstyle = MSG_ReadByte(&cl_message);
if (bits & E_LIGHTPFLAGS)
- e->lightpflags = MSG_ReadByte();
+ e->lightpflags = MSG_ReadByte(&cl_message);
if (developer_networkentities.integer >= 2)
{
}
}
-extern void CL_NewFrameReceived(int num);
-
// (client and server) allocates a new empty database
entityframe_database_t *EntityFrame_AllocDatabase(mempool_t *mempool)
{
// (server) writes a frame to network stream
qboolean EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t **states, int viewentnum)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, onum, number;
entity_frame_t *o = &d->deltaframe;
const entity_state_t *ent, *delta;
// read the frame header info
f->time = cl.mtime[0];
- number = MSG_ReadLong();
- f->framenum = MSG_ReadLong();
+ number = MSG_ReadLong(&cl_message);
+ f->framenum = MSG_ReadLong(&cl_message);
CL_NewFrameReceived(f->framenum);
- f->eye[0] = MSG_ReadFloat();
- f->eye[1] = MSG_ReadFloat();
- f->eye[2] = MSG_ReadFloat();
+ f->eye[0] = MSG_ReadFloat(&cl_message);
+ f->eye[1] = MSG_ReadFloat(&cl_message);
+ f->eye[2] = MSG_ReadFloat(&cl_message);
EntityFrame_AckFrame(d, number);
EntityFrame_FetchFrame(d, number, delta);
old = delta->entitydata;
oldend = old + delta->numentities;
// read entities until we hit the magic 0xFFFF end tag
- while ((number = (unsigned short) MSG_ReadShort()) != 0xFFFF && !msg_badread)
+ while ((number = (unsigned short) MSG_ReadShort(&cl_message)) != 0xFFFF && !cl_message.badread)
{
- if (msg_badread)
+ if (cl_message.badread)
Host_Error("EntityFrame_Read: read error");
removed = number & 0x8000;
number &= 0x7FFF;
cl.entitydatabase4 = EntityFrame4_AllocDatabase(cls.levelmempool);
d = cl.entitydatabase4;
// read the number of the frame this refers to
- referenceframenum = MSG_ReadLong();
+ referenceframenum = MSG_ReadLong(&cl_message);
// read the number of this frame
- framenum = MSG_ReadLong();
+ framenum = MSG_ReadLong(&cl_message);
CL_NewFrameReceived(framenum);
// read the start number
- enumber = (unsigned short) MSG_ReadShort();
+ enumber = (unsigned short) MSG_ReadShort(&cl_message);
if (developer_networkentities.integer >= 10)
{
Con_Printf("recv svc_entities num:%i ref:%i database: ref:%i commits:", framenum, referenceframenum, d->referenceframenum);
skip = true;
}
done = false;
- while (!done && !msg_badread)
+ while (!done && !cl_message.badread)
{
// read the number of the modified entity
// (gaps will be copied unmodified)
- n = (unsigned short)MSG_ReadShort();
+ n = (unsigned short)MSG_ReadShort(&cl_message);
if (n == 0x8000)
{
// no more entities in this update, but we still need to copy the
// rest of the reference entities (final gap)
done = true;
// read end of range number, then process normally
- n = (unsigned short)MSG_ReadShort();
+ n = (unsigned short)MSG_ReadShort(&cl_message);
}
// high bit means it's a remove message
cnumber = n & 0x7FFF;
qboolean EntityFrame4_WriteFrame(sizebuf_t *msg, int maxsize, entityframe4_database_t *d, int numstates, const entity_state_t **states)
{
+ prvm_prog_t *prog = SVVM_prog;
const entity_state_t *e, *s;
entity_state_t inactiveentitystate;
int i, n, startnumber;
return bound(1, priority, ENTITYFRAME5_PRIORITYLEVELS - 1);
}
+static double anim_reducetime(double t, double frameduration, double maxtime)
+{
+ if(t < 0) // clamp to non-negative
+ return 0;
+ if(t <= maxtime) // time can be represented normally
+ return t;
+ if(frameduration == 0) // don't like dividing by zero
+ return t;
+ if(maxtime <= 2 * frameduration) // if two frames don't fit, we better not do this
+ return t;
+ t -= frameduration * ceil((t - maxtime) / frameduration);
+ // now maxtime - frameduration < t <= maxtime
+ return t;
+}
+
+// see VM_SV_frameduration
+static double anim_frameduration(dp_model_t *model, int framenum)
+{
+ if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
+ return 0;
+ if(model->animscenes[framenum].framerate)
+ return model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
+ return 0;
+}
+
void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg)
{
+ prvm_prog_t *prog = SVVM_prog;
unsigned int bits = 0;
//dp_model_t *model;
ENTITYSIZEPROFILING_START(msg, s->number);
MSG_WriteShort(msg, pose6s[5]);
}
}
- else if (s->framegroupblend[3].lerp > 0)
- {
- MSG_WriteByte(msg, 3);
- MSG_WriteShort(msg, s->framegroupblend[0].frame);
- MSG_WriteShort(msg, s->framegroupblend[1].frame);
- MSG_WriteShort(msg, s->framegroupblend[2].frame);
- MSG_WriteShort(msg, s->framegroupblend[3].frame);
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0));
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[2].start) * 1000.0));
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[3].start) * 1000.0));
- MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
- MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
- MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
- MSG_WriteByte(msg, s->framegroupblend[3].lerp * 255.0f);
- }
- else if (s->framegroupblend[2].lerp > 0)
- {
- MSG_WriteByte(msg, 2);
- MSG_WriteShort(msg, s->framegroupblend[0].frame);
- MSG_WriteShort(msg, s->framegroupblend[1].frame);
- MSG_WriteShort(msg, s->framegroupblend[2].frame);
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0));
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[2].start) * 1000.0));
- MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
- MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
- MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
- }
- else if (s->framegroupblend[1].lerp > 0)
- {
- MSG_WriteByte(msg, 1);
- MSG_WriteShort(msg, s->framegroupblend[0].frame);
- MSG_WriteShort(msg, s->framegroupblend[1].frame);
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0));
- MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
- MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
- }
else
{
- MSG_WriteByte(msg, 0);
- MSG_WriteShort(msg, s->framegroupblend[0].frame);
- MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0));
+ dp_model_t *model = SV_GetModelByIndex(s->modelindex);
+ if (s->framegroupblend[3].lerp > 0)
+ {
+ MSG_WriteByte(msg, 3);
+ MSG_WriteShort(msg, s->framegroupblend[0].frame);
+ MSG_WriteShort(msg, s->framegroupblend[1].frame);
+ MSG_WriteShort(msg, s->framegroupblend[2].frame);
+ MSG_WriteShort(msg, s->framegroupblend[3].frame);
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0));
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[3].start, anim_frameduration(model, s->framegroupblend[3].frame), 65.535) * 1000.0));
+ MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
+ MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
+ MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
+ MSG_WriteByte(msg, s->framegroupblend[3].lerp * 255.0f);
+ }
+ else if (s->framegroupblend[2].lerp > 0)
+ {
+ MSG_WriteByte(msg, 2);
+ MSG_WriteShort(msg, s->framegroupblend[0].frame);
+ MSG_WriteShort(msg, s->framegroupblend[1].frame);
+ MSG_WriteShort(msg, s->framegroupblend[2].frame);
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0));
+ MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
+ MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
+ MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f);
+ }
+ else if (s->framegroupblend[1].lerp > 0)
+ {
+ MSG_WriteByte(msg, 1);
+ MSG_WriteShort(msg, s->framegroupblend[0].frame);
+ MSG_WriteShort(msg, s->framegroupblend[1].frame);
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0));
+ MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f);
+ MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f);
+ }
+ else
+ {
+ MSG_WriteByte(msg, 0);
+ MSG_WriteShort(msg, s->framegroupblend[0].frame);
+ MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0));
+ }
}
}
if (bits & E5_TRAILEFFECTNUM)
ENTITYSIZEPROFILING_END(msg, s->number);
}
-extern dp_model_t *CL_GetModelByIndex(int modelindex);
-
static void EntityState5_ReadUpdate(entity_state_t *s, int number)
{
int bits;
- bits = MSG_ReadByte();
+ bits = MSG_ReadByte(&cl_message);
if (bits & E5_EXTEND1)
{
- bits |= MSG_ReadByte() << 8;
+ bits |= MSG_ReadByte(&cl_message) << 8;
if (bits & E5_EXTEND2)
{
- bits |= MSG_ReadByte() << 16;
+ bits |= MSG_ReadByte(&cl_message) << 16;
if (bits & E5_EXTEND3)
- bits |= MSG_ReadByte() << 24;
+ bits |= MSG_ReadByte(&cl_message) << 24;
}
}
if (bits & E5_FULLUPDATE)
s->active = ACTIVE_NETWORK;
}
if (bits & E5_FLAGS)
- s->flags = MSG_ReadByte();
+ s->flags = MSG_ReadByte(&cl_message);
if (bits & E5_ORIGIN)
{
if (bits & E5_ORIGIN32)
{
- s->origin[0] = MSG_ReadCoord32f();
- s->origin[1] = MSG_ReadCoord32f();
- s->origin[2] = MSG_ReadCoord32f();
+ s->origin[0] = MSG_ReadCoord32f(&cl_message);
+ s->origin[1] = MSG_ReadCoord32f(&cl_message);
+ s->origin[2] = MSG_ReadCoord32f(&cl_message);
}
else
{
- s->origin[0] = MSG_ReadCoord13i();
- s->origin[1] = MSG_ReadCoord13i();
- s->origin[2] = MSG_ReadCoord13i();
+ s->origin[0] = MSG_ReadCoord13i(&cl_message);
+ s->origin[1] = MSG_ReadCoord13i(&cl_message);
+ s->origin[2] = MSG_ReadCoord13i(&cl_message);
}
}
if (bits & E5_ANGLES)
{
if (bits & E5_ANGLES16)
{
- s->angles[0] = MSG_ReadAngle16i();
- s->angles[1] = MSG_ReadAngle16i();
- s->angles[2] = MSG_ReadAngle16i();
+ s->angles[0] = MSG_ReadAngle16i(&cl_message);
+ s->angles[1] = MSG_ReadAngle16i(&cl_message);
+ s->angles[2] = MSG_ReadAngle16i(&cl_message);
}
else
{
- s->angles[0] = MSG_ReadAngle8i();
- s->angles[1] = MSG_ReadAngle8i();
- s->angles[2] = MSG_ReadAngle8i();
+ s->angles[0] = MSG_ReadAngle8i(&cl_message);
+ s->angles[1] = MSG_ReadAngle8i(&cl_message);
+ s->angles[2] = MSG_ReadAngle8i(&cl_message);
}
}
if (bits & E5_MODEL)
{
if (bits & E5_MODEL16)
- s->modelindex = (unsigned short) MSG_ReadShort();
+ s->modelindex = (unsigned short) MSG_ReadShort(&cl_message);
else
- s->modelindex = MSG_ReadByte();
+ s->modelindex = MSG_ReadByte(&cl_message);
}
if (bits & E5_FRAME)
{
if (bits & E5_FRAME16)
- s->frame = (unsigned short) MSG_ReadShort();
+ s->frame = (unsigned short) MSG_ReadShort(&cl_message);
else
- s->frame = MSG_ReadByte();
+ s->frame = MSG_ReadByte(&cl_message);
}
if (bits & E5_SKIN)
- s->skin = MSG_ReadByte();
+ s->skin = MSG_ReadByte(&cl_message);
if (bits & E5_EFFECTS)
{
if (bits & E5_EFFECTS32)
- s->effects = (unsigned int) MSG_ReadLong();
+ s->effects = (unsigned int) MSG_ReadLong(&cl_message);
else if (bits & E5_EFFECTS16)
- s->effects = (unsigned short) MSG_ReadShort();
+ s->effects = (unsigned short) MSG_ReadShort(&cl_message);
else
- s->effects = MSG_ReadByte();
+ s->effects = MSG_ReadByte(&cl_message);
}
if (bits & E5_ALPHA)
- s->alpha = MSG_ReadByte();
+ s->alpha = MSG_ReadByte(&cl_message);
if (bits & E5_SCALE)
- s->scale = MSG_ReadByte();
+ s->scale = MSG_ReadByte(&cl_message);
if (bits & E5_COLORMAP)
- s->colormap = MSG_ReadByte();
+ s->colormap = MSG_ReadByte(&cl_message);
if (bits & E5_ATTACHMENT)
{
- s->tagentity = (unsigned short) MSG_ReadShort();
- s->tagindex = MSG_ReadByte();
+ s->tagentity = (unsigned short) MSG_ReadShort(&cl_message);
+ s->tagindex = MSG_ReadByte(&cl_message);
}
if (bits & E5_LIGHT)
{
- s->light[0] = (unsigned short) MSG_ReadShort();
- s->light[1] = (unsigned short) MSG_ReadShort();
- s->light[2] = (unsigned short) MSG_ReadShort();
- s->light[3] = (unsigned short) MSG_ReadShort();
- s->lightstyle = MSG_ReadByte();
- s->lightpflags = MSG_ReadByte();
+ s->light[0] = (unsigned short) MSG_ReadShort(&cl_message);
+ s->light[1] = (unsigned short) MSG_ReadShort(&cl_message);
+ s->light[2] = (unsigned short) MSG_ReadShort(&cl_message);
+ s->light[3] = (unsigned short) MSG_ReadShort(&cl_message);
+ s->lightstyle = MSG_ReadByte(&cl_message);
+ s->lightpflags = MSG_ReadByte(&cl_message);
}
if (bits & E5_GLOW)
{
- s->glowsize = MSG_ReadByte();
- s->glowcolor = MSG_ReadByte();
+ s->glowsize = MSG_ReadByte(&cl_message);
+ s->glowcolor = MSG_ReadByte(&cl_message);
}
if (bits & E5_COLORMOD)
{
- s->colormod[0] = MSG_ReadByte();
- s->colormod[1] = MSG_ReadByte();
- s->colormod[2] = MSG_ReadByte();
+ s->colormod[0] = MSG_ReadByte(&cl_message);
+ s->colormod[1] = MSG_ReadByte(&cl_message);
+ s->colormod[2] = MSG_ReadByte(&cl_message);
}
if (bits & E5_GLOWMOD)
{
- s->glowmod[0] = MSG_ReadByte();
- s->glowmod[1] = MSG_ReadByte();
- s->glowmod[2] = MSG_ReadByte();
+ s->glowmod[0] = MSG_ReadByte(&cl_message);
+ s->glowmod[1] = MSG_ReadByte(&cl_message);
+ s->glowmod[2] = MSG_ReadByte(&cl_message);
}
if (bits & E5_COMPLEXANIMATION)
{
int bonenum;
int numbones;
short pose6s[6];
- type = MSG_ReadByte();
+ type = MSG_ReadByte(&cl_message);
switch(type)
{
case 0:
- s->framegroupblend[0].frame = MSG_ReadShort();
+ s->framegroupblend[0].frame = MSG_ReadShort(&cl_message);
s->framegroupblend[1].frame = 0;
s->framegroupblend[2].frame = 0;
s->framegroupblend[3].frame = 0;
- s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
+ s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
s->framegroupblend[1].start = 0;
s->framegroupblend[2].start = 0;
s->framegroupblend[3].start = 0;
s->framegroupblend[3].lerp = 0;
break;
case 1:
- s->framegroupblend[0].frame = MSG_ReadShort();
- s->framegroupblend[1].frame = MSG_ReadShort();
+ s->framegroupblend[0].frame = MSG_ReadShort(&cl_message);
+ s->framegroupblend[1].frame = MSG_ReadShort(&cl_message);
s->framegroupblend[2].frame = 0;
s->framegroupblend[3].frame = 0;
- s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
- s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
+ s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+ s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
s->framegroupblend[2].start = 0;
s->framegroupblend[3].start = 0;
- s->framegroupblend[0].lerp = MSG_ReadByte() * (1.0f / 255.0f);
- s->framegroupblend[1].lerp = MSG_ReadByte() * (1.0f / 255.0f);
+ s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
+ s->framegroupblend[1].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
s->framegroupblend[2].lerp = 0;
s->framegroupblend[3].lerp = 0;
break;
case 2:
- s->framegroupblend[0].frame = MSG_ReadShort();
- s->framegroupblend[1].frame = MSG_ReadShort();
- s->framegroupblend[2].frame = MSG_ReadShort();
+ s->framegroupblend[0].frame = MSG_ReadShort(&cl_message);
+ s->framegroupblend[1].frame = MSG_ReadShort(&cl_message);
+ s->framegroupblend[2].frame = MSG_ReadShort(&cl_message);
s->framegroupblend[3].frame = 0;
- s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
- s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
- s->framegroupblend[2].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
+ s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+ s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+ s->framegroupblend[2].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
s->framegroupblend[3].start = 0;
- s->framegroupblend[0].lerp = MSG_ReadByte() * (1.0f / 255.0f);
- s->framegroupblend[1].lerp = MSG_ReadByte() * (1.0f / 255.0f);
- s->framegroupblend[2].lerp = MSG_ReadByte() * (1.0f / 255.0f);
+ s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
+ s->framegroupblend[1].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
+ s->framegroupblend[2].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
s->framegroupblend[3].lerp = 0;
break;
case 3:
- s->framegroupblend[0].frame = MSG_ReadShort();
- s->framegroupblend[1].frame = MSG_ReadShort();
- s->framegroupblend[2].frame = MSG_ReadShort();
- s->framegroupblend[3].frame = MSG_ReadShort();
- s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
- s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
- s->framegroupblend[2].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
- s->framegroupblend[3].start = cl.time - (short)MSG_ReadShort() * (1.0f / 1000.0f);
- s->framegroupblend[0].lerp = MSG_ReadByte() * (1.0f / 255.0f);
- s->framegroupblend[1].lerp = MSG_ReadByte() * (1.0f / 255.0f);
- s->framegroupblend[2].lerp = MSG_ReadByte() * (1.0f / 255.0f);
- s->framegroupblend[3].lerp = MSG_ReadByte() * (1.0f / 255.0f);
+ s->framegroupblend[0].frame = MSG_ReadShort(&cl_message);
+ s->framegroupblend[1].frame = MSG_ReadShort(&cl_message);
+ s->framegroupblend[2].frame = MSG_ReadShort(&cl_message);
+ s->framegroupblend[3].frame = MSG_ReadShort(&cl_message);
+ s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+ s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+ s->framegroupblend[2].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+ s->framegroupblend[3].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f);
+ s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
+ s->framegroupblend[1].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
+ s->framegroupblend[2].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
+ s->framegroupblend[3].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f);
break;
case 4:
if (!cl.engineskeletonobjects)
cl.engineskeletonobjects = (skeleton_t *) Mem_Alloc(cls.levelmempool, sizeof(*cl.engineskeletonobjects) * MAX_EDICTS);
skeleton = &cl.engineskeletonobjects[number];
- modelindex = MSG_ReadShort();
+ modelindex = MSG_ReadShort(&cl_message);
model = CL_GetModelByIndex(modelindex);
- numbones = MSG_ReadByte();
+ numbones = MSG_ReadByte(&cl_message);
if (model && numbones != model->num_bones)
Host_Error("E5_COMPLEXANIMATION: model has different number of bones than network packet describes\n");
if (!skeleton->relativetransforms || skeleton->model != model)
}
for (bonenum = 0;bonenum < numbones;bonenum++)
{
- pose6s[0] = (short)MSG_ReadShort();
- pose6s[1] = (short)MSG_ReadShort();
- pose6s[2] = (short)MSG_ReadShort();
- pose6s[3] = (short)MSG_ReadShort();
- pose6s[4] = (short)MSG_ReadShort();
- pose6s[5] = (short)MSG_ReadShort();
+ pose6s[0] = (short)MSG_ReadShort(&cl_message);
+ pose6s[1] = (short)MSG_ReadShort(&cl_message);
+ pose6s[2] = (short)MSG_ReadShort(&cl_message);
+ pose6s[3] = (short)MSG_ReadShort(&cl_message);
+ pose6s[4] = (short)MSG_ReadShort(&cl_message);
+ pose6s[5] = (short)MSG_ReadShort(&cl_message);
Matrix4x4_FromBonePose6s(skeleton->relativetransforms + bonenum, 1.0f / 64.0f, pose6s);
}
s->skeletonobject = *skeleton;
}
}
if (bits & E5_TRAILEFFECTNUM)
- s->traileffectnum = (unsigned short) MSG_ReadShort();
+ s->traileffectnum = (unsigned short) MSG_ReadShort(&cl_message);
if (developer_networkentities.integer >= 2)
if (o->glowmod[0] != n->glowmod[0] || o->glowmod[1] != n->glowmod[1] || o->glowmod[2] != n->glowmod[2])
bits |= E5_GLOWMOD;
if (n->flags & RENDER_COMPLEXANIMATION)
- bits |= E5_COMPLEXANIMATION;
+ {
+ if ((o->skeletonobject.model && o->skeletonobject.relativetransforms) != (n->skeletonobject.model && n->skeletonobject.relativetransforms))
+ {
+ bits |= E5_COMPLEXANIMATION;
+ }
+ else if (o->skeletonobject.model && o->skeletonobject.relativetransforms)
+ {
+ if(o->modelindex != n->modelindex)
+ bits |= E5_COMPLEXANIMATION;
+ else if(o->skeletonobject.model->num_bones != n->skeletonobject.model->num_bones)
+ bits |= E5_COMPLEXANIMATION;
+ else if(memcmp(o->skeletonobject.relativetransforms, n->skeletonobject.relativetransforms, o->skeletonobject.model->num_bones * sizeof(*o->skeletonobject.relativetransforms)))
+ bits |= E5_COMPLEXANIMATION;
+ }
+ else if (memcmp(o->framegroupblend, n->framegroupblend, sizeof(o->framegroupblend)))
+ {
+ bits |= E5_COMPLEXANIMATION;
+ }
+ }
if (o->traileffectnum != n->traileffectnum)
bits |= E5_TRAILEFFECTNUM;
}
entity_t *ent;
entity_state_t *s;
// read the number of this frame to echo back in next input packet
- framenum = MSG_ReadLong();
+ framenum = MSG_ReadLong(&cl_message);
CL_NewFrameReceived(framenum);
if (cls.protocol != PROTOCOL_QUAKE && cls.protocol != PROTOCOL_QUAKEDP && cls.protocol != PROTOCOL_NEHAHRAMOVIE && cls.protocol != PROTOCOL_DARKPLACES1 && cls.protocol != PROTOCOL_DARKPLACES2 && cls.protocol != PROTOCOL_DARKPLACES3 && cls.protocol != PROTOCOL_DARKPLACES4 && cls.protocol != PROTOCOL_DARKPLACES5 && cls.protocol != PROTOCOL_DARKPLACES6)
- cls.servermovesequence = MSG_ReadLong();
+ cls.servermovesequence = MSG_ReadLong(&cl_message);
// read entity numbers until we find a 0x8000
// (which would be remove world entity, but is actually a terminator)
- while ((n = (unsigned short)MSG_ReadShort()) != 0x8000 && !msg_badread)
+ while ((n = (unsigned short)MSG_ReadShort(&cl_message)) != 0x8000 && !cl_message.badread)
{
// get the entity number
enumber = n & 0x7FFF;
qboolean EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t **states, int viewentnum, int movesequence, qboolean need_empty)
{
+ prvm_prog_t *prog = SVVM_prog;
const entity_state_t *n;
int i, num, l, framenum, packetlognumber, priority;
sizebuf_t buf;
void EntityStateQW_ReadPlayerUpdate(void)
{
- int slot = MSG_ReadByte();
+ int slot = MSG_ReadByte(&cl_message);
int enumber = slot + 1;
int weaponframe;
int msec;
s->active = ACTIVE_NETWORK;
s->number = enumber;
s->colormap = enumber;
- playerflags = MSG_ReadShort();
- MSG_ReadVector(s->origin, cls.protocol);
- s->frame = MSG_ReadByte();
+ playerflags = MSG_ReadShort(&cl_message);
+ MSG_ReadVector(&cl_message, s->origin, cls.protocol);
+ s->frame = MSG_ReadByte(&cl_message);
VectorClear(viewangles);
VectorClear(velocity);
// and last input we sent to the server (this packet is in response to
// our input, so msec is how long ago the last update of this player
// entity occurred, compared to our input being received)
- msec = MSG_ReadByte();
+ msec = MSG_ReadByte(&cl_message);
}
else
msec = 0;
if (playerflags & QW_PF_COMMAND)
{
- bits = MSG_ReadByte();
+ bits = MSG_ReadByte(&cl_message);
if (bits & QW_CM_ANGLE1)
- viewangles[0] = MSG_ReadAngle16i(); // cmd->angles[0]
+ viewangles[0] = MSG_ReadAngle16i(&cl_message); // cmd->angles[0]
if (bits & QW_CM_ANGLE2)
- viewangles[1] = MSG_ReadAngle16i(); // cmd->angles[1]
+ viewangles[1] = MSG_ReadAngle16i(&cl_message); // cmd->angles[1]
if (bits & QW_CM_ANGLE3)
- viewangles[2] = MSG_ReadAngle16i(); // cmd->angles[2]
+ viewangles[2] = MSG_ReadAngle16i(&cl_message); // cmd->angles[2]
if (bits & QW_CM_FORWARD)
- MSG_ReadShort(); // cmd->forwardmove
+ MSG_ReadShort(&cl_message); // cmd->forwardmove
if (bits & QW_CM_SIDE)
- MSG_ReadShort(); // cmd->sidemove
+ MSG_ReadShort(&cl_message); // cmd->sidemove
if (bits & QW_CM_UP)
- MSG_ReadShort(); // cmd->upmove
+ MSG_ReadShort(&cl_message); // cmd->upmove
if (bits & QW_CM_BUTTONS)
- (void) MSG_ReadByte(); // cmd->buttons
+ (void) MSG_ReadByte(&cl_message); // cmd->buttons
if (bits & QW_CM_IMPULSE)
- (void) MSG_ReadByte(); // cmd->impulse
- (void) MSG_ReadByte(); // cmd->msec
+ (void) MSG_ReadByte(&cl_message); // cmd->impulse
+ (void) MSG_ReadByte(&cl_message); // cmd->msec
}
if (playerflags & QW_PF_VELOCITY1)
- velocity[0] = MSG_ReadShort();
+ velocity[0] = MSG_ReadShort(&cl_message);
if (playerflags & QW_PF_VELOCITY2)
- velocity[1] = MSG_ReadShort();
+ velocity[1] = MSG_ReadShort(&cl_message);
if (playerflags & QW_PF_VELOCITY3)
- velocity[2] = MSG_ReadShort();
+ velocity[2] = MSG_ReadShort(&cl_message);
if (playerflags & QW_PF_MODEL)
- s->modelindex = MSG_ReadByte();
+ s->modelindex = MSG_ReadByte(&cl_message);
else
s->modelindex = cl.qw_modelindex_player;
if (playerflags & QW_PF_SKINNUM)
- s->skin = MSG_ReadByte();
+ s->skin = MSG_ReadByte(&cl_message);
if (playerflags & QW_PF_EFFECTS)
- QW_TranslateEffects(s, MSG_ReadByte());
+ QW_TranslateEffects(s, MSG_ReadByte(&cl_message));
if (playerflags & QW_PF_WEAPONFRAME)
- weaponframe = MSG_ReadByte();
+ weaponframe = MSG_ReadByte(&cl_message);
else
weaponframe = 0;
s->number = bits & 511;
bits &= ~511;
if (bits & QW_U_MOREBITS)
- bits |= MSG_ReadByte();
+ bits |= MSG_ReadByte(&cl_message);
// store the QW_U_SOLID bit here?
if (bits & QW_U_MODEL)
- s->modelindex = MSG_ReadByte();
+ s->modelindex = MSG_ReadByte(&cl_message);
if (bits & QW_U_FRAME)
- s->frame = MSG_ReadByte();
+ s->frame = MSG_ReadByte(&cl_message);
if (bits & QW_U_COLORMAP)
- s->colormap = MSG_ReadByte();
+ s->colormap = MSG_ReadByte(&cl_message);
if (bits & QW_U_SKIN)
- s->skin = MSG_ReadByte();
+ s->skin = MSG_ReadByte(&cl_message);
if (bits & QW_U_EFFECTS)
- QW_TranslateEffects(s, qweffects = MSG_ReadByte());
+ QW_TranslateEffects(s, qweffects = MSG_ReadByte(&cl_message));
if (bits & QW_U_ORIGIN1)
- s->origin[0] = MSG_ReadCoord13i();
+ s->origin[0] = MSG_ReadCoord13i(&cl_message);
if (bits & QW_U_ANGLE1)
- s->angles[0] = MSG_ReadAngle8i();
+ s->angles[0] = MSG_ReadAngle8i(&cl_message);
if (bits & QW_U_ORIGIN2)
- s->origin[1] = MSG_ReadCoord13i();
+ s->origin[1] = MSG_ReadCoord13i(&cl_message);
if (bits & QW_U_ANGLE2)
- s->angles[1] = MSG_ReadAngle8i();
+ s->angles[1] = MSG_ReadAngle8i(&cl_message);
if (bits & QW_U_ORIGIN3)
- s->origin[2] = MSG_ReadCoord13i();
+ s->origin[2] = MSG_ReadCoord13i(&cl_message);
if (bits & QW_U_ANGLE3)
- s->angles[2] = MSG_ReadAngle8i();
+ s->angles[2] = MSG_ReadAngle8i(&cl_message);
if (developer_networkentities.integer >= 2)
{
oldsnap = NULL;
if (delta)
{
- number = MSG_ReadByte();
+ number = MSG_ReadByte(&cl_message);
oldsnapindex = cl.qw_deltasequence[newsnapindex];
if ((number & QW_UPDATE_MASK) != (oldsnapindex & QW_UPDATE_MASK))
Con_DPrintf("WARNING: from mismatch\n");
oldindex = 0;
for (;;)
{
- int word = (unsigned short)MSG_ReadShort();
- if (msg_badread)
+ int word = (unsigned short)MSG_ReadShort(&cl_message);
+ if (cl_message.badread)
return; // just return, the main parser will print an error
newnum = word == 0 ? 512 : (word & 511);
oldnum = delta ? (oldindex >= oldsnap->num_entities ? 9999 : oldsnap->entities[oldindex].number) : 9999;
#define SND_LOOPING (1<<2) // a long
#define SND_LARGEENTITY (1<<3) // a short and a byte (instead of a short)
#define SND_LARGESOUND (1<<4) // a short (instead of a byte)
+#define SND_SPEEDUSHORT4000 (1<<5) // ushort speed*4000 (speed is usually 1.0, a value of 0.0 is the same as 1.0)
// defaults for clientinfo messages
#define RENDER_EXTERIORMODEL 8
#define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth
#define RENDER_COLORMAPPED 32
-#define RENDER_NOCULL 64 // do not cull this entity with r_cullentities
+#define RENDER_WORLDOBJECT 64 // do not cull this entity with r_cullentities
#define RENDER_COMPLEXANIMATION 128
#define RENDER_SHADOW 65536 // cast shadow
#define RENDER_NODEPTHTEST 1048576
#define RENDER_ADDITIVE 2097152
#define RENDER_DOUBLESIDED 4194304
+#define RENDER_CUSTOMIZEDMODELLIGHT 4096
#define MAX_FRAMEGROUPBLENDS 4
typedef struct framegroupblend_s
#include "cl_collision.h"
#include "clvm_cmds.h"
+#include "csprogs.h"
#include "ft2.h"
+#include "mdfour.h"
extern cvar_t prvm_backtraceforwarnings;
// LordHavoc: changed this to NOT use a return statement, so that it can be used in functions that must return a value
-void VM_Warning(const char *fmt, ...)
+void VM_Warning(prvm_prog_t *prog, const char *fmt, ...)
{
va_list argptr;
char msg[MAX_INPUTLINE];
dpvsnprintf(msg,sizeof(msg),fmt,argptr);
va_end(argptr);
- Con_DPrint(msg);
+ Con_Print(msg);
// TODO: either add a cvar/cmd to control the state dumping or replace some of the calls with Con_Printf [9/13/2006 Black]
if(prvm_backtraceforwarnings.integer && recursive != realtime) // NOTE: this compares to the time, just in case if PRVM_PrintState causes a Host_Error and keeps recursive set
{
recursive = realtime;
- PRVM_PrintState();
+ PRVM_PrintState(prog);
recursive = -1;
}
}
// TODO: (move vm_files and vm_fssearchlist to prvm_prog_t struct again) [2007-01-23 LordHavoc]
// TODO: will this war ever end? [2007-01-23 LordHavoc]
-void VM_CheckEmptyString (const char *s)
+void VM_CheckEmptyString(prvm_prog_t *prog, const char *s)
{
if (ISWHITESPACE(s[0]))
- PRVM_ERROR ("%s: Bad string", PRVM_NAME);
+ prog->error_cmd("%s: Bad string", prog->name);
}
-void VM_GenerateFrameGroupBlend(framegroupblend_t *framegroupblend, const prvm_edict_t *ed)
+void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroupblend, const prvm_edict_t *ed)
{
// self.frame is the interpolation target (new frame)
// self.frame1time is the animation base time for the interpolation target
f = g->frame;
if ((unsigned int)f >= (unsigned int)numframes)
{
- Con_DPrintf("VM_FrameBlendFromFrameGroupBlend: no such frame %d in model %s\n", f, model->name);
+ if (developer_extra.integer)
+ Con_DPrintf("VM_FrameBlendFromFrameGroupBlend: no such frame %d in model %s\n", f, model->name);
f = 0;
}
d = lerp = g->lerp;
}
}
-void VM_UpdateEdictSkeleton(prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend)
+void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend)
{
if (ed->priv.server->skeleton.model != edmodel)
{
- VM_RemoveEdictSkeleton(ed);
+ VM_RemoveEdictSkeleton(prog, ed);
ed->priv.server->skeleton.model = edmodel;
}
if (!ed->priv.server->skeleton.model || !ed->priv.server->skeleton.model->num_bones)
}
}
-void VM_RemoveEdictSkeleton(prvm_edict_t *ed)
+void VM_RemoveEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed)
{
if (ed->priv.server->skeleton.relativetransforms)
Mem_Free(ed->priv.server->skeleton.relativetransforms);
//============================================================================
//BUILT-IN FUNCTIONS
-void VM_VarString(int first, char *out, int outlength)
+void VM_VarString(prvm_prog_t *prog, int first, char *out, int outlength)
{
int i;
const char *s;
*/
// kind of helper function
-static qboolean checkextension(const char *name)
+static qboolean checkextension(prvm_prog_t *prog, const char *name)
{
int len;
const char *e, *start;
return false;
#endif
}
+
+ // special sheck for d0_blind_id
+ if (!strcasecmp("DP_CRYPTO", name))
+ return Crypto_Available();
+ if (!strcasecmp("DP_QC_DIGEST_SHA256", name))
+ return Crypto_Available();
+
return true;
}
}
return false;
}
-void VM_checkextension (void)
+void VM_checkextension(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_checkextension);
- PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
+ PRVM_G_FLOAT(OFS_RETURN) = checkextension(prog, PRVM_G_STRING(OFS_PARM0));
}
/*
error(value)
=================
*/
-void VM_error (void)
+void VM_error(prvm_prog_t *prog)
{
prvm_edict_t *ed;
char string[VM_STRINGTEMP_LENGTH];
- VM_VarString(0, string, sizeof(string));
- Con_Printf("======%s ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
+ VM_VarString(prog, 0, string, sizeof(string));
+ Con_Printf("======%s ERROR in %s:\n%s\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string);
ed = PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self));
- PRVM_ED_Print(ed, NULL);
+ PRVM_ED_Print(prog, ed, NULL);
- PRVM_ERROR ("%s: Program error in function %s:\n%s\nTip: read above for entity information\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
+ prog->error_cmd("%s: Program error in function %s:\n%s\nTip: read above for entity information\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string);
}
/*
objerror(value)
=================
*/
-void VM_objerror (void)
+void VM_objerror(prvm_prog_t *prog)
{
prvm_edict_t *ed;
char string[VM_STRINGTEMP_LENGTH];
- VM_VarString(0, string, sizeof(string));
- Con_Printf("======OBJECT ERROR======\n"); // , PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string); // or include them? FIXME
+ VM_VarString(prog, 0, string, sizeof(string));
+ Con_Printf("======OBJECT ERROR======\n"); // , prog->name, PRVM_GetString(prog->xfunction->s_name), string); // or include them? FIXME
ed = PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self));
- PRVM_ED_Print(ed, NULL);
- PRVM_ED_Free (ed);
- Con_Printf("%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
+ PRVM_ED_Print(prog, ed, NULL);
+ PRVM_ED_Free (prog, ed);
+ Con_Printf("%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string);
}
/*
print(...[string])
=================
*/
-void VM_print (void)
+void VM_print(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
Con_Print(string);
}
bprint(...[string])
=================
*/
-void VM_bprint (void)
+void VM_bprint(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
if(!sv.active)
{
- VM_Warning("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
+ VM_Warning(prog, "VM_bprint: game is not server(%s) !\n", prog->name);
return;
}
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
SV_BroadcastPrint(string);
}
sprint(float clientnum,...[string])
=================
*/
-void VM_sprint (void)
+void VM_sprint(prvm_prog_t *prog)
{
client_t *client;
int clientnum;
clientnum = (int)PRVM_G_FLOAT(OFS_PARM0);
if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
{
- VM_Warning("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
+ VM_Warning(prog, "VM_sprint: %s: invalid client or server is not active !\n", prog->name);
return;
}
if (!client->netconnection)
return;
- VM_VarString(1, string, sizeof(string));
+ VM_VarString(prog, 1, string, sizeof(string));
MSG_WriteChar(&client->netconnection->message,svc_print);
MSG_WriteString(&client->netconnection->message, string);
}
centerprint(value)
=================
*/
-void VM_centerprint (void)
+void VM_centerprint(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1, 8, VM_centerprint);
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
SCR_CenterPrint(string);
}
vector normalize(vector)
=================
*/
-void VM_normalize (void)
+void VM_normalize(prvm_prog_t *prog)
{
float *value1;
vec3_t newvalue;
scalar vlen(vector)
=================
*/
-void VM_vlen (void)
+void VM_vlen(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_vlen);
PRVM_G_FLOAT(OFS_RETURN) = VectorLength(PRVM_G_VECTOR(OFS_PARM0));
float vectoyaw(vector)
=================
*/
-void VM_vectoyaw (void)
+void VM_vectoyaw(prvm_prog_t *prog)
{
float *value1;
float yaw;
vector vectoangles(vector[, vector])
=================
*/
-void VM_vectoangles (void)
+void VM_vectoangles(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNTRANGE(1, 2,VM_vectoangles);
float random()
=================
*/
-void VM_random (void)
+void VM_random(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_random);
localsound(string sample)
=========
*/
-void VM_localsound(void)
+void VM_localsound(prvm_prog_t *prog)
{
const char *s;
if(!S_LocalSound (s))
{
PRVM_G_FLOAT(OFS_RETURN) = -4;
- VM_Warning("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
+ VM_Warning(prog, "VM_localsound: Failed to play %s for %s !\n", s, prog->name);
return;
}
break()
=================
*/
-void VM_break (void)
+void VM_break(prvm_prog_t *prog)
{
- PRVM_ERROR ("%s: break statement", PRVM_NAME);
+ prog->error_cmd("%s: break statement", prog->name);
}
//============================================================================
cmd (string, ...)
=================
*/
-void VM_localcmd (void)
+void VM_localcmd(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd);
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
Cbuf_AddText(string);
}
float cvar (string)
=================
*/
-void VM_cvar (void)
+void VM_cvar(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar);
- VM_VarString(0, string, sizeof(string));
- VM_CheckEmptyString(string);
+ VM_VarString(prog, 0, string, sizeof(string));
+ VM_CheckEmptyString(prog, string);
PRVM_G_FLOAT(OFS_RETURN) = PRVM_Cvar_ReadOk(string) ? Cvar_VariableValue(string) : 0;
}
float CVAR_TYPEFLAG_READONLY = 32;
=================
*/
-void VM_cvar_type (void)
+void VM_cvar_type(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
cvar_t *cvar;
int ret;
VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar);
- VM_VarString(0, string, sizeof(string));
- VM_CheckEmptyString(string);
+ VM_VarString(prog, 0, string, sizeof(string));
+ VM_CheckEmptyString(prog, string);
cvar = Cvar_FindVar(string);
const string VM_cvar_string (string, ...)
=================
*/
-void VM_cvar_string(void)
+void VM_cvar_string(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_string);
- VM_VarString(0, string, sizeof(string));
- VM_CheckEmptyString(string);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(PRVM_Cvar_ReadOk(string) ? Cvar_VariableString(string) : "");
+ VM_VarString(prog, 0, string, sizeof(string));
+ VM_CheckEmptyString(prog, string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_Cvar_ReadOk(string) ? Cvar_VariableString(string) : "");
}
const string VM_cvar_defstring (string, ...)
========================
*/
-void VM_cvar_defstring (void)
+void VM_cvar_defstring(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_defstring);
- VM_VarString(0, string, sizeof(string));
- VM_CheckEmptyString(string);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Cvar_VariableDefString(string));
+ VM_VarString(prog, 0, string, sizeof(string));
+ VM_CheckEmptyString(prog, string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDefString(string));
}
/*
const string VM_cvar_description (string, ...)
========================
*/
-void VM_cvar_description (void)
+void VM_cvar_description(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_description);
- VM_VarString(0, string, sizeof(string));
- VM_CheckEmptyString(string);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Cvar_VariableDescription(string));
+ VM_VarString(prog, 0, string, sizeof(string));
+ VM_CheckEmptyString(prog, string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDescription(string));
}
/*
=================
void cvar_set (string,string, ...)
=================
*/
-void VM_cvar_set (void)
+void VM_cvar_set(prvm_prog_t *prog)
{
const char *name;
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(2,8,VM_cvar_set);
- VM_VarString(1, string, sizeof(string));
+ VM_VarString(prog, 1, string, sizeof(string));
name = PRVM_G_STRING(OFS_PARM0);
- VM_CheckEmptyString(name);
+ VM_CheckEmptyString(prog, name);
Cvar_Set(name, string);
}
dprint(...[string])
=========
*/
-void VM_dprint (void)
+void VM_dprint(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1, 8, VM_dprint);
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
#if 1
Con_DPrintf("%s", string);
#else
- Con_DPrintf("%s: %s", PRVM_NAME, string);
+ Con_DPrintf("%s: %s", prog->name, string);
#endif
}
=========
*/
-void VM_ftos (void)
+void VM_ftos(prvm_prog_t *prog)
{
float v;
char s[128];
dpsnprintf(s, sizeof(s), "%i", (int)v);
else
dpsnprintf(s, sizeof(s), "%f", v);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
}
/*
=========
*/
-void VM_fabs (void)
+void VM_fabs(prvm_prog_t *prog)
{
float v;
=========
*/
-void VM_vtos (void)
+void VM_vtos(prvm_prog_t *prog)
{
char s[512];
VM_SAFEPARMCOUNT(1,VM_vtos);
dpsnprintf (s, sizeof(s), "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
}
/*
=========
*/
-void VM_etos (void)
+void VM_etos(prvm_prog_t *prog)
{
char s[128];
VM_SAFEPARMCOUNT(1, VM_etos);
dpsnprintf (s, sizeof(s), "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
}
/*
float stof(...[string])
=========
*/
-void VM_stof(void)
+void VM_stof(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1, 8, VM_stof);
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
PRVM_G_FLOAT(OFS_RETURN) = atof(string);
}
float itof(intt ent)
========================
*/
-void VM_itof(void)
+void VM_itof(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_itof);
PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
entity ftoe(float num)
========================
*/
-void VM_ftoe(void)
+void VM_ftoe(prvm_prog_t *prog)
{
int ent;
VM_SAFEPARMCOUNT(1, VM_ftoe);
float etof(entity ent)
========================
*/
-void VM_etof(void)
+void VM_etof(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_etof);
PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_EDICTNUM(OFS_PARM0);
string strftime(float uselocaltime, string[, string ...])
=========
*/
-void VM_strftime(void)
+void VM_strftime(prvm_prog_t *prog)
{
time_t t;
#if _MSC_VER >= 1400
char fmt[VM_STRINGTEMP_LENGTH];
char result[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(2, 8, VM_strftime);
- VM_VarString(1, fmt, sizeof(fmt));
+ VM_VarString(prog, 1, fmt, sizeof(fmt));
t = time(NULL);
#if _MSC_VER >= 1400
if (PRVM_G_FLOAT(OFS_PARM0))
#else
strftime(result, sizeof(result), fmt, tm);
#endif
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(result);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, result);
}
/*
=========
*/
-void VM_spawn (void)
+void VM_spawn(prvm_prog_t *prog)
{
prvm_edict_t *ed;
VM_SAFEPARMCOUNT(0, VM_spawn);
prog->xfunction->builtinsprofile += 20;
- ed = PRVM_ED_Alloc();
+ ed = PRVM_ED_Alloc(prog);
VM_RETURN_EDICT(ed);
}
=========
*/
-void VM_remove (void)
+void VM_remove(prvm_prog_t *prog)
{
prvm_edict_t *ed;
prog->xfunction->builtinsprofile += 20;
if( PRVM_NUM_FOR_EDICT(ed) <= prog->reserved_edicts )
{
if (developer.integer > 0)
- VM_Warning( "VM_remove: tried to remove the null entity or a reserved entity!\n" );
+ VM_Warning(prog, "VM_remove: tried to remove the null entity or a reserved entity!\n" );
}
else if( ed->priv.required->free )
{
if (developer.integer > 0)
- VM_Warning( "VM_remove: tried to remove an already freed entity!\n" );
+ VM_Warning(prog, "VM_remove: tried to remove an already freed entity!\n" );
}
else
- PRVM_ED_Free (ed);
+ PRVM_ED_Free (prog, ed);
}
/*
=========
*/
-void VM_find (void)
+void VM_find(prvm_prog_t *prog)
{
int e;
int f;
=========
*/
// LordHavoc: added this for searching float, int, and entity reference fields
-void VM_findfloat (void)
+void VM_findfloat(prvm_prog_t *prog)
{
int e;
int f;
*/
// chained search for strings in entity fields
// entity(.string field, string match) findchain = #402;
-void VM_findchain (void)
+void VM_findchain(prvm_prog_t *prog)
{
int i;
int f;
else
chainfield = prog->fieldoffsets.chain;
if (chainfield < 0)
- PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
+ prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
chain = prog->edicts;
*/
// LordHavoc: chained search for float, int, and entity reference fields
// entity(.string field, float match) findchainfloat = #403;
-void VM_findchainfloat (void)
+void VM_findchainfloat(prvm_prog_t *prog)
{
int i;
int f;
else
chainfield = prog->fieldoffsets.chain;
if (chainfield < 0)
- PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
+ prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
chain = (prvm_edict_t *)prog->edicts;
========================
*/
// LordHavoc: search for flags in float fields
-void VM_findflags (void)
+void VM_findflags(prvm_prog_t *prog)
{
int e;
int f;
========================
*/
// LordHavoc: chained search for flags in float fields
-void VM_findchainflags (void)
+void VM_findchainflags(prvm_prog_t *prog)
{
int i;
int f;
else
chainfield = prog->fieldoffsets.chain;
if (chainfield < 0)
- PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
+ prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
chain = (prvm_edict_t *)prog->edicts;
string precache_sound (string sample)
=========
*/
-void VM_precache_sound (void)
+void VM_precache_sound(prvm_prog_t *prog)
{
const char *s;
s = PRVM_G_STRING(OFS_PARM0);
PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
- //VM_CheckEmptyString(s);
+ //VM_CheckEmptyString(prog, s);
if(snd_initialized.integer && !S_PrecacheSound(s, true, true))
{
- VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
+ VM_Warning(prog, "VM_precache_sound: Failed to load %s for %s\n", s, prog->name);
return;
}
}
does nothing, only used by qcc to build .pak archives
=================
*/
-void VM_precache_file (void)
+void VM_precache_file(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_precache_file);
// precache_file is only used to copy files with qcc, it does nothing
coredump()
=========
*/
-void VM_coredump (void)
+void VM_coredump(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_coredump);
Cbuf_AddText("prvm_edicts ");
- Cbuf_AddText(PRVM_NAME);
+ Cbuf_AddText(prog->name);
Cbuf_AddText("\n");
}
stackdump()
=========
*/
-void PRVM_StackTrace(void);
-void VM_stackdump (void)
+void VM_stackdump(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_stackdump);
- PRVM_StackTrace();
+ PRVM_StackTrace(prog);
}
/*
=========
*/
-void VM_crash(void)
+void VM_crash(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_crash);
- PRVM_ERROR("Crash called by %s",PRVM_NAME);
+ prog->error_cmd("Crash called by %s",prog->name);
}
/*
traceon()
=========
*/
-void VM_traceon (void)
+void VM_traceon(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_traceon);
traceoff()
=========
*/
-void VM_traceoff (void)
+void VM_traceoff(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_traceoff);
eprint(entity e)
=========
*/
-void VM_eprint (void)
+void VM_eprint(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_eprint);
- PRVM_ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0), NULL);
+ PRVM_ED_PrintNum (prog, PRVM_G_EDICTNUM(OFS_PARM0), NULL);
}
/*
float rint(float)
=========
*/
-void VM_rint (void)
+void VM_rint(prvm_prog_t *prog)
{
float f;
VM_SAFEPARMCOUNT(1,VM_rint);
float floor(float)
=========
*/
-void VM_floor (void)
+void VM_floor(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_floor);
float ceil(float)
=========
*/
-void VM_ceil (void)
+void VM_ceil(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_ceil);
entity nextent(entity)
=============
*/
-void VM_nextent (void)
+void VM_nextent(prvm_prog_t *prog)
{
int i;
prvm_edict_t *ent;
changelevel(string map)
==============
*/
-void VM_changelevel (void)
+void VM_changelevel(prvm_prog_t *prog)
{
+ char vabuf[1024];
VM_SAFEPARMCOUNT(1, VM_changelevel);
if(!sv.active)
{
- VM_Warning("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
+ VM_Warning(prog, "VM_changelevel: game is not server (%s)\n", prog->name);
return;
}
return;
svs.changelevel_issued = true;
- Cbuf_AddText (va("changelevel %s\n",PRVM_G_STRING(OFS_PARM0)));
+ Cbuf_AddText(va(vabuf, sizeof(vabuf), "changelevel %s\n",PRVM_G_STRING(OFS_PARM0)));
}
/*
float sin(float)
=========
*/
-void VM_sin (void)
+void VM_sin(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_sin);
PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
float cos(float)
=========
*/
-void VM_cos (void)
+void VM_cos(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_cos);
PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
float sqrt(float)
=========
*/
-void VM_sqrt (void)
+void VM_sqrt(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_sqrt);
PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
float asin(float)
=========
*/
-void VM_asin (void)
+void VM_asin(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_asin);
PRVM_G_FLOAT(OFS_RETURN) = asin(PRVM_G_FLOAT(OFS_PARM0));
float acos(float)
=========
*/
-void VM_acos (void)
+void VM_acos(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_acos);
PRVM_G_FLOAT(OFS_RETURN) = acos(PRVM_G_FLOAT(OFS_PARM0));
float atan(float)
=========
*/
-void VM_atan (void)
+void VM_atan(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_atan);
PRVM_G_FLOAT(OFS_RETURN) = atan(PRVM_G_FLOAT(OFS_PARM0));
float atan2(float,float)
=========
*/
-void VM_atan2 (void)
+void VM_atan2(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2,VM_atan2);
PRVM_G_FLOAT(OFS_RETURN) = atan2(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
float tan(float)
=========
*/
-void VM_tan (void)
+void VM_tan(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_tan);
PRVM_G_FLOAT(OFS_RETURN) = tan(PRVM_G_FLOAT(OFS_PARM0));
vector randomvec()
=================
*/
-void VM_randomvec (void)
+void VM_randomvec(prvm_prog_t *prog)
{
- vec3_t temp;
- //float length;
-
+ vec3_t temp;
VM_SAFEPARMCOUNT(0, VM_randomvec);
-
- //// WTF ??
- do
- {
- temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
- temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
- temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
- }
- while (DotProduct(temp, temp) >= 1);
- VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
-
- /*
- temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
- temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
- temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
- // length returned always > 0
- length = (rand()&32766 + 1) * (1.0 / 32767.0) / VectorLength(temp);
- VectorScale(temp,length, temp);*/
- //VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
+ VectorRandom(temp);
+ VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
}
//=============================================================================
float registercvar (string name, string value[, float flags])
=========
*/
-void VM_registercvar (void)
+void VM_registercvar(prvm_prog_t *prog)
{
const char *name, *value;
int flags;
// check for overlap with a command
if (Cmd_Exists (name))
{
- VM_Warning("VM_registercvar: %s is a command\n", name);
+ VM_Warning(prog, "VM_registercvar: %s is a command\n", name);
return;
}
float min(float a, float b, ...[float])
=================
*/
-void VM_min (void)
+void VM_min(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNTRANGE(2, 8, VM_min);
// LordHavoc: 3+ argument enhancement suggested by FrikaC
float max(float a, float b, ...[float])
=================
*/
-void VM_max (void)
+void VM_max(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNTRANGE(2, 8, VM_max);
// LordHavoc: 3+ argument enhancement suggested by FrikaC
float bound(float min, float value, float max)
=================
*/
-void VM_bound (void)
+void VM_bound(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3,VM_bound);
PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
float pow(float a, float b)
=================
*/
-void VM_pow (void)
+void VM_pow(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2,VM_pow);
PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
}
-void VM_log (void)
+void VM_log(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_log);
PRVM_G_FLOAT(OFS_RETURN) = log(PRVM_G_FLOAT(OFS_PARM0));
}
-void VM_Files_Init(void)
+void VM_Files_Init(prvm_prog_t *prog)
{
int i;
for (i = 0;i < PRVM_MAX_OPENFILES;i++)
prog->openfiles[i] = NULL;
}
-void VM_Files_CloseAll(void)
+void VM_Files_CloseAll(prvm_prog_t *prog)
{
int i;
for (i = 0;i < PRVM_MAX_OPENFILES;i++)
}
}
-static qfile_t *VM_GetFileHandle( int index )
+static qfile_t *VM_GetFileHandle(prvm_prog_t *prog, int index)
{
if (index < 0 || index >= PRVM_MAX_OPENFILES)
{
- Con_Printf("VM_GetFileHandle: invalid file handle %i used in %s\n", index, PRVM_NAME);
+ Con_Printf("VM_GetFileHandle: invalid file handle %i used in %s\n", index, prog->name);
return NULL;
}
if (prog->openfiles[index] == NULL)
{
- Con_Printf("VM_GetFileHandle: no such file handle %i (or file has been closed) in %s\n", index, PRVM_NAME);
+ Con_Printf("VM_GetFileHandle: no such file handle %i (or file has been closed) in %s\n", index, prog->name);
return NULL;
}
return prog->openfiles[index];
// float(string filename, float mode) fopen = #110;
// opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
// returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
-void VM_fopen(void)
+void VM_fopen(prvm_prog_t *prog)
{
int filenum, mode;
const char *modestring, *filename;
+ char vabuf[1024];
VM_SAFEPARMCOUNT(2,VM_fopen);
if (filenum >= PRVM_MAX_OPENFILES)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, PRVM_MAX_OPENFILES);
+ VM_Warning(prog, "VM_fopen: %s ran out of file handles (%i)\n", prog->name, PRVM_MAX_OPENFILES);
return;
}
filename = PRVM_G_STRING(OFS_PARM0);
{
case 0: // FILE_READ
modestring = "rb";
- prog->openfiles[filenum] = FS_OpenVirtualFile(va("data/%s", filename), false);
+ prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false);
if (prog->openfiles[filenum] == NULL)
- prog->openfiles[filenum] = FS_OpenVirtualFile(va("%s", filename), false);
+ prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false);
break;
case 1: // FILE_APPEND
modestring = "a";
- prog->openfiles[filenum] = FS_OpenRealFile(va("data/%s", filename), modestring, false);
+ prog->openfiles[filenum] = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "data/%s", filename), modestring, false);
break;
case 2: // FILE_WRITE
modestring = "w";
- prog->openfiles[filenum] = FS_OpenRealFile(va("data/%s", filename), modestring, false);
+ prog->openfiles[filenum] = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "data/%s", filename), modestring, false);
break;
default:
PRVM_G_FLOAT(OFS_RETURN) = -3;
- VM_Warning("VM_fopen: %s: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
+ VM_Warning(prog, "VM_fopen: %s: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", prog->name, mode);
return;
}
{
PRVM_G_FLOAT(OFS_RETURN) = -1;
if (developer_extra.integer)
- VM_Warning("VM_fopen: %s: %s mode %s failed\n", PRVM_NAME, filename, modestring);
+ VM_Warning(prog, "VM_fopen: %s: %s mode %s failed\n", prog->name, filename, modestring);
}
else
{
PRVM_G_FLOAT(OFS_RETURN) = filenum;
if (developer_extra.integer)
- Con_DPrintf("VM_fopen: %s: %s mode %s opened as #%i\n", PRVM_NAME, filename, modestring, filenum);
- prog->openfiles_origin[filenum] = PRVM_AllocationOrigin();
+ Con_DPrintf("VM_fopen: %s: %s mode %s opened as #%i\n", prog->name, filename, modestring, filenum);
+ prog->openfiles_origin[filenum] = PRVM_AllocationOrigin(prog);
}
}
=========
*/
//void(float fhandle) fclose = #111; // closes a file
-void VM_fclose(void)
+void VM_fclose(prvm_prog_t *prog)
{
int filenum;
filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
{
- VM_Warning("VM_fclose: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
+ VM_Warning(prog, "VM_fclose: invalid file handle %i used in %s\n", filenum, prog->name);
return;
}
if (prog->openfiles[filenum] == NULL)
{
- VM_Warning("VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
+ VM_Warning(prog, "VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
return;
}
FS_Close(prog->openfiles[filenum]);
if(prog->openfiles_origin[filenum])
PRVM_Free((char *)prog->openfiles_origin[filenum]);
if (developer_extra.integer)
- Con_DPrintf("VM_fclose: %s: #%i closed\n", PRVM_NAME, filenum);
+ Con_DPrintf("VM_fclose: %s: #%i closed\n", prog->name, filenum);
}
/*
=========
*/
//string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
-void VM_fgets(void)
+void VM_fgets(prvm_prog_t *prog)
{
int c, end;
char string[VM_STRINGTEMP_LENGTH];
filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
{
- VM_Warning("VM_fgets: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
+ VM_Warning(prog, "VM_fgets: invalid file handle %i used in %s\n", filenum, prog->name);
return;
}
if (prog->openfiles[filenum] == NULL)
{
- VM_Warning("VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
+ VM_Warning(prog, "VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
return;
}
end = 0;
FS_UnGetc(prog->openfiles[filenum], (unsigned char)c);
}
if (developer_extra.integer)
- Con_DPrintf("fgets: %s: %s\n", PRVM_NAME, string);
+ Con_DPrintf("fgets: %s: %s\n", prog->name, string);
if (c >= 0 || end)
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
}
/*
=========
*/
//void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
-void VM_fputs(void)
+void VM_fputs(prvm_prog_t *prog)
{
int stringlength;
char string[VM_STRINGTEMP_LENGTH];
filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
{
- VM_Warning("VM_fputs: invalid file handle %i used in %s\n", filenum, PRVM_NAME);
+ VM_Warning(prog, "VM_fputs: invalid file handle %i used in %s\n", filenum, prog->name);
return;
}
if (prog->openfiles[filenum] == NULL)
{
- VM_Warning("VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, PRVM_NAME);
+ VM_Warning(prog, "VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
return;
}
- VM_VarString(1, string, sizeof(string));
+ VM_VarString(prog, 1, string, sizeof(string));
if ((stringlength = (int)strlen(string)))
FS_Write(prog->openfiles[filenum], string, stringlength);
if (developer_extra.integer)
- Con_DPrintf("fputs: %s: %s\n", PRVM_NAME, string);
+ Con_DPrintf("fputs: %s: %s\n", prog->name, string);
}
/*
writetofile(float fhandle, entity ent)
=========
*/
-void VM_writetofile(void)
+void VM_writetofile(prvm_prog_t *prog)
{
prvm_edict_t * ent;
qfile_t *file;
VM_SAFEPARMCOUNT(2, VM_writetofile);
- file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) );
+ file = VM_GetFileHandle(prog, (int)PRVM_G_FLOAT(OFS_PARM0));
if( !file )
{
- VM_Warning("VM_writetofile: invalid or closed file handle\n");
+ VM_Warning(prog, "VM_writetofile: invalid or closed file handle\n");
return;
}
ent = PRVM_G_EDICT(OFS_PARM1);
if(ent->priv.required->free)
{
- VM_Warning("VM_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
+ VM_Warning(prog, "VM_writetofile: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
return;
}
- PRVM_ED_Write (file, ent);
+ PRVM_ED_Write (prog, file, ent);
}
// KrimZon - DP_QC_ENTITYDATA
Return the number of entity fields - NOT offsets
=========
*/
-void VM_numentityfields(void)
+void VM_numentityfields(prvm_prog_t *prog)
{
PRVM_G_FLOAT(OFS_RETURN) = prog->numfielddefs;
}
Return name of the specified field as a string, or empty if the field is invalid (warning)
=========
*/
-void VM_entityfieldname(void)
+void VM_entityfieldname(prvm_prog_t *prog)
{
ddef_t *d;
int i = (int)PRVM_G_FLOAT(OFS_PARM0);
if (i < 0 || i >= prog->numfielddefs)
{
- VM_Warning("VM_entityfieldname: %s: field index out of bounds\n", PRVM_NAME);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString("");
+ VM_Warning(prog, "VM_entityfieldname: %s: field index out of bounds\n", prog->name);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
return;
}
float(float fieldnum) entityfieldtype
=========
*/
-void VM_entityfieldtype(void)
+void VM_entityfieldtype(prvm_prog_t *prog)
{
ddef_t *d;
int i = (int)PRVM_G_FLOAT(OFS_PARM0);
if (i < 0 || i >= prog->numfielddefs)
{
- VM_Warning("VM_entityfieldtype: %s: field index out of bounds\n", PRVM_NAME);
+ VM_Warning(prog, "VM_entityfieldtype: %s: field index out of bounds\n", prog->name);
PRVM_G_FLOAT(OFS_RETURN) = -1.0;
return;
}
string(float fieldnum, entity ent) getentityfieldstring
=========
*/
-void VM_getentityfieldstring(void)
+void VM_getentityfieldstring(prvm_prog_t *prog)
{
// put the data into a string
ddef_t *d;
int *v;
prvm_edict_t * ent;
int i = (int)PRVM_G_FLOAT(OFS_PARM0);
+ char valuebuf[MAX_INPUTLINE];
if (i < 0 || i >= prog->numfielddefs)
{
- VM_Warning("VM_entityfielddata: %s: field index out of bounds\n", PRVM_NAME);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString("");
+ VM_Warning(prog, "VM_entityfielddata: %s: field index out of bounds\n", prog->name);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
return;
}
ent = PRVM_G_EDICT(OFS_PARM1);
if(ent->priv.required->free)
{
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString("");
- VM_Warning("VM_entityfielddata: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+ VM_Warning(prog, "VM_entityfielddata: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
return;
}
v = (int *)((char *)ent->fields.vp + d->ofs*4);
break;
if (j == prvm_type_size[type])
{
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString("");
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
return;
}
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(PRVM_UglyValueString((etype_t)d->type, (prvm_eval_t *)v));
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_UglyValueString(prog, (etype_t)d->type, (prvm_eval_t *)v, valuebuf, sizeof(valuebuf)));
}
// KrimZon - DP_QC_ENTITYDATA
float(float fieldnum, entity ent, string s) putentityfieldstring
=========
*/
-void VM_putentityfieldstring(void)
+void VM_putentityfieldstring(prvm_prog_t *prog)
{
ddef_t *d;
prvm_edict_t * ent;
if (i < 0 || i >= prog->numfielddefs)
{
- VM_Warning("VM_entityfielddata: %s: field index out of bounds\n", PRVM_NAME);
+ VM_Warning(prog, "VM_entityfielddata: %s: field index out of bounds\n", prog->name);
PRVM_G_FLOAT(OFS_RETURN) = 0.0f;
return;
}
ent = PRVM_G_EDICT(OFS_PARM1);
if(ent->priv.required->free)
{
- VM_Warning("VM_entityfielddata: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
+ VM_Warning(prog, "VM_entityfielddata: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
PRVM_G_FLOAT(OFS_RETURN) = 0.0f;
return;
}
// parse the string into the value
- PRVM_G_FLOAT(OFS_RETURN) = ( PRVM_ED_ParseEpair(ent, d, PRVM_G_STRING(OFS_PARM2), false) ) ? 1.0f : 0.0f;
+ PRVM_G_FLOAT(OFS_RETURN) = ( PRVM_ED_ParseEpair(prog, ent, d, PRVM_G_STRING(OFS_PARM2), false) ) ? 1.0f : 0.0f;
}
/*
=========
*/
//float(string s) strlen = #114; // returns how many characters are in a string
-void VM_strlen(void)
+void VM_strlen(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_strlen);
=========
*/
// string (string s) strdecolorize = #472; // returns the passed in string with color codes stripped
-void VM_strdecolorize(void)
+void VM_strdecolorize(prvm_prog_t *prog)
{
char szNewString[VM_STRINGTEMP_LENGTH];
const char *szString;
VM_SAFEPARMCOUNT(1,VM_strdecolorize);
szString = PRVM_G_STRING(OFS_PARM0);
COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), TRUE);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(szNewString);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
}
// DRESK - String Length (not counting color codes)
*/
// float(string s) strlennocol = #471; // returns how many characters are in a string not including color codes
// For example, ^2Dresk returns a length of 5
-void VM_strlennocol(void)
+void VM_strlennocol(prvm_prog_t *prog)
{
const char *szString;
int nCnt;
=========
*/
// string (string s) strtolower = #480; // returns passed in string in lowercase form
-void VM_strtolower(void)
+void VM_strtolower(prvm_prog_t *prog)
{
char szNewString[VM_STRINGTEMP_LENGTH];
const char *szString;
COM_ToLowerString(szString, szNewString, sizeof(szNewString) );
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(szNewString);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
}
/*
=========
*/
// string (string s) strtoupper = #481; // returns passed in string in uppercase form
-void VM_strtoupper(void)
+void VM_strtoupper(prvm_prog_t *prog)
{
char szNewString[VM_STRINGTEMP_LENGTH];
const char *szString;
COM_ToUpperString(szString, szNewString, sizeof(szNewString) );
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(szNewString);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
}
/*
//string(string s1, string s2) strcat = #115;
// concatenates two strings (for example "abc", "def" would return "abcdef")
// and returns as a tempstring
-void VM_strcat(void)
+void VM_strcat(prvm_prog_t *prog)
{
char s[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(1, 8, VM_strcat);
- VM_VarString(0, s, sizeof(s));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s);
+ VM_VarString(prog, 0, s, sizeof(s));
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
}
/*
*/
// string(string s, float start, float length) substring = #116;
// returns a section of a string as a tempstring
-void VM_substring(void)
+void VM_substring(prvm_prog_t *prog)
{
int start, length;
int u_slength = 0, u_start;
memcpy(string, s + start, length);
string[length] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
*/
s = PRVM_G_STRING(OFS_PARM0);
u_start = u8_byteofs(s, start, NULL);
if (u_start < 0)
{
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString("");
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
return;
}
u_length = u8_bytelen(s + u_start, length);
memcpy(string, s + u_start, u_length);
string[u_length] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
}
/*
=========
*/
// replaces all occurrences of search with replace in the string subject, and returns the result
-void VM_strreplace(void)
+void VM_strreplace(prvm_prog_t *prog)
{
int i, j, si;
const char *search, *replace, *subject;
string[si++] = subject[i];
string[si] = '\0';
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
}
/*
=========
*/
// case-insensitive version of strreplace
-void VM_strireplace(void)
+void VM_strireplace(prvm_prog_t *prog)
{
int i, j, si;
const char *search, *replace, *subject;
string[si++] = subject[i];
string[si] = '\0';
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
}
/*
=========
*/
//vector(string s) stov = #117; // returns vector value from a string
-void VM_stov(void)
+void VM_stov(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNT(1,VM_stov);
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
}
=========
*/
//string(string s, ...) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
-void VM_strzone(void)
+void VM_strzone(prvm_prog_t *prog)
{
char *out;
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNT(1,VM_strzone);
- VM_VarString(0, string, sizeof(string));
+ VM_VarString(prog, 0, string, sizeof(string));
alloclen = strlen(string) + 1;
- PRVM_G_INT(OFS_RETURN) = PRVM_AllocString(alloclen, &out);
+ PRVM_G_INT(OFS_RETURN) = PRVM_AllocString(prog, alloclen, &out);
memcpy(out, string, alloclen);
}
=========
*/
//void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
-void VM_strunzone(void)
+void VM_strunzone(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_strunzone);
- PRVM_FreeString(PRVM_G_INT(OFS_PARM0));
+ PRVM_FreeString(prog, PRVM_G_INT(OFS_PARM0));
}
/*
*/
//void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
//this function originally written by KrimZon, made shorter by LordHavoc
-void VM_clcommand (void)
+void VM_clcommand (prvm_prog_t *prog)
{
client_t *temp_client;
int i;
i = (int)PRVM_G_FLOAT(OFS_PARM0);
if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
{
- VM_Warning("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
+ VM_Warning(prog, "VM_clientcommand: %s: invalid client/server is not active !\n", prog->name);
return;
}
temp_client = host_client;
host_client = svs.clients + i;
- Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
+ Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
host_client = temp_client;
}
static int tokens_startpos[VM_STRINGTEMP_LENGTH / 2];
static int tokens_endpos[VM_STRINGTEMP_LENGTH / 2];
static char tokenize_string[VM_STRINGTEMP_LENGTH];
-void VM_tokenize (void)
+void VM_tokenize (prvm_prog_t *prog)
{
const char *p;
if(!COM_ParseToken_VM_Tokenize(&p, false))
break;
tokens_endpos[num_tokens] = p - tokenize_string;
- tokens[num_tokens] = PRVM_SetTempString(com_token);
+ tokens[num_tokens] = PRVM_SetTempString(prog, com_token);
++num_tokens;
}
}
//float(string s) tokenize = #514; // takes apart a string into individal words (access them with argv), returns how many
-void VM_tokenize_console (void)
+void VM_tokenize_console (prvm_prog_t *prog)
{
const char *p;
if(!COM_ParseToken_Console(&p))
break;
tokens_endpos[num_tokens] = p - tokenize_string;
- tokens[num_tokens] = PRVM_SetTempString(com_token);
+ tokens[num_tokens] = PRVM_SetTempString(prog, com_token);
++num_tokens;
}
//example:
//numnumbers = tokenizebyseparator("10.1.2.3", ".");
//returns 4 and the tokens "10" "1" "2" "3".
-void VM_tokenizebyseparator (void)
+void VM_tokenizebyseparator (prvm_prog_t *prog)
{
int j, k;
int numseparators;
if (j >= (int)sizeof(tokentext))
break;
tokentext[j++] = 0;
- tokens[num_tokens++] = PRVM_SetTempString(token);
+ tokens[num_tokens++] = PRVM_SetTempString(prog, token);
if (!*p)
break;
}
//string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
//this function originally written by KrimZon, made shorter by LordHavoc
-void VM_argv (void)
+void VM_argv (prvm_prog_t *prog)
{
int token_num;
}
//float(float n) argv_start_index = #515; // returns the start index of a token
-void VM_argv_start_index (void)
+void VM_argv_start_index (prvm_prog_t *prog)
{
int token_num;
}
//float(float n) argv_end_index = #516; // returns the end index of a token
-void VM_argv_end_index (void)
+void VM_argv_end_index (prvm_prog_t *prog)
{
int token_num;
float isserver()
=========
*/
-void VM_isserver(void)
+void VM_isserver(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_serverstate);
float clientcount()
=========
*/
-void VM_clientcount(void)
+void VM_clientcount(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_clientcount);
float clientstate()
=========
*/
-void VM_clientstate(void)
+void VM_clientstate(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_clientstate);
=========
VM_getostype
-float getostype(void)
+float getostype(prvm_prog_t *prog)
=========
*/ // not used at the moment -> not included in the common list
-void VM_getostype(void)
+void VM_getostype(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_getostype);
=========
VM_gettime
-float gettime(void)
+float gettime(prvm_prog_t *prog)
=========
*/
-extern double host_starttime;
float CDAudio_GetPosition(void);
-void VM_gettime(void)
+void VM_gettime(prvm_prog_t *prog)
{
int timer_index;
else
{
timer_index = (int) PRVM_G_FLOAT(OFS_PARM0);
- switch(timer_index)
- {
- case 0: // GETTIME_FRAMESTART
- PRVM_G_FLOAT(OFS_RETURN) = (float) realtime;
- break;
- case 1: // GETTIME_REALTIME
- PRVM_G_FLOAT(OFS_RETURN) = (float) Sys_DoubleTime();
- break;
- case 2: // GETTIME_HIRES
- PRVM_G_FLOAT(OFS_RETURN) = (float) (Sys_DoubleTime() - realtime);
- break;
- case 3: // GETTIME_UPTIME
- PRVM_G_FLOAT(OFS_RETURN) = (float) (Sys_DoubleTime() - host_starttime);
- break;
- case 4: // GETTIME_CDTRACK
- PRVM_G_FLOAT(OFS_RETURN) = (float) CDAudio_GetPosition();
- break;
+ switch(timer_index)
+ {
+ case 0: // GETTIME_FRAMESTART
+ PRVM_G_FLOAT(OFS_RETURN) = realtime;
+ break;
+ case 1: // GETTIME_REALTIME
+ PRVM_G_FLOAT(OFS_RETURN) = Sys_DirtyTime();
+ break;
+ case 2: // GETTIME_HIRES
+ PRVM_G_FLOAT(OFS_RETURN) = (Sys_DirtyTime() - host_dirtytime);
+ break;
+ case 3: // GETTIME_UPTIME
+ PRVM_G_FLOAT(OFS_RETURN) = realtime;
+ break;
+ case 4: // GETTIME_CDTRACK
+ PRVM_G_FLOAT(OFS_RETURN) = CDAudio_GetPosition();
+ break;
default:
- VM_Warning("VM_gettime: %s: unsupported timer specified, returning realtime\n", PRVM_NAME);
- PRVM_G_FLOAT(OFS_RETURN) = (float) realtime;
+ VM_Warning(prog, "VM_gettime: %s: unsupported timer specified, returning realtime\n", prog->name);
+ PRVM_G_FLOAT(OFS_RETURN) = realtime;
break;
}
}
=========
VM_getsoundtime
-float getsoundtime(void)
+float getsoundtime(prvm_prog_t *prog)
=========
*/
-void VM_getsoundtime (void)
+void VM_getsoundtime (prvm_prog_t *prog)
{
- int entnum, entchannel, pnum;
+ int entnum, entchannel;
VM_SAFEPARMCOUNT(2,VM_getsoundtime);
- pnum = PRVM_GetProgNr();
- if (pnum == PRVM_MENUPROG)
+ if (prog == SVVM_prog)
+ entnum = PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
+ else if (prog == CLVM_prog)
+ entnum = MAX_EDICTS + PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
+ else
{
- VM_Warning("VM_getsoundtime: %s: not supported on this progs\n", PRVM_NAME);
+ VM_Warning(prog, "VM_getsoundtime: %s: not supported on this progs\n", prog->name);
PRVM_G_FLOAT(OFS_RETURN) = -1;
return;
}
- entnum = ((pnum == PRVM_CLIENTPROG) ? MAX_EDICTS : 0) + PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
entchannel = (int)PRVM_G_FLOAT(OFS_PARM1);
entchannel = CHAN_USER2ENGINE(entchannel);
if (!IS_CHAN(entchannel))
- VM_Warning("VM_getsoundtime: %s: bad channel %i\n", PRVM_NAME, entchannel);
+ VM_Warning(prog, "VM_getsoundtime: %s: bad channel %i\n", prog->name, entchannel);
PRVM_G_FLOAT(OFS_RETURN) = (float)S_GetEntChannelPosition(entnum, entchannel);
}
string soundlength (string sample)
=========
*/
-void VM_soundlength (void)
+void VM_soundlength (prvm_prog_t *prog)
{
const char *s;
loadfromdata(string data)
=========
*/
-void VM_loadfromdata(void)
+void VM_loadfromdata(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_loadentsfromfile);
- PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
+ PRVM_ED_LoadFromFile(prog, PRVM_G_STRING(OFS_PARM0));
}
/*
parseentitydata(entity ent, string data)
========================
*/
-void VM_parseentitydata(void)
+void VM_parseentitydata(prvm_prog_t *prog)
{
prvm_edict_t *ent;
const char *data;
// get edict and test it
ent = PRVM_G_EDICT(OFS_PARM0);
if (ent->priv.required->free)
- PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
+ prog->error_cmd("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!", prog->name, PRVM_NUM_FOR_EDICT(ent));
data = PRVM_G_STRING(OFS_PARM1);
// parse the opening brace
- if (!COM_ParseToken_Simple(&data, false, false) || com_token[0] != '{' )
- PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s", PRVM_NAME, data );
+ if (!COM_ParseToken_Simple(&data, false, false, true) || com_token[0] != '{' )
+ prog->error_cmd("VM_parseentitydata: %s: Couldn't parse entity data:\n%s", prog->name, data );
- PRVM_ED_ParseEdict (data, ent);
+ PRVM_ED_ParseEdict (prog, data, ent);
}
/*
loadfromfile(string file)
=========
*/
-void VM_loadfromfile(void)
+void VM_loadfromfile(prvm_prog_t *prog)
{
const char *filename;
char *data;
if (FS_CheckNastyPath(filename, false))
{
PRVM_G_FLOAT(OFS_RETURN) = -4;
- VM_Warning("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename);
+ VM_Warning(prog, "VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", prog->name, filename);
return;
}
if (data == NULL)
PRVM_G_FLOAT(OFS_RETURN) = -1;
- PRVM_ED_LoadFromFile(data);
+ PRVM_ED_LoadFromFile(prog, data);
if(data)
Mem_Free(data);
float mod(float val, float m)
=========
*/
-void VM_modulo(void)
+void VM_modulo(prvm_prog_t *prog)
{
int val, m;
VM_SAFEPARMCOUNT(2,VM_module);
PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m);
}
-void VM_Search_Init(void)
+static void VM_Search_Init(prvm_prog_t *prog)
{
int i;
for (i = 0;i < PRVM_MAX_OPENSEARCHES;i++)
prog->opensearches[i] = NULL;
}
-void VM_Search_Reset(void)
+static void VM_Search_Reset(prvm_prog_t *prog)
{
int i;
// reset the fssearch list
float search_begin(string pattern, float caseinsensitive, float quiet)
=========
*/
-void VM_search_begin(void)
+void VM_search_begin(prvm_prog_t *prog)
{
int handle;
const char *pattern;
pattern = PRVM_G_STRING(OFS_PARM0);
- VM_CheckEmptyString(pattern);
+ VM_CheckEmptyString(prog, pattern);
caseinsens = (int)PRVM_G_FLOAT(OFS_PARM1);
quiet = (int)PRVM_G_FLOAT(OFS_PARM2);
if(handle >= PRVM_MAX_OPENSEARCHES)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_search_begin: %s ran out of search handles (%i)\n", PRVM_NAME, PRVM_MAX_OPENSEARCHES);
+ VM_Warning(prog, "VM_search_begin: %s ran out of search handles (%i)\n", prog->name, PRVM_MAX_OPENSEARCHES);
return;
}
PRVM_G_FLOAT(OFS_RETURN) = -1;
else
{
- prog->opensearches_origin[handle] = PRVM_AllocationOrigin();
+ prog->opensearches_origin[handle] = PRVM_AllocationOrigin(prog);
PRVM_G_FLOAT(OFS_RETURN) = handle;
}
}
void search_end(float handle)
=========
*/
-void VM_search_end(void)
+void VM_search_end(prvm_prog_t *prog)
{
int handle;
VM_SAFEPARMCOUNT(1, VM_search_end);
if(handle < 0 || handle >= PRVM_MAX_OPENSEARCHES)
{
- VM_Warning("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
+ VM_Warning(prog, "VM_search_end: invalid handle %i used in %s\n", handle, prog->name);
return;
}
if(prog->opensearches[handle] == NULL)
{
- VM_Warning("VM_search_end: no such handle %i in %s\n", handle, PRVM_NAME);
+ VM_Warning(prog, "VM_search_end: no such handle %i in %s\n", handle, prog->name);
return;
}
float search_getsize(float handle)
=========
*/
-void VM_search_getsize(void)
+void VM_search_getsize(prvm_prog_t *prog)
{
int handle;
VM_SAFEPARMCOUNT(1, VM_M_search_getsize);
if(handle < 0 || handle >= PRVM_MAX_OPENSEARCHES)
{
- VM_Warning("VM_search_getsize: invalid handle %i used in %s\n", handle, PRVM_NAME);
+ VM_Warning(prog, "VM_search_getsize: invalid handle %i used in %s\n", handle, prog->name);
return;
}
if(prog->opensearches[handle] == NULL)
{
- VM_Warning("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
+ VM_Warning(prog, "VM_search_getsize: no such handle %i in %s\n", handle, prog->name);
return;
}
string search_getfilename(float handle, float num)
=========
*/
-void VM_search_getfilename(void)
+void VM_search_getfilename(prvm_prog_t *prog)
{
int handle, filenum;
VM_SAFEPARMCOUNT(2, VM_search_getfilename);
if(handle < 0 || handle >= PRVM_MAX_OPENSEARCHES)
{
- VM_Warning("VM_search_getfilename: invalid handle %i used in %s\n", handle, PRVM_NAME);
+ VM_Warning(prog, "VM_search_getfilename: invalid handle %i used in %s\n", handle, prog->name);
return;
}
if(prog->opensearches[handle] == NULL)
{
- VM_Warning("VM_search_getfilename: no such handle %i in %s\n", handle, PRVM_NAME);
+ VM_Warning(prog, "VM_search_getfilename: no such handle %i in %s\n", handle, prog->name);
return;
}
if(filenum < 0 || filenum >= prog->opensearches[handle]->numfilenames)
{
- VM_Warning("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
+ VM_Warning(prog, "VM_search_getfilename: invalid filenum %i in %s\n", filenum, prog->name);
return;
}
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog->opensearches[handle]->filenames[filenum]);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, prog->opensearches[handle]->filenames[filenum]);
}
/*
string chr(float ascii)
=========
*/
-void VM_chr(void)
+void VM_chr(prvm_prog_t *prog)
{
/*
char tmp[2];
tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
tmp[1] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(tmp);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, tmp);
*/
char tmp[8];
len = u8_fromchar((Uchar)PRVM_G_FLOAT(OFS_PARM0), tmp, sizeof(tmp));
tmp[len] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(tmp);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, tmp);
}
//=============================================================================
float iscachedpic(string pic)
=========
*/
-void VM_iscachedpic(void)
+void VM_iscachedpic(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_iscachedpic);
string precache_pic(string pic)
=========
*/
-void VM_precache_pic(void)
+void VM_precache_pic(prvm_prog_t *prog)
{
const char *s;
s = PRVM_G_STRING(OFS_PARM0);
PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
- VM_CheckEmptyString (s);
+ VM_CheckEmptyString(prog, s);
// AK Draw_CachePic is supposed to always return a valid pointer
if( Draw_CachePic_Flags(s, 0)->tex == r_texture_notexture )
freepic(string s)
=========
*/
-void VM_freepic(void)
+void VM_freepic(prvm_prog_t *prog)
{
const char *s;
VM_SAFEPARMCOUNT(1,VM_freepic);
s = PRVM_G_STRING(OFS_PARM0);
- VM_CheckEmptyString (s);
+ VM_CheckEmptyString(prog, s);
Draw_FreePic(s);
}
-void getdrawfontscale(float *sx, float *sy)
+static void getdrawfontscale(prvm_prog_t *prog, float *sx, float *sy)
{
vec3_t v;
*sx = *sy = 1;
}
}
-dp_font_t *getdrawfont(void)
+static dp_font_t *getdrawfont(prvm_prog_t *prog)
{
int f = (int) PRVM_drawglobalfloat(drawfont);
if(f < 0 || f >= dp_fonts.maxsize)
float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
=========
*/
-void VM_drawcharacter(void)
+void VM_drawcharacter(prvm_prog_t *prog)
{
float *pos,*scale,*rgb;
char character;
if(character == 0)
{
PRVM_G_FLOAT(OFS_RETURN) = -1;
- VM_Warning("VM_drawcharacter: %s passed null character !\n",PRVM_NAME);
+ VM_Warning(prog, "VM_drawcharacter: %s passed null character !\n",prog->name);
return;
}
if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
+ VM_Warning(prog, "VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",prog->name,flag);
return;
}
if(pos[2] || scale[2])
- Con_Printf("VM_drawcharacter: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
+ VM_Warning(prog, "VM_drawcharacter: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
if(!scale[0] || !scale[1])
{
PRVM_G_FLOAT(OFS_RETURN) = -3;
- VM_Warning("VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
+ VM_Warning(prog, "VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
return;
}
- getdrawfontscale(&sx, &sy);
- DrawQ_String_Scale(pos[0], pos[1], &character, 1, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont());
+ getdrawfontscale(prog, &sx, &sy);
+ DrawQ_String_Scale(pos[0], pos[1], &character, 1, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont(prog));
PRVM_G_FLOAT(OFS_RETURN) = 1;
}
=========
VM_drawstring
-float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
+float drawstring(vector position, string text, vector scale, vector rgb, float alpha[, float flag])
=========
*/
-void VM_drawstring(void)
+void VM_drawstring(prvm_prog_t *prog)
{
float *pos,*scale,*rgb;
const char *string;
- int flag;
+ int flag = 0;
float sx, sy;
- VM_SAFEPARMCOUNT(6,VM_drawstring);
+ VM_SAFEPARMCOUNTRANGE(5,6,VM_drawstring);
string = PRVM_G_STRING(OFS_PARM1);
pos = PRVM_G_VECTOR(OFS_PARM0);
scale = PRVM_G_VECTOR(OFS_PARM2);
rgb = PRVM_G_VECTOR(OFS_PARM3);
- flag = (int)PRVM_G_FLOAT(OFS_PARM5);
+ if (prog->argc >= 6)
+ flag = (int)PRVM_G_FLOAT(OFS_PARM5);
if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
+ VM_Warning(prog, "VM_drawstring: %s: wrong DRAWFLAG %i !\n",prog->name,flag);
return;
}
if(!scale[0] || !scale[1])
{
PRVM_G_FLOAT(OFS_RETURN) = -3;
- VM_Warning("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
+ VM_Warning(prog, "VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
return;
}
if(pos[2] || scale[2])
- Con_Printf("VM_drawstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
+ VM_Warning(prog, "VM_drawstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
- getdrawfontscale(&sx, &sy);
- DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont());
+ getdrawfontscale(prog, &sx, &sy);
+ DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont(prog));
//Font_DrawString(pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true);
PRVM_G_FLOAT(OFS_RETURN) = 1;
}
float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
=========
*/
-void VM_drawcolorcodedstring(void)
+void VM_drawcolorcodedstring(prvm_prog_t *prog)
{
float *pos, *scale;
const char *string;
if(flag < DRAWFLAG_NORMAL || flag >= DRAWFLAG_NUMFLAGS)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_drawcolorcodedstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
+ VM_Warning(prog, "VM_drawcolorcodedstring: %s: wrong DRAWFLAG %i !\n",prog->name,flag);
return;
}
if(!scale[0] || !scale[1])
{
PRVM_G_FLOAT(OFS_RETURN) = -3;
- VM_Warning("VM_drawcolorcodedstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
+ VM_Warning(prog, "VM_drawcolorcodedstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
return;
}
if(pos[2] || scale[2])
- Con_Printf("VM_drawcolorcodedstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
+ VM_Warning(prog, "VM_drawcolorcodedstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
- getdrawfontscale(&sx, &sy);
- DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], alpha, flag, NULL, false, getdrawfont());
+ getdrawfontscale(prog, &sx, &sy);
+ DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], alpha, flag, NULL, false, getdrawfont(prog));
if (prog->argc == 6) // also return vector of last color
VectorCopy(DrawQ_Color, PRVM_G_VECTOR(OFS_RETURN));
else
float stringwidth(string text, float allowColorCodes, float size)
=========
*/
-void VM_stringwidth(void)
+void VM_stringwidth(prvm_prog_t *prog)
{
const char *string;
float *szv;
size_t maxlen = 0;
VM_SAFEPARMCOUNTRANGE(2,3,VM_drawstring);
- getdrawfontscale(&sx, &sy);
+ getdrawfontscale(prog, &sx, &sy);
if(prog->argc == 3)
{
szv = PRVM_G_VECTOR(OFS_PARM2);
string = PRVM_G_STRING(OFS_PARM0);
colors = (int)PRVM_G_FLOAT(OFS_PARM1);
- PRVM_G_FLOAT(OFS_RETURN) = DrawQ_TextWidth_UntilWidth_TrackColors_Scale(string, &maxlen, szv[0], szv[1], sx, sy, NULL, !colors, getdrawfont(), 1000000000) * mult;
+ PRVM_G_FLOAT(OFS_RETURN) = DrawQ_TextWidth_UntilWidth_TrackColors_Scale(string, &maxlen, szv[0], szv[1], sx, sy, NULL, !colors, getdrawfont(prog), 1000000000) * mult;
/*
if(prog->argc == 3)
{
=========
*/
-float getdrawfontnum(const char *fontname)
+static float getdrawfontnum(const char *fontname)
{
int i;
return -1;
}
-void VM_findfont(void)
+void VM_findfont(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1,VM_findfont);
PRVM_G_FLOAT(OFS_RETURN) = getdrawfontnum(PRVM_G_STRING(OFS_PARM0));
=========
*/
-dp_font_t *FindFont(const char *title, qboolean allocate_new);
-void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, float voffset);
-void VM_loadfont(void)
+void VM_loadfont(prvm_prog_t *prog)
{
const char *fontname, *filelist, *sizes, *c, *cm;
char mainfont[MAX_QPATH];
// detect crap size
if (sz < 0.001f || sz > 1000.0f)
{
- VM_Warning("VM_loadfont: crap size %s", com_token);
+ VM_Warning(prog, "VM_loadfont: crap size %s", com_token);
continue;
}
// check overflow
if (numsizes == MAX_FONT_SIZES)
{
- VM_Warning("VM_loadfont: MAX_FONT_SIZES = %i exceeded", MAX_FONT_SIZES);
+ VM_Warning(prog, "VM_loadfont: MAX_FONT_SIZES = %i exceeded", MAX_FONT_SIZES);
break;
}
f->req_sizes[numsizes] = sz;
float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag)
=========
*/
-void VM_drawpic(void)
+void VM_drawpic(prvm_prog_t *prog)
{
const char *picname;
float *size, *pos, *rgb;
- int flag;
+ int flag = 0;
- VM_SAFEPARMCOUNT(6,VM_drawpic);
+ VM_SAFEPARMCOUNTRANGE(5,6,VM_drawpic);
picname = PRVM_G_STRING(OFS_PARM1);
- VM_CheckEmptyString (picname);
+ VM_CheckEmptyString(prog, picname);
// is pic cached ? no function yet for that
if(!1)
{
PRVM_G_FLOAT(OFS_RETURN) = -4;
- VM_Warning("VM_drawpic: %s: %s not cached !\n", PRVM_NAME, picname);
+ VM_Warning(prog, "VM_drawpic: %s: %s not cached !\n", prog->name, picname);
return;
}
pos = PRVM_G_VECTOR(OFS_PARM0);
size = PRVM_G_VECTOR(OFS_PARM2);
rgb = PRVM_G_VECTOR(OFS_PARM3);
- flag = (int) PRVM_G_FLOAT(OFS_PARM5);
+ if (prog->argc >= 6)
+ flag = (int) PRVM_G_FLOAT(OFS_PARM5);
if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_drawpic: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
+ VM_Warning(prog, "VM_drawpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag);
return;
}
if(pos[2] || size[2])
- Con_Printf("VM_drawpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
+ VM_Warning(prog, "VM_drawpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
DrawQ_Pic(pos[0], pos[1], Draw_CachePic_Flags (picname, CACHEPICFLAG_NOTPERSISTENT), size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
PRVM_G_FLOAT(OFS_RETURN) = 1;
float drawrotpic(vector position, string pic, vector size, vector org, float angle, vector rgb, float alpha, float flag)
=========
*/
-void VM_drawrotpic(void)
+void VM_drawrotpic(prvm_prog_t *prog)
{
const char *picname;
float *size, *pos, *org, *rgb;
VM_SAFEPARMCOUNT(8,VM_drawrotpic);
picname = PRVM_G_STRING(OFS_PARM1);
- VM_CheckEmptyString (picname);
+ VM_CheckEmptyString(prog, picname);
// is pic cached ? no function yet for that
if(!1)
{
PRVM_G_FLOAT(OFS_RETURN) = -4;
- VM_Warning("VM_drawrotpic: %s: %s not cached !\n", PRVM_NAME, picname);
+ VM_Warning(prog, "VM_drawrotpic: %s: %s not cached !\n", prog->name, picname);
return;
}
if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_drawrotpic: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
+ VM_Warning(prog, "VM_drawrotpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag);
return;
}
if(pos[2] || size[2] || org[2])
- Con_Printf("VM_drawrotpic: z value from pos/size/org discarded\n");
+ VM_Warning(prog, "VM_drawrotpic: z value from pos/size/org discarded\n");
DrawQ_RotPic(pos[0], pos[1], Draw_CachePic_Flags(picname, CACHEPICFLAG_NOTPERSISTENT), size[0], size[1], org[0], org[1], PRVM_G_FLOAT(OFS_PARM4), rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM6), flag);
PRVM_G_FLOAT(OFS_RETURN) = 1;
=========
*/
-void VM_drawsubpic(void)
+void VM_drawsubpic(prvm_prog_t *prog)
{
const char *picname;
float *size, *pos, *rgb, *srcPos, *srcSize, alpha;
VM_SAFEPARMCOUNT(8,VM_drawsubpic);
picname = PRVM_G_STRING(OFS_PARM2);
- VM_CheckEmptyString (picname);
+ VM_CheckEmptyString(prog, picname);
// is pic cached ? no function yet for that
if(!1)
{
PRVM_G_FLOAT(OFS_RETURN) = -4;
- VM_Warning("VM_drawsubpic: %s: %s not cached !\n", PRVM_NAME, picname);
+ VM_Warning(prog, "VM_drawsubpic: %s: %s not cached !\n", prog->name, picname);
return;
}
if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_drawsubpic: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
+ VM_Warning(prog, "VM_drawsubpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag);
return;
}
if(pos[2] || size[2])
- Con_Printf("VM_drawsubpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
+ VM_Warning(prog, "VM_drawsubpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
DrawQ_SuperPic(pos[0], pos[1], Draw_CachePic_Flags (picname, CACHEPICFLAG_NOTPERSISTENT),
size[0], size[1],
float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
=========
*/
-void VM_drawfill(void)
+void VM_drawfill(prvm_prog_t *prog)
{
float *size, *pos, *rgb;
int flag;
if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
{
PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning("VM_drawfill: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
+ VM_Warning(prog, "VM_drawfill: %s: wrong DRAWFLAG %i !\n",prog->name,flag);
return;
}
if(pos[2] || size[2])
- Con_Printf("VM_drawfill: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
+ VM_Warning(prog, "VM_drawfill: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
DrawQ_Fill(pos[0], pos[1], size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
PRVM_G_FLOAT(OFS_RETURN) = 1;
drawsetcliparea(float x, float y, float width, float height)
=========
*/
-void VM_drawsetcliparea(void)
+void VM_drawsetcliparea(prvm_prog_t *prog)
{
float x,y,w,h;
VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
drawresetcliparea()
=========
*/
-void VM_drawresetcliparea(void)
+void VM_drawresetcliparea(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
vector getimagesize(string pic)
=========
*/
-void VM_getimagesize(void)
+void VM_getimagesize(prvm_prog_t *prog)
{
const char *p;
cachepic_t *pic;
VM_SAFEPARMCOUNT(1,VM_getimagesize);
p = PRVM_G_STRING(OFS_PARM0);
- VM_CheckEmptyString (p);
+ VM_CheckEmptyString(prog, p);
pic = Draw_CachePic_Flags (p, CACHEPICFLAG_NOTPERSISTENT);
string keynumtostring(float keynum)
=========
*/
-void VM_keynumtostring (void)
+void VM_keynumtostring (prvm_prog_t *prog)
{
+ char tinystr[2];
VM_SAFEPARMCOUNT(1, VM_keynumtostring);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0)));
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0), tinystr, sizeof(tinystr)));
}
/*
*/
#define FKFC_NUMKEYS 5
void M_FindKeysForCommand(const char *command, int *keys);
-void VM_findkeysforcommand(void)
+void VM_findkeysforcommand(prvm_prog_t *prog)
{
const char *cmd;
char ret[VM_STRINGTEMP_LENGTH];
int keys[FKFC_NUMKEYS];
int i;
int bindmap;
+ char vabuf[1024];
VM_SAFEPARMCOUNTRANGE(1, 2, VM_findkeysforcommand);
else
bindmap = 0; // consistent to "bind"
- VM_CheckEmptyString(cmd);
+ VM_CheckEmptyString(prog, cmd);
Key_FindKeysForCommand(cmd, keys, FKFC_NUMKEYS, bindmap);
ret[0] = 0;
for(i = 0; i < FKFC_NUMKEYS; i++)
- strlcat(ret, va(" \'%i\'", keys[i]), sizeof(ret));
+ strlcat(ret, va(vabuf, sizeof(vabuf), " \'%i\'", keys[i]), sizeof(ret));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(ret);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, ret);
}
/*
float stringtokeynum(string key)
=========
*/
-void VM_stringtokeynum (void)
+void VM_stringtokeynum (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT( 1, VM_keynumtostring );
string getkeybind(float key, float bindmap)
=========
*/
-void VM_getkeybind (void)
+void VM_getkeybind (prvm_prog_t *prog)
{
int bindmap;
VM_SAFEPARMCOUNTRANGE(1, 2, VM_CL_getkeybind);
else
bindmap = 0; // consistent to "bind"
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0), bindmap));
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0), bindmap));
}
/*
float setkeybind(float key, string cmd, float bindmap)
=========
*/
-void VM_setkeybind (void)
+void VM_setkeybind (prvm_prog_t *prog)
{
int bindmap;
VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_setkeybind);
vector getbindmaps()
=========
*/
-void VM_getbindmaps (void)
+void VM_getbindmaps (prvm_prog_t *prog)
{
int fg, bg;
VM_SAFEPARMCOUNT(0, VM_CL_getbindmap);
float setbindmaps(vector bindmap)
=========
*/
-void VM_setbindmaps (void)
+void VM_setbindmaps (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_CL_setbindmap);
PRVM_G_FLOAT(OFS_RETURN) = 0;
float cin_open(string file, string name)
========================
*/
-void VM_cin_open( void )
+void VM_cin_open(prvm_prog_t *prog)
{
const char *file;
const char *name;
file = PRVM_G_STRING( OFS_PARM0 );
name = PRVM_G_STRING( OFS_PARM1 );
- VM_CheckEmptyString( file );
- VM_CheckEmptyString( name );
+ VM_CheckEmptyString(prog, file );
+ VM_CheckEmptyString(prog, name );
if( CL_OpenVideo( file, name, MENUOWNER, "" ) )
PRVM_G_FLOAT( OFS_RETURN ) = 1;
void cin_close(string name)
========================
*/
-void VM_cin_close( void )
+void VM_cin_close(prvm_prog_t *prog)
{
const char *name;
VM_SAFEPARMCOUNT( 1, VM_cin_close );
name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
+ VM_CheckEmptyString(prog, name );
CL_CloseVideo( CL_GetVideoByName( name ) );
}
void cin_setstate(string name, float type)
========================
*/
-void VM_cin_setstate( void )
+void VM_cin_setstate(prvm_prog_t *prog)
{
const char *name;
clvideostate_t state;
VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
+ VM_CheckEmptyString(prog, name );
state = (clvideostate_t)((int)PRVM_G_FLOAT( OFS_PARM1 ));
float cin_getstate(string name)
========================
*/
-void VM_cin_getstate( void )
+void VM_cin_getstate(prvm_prog_t *prog)
{
const char *name;
clvideo_t *video;
VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
+ VM_CheckEmptyString(prog, name );
video = CL_GetVideoByName( name );
if( video )
void cin_restart(string name)
========================
*/
-void VM_cin_restart( void )
+void VM_cin_restart(prvm_prog_t *prog)
{
const char *name;
clvideo_t *video;
VM_SAFEPARMCOUNT( 1, VM_cin_restart );
name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
+ VM_CheckEmptyString(prog, name );
video = CL_GetVideoByName( name );
if( video )
CL_RestartVideo( video );
}
-/*
-========================
-VM_Gecko_Init
-========================
-*/
-void VM_Gecko_Init( void ) {
- // the prog struct is memset to 0 by Initprog? [12/6/2007 Black]
- // FIXME: remove the other _Init functions then, too? [12/6/2007 Black]
-}
-
-/*
-========================
-VM_Gecko_Destroy
-========================
-*/
-void VM_Gecko_Destroy( void ) {
- int i;
- for( i = 0 ; i < PRVM_MAX_GECKOINSTANCES ; i++ ) {
- clgecko_t **instance = &prog->opengeckoinstances[ i ];
- if( *instance ) {
- CL_Gecko_DestroyBrowser( *instance );
- }
- *instance = NULL;
- }
-}
-
/*
========================
VM_gecko_create
float[bool] gecko_create( string name )
========================
*/
-void VM_gecko_create( void ) {
- const char *name;
- int i;
- clgecko_t *instance;
-
- VM_SAFEPARMCOUNT( 1, VM_gecko_create );
-
- name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
-
- // find an empty slot for this gecko browser..
- for( i = 0 ; i < PRVM_MAX_GECKOINSTANCES ; i++ ) {
- if( prog->opengeckoinstances[ i ] == NULL ) {
- break;
- }
- }
- if( i == PRVM_MAX_GECKOINSTANCES ) {
- VM_Warning("VM_gecko_create: %s ran out of gecko handles (%i)\n", PRVM_NAME, PRVM_MAX_GECKOINSTANCES);
- PRVM_G_FLOAT( OFS_RETURN ) = 0;
- return;
- }
-
- instance = prog->opengeckoinstances[ i ] = CL_Gecko_CreateBrowser( name, PRVM_GetProgNr() );
- if( !instance ) {
- // TODO: error handling [12/3/2007 Black]
- PRVM_G_FLOAT( OFS_RETURN ) = 0;
- return;
- }
- PRVM_G_FLOAT( OFS_RETURN ) = 1;
+void VM_gecko_create(prvm_prog_t *prog) {
+ // REMOVED
+ PRVM_G_FLOAT( OFS_RETURN ) = 0;
}
/*
void gecko_destroy( string name )
========================
*/
-void VM_gecko_destroy( void ) {
- const char *name;
- clgecko_t *instance;
-
- VM_SAFEPARMCOUNT( 1, VM_gecko_destroy );
-
- name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
- instance = CL_Gecko_FindBrowser( name );
- if( !instance ) {
- return;
- }
- CL_Gecko_DestroyBrowser( instance );
+void VM_gecko_destroy(prvm_prog_t *prog) {
+ // REMOVED
}
/*
void gecko_navigate( string name, string URI )
========================
*/
-void VM_gecko_navigate( void ) {
- const char *name;
- const char *URI;
- clgecko_t *instance;
-
- VM_SAFEPARMCOUNT( 2, VM_gecko_navigate );
-
- name = PRVM_G_STRING( OFS_PARM0 );
- URI = PRVM_G_STRING( OFS_PARM1 );
- VM_CheckEmptyString( name );
- VM_CheckEmptyString( URI );
-
- instance = CL_Gecko_FindBrowser( name );
- if( !instance ) {
- return;
- }
- CL_Gecko_NavigateToURI( instance, URI );
+void VM_gecko_navigate(prvm_prog_t *prog) {
+ // REMOVED
}
/*
float[bool] gecko_keyevent( string name, float key, float eventtype )
========================
*/
-void VM_gecko_keyevent( void ) {
- const char *name;
- unsigned int key;
- clgecko_buttoneventtype_t eventtype;
- clgecko_t *instance;
-
- VM_SAFEPARMCOUNT( 3, VM_gecko_keyevent );
-
- name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
- key = (unsigned int) PRVM_G_FLOAT( OFS_PARM1 );
- switch( (unsigned int) PRVM_G_FLOAT( OFS_PARM2 ) ) {
- case 0:
- eventtype = CLG_BET_DOWN;
- break;
- case 1:
- eventtype = CLG_BET_UP;
- break;
- case 2:
- eventtype = CLG_BET_PRESS;
- break;
- case 3:
- eventtype = CLG_BET_DOUBLECLICK;
- break;
- default:
- // TODO: console printf? [12/3/2007 Black]
- PRVM_G_FLOAT( OFS_RETURN ) = 0;
- return;
- }
-
- instance = CL_Gecko_FindBrowser( name );
- if( !instance ) {
- PRVM_G_FLOAT( OFS_RETURN ) = 0;
- return;
- }
-
- PRVM_G_FLOAT( OFS_RETURN ) = (CL_Gecko_Event_Key( instance, (keynum_t) key, eventtype ) == true);
+void VM_gecko_keyevent(prvm_prog_t *prog) {
+ // REMOVED
+ PRVM_G_FLOAT( OFS_RETURN ) = 0;
}
/*
void gecko_mousemove( string name, float x, float y )
========================
*/
-void VM_gecko_movemouse( void ) {
- const char *name;
- float x, y;
- clgecko_t *instance;
-
- VM_SAFEPARMCOUNT( 3, VM_gecko_movemouse );
-
- name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
- x = PRVM_G_FLOAT( OFS_PARM1 );
- y = PRVM_G_FLOAT( OFS_PARM2 );
-
- instance = CL_Gecko_FindBrowser( name );
- if( !instance ) {
- return;
- }
- CL_Gecko_Event_CursorMove( instance, x, y );
+void VM_gecko_movemouse(prvm_prog_t *prog) {
+ // REMOVED
}
void gecko_resize( string name, float w, float h )
========================
*/
-void VM_gecko_resize( void ) {
- const char *name;
- float w, h;
- clgecko_t *instance;
-
- VM_SAFEPARMCOUNT( 3, VM_gecko_movemouse );
-
- name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
- w = PRVM_G_FLOAT( OFS_PARM1 );
- h = PRVM_G_FLOAT( OFS_PARM2 );
-
- instance = CL_Gecko_FindBrowser( name );
- if( !instance ) {
- return;
- }
- CL_Gecko_Resize( instance, (int) w, (int) h );
+void VM_gecko_resize(prvm_prog_t *prog) {
+ // REMOVED
}
vector gecko_get_texture_extent( string name )
========================
*/
-void VM_gecko_get_texture_extent( void ) {
- const char *name;
- clgecko_t *instance;
-
- VM_SAFEPARMCOUNT( 1, VM_gecko_movemouse );
-
- name = PRVM_G_STRING( OFS_PARM0 );
- VM_CheckEmptyString( name );
-
- PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
- instance = CL_Gecko_FindBrowser( name );
- if( !instance ) {
- PRVM_G_VECTOR(OFS_RETURN)[0] = 0;
- PRVM_G_VECTOR(OFS_RETURN)[1] = 0;
- return;
- }
- CL_Gecko_GetTextureExtent( instance,
- PRVM_G_VECTOR(OFS_RETURN), PRVM_G_VECTOR(OFS_RETURN)+1 );
+void VM_gecko_get_texture_extent(prvm_prog_t *prog) {
+ // REMOVED
+ PRVM_G_VECTOR(OFS_RETURN)[0] = 0;
+ PRVM_G_VECTOR(OFS_RETURN)[1] = 0;
}
void makevectors(vector angle)
==============
*/
-void VM_makevectors (void)
+void VM_makevectors (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_makevectors);
AngleVectors(PRVM_G_VECTOR(OFS_PARM0), PRVM_gameglobalvector(v_forward), PRVM_gameglobalvector(v_right), PRVM_gameglobalvector(v_up));
vectorvectors(vector)
==============
*/
-void VM_vectorvectors (void)
+void VM_vectorvectors (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_vectorvectors);
VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), PRVM_gameglobalvector(v_forward));
void drawline(float width, vector pos1, vector pos2, vector rgb, float alpha, float flags)
========================
*/
-void VM_drawline (void)
+void VM_drawline (prvm_prog_t *prog)
{
float *c1, *c2, *rgb;
float alpha, width;
}
// float(float number, float quantity) bitshift (EXT_BITSHIFT)
-void VM_bitshift (void)
+void VM_bitshift (prvm_prog_t *prog)
{
int n1, n2;
VM_SAFEPARMCOUNT(2, VM_bitshift);
float altstr_count(string)
========================
*/
-void VM_altstr_count( void )
+void VM_altstr_count(prvm_prog_t *prog)
{
const char *altstr, *pos;
int count;
VM_SAFEPARMCOUNT( 1, VM_altstr_count );
altstr = PRVM_G_STRING( OFS_PARM0 );
- //VM_CheckEmptyString( altstr );
+ //VM_CheckEmptyString(prog, altstr );
for( count = 0, pos = altstr ; *pos ; pos++ ) {
if( *pos == '\\' ) {
string altstr_prepare(string)
========================
*/
-void VM_altstr_prepare( void )
+void VM_altstr_prepare(prvm_prog_t *prog)
{
char *out;
const char *instr, *in;
*out = *in;
*out = 0;
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr );
}
/*
string altstr_get(string, float)
========================
*/
-void VM_altstr_get( void )
+void VM_altstr_get(prvm_prog_t *prog)
{
const char *altstr, *pos;
char *out;
*out = *pos;
*out = 0;
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr );
}
/*
string altstr_set(string altstr, float num, string set)
========================
*/
-void VM_altstr_set( void )
+void VM_altstr_set(prvm_prog_t *prog)
{
int num;
const char *altstr, *str;
break;
strlcpy(out, in, outstr + sizeof(outstr) - out);
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr );
}
/*
string altstr_ins(string altstr, float num, string set)
========================
*/
-void VM_altstr_ins(void)
+void VM_altstr_ins(prvm_prog_t *prog)
{
int num;
const char *set;
*out++ = '\'';
strlcpy(out, in, outstr + sizeof(outstr) - out);
- PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr );
+ PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr );
}
static size_t stringbuffers_sortlength;
-static void BufStr_Expand(prvm_stringbuffer_t *stringbuffer, int strindex)
+static void BufStr_Expand(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex)
{
if (stringbuffer->max_strings <= strindex)
{
}
}
-static void BufStr_Shrink(prvm_stringbuffer_t *stringbuffer)
+static void BufStr_Shrink(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer)
{
// reduce num_strings if there are empty string slots at the end
while (stringbuffer->num_strings > 0 && stringbuffer->strings[stringbuffer->num_strings - 1] == NULL)
========================
VM_buf_create
creates new buffer, and returns it's index, returns -1 if failed
-float buf_create(void) = #460;
+float buf_create(prvm_prog_t *prog) = #460;
float newbuf(string format, float flags) = #460;
========================
*/
-void VM_buf_create (void)
+void VM_buf_create (prvm_prog_t *prog)
{
prvm_stringbuffer_t *stringbuffer;
int i;
}
stringbuffer = (prvm_stringbuffer_t *) Mem_ExpandableArray_AllocRecord(&prog->stringbuffersarray);
for (i = 0;stringbuffer != Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);i++);
- stringbuffer->origin = PRVM_AllocationOrigin();
+ stringbuffer->origin = PRVM_AllocationOrigin(prog);
// optional flags parm
if (prog->argc >= 2)
stringbuffer->flags = (int)PRVM_G_FLOAT(OFS_PARM1) & 0xFF;
void buf_del(float bufhandle) = #461;
========================
*/
-void VM_buf_del (void)
+void VM_buf_del (prvm_prog_t *prog)
{
prvm_stringbuffer_t *stringbuffer;
VM_SAFEPARMCOUNT(1, VM_buf_del);
}
else
{
- VM_Warning("VM_buf_del: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_buf_del: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
}
float buf_getsize(float bufhandle) = #462;
========================
*/
-void VM_buf_getsize (void)
+void VM_buf_getsize (prvm_prog_t *prog)
{
prvm_stringbuffer_t *stringbuffer;
VM_SAFEPARMCOUNT(1, VM_buf_getsize);
if(!stringbuffer)
{
PRVM_G_FLOAT(OFS_RETURN) = -1;
- VM_Warning("VM_buf_getsize: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_buf_getsize: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
else
void buf_copy(float bufhandle_from, float bufhandle_to) = #463;
========================
*/
-void VM_buf_copy (void)
+void VM_buf_copy (prvm_prog_t *prog)
{
prvm_stringbuffer_t *srcstringbuffer, *dststringbuffer;
int i;
srcstringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
if(!srcstringbuffer)
{
- VM_Warning("VM_buf_copy: invalid source buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_buf_copy: invalid source buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
i = (int)PRVM_G_FLOAT(OFS_PARM1);
if(i == (int)PRVM_G_FLOAT(OFS_PARM0))
{
- VM_Warning("VM_buf_copy: source == destination (%i) in %s\n", i, PRVM_NAME);
+ VM_Warning(prog, "VM_buf_copy: source == destination (%i) in %s\n", i, prog->name);
return;
}
dststringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
if(!dststringbuffer)
{
- VM_Warning("VM_buf_copy: invalid destination buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), PRVM_NAME);
+ VM_Warning(prog, "VM_buf_copy: invalid destination buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), prog->name);
return;
}
void buf_sort(float bufhandle, float cmplength, float backward) = #464;
========================
*/
-void VM_buf_sort (void)
+void VM_buf_sort (prvm_prog_t *prog)
{
prvm_stringbuffer_t *stringbuffer;
VM_SAFEPARMCOUNT(3, VM_buf_sort);
stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
if(!stringbuffer)
{
- VM_Warning("VM_buf_sort: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_buf_sort: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
if(stringbuffer->num_strings <= 0)
{
- VM_Warning("VM_buf_sort: tried to sort empty buffer %i in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_buf_sort: tried to sort empty buffer %i in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
stringbuffers_sortlength = (int)PRVM_G_FLOAT(OFS_PARM1);
else
qsort(stringbuffer->strings, stringbuffer->num_strings, sizeof(char*), BufStr_SortStringsDOWN);
- BufStr_Shrink(stringbuffer);
+ BufStr_Shrink(prog, stringbuffer);
}
/*
string buf_implode(float bufhandle, string glue) = #465;
========================
*/
-void VM_buf_implode (void)
+void VM_buf_implode (prvm_prog_t *prog)
{
prvm_stringbuffer_t *stringbuffer;
char k[VM_STRINGTEMP_LENGTH];
PRVM_G_INT(OFS_RETURN) = OFS_NULL;
if(!stringbuffer)
{
- VM_Warning("VM_buf_implode: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_buf_implode: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
if(!stringbuffer->num_strings)
strlcat(k, stringbuffer->strings[i], sizeof(k));
}
}
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(k);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, k);
}
/*
string bufstr_get(float bufhandle, float string_index) = #465;
========================
*/
-void VM_bufstr_get (void)
+void VM_bufstr_get (prvm_prog_t *prog)
{
prvm_stringbuffer_t *stringbuffer;
int strindex;
stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
if(!stringbuffer)
{
- VM_Warning("VM_bufstr_get: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_get: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
strindex = (int)PRVM_G_FLOAT(OFS_PARM1);
if (strindex < 0)
{
- // VM_Warning("VM_bufstr_get: invalid string index %i used in %s\n", strindex, PRVM_NAME);
+ // VM_Warning(prog, "VM_bufstr_get: invalid string index %i used in %s\n", strindex, prog->name);
return;
}
if (strindex < stringbuffer->num_strings && stringbuffer->strings[strindex])
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(stringbuffer->strings[strindex]);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, stringbuffer->strings[strindex]);
}
/*
void bufstr_set(float bufhandle, float string_index, string str) = #466;
========================
*/
-void VM_bufstr_set (void)
+void VM_bufstr_set (prvm_prog_t *prog)
{
size_t alloclen;
int strindex;
stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
if(!stringbuffer)
{
- VM_Warning("VM_bufstr_set: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_set: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
strindex = (int)PRVM_G_FLOAT(OFS_PARM1);
if(strindex < 0 || strindex >= 1000000) // huge number of strings
{
- VM_Warning("VM_bufstr_set: invalid string index %i used in %s\n", strindex, PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_set: invalid string index %i used in %s\n", strindex, prog->name);
return;
}
- BufStr_Expand(stringbuffer, strindex);
+ BufStr_Expand(prog, stringbuffer, strindex);
stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1);
if(stringbuffer->strings[strindex])
memcpy(stringbuffer->strings[strindex], news, alloclen);
}
- BufStr_Shrink(stringbuffer);
+ BufStr_Shrink(prog, stringbuffer);
}
/*
float bufstr_add(float bufhandle, string str, float order) = #467;
========================
*/
-void VM_bufstr_add (void)
+void VM_bufstr_add (prvm_prog_t *prog)
{
int order, strindex;
prvm_stringbuffer_t *stringbuffer;
PRVM_G_FLOAT(OFS_RETURN) = -1;
if(!stringbuffer)
{
- VM_Warning("VM_bufstr_add: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_add: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
if(!PRVM_G_INT(OFS_PARM1)) // NULL string
{
- VM_Warning("VM_bufstr_add: can not add an empty string to buffer %i in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_add: can not add an empty string to buffer %i in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
string = PRVM_G_STRING(OFS_PARM1);
if (stringbuffer->strings[strindex] == NULL)
break;
- BufStr_Expand(stringbuffer, strindex);
+ BufStr_Expand(prog, stringbuffer, strindex);
stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1);
alloclen = strlen(string) + 1;
void bufstr_free(float bufhandle, float string_index) = #468;
========================
*/
-void VM_bufstr_free (void)
+void VM_bufstr_free (prvm_prog_t *prog)
{
int i;
prvm_stringbuffer_t *stringbuffer;
stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
if(!stringbuffer)
{
- VM_Warning("VM_bufstr_free: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_free: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
i = (int)PRVM_G_FLOAT(OFS_PARM1);
if(i < 0)
{
- VM_Warning("VM_bufstr_free: invalid string index %i used in %s\n", i, PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_free: invalid string index %i used in %s\n", i, prog->name);
return;
}
stringbuffer->strings[i] = NULL;
}
- BufStr_Shrink(stringbuffer);
+ BufStr_Shrink(prog, stringbuffer);
}
-void VM_buf_cvarlist(void)
+void VM_buf_cvarlist(prvm_prog_t *prog)
{
cvar_t *cvar;
const char *partial, *antipartial;
stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
if(!stringbuffer)
{
- VM_Warning("VM_bufstr_free: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "VM_bufstr_free: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
This was a major timewaster in progs, so it was converted to C
==============
*/
-void VM_changeyaw (void)
+void VM_changeyaw (prvm_prog_t *prog)
{
prvm_edict_t *ent;
float ideal, current, move, speed;
- // this is called (VERY HACKISHLY) by SV_MoveToGoal, so it can not use any
- // parameters because they are the parameters to SV_MoveToGoal, not this
+ // this is called (VERY HACKISHLY) by VM_SV_MoveToGoal, so it can not use any
+ // parameters because they are the parameters to VM_SV_MoveToGoal, not this
//VM_SAFEPARMCOUNT(0, VM_changeyaw);
ent = PRVM_PROG_TO_EDICT(PRVM_gameglobaledict(self));
if (ent == prog->edicts)
{
- VM_Warning("changeyaw: can not modify world entity\n");
+ VM_Warning(prog, "changeyaw: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("changeyaw: can not modify free entity\n");
+ VM_Warning(prog, "changeyaw: can not modify free entity\n");
return;
}
current = PRVM_gameedictvector(ent, angles)[1];
VM_changepitch
==============
*/
-void VM_changepitch (void)
+void VM_changepitch (prvm_prog_t *prog)
{
prvm_edict_t *ent;
float ideal, current, move, speed;
ent = PRVM_G_EDICT(OFS_PARM0);
if (ent == prog->edicts)
{
- VM_Warning("changepitch: can not modify world entity\n");
+ VM_Warning(prog, "changepitch: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("changepitch: can not modify free entity\n");
+ VM_Warning(prog, "changepitch: can not modify free entity\n");
return;
}
current = PRVM_gameedictvector(ent, angles)[0];
}
-void VM_uncolorstring (void)
+void VM_uncolorstring (prvm_prog_t *prog)
{
char szNewString[VM_STRINGTEMP_LENGTH];
const char *szString;
VM_SAFEPARMCOUNT(1, VM_uncolorstring);
szString = PRVM_G_STRING(OFS_PARM0);
COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), TRUE);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(szNewString);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
}
// #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
//strstr, without generating a new string. Use in conjunction with FRIK_FILE's substring for more similar strstr.
-void VM_strstrofs (void)
+void VM_strstrofs (prvm_prog_t *prog)
{
const char *instr, *match;
int firstofs;
}
//#222 string(string s, float index) str2chr (FTE_STRINGS)
-void VM_str2chr (void)
+void VM_str2chr (prvm_prog_t *prog)
{
const char *s;
Uchar ch;
}
//#223 string(float c, ...) chr2str (FTE_STRINGS)
-void VM_chr2str (void)
+void VM_chr2str (prvm_prog_t *prog)
{
/*
char t[9];
for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++)
t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
t[i] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
*/
char t[9 * 4 + 1];
int i;
for(i = 0; i < prog->argc && len < sizeof(t)-1; ++i)
len += u8_fromchar((Uchar)PRVM_G_FLOAT(OFS_PARM0+i*3), t + len, sizeof(t)-1);
t[len] = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
}
static int chrconv_number(int i, int base, int conv)
}
// #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
//bulk convert a string. change case or colouring.
-void VM_strconv (void)
+void VM_strconv (prvm_prog_t *prog)
{
int ccase, redalpha, rednum, len, i;
unsigned char resbuf[VM_STRINGTEMP_LENGTH];
ccase = (int) PRVM_G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper
redalpha = (int) PRVM_G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate
rednum = (int) PRVM_G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate
- VM_VarString(3, (char *) resbuf, sizeof(resbuf));
+ VM_VarString(prog, 3, (char *) resbuf, sizeof(resbuf));
len = strlen((char *) resbuf);
for (i = 0; i < len; i++, result++) //should this be done backwards?
}
*result = '\0';
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString((char *) resbuf);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, (char *) resbuf);
}
// #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
-void VM_strpad (void)
+void VM_strpad (prvm_prog_t *prog)
{
char src[VM_STRINGTEMP_LENGTH];
char destbuf[VM_STRINGTEMP_LENGTH];
int pad;
VM_SAFEPARMCOUNTRANGE(1, 8, VM_strpad);
pad = (int) PRVM_G_FLOAT(OFS_PARM0);
- VM_VarString(1, src, sizeof(src));
+ VM_VarString(prog, 1, src, sizeof(src));
// note: < 0 = left padding, > 0 = right padding,
// this is reverse logic of printf!
dpsnprintf(destbuf, sizeof(destbuf), "%*s", -pad, src);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(destbuf);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, destbuf);
}
// #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
//uses qw style \key\value strings
-void VM_infoadd (void)
+void VM_infoadd (prvm_prog_t *prog)
{
const char *info, *key;
char value[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNTRANGE(2, 8, VM_infoadd);
info = PRVM_G_STRING(OFS_PARM0);
key = PRVM_G_STRING(OFS_PARM1);
- VM_VarString(2, value, sizeof(value));
+ VM_VarString(prog, 2, value, sizeof(value));
strlcpy(temp, info, VM_STRINGTEMP_LENGTH);
InfoString_SetValue(temp, VM_STRINGTEMP_LENGTH, key, value);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(temp);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, temp);
}
// #227 string(string info, string key) infoget (FTE_STRINGS)
//uses qw style \key\value strings
-void VM_infoget (void)
+void VM_infoget (prvm_prog_t *prog)
{
const char *info;
const char *key;
InfoString_GetValue(info, key, value, VM_STRINGTEMP_LENGTH);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(value);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, value);
}
//#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
// also float(string s1, string s2) strcmp (FRIK_FILE)
-void VM_strncmp (void)
+void VM_strncmp (prvm_prog_t *prog)
{
const char *s1, *s2;
VM_SAFEPARMCOUNTRANGE(2, 3, VM_strncmp);
// #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
// #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
-void VM_strncasecmp (void)
+void VM_strncasecmp (prvm_prog_t *prog)
{
const char *s1, *s2;
VM_SAFEPARMCOUNTRANGE(2, 3, VM_strncasecmp);
}
// #494 float(float caseinsensitive, string s, ...) crc16
-void VM_crc16(void)
+void VM_crc16(prvm_prog_t *prog)
{
float insensitive;
- static char s[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(2, 8, VM_hash);
+ char s[VM_STRINGTEMP_LENGTH];
+ VM_SAFEPARMCOUNTRANGE(2, 8, VM_crc16);
insensitive = PRVM_G_FLOAT(OFS_PARM0);
- VM_VarString(1, s, sizeof(s));
+ VM_VarString(prog, 1, s, sizeof(s));
PRVM_G_FLOAT(OFS_RETURN) = (unsigned short) ((insensitive ? CRC_Block_CaseInsensitive : CRC_Block) ((unsigned char *) s, strlen(s)));
}
-void VM_wasfreed (void)
+// #639 float(string digest, string data, ...) digest_hex
+void VM_digest_hex(prvm_prog_t *prog)
+{
+ const char *digest;
+
+ char out[32];
+ char outhex[65];
+ int outlen;
+
+ char s[VM_STRINGTEMP_LENGTH];
+ int len;
+
+ VM_SAFEPARMCOUNTRANGE(2, 8, VM_digest_hex);
+ digest = PRVM_G_STRING(OFS_PARM0);
+ if(!digest)
+ digest = "";
+ VM_VarString(prog, 1, s, sizeof(s));
+ len = strlen(s);
+
+ outlen = 0;
+
+ if(!strcmp(digest, "MD4"))
+ {
+ outlen = 16;
+ mdfour((unsigned char *) out, (unsigned char *) s, len);
+ }
+ else if(!strcmp(digest, "SHA256") && Crypto_Available())
+ {
+ outlen = 32;
+ sha256((unsigned char *) out, (unsigned char *) s, len);
+ }
+ // no warning needed on mismatch - we return string_null to QC
+
+ if(outlen)
+ {
+ int i;
+ static const char *hexmap = "0123456789abcdef";
+ for(i = 0; i < outlen; ++i)
+ {
+ outhex[2*i] = hexmap[(out[i] >> 4) & 15];
+ outhex[2*i+1] = hexmap[(out[i] >> 0) & 15];
+ }
+ outhex[2*i] = 0;
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outhex);
+ }
+ else
+ PRVM_G_INT(OFS_RETURN) = 0;
+}
+
+void VM_wasfreed (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_wasfreed);
PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_EDICT(OFS_PARM0)->priv.required->free;
}
-void VM_SetTraceGlobals(const trace_t *trace)
+void VM_SetTraceGlobals(prvm_prog_t *prog, const trace_t *trace)
{
PRVM_gameglobalfloat(trace_allsolid) = trace->allsolid;
PRVM_gameglobalfloat(trace_startsolid) = trace->startsolid;
PRVM_gameglobalfloat(trace_dpstartcontents) = trace->startsupercontents;
PRVM_gameglobalfloat(trace_dphitcontents) = trace->hitsupercontents;
PRVM_gameglobalfloat(trace_dphitq3surfaceflags) = trace->hitq3surfaceflags;
- PRVM_gameglobalstring(trace_dphittexturename) = trace->hittexture ? PRVM_SetTempString(trace->hittexture->name) : 0;
+ PRVM_gameglobalstring(trace_dphittexturename) = trace->hittexture ? PRVM_SetTempString(prog, trace->hittexture->name) : 0;
}
-void VM_ClearTraceGlobals(void)
+void VM_ClearTraceGlobals(prvm_prog_t *prog)
{
// clean up all trace globals when leaving the VM (anti-triggerbot safeguard)
PRVM_gameglobalfloat(trace_allsolid) = 0;
//=============
-void VM_Cmd_Init(void)
+void VM_Cmd_Init(prvm_prog_t *prog)
{
// only init the stuff for the current prog
- VM_Files_Init();
- VM_Search_Init();
- VM_Gecko_Init();
-// VM_BufStr_Init();
+ VM_Files_Init(prog);
+ VM_Search_Init(prog);
}
-void VM_Cmd_Reset(void)
+void VM_Cmd_Reset(prvm_prog_t *prog)
{
CL_PurgeOwner( MENUOWNER );
- VM_Search_Reset();
- VM_Files_CloseAll();
- VM_Gecko_Destroy();
-// VM_BufStr_ShutDown();
+ VM_Search_Reset(prog);
+ VM_Files_CloseAll(prog);
}
// #510 string(string input, ...) uri_escape (DP_QC_URI_ESCAPE)
// does URI escaping on a string (replace evil stuff by %AB escapes)
-void VM_uri_escape (void)
+void VM_uri_escape (prvm_prog_t *prog)
{
char src[VM_STRINGTEMP_LENGTH];
char dest[VM_STRINGTEMP_LENGTH];
static const char *hex = "0123456789ABCDEF";
VM_SAFEPARMCOUNTRANGE(1, 8, VM_uri_escape);
- VM_VarString(0, src, sizeof(src));
+ VM_VarString(prog, 0, src, sizeof(src));
for(p = src, q = dest; *p && q < dest + sizeof(dest) - 3; ++p)
{
}
*q++ = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(dest);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, dest);
}
// #510 string(string input, ...) uri_unescape (DP_QC_URI_ESCAPE)
// does URI unescaping on a string (get back the evil stuff)
-void VM_uri_unescape (void)
+void VM_uri_unescape (prvm_prog_t *prog)
{
char src[VM_STRINGTEMP_LENGTH];
char dest[VM_STRINGTEMP_LENGTH];
int hi, lo;
VM_SAFEPARMCOUNTRANGE(1, 8, VM_uri_unescape);
- VM_VarString(0, src, sizeof(src));
+ VM_VarString(prog, 0, src, sizeof(src));
for(p = src, q = dest; *p; ) // no need to check size, because unescape can't expand
{
}
*q++ = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(dest);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, dest);
}
// #502 string(string filename) whichpack (DP_QC_WHICHPACK)
// returns the name of the pack containing a file, or "" if it is not in any pack (but local or non-existant)
-void VM_whichpack (void)
+void VM_whichpack (prvm_prog_t *prog)
{
const char *fn, *pack;
fn = PRVM_G_STRING(OFS_PARM0);
pack = FS_WhichPack(fn);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(pack ? pack : "");
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, pack ? pack : "");
}
typedef struct
{
- int prognr;
+ prvm_prog_t *prog;
double starttime;
float id;
char buffer[MAX_INPUTLINE];
static void uri_to_string_callback(int status, size_t length_received, unsigned char *buffer, void *cbdata)
{
+ prvm_prog_t *prog;
uri_to_prog_t *handle = (uri_to_prog_t *) cbdata;
- if(!PRVM_ProgLoaded(handle->prognr))
+ prog = handle->prog;
+ if(!prog->loaded)
{
// curl reply came too late... so just drop it
if(handle->postdata)
Z_Free(handle);
return;
}
-
- PRVM_SetProg(handle->prognr);
- PRVM_Begin;
- if((prog->starttime == handle->starttime) && (PRVM_allfunction(URI_Get_Callback)))
- {
- if(length_received >= sizeof(handle->buffer))
- length_received = sizeof(handle->buffer) - 1;
- handle->buffer[length_received] = 0;
-
- PRVM_G_FLOAT(OFS_PARM0) = handle->id;
- PRVM_G_FLOAT(OFS_PARM1) = status;
- PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(handle->buffer);
- PRVM_ExecuteProgram(PRVM_allfunction(URI_Get_Callback), "QC function URI_Get_Callback is missing");
- }
- PRVM_End;
-
+
+ if((prog->starttime == handle->starttime) && (PRVM_allfunction(URI_Get_Callback)))
+ {
+ if(length_received >= sizeof(handle->buffer))
+ length_received = sizeof(handle->buffer) - 1;
+ handle->buffer[length_received] = 0;
+
+ PRVM_G_FLOAT(OFS_PARM0) = handle->id;
+ PRVM_G_FLOAT(OFS_PARM1) = status;
+ PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(prog, handle->buffer);
+ prog->ExecuteProgram(prog, PRVM_allfunction(URI_Get_Callback), "QC function URI_Get_Callback is missing");
+ }
+
if(handle->postdata)
Z_Free(handle->postdata);
if(handle->sigdata)
// uri_get() gets content from an URL and calls a callback "uri_get_callback" with it set as string; an unique ID of the transfer is returned
// returns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string
-void VM_uri_get (void)
+void VM_uri_get (prvm_prog_t *prog)
{
const char *url;
float id;
size_t lq;
if(!PRVM_allfunction(URI_Get_Callback))
- PRVM_ERROR("uri_get called by %s without URI_Get_Callback defined", PRVM_NAME);
+ prog->error_cmd("uri_get called by %s without URI_Get_Callback defined", prog->name);
VM_SAFEPARMCOUNTRANGE(2, 6, VM_uri_get);
++query_string;
lq = query_string ? strlen(query_string) : 0;
- handle->prognr = PRVM_GetProgNr();
+ handle->prog = prog;
handle->starttime = prog->starttime;
handle->id = id;
- if(postseparator)
+ if(postseparator && posttype && *posttype)
{
size_t l = strlen(postseparator);
if(poststringbuffer >= 0)
stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, poststringbuffer);
if(!stringbuffer)
{
- VM_Warning("uri_get: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ VM_Warning(prog, "uri_get: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
return;
}
ltotal = 0;
}
}
if(ltotal != handle->postlen)
- PRVM_ERROR ("%s: string buffer content size mismatch, possible overrun", PRVM_NAME);
+ prog->error_cmd("%s: string buffer content size mismatch, possible overrun", prog->name);
}
else
{
}
}
-void VM_netaddress_resolve (void)
+void VM_netaddress_resolve (prvm_prog_t *prog)
{
const char *ip;
char normalized[128];
port = (int) PRVM_G_FLOAT(OFS_PARM1);
if(LHNETADDRESS_FromString(&addr, ip, port) && LHNETADDRESS_ToString(&addr, normalized, sizeof(normalized), prog->argc > 1))
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(normalized);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, normalized);
else
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString("");
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
}
-//string(void) getextresponse = #624; // returns the next extResponse packet that was sent to this client
-void VM_CL_getextresponse (void)
+//string(prvm_prog_t *prog) getextresponse = #624; // returns the next extResponse packet that was sent to this client
+void VM_CL_getextresponse (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_argv);
int first;
--cl_net_extresponse_count;
first = (cl_net_extresponse_last + NET_EXTRESPONSE_MAX - cl_net_extresponse_count) % NET_EXTRESPONSE_MAX;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(cl_net_extresponse[first]);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cl_net_extresponse[first]);
}
}
-void VM_SV_getextresponse (void)
+void VM_SV_getextresponse (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0,VM_argv);
int first;
--sv_net_extresponse_count;
first = (sv_net_extresponse_last + NET_EXTRESPONSE_MAX - sv_net_extresponse_count) % NET_EXTRESPONSE_MAX;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(sv_net_extresponse[first]);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, sv_net_extresponse[first]);
}
}
*/
//#349 float() isdemo
-void VM_CL_isdemo (void)
+void VM_CL_isdemo (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_isdemo);
PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
}
//#355 float() videoplaying
-void VM_CL_videoplaying (void)
+void VM_CL_videoplaying (prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(0, VM_CL_videoplaying);
PRVM_G_FLOAT(OFS_RETURN) = cl_videoplaying;
Extension: pass
=========
*/
-mfunction_t *PRVM_ED_FindFunction (const char *name);
-void VM_callfunction(void)
+void VM_callfunction(prvm_prog_t *prog)
{
mfunction_t *func;
const char *s;
s = PRVM_G_STRING(OFS_PARM0+(prog->argc - 1)*3);
- VM_CheckEmptyString(s);
+ VM_CheckEmptyString(prog, s);
- func = PRVM_ED_FindFunction(s);
+ func = PRVM_ED_FindFunction(prog, s);
if(!func)
- PRVM_ERROR("VM_callfunciton: function %s not found !", s);
+ prog->error_cmd("VM_callfunciton: function %s not found !", s);
else if (func->first_statement < 0)
{
// negative statements are built in functions
int builtinnumber = -func->first_statement;
prog->xfunction->builtinsprofile++;
if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
- prog->builtins[builtinnumber]();
+ prog->builtins[builtinnumber](prog);
else
- PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
+ prog->error_cmd("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, prog->name);
}
else if(func - prog->functions > 0)
{
prog->argc--;
- PRVM_ExecuteProgram(func - prog->functions,"");
+ prog->ExecuteProgram(prog, func - prog->functions,"");
prog->argc++;
}
}
float isfunction(string function_name)
=========
*/
-mfunction_t *PRVM_ED_FindFunction (const char *name);
-void VM_isfunction(void)
+void VM_isfunction(prvm_prog_t *prog)
{
mfunction_t *func;
const char *s;
s = PRVM_G_STRING(OFS_PARM0);
- VM_CheckEmptyString(s);
+ VM_CheckEmptyString(prog, s);
- func = PRVM_ED_FindFunction(s);
+ func = PRVM_ED_FindFunction(prog, s);
if(!func)
PRVM_G_FLOAT(OFS_RETURN) = false;
=========
*/
-void VM_sprintf(void)
+void VM_sprintf(prvm_prog_t *prog)
{
const char *s, *s0;
char outbuf[MAX_INPUTLINE];
int isfloat;
static int dummyivec[3] = {0, 0, 0};
static float dummyvec[3] = {0, 0, 0};
+ char vabuf[1024];
#define PRINTF_ALTERNATE 1
#define PRINTF_ZEROPAD 2
width = strtol(s, &err, 10);
if(!err)
{
- VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ VM_Warning(prog, "VM_sprintf: invalid directive in %s: %s\n", prog->name, s0);
goto finished;
}
if(*err == '$')
width = strtol(s, &err, 10);
if(!err || *err != '$')
{
- VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ VM_Warning(prog, "VM_sprintf: invalid directive in %s: %s\n", prog->name, s0);
goto finished;
}
s = err + 1;
width = strtol(s, &err, 10);
if(!err)
{
- VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ VM_Warning(prog, "VM_sprintf: invalid directive in %s: %s\n", prog->name, s0);
goto finished;
}
s = err;
precision = strtol(s, &err, 10);
if(!err || *err != '$')
{
- VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ VM_Warning(prog, "VM_sprintf: invalid directive in %s: %s\n", prog->name, s0);
goto finished;
}
s = err + 1;
precision = strtol(s, &err, 10);
if(!err)
{
- VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ VM_Warning(prog, "VM_sprintf: invalid directive in %s: %s\n", prog->name, s0);
goto finished;
}
s = err;
}
else
{
- VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ VM_Warning(prog, "VM_sprintf: invalid directive in %s: %s\n", prog->name, s0);
goto finished;
}
}
case 'v': case 'V':
f[-2] += 'g' - 'v';
if(precision < 0) // not set
- o += dpsnprintf(o, end - o, va("%s %s %s", /* NESTED SPRINTF IS NESTED */ formatbuf, formatbuf, formatbuf),
+ o += dpsnprintf(o, end - o, va(vabuf, sizeof(vabuf), "%s %s %s", /* NESTED SPRINTF IS NESTED */ formatbuf, formatbuf, formatbuf),
width, (isfloat ? (double) GETARG_VECTOR(thisarg)[0] : (double) GETARG_INTVECTOR(thisarg)[0]),
width, (isfloat ? (double) GETARG_VECTOR(thisarg)[1] : (double) GETARG_INTVECTOR(thisarg)[1]),
width, (isfloat ? (double) GETARG_VECTOR(thisarg)[2] : (double) GETARG_INTVECTOR(thisarg)[2])
);
else
- o += dpsnprintf(o, end - o, va("%s %s %s", /* NESTED SPRINTF IS NESTED */ formatbuf, formatbuf, formatbuf),
+ o += dpsnprintf(o, end - o, va(vabuf, sizeof(vabuf), "%s %s %s", /* NESTED SPRINTF IS NESTED */ formatbuf, formatbuf, formatbuf),
width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[0] : (double) GETARG_INTVECTOR(thisarg)[0]),
width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[1] : (double) GETARG_INTVECTOR(thisarg)[1]),
width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[2] : (double) GETARG_INTVECTOR(thisarg)[2])
else
{
unsigned int c = (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg));
- const char *buf = u8_encodech(c, NULL);
+ char charbuf16[16];
+ const char *buf = u8_encodech(c, NULL, charbuf16);
if(!buf)
buf = "";
if(precision < 0) // not set
}
break;
default:
- VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ VM_Warning(prog, "VM_sprintf: invalid directive in %s: %s\n", prog->name, s0);
goto finished;
}
}
}
finished:
*o = 0;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(outbuf);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outbuf);
}
// surface querying
-static dp_model_t *getmodel(prvm_edict_t *ed)
+static dp_model_t *getmodel(prvm_prog_t *prog, prvm_edict_t *ed)
{
- switch(PRVM_GetProgNr())
- {
- case PRVM_SERVERPROG:
- return SV_GetModelFromEdict(ed);
- case PRVM_CLIENTPROG:
- return CL_GetModelFromEdict(ed);
- default:
- return NULL;
- }
+ if (prog == SVVM_prog)
+ return SV_GetModelFromEdict(ed);
+ else if (prog == CLVM_prog)
+ return CL_GetModelFromEdict(ed);
+ else
+ return NULL;
}
typedef struct
animatemodel_cache_t;
static animatemodel_cache_t animatemodel_cache;
-void animatemodel(dp_model_t *model, prvm_edict_t *ed)
+static void animatemodel(prvm_prog_t *prog, dp_model_t *model, prvm_edict_t *ed)
{
skeleton_t *skeleton;
int skeletonindex = -1;
if(animatemodel_cache.progid != prog->id)
memset(&animatemodel_cache, 0, sizeof(animatemodel_cache));
need |= (animatemodel_cache.model != model);
- VM_GenerateFrameGroupBlend(ed->priv.server->framegroupblend, ed);
+ VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed);
VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model);
need |= (memcmp(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0;
skeletonindex = (int)PRVM_gameedictfloat(ed, skeletonindex) - 1;
animatemodel_cache.data_svector3f = animatemodel_cache.buf_svector3f;
animatemodel_cache.data_tvector3f = animatemodel_cache.buf_tvector3f;
animatemodel_cache.data_normal3f = animatemodel_cache.buf_normal3f;
- VM_UpdateEdictSkeleton(ed, model, ed->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, ed, model, ed->priv.server->frameblend);
model->AnimateVertices(model, ed->priv.server->frameblend, &ed->priv.server->skeleton, animatemodel_cache.data_vertex3f, animatemodel_cache.data_normal3f, animatemodel_cache.data_svector3f, animatemodel_cache.data_tvector3f);
animatemodel_cache.progid = prog->id;
animatemodel_cache.model = model;
memcpy(&animatemodel_cache.skeleton, skeleton, sizeof(ed->priv.server->skeleton));
}
-static void getmatrix(prvm_edict_t *ed, matrix4x4_t *out)
+static void getmatrix(prvm_prog_t *prog, prvm_edict_t *ed, matrix4x4_t *out)
{
- switch(PRVM_GetProgNr())
- {
- case PRVM_SERVERPROG:
- SV_GetEntityMatrix(ed, out, false);
- break;
- case PRVM_CLIENTPROG:
- CL_GetEntityMatrix(ed, out, false);
- break;
- default:
- *out = identitymatrix;
- break;
- }
+ if (prog == SVVM_prog)
+ SV_GetEntityMatrix(prog, ed, out, false);
+ else if (prog == CLVM_prog)
+ CL_GetEntityMatrix(prog, ed, out, false);
+ else
+ *out = identitymatrix;
}
-static void applytransform_forward(const vec3_t in, prvm_edict_t *ed, vec3_t out)
+static void applytransform_forward(prvm_prog_t *prog, const vec3_t in, prvm_edict_t *ed, vec3_t out)
{
matrix4x4_t m;
- getmatrix(ed, &m);
+ getmatrix(prog, ed, &m);
Matrix4x4_Transform(&m, in, out);
}
-static void applytransform_forward_direction(const vec3_t in, prvm_edict_t *ed, vec3_t out)
+static void applytransform_forward_direction(prvm_prog_t *prog, const vec3_t in, prvm_edict_t *ed, vec3_t out)
{
matrix4x4_t m;
- getmatrix(ed, &m);
+ getmatrix(prog, ed, &m);
Matrix4x4_Transform3x3(&m, in, out);
}
-static void applytransform_inverted(const vec3_t in, prvm_edict_t *ed, vec3_t out)
+static void applytransform_inverted(prvm_prog_t *prog, const vec3_t in, prvm_edict_t *ed, vec3_t out)
{
matrix4x4_t m, n;
- getmatrix(ed, &m);
+ getmatrix(prog, ed, &m);
Matrix4x4_Invert_Full(&n, &m);
Matrix4x4_Transform3x3(&n, in, out);
}
-static void applytransform_forward_normal(const vec3_t in, prvm_edict_t *ed, vec3_t out)
+static void applytransform_forward_normal(prvm_prog_t *prog, const vec3_t in, prvm_edict_t *ed, vec3_t out)
{
matrix4x4_t m;
float p[4];
- getmatrix(ed, &m);
+ getmatrix(prog, ed, &m);
Matrix4x4_TransformPositivePlane(&m, in[0], in[1], in[2], 0, p);
VectorCopy(p, out);
}
-static void clippointtosurface(prvm_edict_t *ed, dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
+static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
{
int i, j, k;
float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
const int *e;
- animatemodel(model, ed);
+ animatemodel(prog, model, ed);
bestdist = 1000000000;
VectorCopy(p, out);
for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
//PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
-void VM_getsurfacenumpoints(void)
+void VM_getsurfacenumpoints(prvm_prog_t *prog)
{
dp_model_t *model;
msurface_t *surface;
VM_SAFEPARMCOUNT(2, VM_getsurfacenumpoints);
// return 0 if no such surface
- if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
{
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
}
//PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
-void VM_getsurfacepoint(void)
+void VM_getsurfacepoint(prvm_prog_t *prog)
{
prvm_edict_t *ed;
dp_model_t *model;
VM_SAFEPARMCOUNT(3, VM_getsurfacepoint);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
ed = PRVM_G_EDICT(OFS_PARM0);
- if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
return;
// note: this (incorrectly) assumes it is a simple polygon
pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
if (pointnum < 0 || pointnum >= surface->num_vertices)
return;
- animatemodel(model, ed);
- applytransform_forward(&(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ animatemodel(prog, model, ed);
+ applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
}
//PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
// float SPA_POSITION = 0;
// float SPA_TEXCOORDS0 = 4;
// float SPA_LIGHTMAP0_TEXCOORDS = 5;
// float SPA_LIGHTMAP0_COLOR = 6;
-void VM_getsurfacepointattribute(void)
+void VM_getsurfacepointattribute(prvm_prog_t *prog)
{
prvm_edict_t *ed;
dp_model_t *model;
VM_SAFEPARMCOUNT(4, VM_getsurfacepoint);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
ed = PRVM_G_EDICT(OFS_PARM0);
- if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
return;
pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
if (pointnum < 0 || pointnum >= surface->num_vertices)
return;
attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
- animatemodel(model, ed);
+ animatemodel(prog, model, ed);
switch( attributetype ) {
// float SPA_POSITION = 0;
case 0:
- applytransform_forward(&(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_S_AXIS = 1;
case 1:
- applytransform_forward_direction(&(animatemodel_cache.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_direction(prog, &(animatemodel_cache.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_T_AXIS = 2;
case 2:
- applytransform_forward_direction(&(animatemodel_cache.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_direction(prog, &(animatemodel_cache.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_R_AXIS = 3; // same as SPA_NORMAL
case 3:
- applytransform_forward_direction(&(animatemodel_cache.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_direction(prog, &(animatemodel_cache.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_TEXCOORDS0 = 4;
case 4: {
}
}
//PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
-void VM_getsurfacenormal(void)
+void VM_getsurfacenormal(prvm_prog_t *prog)
{
dp_model_t *model;
msurface_t *surface;
vec3_t normal;
VM_SAFEPARMCOUNT(2, VM_getsurfacenormal);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
- if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
return;
// note: this only returns the first triangle, so it doesn't work very
// well for curved surfaces or arbitrary meshes
- animatemodel(model, PRVM_G_EDICT(OFS_PARM0));
+ animatemodel(prog, model, PRVM_G_EDICT(OFS_PARM0));
TriangleNormal((animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex), (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 3, (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
- applytransform_forward_normal(normal, PRVM_G_EDICT(OFS_PARM0), PRVM_G_VECTOR(OFS_RETURN));
+ applytransform_forward_normal(prog, normal, PRVM_G_EDICT(OFS_PARM0), PRVM_G_VECTOR(OFS_RETURN));
VectorNormalize(PRVM_G_VECTOR(OFS_RETURN));
}
//PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
-void VM_getsurfacetexture(void)
+void VM_getsurfacetexture(prvm_prog_t *prog)
{
dp_model_t *model;
msurface_t *surface;
VM_SAFEPARMCOUNT(2, VM_getsurfacetexture);
PRVM_G_INT(OFS_RETURN) = OFS_NULL;
- if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
return;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(surface->texture->name);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, surface->texture->name);
}
//PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
-void VM_getsurfacenearpoint(void)
+void VM_getsurfacenearpoint(prvm_prog_t *prog)
{
int surfacenum, best;
vec3_t clipped, p;
if (!ed || ed->priv.server->free)
return;
- model = getmodel(ed);
+ model = getmodel(prog, ed);
if (!model || !model->num_surfaces)
return;
- animatemodel(model, ed);
+ animatemodel(prog, model, ed);
- applytransform_inverted(point, ed, p);
+ applytransform_inverted(prog, point, ed, p);
best = -1;
bestdist = 1000000000;
for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
if (dist < bestdist)
{
// it is, check the nearest point on the actual geometry
- clippointtosurface(ed, model, surface, p, clipped);
+ clippointtosurface(prog, ed, model, surface, p, clipped);
VectorSubtract(clipped, p, clipped);
dist += VectorLength2(clipped);
if (dist < bestdist)
PRVM_G_FLOAT(OFS_RETURN) = best;
}
//PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
-void VM_getsurfaceclippedpoint(void)
+void VM_getsurfaceclippedpoint(prvm_prog_t *prog)
{
prvm_edict_t *ed;
dp_model_t *model;
VM_SAFEPARMCOUNT(3, VM_te_getsurfaceclippedpoint);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
ed = PRVM_G_EDICT(OFS_PARM0);
- if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
return;
- animatemodel(model, ed);
- applytransform_inverted(PRVM_G_VECTOR(OFS_PARM2), ed, p);
- clippointtosurface(ed, model, surface, p, out);
+ animatemodel(prog, model, ed);
+ applytransform_inverted(prog, PRVM_G_VECTOR(OFS_PARM2), ed, p);
+ clippointtosurface(prog, ed, model, surface, p, out);
VectorAdd(out, PRVM_serveredictvector(ed, origin), PRVM_G_VECTOR(OFS_RETURN));
}
//PF_getsurfacenumtriangles, // #??? float(entity e, float s) getsurfacenumtriangles = #???;
-void VM_getsurfacenumtriangles(void)
+void VM_getsurfacenumtriangles(prvm_prog_t *prog)
{
dp_model_t *model;
msurface_t *surface;
VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumtriangles);
// return 0 if no such surface
- if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
{
PRVM_G_FLOAT(OFS_RETURN) = 0;
return;
}
- // note: this (incorrectly) assumes it is a simple polygon
PRVM_G_FLOAT(OFS_RETURN) = surface->num_triangles;
}
//PF_getsurfacetriangle, // #??? vector(entity e, float s, float n) getsurfacetriangle = #???;
-void VM_getsurfacetriangle(void)
+void VM_getsurfacetriangle(prvm_prog_t *prog)
{
const vec3_t d = {-1, -1, -1};
prvm_edict_t *ed;
VM_SAFEPARMCOUNT(3, VM_SV_getsurfacetriangle);
VectorClear(PRVM_G_VECTOR(OFS_RETURN));
ed = PRVM_G_EDICT(OFS_PARM0);
- if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+ if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
return;
trinum = (int)PRVM_G_FLOAT(OFS_PARM2);
if (trinum < 0 || trinum >= surface->num_triangles)
// physics builtins
//
-void World_Physics_ApplyCmd(prvm_edict_t *ed, edict_odefunc_t *f);
-
-#define VM_physics_ApplyCmd(ed,f) if (!ed->priv.server->ode_body) VM_physics_newstackfunction(ed, f); else World_Physics_ApplyCmd(ed, f)
+#define VM_physics_ApplyCmd(ed,f) if (!ed->priv.server->ode_body) VM_physics_newstackfunction(prog, ed, f); else World_Physics_ApplyCmd(ed, f)
-edict_odefunc_t *VM_physics_newstackfunction(prvm_edict_t *ed, edict_odefunc_t *f)
+static edict_odefunc_t *VM_physics_newstackfunction(prvm_prog_t *prog, prvm_edict_t *ed, edict_odefunc_t *f)
{
edict_odefunc_t *newfunc, *func;
}
// void(entity e, float physics_enabled) physics_enable = #;
-void VM_physics_enable(void)
+void VM_physics_enable(prvm_prog_t *prog)
{
prvm_edict_t *ed;
edict_odefunc_t f;
if (!ed)
{
if (developer.integer > 0)
- VM_Warning("VM_physics_enable: null entity!\n");
+ VM_Warning(prog, "VM_physics_enable: null entity!\n");
return;
}
// entity should have MOVETYPE_PHYSICS already set, this can damage memory (making leaked allocation) so warn about this even if non-developer
if (PRVM_serveredictfloat(ed, movetype) != MOVETYPE_PHYSICS)
{
- VM_Warning("VM_physics_enable: entity is not MOVETYPE_PHYSICS!\n");
+ VM_Warning(prog, "VM_physics_enable: entity is not MOVETYPE_PHYSICS!\n");
return;
}
f.type = PRVM_G_FLOAT(OFS_PARM1) == 0 ? ODEFUNC_DISABLE : ODEFUNC_ENABLE;
}
// void(entity e, vector force, vector relative_ofs) physics_addforce = #;
-void VM_physics_addforce(void)
+void VM_physics_addforce(prvm_prog_t *prog)
{
prvm_edict_t *ed;
edict_odefunc_t f;
if (!ed)
{
if (developer.integer > 0)
- VM_Warning("VM_physics_addforce: null entity!\n");
+ VM_Warning(prog, "VM_physics_addforce: null entity!\n");
return;
}
// entity should have MOVETYPE_PHYSICS already set, this can damage memory (making leaked allocation) so warn about this even if non-developer
if (PRVM_serveredictfloat(ed, movetype) != MOVETYPE_PHYSICS)
{
- VM_Warning("VM_physics_addforce: entity is not MOVETYPE_PHYSICS!\n");
+ VM_Warning(prog, "VM_physics_addforce: entity is not MOVETYPE_PHYSICS!\n");
return;
}
f.type = ODEFUNC_RELFORCEATPOS;
}
// void(entity e, vector torque) physics_addtorque = #;
-void VM_physics_addtorque(void)
+void VM_physics_addtorque(prvm_prog_t *prog)
{
prvm_edict_t *ed;
edict_odefunc_t f;
if (!ed)
{
if (developer.integer > 0)
- VM_Warning("VM_physics_addtorque: null entity!\n");
+ VM_Warning(prog, "VM_physics_addtorque: null entity!\n");
return;
}
// entity should have MOVETYPE_PHYSICS already set, this can damage memory (making leaked allocation) so warn about this even if non-developer
if (PRVM_serveredictfloat(ed, movetype) != MOVETYPE_PHYSICS)
{
- VM_Warning("VM_physics_addtorque: entity is not MOVETYPE_PHYSICS!\n");
+ VM_Warning(prog, "VM_physics_addtorque: entity is not MOVETYPE_PHYSICS!\n");
return;
}
f.type = ODEFUNC_RELTORQUE;
+
+#ifndef PRVM_CMDS_H
+#define PRVM_CMDS_H
+
// AK
// Basically every vm builtin cmd should be in here.
// All 3 builtin and extension lists can be found here
#include "mprogdefs.h"
#include "cl_video.h"
-#include "cl_gecko.h"
//============================================================================
// nice helper macros
#ifndef VM_NOPARMCHECK
-#define VM_SAFEPARMCOUNTRANGE(p1,p2,f) if(prog->argc < p1 || prog->argc > p2) PRVM_ERROR(#f " wrong parameter count %i (" #p1 " to " #p2 " expected ) !", prog->argc)
-#define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) PRVM_ERROR(#f " wrong parameter count %i (" #p " expected ) !", prog->argc)
+#define VM_SAFEPARMCOUNTRANGE(p1,p2,f) if(prog->argc < p1 || prog->argc > p2) prog->error_cmd(#f " wrong parameter count %i (" #p1 " to " #p2 " expected ) !", prog->argc)
+#define VM_SAFEPARMCOUNT(p,f) if(prog->argc != p) prog->error_cmd(#f " wrong parameter count %i (" #p " expected ) !", prog->argc)
#else
#define VM_SAFEPARMCOUNTRANGE(p1,p2,f)
#define VM_SAFEPARMCOUNT(p,f)
#define VM_STRINGTEMP_LENGTH MAX_INPUTLINE
+// init code
+void PR_Cmd_Init(void);
+
// builtins and other general functions
-void VM_CheckEmptyString (const char *s);
-void VM_VarString(int first, char *out, int outlength);
-
-void VM_checkextension (void);
-void VM_error (void);
-void VM_objerror (void);
-void VM_print (void);
-void VM_bprint (void);
-void VM_sprint (void);
-void VM_centerprint (void);
-void VM_normalize (void);
-void VM_vlen (void);
-void VM_vectoyaw (void);
-void VM_vectoangles (void);
-void VM_random (void);
-void VM_localsound(void);
-void VM_break (void);
-void VM_localcmd (void);
-void VM_cvar (void);
-void VM_cvar_string(void);
-void VM_cvar_type (void);
-void VM_cvar_defstring (void);
-void VM_cvar_set (void);
-void VM_dprint (void);
-void VM_ftos (void);
-void VM_fabs (void);
-void VM_vtos (void);
-void VM_etos (void);
-void VM_stof(void);
-void VM_itof(void);
-void VM_ftoe(void);
-void VM_strftime(void);
-void VM_spawn (void);
-void VM_remove (void);
-void VM_find (void);
-void VM_findfloat (void);
-void VM_findchain (void);
-void VM_findchainfloat (void);
-void VM_findflags (void);
-void VM_findchainflags (void);
-void VM_precache_file (void);
-void VM_precache_sound (void);
-void VM_coredump (void);
-
-void VM_stackdump (void);
-void VM_crash(void); // REMOVE IT
-void VM_traceon (void);
-void VM_traceoff (void);
-void VM_eprint (void);
-void VM_rint (void);
-void VM_floor (void);
-void VM_ceil (void);
-void VM_nextent (void);
-
-void VM_changelevel (void);
-void VM_sin (void);
-void VM_cos (void);
-void VM_sqrt (void);
-void VM_randomvec (void);
-void VM_registercvar (void);
-void VM_min (void);
-void VM_max (void);
-void VM_bound (void);
-void VM_pow (void);
-void VM_log (void);
-void VM_asin (void);
-void VM_acos (void);
-void VM_atan (void);
-void VM_atan2 (void);
-void VM_tan (void);
-
-void VM_Files_Init(void);
-void VM_Files_CloseAll(void);
-
-void VM_fopen(void);
-void VM_fclose(void);
-void VM_fgets(void);
-void VM_fputs(void);
-void VM_writetofile(void); // only used by menu
-
-void VM_strlen(void);
-void VM_strcat(void);
-void VM_substring(void);
-void VM_stov(void);
-void VM_strzone(void);
-void VM_strunzone(void);
+void VM_CheckEmptyString (prvm_prog_t *prog, const char *s);
+void VM_VarString(prvm_prog_t *prog, int first, char *out, int outlength);
+
+void VM_checkextension (prvm_prog_t *prog);
+void VM_error (prvm_prog_t *prog);
+void VM_objerror (prvm_prog_t *prog);
+void VM_print (prvm_prog_t *prog);
+void VM_bprint (prvm_prog_t *prog);
+void VM_sprint (prvm_prog_t *prog);
+void VM_centerprint (prvm_prog_t *prog);
+void VM_normalize (prvm_prog_t *prog);
+void VM_vlen (prvm_prog_t *prog);
+void VM_vectoyaw (prvm_prog_t *prog);
+void VM_vectoangles (prvm_prog_t *prog);
+void VM_random (prvm_prog_t *prog);
+void VM_localsound(prvm_prog_t *prog);
+void VM_break (prvm_prog_t *prog);
+void VM_localcmd (prvm_prog_t *prog);
+void VM_cvar (prvm_prog_t *prog);
+void VM_cvar_string(prvm_prog_t *prog);
+void VM_cvar_type (prvm_prog_t *prog);
+void VM_cvar_defstring (prvm_prog_t *prog);
+void VM_cvar_set (prvm_prog_t *prog);
+void VM_dprint (prvm_prog_t *prog);
+void VM_ftos (prvm_prog_t *prog);
+void VM_fabs (prvm_prog_t *prog);
+void VM_vtos (prvm_prog_t *prog);
+void VM_etos (prvm_prog_t *prog);
+void VM_stof(prvm_prog_t *prog);
+void VM_itof(prvm_prog_t *prog);
+void VM_ftoe(prvm_prog_t *prog);
+void VM_strftime(prvm_prog_t *prog);
+void VM_spawn (prvm_prog_t *prog);
+void VM_remove (prvm_prog_t *prog);
+void VM_find (prvm_prog_t *prog);
+void VM_findfloat (prvm_prog_t *prog);
+void VM_findchain (prvm_prog_t *prog);
+void VM_findchainfloat (prvm_prog_t *prog);
+void VM_findflags (prvm_prog_t *prog);
+void VM_findchainflags (prvm_prog_t *prog);
+void VM_precache_file (prvm_prog_t *prog);
+void VM_precache_sound (prvm_prog_t *prog);
+void VM_coredump (prvm_prog_t *prog);
+
+void VM_stackdump (prvm_prog_t *prog);
+void VM_crash(prvm_prog_t *prog); // REMOVE IT
+void VM_traceon (prvm_prog_t *prog);
+void VM_traceoff (prvm_prog_t *prog);
+void VM_eprint (prvm_prog_t *prog);
+void VM_rint (prvm_prog_t *prog);
+void VM_floor (prvm_prog_t *prog);
+void VM_ceil (prvm_prog_t *prog);
+void VM_nextent (prvm_prog_t *prog);
+
+void VM_changelevel (prvm_prog_t *prog);
+void VM_sin (prvm_prog_t *prog);
+void VM_cos (prvm_prog_t *prog);
+void VM_sqrt (prvm_prog_t *prog);
+void VM_randomvec (prvm_prog_t *prog);
+void VM_registercvar (prvm_prog_t *prog);
+void VM_min (prvm_prog_t *prog);
+void VM_max (prvm_prog_t *prog);
+void VM_bound (prvm_prog_t *prog);
+void VM_pow (prvm_prog_t *prog);
+void VM_log (prvm_prog_t *prog);
+void VM_asin (prvm_prog_t *prog);
+void VM_acos (prvm_prog_t *prog);
+void VM_atan (prvm_prog_t *prog);
+void VM_atan2 (prvm_prog_t *prog);
+void VM_tan (prvm_prog_t *prog);
+
+void VM_Files_Init(prvm_prog_t *prog);
+void VM_Files_CloseAll(prvm_prog_t *prog);
+
+void VM_fopen(prvm_prog_t *prog);
+void VM_fclose(prvm_prog_t *prog);
+void VM_fgets(prvm_prog_t *prog);
+void VM_fputs(prvm_prog_t *prog);
+void VM_writetofile(prvm_prog_t *prog); // only used by menu
+
+void VM_strlen(prvm_prog_t *prog);
+void VM_strcat(prvm_prog_t *prog);
+void VM_substring(prvm_prog_t *prog);
+void VM_stov(prvm_prog_t *prog);
+void VM_strzone(prvm_prog_t *prog);
+void VM_strunzone(prvm_prog_t *prog);
// KrimZon - DP_QC_ENTITYDATA
-void VM_numentityfields(void);
-void VM_entityfieldname(void);
-void VM_entityfieldtype(void);
-void VM_getentityfieldstring(void);
-void VM_putentityfieldstring(void);
-// And declared these ones for VM_getentityfieldstring and VM_putentityfieldstring in prvm_cmds.c
-// the function is from prvm_edict.c
-char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val);
-qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash);
+void VM_numentityfields(prvm_prog_t *prog);
+void VM_entityfieldname(prvm_prog_t *prog);
+void VM_entityfieldtype(prvm_prog_t *prog);
+void VM_getentityfieldstring(prvm_prog_t *prog);
+void VM_putentityfieldstring(prvm_prog_t *prog);
// DRESK - String Length (not counting color codes)
-void VM_strlennocol(void);
+void VM_strlennocol(prvm_prog_t *prog);
// DRESK - Decolorized String
-void VM_strdecolorize(void);
+void VM_strdecolorize(prvm_prog_t *prog);
// DRESK - String Uppercase and Lowercase Support
-void VM_strtolower(void);
-void VM_strtoupper(void);
+void VM_strtolower(prvm_prog_t *prog);
+void VM_strtoupper(prvm_prog_t *prog);
-void VM_clcommand (void);
+void VM_clcommand (prvm_prog_t *prog);
-void VM_tokenize (void);
-void VM_tokenizebyseparator (void);
-void VM_argv (void);
+void VM_tokenize (prvm_prog_t *prog);
+void VM_tokenizebyseparator (prvm_prog_t *prog);
+void VM_argv (prvm_prog_t *prog);
-void VM_isserver(void);
-void VM_clientcount(void);
-void VM_clientstate(void);
+void VM_isserver(prvm_prog_t *prog);
+void VM_clientcount(prvm_prog_t *prog);
+void VM_clientstate(prvm_prog_t *prog);
// not used at the moment -> not included in the common list
-void VM_getostype(void);
-void VM_getmousepos(void);
-void VM_gettime(void);
-void VM_getsoundtime(void);
-void VM_soundlength(void);
-void VM_loadfromdata(void);
-void VM_parseentitydata(void);
-void VM_loadfromfile(void);
-void VM_modulo(void);
-
-void VM_search_begin(void);
-void VM_search_end(void);
-void VM_search_getsize(void);
-void VM_search_getfilename(void);
-void VM_chr(void);
-void VM_iscachedpic(void);
-void VM_precache_pic(void);
-void VM_freepic(void);
-void VM_drawcharacter(void);
-void VM_drawstring(void);
-void VM_drawcolorcodedstring(void);
-void VM_stringwidth(void);
-void VM_drawpic(void);
-void VM_drawrotpic(void);
-void VM_drawsubpic(void);
-void VM_drawfill(void);
-void VM_drawsetcliparea(void);
-void VM_drawresetcliparea(void);
-void VM_getimagesize(void);
-
-void VM_findfont(void);
-void VM_loadfont(void);
-
-void VM_makevectors (void);
-void VM_vectorvectors (void);
-
-void VM_keynumtostring (void);
-void VM_getkeybind (void);
-void VM_findkeysforcommand (void);
-void VM_stringtokeynum (void);
-void VM_setkeybind (void);
-void VM_getbindmaps (void);
-void VM_setbindmaps (void);
-
-void VM_cin_open( void );
-void VM_cin_close( void );
-void VM_cin_setstate( void );
-void VM_cin_getstate( void );
-void VM_cin_restart( void );
-
-void VM_gecko_create( void );
-void VM_gecko_destroy( void );
-void VM_gecko_navigate( void );
-void VM_gecko_keyevent( void );
-void VM_gecko_movemouse( void );
-void VM_gecko_resize( void );
-void VM_gecko_get_texture_extent( void );
-
-void VM_drawline (void);
-
-void VM_bitshift (void);
-
-void VM_altstr_count( void );
-void VM_altstr_prepare( void );
-void VM_altstr_get( void );
-void VM_altstr_set( void );
-void VM_altstr_ins(void);
-
-void VM_buf_create(void);
-void VM_buf_del (void);
-void VM_buf_getsize (void);
-void VM_buf_copy (void);
-void VM_buf_sort (void);
-void VM_buf_implode (void);
-void VM_bufstr_get (void);
-void VM_bufstr_set (void);
-void VM_bufstr_add (void);
-void VM_bufstr_free (void);
-
-void VM_changeyaw (void);
-void VM_changepitch (void);
-
-void VM_uncolorstring (void);
-
-void VM_strstrofs (void);
-void VM_str2chr (void);
-void VM_chr2str (void);
-void VM_strconv (void);
-void VM_strpad (void);
-void VM_infoadd (void);
-void VM_infoget (void);
-void VM_strncmp (void);
-void VM_strncmp (void);
-void VM_strncasecmp (void);
-void VM_registercvar (void);
-void VM_wasfreed (void);
-
-void VM_strreplace (void);
-void VM_strireplace (void);
-
-void VM_crc16(void);
-
-void VM_SetTraceGlobals(const trace_t *trace);
-void VM_ClearTraceGlobals(void);
-
-void VM_Cmd_Init(void);
-void VM_Cmd_Reset(void);
-
-void VM_uri_escape (void);
-void VM_uri_unescape (void);
-void VM_whichpack (void);
-
-void VM_etof (void);
-void VM_uri_get (void);
-void VM_netaddress_resolve (void);
-
-void VM_tokenize_console (void);
-void VM_argv_start_index (void);
-void VM_argv_end_index (void);
-
-void VM_buf_cvarlist(void);
-void VM_cvar_description(void);
-
-void VM_CL_getextresponse (void);
-void VM_SV_getextresponse (void);
+void VM_getostype(prvm_prog_t *prog);
+void VM_getmousepos(prvm_prog_t *prog);
+void VM_gettime(prvm_prog_t *prog);
+void VM_getsoundtime(prvm_prog_t *prog);
+void VM_soundlength(prvm_prog_t *prog);
+void VM_loadfromdata(prvm_prog_t *prog);
+void VM_parseentitydata(prvm_prog_t *prog);
+void VM_loadfromfile(prvm_prog_t *prog);
+void VM_modulo(prvm_prog_t *prog);
+
+void VM_search_begin(prvm_prog_t *prog);
+void VM_search_end(prvm_prog_t *prog);
+void VM_search_getsize(prvm_prog_t *prog);
+void VM_search_getfilename(prvm_prog_t *prog);
+void VM_chr(prvm_prog_t *prog);
+void VM_iscachedpic(prvm_prog_t *prog);
+void VM_precache_pic(prvm_prog_t *prog);
+void VM_freepic(prvm_prog_t *prog);
+void VM_drawcharacter(prvm_prog_t *prog);
+void VM_drawstring(prvm_prog_t *prog);
+void VM_drawcolorcodedstring(prvm_prog_t *prog);
+void VM_stringwidth(prvm_prog_t *prog);
+void VM_drawpic(prvm_prog_t *prog);
+void VM_drawrotpic(prvm_prog_t *prog);
+void VM_drawsubpic(prvm_prog_t *prog);
+void VM_drawfill(prvm_prog_t *prog);
+void VM_drawsetcliparea(prvm_prog_t *prog);
+void VM_drawresetcliparea(prvm_prog_t *prog);
+void VM_getimagesize(prvm_prog_t *prog);
+
+void VM_findfont(prvm_prog_t *prog);
+void VM_loadfont(prvm_prog_t *prog);
+
+void VM_makevectors (prvm_prog_t *prog);
+void VM_vectorvectors (prvm_prog_t *prog);
+
+void VM_keynumtostring (prvm_prog_t *prog);
+void VM_getkeybind (prvm_prog_t *prog);
+void VM_findkeysforcommand (prvm_prog_t *prog);
+void VM_stringtokeynum (prvm_prog_t *prog);
+void VM_setkeybind (prvm_prog_t *prog);
+void VM_getbindmaps (prvm_prog_t *prog);
+void VM_setbindmaps (prvm_prog_t *prog);
+
+void VM_cin_open(prvm_prog_t *prog);
+void VM_cin_close(prvm_prog_t *prog);
+void VM_cin_setstate(prvm_prog_t *prog);
+void VM_cin_getstate(prvm_prog_t *prog);
+void VM_cin_restart(prvm_prog_t *prog);
+
+void VM_gecko_create(prvm_prog_t *prog);
+void VM_gecko_destroy(prvm_prog_t *prog);
+void VM_gecko_navigate(prvm_prog_t *prog);
+void VM_gecko_keyevent(prvm_prog_t *prog);
+void VM_gecko_movemouse(prvm_prog_t *prog);
+void VM_gecko_resize(prvm_prog_t *prog);
+void VM_gecko_get_texture_extent(prvm_prog_t *prog);
+
+void VM_drawline (prvm_prog_t *prog);
+
+void VM_bitshift (prvm_prog_t *prog);
+
+void VM_altstr_count(prvm_prog_t *prog);
+void VM_altstr_prepare(prvm_prog_t *prog);
+void VM_altstr_get(prvm_prog_t *prog);
+void VM_altstr_set(prvm_prog_t *prog);
+void VM_altstr_ins(prvm_prog_t *prog);
+
+void VM_buf_create(prvm_prog_t *prog);
+void VM_buf_del (prvm_prog_t *prog);
+void VM_buf_getsize (prvm_prog_t *prog);
+void VM_buf_copy (prvm_prog_t *prog);
+void VM_buf_sort (prvm_prog_t *prog);
+void VM_buf_implode (prvm_prog_t *prog);
+void VM_bufstr_get (prvm_prog_t *prog);
+void VM_bufstr_set (prvm_prog_t *prog);
+void VM_bufstr_add (prvm_prog_t *prog);
+void VM_bufstr_free (prvm_prog_t *prog);
+
+void VM_changeyaw (prvm_prog_t *prog);
+void VM_changepitch (prvm_prog_t *prog);
+
+void VM_uncolorstring (prvm_prog_t *prog);
+
+void VM_strstrofs (prvm_prog_t *prog);
+void VM_str2chr (prvm_prog_t *prog);
+void VM_chr2str (prvm_prog_t *prog);
+void VM_strconv (prvm_prog_t *prog);
+void VM_strpad (prvm_prog_t *prog);
+void VM_infoadd (prvm_prog_t *prog);
+void VM_infoget (prvm_prog_t *prog);
+void VM_strncmp (prvm_prog_t *prog);
+void VM_strncmp (prvm_prog_t *prog);
+void VM_strncasecmp (prvm_prog_t *prog);
+void VM_registercvar (prvm_prog_t *prog);
+void VM_wasfreed (prvm_prog_t *prog);
+
+void VM_strreplace (prvm_prog_t *prog);
+void VM_strireplace (prvm_prog_t *prog);
+
+void VM_crc16(prvm_prog_t *prog);
+void VM_digest_hex(prvm_prog_t *prog);
+
+void VM_SetTraceGlobals(prvm_prog_t *prog, const trace_t *trace);
+void VM_ClearTraceGlobals(prvm_prog_t *prog);
+
+void VM_uri_escape (prvm_prog_t *prog);
+void VM_uri_unescape (prvm_prog_t *prog);
+void VM_whichpack (prvm_prog_t *prog);
+
+void VM_etof (prvm_prog_t *prog);
+void VM_uri_get (prvm_prog_t *prog);
+void VM_netaddress_resolve (prvm_prog_t *prog);
+
+void VM_tokenize_console (prvm_prog_t *prog);
+void VM_argv_start_index (prvm_prog_t *prog);
+void VM_argv_end_index (prvm_prog_t *prog);
+
+void VM_buf_cvarlist(prvm_prog_t *prog);
+void VM_cvar_description(prvm_prog_t *prog);
+
+void VM_CL_getextresponse (prvm_prog_t *prog);
+void VM_SV_getextresponse (prvm_prog_t *prog);
// Common functions between menu.dat and clsprogs
-void VM_CL_isdemo (void);
-void VM_CL_videoplaying (void);
+void VM_CL_isdemo (prvm_prog_t *prog);
+void VM_CL_videoplaying (prvm_prog_t *prog);
-void VM_isfunction(void);
-void VM_callfunction(void);
+void VM_isfunction(prvm_prog_t *prog);
+void VM_callfunction(prvm_prog_t *prog);
-void VM_sprintf(void);
+void VM_sprintf(prvm_prog_t *prog);
-void VM_getsurfacenumpoints(void);
-void VM_getsurfacepoint(void);
-void VM_getsurfacepointattribute(void);
-void VM_getsurfacenormal(void);
-void VM_getsurfacetexture(void);
-void VM_getsurfacenearpoint(void);
-void VM_getsurfaceclippedpoint(void);
-void VM_getsurfacenumtriangles(void);
-void VM_getsurfacetriangle(void);
+void VM_getsurfacenumpoints(prvm_prog_t *prog);
+void VM_getsurfacepoint(prvm_prog_t *prog);
+void VM_getsurfacepointattribute(prvm_prog_t *prog);
+void VM_getsurfacenormal(prvm_prog_t *prog);
+void VM_getsurfacetexture(prvm_prog_t *prog);
+void VM_getsurfacenearpoint(prvm_prog_t *prog);
+void VM_getsurfaceclippedpoint(prvm_prog_t *prog);
+void VM_getsurfacenumtriangles(prvm_prog_t *prog);
+void VM_getsurfacetriangle(prvm_prog_t *prog);
// physics builtins
-void VM_physics_enable(void);
-void VM_physics_addforce(void);
-void VM_physics_addtorque(void);
+void VM_physics_enable(prvm_prog_t *prog);
+void VM_physics_addforce(prvm_prog_t *prog);
+void VM_physics_addtorque(prvm_prog_t *prog);
+
+#endif
#include "progsvm.h"
#include "csprogs.h"
-prvm_prog_t *prog;
-
-static prvm_prog_t prog_list[PRVM_MAXPROGS];
+prvm_prog_t prvm_prog_list[PRVM_PROG_MAX];
int prvm_type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
prvm_eval_t prvm_badvalue; // used only for error returns
-ddef_t *PRVM_ED_FieldAtOfs(int ofs);
-qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash);
-
cvar_t prvm_language = {CVAR_SAVE, "prvm_language", "", "when set, loads progs.dat.LANGUAGENAME.po for string translations; when set to dump, progs.dat.pot is written from the strings in the progs"};
// LordHavoc: prints every opcode as it executes - warning: this is significant spew
cvar_t prvm_traceqc = {0, "prvm_traceqc", "0", "prints every QuakeC statement as it is executed (only for really thorough debugging!)"};
static double prvm_reuseedicts_always_allow = 0;
qboolean prvm_runawaycheck = true;
-extern sizebuf_t vm_tempstringsbuf;
-
//============================================================================
// mempool handling
PRVM_MEM_Alloc
===============
*/
-void PRVM_MEM_Alloc(void)
+static void PRVM_MEM_Alloc(prvm_prog_t *prog)
{
int i;
PRVM_MEM_IncreaseEdicts
===============
*/
-void PRVM_MEM_IncreaseEdicts(void)
+void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog)
{
int i;
if(prog->max_edicts >= prog->limit_edicts)
return;
- PRVM_GCALL(begin_increase_edicts)();
+ prog->begin_increase_edicts(prog);
// increase edicts
prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
prog->edicts[i].fields.vp = prog->edictsfields + i * prog->entityfields;
}
- PRVM_GCALL(end_increase_edicts)();
+ prog->end_increase_edicts(prog);
}
//============================================================================
// normal prvm
-int PRVM_ED_FindFieldOffset(const char *field)
+int PRVM_ED_FindFieldOffset(prvm_prog_t *prog, const char *field)
{
ddef_t *d;
- d = PRVM_ED_FindField(field);
+ d = PRVM_ED_FindField(prog, field);
if (!d)
return -1;
return d->ofs;
}
-int PRVM_ED_FindGlobalOffset(const char *global)
+int PRVM_ED_FindGlobalOffset(prvm_prog_t *prog, const char *global)
{
ddef_t *d;
- d = PRVM_ED_FindGlobal(global);
+ d = PRVM_ED_FindGlobal(prog, global);
if (!d)
return -1;
return d->ofs;
}
-func_t PRVM_ED_FindFunctionOffset(const char *function)
+func_t PRVM_ED_FindFunctionOffset(prvm_prog_t *prog, const char *function)
{
mfunction_t *f;
- f = PRVM_ED_FindFunction(function);
+ f = PRVM_ED_FindFunction(prog, function);
if (!f)
return 0;
return (func_t)(f - prog->functions);
}
-qboolean PRVM_ProgLoaded(int prognr)
-{
- if(prognr < 0 || prognr >= PRVM_MAXPROGS)
- return FALSE;
-
- return (prog_list[prognr].loaded ? TRUE : FALSE);
-}
-
/*
=================
-PRVM_SetProgFromString
+PRVM_ProgFromString
=================
*/
-// perhaps add a return value when the str doesnt exist
-qboolean PRVM_SetProgFromString(const char *str)
-{
- int i = 0;
- for(; i < PRVM_MAXPROGS ; i++)
- if(prog_list[i].name && !strcmp(prog_list[i].name,str))
- {
- if(prog_list[i].loaded)
- {
- prog = &prog_list[i];
- return TRUE;
- }
- else
- {
- Con_Printf("%s not loaded !\n",PRVM_NAME);
- return FALSE;
- }
- }
-
- Con_Printf("Invalid program name %s !\n", str);
- return FALSE;
+prvm_prog_t *PRVM_ProgFromString(const char *str)
+{
+ if (!strcmp(str, "server"))
+ return SVVM_prog;
+ if (!strcmp(str, "client"))
+ return CLVM_prog;
+ if (!strcmp(str, "menu"))
+ return MVM_prog;
+ return NULL;
}
/*
=================
-PRVM_SetProg
+PRVM_FriendlyProgFromString
=================
*/
-void PRVM_SetProg(int prognr)
+prvm_prog_t *PRVM_FriendlyProgFromString(const char *str)
{
- if(0 <= prognr && prognr < PRVM_MAXPROGS)
+ prvm_prog_t *prog = PRVM_ProgFromString(str);
+ if (!prog)
{
- if(prog_list[prognr].loaded)
- prog = &prog_list[prognr];
- else
- PRVM_ERROR("%i not loaded !", prognr);
- return;
+ Con_Printf("%s: unknown program name\n", str);
+ return NULL;
+ }
+ if (!prog->loaded)
+ {
+ Con_Printf("%s: program is not loaded\n", str);
+ return NULL;
}
- PRVM_ERROR("Invalid program number %i", prognr);
+ return prog;
}
/*
Sets everything to NULL
=================
*/
-void PRVM_ED_ClearEdict (prvm_edict_t *e)
+void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e)
{
- memset (e->fields.vp, 0, prog->entityfields * 4);
+ memset(e->fields.vp, 0, prog->entityfields * 4);
e->priv.required->free = false;
// AK: Let the init_edict function determine if something needs to be initialized
- PRVM_GCALL(init_edict)(e);
+ prog->init_edict(prog, e);
}
-const char *PRVM_AllocationOrigin(void)
+const char *PRVM_AllocationOrigin(prvm_prog_t *prog)
{
char *buf = NULL;
if(prog->leaktest_active)
if(prog->depth > 0) // actually in QC code and not just parsing the entities block of a map/savegame
{
buf = (char *)PRVM_Alloc(128);
- PRVM_ShortStackTrace(buf, 128);
+ PRVM_ShortStackTrace(prog, buf, 128);
}
return buf;
}
Returns if this particular edict could get allocated by PRVM_ED_Alloc
=================
*/
-qboolean PRVM_ED_CanAlloc(prvm_edict_t *e)
+qboolean PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e)
{
if(!e->priv.required->free)
return false;
if(prvm_reuseedicts_always_allow == realtime)
return true;
- if(realtime <= e->priv.required->freetime && prvm_reuseedicts_neverinsameframe.integer)
+ if(realtime <= e->priv.required->freetime + 0.1 && prvm_reuseedicts_neverinsameframe.integer)
return false; // never allow reuse in same frame (causes networking trouble)
if(e->priv.required->freetime < prog->starttime + prvm_reuseedicts_startuptime.value)
return true;
angles and bad trails.
=================
*/
-prvm_edict_t *PRVM_ED_Alloc (void)
+prvm_edict_t *PRVM_ED_Alloc(prvm_prog_t *prog)
{
- int i;
- prvm_edict_t *e;
+ int i;
+ prvm_edict_t *e;
// the client qc dont need maxclients
// thus it doesnt need to use svs.maxclients
for (i = prog->reserved_edicts + 1;i < prog->num_edicts;i++)
{
e = PRVM_EDICT_NUM(i);
- if(PRVM_ED_CanAlloc(e))
+ if(PRVM_ED_CanAlloc(prog, e))
{
- PRVM_ED_ClearEdict (e);
- e->priv.required->allocation_origin = PRVM_AllocationOrigin();
+ PRVM_ED_ClearEdict (prog, e);
+ e->priv.required->allocation_origin = PRVM_AllocationOrigin(prog);
return e;
}
}
if (i == prog->limit_edicts)
- PRVM_ERROR ("%s: PRVM_ED_Alloc: no free edicts",PRVM_NAME);
+ prog->error_cmd("%s: PRVM_ED_Alloc: no free edicts", prog->name);
prog->num_edicts++;
if (prog->num_edicts >= prog->max_edicts)
- PRVM_MEM_IncreaseEdicts();
+ PRVM_MEM_IncreaseEdicts(prog);
e = PRVM_EDICT_NUM(i);
- PRVM_ED_ClearEdict (e);
+ PRVM_ED_ClearEdict(prog, e);
- e->priv.required->allocation_origin = PRVM_AllocationOrigin();
+ e->priv.required->allocation_origin = PRVM_AllocationOrigin(prog);
return e;
}
FIXME: walk all entities and NULL out references to this entity
=================
*/
-void PRVM_ED_Free (prvm_edict_t *ed)
+void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed)
{
// dont delete the null entity (world) or reserved edicts
- if(PRVM_NUM_FOR_EDICT(ed) <= prog->reserved_edicts )
+ if (ed - prog->edicts <= prog->reserved_edicts)
return;
- PRVM_GCALL(free_edict)(ed);
+ prog->free_edict(prog, ed);
ed->priv.required->free = true;
ed->priv.required->freetime = realtime;
if(ed->priv.required->allocation_origin)
{
- PRVM_Free((char *)ed->priv.required->allocation_origin);
+ Mem_Free((char *)ed->priv.required->allocation_origin);
ed->priv.required->allocation_origin = NULL;
}
}
PRVM_ED_GlobalAtOfs
============
*/
-ddef_t *PRVM_ED_GlobalAtOfs (int ofs)
+static ddef_t *PRVM_ED_GlobalAtOfs (prvm_prog_t *prog, int ofs)
{
ddef_t *def;
int i;
PRVM_ED_FieldAtOfs
============
*/
-ddef_t *PRVM_ED_FieldAtOfs (int ofs)
+ddef_t *PRVM_ED_FieldAtOfs (prvm_prog_t *prog, int ofs)
{
ddef_t *def;
int i;
PRVM_ED_FindField
============
*/
-ddef_t *PRVM_ED_FindField (const char *name)
+ddef_t *PRVM_ED_FindField (prvm_prog_t *prog, const char *name)
{
ddef_t *def;
int i;
for (i = 0;i < prog->numfielddefs;i++)
{
def = &prog->fielddefs[i];
- if (!strcmp(PRVM_GetString(def->s_name), name))
+ if (!strcmp(PRVM_GetString(prog, def->s_name), name))
return def;
}
return NULL;
PRVM_ED_FindGlobal
============
*/
-ddef_t *PRVM_ED_FindGlobal (const char *name)
+ddef_t *PRVM_ED_FindGlobal (prvm_prog_t *prog, const char *name)
{
ddef_t *def;
int i;
for (i = 0;i < prog->numglobaldefs;i++)
{
def = &prog->globaldefs[i];
- if (!strcmp(PRVM_GetString(def->s_name), name))
+ if (!strcmp(PRVM_GetString(prog, def->s_name), name))
return def;
}
return NULL;
PRVM_ED_FindFunction
============
*/
-mfunction_t *PRVM_ED_FindFunction (const char *name)
+mfunction_t *PRVM_ED_FindFunction (prvm_prog_t *prog, const char *name)
{
mfunction_t *func;
int i;
for (i = 0;i < prog->numfunctions;i++)
{
func = &prog->functions[i];
- if (!strcmp(PRVM_GetString(func->s_name), name))
+ if (!strcmp(PRVM_GetString(prog, func->s_name), name))
return func;
}
return NULL;
Returns a string describing *data in a type specific manner
=============
*/
-char *PRVM_ValueString (etype_t type, prvm_eval_t *val)
+static char *PRVM_ValueString (prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
{
- static char line[MAX_INPUTLINE];
ddef_t *def;
mfunction_t *f;
int n;
switch (type)
{
case ev_string:
- strlcpy (line, PRVM_GetString (val->string), sizeof (line));
+ strlcpy (line, PRVM_GetString (prog, val->string), linelength);
break;
case ev_entity:
n = val->edict;
if (n < 0 || n >= prog->max_edicts)
- dpsnprintf (line, sizeof(line), "entity %i (invalid!)", n);
+ dpsnprintf (line, linelength, "entity %i (invalid!)", n);
else
- dpsnprintf (line, sizeof(line), "entity %i", n);
+ dpsnprintf (line, linelength, "entity %i", n);
break;
case ev_function:
f = prog->functions + val->function;
- dpsnprintf (line, sizeof(line), "%s()", PRVM_GetString(f->s_name));
+ dpsnprintf (line, linelength, "%s()", PRVM_GetString(prog, f->s_name));
break;
case ev_field:
- def = PRVM_ED_FieldAtOfs ( val->_int );
- dpsnprintf (line, sizeof(line), ".%s", PRVM_GetString(def->s_name));
+ def = PRVM_ED_FieldAtOfs ( prog, val->_int );
+ dpsnprintf (line, linelength, ".%s", PRVM_GetString(prog, def->s_name));
break;
case ev_void:
- dpsnprintf (line, sizeof(line), "void");
+ dpsnprintf (line, linelength, "void");
break;
case ev_float:
// LordHavoc: changed from %5.1f to %10.4f
- dpsnprintf (line, sizeof(line), "%10.4f", val->_float);
+ dpsnprintf (line, linelength, "%10.4f", val->_float);
break;
case ev_vector:
// LordHavoc: changed from %5.1f to %10.4f
- dpsnprintf (line, sizeof(line), "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
+ dpsnprintf (line, linelength, "'%10.4f %10.4f %10.4f'", val->vector[0], val->vector[1], val->vector[2]);
break;
case ev_pointer:
- dpsnprintf (line, sizeof(line), "pointer");
+ dpsnprintf (line, linelength, "pointer");
break;
default:
- dpsnprintf (line, sizeof(line), "bad type %i", (int) type);
+ dpsnprintf (line, linelength, "bad type %i", (int) type);
break;
}
Easier to parse than PR_ValueString
=============
*/
-char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val)
+char *PRVM_UglyValueString (prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
{
- static char line[MAX_INPUTLINE];
int i;
const char *s;
ddef_t *def;
// Parse the string a bit to turn special characters
// (like newline, specifically) into escape codes,
// this fixes saving games from various mods
- s = PRVM_GetString (val->string);
- for (i = 0;i < (int)sizeof(line) - 2 && *s;)
+ s = PRVM_GetString (prog, val->string);
+ for (i = 0;i < (int)linelength - 2 && *s;)
{
if (*s == '\n')
{
line[i] = '\0';
break;
case ev_entity:
- dpsnprintf (line, sizeof (line), "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
+ dpsnprintf (line, linelength, "%i", PRVM_NUM_FOR_EDICT(PRVM_PROG_TO_EDICT(val->edict)));
break;
case ev_function:
f = prog->functions + val->function;
- strlcpy (line, PRVM_GetString (f->s_name), sizeof (line));
+ strlcpy (line, PRVM_GetString (prog, f->s_name), linelength);
break;
case ev_field:
- def = PRVM_ED_FieldAtOfs ( val->_int );
- dpsnprintf (line, sizeof (line), ".%s", PRVM_GetString(def->s_name));
+ def = PRVM_ED_FieldAtOfs ( prog, val->_int );
+ dpsnprintf (line, linelength, ".%s", PRVM_GetString(prog, def->s_name));
break;
case ev_void:
- dpsnprintf (line, sizeof (line), "void");
+ dpsnprintf (line, linelength, "void");
break;
case ev_float:
- dpsnprintf (line, sizeof (line), "%.9g", val->_float);
+ dpsnprintf (line, linelength, "%.9g", val->_float);
break;
case ev_vector:
- dpsnprintf (line, sizeof (line), "%.9g %.9g %.9g", val->vector[0], val->vector[1], val->vector[2]);
+ dpsnprintf (line, linelength, "%.9g %.9g %.9g", val->vector[0], val->vector[1], val->vector[2]);
break;
default:
- dpsnprintf (line, sizeof (line), "bad type %i", type);
+ dpsnprintf (line, linelength, "bad type %i", type);
break;
}
padded to 20 field width
============
*/
-char *PRVM_GlobalString (int ofs)
+char *PRVM_GlobalString (prvm_prog_t *prog, int ofs, char *line, size_t linelength)
{
char *s;
//size_t i;
ddef_t *def;
void *val;
- static char line[128];
+ char valuebuf[MAX_INPUTLINE];
val = (void *)&prog->globals.generic[ofs];
- def = PRVM_ED_GlobalAtOfs(ofs);
+ def = PRVM_ED_GlobalAtOfs(prog, ofs);
if (!def)
- dpsnprintf (line, sizeof(line), "GLOBAL%i", ofs);
+ dpsnprintf (line, linelength, "GLOBAL%i", ofs);
else
{
- s = PRVM_ValueString ((etype_t)def->type, (prvm_eval_t *)val);
- dpsnprintf (line, sizeof(line), "%s (=%s)", PRVM_GetString(def->s_name), s);
+ s = PRVM_ValueString (prog, (etype_t)def->type, (prvm_eval_t *)val, valuebuf, sizeof(valuebuf));
+ dpsnprintf (line, linelength, "%s (=%s)", PRVM_GetString(prog, def->s_name), s);
}
//i = strlen(line);
return line;
}
-char *PRVM_GlobalStringNoContents (int ofs)
+char *PRVM_GlobalStringNoContents (prvm_prog_t *prog, int ofs, char *line, size_t linelength)
{
//size_t i;
ddef_t *def;
- static char line[128];
- def = PRVM_ED_GlobalAtOfs(ofs);
+ def = PRVM_ED_GlobalAtOfs(prog, ofs);
if (!def)
- dpsnprintf (line, sizeof(line), "GLOBAL%i", ofs);
+ dpsnprintf (line, linelength, "GLOBAL%i", ofs);
else
- dpsnprintf (line, sizeof(line), "%s", PRVM_GetString(def->s_name));
+ dpsnprintf (line, linelength, "%s", PRVM_GetString(prog, def->s_name));
//i = strlen(line);
//for ( ; i<20 ; i++)
*/
// LordHavoc: optimized this to print out much more quickly (tempstring)
// LordHavoc: changed to print out every 4096 characters (incase there are a lot of fields to print)
-void PRVM_ED_Print(prvm_edict_t *ed, const char *wildcard_fieldname)
+void PRVM_ED_Print(prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname)
{
size_t l;
ddef_t *d;
const char *name;
int type;
char tempstring[MAX_INPUTLINE], tempstring2[260]; // temporary string buffers
+ char valuebuf[MAX_INPUTLINE];
if (ed->priv.required->free)
{
- Con_Printf("%s: FREE\n",PRVM_NAME);
+ Con_Printf("%s: FREE\n",prog->name);
return;
}
tempstring[0] = 0;
- dpsnprintf(tempstring, sizeof(tempstring), "\n%s EDICT %i:\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ed));
+ dpsnprintf(tempstring, sizeof(tempstring), "\n%s EDICT %i:\n", prog->name, PRVM_NUM_FOR_EDICT(ed));
for (i = 1;i < prog->numfielddefs;i++)
{
d = &prog->fielddefs[i];
- name = PRVM_GetString(d->s_name);
+ name = PRVM_GetString(prog, d->s_name);
if(strlen(name) > 1 && name[strlen(name)-2] == '_' && (name[strlen(name)-1] == 'x' || name[strlen(name)-1] == 'y' || name[strlen(name)-1] == 'z'))
continue; // skip _x, _y, _z vars
strlcat(tempstring, " ", sizeof(tempstring));
strlcat(tempstring, " ", sizeof(tempstring));
- name = PRVM_ValueString((etype_t)d->type, (prvm_eval_t *)v);
+ name = PRVM_ValueString(prog, (etype_t)d->type, (prvm_eval_t *)v, valuebuf, sizeof(valuebuf));
if (strlen(name) > sizeof(tempstring2)-4)
{
memcpy (tempstring2, name, sizeof(tempstring2)-4);
=============
*/
extern cvar_t developer_entityparsing;
-void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed)
+void PRVM_ED_Write (prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed)
{
ddef_t *d;
int *v;
int i, j;
const char *name;
int type;
+ char vabuf[1024];
+ char valuebuf[MAX_INPUTLINE];
FS_Print(f, "{\n");
for (i = 1;i < prog->numfielddefs;i++)
{
d = &prog->fielddefs[i];
- name = PRVM_GetString(d->s_name);
+ name = PRVM_GetString(prog, d->s_name);
if(developer_entityparsing.integer)
Con_Printf("PRVM_ED_Write: at entity %d field %s\n", PRVM_NUM_FOR_EDICT(ed), name);
continue;
FS_Printf(f,"\"%s\" ",name);
- prog->statestring = va("PRVM_ED_Write, ent=%d, name=%s", i, name);
- FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString((etype_t)d->type, (prvm_eval_t *)v));
+ prog->statestring = va(vabuf, sizeof(vabuf), "PRVM_ED_Write, ent=%d, name=%s", i, name);
+ FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)d->type, (prvm_eval_t *)v, valuebuf, sizeof(valuebuf)));
prog->statestring = NULL;
}
FS_Print(f, "}\n");
}
-void PRVM_ED_PrintNum (int ent, const char *wildcard_fieldname)
+void PRVM_ED_PrintNum (prvm_prog_t *prog, int ent, const char *wildcard_fieldname)
{
- PRVM_ED_Print(PRVM_EDICT_NUM(ent), wildcard_fieldname);
+ PRVM_ED_Print(prog, PRVM_EDICT_NUM(ent), wildcard_fieldname);
}
/*
*/
void PRVM_ED_PrintEdicts_f (void)
{
+ prvm_prog_t *prog;
int i;
const char *wildcard_fieldname;
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
if( Cmd_Argc() == 3)
else
wildcard_fieldname = NULL;
- Con_Printf("%s: %i entities\n", PRVM_NAME, prog->num_edicts);
+ Con_Printf("%s: %i entities\n", prog->name, prog->num_edicts);
for (i=0 ; i<prog->num_edicts ; i++)
- PRVM_ED_PrintNum (i, wildcard_fieldname);
-
- PRVM_End;
+ PRVM_ED_PrintNum (prog, i, wildcard_fieldname);
}
/*
For debugging, prints a single edict
=============
*/
-void PRVM_ED_PrintEdict_f (void)
+static void PRVM_ED_PrintEdict_f (void)
{
+ prvm_prog_t *prog;
int i;
const char *wildcard_fieldname;
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
i = atoi (Cmd_Argv(2));
if (i >= prog->num_edicts)
{
Con_Print("Bad edict number\n");
- PRVM_End;
return;
}
if( Cmd_Argc() == 4)
else
// Use All
wildcard_fieldname = NULL;
- PRVM_ED_PrintNum (i, wildcard_fieldname);
-
- PRVM_End;
+ PRVM_ED_PrintNum (prog, i, wildcard_fieldname);
}
/*
*/
// 2 possibilities : 1. just displaying the active edict count
// 2. making a function pointer [x]
-void PRVM_ED_Count_f (void)
+static void PRVM_ED_Count_f (void)
{
- int i;
- prvm_edict_t *ent;
- int active;
+ prvm_prog_t *prog;
if(Cmd_Argc() != 2)
{
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- if(prog->count_edicts)
- prog->count_edicts();
- else
- {
- active = 0;
- for (i=0 ; i<prog->num_edicts ; i++)
- {
- ent = PRVM_EDICT_NUM(i);
- if (ent->priv.required->free)
- continue;
- active++;
- }
-
- Con_Printf("num_edicts:%3i\n", prog->num_edicts);
- Con_Printf("active :%3i\n", active);
- }
-
- PRVM_End;
+ prog->count_edicts(prog);
}
/*
PRVM_ED_WriteGlobals
=============
*/
-void PRVM_ED_WriteGlobals (qfile_t *f)
+void PRVM_ED_WriteGlobals (prvm_prog_t *prog, qfile_t *f)
{
ddef_t *def;
int i;
const char *name;
int type;
+ char vabuf[1024];
+ char valuebuf[MAX_INPUTLINE];
FS_Print(f,"{\n");
for (i = 0;i < prog->numglobaldefs;i++)
if (type != ev_string && type != ev_float && type != ev_entity)
continue;
- name = PRVM_GetString(def->s_name);
+ name = PRVM_GetString(prog, def->s_name);
if(developer_entityparsing.integer)
Con_Printf("PRVM_ED_WriteGlobals: at global %s\n", name);
- prog->statestring = va("PRVM_ED_WriteGlobals, name=%s", name);
+ prog->statestring = va(vabuf, sizeof(vabuf), "PRVM_ED_WriteGlobals, name=%s", name);
FS_Printf(f,"\"%s\" ", name);
- FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString((etype_t)type, (prvm_eval_t *)&prog->globals.generic[def->ofs]));
+ FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)type, (prvm_eval_t *)&prog->globals.generic[def->ofs], valuebuf, sizeof(valuebuf)));
prog->statestring = NULL;
}
FS_Print(f,"}\n");
PRVM_ED_ParseGlobals
=============
*/
-void PRVM_ED_ParseGlobals (const char *data)
+void PRVM_ED_ParseGlobals (prvm_prog_t *prog, const char *data)
{
char keyname[MAX_INPUTLINE];
ddef_t *key;
while (1)
{
// parse key
- if (!COM_ParseToken_Simple(&data, false, false))
- PRVM_ERROR ("PRVM_ED_ParseGlobals: EOF without closing brace");
+ if (!COM_ParseToken_Simple(&data, false, false, true))
+ prog->error_cmd("PRVM_ED_ParseGlobals: EOF without closing brace");
if (com_token[0] == '}')
break;
strlcpy (keyname, com_token, sizeof(keyname));
// parse value
- if (!COM_ParseToken_Simple(&data, false, true))
- PRVM_ERROR ("PRVM_ED_ParseGlobals: EOF without closing brace");
+ if (!COM_ParseToken_Simple(&data, false, true, true))
+ prog->error_cmd("PRVM_ED_ParseGlobals: EOF without closing brace");
if (developer_entityparsing.integer)
Con_Printf(" \"%s\"\n", com_token);
if (com_token[0] == '}')
- PRVM_ERROR ("PRVM_ED_ParseGlobals: closing brace without data");
+ prog->error_cmd("PRVM_ED_ParseGlobals: closing brace without data");
- key = PRVM_ED_FindGlobal (keyname);
+ key = PRVM_ED_FindGlobal (prog, keyname);
if (!key)
{
- Con_DPrintf("'%s' is not a global on %s\n", keyname, PRVM_NAME);
+ Con_DPrintf("'%s' is not a global on %s\n", keyname, prog->name);
continue;
}
- if (!PRVM_ED_ParseEpair(NULL, key, com_token, true))
- PRVM_ERROR ("PRVM_ED_ParseGlobals: parse error");
+ if (!PRVM_ED_ParseEpair(prog, NULL, key, com_token, true))
+ prog->error_cmd("PRVM_ED_ParseGlobals: parse error");
}
}
returns false if error
=============
*/
-qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash)
+qboolean PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, ddef_t *key, const char *s, qboolean parsebackslash)
{
int i, l;
char *new_p;
{
case ev_string:
l = (int)strlen(s) + 1;
- val->string = PRVM_AllocString(l, &new_p);
+ val->string = PRVM_AllocString(prog, l, &new_p);
for (i = 0;i < l;i++)
{
if (s[i] == '\\' && s[i+1] && parsebackslash)
s++;
i = atoi(s);
if (i >= prog->limit_edicts)
- Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %u >= MAX_EDICTS %u) on %s\n", (unsigned int)i, prog->limit_edicts, PRVM_NAME);
+ Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %u >= MAX_EDICTS %u) on %s\n", (unsigned int)i, prog->limit_edicts, prog->name);
while (i >= prog->max_edicts)
- PRVM_MEM_IncreaseEdicts();
+ PRVM_MEM_IncreaseEdicts(prog);
// if IncreaseEdicts was called the base pointer needs to be updated
if (ent)
val = (prvm_eval_t *)(ent->fields.vp + key->ofs);
case ev_field:
if (*s != '.')
{
- Con_DPrintf("PRVM_ED_ParseEpair: Bogus field name %s in %s\n", s, PRVM_NAME);
+ Con_DPrintf("PRVM_ED_ParseEpair: Bogus field name %s in %s\n", s, prog->name);
return false;
}
- def = PRVM_ED_FindField(s + 1);
+ def = PRVM_ED_FindField(prog, s + 1);
if (!def)
{
- Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, PRVM_NAME);
+ Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, prog->name);
return false;
}
val->_int = def->ofs;
break;
case ev_function:
- func = PRVM_ED_FindFunction(s);
+ func = PRVM_ED_FindFunction(prog, s);
if (!func)
{
- Con_Printf("PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, PRVM_NAME);
+ Con_Printf("PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, prog->name);
return false;
}
val->function = func - prog->functions;
break;
default:
- Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PRVM_GetString(key->s_name), PRVM_NAME);
+ Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PRVM_GetString(prog, key->s_name), prog->name);
return false;
}
return true;
QC, mg in menu QC.
=============
*/
-void PRVM_GameCommand(const char *whichprogs, const char *whichcmd)
+static void PRVM_GameCommand(const char *whichprogs, const char *whichcmd)
{
+ prvm_prog_t *prog;
if(Cmd_Argc() < 1)
{
Con_Printf("%s text...\n", whichcmd);
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(whichprogs))
- // note: this is not PRVM_SetProg because that one aborts "hard" using PRVM_Error
- // also, it makes printing error messages easier!
- {
- Con_Printf("%s program not loaded.\n", whichprogs);
+ if (!(prog = PRVM_FriendlyProgFromString(whichprogs)))
return;
- }
if(!PRVM_allfunction(GameCommand))
{
s = Cmd_Args();
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
- PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(s ? s : "");
- PRVM_ExecuteProgram (PRVM_allfunction(GameCommand), "QC function GameCommand is missing");
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s ? s : "");
+ prog->ExecuteProgram(prog, PRVM_allfunction(GameCommand), "QC function GameCommand is missing");
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
}
-
- PRVM_End;
}
-void PRVM_GameCommand_Server_f(void)
+static void PRVM_GameCommand_Server_f(void)
{
PRVM_GameCommand("server", "sv_cmd");
}
-void PRVM_GameCommand_Client_f(void)
+static void PRVM_GameCommand_Client_f(void)
{
PRVM_GameCommand("client", "cl_cmd");
}
-void PRVM_GameCommand_Menu_f(void)
+static void PRVM_GameCommand_Menu_f(void)
{
PRVM_GameCommand("menu", "menu_cmd");
}
Console command to load a field of a specified edict
=============
*/
-void PRVM_ED_EdictGet_f(void)
+static void PRVM_ED_EdictGet_f(void)
{
+ prvm_prog_t *prog;
prvm_edict_t *ed;
ddef_t *key;
const char *s;
prvm_eval_t *v;
+ char valuebuf[MAX_INPUTLINE];
if(Cmd_Argc() != 4 && Cmd_Argc() != 5)
{
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
- {
- Con_Printf("Wrong program name %s !\n", Cmd_Argv(1));
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- }
ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(2)));
- if((key = PRVM_ED_FindField(Cmd_Argv(3))) == 0)
+ if((key = PRVM_ED_FindField(prog, Cmd_Argv(3))) == 0)
{
Con_Printf("Key %s not found !\n", Cmd_Argv(3));
goto fail;
}
v = (prvm_eval_t *)(ed->fields.vp + key->ofs);
- s = PRVM_UglyValueString((etype_t)key->type, v);
+ s = PRVM_UglyValueString(prog, (etype_t)key->type, v, valuebuf, sizeof(valuebuf));
if(Cmd_Argc() == 5)
{
cvar_t *cvar = Cvar_FindVar(Cmd_Argv(4));
Con_Printf("%s\n", s);
fail:
- PRVM_End;
+ ;
}
-void PRVM_ED_GlobalGet_f(void)
+static void PRVM_ED_GlobalGet_f(void)
{
+ prvm_prog_t *prog;
ddef_t *key;
const char *s;
prvm_eval_t *v;
+ char valuebuf[MAX_INPUTLINE];
if(Cmd_Argc() != 3 && Cmd_Argc() != 4)
{
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
- {
- Con_Printf("Wrong program name %s !\n", Cmd_Argv(1));
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- }
- key = PRVM_ED_FindGlobal(Cmd_Argv(2));
+ key = PRVM_ED_FindGlobal(prog, Cmd_Argv(2));
if(!key)
{
Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
}
v = (prvm_eval_t *) &prog->globals.generic[key->ofs];
- s = PRVM_UglyValueString((etype_t)key->type, v);
+ s = PRVM_UglyValueString(prog, (etype_t)key->type, v, valuebuf, sizeof(valuebuf));
if(Cmd_Argc() == 4)
{
cvar_t *cvar = Cvar_FindVar(Cmd_Argv(3));
Con_Printf("%s\n", s);
fail:
- PRVM_End;
+ ;
}
/*
Console command to set a field of a specified edict
=============
*/
-void PRVM_ED_EdictSet_f(void)
+static void PRVM_ED_EdictSet_f(void)
{
+ prvm_prog_t *prog;
prvm_edict_t *ed;
ddef_t *key;
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
- {
- Con_Printf("Wrong program name %s !\n", Cmd_Argv(1));
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- }
ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(2)));
- if((key = PRVM_ED_FindField(Cmd_Argv(3))) == 0)
+ if((key = PRVM_ED_FindField(prog, Cmd_Argv(3))) == 0)
Con_Printf("Key %s not found !\n", Cmd_Argv(3));
else
- PRVM_ED_ParseEpair(ed, key, Cmd_Argv(4), true);
-
- PRVM_End;
+ PRVM_ED_ParseEpair(prog, ed, key, Cmd_Argv(4), true);
}
/*
Used for initial level load and for savegames.
====================
*/
-const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent)
+const char *PRVM_ED_ParseEdict (prvm_prog_t *prog, const char *data, prvm_edict_t *ent)
{
ddef_t *key;
qboolean anglehack;
while (1)
{
// parse key
- if (!COM_ParseToken_Simple(&data, false, false))
- PRVM_ERROR ("PRVM_ED_ParseEdict: EOF without closing brace");
+ if (!COM_ParseToken_Simple(&data, false, false, true))
+ prog->error_cmd("PRVM_ED_ParseEdict: EOF without closing brace");
if (developer_entityparsing.integer)
Con_Printf("Key: \"%s\"", com_token);
if (com_token[0] == '}')
}
// parse value
- if (!COM_ParseToken_Simple(&data, false, false))
- PRVM_ERROR ("PRVM_ED_ParseEdict: EOF without closing brace");
+ if (!COM_ParseToken_Simple(&data, false, false, true))
+ prog->error_cmd("PRVM_ED_ParseEdict: EOF without closing brace");
if (developer_entityparsing.integer)
Con_Printf(" \"%s\"\n", com_token);
if (com_token[0] == '}')
- PRVM_ERROR ("PRVM_ED_ParseEdict: closing brace without data");
+ prog->error_cmd("PRVM_ED_ParseEdict: closing brace without data");
init = true;
if (keyname[0] == '_')
continue;
- key = PRVM_ED_FindField (keyname);
+ key = PRVM_ED_FindField (prog, keyname);
if (!key)
{
- Con_DPrintf("%s: '%s' is not a field\n", PRVM_NAME, keyname);
+ Con_DPrintf("%s: '%s' is not a field\n", prog->name, keyname);
continue;
}
dpsnprintf (com_token, sizeof(com_token), "0 %s 0", temp);
}
- if (!PRVM_ED_ParseEpair(ent, key, com_token, strcmp(keyname, "wad") != 0))
- PRVM_ERROR ("PRVM_ED_ParseEdict: parse error");
+ if (!PRVM_ED_ParseEpair(prog, ent, key, com_token, strcmp(keyname, "wad") != 0))
+ prog->error_cmd("PRVM_ED_ParseEdict: parse error");
}
if (!init)
to call PRVM_ED_CallSpawnFunctions () to let the objects initialize themselves.
================
*/
-void PRVM_ED_LoadFromFile (const char *data)
+void PRVM_ED_LoadFromFile (prvm_prog_t *prog, const char *data)
{
prvm_edict_t *ent;
int parsed, inhibited, spawned, died;
const char *funcname;
mfunction_t *func;
+ char vabuf[1024];
parsed = 0;
inhibited = 0;
while (1)
{
// parse the opening brace
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break;
if (com_token[0] != '{')
- PRVM_ERROR ("PRVM_ED_LoadFromFile: %s: found %s when expecting {", PRVM_NAME, com_token);
+ prog->error_cmd("PRVM_ED_LoadFromFile: %s: found %s when expecting {", prog->name, com_token);
// CHANGED: this is not conform to PR_LoadFromFile
if(prog->loadintoworld)
ent = PRVM_EDICT_NUM(0);
}
else
- ent = PRVM_ED_Alloc();
+ ent = PRVM_ED_Alloc(prog);
// clear it
if (ent != prog->edicts) // hack
memset (ent->fields.vp, 0, prog->entityfields * 4);
- data = PRVM_ED_ParseEdict (data, ent);
+ data = PRVM_ED_ParseEdict (prog, data, ent);
parsed++;
// remove the entity ?
- if(prog->load_edict && !prog->load_edict(ent))
+ if(!prog->load_edict(prog, ent))
{
- PRVM_ED_Free(ent);
+ PRVM_ED_Free(prog, ent);
inhibited++;
continue;
}
if (PRVM_serverfunction(SV_OnEntityPreSpawnFunction))
{
// self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (PRVM_serverfunction(SV_OnEntityPreSpawnFunction), "QC function SV_OnEntityPreSpawnFunction is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPreSpawnFunction), "QC function SV_OnEntityPreSpawnFunction is missing");
}
if(ent->priv.required->free)
if (!PRVM_alledictstring(ent, classname))
{
Con_Print("No classname for:\n");
- PRVM_ED_Print(ent, NULL);
- PRVM_ED_Free (ent);
+ PRVM_ED_Print(prog, ent, NULL);
+ PRVM_ED_Free (prog, ent);
continue;
}
// look for the spawn function
- funcname = PRVM_GetString(PRVM_alledictstring(ent, classname));
- func = PRVM_ED_FindFunction (va("spawnfunc_%s", funcname));
+ funcname = PRVM_GetString(prog, PRVM_alledictstring(ent, classname));
+ func = PRVM_ED_FindFunction (prog, va(vabuf, sizeof(vabuf), "spawnfunc_%s", funcname));
if(!func)
if(!PRVM_allglobalfloat(require_spawnfunc_prefix))
- func = PRVM_ED_FindFunction (funcname);
+ func = PRVM_ED_FindFunction (prog, funcname);
if (!func)
{
if (PRVM_serverfunction(SV_OnEntityNoSpawnFunction))
{
// self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (PRVM_serverfunction(SV_OnEntityNoSpawnFunction), "QC function SV_OnEntityNoSpawnFunction is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityNoSpawnFunction), "QC function SV_OnEntityNoSpawnFunction is missing");
}
else
{
if (developer.integer > 0) // don't confuse non-developers with errors
{
Con_Print("No spawn function for:\n");
- PRVM_ED_Print(ent, NULL);
+ PRVM_ED_Print(prog, ent, NULL);
}
- PRVM_ED_Free (ent);
+ PRVM_ED_Free (prog, ent);
continue; // not included in "inhibited" count
}
}
else
{
// self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_allglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (func - prog->functions, "");
+ prog->ExecuteProgram(prog, func - prog->functions, "");
}
}
if (PRVM_serverfunction(SV_OnEntityPostSpawnFunction))
{
// self = ent
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (PRVM_serverfunction(SV_OnEntityPostSpawnFunction), "QC function SV_OnEntityPostSpawnFunction is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPostSpawnFunction), "QC function SV_OnEntityPostSpawnFunction is missing");
}
spawned++;
died++;
}
- Con_DPrintf("%s: %i new entities parsed, %i new inhibited, %i (%i new) spawned (whereas %i removed self, %i stayed)\n", PRVM_NAME, parsed, inhibited, prog->num_edicts, spawned, died, spawned - died);
+ Con_DPrintf("%s: %i new entities parsed, %i new inhibited, %i (%i new) spawned (whereas %i removed self, %i stayed)\n", prog->name, parsed, inhibited, prog->num_edicts, spawned, died, spawned - died);
prvm_reuseedicts_always_allow = 0;
}
-void PRVM_FindOffsets(void)
+static void PRVM_FindOffsets(prvm_prog_t *prog)
{
// field and global searches use -1 for NULL
memset(&prog->fieldoffsets, -1, sizeof(prog->fieldoffsets));
#define PRVM_DECLARE_serverfunction(x)
#define PRVM_DECLARE_clientfunction(x)
#define PRVM_DECLARE_menufunction(x)
-#define PRVM_DECLARE_field(x) prog->fieldoffsets.x = PRVM_ED_FindFieldOffset(#x);
-#define PRVM_DECLARE_global(x) prog->globaloffsets.x = PRVM_ED_FindGlobalOffset(#x);
-#define PRVM_DECLARE_function(x) prog->funcoffsets.x = PRVM_ED_FindFunctionOffset(#x);
+#define PRVM_DECLARE_field(x) prog->fieldoffsets.x = PRVM_ED_FindFieldOffset(prog, #x);
+#define PRVM_DECLARE_global(x) prog->globaloffsets.x = PRVM_ED_FindGlobalOffset(prog, #x);
+#define PRVM_DECLARE_function(x) prog->funcoffsets.x = PRVM_ED_FindFunctionOffset(prog, #x);
#include "prvm_offsets.h"
#undef PRVM_DECLARE_serverglobalfloat
#undef PRVM_DECLARE_serverglobalvector
po_string_t *hashtable[PO_HASHSIZE];
}
po_t;
-void PRVM_PO_UnparseString(char *out, const char *in, size_t outsize)
+static void PRVM_PO_UnparseString(char *out, const char *in, size_t outsize)
{
for(;;)
{
++in;
}
}
-void PRVM_PO_ParseString(char *out, const char *in, size_t outsize)
+static void PRVM_PO_ParseString(char *out, const char *in, size_t outsize)
{
for(;;)
{
++in;
}
}
-po_t *PRVM_PO_Load(const char *filename, mempool_t *pool)
+static po_t *PRVM_PO_Load(const char *filename, mempool_t *pool)
{
po_t *po;
const char *p, *q;
Mem_Free((char *) buf);
return po;
}
-const char *PRVM_PO_Lookup(po_t *po, const char *str)
+static const char *PRVM_PO_Lookup(po_t *po, const char *str)
{
int hashindex = CRC_Block((const unsigned char *) str, strlen(str)) % PO_HASHSIZE;
po_string_t *p = po->hashtable[hashindex];
}
return NULL;
}
-void PRVM_PO_Destroy(po_t *po)
+static void PRVM_PO_Destroy(po_t *po)
{
int i;
for(i = 0; i < PO_HASHSIZE; ++i)
Mem_Free(po);
}
-void PRVM_LeakTest(void);
-void PRVM_ResetProg(void)
+void PRVM_LeakTest(prvm_prog_t *prog);
+void PRVM_Prog_Reset(prvm_prog_t *prog)
{
- PRVM_LeakTest();
- PRVM_GCALL(reset_cmd)();
+ PRVM_LeakTest(prog);
+ prog->reset_cmd(prog);
Mem_FreePool(&prog->progs_mempool);
if(prog->po)
PRVM_PO_Destroy((po_t *) prog->po);
memset(prog,0,sizeof(prvm_prog_t));
- prog->starttime = Sys_DoubleTime();
}
/*
PRVM_LoadLNO
===============
*/
-void PRVM_LoadLNO( const char *progname ) {
+static void PRVM_LoadLNO( prvm_prog_t *prog, const char *progname ) {
fs_offset_t filesize;
unsigned char *lno;
unsigned int *header;
PRVM_LoadProgs
===============
*/
-void PRVM_LoadProgs (const char * filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global)
+void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global)
{
int i;
dprograms_t *dprograms;
int a;
int b;
int c;
+ char vabuf[1024];
if (prog->loaded)
- PRVM_ERROR ("PRVM_LoadProgs: there is already a %s program loaded!", PRVM_NAME );
+ prog->error_cmd("PRVM_LoadProgs: there is already a %s program loaded!", prog->name );
+
+ Host_LockSession(); // all progs can use the session cvar
+ Crypto_LoadKeys(); // all progs might use the keys at init time
dprograms = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false, &filesize);
if (dprograms == NULL || filesize < (fs_offset_t)sizeof(dprograms_t))
- PRVM_ERROR ("PRVM_LoadProgs: couldn't load %s for %s", filename, PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: couldn't load %s for %s", filename, prog->name);
// TODO bounds check header fields (e.g. numstatements), they must never go behind end of file
- Con_DPrintf("%s programs occupy %iK.\n", PRVM_NAME, (int)(filesize/1024));
+ prog->profiletime = Sys_DirtyTime();
+ prog->starttime = realtime;
+
+ Con_DPrintf("%s programs occupy %iK.\n", prog->name, (int)(filesize/1024));
requiredglobalspace = 0;
for (i = 0;i < numrequiredglobals;i++)
prog->progs_version = LittleLong(dprograms->version);
prog->progs_crc = LittleLong(dprograms->crc);
if (prog->progs_version != PROG_VERSION)
- PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, prog->progs_version, PROG_VERSION);
+ prog->error_cmd("%s: %s has wrong version number (%i should be %i)", prog->name, filename, prog->progs_version, PROG_VERSION);
instatements = (dstatement_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_statements));
prog->progs_numstatements = LittleLong(dprograms->numstatements);
inglobaldefs = (ddef_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_globaldefs));
prog->entityfields = prog->progs_entityfields;
if (LittleLong(dprograms->ofs_strings) + prog->progs_numstrings >= (int)filesize)
- PRVM_ERROR ("%s: %s strings go past end of file", PRVM_NAME, filename);
+ prog->error_cmd("%s: %s strings go past end of file", prog->name, filename);
prog->strings = (char *)Mem_Alloc(prog->progs_mempool, prog->progs_numstrings);
memcpy(prog->strings, instrings, prog->progs_numstrings);
prog->stringssize = prog->progs_numstrings;
prog->functions[i].locals = LittleLong(infunctions[i].locals);
memcpy(prog->functions[i].parm_size, infunctions[i].parm_size, sizeof(infunctions[i].parm_size));
if(prog->functions[i].first_statement >= prog->numstatements)
- PRVM_ERROR("PRVM_LoadProgs: out of bounds function statement (function %d) in %s", i, PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: out of bounds function statement (function %d) in %s", i, prog->name);
// TODO bounds check parm_start, s_name, s_file, numparms, locals, parm_size
}
{
prog->globaldefs[prog->numglobaldefs].type = required_global[i].type;
prog->globaldefs[prog->numglobaldefs].ofs = prog->numglobals;
- prog->globaldefs[prog->numglobaldefs].s_name = PRVM_SetEngineString(required_global[i].name);
+ prog->globaldefs[prog->numglobaldefs].s_name = PRVM_SetEngineString(prog, required_global[i].name);
if (prog->globaldefs[prog->numglobaldefs].type == ev_vector)
prog->numglobals += 3;
else
{
prog->fielddefs[i].type = LittleShort(infielddefs[i].type);
if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
- PRVM_ERROR ("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", prog->name);
prog->fielddefs[i].ofs = LittleShort(infielddefs[i].ofs);
prog->fielddefs[i].s_name = LittleLong(infielddefs[i].s_name);
// TODO bounds check ofs, s_name
{
prog->fielddefs[prog->numfielddefs].type = required_field[i].type;
prog->fielddefs[prog->numfielddefs].ofs = prog->entityfields;
- prog->fielddefs[prog->numfielddefs].s_name = PRVM_SetEngineString(required_field[i].name);
+ prog->fielddefs[prog->numfielddefs].s_name = PRVM_SetEngineString(prog, required_field[i].name);
if (prog->fielddefs[prog->numfielddefs].type == ev_vector)
prog->entityfields += 3;
else
case OP_IFNOT:
b = (short)b;
if (a >= prog->progs_numglobals || b + i < 0 || b + i >= prog->progs_numstatements)
- PRVM_ERROR("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s", i, PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: out of bounds IF/IFNOT (statement %d) in %s", i, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = -1;
case OP_GOTO:
a = (short)a;
if (a + i < 0 || a + i >= prog->progs_numstatements)
- PRVM_ERROR("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s", i, PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: out of bounds GOTO (statement %d) in %s", i, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = -1;
prog->statements[i].operand[1] = -1;
prog->statements[i].jumpabsolute = i + a;
break;
default:
- Con_DPrintf("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", (int)op, i, PRVM_NAME);
+ Con_DPrintf("PRVM_LoadProgs: unknown opcode %d at statement %d in %s\n", (int)op, i, prog->name);
// global global global
case OP_ADD_F:
case OP_ADD_V:
case OP_LOAD_FNC:
case OP_LOAD_V:
if (a >= prog->progs_numglobals || b >= prog->progs_numglobals || c >= prog->progs_numglobals)
- PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d)", i);
+ prog->error_cmd("PRVM_LoadProgs: out of bounds global index (statement %d)", i);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = remapglobal(b);
case OP_NOT_FNC:
case OP_NOT_ENT:
if (a >= prog->progs_numglobals || c >= prog->progs_numglobals)
- PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = -1;
case OP_STOREP_V:
case OP_STORE_V:
if (a >= prog->progs_numglobals || b >= prog->progs_numglobals)
- PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = remapglobal(b);
case OP_DONE:
case OP_RETURN:
if ( a >= prog->progs_numglobals)
- PRVM_ERROR("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: out of bounds global index (statement %d) in %s", i, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = -1;
}
if(prog->numstatements < 1)
{
- PRVM_ERROR("PRVM_LoadProgs: empty program in %s", PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: empty program in %s", prog->name);
}
else switch(prog->statements[prog->numstatements - 1].op)
{
case OP_DONE:
break;
default:
- PRVM_ERROR("PRVM_LoadProgs: program may fall off the edge (does not end with RETURN, GOTO or DONE) in %s", PRVM_NAME);
+ prog->error_cmd("PRVM_LoadProgs: program may fall off the edge (does not end with RETURN, GOTO or DONE) in %s", prog->name);
break;
}
// check required functions
for(i=0 ; i < numrequiredfunc ; i++)
- if(PRVM_ED_FindFunction(required_func[i]) == 0)
- PRVM_ERROR("%s: %s not found in %s",PRVM_NAME, required_func[i], filename);
+ if(PRVM_ED_FindFunction(prog, required_func[i]) == 0)
+ prog->error_cmd("%s: %s not found in %s",prog->name, required_func[i], filename);
- PRVM_LoadLNO(filename);
+ PRVM_LoadLNO(prog, filename);
- PRVM_Init_Exec();
+ PRVM_Init_Exec(prog);
if(*prvm_language.string)
// in CSQC we really shouldn't be able to change how stuff works... sorry for now
// later idea: include a list of authorized .po file checksums with the csprogs
{
- qboolean deftrans = !!strcmp(PRVM_NAME, "client");
- const char *realfilename = (strcmp(PRVM_NAME, "client") ? filename : csqc_progname.string);
+ qboolean deftrans = prog == CLVM_prog;
+ const char *realfilename = (prog != CLVM_prog ? filename : csqc_progname.string);
if(deftrans) // once we have dotranslate_ strings, ALWAYS use the opt-in method!
{
for (i=0 ; i<prog->numglobaldefs ; i++)
{
const char *name;
- name = PRVM_GetString(prog->globaldefs[i].s_name);
+ name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
if(name && !strncmp(name, "dotranslate_", 12))
{
}
if(!strcmp(prvm_language.string, "dump"))
{
- qfile_t *f = FS_OpenRealFile(va("%s.pot", realfilename), "w", false);
+ qfile_t *f = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.pot", realfilename), "w", false);
Con_Printf("Dumping to %s.pot\n", realfilename);
if(f)
{
for (i=0 ; i<prog->numglobaldefs ; i++)
{
const char *name;
- name = PRVM_GetString(prog->globaldefs[i].s_name);
+ name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
if(deftrans ? (!name || strncmp(name, "notranslate_", 12)) : (name && !strncmp(name, "dotranslate_", 12)))
if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
{
prvm_eval_t *val = PRVM_GLOBALFIELDVALUE(prog->globaldefs[i].ofs);
- const char *value = PRVM_GetString(val->string);
+ const char *value = PRVM_GetString(prog, val->string);
if(*value)
{
char buf[MAX_INPUTLINE];
}
else
{
- po_t *po = PRVM_PO_Load(va("%s.%s.po", realfilename, prvm_language.string), prog->progs_mempool);
+ po_t *po = PRVM_PO_Load(va(vabuf, sizeof(vabuf), "%s.%s.po", realfilename, prvm_language.string), prog->progs_mempool);
if(po)
{
for (i=0 ; i<prog->numglobaldefs ; i++)
{
const char *name;
- name = PRVM_GetString(prog->globaldefs[i].s_name);
+ name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
if(deftrans ? (!name || strncmp(name, "notranslate_", 12)) : (name && !strncmp(name, "dotranslate_", 12)))
if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
{
prvm_eval_t *val = PRVM_GLOBALFIELDVALUE(prog->globaldefs[i].ofs);
- const char *value = PRVM_GetString(val->string);
+ const char *value = PRVM_GetString(prog, val->string);
if(*value)
{
value = PRVM_PO_Lookup(po, value);
if(value)
- val->string = PRVM_SetEngineString(value);
+ val->string = PRVM_SetEngineString(prog, value);
}
}
}
for (i=0 ; i<prog->numglobaldefs ; i++)
{
const char *name;
- name = PRVM_GetString(prog->globaldefs[i].s_name);
+ name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
//Con_Printf("found var %s\n", name);
if(name
&& !strncmp(name, "autocvar_", 9)
{
prvm_eval_t *val = PRVM_GLOBALFIELDVALUE(prog->globaldefs[i].ofs);
cvar_t *cvar = Cvar_FindVar(name + 9);
- //Con_Printf("PRVM_LoadProgs: autocvar global %s in %s, processing...\n", name, PRVM_NAME);
+ //Con_Printf("PRVM_LoadProgs: autocvar global %s in %s, processing...\n", name, prog->name);
if(!cvar)
{
const char *value;
char buf[64];
- Con_DPrintf("PRVM_LoadProgs: no cvar for autocvar global %s in %s, creating...\n", name, PRVM_NAME);
+ Con_DPrintf("PRVM_LoadProgs: no cvar for autocvar global %s in %s, creating...\n", name, prog->name);
switch(prog->globaldefs[i].type & ~DEF_SAVEGLOBAL)
{
case ev_float:
dpsnprintf(buf, sizeof(buf), "%.9g %.9g %.9g", val->vector[0], val->vector[1], val->vector[2]); value = buf;
break;
case ev_string:
- value = PRVM_GetString(val->string);
+ value = PRVM_GetString(prog, val->string);
break;
default:
- Con_Printf("PRVM_LoadProgs: invalid type of autocvar global %s in %s\n", name, PRVM_NAME);
+ Con_Printf("PRVM_LoadProgs: invalid type of autocvar global %s in %s\n", name, prog->name);
goto fail;
}
cvar = Cvar_Get(name + 9, value, 0, NULL);
if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
{
- val->string = PRVM_SetEngineString(cvar->string);
- cvar->globaldefindex_stringno[prog - prog_list] = val->string;
+ val->string = PRVM_SetEngineString(prog, cvar->string);
+ cvar->globaldefindex_stringno[prog - prvm_prog_list] = val->string;
}
if(!cvar)
- PRVM_ERROR("PRVM_LoadProgs: could not create cvar for autocvar global %s in %s", name, PRVM_NAME);
- cvar->globaldefindex_progid[prog - prog_list] = prog->id;
- cvar->globaldefindex[prog - prog_list] = i;
+ prog->error_cmd("PRVM_LoadProgs: could not create cvar for autocvar global %s in %s", name, prog->name);
+ cvar->globaldefindex_progid[prog - prvm_prog_list] = prog->id;
+ cvar->globaldefindex[prog - prvm_prog_list] = i;
}
else if((cvar->flags & CVAR_PRIVATE) == 0)
{
}
break;
case ev_string:
- val->string = PRVM_SetEngineString(cvar->string);
- cvar->globaldefindex_stringno[prog - prog_list] = val->string;
+ val->string = PRVM_SetEngineString(prog, cvar->string);
+ cvar->globaldefindex_stringno[prog - prvm_prog_list] = val->string;
break;
default:
- Con_Printf("PRVM_LoadProgs: invalid type of autocvar global %s in %s\n", name, PRVM_NAME);
+ Con_Printf("PRVM_LoadProgs: invalid type of autocvar global %s in %s\n", name, prog->name);
goto fail;
}
- cvar->globaldefindex_progid[prog - prog_list] = prog->id;
- cvar->globaldefindex[prog - prog_list] = i;
+ cvar->globaldefindex_progid[prog - prvm_prog_list] = prog->id;
+ cvar->globaldefindex[prog - prvm_prog_list] = i;
}
else
- Con_Printf("PRVM_LoadProgs: private cvar for autocvar global %s in %s\n", name, PRVM_NAME);
+ Con_Printf("PRVM_LoadProgs: private cvar for autocvar global %s in %s\n", name, prog->name);
}
fail:
;
prog->flag = 0;
- PRVM_FindOffsets();
+ PRVM_FindOffsets(prog);
- PRVM_GCALL(init_cmd)();
+ prog->init_cmd(prog);
// init mempools
- PRVM_MEM_Alloc();
+ PRVM_MEM_Alloc(prog);
}
-void PRVM_Fields_f (void)
+static void PRVM_Fields_f (void)
{
+ prvm_prog_t *prog;
int i, j, ednum, used, usedamount;
int *counts;
char tempstring[MAX_INPUTLINE], tempstring2[260];
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
counts = (int *)Mem_Alloc(tempmempool, prog->numfielddefs * sizeof(int));
for (i = 1;i < prog->numfielddefs;i++)
{
d = &prog->fielddefs[i];
- name = PRVM_GetString(d->s_name);
+ name = PRVM_GetString(prog, d->s_name);
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
v = (int *)(ed->fields.vp + d->ofs);
for (i = 0;i < prog->numfielddefs;i++)
{
d = &prog->fielddefs[i];
- name = PRVM_GetString(d->s_name);
+ name = PRVM_GetString(prog, d->s_name);
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
switch(d->type & ~DEF_SAVEGLOBAL)
}
}
Mem_Free(counts);
- Con_Printf("%s: %i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", PRVM_NAME, prog->entityfields, used, prog->entityfields * 4, usedamount * 4, prog->max_edicts, prog->entityfields * 4 * prog->max_edicts, usedamount * 4 * prog->max_edicts);
-
- PRVM_End;
+ Con_Printf("%s: %i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", prog->name, prog->entityfields, used, prog->entityfields * 4, usedamount * 4, prog->max_edicts, prog->entityfields * 4 * prog->max_edicts, usedamount * 4 * prog->max_edicts);
}
-void PRVM_Globals_f (void)
+static void PRVM_Globals_f (void)
{
+ prvm_prog_t *prog;
int i;
const char *wildcard;
int numculled;
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString (Cmd_Argv (1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
if( Cmd_Argc() == 3)
else
wildcard = NULL;
- Con_Printf("%s :", PRVM_NAME);
+ Con_Printf("%s :", prog->name);
for (i = 0;i < prog->numglobaldefs;i++)
{
if(wildcard)
- if( !matchpattern( PRVM_GetString(prog->globaldefs[i].s_name), wildcard, 1) )
+ if( !matchpattern( PRVM_GetString(prog, prog->globaldefs[i].s_name), wildcard, 1) )
{
numculled++;
continue;
}
- Con_Printf("%s\n", PRVM_GetString(prog->globaldefs[i].s_name));
+ Con_Printf("%s\n", PRVM_GetString(prog, prog->globaldefs[i].s_name));
}
Con_Printf("%i global variables, %i culled, totalling %i bytes\n", prog->numglobals, numculled, prog->numglobals * 4);
-
- PRVM_End;
}
/*
PRVM_Global
===============
*/
-void PRVM_Global_f(void)
+static void PRVM_Global_f(void)
{
+ prvm_prog_t *prog;
ddef_t *global;
+ char valuebuf[MAX_INPUTLINE];
if( Cmd_Argc() != 3 ) {
Con_Printf( "prvm_global <program name> <global name>\n" );
return;
}
- PRVM_Begin;
- if( !PRVM_SetProgFromString( Cmd_Argv(1) ) )
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- global = PRVM_ED_FindGlobal( Cmd_Argv(2) );
+ global = PRVM_ED_FindGlobal( prog, Cmd_Argv(2) );
if( !global )
Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
else
- Con_Printf( "%s: %s\n", Cmd_Argv(2), PRVM_ValueString( (etype_t)global->type, PRVM_GLOBALFIELDVALUE(global->ofs) ) );
- PRVM_End;
+ Con_Printf( "%s: %s\n", Cmd_Argv(2), PRVM_ValueString( prog, (etype_t)global->type, PRVM_GLOBALFIELDVALUE(global->ofs), valuebuf, sizeof(valuebuf) ) );
}
/*
PRVM_GlobalSet
===============
*/
-void PRVM_GlobalSet_f(void)
+static void PRVM_GlobalSet_f(void)
{
+ prvm_prog_t *prog;
ddef_t *global;
if( Cmd_Argc() != 4 ) {
Con_Printf( "prvm_globalset <program name> <global name> <value>\n" );
return;
}
- PRVM_Begin;
- if( !PRVM_SetProgFromString( Cmd_Argv(1) ) )
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- global = PRVM_ED_FindGlobal( Cmd_Argv(2) );
+ global = PRVM_ED_FindGlobal( prog, Cmd_Argv(2) );
if( !global )
Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(2), Cmd_Argv(1) );
else
- PRVM_ED_ParseEpair( NULL, global, Cmd_Argv(3), true );
- PRVM_End;
+ PRVM_ED_ParseEpair( prog, NULL, global, Cmd_Argv(3), true );
}
/*
PRVM_InitProg
===============
*/
-void PRVM_InitProg(int prognr)
+void PRVM_Prog_Init(prvm_prog_t *prog)
{
- static unsigned int progid = 0;
-
- if(prognr < 0 || prognr >= PRVM_MAXPROGS)
- Sys_Error("PRVM_InitProg: Invalid program number %i",prognr);
-
- prog = &prog_list[prognr];
-
- if(prog->loaded)
- PRVM_ResetProg();
+ if (prog->loaded)
+ PRVM_Prog_Reset(prog);
memset(prog, 0, sizeof(prvm_prog_t));
- prog->starttime = Sys_DoubleTime();
- prog->id = ++progid;
-
- prog->error_cmd = Host_Error;
prog->leaktest_active = prvm_leaktest.integer != 0;
}
-int PRVM_GetProgNr(void)
-{
- return prog - prog_list;
-}
-
-void *_PRVM_Alloc(size_t buffersize, const char *filename, int fileline)
-{
- return _Mem_Alloc(prog->progs_mempool, NULL, buffersize, 16, filename, fileline);
-}
-
-void _PRVM_Free(void *buffer, const char *filename, int fileline)
-{
- _Mem_Free(buffer, filename, fileline);
-}
-
-void _PRVM_FreeAll(const char *filename, int fileline)
-{
- prog->functions = NULL;
- prog->strings = NULL;
- prog->fielddefs = NULL;
- prog->globaldefs = NULL;
- prog->statements = NULL;
- // FIXME: what about knownstrings?
- _Mem_EmptyPool(prog->progs_mempool, filename, fileline);
-}
-
// LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
-unsigned int PRVM_EDICT_NUM_ERROR(unsigned int n, const char *filename, int fileline)
+unsigned int PRVM_EDICT_NUM_ERROR(prvm_prog_t *prog, unsigned int n, const char *filename, int fileline)
{
- PRVM_ERROR ("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", PRVM_NAME, n, filename, fileline);
+ prog->error_cmd("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", prog->name, n, filename, fileline);
return 0;
}
-sizebuf_t vm_tempstringsbuf;
#define PRVM_KNOWNSTRINGBASE 0x40000000
-const char *PRVM_GetString(int num)
+const char *PRVM_GetString(prvm_prog_t *prog, int num)
{
if (num < 0)
{
// invalid
- VM_Warning("PRVM_GetString: Invalid string offset (%i < 0)\n", num);
+ VM_Warning(prog, "PRVM_GetString: Invalid string offset (%i < 0)\n", num);
return "";
}
else if (num < prog->stringssize)
// constant string from progs.dat
return prog->strings + num;
}
- else if (num <= prog->stringssize + vm_tempstringsbuf.maxsize)
+ else if (num <= prog->stringssize + prog->tempstringsbuf.maxsize)
{
// tempstring returned by engine to QC (becomes invalid after returning to engine)
num -= prog->stringssize;
- if (num < vm_tempstringsbuf.cursize)
- return (char *)vm_tempstringsbuf.data + num;
+ if (num < prog->tempstringsbuf.cursize)
+ return (char *)prog->tempstringsbuf.data + num;
else
{
- VM_Warning("PRVM_GetString: Invalid temp-string offset (%i >= %i vm_tempstringsbuf.cursize)\n", num, vm_tempstringsbuf.cursize);
+ VM_Warning(prog, "PRVM_GetString: Invalid temp-string offset (%i >= %i prog->tempstringsbuf.cursize)\n", num, prog->tempstringsbuf.cursize);
return "";
}
}
{
if (!prog->knownstrings[num])
{
- VM_Warning("PRVM_GetString: Invalid zone-string offset (%i has been freed)\n", num);
+ VM_Warning(prog, "PRVM_GetString: Invalid zone-string offset (%i has been freed)\n", num);
return "";
}
return prog->knownstrings[num];
}
else
{
- VM_Warning("PRVM_GetString: Invalid zone-string offset (%i >= %i)\n", num, prog->numknownstrings);
+ VM_Warning(prog, "PRVM_GetString: Invalid zone-string offset (%i >= %i)\n", num, prog->numknownstrings);
return "";
}
}
else
{
// invalid string offset
- VM_Warning("PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)\n", num, prog->stringssize);
+ VM_Warning(prog, "PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)\n", num, prog->stringssize);
return "";
}
}
-const char *PRVM_ChangeEngineString(int i, const char *s)
+const char *PRVM_ChangeEngineString(prvm_prog_t *prog, int i, const char *s)
{
const char *old;
i = i - PRVM_KNOWNSTRINGBASE;
if(i < 0 || i >= prog->numknownstrings)
- PRVM_ERROR("PRVM_ChangeEngineString: s is not an engine string");
+ prog->error_cmd("PRVM_ChangeEngineString: s is not an engine string");
old = prog->knownstrings[i];
prog->knownstrings[i] = s;
return old;
}
-int PRVM_SetEngineString(const char *s)
+int PRVM_SetEngineString(prvm_prog_t *prog, const char *s)
{
int i;
if (!s)
return 0;
if (s >= prog->strings && s <= prog->strings + prog->stringssize)
- PRVM_ERROR("PRVM_SetEngineString: s in prog->strings area");
+ prog->error_cmd("PRVM_SetEngineString: s in prog->strings area");
// if it's in the tempstrings area, use a reserved range
// (otherwise we'd get millions of useless string offsets cluttering the database)
- if (s >= (char *)vm_tempstringsbuf.data && s < (char *)vm_tempstringsbuf.data + vm_tempstringsbuf.maxsize)
+ if (s >= (char *)prog->tempstringsbuf.data && s < (char *)prog->tempstringsbuf.data + prog->tempstringsbuf.maxsize)
#if 1
- return prog->stringssize + (s - (char *)vm_tempstringsbuf.data);
+ return prog->stringssize + (s - (char *)prog->tempstringsbuf.data);
#endif
// see if it's a known string address
for (i = 0;i < prog->numknownstrings;i++)
// buffer)
// the buffer size is automatically grown as needed
-int PRVM_SetTempString(const char *s)
+int PRVM_SetTempString(prvm_prog_t *prog, const char *s)
{
int size;
char *t;
return 0;
size = (int)strlen(s) + 1;
if (developer_insane.integer)
- Con_DPrintf("PRVM_SetTempString: cursize %i, size %i\n", vm_tempstringsbuf.cursize, size);
- if (vm_tempstringsbuf.maxsize < vm_tempstringsbuf.cursize + size)
- {
- sizebuf_t old = vm_tempstringsbuf;
- if (vm_tempstringsbuf.cursize + size >= 1<<28)
- PRVM_ERROR("PRVM_SetTempString: ran out of tempstring memory! (refusing to grow tempstring buffer over 256MB, cursize %i, size %i)\n", vm_tempstringsbuf.cursize, size);
- vm_tempstringsbuf.maxsize = max(vm_tempstringsbuf.maxsize, 65536);
- while (vm_tempstringsbuf.maxsize < vm_tempstringsbuf.cursize + size)
- vm_tempstringsbuf.maxsize *= 2;
- if (vm_tempstringsbuf.maxsize != old.maxsize || vm_tempstringsbuf.data == NULL)
+ Con_DPrintf("PRVM_SetTempString: cursize %i, size %i\n", prog->tempstringsbuf.cursize, size);
+ if (prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
+ {
+ sizebuf_t old = prog->tempstringsbuf;
+ if (prog->tempstringsbuf.cursize + size >= 1<<28)
+ prog->error_cmd("PRVM_SetTempString: ran out of tempstring memory! (refusing to grow tempstring buffer over 256MB, cursize %i, size %i)\n", prog->tempstringsbuf.cursize, size);
+ prog->tempstringsbuf.maxsize = max(prog->tempstringsbuf.maxsize, 65536);
+ while (prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
+ prog->tempstringsbuf.maxsize *= 2;
+ if (prog->tempstringsbuf.maxsize != old.maxsize || prog->tempstringsbuf.data == NULL)
{
- Con_DPrintf("PRVM_SetTempString: enlarging tempstrings buffer (%iKB -> %iKB)\n", old.maxsize/1024, vm_tempstringsbuf.maxsize/1024);
- vm_tempstringsbuf.data = (unsigned char *) Mem_Alloc(sv_mempool, vm_tempstringsbuf.maxsize);
+ Con_DPrintf("PRVM_SetTempString: enlarging tempstrings buffer (%iKB -> %iKB)\n", old.maxsize/1024, prog->tempstringsbuf.maxsize/1024);
+ prog->tempstringsbuf.data = (unsigned char *) Mem_Alloc(prog->progs_mempool, prog->tempstringsbuf.maxsize);
if (old.cursize)
- memcpy(vm_tempstringsbuf.data, old.data, old.cursize);
+ memcpy(prog->tempstringsbuf.data, old.data, old.cursize);
if (old.data)
Mem_Free(old.data);
}
}
- t = (char *)vm_tempstringsbuf.data + vm_tempstringsbuf.cursize;
+ t = (char *)prog->tempstringsbuf.data + prog->tempstringsbuf.cursize;
memcpy(t, s, size);
- vm_tempstringsbuf.cursize += size;
- return PRVM_SetEngineString(t);
+ prog->tempstringsbuf.cursize += size;
+ return PRVM_SetEngineString(prog, t);
}
-int PRVM_AllocString(size_t bufferlength, char **pointer)
+int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer)
{
int i;
if (!bufferlength)
prog->knownstrings[i] = (char *)PRVM_Alloc(bufferlength);
prog->knownstrings_freeable[i] = true;
if(prog->leaktest_active)
- prog->knownstrings_origin[i] = PRVM_AllocationOrigin();
+ prog->knownstrings_origin[i] = PRVM_AllocationOrigin(prog);
if (pointer)
*pointer = (char *)(prog->knownstrings[i]);
return PRVM_KNOWNSTRINGBASE + i;
}
-void PRVM_FreeString(int num)
+void PRVM_FreeString(prvm_prog_t *prog, int num)
{
if (num == 0)
- PRVM_ERROR("PRVM_FreeString: attempt to free a NULL string");
+ prog->error_cmd("PRVM_FreeString: attempt to free a NULL string");
else if (num >= 0 && num < prog->stringssize)
- PRVM_ERROR("PRVM_FreeString: attempt to free a constant string");
+ prog->error_cmd("PRVM_FreeString: attempt to free a constant string");
else if (num >= PRVM_KNOWNSTRINGBASE && num < PRVM_KNOWNSTRINGBASE + prog->numknownstrings)
{
num = num - PRVM_KNOWNSTRINGBASE;
if (!prog->knownstrings[num])
- PRVM_ERROR("PRVM_FreeString: attempt to free a non-existent or already freed string");
+ prog->error_cmd("PRVM_FreeString: attempt to free a non-existent or already freed string");
if (!prog->knownstrings_freeable[num])
- PRVM_ERROR("PRVM_FreeString: attempt to free a string owned by the engine");
+ prog->error_cmd("PRVM_FreeString: attempt to free a string owned by the engine");
PRVM_Free((char *)prog->knownstrings[num]);
if(prog->leaktest_active)
if(prog->knownstrings_origin[num])
prog->firstfreeknownstring = min(prog->firstfreeknownstring, num);
}
else
- PRVM_ERROR("PRVM_FreeString: invalid string offset %i", num);
+ prog->error_cmd("PRVM_FreeString: invalid string offset %i", num);
}
-static qboolean PRVM_IsStringReferenced(string_t string)
+static qboolean PRVM_IsStringReferenced(prvm_prog_t *prog, string_t string)
{
int i, j;
return false;
}
-static qboolean PRVM_IsEdictRelevant(prvm_edict_t *edict)
+static qboolean PRVM_IsEdictRelevant(prvm_prog_t *prog, prvm_edict_t *edict)
{
+ char vabuf[1024];
+ char vabuf2[1024];
if(PRVM_NUM_FOR_EDICT(edict) <= prog->reserved_edicts)
return true; // world or clients
- switch(prog - prog_list)
+ if (prog == SVVM_prog)
{
- case PRVM_SERVERPROG:
- {
- if(PRVM_serveredictfloat(edict, solid)) // can block other stuff, or is a trigger?
- return true;
- if(PRVM_serveredictfloat(edict, modelindex)) // visible ent?
- return true;
- if(PRVM_serveredictfloat(edict, effects)) // particle effect?
- return true;
- if(PRVM_serveredictfunction(edict, think)) // has a think function?
- if(PRVM_serveredictfloat(edict, nextthink) > 0) // that actually will eventually run?
- return true;
- if(PRVM_serveredictfloat(edict, takedamage))
- return true;
- if(*prvm_leaktest_ignore_classnames.string)
- {
- if(strstr(va(" %s ", prvm_leaktest_ignore_classnames.string), va(" %s ", PRVM_GetString(PRVM_serveredictstring(edict, classname)))))
- return true;
- }
- }
- break;
- case PRVM_CLIENTPROG:
- {
- // TODO someone add more stuff here
- if(PRVM_clientedictfloat(edict, entnum)) // csqc networked
- return true;
- if(PRVM_clientedictfloat(edict, modelindex)) // visible ent?
- return true;
- if(PRVM_clientedictfloat(edict, effects)) // particle effect?
- return true;
- if(PRVM_clientedictfunction(edict, think)) // has a think function?
- if(PRVM_clientedictfloat(edict, nextthink) > 0) // that actually will eventually run?
- return true;
- if(*prvm_leaktest_ignore_classnames.string)
- {
- if(strstr(va(" %s ", prvm_leaktest_ignore_classnames.string), va(" %s ", PRVM_GetString(PRVM_clientedictstring(edict, classname)))))
- return true;
- }
- }
- break;
- case PRVM_MENUPROG:
- // menu prog does not have classnames
- break;
+ if(PRVM_serveredictfloat(edict, solid)) // can block other stuff, or is a trigger?
+ return true;
+ if(PRVM_serveredictfloat(edict, modelindex)) // visible ent?
+ return true;
+ if(PRVM_serveredictfloat(edict, effects)) // particle effect?
+ return true;
+ if(PRVM_serveredictfunction(edict, think)) // has a think function?
+ if(PRVM_serveredictfloat(edict, nextthink) > 0) // that actually will eventually run?
+ return true;
+ if(PRVM_serveredictfloat(edict, takedamage))
+ return true;
+ if(*prvm_leaktest_ignore_classnames.string)
+ {
+ if(strstr(va(vabuf, sizeof(vabuf), " %s ", prvm_leaktest_ignore_classnames.string), va(vabuf2, sizeof(vabuf2), " %s ", PRVM_GetString(prog, PRVM_serveredictstring(edict, classname)))))
+ return true;
+ }
+ }
+ else if (prog == CLVM_prog)
+ {
+ // TODO someone add more stuff here
+ if(PRVM_clientedictfloat(edict, entnum)) // csqc networked
+ return true;
+ if(PRVM_clientedictfloat(edict, modelindex)) // visible ent?
+ return true;
+ if(PRVM_clientedictfloat(edict, effects)) // particle effect?
+ return true;
+ if(PRVM_clientedictfunction(edict, think)) // has a think function?
+ if(PRVM_clientedictfloat(edict, nextthink) > 0) // that actually will eventually run?
+ return true;
+ if(*prvm_leaktest_ignore_classnames.string)
+ {
+ if(strstr(va(vabuf, sizeof(vabuf), " %s ", prvm_leaktest_ignore_classnames.string), va(vabuf2, sizeof(vabuf2), " %s ", PRVM_GetString(prog, PRVM_clientedictstring(edict, classname)))))
+ return true;
+ }
+ }
+ else
+ {
+ // menu prog does not have classnames
}
return false;
}
-static qboolean PRVM_IsEdictReferenced(prvm_edict_t *edict, int mark)
+static qboolean PRVM_IsEdictReferenced(prvm_prog_t *prog, prvm_edict_t *edict, int mark)
{
int i, j;
int edictnum = PRVM_NUM_FOR_EDICT(edict);
const char *targetname = NULL;
- switch(prog - prog_list)
- {
- case PRVM_SERVERPROG:
- targetname = PRVM_GetString(PRVM_serveredictstring(edict, targetname));
- break;
- }
+ if (prog == SVVM_prog)
+ targetname = PRVM_GetString(prog, PRVM_serveredictstring(edict, targetname));
if(targetname)
if(!*targetname) // ""
targetname = NULL;
- for (i = 0;i < prog->numglobaldefs;i++)
+ if(mark == 0)
{
- ddef_t *d = &prog->globaldefs[i];
- if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
- continue;
- if(edictnum == PRVM_GLOBALFIELDEDICT(d->ofs))
- return true;
+ for (i = 0;i < prog->numglobaldefs;i++)
+ {
+ ddef_t *d = &prog->globaldefs[i];
+ if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
+ continue;
+ if(edictnum == PRVM_GLOBALFIELDEDICT(d->ofs))
+ return true;
+ }
}
for(j = 0; j < prog->num_edicts; ++j)
continue;
if(targetname)
{
- const char *target = PRVM_GetString(PRVM_serveredictstring(ed, target));
+ const char *target = PRVM_GetString(prog, PRVM_serveredictstring(ed, target));
if(target)
if(!strcmp(target, targetname))
return true;
return false;
}
-static void PRVM_MarkReferencedEdicts(void)
+static void PRVM_MarkReferencedEdicts(prvm_prog_t *prog)
{
int j;
qboolean found_new;
prvm_edict_t *ed = PRVM_EDICT_NUM(j);
if(ed->priv.required->free)
continue;
- ed->priv.required->mark = PRVM_IsEdictRelevant(ed) ? 1 : 0;
+ ed->priv.required->mark = PRVM_IsEdictRelevant(prog, ed) ? 1 : 0;
}
stage = 1;
continue;
if(ed->priv.required->mark)
continue;
- if(PRVM_IsEdictReferenced(ed, stage))
+ if(PRVM_IsEdictReferenced(prog, ed, stage))
{
ed->priv.required->mark = stage + 1;
found_new = true;
Con_DPrintf("leak check used %d stages to find all references\n", stage);
}
-void PRVM_LeakTest(void)
+void PRVM_LeakTest(prvm_prog_t *prog)
{
int i, j;
qboolean leaked = false;
if(prog->knownstrings[i])
if(prog->knownstrings_freeable[i])
if(prog->knownstrings_origin[i])
- if(!PRVM_IsStringReferenced(PRVM_KNOWNSTRINGBASE + i))
+ if(!PRVM_IsStringReferenced(prog, PRVM_KNOWNSTRINGBASE + i))
{
Con_Printf("Unreferenced string found!\n Value: %s\n Origin: %s\n", prog->knownstrings[i], prog->knownstrings_origin[i]);
leaked = true;
}
// 2. Edicts
- PRVM_MarkReferencedEdicts();
+ PRVM_MarkReferencedEdicts(prog);
for(j = 0; j < prog->num_edicts; ++j)
{
prvm_edict_t *ed = PRVM_EDICT_NUM(j);
if(ed->priv.required->allocation_origin)
{
Con_Printf("Unreferenced edict found!\n Allocated at: %s\n", ed->priv.required->allocation_origin);
- PRVM_ED_Print(ed, NULL);
+ PRVM_ED_Print(prog, ed, NULL);
Con_Print("\n");
leaked = true;
}
+
+ ed->priv.required->mark = 0; // clear marks again when done
}
for (i = 0; i < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); ++i)
"BITOR"
};
-char *PRVM_GlobalString (int ofs);
-char *PRVM_GlobalStringNoContents (int ofs);
-extern ddef_t *PRVM_ED_FieldAtOfs(int ofs);
//=============================================================================
*/
extern cvar_t prvm_statementprofiling;
extern cvar_t prvm_timeprofiling;
-void PRVM_PrintStatement(mstatement_t *s)
+static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s)
{
size_t i;
int opnum = (int)(s - prog->statements);
+ char valuebuf[MAX_INPUTLINE];
Con_Printf("s%i: ", opnum);
if( prog->statement_linenums )
- Con_Printf( "%s:%i: ", PRVM_GetString( prog->xfunction->s_file ), prog->statement_linenums[ opnum ] );
+ Con_Printf( "%s:%i: ", PRVM_GetString( prog, prog->xfunction->s_file ), prog->statement_linenums[ opnum ] );
if (prvm_statementprofiling.integer)
Con_Printf("%7.0f ", prog->statement_profile[s - prog->statements]);
for ( ; i<10 ; i++)
Con_Print(" ");
}
- if (s->operand[0] >= 0) Con_Printf( "%s", PRVM_GlobalString(s->operand[0]));
- if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(s->operand[1]));
- if (s->operand[2] >= 0) Con_Printf(", %s", PRVM_GlobalString(s->operand[2]));
+ if (s->operand[0] >= 0) Con_Printf( "%s", PRVM_GlobalString(prog, s->operand[0], valuebuf, sizeof(valuebuf)));
+ if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[1], valuebuf, sizeof(valuebuf)));
+ if (s->operand[2] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[2], valuebuf, sizeof(valuebuf)));
if (s->jumpabsolute >= 0) Con_Printf(", statement %i", s->jumpabsolute);
Con_Print("\n");
}
-void PRVM_PrintFunctionStatements (const char *name)
+void PRVM_PrintFunctionStatements (prvm_prog_t *prog, const char *name)
{
int i, firststatement, endstatement;
mfunction_t *func;
- func = PRVM_ED_FindFunction (name);
+ func = PRVM_ED_FindFunction (prog, name);
if (!func)
{
- Con_Printf("%s progs: no function named %s\n", PRVM_NAME, name);
+ Con_Printf("%s progs: no function named %s\n", prog->name, name);
return;
}
firststatement = func->first_statement;
if (firststatement < 0)
{
- Con_Printf("%s progs: function %s is builtin #%i\n", PRVM_NAME, name, -firststatement);
+ Con_Printf("%s progs: function %s is builtin #%i\n", prog->name, name, -firststatement);
return;
}
endstatement = prog->functions[i].first_statement;
// now print the range of statements
- Con_Printf("%s progs: disassembly of function %s (statements %i-%i, locals %i-%i):\n", PRVM_NAME, name, firststatement, endstatement, func->parm_start, func->parm_start + func->locals - 1);
+ Con_Printf("%s progs: disassembly of function %s (statements %i-%i, locals %i-%i):\n", prog->name, name, firststatement, endstatement, func->parm_start, func->parm_start + func->locals - 1);
+ prog->xfunction = func;
for (i = firststatement;i < endstatement;i++)
{
- PRVM_PrintStatement(prog->statements + i);
+ PRVM_PrintStatement(prog, prog->statements + i);
prog->statement_profile[i] = 0;
}
}
*/
void PRVM_PrintFunction_f (void)
{
+ prvm_prog_t *prog;
if (Cmd_Argc() != 3)
{
Con_Printf("usage: prvm_printfunction <program name> <function name>\n");
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- PRVM_PrintFunctionStatements(Cmd_Argv(2));
-
- PRVM_End;
+ PRVM_PrintFunctionStatements(prog, Cmd_Argv(2));
}
/*
PRVM_StackTrace
============
*/
-void PRVM_StackTrace (void)
+void PRVM_StackTrace (prvm_prog_t *prog)
{
mfunction_t *f;
int i;
if (!f)
Con_Print("<NULL FUNCTION>\n");
else
- Con_Printf("%12s : %s : statement %i\n", PRVM_GetString(f->s_file), PRVM_GetString(f->s_name), prog->stack[i].s - f->first_statement);
+ Con_Printf("%12s : %s : statement %i\n", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement);
}
}
-void PRVM_ShortStackTrace(char *buf, size_t bufsize)
+void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize)
{
mfunction_t *f;
int i;
+ char vabuf[1024];
if(prog)
{
if(strlcat(buf,
f
- ? va("%s:%s(%i) ", PRVM_GetString(f->s_file), PRVM_GetString(f->s_name), prog->stack[i].s - f->first_statement)
+ ? va(vabuf, sizeof(vabuf), "%s:%s(%i) ", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement)
: "<NULL> ",
bufsize
) >= bufsize)
}
-void PRVM_CallProfile (void)
+static void PRVM_CallProfile (prvm_prog_t *prog)
{
mfunction_t *f, *best;
int i;
double max;
double sum;
+ double newprofiletime;
- Con_Printf( "%s Call Profile:\n", PRVM_NAME );
+ Con_Printf( "%s Call Profile:\n", prog->name );
sum = 0;
do
if (best)
{
sum += best->totaltime;
- Con_Printf("%9.4f %s\n", best->totaltime, PRVM_GetString(best->s_name));
+ Con_Printf("%9.4f %s\n", best->totaltime, PRVM_GetString(prog, best->s_name));
best->totaltime = 0;
}
} while (best);
- Con_Printf("Total time since last profile reset: %9.4f\n", Sys_DoubleTime() - prog->starttime);
+ newprofiletime = Sys_DirtyTime();
+ Con_Printf("Total time since last profile reset: %9.4f\n", newprofiletime - prog->profiletime);
Con_Printf(" - used by QC code of this VM: %9.4f\n", sum);
- prog->starttime = Sys_DoubleTime();
+ prog->profiletime = newprofiletime;
}
-void PRVM_Profile (int maxfunctions, double mintime, int sortby)
+void PRVM_Profile (prvm_prog_t *prog, int maxfunctions, double mintime, int sortby)
{
mfunction_t *f, *best;
int i, num;
mintime *= 10000000; // count each statement as about 0.1µs
if(prvm_timeprofiling.integer)
- Con_Printf( "%s Profile:\n[CallCount] [Time] [BuiltinTm] [Statement] [BuiltinCt] [TimeTotal] [StmtTotal] [BltnTotal] [self]\n", PRVM_NAME );
+ Con_Printf( "%s Profile:\n[CallCount] [Time] [BuiltinTm] [Statement] [BuiltinCt] [TimeTotal] [StmtTotal] [BltnTotal] [self]\n", prog->name );
// 12345678901 12345678901 12345678901 12345678901 12345678901 12345678901 12345678901 123.45%
else
- Con_Printf( "%s Profile:\n[CallCount] [Statement] [BuiltinCt] [StmtTotal] [BltnTotal] [self]\n", PRVM_NAME );
+ Con_Printf( "%s Profile:\n[CallCount] [Statement] [BuiltinCt] [StmtTotal] [BltnTotal] [self]\n", prog->name );
// 12345678901 12345678901 12345678901 12345678901 12345678901 123.45%
num = 0;
if(prvm_timeprofiling.integer)
{
if (best->first_statement < 0)
- Con_Printf("%11.0f %11.6f ------------- builtin ------------- %11.6f ----------- builtin ----------- %s\n", best->callcount, best->tprofile, best->tprofile, PRVM_GetString(best->s_name));
+ Con_Printf("%11.0f %11.6f ------------- builtin ------------- %11.6f ----------- builtin ----------- %s\n", best->callcount, best->tprofile, best->tprofile, PRVM_GetString(prog, best->s_name));
// %11.6f 12345678901 12345678901 12345678901 %11.6f 12345678901 12345678901 123.45%
else
- Con_Printf("%11.0f %11.6f %11.6f %11.0f %11.0f %11.6f %11.0f %11.0f %6.2f%% %s\n", best->callcount, best->tprofile, best->tbprofile, best->profile, best->builtinsprofile, best->tprofile_total, best->profile_total, best->builtinsprofile_total, (best->tprofile_total > 0) ? ((best->tprofile) * 100.0 / (best->tprofile_total)) : -99.99, PRVM_GetString(best->s_name));
+ Con_Printf("%11.0f %11.6f %11.6f %11.0f %11.0f %11.6f %11.0f %11.0f %6.2f%% %s\n", best->callcount, best->tprofile, best->tbprofile, best->profile, best->builtinsprofile, best->tprofile_total, best->profile_total, best->builtinsprofile_total, (best->tprofile_total > 0) ? ((best->tprofile) * 100.0 / (best->tprofile_total)) : -99.99, PRVM_GetString(prog, best->s_name));
}
else
{
if (best->first_statement < 0)
- Con_Printf("%11.0f ----------------------- builtin ----------------------- %s\n", best->callcount, PRVM_GetString(best->s_name));
+ Con_Printf("%11.0f ----------------------- builtin ----------------------- %s\n", best->callcount, PRVM_GetString(prog, best->s_name));
// 12345678901 12345678901 12345678901 12345678901 123.45%
else
- Con_Printf("%11.0f %11.0f %11.0f %11.0f %11.0f %6.2f%% %s\n", best->callcount, best->profile, best->builtinsprofile, best->profile_total, best->builtinsprofile_total, (best->profile + best->builtinsprofile) * 100.0 / (best->profile_total + best->builtinsprofile_total), PRVM_GetString(best->s_name));
+ Con_Printf("%11.0f %11.0f %11.0f %11.0f %11.0f %6.2f%% %s\n", best->callcount, best->profile, best->builtinsprofile, best->profile_total, best->builtinsprofile_total, (best->profile + best->builtinsprofile) * 100.0 / (best->profile_total + best->builtinsprofile_total), PRVM_GetString(prog, best->s_name));
}
}
num++;
*/
void PRVM_CallProfile_f (void)
{
+ prvm_prog_t *prog;
if (Cmd_Argc() != 2)
{
Con_Print("prvm_callprofile <program name>\n");
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- PRVM_CallProfile();
-
- PRVM_End;
+ PRVM_CallProfile(prog);
}
/*
*/
void PRVM_Profile_f (void)
{
+ prvm_prog_t *prog;
int howmany;
howmany = 1<<30;
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- PRVM_Profile(howmany, 0, 0);
-
- PRVM_End;
+ PRVM_Profile(prog, howmany, 0, 0);
}
void PRVM_ChildProfile_f (void)
{
+ prvm_prog_t *prog;
int howmany;
howmany = 1<<30;
return;
}
- PRVM_Begin;
- if(!PRVM_SetProgFromString(Cmd_Argv(1)))
+ if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1))))
return;
- PRVM_Profile(howmany, 0, 1);
-
- PRVM_End;
+ PRVM_Profile(prog, howmany, 0, 1);
}
-void PRVM_CrashAll(void)
+void PRVM_PrintState(prvm_prog_t *prog)
{
int i;
- prvm_prog_t *oldprog = prog;
-
- for(i = 0; i < PRVM_MAXPROGS; i++)
- {
- if(!PRVM_ProgLoaded(i))
- continue;
- PRVM_SetProg(i);
- PRVM_Crash();
- }
-
- prog = oldprog;
-}
-
-void PRVM_PrintState(void)
-{
- int i;
- if(prog->statestring)
+ if (prog->statestring)
{
Con_Printf("Caller-provided information: %s\n", prog->statestring);
}
{
for (i = -7; i <= 0;i++)
if (prog->xstatement + i >= prog->xfunction->first_statement)
- PRVM_PrintStatement (prog->statements + prog->xstatement + i);
+ PRVM_PrintStatement(prog, prog->statements + prog->xstatement + i);
}
else
Con_Print("null function executing??\n");
- PRVM_StackTrace ();
+ PRVM_StackTrace(prog);
}
-extern sizebuf_t vm_tempstringsbuf;
extern cvar_t prvm_errordump;
-void Host_Savegame_to (const char *name);
-void PRVM_Crash(void)
+void PRVM_Crash(prvm_prog_t *prog)
{
+ char vabuf[1024];
if (prog == NULL)
return;
+ if (!prog->loaded)
+ return;
PRVM_serverfunction(SV_Shutdown) = 0; // don't call SV_Shutdown on crash
if( prog->depth > 0 )
{
- Con_Printf("QuakeC crash report for %s:\n", PRVM_NAME);
- PRVM_PrintState();
+ Con_Printf("QuakeC crash report for %s:\n", prog->name);
+ PRVM_PrintState(prog);
}
if(prvm_errordump.integer)
{
// make a savegame
- Host_Savegame_to(va("crash-%s.dmp", PRVM_NAME));
+ Host_Savegame_to(prog, va(vabuf, sizeof(vabuf), "crash-%s.dmp", prog->name));
}
// dump the stack so host_error can shutdown functions
prog->localstack_used = 0;
// delete all tempstrings (FIXME: is this safe in VM->engine->VM recursion?)
- vm_tempstringsbuf.cursize = 0;
+ prog->tempstringsbuf.cursize = 0;
// reset the prog pointer
prog = NULL;
Returns the new program statement counter
====================
*/
-int PRVM_EnterFunction (mfunction_t *f)
+static int PRVM_EnterFunction (prvm_prog_t *prog, mfunction_t *f)
{
int i, j, c, o;
if (!f)
- PRVM_ERROR ("PRVM_EnterFunction: NULL function in %s", PRVM_NAME);
+ prog->error_cmd("PRVM_EnterFunction: NULL function in %s", prog->name);
prog->stack[prog->depth].s = prog->xstatement;
prog->stack[prog->depth].f = prog->xfunction;
prog->stack[prog->depth].builtinsprofile_acc = -f->builtinsprofile;
prog->depth++;
if (prog->depth >=PRVM_MAX_STACK_DEPTH)
- PRVM_ERROR ("stack overflow");
+ prog->error_cmd("stack overflow");
// save off any locals that the new function steps on
c = f->locals;
if (prog->localstack_used + c > PRVM_LOCALSTACK_SIZE)
- PRVM_ERROR ("PRVM_ExecuteProgram: locals stack overflow in %s", PRVM_NAME);
+ prog->error_cmd("PRVM_ExecuteProgram: locals stack overflow in %s", prog->name);
for (i=0 ; i < c ; i++)
prog->localstack[prog->localstack_used+i] = ((int *)prog->globals.generic)[f->parm_start + i];
PRVM_LeaveFunction
====================
*/
-int PRVM_LeaveFunction (void)
+static int PRVM_LeaveFunction (prvm_prog_t *prog)
{
int i, c;
mfunction_t *f;
if (prog->depth <= 0)
- PRVM_ERROR ("prog stack underflow in %s", PRVM_NAME);
+ prog->error_cmd("prog stack underflow in %s", prog->name);
if (!prog->xfunction)
- PRVM_ERROR ("PR_LeaveFunction: NULL function in %s", PRVM_NAME);
+ prog->error_cmd("PR_LeaveFunction: NULL function in %s", prog->name);
// restore locals from the stack
c = prog->xfunction->locals;
prog->localstack_used -= c;
if (prog->localstack_used < 0)
- PRVM_ERROR ("PRVM_ExecuteProgram: locals stack underflow in %s", PRVM_NAME);
+ prog->error_cmd("PRVM_ExecuteProgram: locals stack underflow in %s", prog->name);
for (i=0 ; i < c ; i++)
((int *)prog->globals.generic)[prog->xfunction->parm_start + i] = prog->localstack[prog->localstack_used+i];
return prog->stack[prog->depth].s;
}
-void PRVM_Init_Exec(void)
+void PRVM_Init_Exec(prvm_prog_t *prog)
{
// dump the stack
prog->depth = 0;
#define OPC ((prvm_eval_t *)&prog->globals.generic[st->operand[2]])
extern cvar_t prvm_traceqc;
extern cvar_t prvm_statementprofiling;
-extern sizebuf_t vm_tempstringsbuf;
extern qboolean prvm_runawaycheck;
#ifdef PROFILING
MVM_ExecuteProgram
====================
*/
-void MVM_ExecuteProgram (func_t fnum, const char *errormessage)
+void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
{
mstatement_t *st, *startst;
mfunction_t *f, *newf;
double calltime;
double tm, starttm;
- calltime = Sys_DoubleTime();
+ calltime = Sys_DirtyTime();
if (!fnum || fnum >= (unsigned int)prog->numfunctions)
{
if (PRVM_allglobaledict(self))
- PRVM_ED_Print(PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)), NULL);
- PRVM_ERROR ("MVM_ExecuteProgram: %s", errormessage);
+ PRVM_ED_Print(prog, PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)), NULL);
+ prog->error_cmd("MVM_ExecuteProgram: %s", errormessage);
}
f = &prog->functions[fnum];
// after executing this function, delete all tempstrings it created
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
prog->trace = prvm_traceqc.integer;
exitdepth = prog->depth;
// make a stack frame
- st = &prog->statements[PRVM_EnterFunction (f)];
+ st = &prog->statements[PRVM_EnterFunction(prog, f)];
// save the starting statement pointer for profiling
// (when the function exits or jumps, the (st - startst) integer value is
// added to the function's profile counter)
}
cleanup:
- if (developer_insane.integer && vm_tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
- Con_DPrintf("MVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog->functions[fnum].s_name), vm_tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
+ if (developer_insane.integer && prog->tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
+ Con_DPrintf("MVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog, prog->functions[fnum].s_name), prog->tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
// delete tempstrings created by this function
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
- f->totaltime += (Sys_DoubleTime() - calltime);
+ tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0;
+ f->totaltime += tm;
- SV_FlushBroadcastMessages();
+ if (prog == SVVM_prog)
+ SV_FlushBroadcastMessages();
}
/*
CLVM_ExecuteProgram
====================
*/
-void CLVM_ExecuteProgram (func_t fnum, const char *errormessage)
+void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
{
mstatement_t *st, *startst;
mfunction_t *f, *newf;
double calltime;
double tm, starttm;
- calltime = Sys_DoubleTime();
+ calltime = Sys_DirtyTime();
if (!fnum || fnum >= (unsigned int)prog->numfunctions)
{
if (PRVM_allglobaledict(self))
- PRVM_ED_Print(PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)), NULL);
- PRVM_ERROR ("CLVM_ExecuteProgram: %s", errormessage);
+ PRVM_ED_Print(prog, PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)), NULL);
+ prog->error_cmd("CLVM_ExecuteProgram: %s", errormessage);
}
f = &prog->functions[fnum];
// after executing this function, delete all tempstrings it created
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
prog->trace = prvm_traceqc.integer;
exitdepth = prog->depth;
// make a stack frame
- st = &prog->statements[PRVM_EnterFunction (f)];
+ st = &prog->statements[PRVM_EnterFunction(prog, f)];
// save the starting statement pointer for profiling
// (when the function exits or jumps, the (st - startst) integer value is
// added to the function's profile counter)
}
cleanup:
- if (developer_insane.integer && vm_tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
- Con_DPrintf("CLVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog->functions[fnum].s_name), vm_tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
+ if (developer_insane.integer && prog->tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
+ Con_DPrintf("CLVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog, prog->functions[fnum].s_name), prog->tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
// delete tempstrings created by this function
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
- f->totaltime += (Sys_DoubleTime() - calltime);
+ tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0;
+ f->totaltime += tm;
- SV_FlushBroadcastMessages();
+ if (prog == SVVM_prog)
+ SV_FlushBroadcastMessages();
}
#endif
SVVM_ExecuteProgram
====================
*/
-void SVVM_ExecuteProgram (func_t fnum, const char *errormessage)
+#ifdef PROFILING
+void SVVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
+#else
+void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
+#endif
{
mstatement_t *st, *startst;
mfunction_t *f, *newf;
double calltime;
double tm, starttm;
- calltime = Sys_DoubleTime();
+ calltime = Sys_DirtyTime();
if (!fnum || fnum >= (unsigned int)prog->numfunctions)
{
if (PRVM_allglobaledict(self))
- PRVM_ED_Print(PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)), NULL);
- PRVM_ERROR ("SVVM_ExecuteProgram: %s", errormessage);
+ PRVM_ED_Print(prog, PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)), NULL);
+ prog->error_cmd("SVVM_ExecuteProgram: %s", errormessage);
}
f = &prog->functions[fnum];
// after executing this function, delete all tempstrings it created
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
prog->trace = prvm_traceqc.integer;
exitdepth = prog->depth;
// make a stack frame
- st = &prog->statements[PRVM_EnterFunction (f)];
+ st = &prog->statements[PRVM_EnterFunction(prog, f)];
// save the starting statement pointer for profiling
// (when the function exits or jumps, the (st - startst) integer value is
// added to the function's profile counter)
}
cleanup:
- if (developer_insane.integer && vm_tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
- Con_DPrintf("SVVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog->functions[fnum].s_name), vm_tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
+ if (developer_insane.integer && prog->tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
+ Con_DPrintf("SVVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog, prog->functions[fnum].s_name), prog->tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
// delete tempstrings created by this function
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
- f->totaltime += (Sys_DoubleTime() - calltime);
+ tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0;
+ f->totaltime += tm;
- SV_FlushBroadcastMessages();
+ if (prog == SVVM_prog)
+ SV_FlushBroadcastMessages();
}
#ifdef PRVMTIMEPROFILING
#define PreError() \
prog->xstatement = st - prog->statements; \
- tm = Sys_DoubleTime(); \
+ tm = Sys_DirtyTime(); \
prog->xfunction->profile += (st - startst); \
- prog->xfunction->tprofile += (tm - starttm);
+ prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
#else
#define PreError() \
prog->xstatement = st - prog->statements; \
#if PRVMSLOWINTERPRETER
if (prog->trace)
- PRVM_PrintStatement(st);
+ PRVM_PrintStatement(prog, st);
prog->statement_profile[st - prog->statements]++;
#endif
prog->xfunction->profile += (st - startst);
startst = st;
prog->xstatement = st - prog->statements;
- VM_Warning( "Attempted division by zero in %s\n", PRVM_NAME );
+ VM_Warning(prog, "Attempted division by zero in %s\n", prog->name );
}
OPC->_float = 0.0f;
}
OPC->_float = !OPA->vector[0] && !OPA->vector[1] && !OPA->vector[2];
break;
case OP_NOT_S:
- OPC->_float = !OPA->string || !*PRVM_GetString(OPA->string);
+ OPC->_float = !OPA->string || !*PRVM_GetString(prog, OPA->string);
break;
case OP_NOT_FNC:
OPC->_float = !OPA->function;
OPC->_float = (OPA->vector[0] == OPB->vector[0]) && (OPA->vector[1] == OPB->vector[1]) && (OPA->vector[2] == OPB->vector[2]);
break;
case OP_EQ_S:
- OPC->_float = !strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
+ OPC->_float = !strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
break;
case OP_EQ_E:
OPC->_float = OPA->_int == OPB->_int;
OPC->_float = (OPA->vector[0] != OPB->vector[0]) || (OPA->vector[1] != OPB->vector[1]) || (OPA->vector[2] != OPB->vector[2]);
break;
case OP_NE_S:
- OPC->_float = strcmp(PRVM_GetString(OPA->string),PRVM_GetString(OPB->string));
+ OPC->_float = strcmp(PRVM_GetString(prog, OPA->string),PRVM_GetString(prog, OPB->string));
break;
case OP_NE_E:
OPC->_float = OPA->_int != OPB->_int;
if (OPB->_int < 0 || OPB->_int + 1 > prog->entityfieldsarea)
{
PreError();
- PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
+ prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, OPB->_int);
goto cleanup;
}
if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
{
prog->xstatement = st - prog->statements;
- VM_Warning("assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(OPB->_int)->s_name), OPB->_int, PRVM_NAME);
+ VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), OPB->_int, prog->name);
}
ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
ptr->_int = OPA->_int;
if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfieldsarea)
{
PreError();
- PRVM_ERROR("%s attempted to write to an out of bounds edict (%i)", PRVM_NAME, OPB->_int);
+ prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, OPB->_int);
goto cleanup;
}
if (OPB->_int < prog->entityfields && !prog->allowworldwrites)
{
prog->xstatement = st - prog->statements;
- VM_Warning("assignment to world.%s (field %i) in %s\n", PRVM_GetString(PRVM_ED_FieldAtOfs(OPB->_int)->s_name), OPB->_int, PRVM_NAME);
+ VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), OPB->_int, prog->name);
}
ptr = (prvm_eval_t *)(prog->edictsfields + OPB->_int);
ptr->ivector[0] = OPA->ivector[0];
if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to address an out of bounds edict number", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to address an out of bounds edict number", prog->name);
goto cleanup;
}
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
{
PreError();
- PRVM_ERROR("%s attempted to address an invalid field (%i) in an edict", PRVM_NAME, OPB->_int);
+ prog->error_cmd("%s attempted to address an invalid field (%i) in an edict", prog->name, OPB->_int);
goto cleanup;
}
#if 0
if (OPA->edict == 0 && !prog->allowworldwrites)
{
PreError();
- PRVM_ERROR("forbidden assignment to null/world entity in %s", PRVM_NAME);
+ prog->error_cmd("forbidden assignment to null/world entity in %s", prog->name);
goto cleanup;
}
#endif
if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name);
goto cleanup;
}
if ((unsigned int)(OPB->_int) >= (unsigned int)(prog->entityfields))
{
PreError();
- PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
+ prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, OPB->_int);
goto cleanup;
}
ed = PRVM_PROG_TO_EDICT(OPA->edict);
if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name);
goto cleanup;
}
if (OPB->_int < 0 || OPB->_int + 2 >= prog->entityfields)
{
PreError();
- PRVM_ERROR("%s attempted to read an invalid field in an edict (%i)", PRVM_NAME, OPB->_int);
+ prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, OPB->_int);
goto cleanup;
}
ed = PRVM_PROG_TO_EDICT(OPA->edict);
if (++jumpcount == 10000000 && prvm_runawaycheck)
{
prog->xstatement = st - prog->statements;
- PRVM_Profile(1<<30, 1000000, 0);
- PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
+ PRVM_Profile(prog, 1<<30, 1000000, 0);
+ prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
}
}
break;
if (++jumpcount == 10000000 && prvm_runawaycheck)
{
prog->xstatement = st - prog->statements;
- PRVM_Profile(1<<30, 0.01, 0);
- PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
+ PRVM_Profile(prog, 1<<30, 0.01, 0);
+ prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
}
}
break;
if (++jumpcount == 10000000 && prvm_runawaycheck)
{
prog->xstatement = st - prog->statements;
- PRVM_Profile(1<<30, 0.01, 0);
- PRVM_ERROR("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", PRVM_NAME, jumpcount);
+ PRVM_Profile(prog, 1<<30, 0.01, 0);
+ prog->error_cmd("%s runaway loop counter hit limit of %d jumps\ntip: read above for list of most-executed functions", prog->name, jumpcount);
}
break;
case OP_CALL7:
case OP_CALL8:
#ifdef PRVMTIMEPROFILING
- tm = Sys_DoubleTime();
- prog->xfunction->tprofile += (tm - starttm);
+ tm = Sys_DirtyTime();
+ prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
starttm = tm;
#endif
prog->xfunction->profile += (st - startst);
prog->xstatement = st - prog->statements;
prog->argc = st->op - OP_CALL0;
if (!OPA->function)
- PRVM_ERROR("NULL function in %s", PRVM_NAME);
+ prog->error_cmd("NULL function in %s", prog->name);
if(!OPA->function || OPA->function >= (unsigned int)prog->numfunctions)
{
PreError();
- PRVM_ERROR("%s CALL outside the program", PRVM_NAME);
+ prog->error_cmd("%s CALL outside the program", prog->name);
goto cleanup;
}
prog->xfunction->builtinsprofile++;
if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
{
- prog->builtins[builtinnumber]();
+ prog->builtins[builtinnumber](prog);
#ifdef PRVMTIMEPROFILING
- tm = Sys_DoubleTime();
- newf->tprofile += (tm - starttm);
- prog->xfunction->tbprofile += (tm - starttm);
+ tm = Sys_DirtyTime();
+ newf->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
+ prog->xfunction->tbprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
starttm = tm;
#endif
}
else
- PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
+ prog->error_cmd("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, prog->name);
}
else
- st = prog->statements + PRVM_EnterFunction(newf);
+ st = prog->statements + PRVM_EnterFunction(prog, newf);
startst = st;
break;
case OP_DONE:
case OP_RETURN:
#ifdef PRVMTIMEPROFILING
- tm = Sys_DoubleTime();
- prog->xfunction->tprofile += (tm - starttm);
+ tm = Sys_DirtyTime();
+ prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0;
starttm = tm;
#endif
prog->xfunction->profile += (st - startst);
prog->globals.generic[OFS_RETURN+1] = prog->globals.generic[st->operand[0]+1];
prog->globals.generic[OFS_RETURN+2] = prog->globals.generic[st->operand[0]+2];
- st = prog->statements + PRVM_LeaveFunction();
+ st = prog->statements + PRVM_LeaveFunction(prog);
startst = st;
if (prog->depth <= exitdepth)
goto cleanup; // all done
{
PreError();
prog->xstatement = st - prog->statements;
- PRVM_ERROR("OP_STATE not supported by %s", PRVM_NAME);
+ prog->error_cmd("OP_STATE not supported by %s", prog->name);
}
break;
if (OPB->_int < 0 || OPB->_int + 4 > pr_edictareasize)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to write to an out of bounds edict", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to write to an out of bounds edict", prog->name);
goto cleanup;
}
#endif
if (OPA->edict < 0 || OPA->edict >= prog->max_edicts)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to read an out of bounds edict number", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name);
goto cleanup;
}
if (OPB->_int < 0 || OPB->_int >= progs->entityfields)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to read an invalid field in an edict", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to read an invalid field in an edict", prog->name);
goto cleanup;
}
#endif
if (OPB->_int < 0 || OPB->_int >= pr_globaldefs)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to write to an invalid indexed global", prog->name);
goto cleanup;
}
#endif
if (OPB->_int < 0 || OPB->_int + 2 >= pr_globaldefs)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to write to an invalid indexed global", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to write to an invalid indexed global", prog->name);
goto cleanup;
}
#endif
if (i < 0 || i >= pr_globaldefs)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to address an out of bounds global", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to address an out of bounds global", prog->name);
goto cleanup;
}
#endif
if (OPA->_int < 0 || OPA->_int >= pr_globaldefs)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to read an invalid indexed global", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to read an invalid indexed global", prog->name);
goto cleanup;
}
#endif
if (OPA->_int < 0 || OPA->_int + 2 >= pr_globaldefs)
{
PreError();
- PRVM_ERROR ("%s Progs attempted to read an invalid indexed global", PRVM_NAME);
+ prog->error_cmd("%s Progs attempted to read an invalid indexed global", prog->name);
goto cleanup;
}
#endif
if (OPA->_int < 0 || OPA->_int >= st->b)
{
PreError();
- PRVM_ERROR ("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", PRVM_NAME, st->b, st->c);
+ prog->error_cmd("%s Progs boundcheck failed at line number %d, value is < 0 or >= %d", prog->name, st->b, st->c);
goto cleanup;
}
break;
default:
PreError();
- PRVM_ERROR ("Bad opcode %i in %s", st->op, PRVM_NAME);
+ prog->error_cmd("Bad opcode %i in %s", st->op, prog->name);
goto cleanup;
}
}
PRVM_DECLARE_clientfieldfloat(lerpfrac3)
PRVM_DECLARE_clientfieldfloat(lerpfrac4)
PRVM_DECLARE_clientfieldfloat(mass)
+PRVM_DECLARE_clientfieldvector(massofs)
+PRVM_DECLARE_clientfieldfloat(friction)
PRVM_DECLARE_clientfieldfloat(modelindex)
PRVM_DECLARE_clientfieldfloat(movetype)
PRVM_DECLARE_clientfieldfloat(nextthink)
PRVM_DECLARE_clientfieldfloat(pitch_speed)
+PRVM_DECLARE_clientfieldfloat(pmove_flags)
PRVM_DECLARE_clientfieldfloat(renderflags)
PRVM_DECLARE_clientfieldfloat(scale)
PRVM_DECLARE_clientfieldfloat(shadertime)
PRVM_DECLARE_clientfieldvector(origin)
PRVM_DECLARE_clientfieldvector(size)
PRVM_DECLARE_clientfieldvector(velocity)
+PRVM_DECLARE_clientfieldvector(modellight_ambient)
+PRVM_DECLARE_clientfieldvector(modellight_diffuse)
+PRVM_DECLARE_clientfieldvector(modellight_dir)
PRVM_DECLARE_clientfunction(CSQC_ConsoleCommand)
PRVM_DECLARE_clientfunction(CSQC_Ent_Remove)
PRVM_DECLARE_clientfunction(CSQC_Ent_Spawn)
PRVM_DECLARE_clientfunction(CSQC_Shutdown)
PRVM_DECLARE_clientfunction(CSQC_UpdateView)
PRVM_DECLARE_clientfunction(GameCommand)
-PRVM_DECLARE_clientfunction(Gecko_Query)
PRVM_DECLARE_clientfunction(URI_Get_Callback)
PRVM_DECLARE_clientglobaledict(other)
PRVM_DECLARE_clientglobaledict(self)
PRVM_DECLARE_clientglobalfloat(drawfont)
PRVM_DECLARE_clientglobalfloat(frametime)
PRVM_DECLARE_clientglobalfloat(gettaginfo_parent)
+PRVM_DECLARE_clientglobalvector(getlight_ambient)
+PRVM_DECLARE_clientglobalvector(getlight_diffuse)
+PRVM_DECLARE_clientglobalvector(getlight_dir)
PRVM_DECLARE_clientglobalfloat(input_buttons)
PRVM_DECLARE_clientglobalfloat(input_timelength)
PRVM_DECLARE_clientglobalfloat(intermission)
PRVM_DECLARE_field(light_lev)
PRVM_DECLARE_field(ltime)
PRVM_DECLARE_field(mass)
+PRVM_DECLARE_field(massofs)
+PRVM_DECLARE_field(friction)
PRVM_DECLARE_field(max_health)
PRVM_DECLARE_field(maxs)
PRVM_DECLARE_field(message)
PRVM_DECLARE_field(playermodel)
PRVM_DECLARE_field(playerskin)
PRVM_DECLARE_field(pmodel)
+PRVM_DECLARE_field(pmove_flags)
PRVM_DECLARE_field(predraw)
PRVM_DECLARE_field(punchangle)
PRVM_DECLARE_field(punchvector)
PRVM_DECLARE_field(userwavefunc_param3)
PRVM_DECLARE_field(v_angle)
PRVM_DECLARE_field(velocity)
+PRVM_DECLARE_field(modellight_ambient)
+PRVM_DECLARE_field(modellight_diffuse)
+PRVM_DECLARE_field(modellight_dir)
PRVM_DECLARE_field(view_ofs)
PRVM_DECLARE_field(viewmodelforclient)
PRVM_DECLARE_field(viewzoom)
PRVM_DECLARE_function(ClientKill)
PRVM_DECLARE_function(EndFrame)
PRVM_DECLARE_function(GameCommand)
-PRVM_DECLARE_function(Gecko_Query)
PRVM_DECLARE_function(PlayerPostThink)
PRVM_DECLARE_function(PlayerPreThink)
PRVM_DECLARE_function(PutClientInServer)
PRVM_DECLARE_global(gettaginfo_parent)
PRVM_DECLARE_global(gettaginfo_right)
PRVM_DECLARE_global(gettaginfo_up)
+PRVM_DECLARE_global(getlight_ambient)
+PRVM_DECLARE_global(getlight_diffuse)
+PRVM_DECLARE_global(getlight_dir)
PRVM_DECLARE_global(input_angles)
PRVM_DECLARE_global(input_buttons)
PRVM_DECLARE_global(input_movevalues)
PRVM_DECLARE_global(worldstatus)
PRVM_DECLARE_menufieldstring(classname)
PRVM_DECLARE_menufunction(GameCommand)
-PRVM_DECLARE_menufunction(Gecko_Query)
PRVM_DECLARE_menufunction(URI_Get_Callback)
PRVM_DECLARE_menufunction(m_draw)
PRVM_DECLARE_menufunction(m_init)
PRVM_DECLARE_serverfieldfloat(light_lev)
PRVM_DECLARE_serverfieldfloat(ltime)
PRVM_DECLARE_serverfieldfloat(mass)
+PRVM_DECLARE_serverfieldvector(massofs)
+PRVM_DECLARE_serverfieldfloat(friction)
PRVM_DECLARE_serverfieldfloat(max_health)
PRVM_DECLARE_serverfieldfloat(modelflags)
PRVM_DECLARE_serverfieldfloat(modelindex)
PRVM_DECLARE_serverglobalvector(trace_plane_normal)
PRVM_DECLARE_serverglobalvector(v_forward)
PRVM_DECLARE_serverglobalvector(v_right)
-PRVM_DECLARE_serverglobalvector(v_up)
\ No newline at end of file
+PRVM_DECLARE_serverglobalvector(v_up)
#define MAX_PARTICLEEFFECTINFO 1024
#define MAX_PARTICLETEXTURES 256
#define MAXCLVIDEOS 1
-#define MAX_GECKO_INSTANCES 1
#define MAX_DYNAMIC_TEXTURE_COUNT 2
#define MAX_MAP_LEAFS 8192
#define MAX_EFFECTS 16
#define MAX_BEAMS 16
#define MAX_TEMPENTITIES 256
+#define SERVERLIST_TOTALSIZE 1024
+#define SERVERLIST_ANDMASKCOUNT 5
+#define SERVERLIST_ORMASKCOUNT 5
#else
#define MAX_INPUTLINE 16384 ///< maximum length of console commandline, QuakeC strings, and many other text processing buffers
#define CON_TEXTSIZE 1048576 ///< max scrollback buffer characters in console
#define MAX_PARTICLEEFFECTINFO 4096 ///< maximum number of unique particle effects (each name may associate with several of these)
#define MAX_PARTICLETEXTURES 256 ///< maximum number of unique particle textures in the particle font
#define MAXCLVIDEOS 65 ///< maximum number of video streams being played back at once (1 is reserved for the playvideo command)
-#define MAX_GECKO_INSTANCES 16 ///< maximum number of web browser textures active at once
#define MAX_DYNAMIC_TEXTURE_COUNT 64 ///< maximum number of dynamic textures (web browsers, playvideo, etc)
#define MAX_MAP_LEAFS 65536 ///< maximum number of BSP leafs in world (8192 in Quake)
#define MAX_EFFECTS 256 ///< limit on size of cl.effects
#define MAX_BEAMS 256 ///< limit on size of cl.beams
#define MAX_TEMPENTITIES 4096 ///< max number of temporary models visible per frame (certain sprite effects, certain types of CSQC entities also use this)
+#define SERVERLIST_TOTALSIZE 2048 ///< max servers in the server list
+#define SERVERLIST_ANDMASKCOUNT 16 ///< max items in server list AND mask
+#define SERVERLIST_ORMASKCOUNT 16 ///< max items in server list OR mask
#endif
#include "keys.h"
#include "console.h"
#include "menu.h"
-
-#include "glquake.h"
-
-#include "palette.h"
+#include "csprogs.h"
extern qboolean noclip_anglehack;
extern cvar_t developer_loadfile;
extern cvar_t developer_loading;
+extern cvar_t sessionid;
+
#define STARTCONFIGFILENAME "quake.rc"
#define CONFIGFILENAME "config.cfg"
#define Sys_HaveSSE2() false
#endif
+#include "glquake.h"
+
+#include "palette.h"
+
/// incremented every frame, never reset
extern int host_framecount;
/// not bounded in any way, changed at start of every frame, never reset
extern double realtime;
+/// equal to Sys_DirtyTime() at the start of this host frame
+extern double host_dirtytime;
void Host_InitCommands(void);
void Host_Main(void);
void Host_ShutdownServer(void);
void Host_Reconnect_f(void);
void Host_NoOperation_f(void);
+void Host_LockSession(void);
+void Host_UnlockSession(void);
void Host_AbortCurrentFrame(void);
R_EntityMatrix(&identitymatrix);
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(explosiontexture, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic(explosiontexture, NULL, GL_MODULATE, 1, false, false, false);
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
const explosion_t *e = explosion + surfacelist[surfacelistindex];
{
R_MoveExplosion(&explosion[i]);
if (explosion[i].alpha)
- R_MeshQueue_AddTransparent(explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, explosion[i].origin, R_DrawExplosion_TransparentCallback, NULL, i, NULL);
}
}
while (numexplosions > 0 && explosion[i-1].alpha <= 0)
int r_lightningbeamelement3i[18] = {0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11};
unsigned short r_lightningbeamelement3s[18] = {0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11};
-void r_lightningbeams_start(void)
+static void r_lightningbeams_start(void)
{
r_lightningbeamtexture = NULL;
r_lightningbeamqmbtexture = NULL;
}
-void r_lightningbeams_setupqmbtexture(void)
+static void r_lightningbeams_setupqmbtexture(void)
{
r_lightningbeamqmbtexture = R_SkinFrame_LoadExternal("textures/particles/lightning.pcx", TEXF_ALPHA | TEXF_FORCELINEAR, false);
if (r_lightningbeamqmbtexture == NULL)
Cvar_SetValueQuick(&r_lightningbeam_qmbtexture, false);
}
-void r_lightningbeams_setuptexture(void)
+static void r_lightningbeams_setuptexture(void)
{
#if 0
#define BEAMWIDTH 128
}
}
- Image_WriteTGABGRA(va("lightningbeam%i.tga", imagenumber), BEAMWIDTH, BEAMHEIGHT, pixels);
+ Image_WriteTGABGRA(va(vabuf, sizeof(vabuf), "lightningbeam%i.tga", imagenumber), BEAMWIDTH, BEAMHEIGHT, pixels);
}
r_lightningbeamtexture = R_LoadTexture2D(r_lightningbeamtexturepool, "lightningbeam", BEAMWIDTH, BEAMHEIGHT, pixels, TEXTYPE_BGRA, TEXF_FORCELINEAR, NULL);
#endif
}
-void r_lightningbeams_shutdown(void)
+static void r_lightningbeams_shutdown(void)
{
r_lightningbeamtexture = NULL;
r_lightningbeamqmbtexture = NULL;
}
-void r_lightningbeams_newmap(void)
+static void r_lightningbeams_newmap(void)
{
if (r_lightningbeamtexture)
R_SkinFrame_MarkUsed(r_lightningbeamtexture);
R_RegisterModule("R_LightningBeams", r_lightningbeams_start, r_lightningbeams_shutdown, r_lightningbeams_newmap, NULL, NULL);
}
-void R_CalcLightningBeamPolygonVertex3f(float *v, const float *start, const float *end, const float *offset)
+static void R_CalcLightningBeamPolygonVertex3f(float *v, const float *start, const float *end, const float *offset)
{
// near right corner
VectorAdd (start, offset, (v + 0));
VectorAdd (end , offset, (v + 9));
}
-void R_CalcLightningBeamPolygonTexCoord2f(float *tc, float t1, float t2)
+static void R_CalcLightningBeamPolygonTexCoord2f(float *tc, float t1, float t2)
{
if (r_lightningbeam_qmbtexture.integer)
{
float beamrepeatscale;
-void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int surfacelistindex;
float vertex3f[12*3];
dist = bound(0, dist, 1);
VectorLerp(start, dist, end, org);
// now we have the nearest point on the line, so sort with it
- R_MeshQueue_AddTransparent(org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL);
}
}
}
extern LPDIRECT3DDEVICE9 vid_d3d9dev;
#endif
-extern void R_Shadow_EditLights_Init(void);
+static void R_Shadow_EditLights_Init(void);
typedef enum r_shadow_rendermode_e
{
rtexture_t *r_shadow_attenuation2dtexture;
rtexture_t *r_shadow_attenuation3dtexture;
skinframe_t *r_shadow_lightcorona;
-rtexture_t *r_shadow_shadowmap2dtexture;
-rtexture_t *r_shadow_shadowmap2dcolortexture;
+rtexture_t *r_shadow_shadowmap2ddepthbuffer;
+rtexture_t *r_shadow_shadowmap2ddepthtexture;
rtexture_t *r_shadow_shadowmapvsdcttexture;
int r_shadow_shadowmapsize; // changes for each light based on distance
int r_shadow_shadowmaplod; // changes for each light based on distance
GLuint r_shadow_prepasslightingdiffusefbo;
int r_shadow_prepass_width;
int r_shadow_prepass_height;
-rtexture_t *r_shadow_prepassgeometrydepthtexture;
-rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
+rtexture_t *r_shadow_prepassgeometrydepthbuffer;
rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
rtexture_t *r_shadow_prepasslightingdiffusetexture;
rtexture_t *r_shadow_prepasslightingspeculartexture;
+// keep track of the provided framebuffer info
+static int r_shadow_fb_fbo;
+static rtexture_t *r_shadow_fb_depthtexture;
+static rtexture_t *r_shadow_fb_colortexture;
+
// lights are reloaded when this changes
char r_shadow_mapname[MAX_QPATH];
// used only for light filters (cubemaps)
rtexturepool_t *r_shadow_filters_texturepool;
-static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
-
cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
cvar_t r_shadow_deferred = {CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"};
-cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "4", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"};
-//cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"};
cvar_t r_shadow_usebihculling = {0, "r_shadow_usebihculling", "1", "use BIH (Bounding Interval Hierarchy) for culling lit surfaces instead of BSP (Binary Space Partitioning)"};
cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
skinframe_t *r_editlights_sprcubemapnoshadowlight;
skinframe_t *r_editlights_sprselection;
-void R_Shadow_SetShadowMode(void)
+static void R_Shadow_SetShadowMode(void)
{
r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4);
r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20;
case RENDERPATH_GL20:
if(r_shadow_shadowmapfilterquality < 0)
{
- if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
+ if (!r_fb.usedepthtextures)
+ r_shadow_shadowmappcf = 1;
+ else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
r_shadow_shadowmappcf = 1;
else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD"))
{
break;
}
}
+ if (!r_fb.usedepthtextures)
+ r_shadow_shadowmapsampler = false;
r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
break;
case RENDERPATH_D3D9:
}
}
-void R_Shadow_FreeShadowMaps(void)
+static void R_Shadow_FreeShadowMaps(void)
{
R_Shadow_SetShadowMode();
r_shadow_fbo2d = 0;
- if (r_shadow_shadowmap2dtexture)
- R_FreeTexture(r_shadow_shadowmap2dtexture);
- r_shadow_shadowmap2dtexture = NULL;
+ if (r_shadow_shadowmap2ddepthtexture)
+ R_FreeTexture(r_shadow_shadowmap2ddepthtexture);
+ r_shadow_shadowmap2ddepthtexture = NULL;
- if (r_shadow_shadowmap2dcolortexture)
- R_FreeTexture(r_shadow_shadowmap2dcolortexture);
- r_shadow_shadowmap2dcolortexture = NULL;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ R_FreeTexture(r_shadow_shadowmap2ddepthbuffer);
+ r_shadow_shadowmap2ddepthbuffer = NULL;
if (r_shadow_shadowmapvsdcttexture)
R_FreeTexture(r_shadow_shadowmapvsdcttexture);
r_shadow_shadowmapvsdcttexture = NULL;
}
-void r_shadow_start(void)
+static void r_shadow_start(void)
{
// allocate vertex processing arrays
r_shadow_bouncegridpixels = NULL;
r_shadow_attenuation2dtexture = NULL;
r_shadow_attenuation3dtexture = NULL;
r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
- r_shadow_shadowmap2dtexture = NULL;
- r_shadow_shadowmap2dcolortexture = NULL;
+ r_shadow_shadowmap2ddepthtexture = NULL;
+ r_shadow_shadowmap2ddepthbuffer = NULL;
r_shadow_shadowmapvsdcttexture = NULL;
r_shadow_shadowmapmaxsize = 0;
r_shadow_shadowmapsize = 0;
}
static void R_Shadow_FreeDeferred(void);
-void r_shadow_shutdown(void)
+static void r_shadow_shutdown(void)
{
CHECKGLERROR
R_Shadow_UncompileWorldLights();
Mem_Free(r_shadow_buffer_lighttrispvs);
}
-void r_shadow_newmap(void)
+static void r_shadow_newmap(void)
{
if (r_shadow_bouncegridtexture) R_FreeTexture(r_shadow_bouncegridtexture);r_shadow_bouncegridtexture = NULL;
if (r_shadow_lightcorona) R_SkinFrame_MarkUsed(r_shadow_lightcorona);
Cvar_RegisterVariable(&r_shadow_usenormalmap);
Cvar_RegisterVariable(&r_shadow_debuglight);
Cvar_RegisterVariable(&r_shadow_deferred);
- Cvar_RegisterVariable(&r_shadow_deferred_8bitrange);
-// Cvar_RegisterVariable(&r_shadow_deferred_fp);
Cvar_RegisterVariable(&r_shadow_gloss);
Cvar_RegisterVariable(&r_shadow_gloss2intensity);
Cvar_RegisterVariable(&r_shadow_glossintensity);
}
};
-void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
+static void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
{
numvertices = ((numvertices + 255) & ~255) * vertscale;
numtriangles = ((numtriangles + 255) & ~255) * triscale;
}
}
-qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
+static qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
{
#if 1
return false;
return mask;
}
-int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
+static int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
{
vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
return mask;
}
-int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
+static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
{
int i;
vec3_t p, n;
void R_Shadow_RenderMode_Reset(void)
{
- R_Mesh_SetMainRenderTargets();
+ R_Mesh_ResetTextureState();
+ R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
R_SetViewport(&r_refdef.view.viewport);
GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
- R_Mesh_ResetTextureState();
GL_DepthRange(0, 1);
GL_DepthTest(true);
GL_DepthMask(false);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
r_shadow_usingshadowmap2d = false;
r_shadow_usingshadowmaportho = false;
R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
GL_ColorMask(0, 0, 0, 0);
GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
GL_CullFace(GL_NONE);
- R_SetupShader_DepthOrShadow(false);
+ R_SetupShader_DepthOrShadow(false, false);
r_shadow_rendermode = mode;
switch(mode)
{
switch (r_shadow_shadowmode)
{
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
- if (r_shadow_shadowmap2dtexture) return;
- r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
- r_shadow_shadowmap2dcolortexture = NULL;
- switch(vid.renderpath)
+ if (r_shadow_shadowmap2ddepthtexture) return;
+ if (r_fb.usedepthtextures)
{
-#ifdef SUPPORTD3D
- case RENDERPATH_D3D9:
- r_shadow_shadowmap2dcolortexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_BGRA, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
- r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
- break;
-#endif
- default:
- r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, NULL, NULL, NULL, NULL);
- break;
+ r_shadow_shadowmap2ddepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP24_COMP : TEXTYPE_SHADOWMAP24_RAW) : (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP16_COMP : TEXTYPE_SHADOWMAP16_RAW), false);
+ r_shadow_shadowmap2ddepthbuffer = NULL;
+ r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ r_shadow_shadowmap2ddepthtexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
+ r_shadow_shadowmap2ddepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? TEXTYPE_DEPTHBUFFER24 : TEXTYPE_DEPTHBUFFER16);
+ r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
}
break;
default:
return;
}
-
- // render depth into the fbo, do not render color at all
- // validate the fbo now
- if (qglDrawBuffer)
- {
- int status;
- qglDrawBuffer(GL_NONE);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
- {
- Con_Printf("R_Shadow_MakeShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- }
- }
}
-void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
+static void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
{
float nearclip, farclip, bias;
r_viewport_t viewport;
int flipped;
- GLuint fbo = 0;
+ GLuint fbo2d = 0;
float clearcolor[4];
nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
farclip = 1.0f;
// complex unrolled cube approach (more flexible)
if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
R_Shadow_MakeVSDCT();
- if (!r_shadow_shadowmap2dtexture)
+ if (!r_shadow_shadowmap2ddepthtexture)
R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
- if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
- r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
- r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
+ fbo2d = r_shadow_fbo2d;
+ r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture);
+ r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture);
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
R_Mesh_ResetTextureState();
R_Shadow_RenderMode_Reset();
- R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true);
+ if (r_shadow_shadowmap2ddepthbuffer)
+ R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
+ else
+ R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL);
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
flipped = (side & 1) ^ (side >> 2);
r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ {
+ // completely different meaning than in depthtexture approach
+ r_shadow_shadowmap_parameters[1] = 0;
+ r_shadow_shadowmap_parameters[3] = -bias;
+ }
+ Vector4Set(clearcolor, 1,1,1,1);
+ if (r_shadow_shadowmap2ddepthbuffer)
+ GL_ColorMask(1,1,1,1);
+ else
+ GL_ColorMask(0,0,0,0);
switch(vid.renderpath)
{
case RENDERPATH_GL11:
int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size);
int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size);
GL_Scissor(x1, y1, x2 - x1, y2 - y1);
- GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
+ if (clear)
+ {
+ if (r_shadow_shadowmap2ddepthbuffer)
+ GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
+ else
+ GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
+ }
}
GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
- Vector4Set(clearcolor, 1,1,1,1);
- // completely different meaning than in OpenGL path
- r_shadow_shadowmap_parameters[1] = 0;
- r_shadow_shadowmap_parameters[3] = -bias;
// we invert the cull mode because we flip the projection matrix
// NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
GL_CullFace(r_refdef.view.cullface_front);
// D3D considers it an error to use a scissor larger than the viewport... clear just this view
GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
- if (r_shadow_shadowmapsampler)
- {
- GL_ColorMask(0,0,0,0);
- if (clear)
- GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
- }
- else
+ if (clear)
{
- GL_ColorMask(1,1,1,1);
- if (clear)
+ if (r_shadow_shadowmap2ddepthbuffer)
GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
+ else
+ GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
}
break;
}
void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
{
R_Mesh_ResetTextureState();
- R_Mesh_SetMainRenderTargets();
if (transparent)
{
r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
// stencil is 128 (values other than this mean shadow)
R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
if (rsurface.rtlight->specularscale > 0 && r_shadow_gloss.integer > 0)
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
else
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
r_shadow_usingshadowmap2d = shadowmapping;
r_refdef.stats.bouncegrid_traces++;
//r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
//r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
- //if (settings.staticmode)
- // Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask, true);
- //else
+ if (settings.staticmode)
+ {
+ // static mode fires a LOT of rays but none of them are identical, so they are not cached
cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, true, false, NULL, true, true);
+ }
+ else
+ {
+ // dynamic mode fires many rays and most will match the cache from the previous frame
+ cliptrace = CL_Cache_TraceLineSurfaces(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), hitsupercontentsmask);
+ }
if (bouncecount > 0 || settings.includedirectlighting)
{
// calculate second order spherical harmonics values (average, slopeX, slopeY, slopeZ)
int *newe;
const int *e;
float *c;
- int maxtriangles = 4096;
- static int newelements[4096*3];
+ int maxtriangles = 1024;
+ int newelements[1024*3];
R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2);
for (renders = 0;renders < 4;renders++)
{
qboolean negated;
float lightcolor[3];
VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
- ambientscale = rsurface.rtlight->ambientscale;
- diffusescale = rsurface.rtlight->diffusescale;
+ ambientscale = rsurface.rtlight->ambientscale + rsurface.texture->rtlightambient;
+ diffusescale = rsurface.rtlight->diffusescale * max(0, 1.0 - rsurface.texture->rtlightambient);
specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
if (!r_shadow_usenormalmap.integer)
{
}
}
-void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
+static void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
{
int i, j;
mplane_t plane;
#endif
}
-void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
+static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
{
shadowmesh_t *mesh;
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
+static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
{
qboolean zpass = false;
shadowmesh_t *mesh;
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-void R_Shadow_DrawEntityShadow(entity_render_t *ent)
+static void R_Shadow_DrawEntityShadow(entity_render_t *ent)
{
vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
vec_t relativeshadowradius;
Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, rsurface.entitylightorigin);
}
-void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
+static void R_Shadow_DrawWorldLight(int numsurfaces, int *surfacelist, const unsigned char *lighttrispvs)
{
if (!r_refdef.scene.worldmodel->DrawLight)
return;
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-void R_Shadow_DrawEntityLight(entity_render_t *ent)
+static void R_Shadow_DrawEntityLight(entity_render_t *ent)
{
dp_model_t *model = ent->model;
if (!model->DrawLight)
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-void R_Shadow_PrepareLight(rtlight_t *rtlight)
+static void R_Shadow_PrepareLight(rtlight_t *rtlight)
{
int i;
float f;
}
}
-void R_Shadow_DrawLight(rtlight_t *rtlight)
+static void R_Shadow_DrawLight(rtlight_t *rtlight)
{
int i;
int numsurfaces;
R_Mesh_DestroyFramebufferObject(r_shadow_prepasslightingdiffusefbo);
r_shadow_prepasslightingdiffusefbo = 0;
- if (r_shadow_prepassgeometrydepthtexture)
- R_FreeTexture(r_shadow_prepassgeometrydepthtexture);
- r_shadow_prepassgeometrydepthtexture = NULL;
-
- if (r_shadow_prepassgeometrydepthcolortexture)
- R_FreeTexture(r_shadow_prepassgeometrydepthcolortexture);
- r_shadow_prepassgeometrydepthcolortexture = NULL;
+ if (r_shadow_prepassgeometrydepthbuffer)
+ R_FreeTexture(r_shadow_prepassgeometrydepthbuffer);
+ r_shadow_prepassgeometrydepthbuffer = NULL;
if (r_shadow_prepassgeometrynormalmaptexture)
R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(1,1,1,1);
GL_DepthTest(true);
- R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
Vector4Set(clearcolor, 0.5f,0.5f,0.5f,1.0f);
GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
if (r_timereport_active)
GL_ColorMask(1,1,1,1);
GL_Color(1,1,1,1);
GL_DepthTest(true);
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
Vector4Set(clearcolor, 0, 0, 0, 0);
GL_Clear(GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
if (r_timereport_active)
if (r_refdef.scene.lights[lnum]->draw)
R_Shadow_DrawLight(r_refdef.scene.lights[lnum]);
- R_Mesh_SetMainRenderTargets();
-
R_Shadow_RenderMode_End();
if (r_timereport_active)
}
void R_Shadow_DrawLightSprites(void);
-void R_Shadow_PrepareLights(void)
+void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
int flag;
int lnum;
dlight_t *light;
size_t range;
float f;
- GLenum status;
if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4) ||
(r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) ||
r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
R_Shadow_FreeShadowMaps();
+ r_shadow_fb_fbo = fbo;
+ r_shadow_fb_depthtexture = depthtexture;
+ r_shadow_fb_colortexture = colortexture;
+
r_shadow_usingshadowmaportho = false;
switch (vid.renderpath)
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
case RENDERPATH_SOFT:
- case RENDERPATH_GLES2:
+#ifndef USE_GLES2
if (!r_shadow_deferred.integer || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_STENCIL || !vid.support.ext_framebuffer_object || vid.maxdrawbuffers < 2)
{
r_shadow_usingdeferredprepass = false;
r_shadow_usingdeferredprepass = true;
r_shadow_prepass_width = vid.width;
r_shadow_prepass_height = vid.height;
- r_shadow_prepassgeometrydepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "prepassgeometrydepthmap", vid.width, vid.height, 24, false);
- switch (vid.renderpath)
- {
- case RENDERPATH_D3D9:
- r_shadow_prepassgeometrydepthcolortexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrydepthcolormap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- break;
- default:
- break;
- }
- r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24);
+ r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
// set up the geometry pass fbo (depth + normalmap)
- r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
- R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL);
- // render depth into one texture and normalmap into the other
- if (qglDrawBuffersARB)
- {
- qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- r_shadow_usingdeferredprepass = false;
- }
- }
+ r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
+ // render depth into a renderbuffer and other important properties into the normalmap texture
// set up the lighting pass fbo (diffuse + specular)
- r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
// render diffuse into one texture and specular into another,
// with depth and normalmap bound as textures,
// with depth bound as attachment as well
- if (qglDrawBuffersARB)
- {
- qglDrawBuffersARB(2, r_shadow_prepasslightingdrawbuffers);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- r_shadow_usingdeferredprepass = false;
- }
- }
// set up the lighting pass fbo (diffuse)
- r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
+ r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
// render diffuse into one texture,
// with depth and normalmap bound as textures,
// with depth bound as attachment as well
- if (qglDrawBuffersARB)
- {
- qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- r_shadow_usingdeferredprepass = false;
- }
- }
}
+#endif
break;
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
r_shadow_usingdeferredprepass = false;
break;
}
R_Shadow_RenderMode_End();
}
-extern const float r_screenvertex3f[12];
-extern void R_SetupView(qboolean allowwaterclippingplane);
-extern void R_ResetViewRendering3D(void);
-extern void R_ResetViewRendering2D(void);
-extern cvar_t r_shadows;
-extern cvar_t r_shadows_darken;
-extern cvar_t r_shadows_drawafterrtlighting;
-extern cvar_t r_shadows_castfrombmodels;
-extern cvar_t r_shadows_throwdistance;
-extern cvar_t r_shadows_throwdirection;
-extern cvar_t r_shadows_focus;
-extern cvar_t r_shadows_shadowmapscale;
-
void R_Shadow_PrepareModelShadows(void)
{
int i;
}
}
-void R_DrawModelShadowMaps(void)
+void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
int i;
float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
float m[12];
matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
r_viewport_t viewport;
- GLuint fbo = 0;
+ GLuint shadowfbo = 0;
float clearcolor[4];
if (!r_refdef.scene.numentities)
return;
}
- R_ResetViewRendering3D();
+ r_shadow_fb_fbo = fbo;
+ r_shadow_fb_depthtexture = depthtexture;
+ r_shadow_fb_colortexture = colortexture;
+
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
R_Shadow_RenderMode_Begin();
R_Shadow_RenderMode_ActiveLight(NULL);
switch (r_shadow_shadowmode)
{
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
- if (!r_shadow_shadowmap2dtexture)
+ if (!r_shadow_shadowmap2ddepthtexture)
R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
- fbo = r_shadow_fbo2d;
- r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
- r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
+ shadowfbo = r_shadow_fbo2d;
+ r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture);
+ r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture);
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
break;
default:
VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
- R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true);
+ if (r_shadow_shadowmap2ddepthbuffer)
+ R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
+ else
+ R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL);
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
Vector4Set(clearcolor, 1,1,1,1);
// in D3D9 we have to render to a color texture shadowmap
// in GL we render directly to a depth texture only
- if (r_shadow_shadowmap2dtexture)
+ if (r_shadow_shadowmap2ddepthbuffer)
GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
else
GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
#if 0
// debugging
- R_Mesh_SetMainRenderTargets();
+ R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
R_SetupShader_ShowDepth(true);
GL_ColorMask(1,1,1,1);
GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
}
}
-void R_DrawModelShadows(void)
+void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
int i;
float relativethrowdistance;
if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
return;
- R_ResetViewRendering3D();
+ r_shadow_fb_fbo = fbo;
+ r_shadow_fb_depthtexture = depthtexture;
+ r_shadow_fb_colortexture = colortexture;
+
+ R_ResetViewRendering3D(fbo, depthtexture, colortexture);
//GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
//GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
R_Shadow_RenderMode_Begin();
//GL_ScissorTest(true);
//R_EntityMatrix(&identitymatrix);
//R_Mesh_ResetTextureState();
- R_ResetViewRendering2D();
+ R_ResetViewRendering2D(fbo, depthtexture, colortexture);
// set up a darkening blend on shadowed areas
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// apply the blend to the shadowed areas
R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
+ R_SetupShader_Generic_NoTexture(false, true);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
// restore the viewport
//R_Shadow_RenderMode_End();
}
-void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
+static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
{
float zdist;
vec3_t centerorigin;
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef GL_SAMPLES_PASSED_ARB
CHECKGLERROR
// NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
CHECKGLERROR
+#endif
break;
case RENDERPATH_D3D9:
Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
-void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
+static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
{
vec3_t color;
GLint allpixels = 0, visiblepixels = 0;
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
+#ifdef GL_SAMPLES_PASSED_ARB
CHECKGLERROR
qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
CHECKGLERROR
+#endif
break;
case RENDERPATH_D3D9:
Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
size_t range;
if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
return;
- if (r_waterstate.renderingscene)
+ if (r_fb.water.renderingscene)
return;
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
R_EntityMatrix(&identitymatrix);
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
+#ifdef GL_SAMPLES_PASSED_ARB
if (usequery)
{
GL_ColorMask(0,0,0,0);
GL_PolygonOffset(0, 0);
GL_DepthTest(true);
R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
+ R_SetupShader_Generic_NoTexture(false, false);
}
+#endif
break;
case RENDERPATH_D3D9:
usequery = false;
-dlight_t *R_Shadow_NewWorldLight(void)
+static dlight_t *R_Shadow_NewWorldLight(void)
{
return (dlight_t *)Mem_ExpandableArray_AllocRecord(&r_shadow_worldlightsarray);
}
-void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
+static void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
{
matrix4x4_t matrix;
// validate parameters
R_RTLight_Update(&light->rtlight, true, &matrix, light->color, light->style, light->cubemapname[0] ? light->cubemapname : NULL, light->shadow, light->corona, light->coronasizescale, light->ambientscale, light->diffusescale, light->specularscale, light->flags);
}
-void R_Shadow_FreeWorldLight(dlight_t *light)
+static void R_Shadow_FreeWorldLight(dlight_t *light)
{
if (r_shadow_selectedlight == light)
r_shadow_selectedlight = NULL;
r_shadow_selectedlight = NULL;
}
-void R_Shadow_SelectLight(dlight_t *light)
+static void R_Shadow_SelectLight(dlight_t *light)
{
if (r_shadow_selectedlight)
r_shadow_selectedlight->selected = false;
r_shadow_selectedlight->selected = true;
}
-void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
// this is never batched (there can be only one)
float vertex3f[12];
R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
}
-void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
float intensity;
float s;
{
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (light)
- R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
}
if (!r_editlights_lockcursor)
- R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
+ R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
}
int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
return 1;
}
-void R_Shadow_SelectLightInView(void)
+static void R_Shadow_SelectLightInView(void)
{
float bestrating, rating, temp[3];
dlight_t *best;
const char *data;
float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
char key[256], value[MAX_INPUTLINE];
+ char vabuf[1024];
if (cl.worldmodel == NULL)
{
data = cl.worldmodel->brush.entities;
if (!data)
return;
- for (entnum = 0;COM_ParseToken_Simple(&data, false, false) && com_token[0] == '{';entnum++)
+ for (entnum = 0;COM_ParseToken_Simple(&data, false, false, true) && com_token[0] == '{';entnum++)
{
type = LIGHTTYPE_MINUSX;
origin[0] = origin[1] = origin[2] = 0;
islight = false;
while (1)
{
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break; // error
if (com_token[0] == '}')
break; // end of entity
strlcpy(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken_Simple(&data, false, false))
+ if (!COM_ParseToken_Simple(&data, false, false, true))
break; // error
strlcpy(value, com_token, sizeof(value));
}
VectorAdd(origin, originhack, origin);
if (radius >= 1)
- R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va("cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
+ R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va(vabuf, sizeof(vabuf), "cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
}
if (entfiledata)
Mem_Free(entfiledata);
}
-void R_Shadow_SetCursorLocationForView(void)
+static void R_Shadow_SetCursorLocationForView(void)
{
vec_t dist, push;
vec3_t dest, endpos;
R_Shadow_SelectLight(NULL);
}
-void R_Shadow_EditLights_Clear_f(void)
+static void R_Shadow_EditLights_Clear_f(void)
{
R_Shadow_ClearWorldLights();
}
}
}
-void R_Shadow_EditLights_Save_f(void)
+static void R_Shadow_EditLights_Save_f(void)
{
if (!cl.worldmodel)
return;
R_Shadow_SaveWorldLights();
}
-void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
+static void R_Shadow_EditLights_ImportLightEntitiesFromMap_f(void)
{
R_Shadow_ClearWorldLights();
R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite();
}
-void R_Shadow_EditLights_ImportLightsFile_f(void)
+static void R_Shadow_EditLights_ImportLightsFile_f(void)
{
R_Shadow_ClearWorldLights();
R_Shadow_LoadLightsFile();
}
-void R_Shadow_EditLights_Spawn_f(void)
+static void R_Shadow_EditLights_Spawn_f(void)
{
vec3_t color;
if (!r_editlights.integer)
R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), r_editlights_cursorlocation, vec3_origin, color, 200, 0, 0, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
}
-void R_Shadow_EditLights_Edit_f(void)
+static void R_Shadow_EditLights_Edit_f(void)
{
vec3_t origin, angles, color;
vec_t radius, corona, coronasizescale, ambientscale, diffusescale, specularscale;
R_Shadow_UpdateWorldLight(r_shadow_selectedlight, origin, angles, color, radius, corona, style, shadows, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
}
-void R_Shadow_EditLights_EditAll_f(void)
+static void R_Shadow_EditLights_EditAll_f(void)
{
size_t lightindex;
dlight_t *light, *oldselected;
dpsnprintf(temp, sizeof(temp), "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true, FONT_DEFAULT);y += 8;
}
-void R_Shadow_EditLights_ToggleShadow_f(void)
+static void R_Shadow_EditLights_ToggleShadow_f(void)
{
if (!r_editlights.integer)
{
R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
}
-void R_Shadow_EditLights_ToggleCorona_f(void)
+static void R_Shadow_EditLights_ToggleCorona_f(void)
{
if (!r_editlights.integer)
{
R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname, r_shadow_selectedlight->coronasizescale, r_shadow_selectedlight->ambientscale, r_shadow_selectedlight->diffusescale, r_shadow_selectedlight->specularscale, r_shadow_selectedlight->flags);
}
-void R_Shadow_EditLights_Remove_f(void)
+static void R_Shadow_EditLights_Remove_f(void)
{
if (!r_editlights.integer)
{
r_shadow_selectedlight = NULL;
}
-void R_Shadow_EditLights_Help_f(void)
+static void R_Shadow_EditLights_Help_f(void)
{
Con_Print(
"Documentation on r_editlights system:\n"
);
}
-void R_Shadow_EditLights_CopyInfo_f(void)
+static void R_Shadow_EditLights_CopyInfo_f(void)
{
if (!r_editlights.integer)
{
r_shadow_bufferlight.flags = r_shadow_selectedlight->flags;
}
-void R_Shadow_EditLights_PasteInfo_f(void)
+static void R_Shadow_EditLights_PasteInfo_f(void)
{
if (!r_editlights.integer)
{
R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_bufferlight.angles, r_shadow_bufferlight.color, r_shadow_bufferlight.radius, r_shadow_bufferlight.corona, r_shadow_bufferlight.style, r_shadow_bufferlight.shadow, r_shadow_bufferlight.cubemapname, r_shadow_bufferlight.coronasizescale, r_shadow_bufferlight.ambientscale, r_shadow_bufferlight.diffusescale, r_shadow_bufferlight.specularscale, r_shadow_bufferlight.flags);
}
-void R_Shadow_EditLights_Lock_f(void)
+static void R_Shadow_EditLights_Lock_f(void)
{
if (!r_editlights.integer)
{
r_editlights_lockcursor = true;
}
-void R_Shadow_EditLights_Init(void)
+static void R_Shadow_EditLights_Init(void)
{
Cvar_RegisterVariable(&r_editlights);
Cvar_RegisterVariable(&r_editlights_cursordistance);
intensity *= VectorLength(color);
VectorMA(sample + 12, intensity, relativepoint, sample + 12);
}
+ // FIXME: sample bouncegrid too!
}
if (flags & LP_DYNLIGHT)
void R_RTLight_Compile(rtlight_t *rtlight);
void R_RTLight_Uncompile(rtlight_t *rtlight);
-void R_Shadow_PrepareLights(void);
+void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
void R_Shadow_DrawPrepass(void);
void R_Shadow_DrawLights(void);
void R_Shadow_DrawCoronas(void);
void R_LightPoint(vec3_t color, const vec3_t p, const int flags);
void R_CompleteLightPoint(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const vec3_t p, const int flags);
+void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+
#endif
R_SetSkyBox
==================
*/
-void R_UnloadSkyBox(void)
+static void R_UnloadSkyBox(void)
{
int i;
int c = 0;
Con_Printf("unloading skybox\n");
}
-int R_LoadSkyBox(void)
+static int R_LoadSkyBox(void)
{
int i, j, success;
int indices[4] = {0,1,2,3};
char name[MAX_INPUTLINE];
unsigned char *image_buffer;
unsigned char *temp;
+ char vabuf[1024];
R_UnloadSkyBox();
}
temp = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height*4);
Image_CopyMux (temp, image_buffer, image_width, image_height, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, indices);
- skyboxskinframe[i] = R_SkinFrame_LoadInternalBGRA(va("skyboxside%d", i), TEXF_CLAMP | (gl_texturecompression_sky.integer ? TEXF_COMPRESS : 0), temp, image_width, image_height, vid.sRGB3D);
+ skyboxskinframe[i] = R_SkinFrame_LoadInternalBGRA(va(vabuf, sizeof(vabuf), "skyboxside%d", i), TEXF_CLAMP | (gl_texturecompression_sky.integer ? TEXF_COMPRESS : 0), temp, image_width, image_height, vid.sRGB3D);
Mem_Free(image_buffer);
Mem_Free(temp);
success++;
}
// LordHavoc: added LoadSky console command
-void LoadSky_f (void)
+static void LoadSky_f (void)
{
switch (Cmd_Argc())
{
#define SIDE_BOTTOM 3
#define SIDE_RIGHT 4
-void R_TrackSprite(const entity_render_t *ent, vec3_t origin, vec3_t left, vec3_t up, int *edge, float *dir_angle)
+static void R_TrackSprite(const entity_render_t *ent, vec3_t origin, vec3_t left, vec3_t up, int *edge, float *dir_angle)
{
float distance;
vec3_t bCoord; // body coordinates of object
}
}
-void R_RotateSprite(const mspriteframe_t *frame, vec3_t origin, vec3_t left, vec3_t up, int edge, float dir_angle)
+static void R_RotateSprite(const mspriteframe_t *frame, vec3_t origin, vec3_t left, vec3_t up, int edge, float dir_angle)
{
if(!(r_track_sprites_flags.integer & TSF_ROTATE))
{
static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
-void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+static void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int i;
dp_model_t *model = ent->model;
// honors scale
// honors a global label scaling cvar
- if(r_waterstate.renderingscene) // labels are considered HUD items, and don't appear in reflections
+ if(r_fb.water.renderingscene) // labels are considered HUD items, and don't appear in reflections
return;
// See the R_TrackSprite definition for a reason for this copying
// honors a global label scaling cvar before the rounding
// FIXME assumes that 1qu is 1 pixel in the sprite like in SPR32 format. Should not do that, but instead query the source image! This bug only applies to the roundtopixels case, though.
- if(r_waterstate.renderingscene) // labels are considered HUD items, and don't appear in reflections
+ if(r_fb.water.renderingscene) // labels are considered HUD items, and don't appear in reflections
return;
// See the R_TrackSprite definition for a reason for this copying
return;
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
- R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_Model_Sprite_Draw_TransparentCallback, ent, 0, rsurface.rtlight);
+ R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((ent->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), org, R_Model_Sprite_Draw_TransparentCallback, ent, 0, rsurface.rtlight);
}
#define TEXF_RENDERTARGET 0x0010000
// used for checking if textures mismatch
#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_RGBMULTIPLYBYALPHA | TEXF_CLAMP | TEXF_FORCENEAREST | TEXF_FORCELINEAR | TEXF_PICMIP | TEXF_COMPRESS | TEXF_COMPARE | TEXF_LOWPRECISION | TEXF_RENDERTARGET)
+// set as a flag to force the texture to be reloaded
+#define TEXF_FORCE_RELOAD 0x80000000
typedef enum textype_e
{
TEXTYPE_COLORBUFFER16F,
// this represents an RGBA float texture (4 32bit floats)
TEXTYPE_COLORBUFFER32F,
- // 16bit D16 (16bit depth) or 32bit S8D24 (24bit depth, 8bit stencil unused)
- TEXTYPE_SHADOWMAP
+ // depth-stencil buffer (or texture)
+ TEXTYPE_DEPTHBUFFER16,
+ // depth-stencil buffer (or texture)
+ TEXTYPE_DEPTHBUFFER24,
+ // 32bit D24S8 buffer (24bit depth, 8bit stencil), not supported on OpenGL ES
+ TEXTYPE_DEPTHBUFFER24STENCIL8,
+ // shadowmap-friendly format with depth comparison (not supported on some hardware)
+ TEXTYPE_SHADOWMAP16_COMP,
+ // shadowmap-friendly format with raw reading (not supported on some hardware)
+ TEXTYPE_SHADOWMAP16_RAW,
+ // shadowmap-friendly format with depth comparison (not supported on some hardware)
+ TEXTYPE_SHADOWMAP24_COMP,
+ // shadowmap-friendly format with raw reading (not supported on some hardware)
+ TEXTYPE_SHADOWMAP24_RAW,
}
textype_t;
typedef struct rtexture_s
{
// this is exposed (rather than private) for speed reasons only
- int texnum;
- qboolean dirty;
- int gltexturetypeenum; // exposed for use in R_Mesh_TexBind
+ int texnum; // GL texture slot number
+ int renderbuffernum; // GL renderbuffer slot number
+ qboolean dirty; // indicates that R_RealGetTexture should be called
+ qboolean glisdepthstencil; // indicates that FBO attachment has to be GL_DEPTH_STENCIL_ATTACHMENT
+ int gltexturetypeenum; // used by R_Mesh_TexBind
// d3d stuff the backend needs
void *d3dtexture;
+ void *d3dsurface;
#ifdef SUPPORTD3D
- qboolean d3disdepthsurface; // for depth/stencil surfaces
+ qboolean d3disrendertargetsurface;
+ qboolean d3disdepthstencilsurface;
int d3dformat;
int d3dusage;
int d3dpool;
rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter);
-rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel);
+rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype, qboolean filter);
+rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype);
+rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel);
// saves a texture to a DDS file
int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha);
// returns height of texture, as was specified when it was uploaded
int R_TextureHeight(rtexture_t *rt);
+// returns flags of texture, as was specified when it was uploaded
+int R_TextureFlags(rtexture_t *rt);
+
// only frees the texture if TEXF_PERSISTENT is not set
// also resets the variable
void R_PurgeTexture(rtexture_t *prt);
// returns the desired picmip level for given TEXF_ flags
int R_PicmipForFlags(int flags);
+void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean printtotal);
+
#endif
extern float ixtable[4096];
// fog stuff
-extern void FOG_clear(void);
+void FOG_clear(void);
// sky stuff
extern cvar_t r_sky;
extern cvar_t r_skyscroll1;
extern cvar_t r_skyscroll2;
extern int skyrenderlater, skyrendermasked;
-extern int R_SetSkyBox(const char *sky);
-extern void R_SkyStartFrame(void);
-extern void R_Sky(void);
-extern void R_ResetSkyBox(void);
+int R_SetSkyBox(const char *sky);
+void R_SkyStartFrame(void);
+void R_Sky(void);
+void R_ResetSkyBox(void);
// SHOWLMP stuff (Nehahra)
-extern void SHOWLMP_decodehide(void);
-extern void SHOWLMP_decodeshow(void);
-extern void SHOWLMP_drawall(void);
+void SHOWLMP_decodehide(void);
+void SHOWLMP_decodeshow(void);
+void SHOWLMP_drawall(void);
// render profiling stuff
extern int r_timereport_active;
extern cvar_t r_showcollisionbrushes_polygonoffset;
extern cvar_t r_showdisabledepthtest;
-//
-// view origin
-//
extern cvar_t r_drawentities;
extern cvar_t r_draw2d;
extern qboolean r_draw2d_force;
void R_Init(void);
void R_UpdateVariables(void); // must call after setting up most of r_refdef, but before calling R_RenderView
void R_RenderView(void); // must set r_refdef and call R_UpdateVariables first
+void R_RenderView_UpdateViewVectors(void); // just updates r_refdef.view.{forward,left,up,origin,right,inverse_matrix}
typedef enum r_refdef_scene_type_s {
RST_CLIENT,
extern cvar_t r_glsl_offsetmapping;
extern cvar_t r_glsl_offsetmapping_reliefmapping;
extern cvar_t r_glsl_offsetmapping_scale;
+extern cvar_t r_glsl_offsetmapping_lod;
+extern cvar_t r_glsl_offsetmapping_lod_distance;
extern cvar_t r_glsl_deluxemapping;
extern cvar_t gl_polyblend;
}
rsurfacepass_t;
-void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy);
-void R_SetupShader_DepthOrShadow(qboolean notrippy);
+void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha);
+void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy);
+void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb);
void R_SetupShader_ShowDepth(qboolean notrippy);
void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *waterplane, qboolean notrippy);
void R_SetupShader_DeferredLight(const rtlight_t *rtlight);
typedef struct r_waterstate_waterplane_s
{
- rtexture_t *texture_refraction;
- rtexture_t *texture_reflection;
- rtexture_t *texture_camera;
+ rtexture_t *texture_refraction; // MATERIALFLAG_WATERSHADER or MATERIALFLAG_REFRACTION
+ rtexture_t *texture_reflection; // MATERIALFLAG_WATERSHADER or MATERIALFLAG_REFLECTION
+ rtexture_t *texture_camera; // MATERIALFLAG_CAMERA
+ int fbo_refraction;
+ int fbo_reflection;
+ int fbo_camera;
mplane_t plane;
int materialflags; // combined flags of all water surfaces on this plane
unsigned char pvsbits[(MAX_MAP_LEAFS+7)>>3]; // FIXME: buffer overflow on huge maps
typedef struct r_waterstate_s
{
- qboolean enabled;
-
- qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
- qboolean renderingrefraction;
-
int waterwidth, waterheight;
int texturewidth, textureheight;
int camerawidth, cameraheight;
+ rtexture_t *depthtexture;
int maxwaterplanes; // same as MAX_WATERPLANES
int numwaterplanes;
float screenscale[2];
float screencenter[2];
+
+ qboolean enabled;
+
+ qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
+ qboolean hideplayer;
}
r_waterstate_t;
-extern r_waterstate_t r_waterstate;
+typedef struct r_framebufferstate_s
+{
+ textype_t textype; // type of color buffer we're using (dependent on r_viewfbo cvar)
+ int fbo; // non-zero if r_viewfbo is enabled and working
+ int screentexturewidth, screentextureheight; // dimensions of texture
+
+ rtexture_t *colortexture; // non-NULL if fbo is non-zero
+ rtexture_t *depthtexture; // non-NULL if fbo is non-zero
+ rtexture_t *ghosttexture; // for r_motionblur (not recommended on multi-GPU hardware!)
+ rtexture_t *bloomtexture[2]; // for r_bloom, multi-stage processing
+ int bloomfbo[2]; // fbos for rendering into bloomtexture[]
+ int bloomindex; // which bloomtexture[] contains the final image
+
+ int bloomwidth, bloomheight;
+ int bloomtexturewidth, bloomtextureheight;
+
+ // arrays for rendering the screen passes
+ float screentexcoord2f[8]; // texcoords for colortexture or ghosttexture
+ float bloomtexcoord2f[8]; // texcoords for bloomtexture[]
+ float offsettexcoord2f[8]; // temporary use while updating bloomtexture[]
+
+ r_viewport_t bloomviewport;
+
+ r_waterstate_t water;
+
+ qboolean ghosttexture_valid; // don't draw garbage on first frame with motionblur
+ qboolean usedepthtextures; // use depth texture instead of depth renderbuffer (faster if you need to read it later anyway)
+}
+r_framebufferstate_t;
+
+extern r_framebufferstate_t r_fb;
+
+extern cvar_t r_viewfbo;
+
+void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2); // this is called by R_ResetViewRendering2D and _DrawQ_Setup and internal
+void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+extern const float r_screenvertex3f[12];
+extern cvar_t r_shadows;
+extern cvar_t r_shadows_darken;
+extern cvar_t r_shadows_drawafterrtlighting;
+extern cvar_t r_shadows_castfrombmodels;
+extern cvar_t r_shadows_throwdistance;
+extern cvar_t r_shadows_throwdirection;
+extern cvar_t r_shadows_focus;
+extern cvar_t r_shadows_shadowmapscale;
+
+extern cvar_t r_transparent_alphatocoverage;
+extern cvar_t r_transparent_sortsurfacesbynearest;
+extern cvar_t r_transparent_useplanardistance;
+extern cvar_t r_transparent_sortarraysize;
+extern cvar_t r_transparent_sortmindist;
+extern cvar_t r_transparent_sortmaxdist;
+
+void R_Model_Sprite_Draw(entity_render_t *ent);
+
+struct prvm_prog_s;
+void R_UpdateFog(void);
+qboolean CL_VM_UpdateView(void);
+void SCR_DrawConsole(void);
+void R_Shadow_EditLights_DrawSelectedLightProperties(void);
+void R_DecalSystem_Reset(decalsystem_t *decalsystem);
+void R_Shadow_UpdateBounceGridTexture(void);
+void R_DrawLightningBeams(void);
+void VM_CL_AddPolygonsToMeshQueue(struct prvm_prog_s *prog);
+void R_DrawPortals(void);
+void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
+void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
+void R_Water_AddWaterPlane(msurface_t *surface, int entno);
+int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color);
+dp_font_t *FindFont(const char *title, qboolean allocate_new);
+void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, float voffset);
+
+void Render_Init(void);
+
+// these are called by Render_Init
+void R_Textures_Init(void);
+void GL_Draw_Init(void);
+void GL_Main_Init(void);
+void R_Shadow_Init(void);
+void R_Sky_Init(void);
+void GL_Surf_Init(void);
+void R_Particles_Init(void);
+void R_Explosion_Init(void);
+void gl_backend_init(void);
+void Sbar_Init(void);
+void R_LightningBeams_Init(void);
+void Mod_RenderInit(void);
+void Font_Init(void);
#endif
#include "quakedef.h"
#include "time.h"
+#include "cl_collision.h"
+#include "csprogs.h"
cachepic_t *sb_disc;
cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
+cvar_t showtex = {0, "showtex", "0", "shows the name of the texture on the crosshair (for map debugging)"};
cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
cvar_t sbar_hudselector = {CVAR_SAVE, "sbar_hudselector", "0", "selects which of the builtin hud layouts to use (meaning is somewhat dependent on gamemode, so nexuiz has a very different set of hud layouts than quake for example)"};
cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
-void Sbar_MiniDeathmatchOverlay (int x, int y);
-void Sbar_DeathmatchOverlay (void);
-void Sbar_IntermissionOverlay (void);
-void Sbar_FinaleOverlay (void);
+static void Sbar_MiniDeathmatchOverlay (int x, int y);
+static void Sbar_DeathmatchOverlay (void);
+static void Sbar_IntermissionOverlay (void);
+static void Sbar_FinaleOverlay (void);
-void CL_VM_UpdateShowingScoresState (int showingscores);
/*
Tab key down
===============
*/
-void Sbar_ShowScores (void)
+static void Sbar_ShowScores (void)
{
if (sb_showscores)
return;
Tab key up
===============
*/
-void Sbar_DontShowScores (void)
+static void Sbar_DontShowScores (void)
{
sb_showscores = false;
CL_VM_UpdateShowingScoresState(sb_showscores);
}
-void sbar_start(void)
+static void sbar_start(void)
{
+ char vabuf[1024];
int i;
if (gamemode == GAME_DELUXEQUAKE || gamemode == GAME_BLOODOMNICIDE)
sb_disc = Draw_CachePic_Flags ("gfx/disc", CACHEPICFLAG_QUIET);
for (i = 0;i < 10;i++)
- sb_nums[0][i] = Draw_CachePic_Flags (va("gfx/num_%i",i), CACHEPICFLAG_QUIET);
+ sb_nums[0][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/num_%i",i), CACHEPICFLAG_QUIET);
somsb_health = Draw_CachePic_Flags ("gfx/hud_health", CACHEPICFLAG_QUIET);
somsb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
else if (gamemode == GAME_NEXUIZ)
{
for (i = 0;i < 10;i++)
- sb_nums[0][i] = Draw_CachePic_Flags (va("gfx/num_%i",i), CACHEPICFLAG_QUIET);
+ sb_nums[0][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/num_%i",i), CACHEPICFLAG_QUIET);
sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET);
sb_sbar_overlay = Draw_CachePic_Flags ("gfx/sbar_overlay", CACHEPICFLAG_QUIET);
for(i = 0; i < 9;i++)
- sb_weapons[0][i] = Draw_CachePic_Flags (va("gfx/inv_weapon%i",i), CACHEPICFLAG_QUIET);
+ sb_weapons[0][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inv_weapon%i",i), CACHEPICFLAG_QUIET);
}
else if (gamemode == GAME_ZYMOTIC)
{
for (i = 0;i < 10;i++)
{
- sb_nums[0][i] = Draw_CachePic_Flags (va("gfx/num_%i",i), CACHEPICFLAG_QUIET);
- sb_nums[1][i] = Draw_CachePic_Flags (va("gfx/anum_%i",i), CACHEPICFLAG_QUIET);
+ sb_nums[0][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/num_%i",i), CACHEPICFLAG_QUIET);
+ sb_nums[1][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/anum_%i",i), CACHEPICFLAG_QUIET);
}
sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
for (i = 0;i < 5;i++)
{
- sb_weapons[2+i][0] = Draw_CachePic_Flags (va("gfx/inva%i_shotgun",i+1), CACHEPICFLAG_QUIET);
- sb_weapons[2+i][1] = Draw_CachePic_Flags (va("gfx/inva%i_sshotgun",i+1), CACHEPICFLAG_QUIET);
- sb_weapons[2+i][2] = Draw_CachePic_Flags (va("gfx/inva%i_nailgun",i+1), CACHEPICFLAG_QUIET);
- sb_weapons[2+i][3] = Draw_CachePic_Flags (va("gfx/inva%i_snailgun",i+1), CACHEPICFLAG_QUIET);
- sb_weapons[2+i][4] = Draw_CachePic_Flags (va("gfx/inva%i_rlaunch",i+1), CACHEPICFLAG_QUIET);
- sb_weapons[2+i][5] = Draw_CachePic_Flags (va("gfx/inva%i_srlaunch",i+1), CACHEPICFLAG_QUIET);
- sb_weapons[2+i][6] = Draw_CachePic_Flags (va("gfx/inva%i_lightng",i+1), CACHEPICFLAG_QUIET);
+ sb_weapons[2+i][0] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_shotgun",i+1), CACHEPICFLAG_QUIET);
+ sb_weapons[2+i][1] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_sshotgun",i+1), CACHEPICFLAG_QUIET);
+ sb_weapons[2+i][2] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_nailgun",i+1), CACHEPICFLAG_QUIET);
+ sb_weapons[2+i][3] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_snailgun",i+1), CACHEPICFLAG_QUIET);
+ sb_weapons[2+i][4] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_rlaunch",i+1), CACHEPICFLAG_QUIET);
+ sb_weapons[2+i][5] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_srlaunch",i+1), CACHEPICFLAG_QUIET);
+ sb_weapons[2+i][6] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_lightng",i+1), CACHEPICFLAG_QUIET);
}
sb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
for (i = 0;i < 5;i++)
{
- hsb_weapons[2+i][0] = Draw_CachePic_Flags (va("gfx/inva%i_laser",i+1), CACHEPICFLAG_QUIET);
- hsb_weapons[2+i][1] = Draw_CachePic_Flags (va("gfx/inva%i_mjolnir",i+1), CACHEPICFLAG_QUIET);
- hsb_weapons[2+i][2] = Draw_CachePic_Flags (va("gfx/inva%i_gren_prox",i+1), CACHEPICFLAG_QUIET);
- hsb_weapons[2+i][3] = Draw_CachePic_Flags (va("gfx/inva%i_prox_gren",i+1), CACHEPICFLAG_QUIET);
- hsb_weapons[2+i][4] = Draw_CachePic_Flags (va("gfx/inva%i_prox",i+1), CACHEPICFLAG_QUIET);
+ hsb_weapons[2+i][0] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_laser",i+1), CACHEPICFLAG_QUIET);
+ hsb_weapons[2+i][1] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_mjolnir",i+1), CACHEPICFLAG_QUIET);
+ hsb_weapons[2+i][2] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_gren_prox",i+1), CACHEPICFLAG_QUIET);
+ hsb_weapons[2+i][3] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_prox_gren",i+1), CACHEPICFLAG_QUIET);
+ hsb_weapons[2+i][4] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/inva%i_prox",i+1), CACHEPICFLAG_QUIET);
}
hsb_items[0] = Draw_CachePic_Flags ("gfx/sb_wsuit", CACHEPICFLAG_QUIET);
sb_finale = Draw_CachePic_Flags ("gfx/finale", CACHEPICFLAG_QUIET);
}
-void sbar_shutdown(void)
+static void sbar_shutdown(void)
{
}
-void sbar_newmap(void)
+static void sbar_newmap(void)
{
}
Cvar_RegisterVariable(&showtime_format);
Cvar_RegisterVariable(&showdate);
Cvar_RegisterVariable(&showdate_format);
+ Cvar_RegisterVariable(&showtex);
Cvar_RegisterVariable(&sbar_alpha_bg);
Cvar_RegisterVariable(&sbar_alpha_fg);
Cvar_RegisterVariable(&sbar_hudselector);
Sbar_DrawPic
=============
*/
-void Sbar_DrawStretchPic (int x, int y, cachepic_t *pic, float alpha, float overridewidth, float overrideheight)
+static void Sbar_DrawStretchPic (int x, int y, cachepic_t *pic, float alpha, float overridewidth, float overrideheight)
{
DrawQ_Pic (sbar_x + x, sbar_y + y, pic, overridewidth, overrideheight, 1, 1, 1, alpha, 0);
}
-void Sbar_DrawPic (int x, int y, cachepic_t *pic)
+static void Sbar_DrawPic (int x, int y, cachepic_t *pic)
{
DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
}
-void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
+static void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
{
DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
}
Draws one solid graphics character
================
*/
-void Sbar_DrawCharacter (int x, int y, int num)
+static void Sbar_DrawCharacter (int x, int y, int num)
{
- DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true, FONT_SBAR);
+ char vabuf[1024];
+ DrawQ_String (sbar_x + x + 4 , sbar_y + y, va(vabuf, sizeof(vabuf), "%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true, FONT_SBAR);
}
/*
Sbar_DrawString
================
*/
-void Sbar_DrawString (int x, int y, char *str)
+static void Sbar_DrawString (int x, int y, char *str)
{
DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR);
}
Sbar_DrawNum
=============
*/
-void Sbar_DrawNum (int x, int y, int num, int digits, int color)
+static void Sbar_DrawNum (int x, int y, int num, int digits, int color)
{
char str[32], *ptr;
int l, frame;
=============
*/
-void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
+static void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
{
char str[32], *ptr;
int l, frame;
//=============================================================================
-int Sbar_IsTeammatch(void)
+static int Sbar_IsTeammatch(void)
{
// currently only nexuiz uses the team score board
return ((gamemode == GAME_NEXUIZ)
Sbar_SoloScoreboard
===============
*/
-void Sbar_SoloScoreboard (void)
+static void Sbar_SoloScoreboard (void)
{
#if 1
char str[80], timestr[40];
int max, timelen;
int minutes, seconds;
double t;
+ char vabuf[1024];
t = (cl.intermission ? cl.completed_time : cl.time);
minutes = (int)(t / 60);
// monsters and secrets are now both on the top row
if (cl.stats[STAT_TOTALMONSTERS])
- Sbar_DrawString(8, 4, va("Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]));
+ Sbar_DrawString(8, 4, va(vabuf, sizeof(vabuf), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]));
else if (cl.stats[STAT_MONSTERS]) // LA: Display something if monsters_killed is non-zero, but total_monsters is zero
- Sbar_DrawString(8, 4, va("Monsters:%3i", cl.stats[STAT_MONSTERS]));
+ Sbar_DrawString(8, 4, va(vabuf, sizeof(vabuf), "Monsters:%3i", cl.stats[STAT_MONSTERS]));
if (cl.stats[STAT_TOTALSECRETS])
- Sbar_DrawString(8+22*8, 4, va("Secrets:%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
+ Sbar_DrawString(8+22*8, 4, va(vabuf, sizeof(vabuf), "Secrets:%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
else if (cl.stats[STAT_SECRETS]) // LA: And similarly for secrets
- Sbar_DrawString(8+22*8, 4, va("Secrets:%3i", cl.stats[STAT_SECRETS]));
+ Sbar_DrawString(8+22*8, 4, va(vabuf, sizeof(vabuf), "Secrets:%3i", cl.stats[STAT_SECRETS]));
// format is like this: e1m1:The Sligpate Complex
dpsnprintf(str, sizeof(str), "%s:%s", cl.worldbasename, cl.worldmessage);
Sbar_DrawScoreboard
===============
*/
-void Sbar_DrawScoreboard (void)
+static void Sbar_DrawScoreboard (void)
{
Sbar_SoloScoreboard ();
// LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
// AK to make DrawInventory smaller
static void Sbar_DrawWeapon(int nr, float fade, int active)
{
+ char vabuf[1024];
if (sbar_hudselector.integer == 1)
{
// width = 300, height = 100
DrawQ_Pic((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr, vid_conheight.integer - w_height, sb_weapons[0][nr], w_width, w_height, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 0.6, (active ? 1 : 0.6) * fade * sbar_alpha_fg.value, DRAWFLAG_NORMAL);
// FIXME ??
- DrawQ_String((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr + w_space, vid_conheight.integer - w_height + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 1, 0, sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
+ DrawQ_String((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr + w_space, vid_conheight.integer - w_height + w_space, va(vabuf, sizeof(vabuf), "%i",nr+1), 0, font_size, font_size, 1, 1, 0, sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
}
else
{
const float w_scale = 0.4;
DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, sb_weapons[0][nr], w_width * w_scale, w_height * w_scale, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 1, fade * sbar_alpha_fg.value, DRAWFLAG_NORMAL);
- //DrawQ_String(vid_conwidth.integer - (w_space + font_size ), (w_height + w_space) * w_scale * nr + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 0, 0, fade, 0, NULL, true, FONT_DEFAULT);
+ //DrawQ_String(vid_conwidth.integer - (w_space + font_size ), (w_height + w_space) * w_scale * nr + w_space, va(vabuf, sizeof(vabuf), "%i",nr+1), 0, font_size, font_size, 1, 0, 0, fade, 0, NULL, true, FONT_DEFAULT);
}
}
Sbar_DrawInventory
===============
*/
-void Sbar_DrawInventory (void)
+static void Sbar_DrawInventory (void)
{
int i;
char num[6];
Sbar_DrawFrags
===============
*/
-void Sbar_DrawFrags (void)
+static void Sbar_DrawFrags (void)
{
int i, k, l, x, f;
char num[12];
Sbar_DrawFace
===============
*/
-void Sbar_DrawFace (void)
+static void Sbar_DrawFace (void)
{
int f;
char speedstring[32];
char blurstring[32];
char topspeedstring[48];
+ char texstring[MAX_QPATH];
qboolean red = false;
soundstring[0] = 0;
fpsstring[0] = 0;
datestring[0] = 0;
speedstring[0] = 0;
blurstring[0] = 0;
+ texstring[0] = 0;
topspeedstring[0] = 0;
if (showfps.integer)
{
fps_strings++;
}
}
+ if (showtex.integer)
+ {
+ vec3_t org;
+ vec3_t dest;
+ vec3_t temp;
+ trace_t trace;
+
+ Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, org);
+ VectorSet(temp, 65536, 0, 0);
+ Matrix4x4_Transform(&r_refdef.view.matrix, temp, dest);
+ trace.hittexture = NULL; // to make sure
+ // TODO change this trace to be stopped by anything "visible" (i.e. with a drawsurface), but not stuff like weapclip
+ // probably needs adding a new SUPERCONTENTS type
+ trace = CL_TraceLine(org, dest, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID, true, false, NULL, true, true);
+ if(trace.hittexture)
+ strlcpy(texstring, trace.hittexture->name, sizeof(texstring));
+ else
+ strlcpy(texstring, "(no texture hit)", sizeof(texstring));
+ fps_strings++;
+ }
if (fps_strings)
{
fps_scalex = 12;
DrawQ_String(fps_x, fps_y, blurstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
fps_y += fps_scaley;
}
+ if (texstring[0])
+ {
+ fps_x = vid_conwidth.integer - DrawQ_TextWidth(texstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
+ DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
+ DrawQ_String(fps_x, fps_y, texstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
+ fps_y += fps_scaley;
+ }
}
}
-void Sbar_DrawGauge(float x, float y, cachepic_t *pic, float width, float height, float rangey, float rangeheight, float c1, float c2, float c1r, float c1g, float c1b, float c1a, float c2r, float c2g, float c2b, float c2a, float c3r, float c3g, float c3b, float c3a, int drawflags)
+static void Sbar_DrawGauge(float x, float y, cachepic_t *pic, float width, float height, float rangey, float rangeheight, float c1, float c2, float c1r, float c1g, float c1b, float c1a, float c2r, float c2g, float c2b, float c2a, float c3r, float c3g, float c3b, float c3a, int drawflags)
{
float r[5];
c2 = bound(0, c2, 1);
void Sbar_Draw (void)
{
cachepic_t *pic;
+ char vabuf[1024];
if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
{
if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value)
{
- pic = Draw_CachePic (va("gfx/crosshair%i", crosshair.integer));
+ pic = Draw_CachePic (va(vabuf, sizeof(vabuf), "gfx/crosshair%i", crosshair.integer));
DrawQ_Pic((vid_conwidth.integer - pic->width * crosshair_size.value) * 0.5f, (vid_conheight.integer - pic->height * crosshair_size.value) * 0.5f, pic, pic->width * crosshair_size.value, pic->height * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0);
}
if (cl_prydoncursor.integer > 0)
- DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic (va("gfx/prydoncursor%03i", cl_prydoncursor.integer)), 0, 0, 1, 1, 1, 1, 0);
+ DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic (va(vabuf, sizeof(vabuf), "gfx/prydoncursor%03i", cl_prydoncursor.integer)), 0, 0, 1, 1, 1, 1, 0);
}
//=============================================================================
==================
*/
-float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
+static float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
{
int minutes;
qboolean myself = false;
unsigned char *c;
+ char vabuf[1024];
minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
if((s - cl.scores) == cl.playerentity - 1)
if (s->qw_spectator)
{
if (s->qw_ping || s->qw_packetloss)
- DrawQ_String(x, y, va("%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), "%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
else
- DrawQ_String(x, y, va(" %4i spectator %c%s", minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), " %4i spectator %c%s", minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
}
else
{
c = palette_rgb_shirtscoreboard[s->colors & 0xf];
DrawQ_Fill(x + 14*8*FONT_SBAR->maxwidth, y+4, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
// print the text
- //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
+ //DrawQ_String(x, y, va(vabuf, sizeof(vabuf), "%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
if (s->qw_ping || s->qw_packetloss)
- DrawQ_String(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), "%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
else
- DrawQ_String(x, y, va(" %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), " %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
}
}
else
if (s->qw_spectator)
{
if (s->qw_ping || s->qw_packetloss)
- DrawQ_String(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), "%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
else
- DrawQ_String(x, y, va(" spect %c%s", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), " spect %c%s", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
}
else
{
c = palette_rgb_shirtscoreboard[s->colors & 0xf];
DrawQ_Fill(x + 9*8*FONT_SBAR->maxwidth, y+4, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
// print the text
- //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
+ //DrawQ_String(x, y, va(vabuf, sizeof(vabuf), "%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true, FONT_DEFAULT);
if (s->qw_ping || s->qw_packetloss)
- DrawQ_String(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), "%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
else
- DrawQ_String(x, y, va(" %5i %c%s", (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(x, y, va(vabuf, sizeof(vabuf), " %5i %c%s", (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
}
}
return 8;
void Sbar_DeathmatchOverlay (void)
{
int i, y, xmin, xmax, ymin, ymax;
+ char vabuf[1024];
// request new ping times every two second
if (cl.last_ping_request < realtime - 2 && cls.netcon)
y = 40;
if (cls.protocol == PROTOCOL_QUAKEWORLD)
{
- DrawQ_String(xmin, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(xmin, y, va(vabuf, sizeof(vabuf), "ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
}
else
{
- DrawQ_String(xmin, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
+ DrawQ_String(xmin, y, va(vabuf, sizeof(vabuf), "ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
}
y += 8;
}
}
-int Sbar_TeamColorCompare(const void *t1_, const void *t2_)
+static int Sbar_TeamColorCompare(const void *t1_, const void *t2_)
{
static int const sortorder[16] =
{
/// called every frame by screen
void Sbar_Draw (void);
+int Sbar_GetSortedPlayerIndex (int index);
+void Sbar_SortFrags (void);
+
#endif
unsigned char *csqc_progdata;
size_t csqc_progsize_deflated;
unsigned char *csqc_progdata_deflated;
+
+ // independent server thread (when running client)
+ qboolean threaded; // true if server is running on separate thread
+ qboolean volatile threadstop;
+ void *threadmutex;
+ void *thread;
} server_static_t;
//=============================================================================
#define MOVETYPE_FOLLOW 12 ///< track movement of aiment
#define MOVETYPE_FAKEPUSH 13 ///< tenebrae's push that doesn't push
#define MOVETYPE_PHYSICS 32 ///< indicates this object is physics controlled
+#define MOVETYPE_FLY_WORLDONLY 33 ///< like MOVETYPE_FLY, but uses MOVE_WORLDONLY for all its traces; objects of this movetype better be SOLID_NOT or SOLID_TRIGGER please, or else...
// edict->solid values
#define SOLID_NOT 0 ///< no interaction with other objects
#define SOLID_PHYSICS_BOX 32 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
#define SOLID_PHYSICS_SPHERE 33 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
#define SOLID_PHYSICS_CAPSULE 34 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
+#define SOLID_PHYSICS_TRIMESH 35 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
+#define SOLID_PHYSICS_CYLINDER 36 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
// edict->deadflag values
#define DEAD_NO 0
extern cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag;
extern cvar_t sv_gameplayfix_downtracesupportsongroundflag;
extern cvar_t sv_gameplayfix_q1bsptracelinereportstexture;
+extern cvar_t sv_gameplayfix_unstickplayers;
+extern cvar_t sv_gameplayfix_unstickentities;
+extern cvar_t sv_gameplayfix_fixedcheckwatertransition;
extern cvar_t sv_gravity;
extern cvar_t sv_idealpitchscale;
extern cvar_t sv_jumpstep;
extern cvar_t sv_wallfriction;
extern cvar_t sv_wateraccelerate;
extern cvar_t sv_waterfriction;
+extern cvar_t sv_areadebug;
extern cvar_t sys_ticrate;
extern cvar_t teamplay;
extern cvar_t temp1;
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count);
void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate);
-void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable);
-void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation);
+void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable, float speed);
+void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation, float speed);
void SV_ConnectClient (int clientnum, netconn_t *netconnection);
void SV_DropClient (qboolean crash);
-void SV_SendClientMessages (void);
+void SV_SendClientMessages(void);
void SV_ReadClientMessage(void);
trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask);
trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask);
trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask);
+int SV_EntitiesInBox(const vec3_t mins, const vec3_t maxs, int maxedicts, prvm_edict_t **resultedicts);
qboolean SV_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs);
void SV_FlushBroadcastMessages(void);
void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats);
-void SV_MoveToGoal (void);
+void VM_SV_MoveToGoal(prvm_prog_t *prog);
void SV_ApplyClientMove (void);
void SV_SaveSpawnparms (void);
void SV_SetupVM(void);
-void SV_VM_Begin(void);
-void SV_VM_End(void);
+const char *Host_TimingReport(char *buf, size_t buflen); ///< for output in Host_Status_f
+
+int SV_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent);
+void SV_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix);
-const char *Host_TimingReport(void); ///< for output in Host_Status_f
+void SV_StartThread(void);
+void SV_StopThread(void);
+#define SV_LockThreadMutex() (svs.threaded ? Thread_LockMutex(svs.threadmutex),1 : 0)
+#define SV_UnlockThreadMutex() (svs.threaded ? Thread_UnlockMutex(svs.threadmutex),1 : 0)
-int SV_GetPitchSign(prvm_edict_t *ent);
-void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix);
+void VM_CustomStats_Clear(void);
+void VM_SV_UpdateCustomStats(client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats);
+void Host_Savegame_to(prvm_prog_t *prog, const char *name);
+void SV_SendServerinfo(client_t *client);
#endif
"# define dp_offsetmapping_dFdx dFdx\n"
"# define dp_offsetmapping_dFdy dFdy\n"
"# define dp_textureGrad textureGrad\n"
+"# define dp_textureOffset(a,b,c,d) textureOffset(a,b,ivec2(c,d))\n"
"# define dp_texture2D texture\n"
"# define dp_texture3D texture\n"
"# define dp_textureCube texture\n"
-"# define dp_shadow2D(a,b) texture(a,b)\n"
+"# define dp_shadow2D(a,b) float(texture(a,b))\n"
"#else\n"
"# ifdef FRAGMENT_SHADER\n"
"# define dp_FragColor gl_FragColor\n"
"# define dp_offsetmapping_dFdx(a) vec2(0.0, 0.0)\n"
"# define dp_offsetmapping_dFdy(a) vec2(0.0, 0.0)\n"
"# define dp_textureGrad(a,b,c,d) texture2D(a,b)\n"
+"# define dp_textureOffset(a,b,c,d) texture2DOffset(a,b,ivec2(c,d))\n"
"# define dp_texture2D texture2D\n"
"# define dp_texture3D texture3D\n"
"# define dp_textureCube textureCube\n"
"#define highp\n"
"#endif\n"
"\n"
+"#ifdef USEDEPTHRGB\n"
+" // for 565 RGB we'd need to use different multipliers\n"
+"#define decodedepthmacro(d) dot((d).rgb, vec3(1.0, 255.0 / 65536.0, 255.0 / 16777215.0))\n"
+"#define encodedepthmacro(d) (vec4(d, d*256.0, d*65536.0, 0.0) - floor(vec4(d, d*256.0, d*65536.0, 0.0)))\n"
+"#endif\n"
+"\n"
"#ifdef VERTEX_SHADER\n"
"dp_attribute vec4 Attrib_Position; // vertex\n"
"dp_attribute vec4 Attrib_Color; // color\n"
"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
-"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
+"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE) || defined(MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP)\n"
"# define USELIGHTMAP\n"
"#endif\n"
"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT) || defined(USEFOG)\n"
"//# define myhalf2 half2\n"
"//# define myhalf3 half3\n"
"//# define myhalf4 half4\n"
+"//# define cast_myhalf half\n"
+"//# define cast_myhalf2 half2\n"
+"//# define cast_myhalf3 half3\n"
+"//# define cast_myhalf4 half4\n"
"//#else\n"
"# define myhalf mediump float\n"
"# define myhalf2 mediump vec2\n"
"# define myhalf3 mediump vec3\n"
"# define myhalf4 mediump vec4\n"
+"# define cast_myhalf float\n"
+"# define cast_myhalf2 vec2\n"
+"# define cast_myhalf3 vec3\n"
+"# define cast_myhalf4 vec4\n"
"//#endif\n"
"\n"
"#ifdef VERTEX_SHADER\n"
"#endif\n"
"\n"
"#ifdef MODE_DEPTH_OR_SHADOW\n"
+"dp_varying highp float Depth;\n"
"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
"#ifdef USETRIPPY\n"
" gl_Position = TrippyVertex(gl_Position);\n"
"#endif\n"
+" Depth = gl_Position.z;\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main(void)\n"
+"{\n"
+"#ifdef USEDEPTHRGB\n"
+" dp_FragColor = encodedepthmacro(Depth);\n"
+"#else\n"
+" dp_FragColor = vec4(1.0,1.0,1.0,1.0);\n"
+"#endif\n"
"}\n"
"#endif\n"
"#else // !MODE_DEPTH_ORSHADOW\n"
"#ifdef USESPECULAR\n"
"uniform sampler2D Texture_Second;\n"
"#endif\n"
+"#ifdef USEGAMMARAMPS\n"
+"uniform sampler2D Texture_GammaRamps;\n"
+"#endif\n"
"\n"
"void main(void)\n"
"{\n"
" dp_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
"#endif\n"
"#ifdef USEDIFFUSE\n"
+"# ifdef USEREFLECTCUBE\n"
+" // suppress texture alpha\n"
+" dp_FragColor.rgb *= dp_texture2D(Texture_First, TexCoord1).rgb;\n"
+"# else\n"
" dp_FragColor *= dp_texture2D(Texture_First, TexCoord1);\n"
+"# endif\n"
"#endif\n"
"\n"
"#ifdef USESPECULAR\n"
" dp_FragColor = mix(dp_FragColor, tex2, tex2.a);\n"
"# endif\n"
"#endif\n"
+"#ifdef USEGAMMARAMPS\n"
+" dp_FragColor.r = dp_texture2D(Texture_GammaRamps, vec2(dp_FragColor.r, 0)).r;\n"
+" dp_FragColor.g = dp_texture2D(Texture_GammaRamps, vec2(dp_FragColor.g, 0)).g;\n"
+" dp_FragColor.b = dp_texture2D(Texture_GammaRamps, vec2(dp_FragColor.b, 0)).b;\n"
+"#endif\n"
"}\n"
"#endif\n"
"#else // !MODE_GENERIC\n"
" #ifdef USENORMALMAPSCROLLBLEND\n"
" vec3 normal = dp_texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
" normal += dp_texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
-" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(normal))).xy * DistortScaleRefractReflect.xy;\n"
+" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(cast_myhalf3(normal))).xy * DistortScaleRefractReflect.xy;\n"
" #else\n"
-" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(dp_texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(cast_myhalf3(dp_texture2D(Texture_Normal, TexCoord)) - cast_myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
" #endif\n"
" // FIXME temporary hack to detect the case that the reflection\n"
" // gets blackened at edges due to leaving the area that contains actual\n"
"dp_varying highp vec3 BounceGridTexCoord;\n"
"#endif\n"
"\n"
+"#ifdef MODE_DEFERREDGEOMETRY\n"
+"dp_varying highp float Depth;\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
"#endif\n"
"\n"
"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform sampler2D Texture_ScreenDepth;\n"
"uniform sampler2D Texture_ScreenNormalMap;\n"
"#endif\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
"uniform highp float FogHeightFade;\n"
"vec3 FogVertex(vec4 surfacecolor)\n"
"{\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE) || defined(USEBOUNCEGRIDDIRECTIONAL)\n"
" vec3 EyeVectorModelSpace = vec3(VectorS.w, VectorT.w, VectorR.w);\n"
"#endif\n"
" float FogPlaneVertexDist = EyeVectorFogDepth.w;\n"
"#ifdef USEFOGHEIGHTTEXTURE\n"
" vec4 fogheightpixel = dp_texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
" fogfrac = fogheightpixel.a;\n"
-" return mix(fogheightpixel.rgb * fc, surfacecolor.rgb, dp_texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
+" return mix(fogheightpixel.rgb * fc, surfacecolor.rgb, dp_texture2D(Texture_FogMask, cast_myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#else\n"
"# ifdef USEFOGOUTSIDE\n"
" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
"# else\n"
" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
"# endif\n"
-" return mix(fc, surfacecolor.rgb, dp_texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
+" return mix(fc, surfacecolor.rgb, dp_texture2D(Texture_FogMask, cast_myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#endif\n"
"}\n"
"#endif\n"
"\n"
"#ifdef USEOFFSETMAPPING\n"
"uniform mediump vec4 OffsetMapping_ScaleSteps;\n"
+"uniform mediump float OffsetMapping_Bias;\n"
+"#ifdef USEOFFSETMAPPING_LOD\n"
+"uniform mediump float OffsetMapping_LodDistance;\n"
+"#endif\n"
"vec2 OffsetMapping(vec2 TexCoord, vec2 dPdx, vec2 dPdy)\n"
"{\n"
" float i;\n"
+" // distance-based LOD\n"
+"#ifdef USEOFFSETMAPPING_LOD\n"
+" mediump float LODFactor = min(1.0, OffsetMapping_LodDistance / EyeVectorFogDepth.z);\n"
+" mediump vec4 ScaleSteps = vec4(OffsetMapping_ScaleSteps.x, OffsetMapping_ScaleSteps.y * LODFactor, OffsetMapping_ScaleSteps.z / LODFactor, OffsetMapping_ScaleSteps.w * LODFactor);\n"
+"#else\n"
+" #define ScaleSteps OffsetMapping_ScaleSteps\n"
+"#endif\n"
"#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
" float f;\n"
" // 14 sample relief mapping: linear search and then binary search\n"
" // this basically steps forward a small amount repeatedly until it finds\n"
" // itself inside solid, then jitters forward and back using decreasing\n"
" // amounts to find the impact\n"
-" //vec3 OffsetVector = vec3(EyeVectorFogDepth.xy * ((1.0 / EyeVectorFogDepth.z) * OffsetMapping_ScaleSteps.x) * vec2(-1, 1), -1);\n"
-" //vec3 OffsetVector = vec3(normalize(EyeVectorFogDepth.xy) * OffsetMapping_ScaleSteps.x * vec2(-1, 1), -1);\n"
-" vec3 OffsetVector = vec3(normalize(EyeVectorFogDepth.xyz).xy * OffsetMapping_ScaleSteps.x * vec2(-1, 1), -1);\n"
-" vec3 RT = vec3(TexCoord, 1);\n"
-" OffsetVector *= OffsetMapping_ScaleSteps.z;\n"
-" for(i = 1.0; i < OffsetMapping_ScaleSteps.y; ++i)\n"
+" //vec3 OffsetVector = vec3(EyeVectorFogDepth.xy * ((1.0 / EyeVectorFogDepth.z) * ScaleSteps.x) * vec2(-1, 1), -1);\n"
+" //vec3 OffsetVector = vec3(normalize(EyeVectorFogDepth.xy) * ScaleSteps.x * vec2(-1, 1), -1);\n"
+" vec3 OffsetVector = vec3(normalize(EyeVectorFogDepth.xyz).xy * ScaleSteps.x * vec2(-1, 1), -1);\n"
+" vec3 RT = vec3(vec2(TexCoord.xy - OffsetVector.xy*OffsetMapping_Bias), 1);\n"
+" OffsetVector *= ScaleSteps.z;\n"
+" for(i = 1.0; i < ScaleSteps.y; ++i)\n"
" RT += OffsetVector * step(dp_textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
-" for(i = 0.0, f = 1.0; i < OffsetMapping_ScaleSteps.w; ++i, f *= 0.5)\n"
+" for(i = 0.0, f = 1.0; i < ScaleSteps.w; ++i, f *= 0.5)\n"
" RT += OffsetVector * (step(dp_textureGrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * f - 0.5 * f);\n"
" return RT.xy;\n"
"#else\n"
" // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
-" //vec2 OffsetVector = vec2(EyeVectorFogDepth.xy * ((1.0 / EyeVectorFogDepth.z) * OffsetMapping_ScaleSteps.x) * vec2(-1, 1));\n"
-" //vec2 OffsetVector = vec2(normalize(EyeVectorFogDepth.xy) * OffsetMapping_ScaleSteps.x * vec2(-1, 1));\n"
-" vec2 OffsetVector = vec2(normalize(EyeVectorFogDepth.xyz).xy * OffsetMapping_ScaleSteps.x * vec2(-1, 1));\n"
-" OffsetVector *= OffsetMapping_ScaleSteps.z;\n"
-" for(i = 0.0; i < OffsetMapping_ScaleSteps.y; ++i)\n"
-" TexCoord += OffsetVector * (1.0 - dp_textureGrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
+" //vec2 OffsetVector = vec2(EyeVectorFogDepth.xy * ((1.0 / EyeVectorFogDepth.z) * ScaleSteps.x) * vec2(-1, 1));\n"
+" //vec2 OffsetVector = vec2(normalize(EyeVectorFogDepth.xy) * ScaleSteps.x * vec2(-1, 1));\n"
+" vec2 OffsetVector = vec2(normalize(EyeVectorFogDepth.xyz).xy * ScaleSteps.x * vec2(-1, 1));\n"
+" OffsetVector *= ScaleSteps.z;\n"
+" for(i = 0.0; i < ScaleSteps.y; ++i)\n"
+" TexCoord += OffsetVector * ((1.0 - OffsetMapping_Bias) - dp_textureGrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
" return TexCoord;\n"
"#endif\n"
"}\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
+" float m = max(max(adir.x, adir.y), adir.z);\n"
+" vec2 mparams = ShadowMap_Parameters.xy / m;\n"
" vec4 proj = dp_textureCube(Texture_CubeProjection, dir);\n"
-" return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+"#ifdef USEDEPTHRGB\n"
+" return vec3(mix(dir.xy, dir.zz, proj.xy) * mparams.x + proj.zw * ShadowMap_Parameters.z, m + 64 * ShadowMap_Parameters.w);\n"
+"#else\n"
+" return vec3(mix(dir.xy, dir.zz, proj.xy) * mparams.x + proj.zw * ShadowMap_Parameters.z, mparams.y + ShadowMap_Parameters.w);\n"
+"#endif\n"
"}\n"
"# else\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" float ma = adir.z;\n"
-" vec4 proj = vec4(dir, 2.5);\n"
-" if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
-" if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
-" vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
-" return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+" float m; vec4 proj;\n"
+" if (adir.x > adir.y) { m = adir.x; proj = vec4(dir.zyx, 0.5); } else { m = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
+" if (adir.z > m) { m = adir.z; proj = vec4(dir, 2.5); }\n"
+"#ifdef USEDEPTHRGB\n"
+" return vec3(proj.xy * ShadowMap_Parameters.x / m + vec2(0.5,0.5) + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, m + 64 * ShadowMap_Parameters.w);\n"
+"#else\n"
+" vec2 mparams = ShadowMap_Parameters.xy / m;\n"
+" return vec3(proj.xy * mparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, mparams.y + ShadowMap_Parameters.w);\n"
+"#endif\n"
"}\n"
"# endif\n"
"# endif\n"
" vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
" float f;\n"
"\n"
-"# ifdef USESHADOWSAMPLER\n"
-"# ifdef USESHADOWMAPPCF\n"
-"# define texval(x, y) dp_shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) \n"
-" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
-" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+"# ifdef USEDEPTHRGB\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# define texval(x, y) decodedepthmacro(dp_texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale))\n"
+"# if USESHADOWMAPPCF > 1\n"
+" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+" center *= ShadowMap_TextureScale;\n"
+" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
+" vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
+" vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
+" vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
+" vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
+" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
"# else\n"
-" f = dp_shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));\n"
+" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
+" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
+" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
+" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
+" vec3 cols = row2 + mix(row1, row3, offset.y);\n"
+" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
"# endif\n"
+"# else\n"
+" f = step(shadowmaptc.z, decodedepthmacro(dp_texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale)));\n"
+"# endif\n"
"# else\n"
-"# ifdef USESHADOWMAPPCF\n"
-"# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
-"# ifdef GL_ARB_texture_gather\n"
-"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
-"# else\n"
-"# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
-"# endif\n"
+"# ifdef USESHADOWSAMPLER\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# define texval(x, y) dp_shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)) \n"
+" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
+" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+"# else\n"
+" f = dp_shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z));\n"
+"# endif\n"
+"# else\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
+"# ifdef GL_ARB_texture_gather\n"
+"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
+"# else\n"
+"# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
+"# endif\n"
" vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
-"# if USESHADOWMAPPCF > 1\n"
+"# if USESHADOWMAPPCF > 1\n"
" vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
" vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
" vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
" vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
" mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
-"# endif\n"
-"# else\n"
-"# ifdef GL_EXT_gpu_shader4\n"
-"# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
+"# endif\n"
"# else\n"
-"# define texval(x, y) dp_texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
-"# endif\n"
-"# if USESHADOWMAPPCF > 1\n"
+"# ifdef GL_EXT_gpu_shader4\n"
+"# define texval(x, y) dp_textureOffset(Texture_ShadowMap2D, center, x, y).r\n"
+"# else\n"
+"# define texval(x, y) dp_texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
+"# endif\n"
+"# if USESHADOWMAPPCF > 1\n"
" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
" center *= ShadowMap_TextureScale;\n"
" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
" vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
" vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
-"# else\n"
+"# else\n"
" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
" vec3 cols = row2 + mix(row1, row3, offset.y);\n"
" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
+"# endif\n"
"# endif\n"
-"# endif\n"
-"# else\n"
+"# else\n"
" f = step(shadowmaptc.z, dp_texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
-"# endif\n"
+"# endif\n"
+"# endif\n"
"# endif\n"
"# ifdef USESHADOWMAPORTHO\n"
" return mix(ShadowMap_Parameters.w, 1.0, f);\n"
"#ifdef USETRIPPY\n"
" gl_Position = TrippyVertex(gl_Position);\n"
"#endif\n"
+" Depth = (ModelViewMatrix * Attrib_Position).z;\n"
"}\n"
"#endif // VERTEX_SHADER\n"
"\n"
" float a = offsetMappedTexture2D(Texture_Gloss).a;\n"
"#endif\n"
"\n"
-" dp_FragColor = vec4(normalize(surfacenormal.x * VectorS.xyz + surfacenormal.y * VectorT.xyz + surfacenormal.z * VectorR.xyz) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
+" vec3 pixelnormal = normalize(surfacenormal.x * VectorS.xyz + surfacenormal.y * VectorT.xyz + surfacenormal.z * VectorR.xyz);\n"
+" dp_FragColor = vec4(pixelnormal.x, pixelnormal.y, Depth, a);\n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"#else // !MODE_DEFERREDGEOMETRY\n"
" // calculate viewspace pixel position\n"
" vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
" vec3 position;\n"
-" position.z = ScreenToDepth.y / (dp_texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
-" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
-" // decode viewspace pixel normal\n"
+" // get the geometry information (depth, normal, specular exponent)\n"
" myhalf4 normalmap = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
-" myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
+" // decode viewspace pixel normal\n"
+"// myhalf3 surfacenormal = normalize(normalmap.rgb - cast_myhalf3(0.5,0.5,0.5));\n"
+" myhalf3 surfacenormal = myhalf3(normalmap.rg, sqrt(1.0-dot(normalmap.rg, normalmap.rg)));\n"
+" // decode viewspace pixel position\n"
+"// position.z = decodedepthmacro(dp_texture2D(Texture_ScreenDepth, ScreenTexCoord));\n"
+" position.z = normalmap.b;\n"
+"// position.z = ScreenToDepth.y / (dp_texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
+" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
+"\n"
+" // now do the actual shading\n"
" // surfacenormal = pixel normal in viewspace\n"
" // LightVector = pixel to light in viewspace\n"
-" // CubeVector = position in lightspace\n"
+" // CubeVector = pixel in lightspace\n"
" // eyevector = pixel to view in viewspace\n"
" vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
-" myhalf fade = myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
+" myhalf fade = cast_myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
"#ifdef USEDIFFUSE\n"
" // calculate diffuse shading\n"
-" myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
-" myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+" myhalf3 lightnormal = cast_myhalf3(normalize(LightPosition - position));\n"
+" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
"#endif\n"
"#ifdef USESPECULAR\n"
" // calculate directional shading\n"
" vec3 eyevector = position * -1.0;\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
+" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), 1.0 + SpecularPower * normalmap.a);\n"
"# else\n"
-" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
+" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(eyevector)));\n"
+" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * normalmap.a);\n"
"# endif\n"
"#endif\n"
"\n"
" gl_FragColor.rgb *= cubecolor;\n"
"# endif\n"
"#endif\n"
-" \n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"#else // !MODE_DEFERREDLIGHTSOURCE\n"
"#endif\n"
"void main(void)\n"
"{\n"
-"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
+"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND) || defined(MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR)\n"
" VertexColor = Attrib_Color;\n"
"#endif\n"
" // copy the surface texcoord\n"
"#endif\n"
"\n"
" // combine the diffuse textures (base, pants, shirt)\n"
-" myhalf4 color = myhalf4(offsetMappedTexture2D(Texture_Color));\n"
+" myhalf4 color = cast_myhalf4(offsetMappedTexture2D(Texture_Color));\n"
"#ifdef USEALPHAKILL\n"
" if (color.a < 0.5)\n"
" discard;\n"
"#endif\n"
" color.a *= Alpha;\n"
"#ifdef USECOLORMAPPING\n"
-" color.rgb += myhalf3(offsetMappedTexture2D(Texture_Pants)) * Color_Pants + myhalf3(offsetMappedTexture2D(Texture_Shirt)) * Color_Shirt;\n"
+" color.rgb += cast_myhalf3(offsetMappedTexture2D(Texture_Pants)) * Color_Pants + cast_myhalf3(offsetMappedTexture2D(Texture_Shirt)) * Color_Shirt;\n"
"#endif\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
"#ifdef USEBOTHALPHAS\n"
-" myhalf4 color2 = myhalf4(dp_texture2D(Texture_SecondaryColor, TexCoord2));\n"
-" myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a, myhalf(1.0 - color2.a), myhalf(1.0));\n"
+" myhalf4 color2 = cast_myhalf4(dp_texture2D(Texture_SecondaryColor, TexCoord2));\n"
+" myhalf terrainblend = clamp(cast_myhalf(VertexColor.a) * color.a, cast_myhalf(1.0 - color2.a), cast_myhalf(1.0));\n"
" color.rgb = mix(color2.rgb, color.rgb, terrainblend);\n"
"#else\n"
-" myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
-" //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
-" //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
-" color.rgb = mix(myhalf3(dp_texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
+" myhalf terrainblend = clamp(cast_myhalf(VertexColor.a) * color.a * 2.0 - 0.5, cast_myhalf(0.0), cast_myhalf(1.0));\n"
+" //myhalf terrainblend = min(cast_myhalf(VertexColor.a) * color.a * 2.0, cast_myhalf(1.0));\n"
+" //myhalf terrainblend = cast_myhalf(VertexColor.a) * color.a > 0.5;\n"
+" color.rgb = mix(cast_myhalf3(dp_texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
"#endif\n"
" color.a = 1.0;\n"
-" //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
+" //color = mix(cast_myhalf4(1, 0, 0, 1), color, terrainblend);\n"
"#endif\n"
"\n"
" // get the surface normal\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
-" myhalf3 surfacenormal = normalize(mix(myhalf3(dp_texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(offsetMappedTexture2D(Texture_Normal)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
+" myhalf3 surfacenormal = normalize(mix(cast_myhalf3(dp_texture2D(Texture_SecondaryNormal, TexCoord2)), cast_myhalf3(offsetMappedTexture2D(Texture_Normal)), terrainblend) - cast_myhalf3(0.5, 0.5, 0.5));\n"
"#else\n"
-" myhalf3 surfacenormal = normalize(myhalf3(offsetMappedTexture2D(Texture_Normal)) - myhalf3(0.5, 0.5, 0.5));\n"
+" myhalf3 surfacenormal = normalize(cast_myhalf3(offsetMappedTexture2D(Texture_Normal)) - cast_myhalf3(0.5, 0.5, 0.5));\n"
"#endif\n"
"\n"
" // get the material colors\n"
" myhalf3 diffusetex = color.rgb;\n"
"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" myhalf4 glosstex = mix(myhalf4(dp_texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(offsetMappedTexture2D(Texture_Gloss)), terrainblend);\n"
+" myhalf4 glosstex = mix(cast_myhalf4(dp_texture2D(Texture_SecondaryGloss, TexCoord2)), cast_myhalf4(offsetMappedTexture2D(Texture_Gloss)), terrainblend);\n"
"# else\n"
-" myhalf4 glosstex = myhalf4(offsetMappedTexture2D(Texture_Gloss));\n"
+" myhalf4 glosstex = cast_myhalf4(offsetMappedTexture2D(Texture_Gloss));\n"
"# endif\n"
"#endif\n"
"\n"
" vec3 TangentReflectVector = reflect(-EyeVectorFogDepth.xyz, surfacenormal);\n"
" vec3 ModelReflectVector = TangentReflectVector.x * VectorS.xyz + TangentReflectVector.y * VectorT.xyz + TangentReflectVector.z * VectorR.xyz;\n"
" vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
-" diffusetex += myhalf3(offsetMappedTexture2D(Texture_ReflectMask)) * myhalf3(dp_textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
+" diffusetex += cast_myhalf3(offsetMappedTexture2D(Texture_ReflectMask)) * cast_myhalf3(dp_textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
"#endif\n"
"\n"
"\n"
"#ifdef MODE_LIGHTSOURCE\n"
" // light source\n"
"#ifdef USEDIFFUSE\n"
-" myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
-" myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+" myhalf3 lightnormal = cast_myhalf3(normalize(LightVector));\n"
+" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
" color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
"#ifdef USESPECULAR\n"
"#ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
+" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
"#else\n"
-" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
+" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
+" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
"#endif\n"
" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
" color.rgb = diffusetex * Color_Ambient;\n"
"#endif\n"
" color.rgb *= LightColor;\n"
-" color.rgb *= myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
+" color.rgb *= cast_myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
"#if defined(USESHADOWMAP2D)\n"
" color.rgb *= ShadowMapCompare(CubeVector);\n"
"#endif\n"
"# ifdef USECUBEFILTER\n"
-" color.rgb *= myhalf3(dp_textureCube(Texture_Cube, CubeVector));\n"
+" color.rgb *= cast_myhalf3(dp_textureCube(Texture_Cube, CubeVector));\n"
"# endif\n"
"#endif // MODE_LIGHTSOURCE\n"
"\n"
"\n"
"\n"
"#ifdef MODE_LIGHTDIRECTION\n"
-"#define SHADING\n"
-"#ifdef USEDIFFUSE\n"
-" myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
-"#endif\n"
-"#define lightcolor LightColor\n"
+" #define SHADING\n"
+" #ifdef USEDIFFUSE\n"
+" myhalf3 lightnormal = cast_myhalf3(normalize(LightVector));\n"
+" #endif\n"
+" #define lightcolor LightColor\n"
"#endif // MODE_LIGHTDIRECTION\n"
"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"#define SHADING\n"
+" #define SHADING\n"
" // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
-" myhalf3 lightnormal_modelspace = myhalf3(dp_texture2D(Texture_Deluxemap, TexCoordSurfaceLightmap.zw)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
-" myhalf3 lightcolor = myhalf3(dp_texture2D(Texture_Lightmap, TexCoordSurfaceLightmap.zw));\n"
+" myhalf3 lightnormal_modelspace = cast_myhalf3(dp_texture2D(Texture_Deluxemap, TexCoordSurfaceLightmap.zw)) * 2.0 + cast_myhalf3(-1.0, -1.0, -1.0);\n"
+" myhalf3 lightcolor = cast_myhalf3(dp_texture2D(Texture_Lightmap, TexCoordSurfaceLightmap.zw));\n"
" // convert modelspace light vector to tangentspace\n"
" myhalf3 lightnormal;\n"
-" lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
-" lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
-" lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
+" lightnormal.x = dot(lightnormal_modelspace, cast_myhalf3(VectorS));\n"
+" lightnormal.y = dot(lightnormal_modelspace, cast_myhalf3(VectorT));\n"
+" lightnormal.z = dot(lightnormal_modelspace, cast_myhalf3(VectorR));\n"
" lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
" // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
" lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
"#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
"#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
-"#define SHADING\n"
+" #define SHADING\n"
" // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
-" myhalf3 lightnormal = myhalf3(dp_texture2D(Texture_Deluxemap, TexCoordSurfaceLightmap.zw)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
-" myhalf3 lightcolor = myhalf3(dp_texture2D(Texture_Lightmap, TexCoordSurfaceLightmap.zw));\n"
+" myhalf3 lightnormal = cast_myhalf3(dp_texture2D(Texture_Deluxemap, TexCoordSurfaceLightmap.zw)) * 2.0 + cast_myhalf3(-1.0, -1.0, -1.0);\n"
+" myhalf3 lightcolor = cast_myhalf3(dp_texture2D(Texture_Lightmap, TexCoordSurfaceLightmap.zw));\n"
+"#endif\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR)\n"
+" #define SHADING\n"
+" // forced deluxemap on lightmapped/vertexlit surfaces\n"
+" myhalf3 lightnormal = cast_myhalf3(0.0, 0.0, 1.0);\n"
+" #ifdef USELIGHTMAP\n"
+" myhalf3 lightcolor = cast_myhalf3(dp_texture2D(Texture_Lightmap, TexCoordSurfaceLightmap.zw));\n"
+" #else\n"
+" myhalf3 lightcolor = cast_myhalf3(VertexColor.rgb);\n"
+" #endif\n"
"#endif\n"
-"\n"
-"\n"
-"\n"
-"\n"
"#ifdef MODE_FAKELIGHT\n"
-"#define SHADING\n"
-"myhalf3 lightnormal = myhalf3(normalize(EyeVectorFogDepth.xyz));\n"
-"myhalf3 lightcolor = myhalf3(1.0);\n"
+" #define SHADING\n"
+" myhalf3 lightnormal = cast_myhalf3(normalize(EyeVectorFogDepth.xyz));\n"
+" myhalf3 lightcolor = cast_myhalf3(1.0);\n"
"#endif // MODE_FAKELIGHT\n"
"\n"
"\n"
"\n"
"\n"
"#ifdef MODE_LIGHTMAP\n"
-" color.rgb = diffusetex * (Color_Ambient + myhalf3(dp_texture2D(Texture_Lightmap, TexCoordSurfaceLightmap.zw)) * Color_Diffuse);\n"
+" color.rgb = diffusetex * (Color_Ambient + cast_myhalf3(dp_texture2D(Texture_Lightmap, TexCoordSurfaceLightmap.zw)) * Color_Diffuse);\n"
"#endif // MODE_LIGHTMAP\n"
"#ifdef MODE_VERTEXCOLOR\n"
-" color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
+" color.rgb = diffusetex * (Color_Ambient + cast_myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
"#endif // MODE_VERTEXCOLOR\n"
"#ifdef MODE_FLATCOLOR\n"
" color.rgb = diffusetex * Color_Ambient;\n"
"\n"
"#ifdef SHADING\n"
"# ifdef USEDIFFUSE\n"
-" myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
"# ifdef USESPECULAR\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
+" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
"# else\n"
-" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
+" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
+" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
"# endif\n"
" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
"\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
" vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
-" color.rgb += diffusetex * myhalf3(dp_texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
-" color.rgb += glosstex.rgb * myhalf3(dp_texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
+" color.rgb += diffusetex * cast_myhalf3(dp_texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
+" color.rgb += glosstex.rgb * cast_myhalf3(dp_texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
+"// color.rgb = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord).rgb * vec3(1.0, 1.0, 0.001);\n"
"#endif\n"
"\n"
"#ifdef USEBOUNCEGRID\n"
"#ifdef USEBOUNCEGRIDDIRECTIONAL\n"
-"// myhalf4 bouncegrid_coeff1 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord ));\n"
-"// myhalf4 bouncegrid_coeff2 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.125))) * 2.0 + myhalf4(-1.0, -1.0, -1.0, -1.0);\n"
-" myhalf4 bouncegrid_coeff3 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.250)));\n"
-" myhalf4 bouncegrid_coeff4 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.375)));\n"
-" myhalf4 bouncegrid_coeff5 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.500)));\n"
-" myhalf4 bouncegrid_coeff6 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.625)));\n"
-" myhalf4 bouncegrid_coeff7 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.750)));\n"
-" myhalf4 bouncegrid_coeff8 = myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.875)));\n"
+"// myhalf4 bouncegrid_coeff1 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord ));\n"
+"// myhalf4 bouncegrid_coeff2 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.125))) * 2.0 + cast_myhalf4(-1.0, -1.0, -1.0, -1.0);\n"
+" myhalf4 bouncegrid_coeff3 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.250)));\n"
+" myhalf4 bouncegrid_coeff4 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.375)));\n"
+" myhalf4 bouncegrid_coeff5 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.500)));\n"
+" myhalf4 bouncegrid_coeff6 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.625)));\n"
+" myhalf4 bouncegrid_coeff7 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.750)));\n"
+" myhalf4 bouncegrid_coeff8 = cast_myhalf4(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord + vec3(0.0, 0.0, 0.875)));\n"
" myhalf3 bouncegrid_dir = normalize(mat3(BounceGridMatrix) * (surfacenormal.x * VectorS.xyz + surfacenormal.y * VectorT.xyz + surfacenormal.z * VectorR.xyz));\n"
-" myhalf3 bouncegrid_dirp = max(myhalf3(0.0, 0.0, 0.0), bouncegrid_dir);\n"
-" myhalf3 bouncegrid_dirn = max(myhalf3(0.0, 0.0, 0.0), -bouncegrid_dir);\n"
-"// bouncegrid_dirp = bouncegrid_dirn = myhalf3(1.0,1.0,1.0);\n"
-" myhalf3 bouncegrid_light = myhalf3(\n"
+" myhalf3 bouncegrid_dirp = max(cast_myhalf3(0.0, 0.0, 0.0), bouncegrid_dir);\n"
+" myhalf3 bouncegrid_dirn = max(cast_myhalf3(0.0, 0.0, 0.0), -bouncegrid_dir);\n"
+"// bouncegrid_dirp = bouncegrid_dirn = cast_myhalf3(1.0,1.0,1.0);\n"
+" myhalf3 bouncegrid_light = cast_myhalf3(\n"
" dot(bouncegrid_coeff3.xyz, bouncegrid_dirp) + dot(bouncegrid_coeff6.xyz, bouncegrid_dirn),\n"
" dot(bouncegrid_coeff4.xyz, bouncegrid_dirp) + dot(bouncegrid_coeff7.xyz, bouncegrid_dirn),\n"
" dot(bouncegrid_coeff5.xyz, bouncegrid_dirp) + dot(bouncegrid_coeff8.xyz, bouncegrid_dirn));\n"
" color.rgb += diffusetex * bouncegrid_light * BounceGridIntensity;\n"
"// color.rgb = bouncegrid_dir.rgb * 0.5 + vec3(0.5, 0.5, 0.5);\n"
"#else\n"
-" color.rgb += diffusetex * myhalf3(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
+" color.rgb += diffusetex * cast_myhalf3(dp_texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
"#endif\n"
"#endif\n"
"\n"
"#ifdef USEGLOW\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
-" color.rgb += mix(myhalf3(dp_texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(offsetMappedTexture2D(Texture_Glow)), terrainblend) * Color_Glow;\n"
+" color.rgb += mix(cast_myhalf3(dp_texture2D(Texture_SecondaryGlow, TexCoord2)), cast_myhalf3(offsetMappedTexture2D(Texture_Glow)), terrainblend) * Color_Glow;\n"
"#else\n"
-" color.rgb += myhalf3(offsetMappedTexture2D(Texture_Glow)) * Color_Glow;\n"
+" color.rgb += cast_myhalf3(offsetMappedTexture2D(Texture_Glow)) * Color_Glow;\n"
"#endif\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
"#ifdef USEREFLECTION\n"
" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(offsetMappedTexture2D(Texture_Normal)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(cast_myhalf3(offsetMappedTexture2D(Texture_Normal)) - cast_myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
" vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
" #ifdef USENORMALMAPSCROLLBLEND\n"
"# ifdef USEOFFSETMAPPING\n"
" vec3 normal = dp_texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
"# endif\n"
" normal += dp_texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
-" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(normal))).xy * DistortScaleRefractReflect.zw;\n"
+" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(cast_myhalf3(normal))).xy * DistortScaleRefractReflect.zw;\n"
" #else\n"
-" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(offsetMappedTexture2D(Texture_Normal)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
+" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(cast_myhalf3(offsetMappedTexture2D(Texture_Normal)) - cast_myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
" #endif\n"
" // FIXME temporary hack to detect the case that the reflection\n"
" // gets blackened at edges due to leaving the area that contains actual\n"
" f *= min(1.0, length(dp_texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
" f *= min(1.0, length(dp_texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
" ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-" color.rgb = mix(color.rgb, myhalf3(dp_texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
+" color.rgb = mix(color.rgb, cast_myhalf3(dp_texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
"#endif\n"
"\n"
" dp_FragColor = vec4(color);\n"
"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
-"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
+"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE) || defined(MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP)\n"
"#define USELIGHTMAP\n"
"#endif\n"
"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
"void main\n"
"(\n"
"float Depth : TEXCOORD0,\n"
-"out float4 gl_FragColor : COLOR\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
"// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
" float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
" temp.yz -= floor(temp.yz);\n"
-" gl_FragColor = temp;\n"
-"// gl_FragColor = float4(Depth,0,0,0);\n"
+" dp_FragColor = temp;\n"
+"// dp_FragColor = float4(Depth,0,0,0);\n"
"}\n"
"#endif\n"
-"#else // !MODE_DEPTH_ORSHADOW\n"
+"#else // !MODE_DEPTH_OR_SHADOW\n"
"\n"
"\n"
"\n"
"void main\n"
"(\n"
"float4 gl_FrontColor : COLOR0,\n"
-"out float4 gl_FragColor : COLOR\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
-" gl_FragColor = gl_FrontColor;\n"
+" dp_FragColor = gl_FrontColor;\n"
"}\n"
"#endif\n"
"#else // !MODE_SHOWDEPTH\n"
"uniform float ClientTime : register(c2),\n"
"uniform float2 PixelSize : register(c25),\n"
"uniform float4 BloomColorSubtract : register(c43),\n"
-"out float4 gl_FragColor : COLOR\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
-" gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
+" dp_FragColor = tex2D(Texture_First, TexCoord1);\n"
"#ifdef USEBLOOM\n"
-" gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
+" dp_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
"#endif\n"
"#ifdef USEVIEWTINT\n"
-" gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
+" dp_FragColor = lerp(dp_FragColor, ViewTintColor, ViewTintColor.a);\n"
"#endif\n"
"\n"
"#ifdef USEPOSTPROCESSING\n"
" float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
" float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
" sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
-" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
-" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
-" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
-" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
-" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
-" gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
-" gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
+" dp_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
+" dp_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
+" dp_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
+" dp_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
+" dp_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
+" dp_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
+" dp_FragColor.rgb = dp_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
"#endif\n"
"\n"
"#ifdef USESATURATION\n"
" //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
-" float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
+" float y = dot(dp_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
" // 'vampire sight' effect, wheres red is compensated\n"
" #ifdef SATURATION_REDCOMPENSATE\n"
-" float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
-" gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
-" gl_FragColor.r += r;\n"
+" float rboost = max(0.0, (dp_FragColor.r - max(dp_FragColor.g, dp_FragColor.b))*(1.0 - Saturation));\n"
+" dp_FragColor.rgb = lerp(float3(y,y,y), dp_FragColor.rgb, Saturation);\n"
+" dp_FragColor.r += r;\n"
" #else\n"
" // normal desaturation\n"
-" //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
-" gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
+" //dp_FragColor = float3(y,y,y) + (dp_FragColor.rgb - float3(y)) * Saturation;\n"
+" dp_FragColor.rgb = lerp(float3(y,y,y), dp_FragColor.rgb, Saturation);\n"
" #endif\n"
"#endif\n"
"\n"
"#ifdef USEGAMMARAMPS\n"
-" gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
-" gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
-" gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
+" dp_FragColor.r = tex2D(Texture_GammaRamps, float2(dp_FragColor.r, 0)).r;\n"
+" dp_FragColor.g = tex2D(Texture_GammaRamps, float2(dp_FragColor.g, 0)).g;\n"
+" dp_FragColor.b = tex2D(Texture_GammaRamps, float2(dp_FragColor.b, 0)).b;\n"
"#endif\n"
"}\n"
"#endif\n"
"#ifdef USESPECULAR\n"
"uniform sampler Texture_Second : register(s1),\n"
"#endif\n"
-"out float4 gl_FragColor : COLOR\n"
+"#ifdef USEGAMMARAMPS\n"
+"uniform sampler Texture_GammaRamps : register(s2),\n"
+"#endif\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
"#ifdef USEVIEWTINT\n"
-" gl_FragColor = gl_FrontColor;\n"
+" dp_FragColor = gl_FrontColor;\n"
"#else\n"
-" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
+" dp_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
"#endif\n"
"#ifdef USEDIFFUSE\n"
-" gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
+"# ifdef USEREFLECTCUBE\n"
+" // suppress texture alpha\n"
+" dp_FragColor.rgb *= tex2D(Texture_First, TexCoord1).rgb;\n"
+"# else\n"
+" dp_FragColor *= tex2D(Texture_First, TexCoord1);\n"
+"# endif\n"
"#endif\n"
"\n"
"#ifdef USESPECULAR\n"
" float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
"# ifdef USECOLORMAPPING\n"
-" gl_FragColor *= tex2;\n"
+" dp_FragColor *= tex2;\n"
"# endif\n"
"# ifdef USEGLOW\n"
-" gl_FragColor += tex2;\n"
+" dp_FragColor += tex2;\n"
"# endif\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
+" dp_FragColor = lerp(dp_FragColor, tex2, tex2.a);\n"
"# endif\n"
"#endif\n"
+"#ifdef USEGAMMARAMPS\n"
+" dp_FragColor.r = tex2D(Texture_GammaRamps, vec2(dp_FragColor.r, 0)).r;\n"
+" dp_FragColor.g = tex2D(Texture_GammaRamps, vec2(dp_FragColor.g, 0)).g;\n"
+" dp_FragColor.b = tex2D(Texture_GammaRamps, vec2(dp_FragColor.b, 0)).b;\n"
+"#endif\n"
"}\n"
"#endif\n"
"#else // !MODE_GENERIC\n"
"float2 TexCoord : TEXCOORD0,\n"
"uniform sampler Texture_First : register(s0),\n"
"uniform float4 BloomBlur_Parameters : register(c1),\n"
-"out float4 gl_FragColor : COLOR\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
" int i;\n"
" color += tex2D(Texture_First, tc).rgb;\n"
" tc += BloomBlur_Parameters.xy;\n"
" }\n"
-" gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
+" dp_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
"}\n"
"#endif\n"
"#else // !MODE_BLOOMBLUR\n"
"uniform float4 ScreenScaleRefractReflect : register(c32),\n"
"uniform float4 ScreenCenterRefractReflect : register(c31),\n"
"uniform float4 RefractColor : register(c29),\n"
-"out float4 gl_FragColor : COLOR\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
" float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
" ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-" gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
+" dp_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
"}\n"
"#endif\n"
"#else // !MODE_REFRACTION\n"
"{\n"
" TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
" float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+" EyeVector = float3(dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz), dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz), dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz));\n"
" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
" ModelViewProjectionPosition = gl_Position;\n"
"#ifdef USETRIPPY\n"
"uniform float4 ReflectColor : register(c26),\n"
"uniform float ReflectFactor : register(c27),\n"
"uniform float ReflectOffset : register(c28),\n"
-"out float4 gl_FragColor : COLOR\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
" float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
" f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
" ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
-" gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
+" dp_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
"}\n"
"#endif\n"
"#else // !MODE_WATER\n"
"#endif\n"
"\n"
"#ifdef USEOFFSETMAPPING\n"
-"float2 OffsetMapping(float2 TexCoord, float4 OffsetMapping_ScaleSteps, float3 EyeVector, sampler Texture_Normal, float2 dPdx, float2 dPdy)\n"
+"float2 OffsetMapping(float2 TexCoord, float4 OffsetMapping_ScaleSteps, float OffsetMapping_Bias, float OffsetMapping_LodDistance, float3 EyeVector, sampler Texture_Normal, float2 dPdx, float2 dPdy)\n"
"{\n"
" float i;\n"
+" // distance-based LOD\n"
+"#ifdef USEOFFSETMAPPING_LOD\n"
+" float LODFactor = min(1.0, OffsetMapping_LodDistance / EyeVectorFogDepth.z);\n"
+" mediump vec4 ScaleSteps = float4(OffsetMapping_ScaleSteps.x, OffsetMapping_ScaleSteps.y * LODFactor, OffsetMapping_ScaleSteps.z / LODFactor, OffsetMapping_ScaleSteps.w * LODFactor);\n"
+"#else\n"
+" #define ScaleSteps OffsetMapping_ScaleSteps\n"
+"#endif\n"
"#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
" // 14 sample relief mapping: linear search and then binary search\n"
" // this basically steps forward a small amount repeatedly until it finds\n"
" // itself inside solid, then jitters forward and back using decreasing\n"
" // amounts to find the impact\n"
-" //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_ScaleSteps.x) * float2(-1, 1), -1);\n"
-" //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_ScaleSteps.x * float2(-1, 1), -1);\n"
-" float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_ScaleSteps.x * float2(-1, 1), -1);\n"
-" float3 RT = float3(TexCoord, 1);\n"
-" OffsetVector *= OffsetMapping_ScaleSteps.z;\n"
-" for(i = 1.0; i < OffsetMapping_ScaleSteps.y; ++i)\n"
+" //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * ScaleSteps.x) * float2(-1, 1), -1);\n"
+" //float3 OffsetVector = float3(normalize(EyeVector.xy) * ScaleSteps.x * float2(-1, 1), -1);\n"
+" float3 OffsetVector = float3(normalize(EyeVector).xy * ScaleSteps.x * float2(-1, 1), -1);\n"
+" float3 RT = float3(float2(TexCoord.xy - OffsetVector.xy*OffsetMapping_Bias), 1);\n"
+" OffsetVector *= ScaleSteps.z;\n"
+" for(i = 1.0; i < ScaleSteps.y; ++i)\n"
" RT += OffsetVector * step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z);\n"
-" for(i = 0.0, f = 1.0; i < OffsetMapping_ScaleSteps.w; ++i, f *= 0.5)\n"
+" for(i = 0.0, f = 1.0; i < ScaleSteps.w; ++i, f *= 0.5)\n"
" RT += OffsetVector * (step(tex2Dgrad(Texture_Normal, RT.xy, dPdx, dPdy).a, RT.z) * f - 0.5 * f);\n"
" return RT.xy;\n"
"#else\n"
" // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
-" //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_ScaleSteps.x) * float2(-1, 1));\n"
-" //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_ScaleSteps.x * float2(-1, 1));\n"
-" float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_ScaleSteps.x * float2(-1, 1));\n"
-" OffsetVector *= OffsetMapping_ScaleSteps.z;\n"
-" for(i = 0.0; i < OffsetMapping_ScaleSteps.y; ++i)\n"
-" TexCoord += OffsetVector * (1.0 - tex2Dgrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
+" //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * ScaleSteps.x) * float2(-1, 1));\n"
+" //float2 OffsetVector = float2(normalize(EyeVector.xy) * ScaleSteps.x * float2(-1, 1));\n"
+" float2 OffsetVector = float2(normalize(EyeVector).xy * ScaleSteps.x * float2(-1, 1));\n"
+" OffsetVector *= ScaleSteps.z;\n"
+" for(i = 0.0; i < ScaleSteps.y; ++i)\n"
+" TexCoord += OffsetVector * ((1.0 - OffsetMapping_Bias) - tex2Dgrad(Texture_Normal, TexCoord, dPdx, dPdy).a);\n"
" return TexCoord;\n"
"#endif\n"
"}\n"
"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
"{\n"
" float3 adir = abs(dir);\n"
-" float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
+" float2 mparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
" float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
-" return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+" return float3(lerp(dir.xy, dir.zz, proj.xy) * mparams.x + proj.zw * ShadowMap_Parameters.z, mparams.y + ShadowMap_Parameters.w);\n"
"}\n"
"# else\n"
"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
"{\n"
" float3 adir = abs(dir);\n"
-" float ma = adir.z;\n"
-" float4 proj = float4(dir, 2.5);\n"
-" if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
-" if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
+" float m; float4 proj;\n"
+" if (adir.x > adir.y) { m = adir.x; proj = float4(dir.zyx, 0.5); } else { m = adir.y; proj = float4(dir.xzy, 1.5); }\n"
+" if (adir.z > m) { m = adir.z; proj = float4(dir, 2.5); }\n"
"#ifdef HLSL\n"
-" return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
+" return float3(proj.xy * ShadowMap_Parameters.x / m + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, m + 64 * ShadowMap_Parameters.w);\n"
"#else\n"
-" float2 aparams = ShadowMap_Parameters.xy / ma;\n"
-" return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+" float2 mparams = ShadowMap_Parameters.xy / m;\n"
+" return float3(proj.xy * mparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, mparams.y + ShadowMap_Parameters.w);\n"
"#endif\n"
"}\n"
"# endif\n"
" // transform unnormalized eye direction into tangent space\n"
"#ifdef USEOFFSETMAPPING\n"
" float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+" EyeVector = float3(dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz), dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz), dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz));\n"
"#endif\n"
"\n"
" VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
"#ifdef USETRIPPY\n"
" gl_Position = TrippyVertex(gl_Position);\n"
"#endif\n"
-" VectorR.w = gl_Position.z;\n"
+" VectorR.w = mul(ModelViewMatrix, gl_Vertex).z;\n"
"}\n"
"#endif // VERTEX_SHADER\n"
"\n"
"#endif\n"
"#ifdef USEOFFSETMAPPING\n"
"uniform float4 OffsetMapping_ScaleSteps : register(c24),\n"
+"uniform float4 OffsetMapping_LodDistance : register(c53),\n"
+"uniform float OffsetMapping_Bias : register(c54),\n"
"#endif\n"
"uniform half SpecularPower : register(c36),\n"
-"#ifdef HLSL\n"
-"out float4 gl_FragData0 : COLOR0,\n"
-"out float4 gl_FragData1 : COLOR1\n"
-"#else\n"
-"out float4 gl_FragColor : COLOR\n"
-"#endif\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
" float2 TexCoord = TexCoordBoth.xy;\n"
" // apply offsetmapping\n"
" float2 dPdx = ddx(TexCoord);\n"
" float2 dPdy = ddy(TexCoord);\n"
-" float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_ScaleSteps, EyeVector, Texture_Normal, dPdx, dPdy);\n"
+" float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_ScaleSteps, OffsetMapping_Bias, OffsetMapping_LodDistance, EyeVector, Texture_Normal, dPdx, dPdy);\n"
"# define offsetMappedTexture2D(t) tex2Dgrad(t, TexCoordOffset, dPdx, dPdy)\n"
"#else\n"
"# define offsetMappedTexture2D(t) tex2D(t, TexCoord)\n"
" float a = offsetMappedTexture2D(Texture_Gloss).a;\n"
"#endif\n"
"\n"
-"#ifdef HLSL\n"
-" gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
-" float Depth = VectorR.w / 256.0;\n"
-" float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
-"// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
-" depthcolor.yz -= floor(depthcolor.yz);\n"
-" gl_FragData1 = depthcolor;\n"
-"#else\n"
-" gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
-"#endif\n"
+" float3 pixelnormal = normalize(surfacenormal.x * VectorS.xyz + surfacenormal.y * VectorT.xyz + surfacenormal.z * VectorR.xyz);\n"
+" dp_FragColor = float4(pixelnormal.x, pixelnormal.y, VectorR.w, a);\n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"#else // !MODE_DEFERREDGEOMETRY\n"
"{\n"
" // calculate viewspace pixel position\n"
" float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
-" //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
" float3 position;\n"
-"#ifdef HLSL\n"
-" position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
-"#else\n"
-" position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
-"#endif\n"
-" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
-" // decode viewspace pixel normal\n"
+" // get the geometry information (depth, normal, specular exponent)\n"
" half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
-" half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
+" // decode viewspace pixel normal\n"
+"// float3 surfacenormal = normalize(normalmap.rgb - cast_myhalf3(0.5,0.5,0.5));\n"
+" float3 surfacenormal = half3(normalmap.rg, sqrt(1.0-dot(normalmap.rg, normalmap.rg)));\n"
+" // decode viewspace pixel position\n"
+"// position.z = decodedepthmacro(dp_texture2D(Texture_ScreenDepth, ScreenTexCoord));\n"
+" position.z = normalmap.b;\n"
+"// position.z = ScreenToDepth.y / (dp_texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
+" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
+"\n"
+" // now do the actual shading\n"
" // surfacenormal = pixel normal in viewspace\n"
" // LightVector = pixel to light in viewspace\n"
" // CubeVector = position in lightspace\n"
" // calculate directional shading\n"
" float3 eyevector = position * -1.0;\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
+" half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), 1.0 + SpecularPower * normalmap.a));\n"
"# else\n"
" half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
-" half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
+" half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * normalmap.a));\n"
"# endif\n"
"#endif\n"
"\n"
"(\n"
"float4 gl_Vertex : POSITION,\n"
"uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
-"#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
+"#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR) || defined(MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR)\n"
"float4 gl_Color : COLOR0,\n"
"#endif\n"
"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
" // (we use unnormalized to ensure that it interpolates correctly and then\n"
" // normalize it per pixel)\n"
" float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
-" LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
-" LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
-" LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
+" LightVector = float3(dot(lightminusvertex, gl_MultiTexCoord1.xyz), dot(lightminusvertex, gl_MultiTexCoord2.xyz), dot(lightminusvertex, gl_MultiTexCoord3.xyz));\n"
"# endif\n"
"#endif\n"
"\n"
"#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
-" LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
-" LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
-" LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
+" LightVector = float3(dot(LightDir, gl_MultiTexCoord1.xyz), dot(LightDir, gl_MultiTexCoord2.xyz), dot(LightDir, gl_MultiTexCoord3.xyz));\n"
"#endif\n"
"\n"
" // transform unnormalized eye direction into tangent space\n"
"#ifdef USEEYEVECTOR\n"
" float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+" EyeVector = float3(dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz), dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz), dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz));\n"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
"\n"
"#ifdef USEOFFSETMAPPING\n"
"uniform float4 OffsetMapping_ScaleSteps : register(c24),\n"
+"uniform float OffsetMapping_Bias : register(c54),\n"
"#endif\n"
"\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
"#endif\n"
"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
"\n"
-"out float4 gl_FragColor : COLOR\n"
+"out float4 dp_FragColor : COLOR\n"
")\n"
"{\n"
" float2 TexCoord = TexCoordBoth.xy;\n"
" // apply offsetmapping\n"
" float2 dPdx = ddx(TexCoord);\n"
" float2 dPdy = ddy(TexCoord);\n"
-" float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_ScaleSteps, EyeVector, Texture_Normal, dPdx, dPdy);\n"
+" float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_ScaleSteps, OffsetMapping_Bias, OffsetMapping_LodDistance, EyeVector, Texture_Normal, dPdx, dPdy);\n"
"# define offsetMappedTexture2D(t) tex2Dgrad(t, TexCoordOffset, dPdx, dPdy)\n"
"#else\n"
"# define offsetMappedTexture2D(t) tex2D(t, TexCoord)\n"
" color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
"#ifdef USESPECULAR\n"
"#ifdef USEEXACTSPECULARMATH\n"
-" half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
+" half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a));\n"
"#else\n"
" half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
-" half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
+" half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a));\n"
"#endif\n"
" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
"\n"
"\n"
"#ifdef MODE_LIGHTDIRECTION\n"
-"#define SHADING\n"
-"#ifdef USEDIFFUSE\n"
-" half3 lightnormal = half3(normalize(LightVector));\n"
-"#endif\n"
-"#define lightcolor LightColor\n"
+" #define SHADING\n"
+" #ifdef USEDIFFUSE\n"
+" half3 lightnormal = half3(normalize(LightVector));\n"
+" #endif\n"
+" #define lightcolor LightColor\n"
"#endif // MODE_LIGHTDIRECTION\n"
"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"#define SHADING\n"
+" #define SHADING\n"
" // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
" half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
" half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
" // convert modelspace light vector to tangentspace\n"
-" half3 lightnormal;\n"
-" lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
-" lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
-" lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
+" half3 lightnormal = half3(dot(lightnormal_modelspace, half3(VectorS)), dot(lightnormal_modelspace, half3(VectorT)), dot(lightnormal_modelspace, half3(VectorR)));\n"
" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
" // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
" // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
" lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
"#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
"#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
-"#define SHADING\n"
+" #define SHADING\n"
" // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
" half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
" half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
"#endif\n"
-"\n"
-"\n"
-"\n"
-"\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR)\n"
+" #define SHADING\n"
+" // forced deluxemap on lightmapped/vertexlit surfaces\n"
+" half3 lightnormal = half3(0.0, 0.0, 1.0);\n"
+" #ifdef USELIGHTMAP\n"
+" half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
+" #else\n"
+" half3 lightcolor = half3(gl_FrontColor.rgb);\n"
+" #endif\n"
+"#endif\n"
"#ifdef MODE_FAKELIGHT\n"
-"#define SHADING\n"
-"half3 lightnormal = half3(normalize(EyeVector));\n"
-"half3 lightcolor = half3(1.0,1.0,1.0);\n"
+" #define SHADING\n"
+" half3 lightnormal = half3(normalize(EyeVector));\n"
+" half3 lightcolor = half3(1.0,1.0,1.0);\n"
"#endif // MODE_FAKELIGHT\n"
"\n"
"\n"
" half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
"# ifdef USESPECULAR\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
+" half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a));\n"
"# else\n"
" half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
-" half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
+" half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a));\n"
"# endif\n"
" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
" color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
"#endif\n"
"\n"
-" gl_FragColor = float4(color);\n"
+" dp_FragColor = float4(color);\n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"\n"
#include "snd_modplug.h"
#include "csprogs.h"
#include "cl_collision.h"
+#include "cdaudio.h"
#define SND_MIN_SPEED 8000
-#define SND_MAX_SPEED 96000
+#define SND_MAX_SPEED 192000
#define SND_MIN_WIDTH 1
#define SND_MAX_WIDTH 2
#define SND_MIN_CHANNELS 1
cvar_t snd_initialized = { CVAR_READONLY, "snd_initialized", "0", "indicates the sound subsystem is active"};
cvar_t snd_staticvolume = {CVAR_SAVE, "snd_staticvolume", "1", "volume of ambient sound effects (such as swampy sounds at the start of e1m2)"};
cvar_t snd_soundradius = {CVAR_SAVE, "snd_soundradius", "1200", "radius of weapon sounds and other standard sound effects (monster idle noises are half this radius and flickering light noises are one third of this radius)"};
+cvar_t snd_attenuation_exponent = {CVAR_SAVE, "snd_attenuation_exponent", "1", "Exponent of (1-radius) in sound attenuation formula"};
+cvar_t snd_attenuation_decibel = {CVAR_SAVE, "snd_attenuation_decibel", "0", "Decibel sound attenuation per sound radius distance"};
cvar_t snd_spatialization_min_radius = {CVAR_SAVE, "snd_spatialization_min_radius", "10000", "use minimum spatialization above to this radius"};
cvar_t snd_spatialization_max_radius = {CVAR_SAVE, "snd_spatialization_max_radius", "100", "use maximum spatialization below this radius"};
cvar_t snd_spatialization_min = {CVAR_SAVE, "snd_spatialization_min", "0.70", "minimum spatializazion of sounds"};
// Cvars declared in snd_main.h (shared with other snd_*.c files)
cvar_t _snd_mixahead = {CVAR_SAVE, "_snd_mixahead", "0.15", "how much sound to mix ahead of time"};
-cvar_t snd_streaming = { CVAR_SAVE, "snd_streaming", "1", "enables keeping compressed ogg sound files compressed, decompressing them only as needed, otherwise they will be decompressed completely at load (may use a lot of memory)"};
+cvar_t snd_streaming = { CVAR_SAVE, "snd_streaming", "1", "enables keeping compressed ogg sound files compressed, decompressing them only as needed, otherwise they will be decompressed completely at load (may use a lot of memory); when set to 2, streaming is performed even if this would waste memory"};
+cvar_t snd_streaming_length = { CVAR_SAVE, "snd_streaming_length", "1", "decompress sounds completely if they are less than this play time when snd_streaming is 1"};
cvar_t snd_swapstereo = {CVAR_SAVE, "snd_swapstereo", "0", "swaps left/right speakers for old ISA soundblaster cards"};
extern cvar_t v_flipped;
cvar_t snd_channellayout = {0, "snd_channellayout", "0", "channel layout. Can be 0 (auto - snd_restart needed), 1 (standard layout), or 2 (ALSA layout)"};
cvar_t snd_mutewhenidle = {CVAR_SAVE, "snd_mutewhenidle", "1", "whether to disable sound output when game window is inactive"};
+cvar_t snd_maxchannelvolume = {CVAR_SAVE, "snd_maxchannelvolume", "10", "maximum volume of a single sound"};
+cvar_t snd_softclip = {CVAR_SAVE, "snd_softclip", "0", "Use soft-clipping. Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this option if the dynamic range of the loudspeakers is very low. WARNING: This feature creates distortion and should be considered a last resort."};
+//cvar_t snd_softclip = {CVAR_SAVE, "snd_softclip", "0", "Use soft-clipping (when set to 2, use it even if output is floating point). Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this option if the dynamic range of the loudspeakers is very low. WARNING: This feature creates distortion and should be considered a last resort."};
cvar_t snd_entchannel0volume = {CVAR_SAVE, "snd_entchannel0volume", "1", "volume multiplier of the auto-allocate entity channel of regular entities (DEPRECATED)"};
cvar_t snd_entchannel1volume = {CVAR_SAVE, "snd_entchannel1volume", "1", "volume multiplier of the 1st entity channel of regular entities (DEPRECATED)"};
cvar_t snd_entchannel2volume = {CVAR_SAVE, "snd_entchannel2volume", "1", "volume multiplier of the 2nd entity channel of regular entities (DEPRECATED)"};
static cvar_t snd_startloopingsounds = {0, "snd_startloopingsounds", "1", "whether to start sounds that would loop (you want this to be 1); existing sounds are not affected"};
static cvar_t snd_startnonloopingsounds = {0, "snd_startnonloopingsounds", "1", "whether to start sounds that would not loop (you want this to be 1); existing sounds are not affected"};
+// randomization
+static cvar_t snd_identicalsoundrandomization_time = {0, "snd_identicalsoundrandomization_time", "0.1", "how much seconds to randomly skip (positive) or delay (negative) sounds when multiple identical sounds are started on the same frame"};
+static cvar_t snd_identicalsoundrandomization_tics = {0, "snd_identicalsoundrandomization_tics", "0", "if nonzero, how many tics to limit sound randomization as defined by snd_identicalsoundrandomization_time"};
+
// Ambient sounds
static sfx_t* ambient_sfxs [2] = { NULL, NULL };
static const char* ambient_names [2] = { "sound/ambience/water1.wav", "sound/ambience/wind2.wav" };
if (sfx->fetcher != NULL)
{
unsigned int size;
- const snd_format_t* format;
size = sfx->memsize;
- format = sfx->fetcher->getfmt(sfx);
- Con_Printf ("%c%c%c(%2db, %6s) %8i : %s\n",
+ Con_Printf ("%c%c%c(%5iHz %2db %6s) %8i : %s\n",
(sfx->loopstart < sfx->total_length) ? 'L' : ' ',
(sfx->flags & SFXFLAG_STREAMED) ? 'S' : ' ',
(sfx->flags & SFXFLAG_MENUSOUND) ? 'P' : ' ',
- format->width * 8,
- (format->channels == 1) ? "mono" : "stereo",
+ sfx->format.speed,
+ sfx->format.width * 8,
+ (sfx->format.channels == 1) ? "mono" : "stereo",
size,
sfx->name);
total += size;
}
-void S_SoundInfo_f(void)
+static void S_SoundInfo_f(void)
{
if (snd_renderbuffer == NULL)
{
fixed_width = true;
}
+#if 0
+ // LordHavoc: now you can with the resampler...
// You can't change sound speed after start time (not yet supported)
if (prev_render_format.speed != 0)
{
chosen_fmt.speed = prev_render_format.speed;
}
}
+#endif
// Sanity checks
if (chosen_fmt.speed < SND_MIN_SPEED)
sound_spatialized = false;
}
-void S_Restart_f(void)
+static void S_Restart_f(void)
{
// NOTE: we can't free all sounds if we are running a map (this frees sfx_t that are still referenced by precaches)
// So, refuse to do this if we are connected.
Cvar_RegisterVariable(&snd_channel6volume);
Cvar_RegisterVariable(&snd_channel7volume);
+ Cvar_RegisterVariable(&snd_attenuation_exponent);
+ Cvar_RegisterVariable(&snd_attenuation_decibel);
+
Cvar_RegisterVariable(&snd_spatialization_min_radius);
Cvar_RegisterVariable(&snd_spatialization_max_radius);
Cvar_RegisterVariable(&snd_spatialization_min);
Cvar_RegisterVariable(&snd_width);
Cvar_RegisterVariable(&snd_channels);
Cvar_RegisterVariable(&snd_mutewhenidle);
+ Cvar_RegisterVariable(&snd_maxchannelvolume);
+ Cvar_RegisterVariable(&snd_softclip);
Cvar_RegisterVariable(&snd_startloopingsounds);
Cvar_RegisterVariable(&snd_startnonloopingsounds);
+ Cvar_RegisterVariable(&snd_identicalsoundrandomization_time);
+ Cvar_RegisterVariable(&snd_identicalsoundrandomization_tics);
+
// COMMANDLINEOPTION: Sound: -nosound disables sound (including CD audio)
if (COM_CheckParm("-nosound"))
{
Cvar_RegisterVariable(&snd_precache);
Cvar_RegisterVariable(&snd_initialized);
Cvar_RegisterVariable(&snd_streaming);
+ Cvar_RegisterVariable(&snd_streaming_length);
Cvar_RegisterVariable(&ambient_level);
Cvar_RegisterVariable(&ambient_fade);
Cvar_RegisterVariable(&snd_noextraupdate);
if(!strcmp (sfx->name, name))
return sfx;
+ // check for # in the beginning, try lookup by soundindex
+ if (name[0] == '#' && name[1])
+ {
+ int soundindex = atoi(name + 1);
+ if (soundindex > 0 && soundindex < MAX_SOUNDS)
+ if (cl.sound_precache[soundindex]->name[0])
+ return cl.sound_precache[soundindex];
+ }
+
// Add a sfx_t struct for this sound
sfx = (sfx_t *)Mem_Alloc (snd_mempool, sizeof (*sfx));
memset (sfx, 0, sizeof(*sfx));
}
// Free it
- if (sfx->fetcher != NULL && sfx->fetcher->free != NULL)
- sfx->fetcher->free (sfx->fetcher_data);
+ if (sfx->fetcher != NULL && sfx->fetcher->freesfx != NULL)
+ sfx->fetcher->freesfx(sfx);
Mem_Free (sfx);
}
channels[i].sfx = ambient_sfxs[i];
channels[i].sfx->flags |= SFXFLAG_MENUSOUND;
channels[i].flags |= CHANNELFLAG_FORCELOOP;
- channels[i].master_vol = 0;
+ channels[i].basevolume = 0.0f;
+ channels[i].basespeed = channels[i].mixspeed = 1.0f;
}
}
Picks a channel based on priorities, empty slots, number of channels
=================
*/
-channel_t *SND_PickChannel(int entnum, int entchannel)
+static channel_t *SND_PickChannel(int entnum, int entchannel)
{
int ch_idx;
int first_to_die;
// don't override looped sounds
if ((ch->flags & CHANNELFLAG_FORCELOOP) || sfx->loopstart < sfx->total_length)
continue;
- life_left = sfx->total_length - ch->pos;
+ life_left = (int)((double)sfx->total_length - ch->position);
if (life_left < first_life_left)
{
=================
*/
extern cvar_t cl_gameplayfix_soundsmovewithentities;
-void SND_Spatialize_WithSfx(channel_t *ch, qboolean isstatic, sfx_t *sfx)
+static void SND_Spatialize_WithSfx(channel_t *ch, qboolean isstatic, sfx_t *sfx)
{
int i;
double f;
- float angle_side, angle_front, angle_factor;
- vec_t dist, mastervol, intensity, vol;
+ float angle_side, angle_front, angle_factor, mixspeed;
+ vec_t dist, mastervol, intensity;
vec3_t source_vec;
+ char vabuf[1024];
// update sound origin if we know about the entity
if (ch->entnum > 0 && cls.state == ca_connected && cl_gameplayfix_soundsmovewithentities.integer)
else
Matrix4x4_OriginFromMatrix(&cl.entities[ch->entnum].render.matrix, ch->origin);
}
+ else if (cl.csqc_server2csqcentitynumber[ch->entnum])
+ {
+ //Con_Printf("-- entnum %i (client %i) origin %f %f %f neworigin %f %f %f\n", ch->entnum, cl.csqc_server2csqcentitynumber[ch->entnum], ch->origin[0], ch->origin[1], ch->origin[2], cl.entities[ch->entnum].state_current.origin[0], cl.entities[ch->entnum].state_current.origin[1], cl.entities[ch->entnum].state_current.origin[2]);
+
+ if (!CL_VM_GetEntitySoundOrigin(cl.csqc_server2csqcentitynumber[ch->entnum] + MAX_EDICTS, ch->origin))
+ ch->entnum = MAX_EDICTS; // entity was removed, disown sound
+ }
}
- mastervol = ch->master_vol;
+ mastervol = ch->basevolume;
+ mixspeed = ch->basespeed;
+
+ // TODO: implement doppler based on origin change relative to viewer and time of recent origin changes
// Adjust volume of static sounds
if (isstatic)
case 5: mastervol *= snd_channel5volume.value; break;
case 6: mastervol *= snd_channel6volume.value; break;
case 7: mastervol *= snd_channel7volume.value; break;
- default: mastervol *= Cvar_VariableValueOr(va("snd_channel%dvolume", CHAN_ENGINE2CVAR(ch->entchannel)), 1.0); break;
+ default: mastervol *= Cvar_VariableValueOr(va(vabuf, sizeof(vabuf), "snd_channel%dvolume", CHAN_ENGINE2CVAR(ch->entchannel)), 1.0); break;
}
}
if (!(ch->flags & CHANNELFLAG_FULLVOLUME))
mastervol *= volume.value;
- // clamp HERE to allow to go at most 10dB past mastervolume (before clamping), when mastervolume < -10dB (so relative volumes don't get too messy)
- mastervol = bound(0, mastervol, 655360);
+ if(snd_maxchannelvolume.value > 0)
+ {
+ // clamp HERE to allow to go at most 10dB past mastervolume (before clamping), when mastervolume < -10dB (so relative volumes don't get too messy)
+ mastervol = bound(0.0f, mastervol, 10.0f * snd_maxchannelvolume.value);
+ }
// always apply "master"
mastervol *= mastervolume.value;
// Replaygain support
// Con_DPrintf("Setting volume on ReplayGain-enabled track... %f -> ", fvol);
mastervol *= sfx->volume_mult;
- if(mastervol * sfx->volume_peak > 65536)
- mastervol = 65536 / sfx->volume_peak;
+ if(snd_maxchannelvolume.value > 0)
+ {
+ if(mastervol * sfx->volume_peak > snd_maxchannelvolume.value)
+ mastervol = snd_maxchannelvolume.value / sfx->volume_peak;
+ }
// Con_DPrintf("%f\n", fvol);
}
- // clamp HERE to keep relative volumes of the channels correct
- mastervol = bound(0, mastervol, 65536);
+ if(snd_maxchannelvolume.value > 0)
+ {
+ // clamp HERE to keep relative volumes of the channels correct
+ mastervol = min(mastervol, snd_maxchannelvolume.value);
+ }
+
+ mastervol = max(0.0f, mastervol);
+
+ ch->mixspeed = mixspeed;
// anything coming from the view entity will always be full volume
// LordHavoc: make sounds with ATTN_NONE have no spatialization
- if (ch->entnum == cl.viewentity || ch->dist_mult == 0)
+ if (ch->entnum == cl.viewentity || ch->distfade == 0)
{
ch->prologic_invert = 1;
if (snd_spatialization_prologic.integer != 0)
{
- vol = mastervol * snd_speakerlayout.listeners[0].ambientvolume * sqrt(0.5);
- ch->listener_volume[0] = (int)bound(0, vol, 65536);
- vol = mastervol * snd_speakerlayout.listeners[1].ambientvolume * sqrt(0.5);
- ch->listener_volume[1] = (int)bound(0, vol, 65536);
+ ch->volume[0] = mastervol * snd_speakerlayout.listeners[0].ambientvolume * sqrt(0.5);
+ ch->volume[1] = mastervol * snd_speakerlayout.listeners[1].ambientvolume * sqrt(0.5);
for (i = 2;i < SND_LISTENERS;i++)
- ch->listener_volume[i] = 0;
+ ch->volume[i] = 0;
}
else
{
for (i = 0;i < SND_LISTENERS;i++)
- {
- vol = mastervol * snd_speakerlayout.listeners[i].ambientvolume;
- ch->listener_volume[i] = (int)bound(0, vol, 65536);
- }
+ ch->volume[i] = mastervol * snd_speakerlayout.listeners[i].ambientvolume;
}
}
else
// calculate stereo seperation and distance attenuation
VectorSubtract(listener_origin, ch->origin, source_vec);
dist = VectorLength(source_vec);
- intensity = mastervol * (1.0 - dist * ch->dist_mult);
+ f = dist * ch->distfade;
+
+ f =
+ ((snd_attenuation_exponent.value == 0) ? 1.0 : pow(1.0 - min(1.0, f), (double)snd_attenuation_exponent.value))
+ *
+ ((snd_attenuation_decibel.value == 0) ? 1.0 : pow(0.1, 0.1 * snd_attenuation_decibel.value * f));
+
+ intensity = mastervol * f;
if (intensity > 0)
{
qboolean occluded = false;
occluded = true;
}
if(occluded)
- intensity *= 0.5;
+ intensity *= 0.5f;
ch->prologic_invert = 1;
if (snd_spatialization_prologic.integer != 0)
{
if (dist == 0)
- angle_factor = 0.5;
+ angle_factor = 0.5f;
else
{
Matrix4x4_Transform(&listener_basematrix, ch->origin, source_vec);
//angle_factor is between 0 and 1 and represents the angle range from the front left to the center to the front right speaker
}
- vol = intensity * sqrt(angle_factor);
- ch->listener_volume[0] = (int)bound(0, vol, 65536);
- vol = intensity * sqrt(1 - angle_factor);
- ch->listener_volume[1] = (int)bound(0, vol, 65536);
+ ch->volume[0] = intensity * sqrt(angle_factor);
+ ch->volume[1] = intensity * sqrt(1 - angle_factor);
for (i = 2;i < SND_LISTENERS;i++)
- ch->listener_volume[i] = 0;
+ ch->volume[i] = 0;
}
else
{
break;
}
- vol = intensity * max(0, source_vec[0] * snd_speakerlayout.listeners[i].dotscale + snd_speakerlayout.listeners[i].dotbias);
-
- ch->listener_volume[i] = (int)bound(0, vol, 65536);
+ ch->volume[i] = intensity * max(0, source_vec[0] * snd_speakerlayout.listeners[i].dotscale + snd_speakerlayout.listeners[i].dotbias);
}
}
}
else
for (i = 0;i < SND_LISTENERS;i++)
- ch->listener_volume[i] = 0;
+ ch->volume[i] = 0;
}
}
-void SND_Spatialize(channel_t *ch, qboolean isstatic)
+static void SND_Spatialize(channel_t *ch, qboolean isstatic)
{
sfx_t *sfx = ch->sfx;
SND_Spatialize_WithSfx(ch, isstatic, sfx);
// Start a sound effect
// =======================================================================
-void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, vec3_t origin, float fvol, float attenuation, qboolean isstatic, int entnum, int entchannel, int startpos)
+static void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, vec3_t origin, float fvol, float attenuation, qboolean isstatic, int entnum, int entchannel, int startpos, float fspeed)
{
if (!sfx)
{
memset (target_chan, 0, sizeof (*target_chan));
VectorCopy (origin, target_chan->origin);
target_chan->flags = flags;
- target_chan->pos = startpos; // start of the sound
+ target_chan->position = startpos; // start of the sound
target_chan->entnum = entnum;
target_chan->entchannel = entchannel;
{
if (sfx->loopstart >= sfx->total_length && (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEWORLD))
Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name);
- target_chan->dist_mult = attenuation / (64.0f * snd_soundradius.value);
+ target_chan->distfade = attenuation / (64.0f * snd_soundradius.value);
}
else
- target_chan->dist_mult = attenuation / snd_soundradius.value;
+ target_chan->distfade = attenuation / snd_soundradius.value;
// set the listener volumes
S_SetChannelVolume(target_chan - channels, fvol);
+ S_SetChannelSpeed(target_chan - channels, fspeed);
SND_Spatialize_WithSfx (target_chan, isstatic, sfx);
// finally, set the sfx pointer, so the channel becomes valid for playback
}
-int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition, int flags)
+int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition, int flags, float fspeed)
{
channel_t *target_chan, *check, *ch;
int ch_idx, startpos;
if (ch->entnum == entnum && ch->entchannel == entchannel)
{
S_SetChannelVolume(ch_idx, fvol);
- ch->dist_mult = attenuation / snd_soundradius.value;
+ S_SetChannelSpeed(ch_idx, fspeed);
+ ch->distfade = attenuation / snd_soundradius.value;
SND_Spatialize(ch, false);
return ch_idx;
}
// if an identical sound has also been started this frame, offset the pos
// a bit to keep it from just making the first one louder
check = &channels[NUM_AMBIENTS];
- startpos = (int)(startposition * S_GetSoundRate());
+ startpos = (int)(startposition * sfx->format.speed);
if (startpos == 0)
{
for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
{
if (check == target_chan)
continue;
- if (check->sfx == sfx && check->pos == 0)
+ if (check->sfx == sfx && check->position == 0 && check->basespeed == fspeed)
{
+ // calculate max offset
+ float maxtime = snd_identicalsoundrandomization_time.value;
+ float maxtics = snd_identicalsoundrandomization_tics.value;
+ float maxticsdelta = ((cls.state == ca_connected) ? (maxtics * (cl.mtime[0] - cl.mtime[1])) : 0);
+ float maxdelta = 0;
+ if(maxticsdelta == 0 || fabs(maxticsdelta) > fabs(maxtime))
+ maxdelta = maxtime;
+ else
+ maxdelta = fabs(maxticsdelta) * ((maxtime > 0) ? 1 : -1);
+
// use negative pos offset to delay this sound effect
- startpos = (int)lhrandom(0, -0.1 * snd_renderbuffer->format.speed);
+ startpos = lhrandom(0, maxdelta * sfx->format.speed);
break;
}
}
}
- S_PlaySfxOnChannel (sfx, target_chan, flags, origin, fvol, attenuation, false, entnum, entchannel, startpos);
+ S_PlaySfxOnChannel (sfx, target_chan, flags, origin, fvol, attenuation, false, entnum, entchannel, startpos, fspeed);
return (target_chan - channels);
}
-int S_StartSound_StartPosition (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition)
-{
- return S_StartSound_StartPosition_Flags(entnum, entchannel, sfx, origin, fvol, attenuation, startposition, CHANNELFLAG_NONE);
-}
-
int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
{
- return S_StartSound_StartPosition(entnum, entchannel, sfx, origin, fvol, attenuation, 0);
+ return S_StartSound_StartPosition_Flags(entnum, entchannel, sfx, origin, fvol, attenuation, 0, CHANNELFLAG_NONE, 1.0f);
}
void S_StopChannel (unsigned int channel_ind, qboolean lockmutex, qboolean freesfx)
sfx = ch->sfx;
if (ch->sfx != NULL)
{
- if (sfx->fetcher != NULL)
- {
- snd_fetcher_endsb_t fetcher_endsb = sfx->fetcher->endsb;
- if (fetcher_endsb != NULL)
- fetcher_endsb (ch->fetcher_data);
- }
-
+ if (sfx->fetcher != NULL && sfx->fetcher->stopchannel != NULL)
+ sfx->fetcher->stopchannel(ch);
ch->fetcher_data = NULL;
ch->sfx = NULL;
}
}
}
-extern void CDAudio_Stop(void);
void S_StopAllSounds (void)
{
unsigned int i;
void S_SetChannelVolume(unsigned int ch_ind, float fvol)
{
- channels[ch_ind].master_vol = (int)(fvol * 65536.0f);
+ channels[ch_ind].basevolume = fvol;
+}
+
+void S_SetChannelSpeed(unsigned int ch_ind, float fspeed)
+{
+ channels[ch_ind].basespeed = fspeed;
}
float S_GetChannelPosition (unsigned int ch_ind)
{
// note: this is NOT accurate yet
- int s;
+ double s;
channel_t *ch = &channels[ch_ind];
sfx_t *sfx = ch->sfx;
if (!sfx)
return -1;
- s = ch->pos;
+ s = ch->position / sfx->format.speed;
/*
if(!snd_usethreadedmixing)
- s += _snd_mixahead.value * S_GetSoundRate();
+ s += _snd_mixahead.value;
*/
- return (s % sfx->total_length) / (float) S_GetSoundRate();
+ return (float)s;
}
float S_GetEntChannelPosition(int entnum, int entchannel)
}
target_chan = &channels[total_channels++];
- S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_FORCELOOP, origin, fvol, attenuation, true, 0, 0, 0);
+ S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_FORCELOOP, origin, fvol, attenuation, true, 0, 0, 0, 1.0f);
}
S_UpdateAmbientSounds
===================
*/
-void S_UpdateAmbientSounds (void)
+static void S_UpdateAmbientSounds (void)
{
int i;
- int vol;
+ float vol;
+ float fade = (float)max(0.0, cl.time - cl.oldtime) * ambient_fade.value / 256.0f;
int ambient_channel;
channel_t *chan;
unsigned char ambientlevels[NUM_AMBIENTS];
if (sfx == NULL || sfx->fetcher == NULL)
continue;
- vol = (int)ambientlevels[ambient_channel];
- if (vol < 8)
- vol = 0;
- vol *= 256;
+ i = ambientlevels[ambient_channel];
+ if (i < 8)
+ i = 0;
+ vol = i * (1.0f / 256.0f);
// Don't adjust volume too fast
- // FIXME: this rounds off to an int each frame, meaning there is little to no fade at extremely high framerates!
- if (cl.time > cl.oldtime)
+ if (chan->basevolume < vol)
{
- if (chan->master_vol < vol)
- {
- chan->master_vol += (int)((cl.time - cl.oldtime) * 256.0 * ambient_fade.value);
- if (chan->master_vol > vol)
- chan->master_vol = vol;
- }
- else if (chan->master_vol > vol)
- {
- chan->master_vol -= (int)((cl.time - cl.oldtime) * 256.0 * ambient_fade.value);
- if (chan->master_vol < vol)
- chan->master_vol = vol;
- }
+ chan->basevolume += fade;
+ if (chan->basevolume > vol)
+ chan->basevolume = vol;
+ }
+ else if (chan->basevolume > vol)
+ {
+ chan->basevolume -= fade;
+ if (chan->basevolume < vol)
+ chan->basevolume = vol;
}
if (snd_spatialization_prologic.integer != 0)
{
- chan->listener_volume[0] = (int)bound(0, chan->master_vol * ambient_level.value * volume.value * mastervolume.value * snd_speakerlayout.listeners[0].ambientvolume * sqrt(0.5), 65536);
- chan->listener_volume[1] = (int)bound(0, chan->master_vol * ambient_level.value * volume.value * mastervolume.value * snd_speakerlayout.listeners[1].ambientvolume * sqrt(0.5), 65536);
+ chan->volume[0] = chan->basevolume * ambient_level.value * volume.value * mastervolume.value * snd_speakerlayout.listeners[0].ambientvolume * sqrt(0.5);
+ chan->volume[1] = chan->basevolume * ambient_level.value * volume.value * mastervolume.value * snd_speakerlayout.listeners[1].ambientvolume * sqrt(0.5);
for (i = 2;i < SND_LISTENERS;i++)
- chan->listener_volume[i] = 0;
+ chan->volume[i] = 0.0f;
}
else
{
for (i = 0;i < SND_LISTENERS;i++)
- chan->listener_volume[i] = (int)bound(0, chan->master_vol * ambient_level.value * volume.value * mastervolume.value * snd_speakerlayout.listeners[i].ambientvolume, 65536);
+ chan->volume[i] = chan->basevolume * ambient_level.value * volume.value * mastervolume.value * snd_speakerlayout.listeners[i].ambientvolume;
}
}
}
{
// no need to merge silent channels
for (j = 0;j < SND_LISTENERS;j++)
- if (ch->listener_volume[j])
+ if (ch->volume[j])
break;
if (j == SND_LISTENERS)
continue;
{
for (j = 0;j < SND_LISTENERS;j++)
{
- combine->listener_volume[j] = bound(0, combine->listener_volume[j] + ch->listener_volume[j], 65536);
- ch->listener_volume[j] = 0;
+ combine->volume[j] += ch->volume[j];
+ ch->volume[j] = 0;
}
}
}
for (k = 0;k < SND_LISTENERS;k++)
- if (ch->listener_volume[k])
+ if (ch->volume[k])
break;
if (k < SND_LISTENERS)
cls.soundstats.mixedsounds++;
sfx_t *next;
size_t memsize; // total memory used (including sfx_t and fetcher data)
+ snd_format_t format; // format describing the audio data that fetcher->getsamplesfloat will return
unsigned int flags; // cf SFXFLAG_* defines
unsigned int loopstart; // in sample frames. equals total_length if not looped
unsigned int total_length; // in sample frames
typedef struct channel_s
{
- int listener_volume [SND_LISTENERS]; // 0-65536 volume per speaker
- int master_vol; // 0-65536 master volume
+ // provided sound information
sfx_t *sfx; // pointer to sound sample being used
+ float basevolume; // 0-1 master volume
unsigned int flags; // cf CHANNELFLAG_* defines
- int pos; // sample position in sfx, negative values delay the start of the sound playback
- int entnum; // to allow overriding a specific sound
- int entchannel;
+ int entnum; // makes sound follow entity origin (allows replacing interrupting existing sound on same id)
+ int entchannel; // which channel id on the entity
vec3_t origin; // origin of sound effect
- vec_t dist_mult; // distance multiplier (attenuation/clipK)
+ vec_t distfade; // distance multiplier (attenuation/clipK)
void *fetcher_data; // Per-channel data for the sound fetching function
int prologic_invert;// whether a sound is played on the surround channels in prologic
+ float basespeed; // playback rate multiplier for pitch variation
+
+ // these are often updated while mixer is running, glitching should be minimized (mismatched channel volumes from spatialization is okay)
+ // spatialized playback speed (speed * doppler ratio)
+ float mixspeed;
+ // spatialized volume per speaker (mastervol * distanceattenuation * channelvolume cvars)
+ float volume[SND_LISTENERS];
+
+ // updated ONLY by mixer
+ // position in sfx, starts at 0, loops or stops at sfx->total_length
+ double position;
} channel_t;
// Sound fetching functions
// "start" is both an input and output parameter: it returns the actual start time of the sound buffer
-typedef const snd_buffer_t* (*snd_fetcher_getsb_t) (void *sfxfetcher, void **chfetcherpointer, unsigned int *start, unsigned int nbsampleframes);
-typedef void (*snd_fetcher_endsb_t) (void *chfetcherdata);
-typedef void (*snd_fetcher_free_t) (void *sfxfetcherdata);
-typedef const snd_format_t* (*snd_fetcher_getfmt_t) (sfx_t* sfx);
+typedef void (*snd_fetcher_getsamplesfloat_t) (channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat);
+typedef void (*snd_fetcher_stopchannel_t) (channel_t *ch);
+typedef void (*snd_fetcher_freesfx_t) (sfx_t *sfx);
struct snd_fetcher_s
{
- snd_fetcher_getsb_t getsb;
- snd_fetcher_endsb_t endsb;
- snd_fetcher_free_t free;
- snd_fetcher_getfmt_t getfmt;
+ snd_fetcher_getsamplesfloat_t getsamplesfloat;
+ snd_fetcher_stopchannel_t stopchannel;
+ snd_fetcher_freesfx_t freesfx;
};
extern unsigned int total_channels;
extern cvar_t _snd_mixahead;
extern cvar_t snd_swapstereo;
extern cvar_t snd_streaming;
+extern cvar_t snd_streaming_length;
#define SND_CHANNELLAYOUT_AUTO 0
#define SND_CHANNELLAYOUT_STANDARD 1
extern qboolean simsound;
-#define STREAM_BUFFER_DURATION 0.3f // in seconds
-#define STREAM_BUFFER_FILL 0.2f // in seconds
-#define STREAM_BUFFER_SIZE(format_ptr) ((int)ceil (STREAM_BUFFER_DURATION * (format_ptr)->speed) * (format_ptr)->width * (format_ptr)->channels)
-
-// We work with 1 sec sequences, so this buffer must be able to contain
-// 1 sec of sound of the highest quality (48 KHz, 16 bit samples, stereo)
-extern unsigned char resampling_buffer [48000 * 2 * 2];
+#define STREAM_BUFFERSIZE 16384 // in sampleframes
// ====================================================================
// exported for capturevideo so ogg can see all channels
typedef struct portable_samplepair_s
{
- int sample[SND_LISTENERS];
+ float sample[SND_LISTENERS];
} portable_sampleframe_t;
typedef struct listener_s
#include "snd_wav.h"
#include "snd_modplug.h"
-unsigned char resampling_buffer [48000 * 2 * 2];
-
/*
====================
#include "quakedef.h"
#include "snd_main.h"
+extern cvar_t snd_softclip;
static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
extern speakerlayout_t snd_speakerlayout; // for querying the listeners
-extern void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length);
-static void S_CaptureAVISound(size_t length)
+static void S_CaptureAVISound(const portable_sampleframe_t *paintbuffer, size_t length)
{
size_t i;
unsigned int j;
SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
}
-static void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
+extern cvar_t snd_softclip;
+
+static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int channels)
+{
+ int i;
+
+ if((snd_softclip.integer == 1 && width <= 2) || snd_softclip.integer > 1)
+ {
+ portable_sampleframe_t *p = painted_ptr;
+
+#if 0
+/* Soft clipping, the sound of a dream, thanks to Jon Wattes
+ post to Musicdsp.org */
+#define SOFTCLIP(x) (x) = sin(bound(-M_PI/2, (x), M_PI/2)) * 0.25
+#endif
+
+ // let's do a simple limiter instead, seems to sound better
+ static float maxvol = 0;
+ maxvol = max(1.0f, maxvol * (1.0f - nbframes / (0.4f * snd_renderbuffer->format.speed)));
+#define SOFTCLIP(x) if(fabs(x)>maxvol) maxvol=fabs(x); (x) /= maxvol;
+
+ if (channels == 8) // 7.1 surround
+ {
+ for (i = 0;i < nbframes;i++, p++)
+ {
+ SOFTCLIP(p->sample[0]);
+ SOFTCLIP(p->sample[1]);
+ SOFTCLIP(p->sample[2]);
+ SOFTCLIP(p->sample[3]);
+ SOFTCLIP(p->sample[4]);
+ SOFTCLIP(p->sample[5]);
+ SOFTCLIP(p->sample[6]);
+ SOFTCLIP(p->sample[7]);
+ }
+ }
+ else if (channels == 6) // 5.1 surround
+ {
+ for (i = 0; i < nbframes; i++, p++)
+ {
+ SOFTCLIP(p->sample[0]);
+ SOFTCLIP(p->sample[1]);
+ SOFTCLIP(p->sample[2]);
+ SOFTCLIP(p->sample[3]);
+ SOFTCLIP(p->sample[4]);
+ SOFTCLIP(p->sample[5]);
+ }
+ }
+ else if (channels == 4) // 4.0 surround
+ {
+ for (i = 0; i < nbframes; i++, p++)
+ {
+ SOFTCLIP(p->sample[0]);
+ SOFTCLIP(p->sample[1]);
+ SOFTCLIP(p->sample[2]);
+ SOFTCLIP(p->sample[3]);
+ }
+ }
+ else if (channels == 2) // 2.0 stereo
+ {
+ for (i = 0; i < nbframes; i++, p++)
+ {
+ SOFTCLIP(p->sample[0]);
+ SOFTCLIP(p->sample[1]);
+ }
+ }
+ else if (channels == 1) // 1.0 mono
+ {
+ for (i = 0; i < nbframes; i++, p++)
+ {
+ SOFTCLIP(p->sample[0]);
+ }
+ }
+#undef SOFTCLIP
+ }
+}
+
+static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
{
int i, val;
+
+ // FIXME: add 24bit and 32bit float formats
+ // FIXME: optimize with SSE intrinsics?
if (width == 2) // 16bit
{
short *snd_out = (short*)rb_ptr;
{
for (i = 0;i < nbframes;i++, painted_ptr++)
{
- *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
+ val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[6] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[7] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
}
}
else if (channels == 6) // 5.1 surround
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
+ val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
}
}
else if (channels == 4) // 4.0 surround
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
+ val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
}
}
else if (channels == 2) // 2.0 stereo
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
- *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
+ val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
+ val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
}
}
else if (channels == 1) // 1.0 mono
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
- *snd_out++ = bound(-32768, val, 32767);
+ val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 16384.0f);*snd_out++ = bound(-32768, val, 32767);
}
}
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[6] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[7] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
}
}
else if (channels == 6) // 5.1 surround
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
}
}
else if (channels == 4) // 4.0 surround
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
}
}
else if (channels == 2) // 2.0 stereo
{
for (i = 0; i < nbframes; i++, painted_ptr++)
{
- val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
- val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
+ val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
}
}
else if (channels == 1) // 1.0 mono
{
for (i = 0;i < nbframes;i++, painted_ptr++)
{
- val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
- *snd_out++ = bound(0, val, 255);
+ val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 64.0f) + 128; *snd_out++ = bound(0, val, 255);
}
}
===============================================================================
*/
-static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
-{
- int vol[SND_LISTENERS];
- const snd_buffer_t *sb;
- unsigned int i, sb_offset;
- sfx_t *sfx;
-
- sfx = ch->sfx; // fetch the volatile variable
- if (!sfx) // given that this is called by the mixer thread, this never happens, but...
- return false;
-
- // move to the stack (do we need to?)
- for (i = 0;i < SND_LISTENERS;i++)
- vol[i] = ch->listener_volume[i];
-
- // if volumes are all zero, just return
- for (i = 0;i < SND_LISTENERS;i++)
- if (vol[i])
- break;
- if (i == SND_LISTENERS)
- return false;
-
- sb_offset = ch->pos;
- sb = sfx->fetcher->getsb (sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
- if (sb == NULL)
- {
- Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
- sfx->name); // , count); // or add this? FIXME
- return false;
- }
- else
- {
-#if SND_LISTENERS != 8
-# error the following code only supports up to 8 channels, update it
-#endif
- if (sb->format.width == 1)
- {
- const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
-
- // Stereo sound support
- if (sb->format.channels == 2)
- {
- if (vol[6] + vol[7] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
- paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
- paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
- paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
- paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
- samples += 2;
- }
- }
- else if (vol[4] + vol[5] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
- paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
- paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
- samples += 2;
- }
- }
- else if (vol[2] + vol[3] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
- samples += 2;
- }
- }
- else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] -= (samples[1] * vol[1]) >> 8;
- samples += 2;
- }
- }
- else if (vol[0] + vol[1] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
- samples += 2;
- }
- }
- }
- else if (sb->format.channels == 1)
- {
- if (vol[6] + vol[7] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
- paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
- paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
- paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
- paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
- samples += 1;
- }
- }
- else if (vol[4] + vol[5] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
- paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
- paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
- samples += 1;
- }
- }
- else if (vol[2] + vol[3] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
- paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
- samples += 1;
- }
- }
- else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] -= (samples[0] * vol[1]) >> 8;
- samples += 1;
- }
- }
- else if (vol[0] + vol[1] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
- samples += 1;
- }
- }
- }
- else
- return false; // unsupported number of channels in sound
- }
- else if (sb->format.width == 2)
- {
- const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
-
- // Stereo sound support
- if (sb->format.channels == 2)
- {
- if (vol[6] + vol[7] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
- paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
- paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
- paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
- paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
- samples += 2;
- }
- }
- else if (vol[4] + vol[5] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
- paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
- paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
- samples += 2;
- }
- }
- else if (vol[2] + vol[3] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
- samples += 2;
- }
- }
- else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] -= (samples[1] * vol[1]) >> 16;
- samples += 2;
- }
- }
- else if (vol[0] + vol[1] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
- samples += 2;
- }
- }
- }
- else if (sb->format.channels == 1)
- {
- if (vol[6] + vol[7] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
- paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
- paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
- paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
- paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
- samples += 1;
- }
- }
- else if (vol[4] + vol[5] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
- paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
- paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
- samples += 1;
- }
- }
- else if (vol[2] + vol[3] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
- paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
- paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
- samples += 1;
- }
- }
- else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] -= (samples[0] * vol[1]) >> 16;
- samples += 1;
- }
- }
- else if (vol[0] + vol[1] > 0)
- {
- for (i = 0;i < count;i++)
- {
- paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
- paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
- samples += 1;
- }
- }
- }
- else
- return false; // unsupported number of channels in sound
- }
- }
- return true;
-}
-
void S_MixToBuffer(void *stream, unsigned int bufferframes)
{
- unsigned int i;
+ int channelindex;
channel_t *ch;
- unsigned int frames;
+ int totalmixframes;
unsigned char *outbytes = (unsigned char *) stream;
+ sfx_t *sfx;
+ portable_sampleframe_t *paint;
+ int wantframes;
+ int i;
+ int count;
+ int fetched;
+ int fetch;
+ int istartframe;
+ int iendframe;
+ int ilengthframes;
+ int totallength;
+ int loopstart;
+ int indexfrac;
+ int indexfracstep;
+#define S_FETCHBUFFERSIZE 4096
+ float fetchsampleframes[S_FETCHBUFFERSIZE*2];
+ const float *fetchsampleframe;
+ float vol[SND_LISTENERS];
+ float lerp[2];
+ float sample[3];
+ double posd;
+ double speedd;
+ float maxvol;
+ qboolean looping;
+ qboolean silent;
// mix as many times as needed to fill the requested buffer
while (bufferframes)
{
// limit to the size of the paint buffer
- frames = min(bufferframes, PAINTBUFFER_SIZE);
+ totalmixframes = min(bufferframes, PAINTBUFFER_SIZE);
// clear the paint buffer
- memset (paintbuffer, 0, frames * sizeof (paintbuffer[0]));
+ memset(paintbuffer, 0, totalmixframes * sizeof(paintbuffer[0]));
// paint in the channels.
// channels with zero volumes still advance in time but don't paint.
ch = channels;
- for (i = 0; i < total_channels ; i++, ch++)
+ for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
{
- sfx_t *sfx;
- int ltime;
- int count;
-
sfx = ch->sfx;
if (sfx == NULL)
continue;
continue;
if (!sfx->total_length)
continue;
- if (sfx->total_length > 1<<30)
- Sys_Error("S_MixToBuffer: sfx corrupt\n");
- ltime = 0;
- if (ch->pos < 0)
+ // copy the channel information to the stack for reference, otherwise the
+ // values might change during a mix if the spatializer is updating them
+ // (note: this still may get some old and some new values!)
+ posd = ch->position;
+ speedd = ch->mixspeed * sfx->format.speed / snd_renderbuffer->format.speed;
+ for (i = 0;i < SND_LISTENERS;i++)
+ vol[i] = ch->volume[i];
+
+ // check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly)
+ maxvol = 0;
+ for (i = 0;i < SND_LISTENERS;i++)
+ if(vol[i] > maxvol)
+ maxvol = vol[i];
+ switch(snd_renderbuffer->format.width)
{
- count = -ch->pos;
- count = min(count, (int)frames - ltime);
- ch->pos += count;
- ltime += count;
+ case 1: // 8bpp
+ silent = maxvol < (1.0f / (256.0f));
+ // so silent it has zero effect
+ break;
+ case 2: // 16bpp
+ silent = maxvol < (1.0f / (65536.0f));
+ // so silent it has zero effect
+ break;
+ default: // floating point
+ silent = maxvol < 1.0e-13f;
+ // 130 dB is difference between hearing
+ // threshold and a jackhammer from
+ // working distance.
+ // therefore, anyone who turns up
+ // volume so much they notice this
+ // cutoff, likely already has their
+ // ear-drums blown out anyway.
+ break;
}
- while (ltime < (int)frames)
+ // when doing prologic mixing, some channels invert one side
+ if (ch->prologic_invert == -1)
+ vol[1] *= -1.0f;
+
+ // get some sfx info in a consistent form
+ totallength = sfx->total_length;
+ loopstart = (int)sfx->loopstart < totallength ? (int)sfx->loopstart : ((ch->flags & CHANNELFLAG_FORCELOOP) ? 0 : totallength);
+ looping = loopstart < totallength;
+
+ // do the actual paint now (may skip work if silent)
+ paint = paintbuffer;
+ wantframes = totalmixframes;
+ istartframe = 0;
+ for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
{
- // paint up to end of buffer or of input, whichever is lower
- count = sfx->total_length - ch->pos;
- count = bound(0, count, (int)frames - ltime);
- // mix the remaining samples
- if (count)
+ // check if this is a delayed sound
+ if (posd < 0)
+ {
+ // for a delayed sound we have to eat into the delay first
+ count = (int)floor(-posd / speedd) + 1;
+ count = bound(1, count, wantframes);
+ // let the for loop iterator apply the skip
+ continue;
+ }
+
+ // compute a fetch size that won't overflow our buffer
+ count = wantframes;
+ for (;;)
{
- SND_PaintChannel (ch, paintbuffer + ltime, count);
- ch->pos += count;
- ltime += count;
+ istartframe = (int)floor(posd);
+ iendframe = (int)floor(posd + (count-1) * speedd);
+ ilengthframes = count > 1 ? (iendframe - istartframe + 2) : 2;
+ if (ilengthframes <= S_FETCHBUFFERSIZE)
+ break;
+ // reduce count by 25% and try again
+ count -= count >> 2;
}
- // if at end of sfx, loop or stop the channel
- else
+
+ // zero whole fetch buffer for safety
+ // (floating point noise from uninitialized memory = HORRIBLE)
+ // otherwise we would only need to clear the excess
+ if (!silent)
+ memset(fetchsampleframes, 0, ilengthframes*sfx->format.channels*sizeof(fetchsampleframes[0]));
+
+ // if looping, do multiple fetches
+ fetched = 0;
+ for (;;)
{
- if (sfx->loopstart < sfx->total_length)
- ch->pos = sfx->loopstart;
- else if (ch->flags & CHANNELFLAG_FORCELOOP)
- ch->pos = 0;
+ fetch = min(ilengthframes - fetched, totallength - istartframe);
+ if (fetch > 0)
+ {
+ if (!silent)
+ sfx->fetcher->getsamplesfloat(ch, sfx, istartframe, fetch, fetchsampleframes + fetched*sfx->format.channels);
+ istartframe += fetch;
+ fetched += fetch;
+ }
+ if (istartframe == totallength && looping && fetched < ilengthframes)
+ {
+ // loop and fetch some more
+ posd += loopstart - totallength;
+ istartframe = loopstart;
+ }
else
{
- S_StopChannel (ch - channels, false, false);
break;
}
}
+
+ // set up our fixedpoint resampling variables (float to int conversions are expensive so do not do one per sampleframe)
+ fetchsampleframe = fetchsampleframes;
+ indexfrac = (int)floor((posd - floor(posd)) * 65536.0);
+ indexfracstep = (int)floor(speedd * 65536.0);
+ if (!silent)
+ {
+ if (sfx->format.channels == 2)
+ {
+ // music is stereo
+#if SND_LISTENERS != 8
+#error the following code only supports up to 8 channels, update it
+#endif
+ if (snd_speakerlayout.channels > 2)
+ {
+ // surround mixing
+ for (i = 0;i < count;i++, paint++)
+ {
+ lerp[1] = indexfrac * (1.0f / 65536.0f);
+ lerp[0] = 1.0f - lerp[1];
+ sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
+ sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
+ sample[2] = (sample[0] + sample[1]) * 0.5f;
+ paint->sample[0] += sample[0] * vol[0];
+ paint->sample[1] += sample[1] * vol[1];
+ paint->sample[2] += sample[0] * vol[2];
+ paint->sample[3] += sample[1] * vol[3];
+ paint->sample[4] += sample[2] * vol[4];
+ paint->sample[5] += sample[2] * vol[5];
+ paint->sample[6] += sample[0] * vol[6];
+ paint->sample[7] += sample[1] * vol[7];
+ indexfrac += indexfracstep;
+ fetchsampleframe += 2 * (indexfrac >> 16);
+ indexfrac &= 0xFFFF;
+ }
+ }
+ else
+ {
+ // stereo mixing
+ for (i = 0;i < count;i++, paint++)
+ {
+ lerp[1] = indexfrac * (1.0f / 65536.0f);
+ lerp[0] = 1.0f - lerp[1];
+ sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
+ sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
+ paint->sample[0] += sample[0] * vol[0];
+ paint->sample[1] += sample[1] * vol[1];
+ indexfrac += indexfracstep;
+ fetchsampleframe += 2 * (indexfrac >> 16);
+ indexfrac &= 0xFFFF;
+ }
+ }
+ }
+ else if (sfx->format.channels == 1)
+ {
+ // most sounds are mono
+#if SND_LISTENERS != 8
+#error the following code only supports up to 8 channels, update it
+#endif
+ if (snd_speakerlayout.channels > 2)
+ {
+ // surround mixing
+ for (i = 0;i < count;i++, paint++)
+ {
+ lerp[1] = indexfrac * (1.0f / 65536.0f);
+ lerp[0] = 1.0f - lerp[1];
+ sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
+ paint->sample[0] += sample[0] * vol[0];
+ paint->sample[1] += sample[0] * vol[1];
+ paint->sample[2] += sample[0] * vol[2];
+ paint->sample[3] += sample[0] * vol[3];
+ paint->sample[4] += sample[0] * vol[4];
+ paint->sample[5] += sample[0] * vol[5];
+ paint->sample[6] += sample[0] * vol[6];
+ paint->sample[7] += sample[0] * vol[7];
+ indexfrac += indexfracstep;
+ fetchsampleframe += (indexfrac >> 16);
+ indexfrac &= 0xFFFF;
+ }
+ }
+ else
+ {
+ // stereo mixing
+ for (i = 0;i < count;i++, paint++)
+ {
+ lerp[1] = indexfrac * (1.0f / 65536.0f);
+ lerp[0] = 1.0f - lerp[1];
+ sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
+ paint->sample[0] += sample[0] * vol[0];
+ paint->sample[1] += sample[0] * vol[1];
+ indexfrac += indexfracstep;
+ fetchsampleframe += (indexfrac >> 16);
+ indexfrac &= 0xFFFF;
+ }
+ }
+ }
+ }
}
+ ch->position = posd;
+ if (!looping && istartframe == totallength)
+ S_StopChannel(ch - channels, false, false);
}
+ S_SoftClipPaintBuffer(paintbuffer, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
+
if (!snd_usethreadedmixing)
- S_CaptureAVISound(frames);
+ S_CaptureAVISound(paintbuffer, totalmixframes);
- S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
+ S_ConvertPaintBuffer(paintbuffer, outbytes, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
// advance the output pointer
- outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
- bufferframes -= frames;
+ outbytes += totalmixframes * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
+ bufferframes -= totalmixframes;
}
}
{
unsigned char *file;
size_t filesize;
- snd_format_t format;
- unsigned int total_length;
- char name[128];
- sfx_t *sfx;
} modplug_stream_persfx_t;
// Per-channel data structure
typedef struct
{
ModPlugFile *mf;
- unsigned int sb_offset;
int bs;
- snd_buffer_t sb; // must be at the end due to its dynamically allocated size
+ int buffer_firstframe;
+ int buffer_numframes;
+ unsigned char buffer[STREAM_BUFFERSIZE*4];
} modplug_stream_perchannel_t;
/*
====================
-ModPlug_FetchSound
+ModPlug_GetSamplesFloat
====================
*/
-static const snd_buffer_t* ModPlug_FetchSound (void *sfxfetcher, void **chfetcherpointer, unsigned int *start, unsigned int nbsampleframes)
+static void ModPlug_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
{
- modplug_stream_perchannel_t* per_ch = (modplug_stream_perchannel_t *)*chfetcherpointer;
- modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfxfetcher;
- snd_buffer_t* sb;
+ modplug_stream_perchannel_t* per_ch = (modplug_stream_perchannel_t *)ch->fetcher_data;
+ modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfx->fetcher_data;
int newlength, done, ret;
- unsigned int real_start;
- unsigned int factor;
+ int f = sfx->format.width * sfx->format.channels; // bytes per frame
+ short *buf;
+ int i, len;
// If there's no fetcher structure attached to the channel yet
if (per_ch == NULL)
{
- size_t buff_len, memsize;
- snd_format_t sb_format;
-
- sb_format.speed = snd_renderbuffer->format.speed;
- sb_format.width = per_sfx->format.width;
- sb_format.channels = per_sfx->format.channels;
-
- buff_len = STREAM_BUFFER_SIZE(&sb_format);
- memsize = sizeof (*per_ch) - sizeof (per_ch->sb.samples) + buff_len;
- per_ch = (modplug_stream_perchannel_t *)Mem_Alloc (snd_mempool, memsize);
+ per_ch = (modplug_stream_perchannel_t *)Mem_Alloc(snd_mempool, sizeof(*per_ch));
// Open it with the modplugFile API
per_ch->mf = qModPlug_Load(per_sfx->file, per_sfx->filesize);
if (!per_ch->mf)
{
- Con_Printf("error while reading ModPlug stream \"%s\"\n", per_sfx->name);
- Mem_Free (per_ch);
- return NULL;
+ // we can't call Con_Printf here, not thread safe
+// Con_Printf("error while reading ModPlug stream \"%s\"\n", per_sfx->name);
+ Mem_Free(per_ch);
+ return;
}
#ifndef SND_MODPLUG_STATIC
per_ch->bs = 0;
- per_ch->sb_offset = 0;
- per_ch->sb.format = sb_format;
- per_ch->sb.nbframes = 0;
- per_ch->sb.maxframes = buff_len / (per_ch->sb.format.channels * per_ch->sb.format.width);
-
- *chfetcherpointer = per_ch;
+ per_ch->buffer_firstframe = 0;
+ per_ch->buffer_numframes = 0;
+ ch->fetcher_data = per_ch;
}
- real_start = *start;
-
- sb = &per_ch->sb;
- factor = per_sfx->format.width * per_sfx->format.channels;
-
- // If the stream buffer can't contain that much samples anyway
- if (nbsampleframes > sb->maxframes)
+ // if the request is too large for our buffer, loop...
+ while (numsampleframes * f > (int)sizeof(per_ch->buffer))
{
- Con_Printf ("ModPlug_FetchSound: stream buffer too small (%u sample frames required)\n", nbsampleframes);
- return NULL;
+ done = sizeof(per_ch->buffer) / f;
+ ModPlug_GetSamplesFloat(ch, sfx, firstsampleframe, done, outsamplesfloat);
+ firstsampleframe += done;
+ numsampleframes -= done;
+ outsamplesfloat += done * sfx->format.channels;
}
- // If the data we need has already been decompressed in the sfxbuffer, just return it
- if (per_ch->sb_offset <= real_start && per_ch->sb_offset + sb->nbframes >= real_start + nbsampleframes)
+ // seek if the request is before the current buffer (loop back)
+ // seek if the request starts beyond the current buffer by at least one frame (channel was zero volume for a while)
+ // do not seek if the request overlaps the buffer end at all (expected behavior)
+ if (per_ch->buffer_firstframe > firstsampleframe || per_ch->buffer_firstframe + per_ch->buffer_numframes < firstsampleframe)
{
- *start = per_ch->sb_offset;
- return sb;
+ // we expect to decode forward from here so this will be our new buffer start
+ per_ch->buffer_firstframe = firstsampleframe;
+ per_ch->buffer_numframes = 0;
+ // we don't actually seek - we don't care much about timing on silent mod music streams and looping never happens
+ //qModPlug_Seek(per_ch->mf, firstsampleframe * 1000.0 / sfx->format.speed);
}
- newlength = (int)(per_ch->sb_offset + sb->nbframes) - real_start;
-
- // If we need to skip some data before decompressing the rest, or if the stream has looped
- if (newlength < 0 || per_ch->sb_offset > real_start)
+ // decompress the file as needed
+ if (firstsampleframe + numsampleframes > per_ch->buffer_firstframe + per_ch->buffer_numframes)
{
- unsigned int time_start;
- unsigned int modplug_start;
-
- /*
- MODs loop on their own, so any position is valid!
- if (real_start > (unsigned int)per_sfx->total_length)
- {
- Con_Printf ("ModPlug_FetchSound: asked for a start position after the end of the sfx! (%u > %u)\n",
- real_start, per_sfx->total_length);
- return NULL;
- }
- */
-
- // We work with 200ms (1/5 sec) steps to avoid rounding errors
- time_start = real_start * 5 / snd_renderbuffer->format.speed;
- modplug_start = time_start * (1000 / 5);
-
- Con_DPrintf("warning: mod file needed to seek (to %d)\n", modplug_start);
-
- qModPlug_Seek(per_ch->mf, modplug_start);
- sb->nbframes = 0;
-
- real_start = (unsigned int) ((float)modplug_start / 1000 * snd_renderbuffer->format.speed);
- if (*start - real_start + nbsampleframes > sb->maxframes)
+ // first slide the buffer back, discarding any data preceding the range we care about
+ int offset = firstsampleframe - per_ch->buffer_firstframe;
+ int keeplength = per_ch->buffer_numframes - offset;
+ if (keeplength > 0)
+ memmove(per_ch->buffer, per_ch->buffer + offset * sfx->format.width * sfx->format.channels, keeplength * sfx->format.width * sfx->format.channels);
+ per_ch->buffer_firstframe = firstsampleframe;
+ per_ch->buffer_numframes -= offset;
+ // decompress as much as we can fit in the buffer
+ newlength = sizeof(per_ch->buffer) - per_ch->buffer_numframes * f;
+ done = 0;
+ while (newlength > done && (ret = qModPlug_Read(per_ch->mf, (void *)((unsigned char *)per_ch->buffer + done), (int)(newlength - done))) > 0)
+ done += ret;
+ // clear the missing space if any
+ if (done < newlength)
{
- Con_Printf ("ModPlug_FetchSound: stream buffer too small after seek (%u sample frames required)\n",
- *start - real_start + nbsampleframes);
- per_ch->sb_offset = real_start;
- return NULL;
+ memset(per_ch->buffer + done, 0, newlength - done);
+ // Argh. We didn't get as many samples as we wanted. Probably
+ // libmodplug forgot what mLoopCount==-1 means... basically, this means
+ // we can't loop like this. Try to let DP fix it later...
+ sfx->total_length = firstsampleframe + done / f;
+ sfx->loopstart = 0;
+ // can't Con_Printf from this thread
+ //if (newlength != done)
+ // Con_DPrintf("ModPlug_Fetch: wanted: %d, got: %d\n", newlength, done);
}
+ // we now have more data in the buffer
+ per_ch->buffer_numframes += done / f;
}
- // Else, move forward the samples we need to keep in the sound buffer
- else
- {
- memmove (sb->samples, sb->samples + (real_start - per_ch->sb_offset) * factor, newlength * factor);
- sb->nbframes = newlength;
- }
-
- per_ch->sb_offset = real_start;
- // We add more than one frame of sound to the buffer:
- // 1- to ensure we won't lose many samples during the resampling process
- // 2- to reduce calls to ModPlug_FetchSound to regulate workload
- newlength = (int)(per_sfx->format.speed*STREAM_BUFFER_FILL);
- if ((size_t) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed) + sb->nbframes > sb->maxframes)
- {
- Con_Printf ("ModPlug_FetchSound: stream buffer overflow (%u + %u = %u sample frames / %u)\n",
- (unsigned int) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed), sb->nbframes, (unsigned int) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed) + sb->nbframes, sb->maxframes);
- return NULL;
- }
- newlength *= factor; // convert from sample frames to bytes
- if(newlength > (int)sizeof(resampling_buffer))
- newlength = sizeof(resampling_buffer);
-
- // Decompress in the resampling_buffer
- done = 0;
- while ((ret = qModPlug_Read (per_ch->mf, (char *)&resampling_buffer[done], (int)(newlength - done))) > 0)
- done += ret;
- if(done < newlength)
- {
- // Argh. We didn't get as many samples as we wanted. Probably
- // libmodplug forgot what mLoopCount==-1 means... basically, this means
- // we can't loop like this. Try to let DP fix it later...
- per_sfx->sfx->total_length = (real_start + ((size_t)done / (size_t)factor));
- per_sfx->sfx->loopstart = 0;
-
- if(newlength != done)
- Con_DPrintf("ModPlug_Fetch: wanted: %d, got: %d\n", newlength, done);
- }
-
- Snd_AppendToSndBuffer (sb, resampling_buffer, (size_t)done / (size_t)factor, &per_sfx->format);
-
- *start = per_ch->sb_offset;
- return sb;
+ // convert the sample format for the caller
+ buf = (short *)(per_ch->buffer + (firstsampleframe - per_ch->buffer_firstframe) * f);
+ len = numsampleframes * sfx->format.channels;
+ for (i = 0;i < len;i++)
+ outsamplesfloat[i] = buf[i] * (1.0f / 32768.0f);
}
/*
====================
-ModPlug_FetchEnd
+ModPlug_StopChannel
====================
*/
-static void ModPlug_FetchEnd (void *chfetcherdata)
+static void ModPlug_StopChannel(channel_t *ch)
{
- modplug_stream_perchannel_t* per_ch = (modplug_stream_perchannel_t *)chfetcherdata;
+ modplug_stream_perchannel_t *per_ch = (modplug_stream_perchannel_t *)ch->fetcher_data;
if (per_ch != NULL)
{
// Free the modplug decoder
- qModPlug_Unload (per_ch->mf);
+ qModPlug_Unload(per_ch->mf);
- Mem_Free (per_ch);
+ Mem_Free(per_ch);
}
}
ModPlug_FreeSfx
====================
*/
-static void ModPlug_FreeSfx (void *sfxfetcherdata)
+static void ModPlug_FreeSfx (sfx_t *sfx)
{
- modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfxfetcherdata;
+ modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfx->fetcher_data;
// Free the modplug file
Mem_Free(per_sfx->file);
}
-/*
-====================
-ModPlug_GetFormat
-====================
-*/
-static const snd_format_t* qModPlug_GetFormat (sfx_t* sfx)
-{
- modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfx->fetcher_data;
- return &per_sfx->format;
-}
-
-static const snd_fetcher_t modplug_fetcher = { ModPlug_FetchSound, ModPlug_FetchEnd, ModPlug_FreeSfx, qModPlug_GetFormat };
+static const snd_fetcher_t modplug_fetcher = { ModPlug_GetSamplesFloat, ModPlug_StopChannel, ModPlug_FreeSfx };
/*
if (developer_loading.integer >= 2)
Con_Printf ("\"%s\" will be streamed\n", filename);
per_sfx = (modplug_stream_persfx_t *)Mem_Alloc (snd_mempool, sizeof (*per_sfx));
- strlcpy(per_sfx->name, sfx->name, sizeof(per_sfx->name));
- sfx->memsize += sizeof (*per_sfx);
per_sfx->file = data;
per_sfx->filesize = filesize;
+ sfx->memsize += sizeof(*per_sfx);
sfx->memsize += filesize;
-
- per_sfx->format.speed = 44100; // modplug always works at that rate
- per_sfx->format.width = 2; // We always work with 16 bits samples
- per_sfx->format.channels = 2; // stereo rulez ;) (MAYBE default to mono because Amiga MODs sound better then?)
- per_sfx->sfx = sfx;
-
+ sfx->format.speed = 44100; // modplug always works at that rate
+ sfx->format.width = 2; // We always work with 16 bits samples
+ sfx->format.channels = 2; // stereo rulez ;) (MAYBE default to mono because Amiga MODs sound better then?)
sfx->fetcher_data = per_sfx;
sfx->fetcher = &modplug_fetcher;
sfx->flags |= SFXFLAG_STREAMED;
- sfx->total_length = 2147384647; // they always loop
+ sfx->total_length = 1<<30; // 2147384647; // they always loop (FIXME this breaks after 6 hours, we need support for a real "infinite" value!)
sfx->loopstart = sfx->total_length; // modplug does it
return true;
return -1;
}
-int S_StartSound_StartPosition (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition)
-{
- return -1;
-}
-
-int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition, int flags)
+int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition, int flags, float fspeed)
{
return -1;
}
{
unsigned char *file;
size_t filesize;
- snd_format_t format;
- unsigned int total_length;
- char name[128];
} ogg_stream_persfx_t;
// Per-channel data structure
{
OggVorbis_File vf;
ov_decode_t ov_decode;
- unsigned int sb_offset;
int bs;
- snd_buffer_t sb; // must be at the end due to its dynamically allocated size
+ int buffer_firstframe;
+ int buffer_numframes;
+ unsigned char buffer[STREAM_BUFFERSIZE*4];
} ogg_stream_perchannel_t;
/*
====================
-OGG_FetchSound
+OGG_GetSamplesFloat
====================
*/
-static const snd_buffer_t* OGG_FetchSound (void *sfxfetcher, void **chfetcherpointer, unsigned int *start, unsigned int nbsampleframes)
+static void OGG_GetSamplesFloat (channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
{
- ogg_stream_perchannel_t* per_ch = (ogg_stream_perchannel_t *)*chfetcherpointer;
- ogg_stream_persfx_t* per_sfx = (ogg_stream_persfx_t *)sfxfetcher;
- snd_buffer_t* sb;
+ ogg_stream_perchannel_t *per_ch = (ogg_stream_perchannel_t *)ch->fetcher_data;
+ ogg_stream_persfx_t *per_sfx = (ogg_stream_persfx_t *)sfx->fetcher_data;
+ int f = sfx->format.width * sfx->format.channels; // bytes per frame in the buffer
+ short *buf;
+ int i, len;
int newlength, done, ret;
- unsigned int real_start;
- unsigned int factor;
- // If there's no fetcher structure attached to the channel yet
+ // if this channel does not yet have a channel fetcher, make one
if (per_ch == NULL)
{
- size_t buff_len, memsize;
- snd_format_t sb_format;
-
- sb_format.speed = snd_renderbuffer->format.speed;
- sb_format.width = per_sfx->format.width;
- sb_format.channels = per_sfx->format.channels;
-
- buff_len = STREAM_BUFFER_SIZE(&sb_format);
- memsize = sizeof (*per_ch) - sizeof (per_ch->sb.samples) + buff_len;
- per_ch = (ogg_stream_perchannel_t *)Mem_Alloc (snd_mempool, memsize);
-
- // Open it with the VorbisFile API
+ // allocate a struct to keep track of our file position and buffer
+ per_ch = (ogg_stream_perchannel_t *)Mem_Alloc(snd_mempool, sizeof(*per_ch));
+ // begin decoding the file
per_ch->ov_decode.buffer = per_sfx->file;
per_ch->ov_decode.ind = 0;
per_ch->ov_decode.buffsize = per_sfx->filesize;
- if (qov_open_callbacks (&per_ch->ov_decode, &per_ch->vf, NULL, 0, callbacks) < 0)
+ if (qov_open_callbacks(&per_ch->ov_decode, &per_ch->vf, NULL, 0, callbacks) < 0)
{
- Con_Printf("error while reading Ogg Vorbis stream \"%s\"\n", per_sfx->name);
- Mem_Free (per_ch);
- return NULL;
+ // this never happens - this function succeeded earlier on the same data
+ Mem_Free(per_ch);
+ return;
}
per_ch->bs = 0;
-
- per_ch->sb_offset = 0;
- per_ch->sb.format = sb_format;
- per_ch->sb.nbframes = 0;
- per_ch->sb.maxframes = buff_len / (per_ch->sb.format.channels * per_ch->sb.format.width);
-
- *chfetcherpointer = per_ch;
- }
-
- real_start = *start;
-
- sb = &per_ch->sb;
- factor = per_sfx->format.width * per_sfx->format.channels;
-
- // If the stream buffer can't contain that much samples anyway
- if (nbsampleframes > sb->maxframes)
- {
- Con_Printf ("OGG_FetchSound: stream buffer too small (%u sample frames required)\n", nbsampleframes);
- return NULL;
+ per_ch->buffer_firstframe = 0;
+ per_ch->buffer_numframes = 0;
+ // attach the struct to our channel
+ ch->fetcher_data = (void *)per_ch;
}
- // If the data we need has already been decompressed in the sfxbuffer, just return it
- if (per_ch->sb_offset <= real_start && per_ch->sb_offset + sb->nbframes >= real_start + nbsampleframes)
+ // if the request is too large for our buffer, loop...
+ while (numsampleframes * f > (int)sizeof(per_ch->buffer))
{
- *start = per_ch->sb_offset;
- return sb;
+ done = sizeof(per_ch->buffer) / f;
+ OGG_GetSamplesFloat(ch, sfx, firstsampleframe, done, outsamplesfloat);
+ firstsampleframe += done;
+ numsampleframes -= done;
+ outsamplesfloat += done * sfx->format.channels;
}
- newlength = (int)(per_ch->sb_offset + sb->nbframes) - real_start;
-
- // If we need to skip some data before decompressing the rest, or if the stream has looped
- if (newlength < 0 || per_ch->sb_offset > real_start)
+ // seek if the request is before the current buffer (loop back)
+ // seek if the request starts beyond the current buffer by at least one frame (channel was zero volume for a while)
+ // do not seek if the request overlaps the buffer end at all (expected behavior)
+ if (per_ch->buffer_firstframe > firstsampleframe || per_ch->buffer_firstframe + per_ch->buffer_numframes < firstsampleframe)
{
- unsigned int time_start;
- ogg_int64_t ogg_start;
- int err;
-
- if (real_start > (unsigned int)per_sfx->total_length)
+ // we expect to decode forward from here so this will be our new buffer start
+ per_ch->buffer_firstframe = firstsampleframe;
+ per_ch->buffer_numframes = 0;
+ ret = qov_pcm_seek(&per_ch->vf, (ogg_int64_t)firstsampleframe);
+ if (ret != 0)
{
- Con_Printf ("OGG_FetchSound: asked for a start position after the end of the sfx! (%u > %u)\n",
- real_start, per_sfx->total_length);
- return NULL;
+ // LordHavoc: we can't Con_Printf here, not thread safe...
+ //Con_Printf("OGG_FetchSound: qov_pcm_seek(..., %d) returned %d\n", firstsampleframe, ret);
+ return;
}
-
- // We work with 200ms (1/5 sec) steps to avoid rounding errors
- time_start = real_start * 5 / snd_renderbuffer->format.speed;
- ogg_start = time_start * (per_sfx->format.speed / 5);
- err = qov_pcm_seek (&per_ch->vf, ogg_start);
- if (err != 0)
- {
- Con_Printf ("OGG_FetchSound: qov_pcm_seek(..., %d) returned %d\n",
- real_start, err);
- return NULL;
- }
- sb->nbframes = 0;
-
- real_start = (unsigned int) ((float)ogg_start / per_sfx->format.speed * snd_renderbuffer->format.speed);
- if (*start - real_start + nbsampleframes > sb->maxframes)
- {
- Con_Printf ("OGG_FetchSound: stream buffer too small after seek (%u sample frames required)\n",
- *start - real_start + nbsampleframes);
- per_ch->sb_offset = real_start;
- return NULL;
- }
- }
- // Else, move forward the samples we need to keep in the sound buffer
- else
- {
- memmove (sb->samples, sb->samples + (real_start - per_ch->sb_offset) * factor, newlength * factor);
- sb->nbframes = newlength;
}
- per_ch->sb_offset = real_start;
-
- // We add more than one frame of sound to the buffer:
- // 1- to ensure we won't lose many samples during the resampling process
- // 2- to reduce calls to OGG_FetchSound to regulate workload
- newlength = (int)(per_sfx->format.speed*STREAM_BUFFER_FILL);
- // this is how much we FETCH...
- if ((size_t) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed) + sb->nbframes > sb->maxframes)
+ // decompress the file as needed
+ if (firstsampleframe + numsampleframes > per_ch->buffer_firstframe + per_ch->buffer_numframes)
{
- Con_Printf ("OGG_FetchSound: stream buffer overflow (%u + %u = %u sample frames / %u)\n",
- (unsigned int) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed), sb->nbframes, (unsigned int) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed) + sb->nbframes, sb->maxframes);
- return NULL;
+ // first slide the buffer back, discarding any data preceding the range we care about
+ int offset = firstsampleframe - per_ch->buffer_firstframe;
+ int keeplength = per_ch->buffer_numframes - offset;
+ if (keeplength > 0)
+ memmove(per_ch->buffer, per_ch->buffer + offset * sfx->format.width * sfx->format.channels, keeplength * sfx->format.width * sfx->format.channels);
+ per_ch->buffer_firstframe = firstsampleframe;
+ per_ch->buffer_numframes -= offset;
+ // decompress as much as we can fit in the buffer
+ newlength = sizeof(per_ch->buffer) - per_ch->buffer_numframes * f;
+ done = 0;
+ while (newlength > done && (ret = qov_read(&per_ch->vf, (char *)per_ch->buffer + per_ch->buffer_numframes * f + done, (int)(newlength - done), mem_bigendian, 2, 1, &per_ch->bs)) > 0)
+ done += ret;
+ // clear the missing space if any
+ if (done < newlength)
+ memset(per_ch->buffer + done, 0, newlength - done);
+ // we now have more data in the buffer
+ per_ch->buffer_numframes += done / f;
}
- newlength *= factor; // convert from sample frames to bytes
- if(newlength > (int)sizeof(resampling_buffer))
- newlength = sizeof(resampling_buffer);
- // Decompress in the resampling_buffer
- done = 0;
- while ((ret = qov_read (&per_ch->vf, (char *)&resampling_buffer[done], (int)(newlength - done), mem_bigendian, 2, 1, &per_ch->bs)) > 0)
- done += ret;
-
- Snd_AppendToSndBuffer (sb, resampling_buffer, (size_t)done / (size_t)factor, &per_sfx->format);
-
- *start = per_ch->sb_offset;
- return sb;
+ // convert the sample format for the caller
+ buf = (short *)((char *)per_ch->buffer + (firstsampleframe - per_ch->buffer_firstframe) * f);
+ len = numsampleframes * sfx->format.channels;
+ for (i = 0;i < len;i++)
+ outsamplesfloat[i] = buf[i] * (1.0f / 32768.0f);
}
/*
====================
-OGG_FetchEnd
+OGG_StopChannel
====================
*/
-static void OGG_FetchEnd (void *chfetcherdata)
+static void OGG_StopChannel(channel_t *ch)
{
- ogg_stream_perchannel_t* per_ch = (ogg_stream_perchannel_t *)chfetcherdata;
-
+ ogg_stream_perchannel_t *per_ch = (ogg_stream_perchannel_t *)ch->fetcher_data;
if (per_ch != NULL)
{
- // Free the ogg vorbis decoder
- qov_clear (&per_ch->vf);
-
- Mem_Free (per_ch);
+ // release the vorbis decompressor
+ qov_clear(&per_ch->vf);
+ Mem_Free(per_ch);
}
}
OGG_FreeSfx
====================
*/
-static void OGG_FreeSfx (void *sfxfetcherdata)
+static void OGG_FreeSfx(sfx_t *sfx)
{
- ogg_stream_persfx_t* per_sfx = (ogg_stream_persfx_t *)sfxfetcherdata;
-
- // Free the Ogg Vorbis file
+ ogg_stream_persfx_t *per_sfx = (ogg_stream_persfx_t *)sfx->fetcher_data;
+ // free the complete file we were keeping around
Mem_Free(per_sfx->file);
-
- // Free the stream structure
+ // free the file information structure
Mem_Free(per_sfx);
}
-/*
-====================
-OGG_GetFormat
-====================
-*/
-static const snd_format_t* OGG_GetFormat (sfx_t* sfx)
-{
- ogg_stream_persfx_t* per_sfx = (ogg_stream_persfx_t *)sfx->fetcher_data;
- return &per_sfx->format;
-}
-
-static const snd_fetcher_t ogg_fetcher = { OGG_FetchSound, OGG_FetchEnd, OGG_FreeSfx, OGG_GetFormat };
+static const snd_fetcher_t ogg_fetcher = {OGG_GetSamplesFloat, OGG_StopChannel, OGG_FreeSfx};
-static void OGG_DecodeTags(vorbis_comment *vc, unsigned int *start, unsigned int *length, double samplesfactor, unsigned int numsamples, double *peak, double *gaindb)
+static void OGG_DecodeTags(vorbis_comment *vc, unsigned int *start, unsigned int *length, unsigned int numsamples, double *peak, double *gaindb)
{
const char *startcomment = NULL, *lengthcomment = NULL, *endcomment = NULL, *thiscomment = NULL;
if(startcomment)
{
- *start = (unsigned int) bound(0, atof(startcomment) * samplesfactor, numsamples);
+ *start = (unsigned int) bound(0, atof(startcomment), numsamples);
if(endcomment)
- *length = (unsigned int) bound(0, atof(endcomment) * samplesfactor, numsamples);
+ *length = (unsigned int) bound(0, atof(endcomment), numsamples);
else if(lengthcomment)
- *length = (unsigned int) bound(0, *start + atof(lengthcomment) * samplesfactor, numsamples);
+ *length = (unsigned int) bound(0, *start + atof(lengthcomment), numsamples);
}
}
Load an Ogg Vorbis file into memory
====================
*/
-qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *sfx)
+qboolean OGG_LoadVorbisFile(const char *filename, sfx_t *sfx)
{
unsigned char *data;
fs_offset_t filesize;
OggVorbis_File vf;
vorbis_info *vi;
vorbis_comment *vc;
- ogg_int64_t len, buff_len;
double peak, gaindb;
#ifndef LINK_TO_LIBVORBIS
return false;
#endif
- // Already loaded?
+ // Return if already loaded
if (sfx->fetcher != NULL)
return true;
- // Load the file
- data = FS_LoadFile (filename, snd_mempool, false, &filesize);
+ // Load the file completely
+ data = FS_LoadFile(filename, snd_mempool, false, &filesize);
if (data == NULL)
return false;
if (developer_loading.integer >= 2)
- Con_Printf ("Loading Ogg Vorbis file \"%s\"\n", filename);
+ Con_Printf("Loading Ogg Vorbis file \"%s\"\n", filename);
// Open it with the VorbisFile API
ov_decode.buffer = data;
ov_decode.ind = 0;
ov_decode.buffsize = filesize;
- if (qov_open_callbacks (&ov_decode, &vf, NULL, 0, callbacks) < 0)
+ if (qov_open_callbacks(&ov_decode, &vf, NULL, 0, callbacks) < 0)
{
- Con_Printf ("error while opening Ogg Vorbis file \"%s\"\n", filename);
+ Con_Printf("error while opening Ogg Vorbis file \"%s\"\n", filename);
Mem_Free(data);
return false;
}
// Get the stream information
- vi = qov_info (&vf, -1);
+ vi = qov_info(&vf, -1);
if (vi->channels < 1 || vi->channels > 2)
{
Con_Printf("%s has an unsupported number of channels (%i)\n",
return false;
}
- len = qov_pcm_total (&vf, -1) * vi->channels * 2; // 16 bits => "* 2"
+ sfx->format.speed = vi->rate;
+ sfx->format.channels = vi->channels;
+ sfx->format.width = 2; // We always work with 16 bits samples
+
+ sfx->total_length = qov_pcm_total(&vf, -1);
- // Decide if we go for a stream or a simple PCM cache
- buff_len = (int)ceil (STREAM_BUFFER_DURATION * snd_renderbuffer->format.speed) * 2 * vi->channels;
- if (snd_streaming.integer && (len > (ogg_int64_t)filesize + 3 * buff_len || snd_streaming.integer >= 2))
+ if (snd_streaming.integer && (snd_streaming.integer >= 2 || sfx->total_length > max(sizeof(ogg_stream_perchannel_t), snd_streaming_length.value * sfx->format.speed)))
{
+ // large sounds use the OGG fetcher to decode the file on demand (but the entire file is held in memory)
ogg_stream_persfx_t* per_sfx;
-
if (developer_loading.integer >= 2)
- Con_Printf ("Ogg sound file \"%s\" will be streamed\n", filename);
- per_sfx = (ogg_stream_persfx_t *)Mem_Alloc (snd_mempool, sizeof (*per_sfx));
- strlcpy(per_sfx->name, sfx->name, sizeof(per_sfx->name));
+ Con_Printf("Ogg sound file \"%s\" will be streamed\n", filename);
+ per_sfx = (ogg_stream_persfx_t *)Mem_Alloc(snd_mempool, sizeof(*per_sfx));
sfx->memsize += sizeof (*per_sfx);
per_sfx->file = data;
per_sfx->filesize = filesize;
sfx->memsize += filesize;
-
- per_sfx->format.speed = vi->rate;
- per_sfx->format.width = 2; // We always work with 16 bits samples
- per_sfx->format.channels = vi->channels;
-
sfx->fetcher_data = per_sfx;
sfx->fetcher = &ogg_fetcher;
sfx->flags |= SFXFLAG_STREAMED;
- sfx->total_length = (int)((size_t)len / (per_sfx->format.channels * 2) * ((double)snd_renderbuffer->format.speed / per_sfx->format.speed));
vc = qov_comment(&vf, -1);
- OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, (double)snd_renderbuffer->format.speed / (double)per_sfx->format.speed, sfx->total_length, &peak, &gaindb);
- per_sfx->total_length = sfx->total_length;
- qov_clear (&vf);
+ OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, sfx->total_length, &peak, &gaindb);
+ qov_clear(&vf);
}
else
{
+ // small sounds are entirely loaded and use the PCM fetcher
char *buff;
+ ogg_int64_t len;
ogg_int64_t done;
int bs;
long ret;
- snd_buffer_t *sb;
- snd_format_t ogg_format;
-
if (developer_loading.integer >= 2)
Con_Printf ("Ogg sound file \"%s\" will be cached\n", filename);
-
- // Decode it
- buff = (char *)Mem_Alloc (snd_mempool, (int)len);
+ len = sfx->total_length * sfx->format.channels * sfx->format.width;
+ sfx->flags &= ~SFXFLAG_STREAMED;
+ sfx->memsize += len;
+ sfx->fetcher = &wav_fetcher;
+ sfx->fetcher_data = Mem_Alloc(snd_mempool, (size_t)len);
+ buff = (char *)sfx->fetcher_data;
done = 0;
bs = 0;
- while ((ret = qov_read (&vf, &buff[done], (int)(len - done), mem_bigendian, 2, 1, &bs)) > 0)
+ while ((ret = qov_read(&vf, &buff[done], (int)(len - done), mem_bigendian, 2, 1, &bs)) > 0)
done += ret;
-
- // Build the sound buffer
- ogg_format.speed = vi->rate;
- ogg_format.channels = vi->channels;
- ogg_format.width = 2; // We always work with 16 bits samples
- sb = Snd_CreateSndBuffer ((unsigned char *)buff, (size_t)done / (vi->channels * 2), &ogg_format, snd_renderbuffer->format.speed);
- if (sb == NULL)
- {
- qov_clear (&vf);
- Mem_Free (data);
- Mem_Free (buff);
- return false;
- }
-
- sfx->fetcher = &wav_fetcher;
- sfx->fetcher_data = sb;
-
- sfx->total_length = sb->nbframes;
- sfx->memsize += sb->maxframes * sb->format.channels * sb->format.width + sizeof (*sb) - sizeof (sb->samples);
-
- sfx->flags &= ~SFXFLAG_STREAMED;
vc = qov_comment(&vf, -1);
- OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, (double)snd_renderbuffer->format.speed / (double)sb->format.speed, sfx->total_length, &peak, &gaindb);
- sb->nbframes = sfx->total_length;
- qov_clear (&vf);
- Mem_Free (data);
- Mem_Free (buff);
+ OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, sfx->total_length, &peak, &gaindb);
+ qov_clear(&vf);
+ Mem_Free(data);
}
if(peak)
if (developer_loading.integer >= 2)
Con_Printf ("Ogg sound file \"%s\" uses ReplayGain (gain %f, peak %f)\n", filename, sfx->volume_mult, sfx->volume_peak);
}
+ else if(gaindb != 0)
+ {
+ sfx->volume_mult = min(1.0f / peak, exp(gaindb * 0.05f * log(10.0f)));
+ sfx->volume_peak = 1.0; // if peak is not defined, we won't trust it
+ if (developer_loading.integer >= 2)
+ Con_Printf ("Ogg sound file \"%s\" uses ReplayGain (gain %f, peak not defined and assumed to be %f)\n", filename, sfx->volume_mult, sfx->volume_peak);
+ }
return true;
}
/*
====================
-WAV_FetchSound
+WAV_GetSamplesFloat
====================
*/
-static const snd_buffer_t* WAV_FetchSound (void *sfxfetcher, void **chfetcherpointer, unsigned int *start, unsigned int nbsampleframes)
+static void WAV_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
{
- *start = 0;
- return (snd_buffer_t *)sfxfetcher;
+ int i, len = numsampleframes * sfx->format.channels;
+ if (sfx->format.width == 2)
+ {
+ const short *bufs = (const short *)sfx->fetcher_data + firstsampleframe * sfx->format.channels;
+ for (i = 0;i < len;i++)
+ outsamplesfloat[i] = bufs[i] * (1.0f / 32768.0f);
+ }
+ else
+ {
+ const signed char *bufb = (const signed char *)sfx->fetcher_data + firstsampleframe * sfx->format.channels;
+ for (i = 0;i < len;i++)
+ outsamplesfloat[i] = bufb[i] * (1.0f / 128.0f);
+ }
}
/*
WAV_FreeSfx
====================
*/
-static void WAV_FreeSfx (void *sfxfetcherdata)
+static void WAV_FreeSfx(sfx_t *sfx)
{
- snd_buffer_t* sb = (snd_buffer_t *)sfxfetcherdata;
- // Free the sound buffer
- Mem_Free(sb);
+ // free the loaded sound data
+ Mem_Free(sfx->fetcher_data);
}
-/*
-====================
-WAV_GetFormat
-====================
-*/
-static const snd_format_t* WAV_GetFormat (sfx_t* sfx)
-{
- snd_buffer_t* sb = (snd_buffer_t *)sfx->fetcher_data;
- return &sb->format;
-}
-
-const snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL, WAV_FreeSfx, WAV_GetFormat };
+const snd_fetcher_t wav_fetcher = { WAV_GetSamplesFloat, NULL, WAV_FreeSfx };
/*
fs_offset_t filesize;
unsigned char *data;
wavinfo_t info;
- snd_format_t wav_format;
- snd_buffer_t* sb;
+ int i, len;
+ const unsigned char *inb;
+ unsigned char *outb;
// Already loaded?
if (sfx->fetcher != NULL)
ptr[i] = LittleShort (ptr[i]);
}
- wav_format.speed = info.rate;
- wav_format.width = info.width;
- wav_format.channels = info.channels;
- sb = Snd_CreateSndBuffer (data + info.dataofs, info.samples, &wav_format, snd_renderbuffer->format.speed);
- if (sb == NULL)
+ sfx->format.speed = info.rate;
+ sfx->format.width = info.width;
+ sfx->format.channels = info.channels;
+ sfx->fetcher = &wav_fetcher;
+ sfx->fetcher_data = Mem_Alloc(snd_mempool, info.samples * sfx->format.width * sfx->format.channels);
+ sfx->total_length = info.samples;
+ sfx->memsize += filesize;
+ len = info.samples * sfx->format.channels * sfx->format.width;
+ inb = data + info.dataofs;
+ outb = (unsigned char *)sfx->fetcher_data;
+ if (info.width == 2)
{
- Mem_Free(data);
- return false;
+ if (mem_bigendian)
+ {
+ // we have to byteswap the data at load (better than doing it while mixing)
+ for (i = 0;i < len;i += 2)
+ {
+ outb[i] = inb[i+1];
+ outb[i+1] = inb[i];
+ }
+ }
+ else
+ {
+ // we can just copy it straight
+ memcpy(outb, inb, len);
+ }
+ }
+ else
+ {
+ // convert unsigned byte sound data to signed bytes for quicker mixing
+ for (i = 0;i < len;i++)
+ outb[i] = inb[i] - 0x80;
}
- sfx->fetcher = &wav_fetcher;
- sfx->fetcher_data = sb;
-
- sfx->total_length = sb->nbframes;
- sfx->memsize += sb->maxframes * sb->format.channels * sb->format.width + sizeof (*sb) - sizeof (sb->samples);
if (info.loopstart < 0)
sfx->loopstart = sfx->total_length;
else
- sfx->loopstart = (unsigned int) ((double)info.loopstart * (double)sb->format.speed / (double)info.rate);
+ sfx->loopstart = info.loopstart;
sfx->loopstart = min(sfx->loopstart, sfx->total_length);
sfx->flags &= ~SFXFLAG_STREAMED;
- Mem_Free (data);
return true;
}
void S_ClearUsed (void);
void S_PurgeUnused (void);
qboolean S_IsSoundPrecached (const sfx_t *sfx);
+sfx_t *S_FindName(const char *name);
// for sound() builtins
#define CHANFLAG_RELIABLE 1
// S_StartSound returns the channel index, or -1 if an error occurred
int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation);
-int S_StartSound_StartPosition (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition);
-int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition, int flags);
+int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition, int flags, float fspeed);
qboolean S_LocalSound (const char *s);
void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation);
void S_StopChannel (unsigned int channel_ind, qboolean lockmutex, qboolean freesfx);
qboolean S_SetChannelFlag (unsigned int ch_ind, unsigned int flag, qboolean value);
void S_SetChannelVolume (unsigned int ch_ind, float fvol);
+void S_SetChannelSpeed (unsigned int ch_ind, float fspeed);
float S_GetChannelPosition (unsigned int ch_ind);
float S_GetEntChannelPosition(int entnum, int entchannel);
void SV_StartDemoRecording(client_t *client, const char *filename, int forcetrack)
{
+ prvm_prog_t *prog = SVVM_prog;
char name[MAX_QPATH];
if(client->sv_demo_file != NULL)
void SV_WriteDemoMessage(client_t *client, sizebuf_t *sendbuffer, qboolean clienttoserver)
{
+ prvm_prog_t *prog = SVVM_prog;
int len, i;
float f;
int temp;
void SV_StopDemoRecording(client_t *client)
{
+ prvm_prog_t *prog = SVVM_prog;
sizebuf_t buf;
unsigned char bufdata[64];
#include "sv_demo.h"
#include "libcurl.h"
#include "csprogs.h"
+#include "thread.h"
static void SV_SaveEntFile_f(void);
static void SV_StartDownload_f(void);
static void SV_VM_Setup(void);
extern cvar_t net_connecttimeout;
-void VM_CustomStats_Clear (void);
-void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats);
-
cvar_t sv_worldmessage = {CVAR_READONLY, "sv_worldmessage", "", "title of current level"};
cvar_t sv_worldname = {CVAR_READONLY, "sv_worldname", "", "name of current worldmodel"};
cvar_t sv_worldnamenoextension = {CVAR_READONLY, "sv_worldnamenoextension", "", "name of current worldmodel without extension"};
cvar_t sv_worldbasename = {CVAR_READONLY, "sv_worldbasename", "", "name of current worldmodel without maps/ prefix or extension"};
+cvar_t sv_disablenotify = {0, "sv_disablenotify", "1", "suppress broadcast prints when certain cvars are changed (CVAR_NOTIFY flag in engine code)"};
cvar_t coop = {0, "coop","0", "coop mode, 0 = no coop, 1 = coop mode, multiple players playing through the singleplayer game (coop mode also shuts off deathmatch)"};
cvar_t deathmatch = {0, "deathmatch","0", "deathmatch mode, values depend on mod but typically 0 = no deathmatch, 1 = normal deathmatch with respawning weapons, 2 = weapons stay (players can only pick up new weapons)"};
cvar_t fraglimit = {CVAR_NOTIFY, "fraglimit","0", "ends level if this many frags is reached by any player"};
cvar_t gamecfg = {0, "gamecfg", "0", "unused cvar in quake, can be used by mods"};
cvar_t noexit = {CVAR_NOTIFY, "noexit","0", "kills anyone attempting to use an exit"};
cvar_t nomonsters = {0, "nomonsters", "0", "unused cvar in quake, can be used by mods"};
-cvar_t pausable = {0, "pausable","1", "allow players to pause or not"};
+cvar_t pausable = {0, "pausable","1", "allow players to pause or not (otherwise, only the server admin can)"};
cvar_t pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1", "indicates to QuakeC that the standard quakec extensions system is available (if 0, quakec should not attempt to use extensions)"};
cvar_t samelevel = {CVAR_NOTIFY, "samelevel","0", "repeats same level if level ends (due to timelimit or someone hitting an exit)"};
cvar_t skill = {0, "skill","1", "difficulty level of game, affects monster layouts in levels, 0 = easy, 1 = normal, 2 = hard, 3 = nightmare (same layout as hard but monsters fire twice)"};
cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag = {0, "sv_gameplayfix_upwardvelocityclearsongroundflag", "1", "prevents monsters, items, and most other objects from being stuck to the floor when pushed around by damage, and other situations in mods"};
cvar_t sv_gameplayfix_downtracesupportsongroundflag = {0, "sv_gameplayfix_downtracesupportsongroundflag", "1", "prevents very short moves from clearing onground (which may make the player stick to the floor at high netfps)"};
cvar_t sv_gameplayfix_q1bsptracelinereportstexture = {0, "sv_gameplayfix_q1bsptracelinereportstexture", "1", "enables mods to get accurate trace_texture results on q1bsp by using a surface-hitting traceline implementation rather than the standard solidbsp method, q3bsp always reports texture accurately"};
+cvar_t sv_gameplayfix_unstickplayers = {0, "sv_gameplayfix_unstickplayers", "1", "big hack to try and fix the rare case of MOVETYPE_WALK entities getting stuck in the world clipping hull."};
+cvar_t sv_gameplayfix_unstickentities = {0, "sv_gameplayfix_unstickentities", "1", "hack to check if entities are crossing world collision hull and try to move them to the right position"};
+cvar_t sv_gameplayfix_fixedcheckwatertransition = {0, "sv_gameplayfix_fixedcheckwatertransition", "1", "fix two very stupid bugs in SV_CheckWaterTransition when watertype is CONTENTS_EMPTY (the bugs causes waterlevel to be 1 on first frame, -1 on second frame - the fix makes it 0 on both frames)"};
cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800", "how fast you fall (512 = roughly earth gravity)"};
cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"};
cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping (sv_gameplayfix_stepwhilejumping must also be 1)"};
cvar_t sv_warsowbunny_turnaccel = {0, "sv_warsowbunny_turnaccel", "0", "max sharpness of turns (also master switch for the sv_warsowbunny_* mode; set this to 9 to enable)"};
cvar_t sv_warsowbunny_backtosideratio = {0, "sv_warsowbunny_backtosideratio", "0.8", "lower values make it easier to change direction without losing speed; the drawback is \"understeering\" in sharp turns"};
cvar_t sv_onlycsqcnetworking = {0, "sv_onlycsqcnetworking", "0", "disables legacy entity networking code for higher performance (except on clients, which can still be legacy)"};
+cvar_t sv_areadebug = {0, "sv_areadebug", "0", "disables physics culling for debugging purposes (only for development)"};
cvar_t sys_ticrate = {CVAR_SAVE, "sys_ticrate","0.0138889", "how long a server frame is in seconds, 0.05 is 20fps server rate, 0.1 is 10fps (can not be set higher than 0.1), 0 runs as many server frames as possible (makes games against bots a little smoother, overwhelms network players), 0.0138889 matches QuakeWorld physics"};
cvar_t teamplay = {CVAR_NOTIFY, "teamplay","0", "teamplay mode, values depend on mod but typically 0 = no teams, 1 = no team damage no self damage, 2 = team damage and self damage, some mods support 3 = no team damage but can damage self"};
cvar_t timelimit = {CVAR_NOTIFY, "timelimit","0", "ends level at this time (in minutes)"};
+cvar_t sv_threaded = {0, "sv_threaded", "0", "enables a separate thread for server code, improving performance, especially when hosting a game while playing, EXPERIMENTAL, may be crashy"};
cvar_t saved1 = {CVAR_SAVE, "saved1", "0", "unused cvar in quake that is saved to config.cfg on exit, can be used by mods"};
cvar_t saved2 = {CVAR_SAVE, "saved2", "0", "unused cvar in quake that is saved to config.cfg on exit, can be used by mods"};
//============================================================================
-void SV_AreaStats_f(void)
+static void SV_AreaStats_f(void)
{
World_PrintAreaStats(&sv.world, "server");
}
extern cvar_t csqc_progname; //[515]: csqc crc check and right csprogs name according to progs.dat
extern cvar_t csqc_progcrc;
extern cvar_t csqc_progsize;
+ extern cvar_t csqc_usedemoprogs;
Cvar_RegisterVariable(&sv_worldmessage);
Cvar_RegisterVariable(&sv_worldname);
Cvar_RegisterVariable (&csqc_progname);
Cvar_RegisterVariable (&csqc_progcrc);
Cvar_RegisterVariable (&csqc_progsize);
+ Cvar_RegisterVariable (&csqc_usedemoprogs);
Cmd_AddCommand("sv_saveentfile", SV_SaveEntFile_f, "save map entities to .ent file (to allow external editing)");
Cmd_AddCommand("sv_areastats", SV_AreaStats_f, "prints statistics on entity culling during collision traces");
Cmd_AddCommand_WithClientCommand("sv_startdownload", NULL, SV_StartDownload_f, "begins sending a file to the client (network protocol use only)");
Cmd_AddCommand_WithClientCommand("download", NULL, SV_Download_f, "downloads a specified file from the server");
+ Cvar_RegisterVariable (&sv_disablenotify);
Cvar_RegisterVariable (&coop);
Cvar_RegisterVariable (&deathmatch);
Cvar_RegisterVariable (&fraglimit);
Cvar_RegisterVariable (&sv_gameplayfix_upwardvelocityclearsongroundflag);
Cvar_RegisterVariable (&sv_gameplayfix_downtracesupportsongroundflag);
Cvar_RegisterVariable (&sv_gameplayfix_q1bsptracelinereportstexture);
+ Cvar_RegisterVariable (&sv_gameplayfix_unstickplayers);
+ Cvar_RegisterVariable (&sv_gameplayfix_unstickentities);
+ Cvar_RegisterVariable (&sv_gameplayfix_fixedcheckwatertransition);
Cvar_RegisterVariable (&sv_gravity);
Cvar_RegisterVariable (&sv_idealpitchscale);
Cvar_RegisterVariable (&sv_jumpstep);
Cvar_RegisterVariable (&sv_warsowbunny_turnaccel);
Cvar_RegisterVariable (&sv_warsowbunny_backtosideratio);
Cvar_RegisterVariable (&sv_onlycsqcnetworking);
+ Cvar_RegisterVariable (&sv_areadebug);
Cvar_RegisterVariable (&sys_ticrate);
Cvar_RegisterVariable (&teamplay);
Cvar_RegisterVariable (&timelimit);
+ Cvar_RegisterVariable (&sv_threaded);
Cvar_RegisterVariable (&saved1);
Cvar_RegisterVariable (&saved2);
static void SV_SaveEntFile_f(void)
{
+ char vabuf[1024];
if (!sv.active || !sv.worldmodel)
{
Con_Print("Not running a server\n");
return;
}
- FS_WriteFile(va("%s.ent", sv.worldnamenoextension), sv.worldmodel->brush.entities, (fs_offset_t)strlen(sv.worldmodel->brush.entities));
+ FS_WriteFile(va(vabuf, sizeof(vabuf), "%s.ent", sv.worldnamenoextension), sv.worldmodel->brush.entities, (fs_offset_t)strlen(sv.worldmodel->brush.entities));
}
==================
*/
-void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable)
+void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation, qboolean reliable, float speed)
{
+ prvm_prog_t *prog = SVVM_prog;
sizebuf_t *dest;
- int sound_num, field_mask, i, ent;
+ int sound_num, field_mask, i, ent, speed4000;
dest = (reliable ? &sv.reliable_datagram : &sv.datagram);
ent = PRVM_NUM_FOR_EDICT(entity);
+ speed4000 = (int)floor(speed * 4000.0f + 0.5f);
field_mask = 0;
if (volume != DEFAULT_SOUND_PACKET_VOLUME)
field_mask |= SND_VOLUME;
if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
field_mask |= SND_ATTENUATION;
+ if (speed4000 && speed4000 != 4000)
+ field_mask |= SND_SPEEDUSHORT4000;
if (ent >= 8192 || channel < 0 || channel > 7)
field_mask |= SND_LARGEENTITY;
if (sound_num >= 256)
MSG_WriteByte (dest, volume);
if (field_mask & SND_ATTENUATION)
MSG_WriteByte (dest, (int)(attenuation*64));
+ if (field_mask & SND_SPEEDUSHORT4000)
+ MSG_WriteShort (dest, speed4000);
if (field_mask & SND_LARGEENTITY)
{
MSG_WriteShort (dest, ent);
==================
*/
-void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation)
+void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation, float speed)
{
- int sound_num, field_mask, i;
+ int sound_num, field_mask, i, speed4000;
if (volume < 0 || volume > 255)
{
if (!sound_num)
return;
+ speed4000 = (int)(speed * 40.0f);
field_mask = 0;
if (volume != DEFAULT_SOUND_PACKET_VOLUME)
field_mask |= SND_VOLUME;
field_mask |= SND_ATTENUATION;
if (sound_num >= 256)
field_mask |= SND_LARGESOUND;
+ if (speed4000 && speed4000 != 4000)
+ field_mask |= SND_SPEEDUSHORT4000;
// directed messages go only to the entity they are targeted on
MSG_WriteByte (&sv.datagram, svc_sound);
MSG_WriteByte (&sv.datagram, volume);
if (field_mask & SND_ATTENUATION)
MSG_WriteByte (&sv.datagram, (int)(attenuation*64));
+ if (field_mask & SND_SPEEDUSHORT4000)
+ MSG_WriteShort (&sv.datagram, speed4000);
// Always write entnum 0 for the world entity
MSG_WriteShort (&sv.datagram, (0<<3) | 0);
if (field_mask & SND_LARGESOUND)
*/
void SV_SendServerinfo (client_t *client)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
char message[128];
+ char vabuf[1024];
// we know that this client has a netconnection and thus is not a bot
{
Con_DPrintf("sending csqc info to client (\"%s\" with size %i and crc %i)\n", sv.csqc_progname, sv.csqc_progsize, sv.csqc_progcrc);
MSG_WriteByte (&client->netconnection->message, svc_stufftext);
- MSG_WriteString (&client->netconnection->message, va("csqc_progname %s\n", sv.csqc_progname));
+ MSG_WriteString (&client->netconnection->message, va(vabuf, sizeof(vabuf), "csqc_progname %s\n", sv.csqc_progname));
MSG_WriteByte (&client->netconnection->message, svc_stufftext);
- MSG_WriteString (&client->netconnection->message, va("csqc_progsize %i\n", sv.csqc_progsize));
+ MSG_WriteString (&client->netconnection->message, va(vabuf, sizeof(vabuf), "csqc_progsize %i\n", sv.csqc_progsize));
MSG_WriteByte (&client->netconnection->message, svc_stufftext);
- MSG_WriteString (&client->netconnection->message, va("csqc_progcrc %i\n", sv.csqc_progcrc));
+ MSG_WriteString (&client->netconnection->message, va(vabuf, sizeof(vabuf), "csqc_progcrc %i\n", sv.csqc_progcrc));
if(client->sv_demo_file != NULL)
{
}
//[515]: init stufftext string (it is sent before svc_serverinfo)
- if (PRVM_GetString(PRVM_serverglobalstring(SV_InitCmd)))
+ if (PRVM_GetString(prog, PRVM_serverglobalstring(SV_InitCmd)))
{
MSG_WriteByte (&client->netconnection->message, svc_stufftext);
- MSG_WriteString (&client->netconnection->message, va("%s\n", PRVM_GetString(PRVM_serverglobalstring(SV_InitCmd))));
+ MSG_WriteString (&client->netconnection->message, va(vabuf, sizeof(vabuf), "%s\n", PRVM_GetString(prog, PRVM_serverglobalstring(SV_InitCmd))));
}
}
else
MSG_WriteByte (&client->netconnection->message, GAME_COOP);
- MSG_WriteString (&client->netconnection->message,PRVM_GetString(PRVM_serveredictstring(prog->edicts, message)));
+ MSG_WriteString (&client->netconnection->message,PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message)));
for (i = 1;i < MAX_MODELS && sv.model_precache[i][0];i++)
MSG_WriteString (&client->netconnection->message, sv.model_precache[i]);
*/
void SV_ConnectClient (int clientnum, netconn_t *netconnection)
{
+ prvm_prog_t *prog = SVVM_prog;
client_t *client;
int i;
{
// call the progs to get default spawn parms for the new client
// set self to world to intentionally cause errors with broken SetNewParms code in some mods
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = 0;
- PRVM_ExecuteProgram (PRVM_serverfunction(SetNewParms), "QC function SetNewParms is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SetNewParms), "QC function SetNewParms is missing");
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
client->spawn_parms[i] = (&PRVM_serverglobalfloat(parm1))[i];
// set up the entity for this client (including .colormap, .team, etc)
- PRVM_ED_ClearEdict(client->edict);
+ PRVM_ED_ClearEdict(prog, client->edict);
}
// don't call SendServerinfo for a fresh botclient because its fields have
static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *cs, int enumber)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
unsigned int sendflags;
unsigned int version;
// LordHavoc: this could kill tags attached to an invisible entity, I
// just hope we never have to support that case
i = (int)PRVM_serveredictfloat(ent, modelindex);
- modelindex = (i >= 1 && i < MAX_MODELS && PRVM_serveredictstring(ent, model) && *PRVM_GetString(PRVM_serveredictstring(ent, model)) && sv.models[i]) ? i : 0;
+ modelindex = (i >= 1 && i < MAX_MODELS && PRVM_serveredictstring(ent, model) && *PRVM_GetString(prog, PRVM_serveredictstring(ent, model)) && sv.models[i]) ? i : 0;
flags = 0;
i = (int)(PRVM_serveredictfloat(ent, glow_size) * 0.25f);
cs->framegroupblend[2].lerp = PRVM_serveredictfloat(ent, lerpfrac3);
cs->framegroupblend[3].lerp = PRVM_serveredictfloat(ent, lerpfrac4);
cs->framegroupblend[0].lerp = 1.0f - cs->framegroupblend[1].lerp - cs->framegroupblend[2].lerp - cs->framegroupblend[3].lerp;
+ cs->frame = 0; // don't need the legacy frame
}
cs->light[0] = light[0];
return true;
}
-void SV_PrepareEntitiesForSending(void)
+static void SV_PrepareEntitiesForSending(void)
{
+ prvm_prog_t *prog = SVVM_prog;
int e;
prvm_edict_t *ent;
// send all entities that touch the pvs
qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
{
+ prvm_prog_t *prog = SVVM_prog;
float pitchsign;
float alpha;
float starttransformed[3], endtransformed[3];
// get the list of entities in the sweep box
if (sv_cullentities_trace_entityocclusion.integer)
- numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
if(model && model->brush.TraceLineOfSight)
{
// get the entity matrix
- pitchsign = SV_GetPitchSign(touch);
+ pitchsign = SV_GetPitchSign(prog, touch);
Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
// see if the ray hits this entity
return false;
}
-void SV_MarkWriteEntityStateToClient(entity_state_t *s)
+static void SV_MarkWriteEntityStateToClient(entity_state_t *s)
{
+ prvm_prog_t *prog = SVVM_prog;
int isbmodel;
dp_model_t *model;
prvm_edict_t *ed;
if (s->customizeentityforclient)
{
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = s->number;
PRVM_serverglobaledict(other) = sv.writeentitiestoclient_cliententitynumber;
- PRVM_ExecuteProgram(s->customizeentityforclient, "customizeentityforclient: NULL function");
+ prog->ExecuteProgram(prog, s->customizeentityforclient, "customizeentityforclient: NULL function");
if(!PRVM_G_FLOAT(OFS_RETURN) || !SV_PrepareEntityForSending(PRVM_EDICT_NUM(s->number), s, s->number))
return;
}
#if MAX_LEVELNETWORKEYES > 0
#define MAX_EYE_RECURSION 1 // increase if recursion gets supported by portals
-void SV_AddCameraEyes(void)
+static void SV_AddCameraEyes(void)
{
+ prvm_prog_t *prog = SVVM_prog;
int e, i, j, k;
prvm_edict_t *ed;
static int cameras[MAX_LEVELNETWORKEYES];
{
if(PRVM_serveredictfunction(ed, camera_transform))
{
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = e;
PRVM_serverglobaledict(other) = sv.writeentitiestoclient_cliententitynumber;
VectorCopy(sv.writeentitiestoclient_eyes[0], PRVM_serverglobalvector(trace_endpos));
VectorCopy(sv.writeentitiestoclient_eyes[0], PRVM_G_VECTOR(OFS_PARM0));
VectorClear(PRVM_G_VECTOR(OFS_PARM1));
- PRVM_ExecuteProgram(PRVM_serveredictfunction(ed, camera_transform), "QC function e.camera_transform is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ed, camera_transform), "QC function e.camera_transform is missing");
if(!VectorCompare(PRVM_serverglobalvector(trace_endpos), sv.writeentitiestoclient_eyes[0]))
{
VectorCopy(PRVM_serverglobalvector(trace_endpos), camera_origins[n_cameras]);
}
#endif
-void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t *msg, int maxsize)
+static void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t *msg, int maxsize)
{
+ prvm_prog_t *prog = SVVM_prog;
qboolean need_empty = false;
int i, numsendstates, numcsqcsendstates;
entity_state_t *s;
*/
static void SV_CleanupEnts (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int e;
prvm_edict_t *ent;
*/
void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
{
+ prvm_prog_t *prog = SVVM_prog;
int bits;
int i;
prvm_edict_t *other;
// stuff the sigil bits into the high bits of items for sbar, or else
// mix in items2
- if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
+ // LordHavoc: detecting items2 turned out to be tricky, check if the field
+ // was forcefully declared, we want to override serverflags if it was
+ // declared by the qc intentionally, but not if we added it in the engine.
+ if (prog->fieldoffsets.items2 < (int)(prog->numfielddefs - SV_REQGLOBALS))
items = (int)PRVM_serveredictfloat(ent, items) | ((int)PRVM_serveredictfloat(ent, items2) << 23);
else
items = (int)PRVM_serveredictfloat(ent, items) | ((int)PRVM_serverglobalfloat(serverflags) << 28);
// cache weapon model name and index in client struct to save time
// (this search can be almost 1% of cpu time!)
- s = PRVM_GetString(PRVM_serveredictstring(ent, weaponmodel));
+ s = PRVM_GetString(prog, PRVM_serveredictstring(ent, weaponmodel));
if (strcmp(s, client->weaponmodel))
{
strlcpy(client->weaponmodel, s, sizeof(client->weaponmodel));
// add the client specific data to the datagram
SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
// now update the stats[] array using any registered custom fields
- VM_SV_UpdateCustomStats (client, client->edict, &msg, stats);
+ VM_SV_UpdateCustomStats(client, client->edict, &msg, stats);
// set host_client->statsdeltabits
Protocol_UpdateClientStats (stats);
*/
static void SV_UpdateToReliableMessages (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
client_t *client;
const char *name;
host_client->edict = PRVM_EDICT_NUM(i+1);
// DP_SV_CLIENTNAME
- name = PRVM_GetString(PRVM_serveredictstring(host_client->edict, netname));
+ name = PRVM_GetString(prog, PRVM_serveredictstring(host_client->edict, netname));
if (name == NULL)
name = "";
// always point the string back at host_client->name to keep it safe
strlcpy (host_client->name, name, sizeof (host_client->name));
- PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(host_client->name);
+ PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
if (host_client->spawned)
}
// NEXUIZ_PLAYERMODEL
- model = PRVM_GetString(PRVM_serveredictstring(host_client->edict, playermodel));
+ model = PRVM_GetString(prog, PRVM_serveredictstring(host_client->edict, playermodel));
if (model == NULL)
model = "";
// always point the string back at host_client->name to keep it safe
strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
- PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(host_client->playermodel);
+ PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(prog, host_client->playermodel);
// NEXUIZ_PLAYERSKIN
- skin = PRVM_GetString(PRVM_serveredictstring(host_client->edict, playerskin));
+ skin = PRVM_GetString(prog, PRVM_serveredictstring(host_client->edict, playerskin));
if (skin == NULL)
skin = "";
// always point the string back at host_client->name to keep it safe
strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
- PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(host_client->playerskin);
+ PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(prog, host_client->playerskin);
// TODO: add an extension name for this [1/17/2008 Black]
clientcamera = PRVM_serveredictedict(host_client->edict, clientcamera);
clientcamera = PRVM_NUM_FOR_EDICT(host_client->edict);
host_client->clientcamera = clientcamera;
- if (oldclientcamera != host_client->clientcamera)
+ if (oldclientcamera != host_client->clientcamera && host_client->netconnection)
{
MSG_WriteByte(&host_client->netconnection->message, svc_setview);
MSG_WriteShort(&host_client->netconnection->message, host_client->clientcamera);
SV_SendClientMessages
=======================
*/
-void SV_SendClientMessages (void)
+void SV_SendClientMessages(void)
{
int i, prepared = false;
// only prepare entities once per frame
SV_PrepareEntitiesForSending();
}
- SV_SendClientDatagram (host_client);
+ SV_SendClientDatagram(host_client);
}
// clear muzzle flashes
if (precachemode == 1)
Con_Printf("SV_ModelIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i]));
- sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, s[0] == '*' ? sv.worldname : NULL);
- if (sv.state != ss_loading)
+ if (sv.state == ss_loading)
+ {
+ // running from SV_SpawnServer which is launched from the client console command interpreter
+ sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, s[0] == '*' ? sv.worldname : NULL);
+ }
+ else
{
+ if (svs.threaded)
+ {
+ // this is running on the server thread, we can't load a model here (it would crash on renderer calls), so only look it up, the svc_precache will cause it to be loaded when it reaches the client
+ sv.models[i] = Mod_FindName (sv.model_precache[i], s[0] == '*' ? sv.worldname : NULL);
+ }
+ else
+ {
+ // running single threaded, so we can load the model here
+ sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, s[0] == '*' ? sv.worldname : NULL);
+ }
MSG_WriteByte(&sv.reliable_datagram, svc_precache);
MSG_WriteShort(&sv.reliable_datagram, i);
MSG_WriteString(&sv.reliable_datagram, filename);
argc = 0;
for (;;)
{
- if (!COM_ParseToken_Simple(&text, true, false) || !strcmp(com_token, "\n"))
+ if (!COM_ParseToken_Simple(&text, true, false, true) || !strcmp(com_token, "\n"))
break;
if (argc < 16)
{
dp_model_t *SV_GetModelFromEdict(prvm_edict_t *ed)
{
+ prvm_prog_t *prog = SVVM_prog;
int modelindex;
if (!ed || ed->priv.server->free)
return NULL;
*/
static void SV_CreateBaseline (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, entnum, large;
prvm_edict_t *svent;
reloaded on request.
================
*/
-void SV_Prepare_CSQC(void)
+static void SV_Prepare_CSQC(void)
{
fs_offset_t progsize;
*/
void SV_SaveSpawnparms (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
svs.serverflags = (int)PRVM_serverglobalfloat(serverflags);
continue;
// call the progs to get default spawn parms for the new client
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (PRVM_serverfunction(SetChangeParms), "QC function SetChangeParms is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SetChangeParms), "QC function SetChangeParms is missing");
for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
host_client->spawn_parms[j] = (&PRVM_serverglobalfloat(parm1))[j];
}
void SV_SpawnServer (const char *server)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *ent;
int i;
char *entities;
dp_model_t *worldmodel;
char modelname[sizeof(sv.worldname)];
+ char vabuf[1024];
Con_DPrintf("SpawnServer: %s\n", server);
}
}
+// SV_LockThreadMutex();
+
+ if(cls.state == ca_dedicated)
+ Sys_MakeProcessNice();
+
if (cls.state != ca_dedicated)
{
SCR_BeginLoadingPlaque();
if(sv.active)
{
- SV_VM_Begin();
World_End(&sv.world);
if(PRVM_serverfunction(SV_Shutdown))
{
func_t s = PRVM_serverfunction(SV_Shutdown);
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
- PRVM_ExecuteProgram(s,"SV_Shutdown() required");
+ prog->ExecuteProgram(prog, s,"SV_Shutdown() required");
}
- SV_VM_End();
}
// free q3 shaders so that any newly downloaded shaders will be active
if (!worldmodel || !worldmodel->TraceBox)
{
Con_Printf("Couldn't load map %s\n", modelname);
+
+ if(cls.state == ca_dedicated)
+ Sys_MakeProcessMean();
+
+// SV_UnlockThreadMutex();
+
return;
}
sv.protocol = PROTOCOL_QUAKE;
}
- SV_VM_Begin();
-
// load progs to get entity field count
//PR_LoadProgs ( sv_progs.string );
prog->allowworldwrites = true;
sv.paused = false;
- PRVM_serverglobalfloat(time) = sv.time = 1.0;
+ sv.time = 1.0;
Mod_ClearUsed();
worldmodel->used = true;
//
// clear world interaction links
//
- World_SetSize(&sv.world, sv.worldname, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs);
+ World_SetSize(&sv.world, sv.worldname, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs, prog);
World_Start(&sv.world);
strlcpy(sv.sound_precache[0], "", sizeof(sv.sound_precache[0]));
ent = PRVM_EDICT_NUM(0);
memset (ent->fields.vp, 0, prog->entityfields * 4);
ent->priv.server->free = false;
- PRVM_serveredictstring(ent, model) = PRVM_SetEngineString(sv.worldname);
+ PRVM_serveredictstring(ent, model) = PRVM_SetEngineString(prog, sv.worldname);
PRVM_serveredictfloat(ent, modelindex) = 1; // world model
PRVM_serveredictfloat(ent, solid) = SOLID_BSP;
PRVM_serveredictfloat(ent, movetype) = MOVETYPE_PUSH;
else
PRVM_serverglobalfloat(deathmatch) = deathmatch.integer;
- PRVM_serverglobalstring(mapname) = PRVM_SetEngineString(sv.name);
+ PRVM_serverglobalstring(mapname) = PRVM_SetEngineString(prog, sv.name);
// serverflags are for cross level information (sigils)
PRVM_serverglobalfloat(serverflags) = svs.serverflags;
{
host_client->spawned = false;
host_client->edict = PRVM_EDICT_NUM(i + 1);
- PRVM_ED_ClearEdict(host_client->edict);
+ PRVM_ED_ClearEdict(prog, host_client->edict);
}
// load replacement entity file if found
- if (sv_entpatch.integer && (entities = (char *)FS_LoadFile(va("%s.ent", sv.worldnamenoextension), tempmempool, true, NULL)))
+ if (sv_entpatch.integer && (entities = (char *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.ent", sv.worldnamenoextension), tempmempool, true, NULL)))
{
Con_Printf("Loaded %s.ent\n", sv.worldnamenoextension);
- PRVM_ED_LoadFromFile (entities);
+ PRVM_ED_LoadFromFile(prog, entities);
Mem_Free(entities);
}
else
- PRVM_ED_LoadFromFile (sv.worldmodel->brush.entities);
+ PRVM_ED_LoadFromFile(prog, sv.worldmodel->brush.entities);
// LordHavoc: clear world angles (to fix e3m3.bsp)
prog->allowworldwrites = false;
// run two frames to allow everything to settle
- PRVM_serverglobalfloat(time) = sv.time = 1.0001;
+ sv.time = 1.0001;
for (i = 0;i < 2;i++)
{
sv.frametime = 0.1;
sv.state = ss_active; // LordHavoc: workaround for svc_precache bug
- // to prevent network timeouts
- realtime = Sys_DoubleTime();
-
// send serverinfo to all connected clients, and set up botclients coming back from a level change
for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
{
host_client->clientconnectcalled = true;
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
- PRVM_ExecuteProgram (PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
host_client->spawned = true;
}
}
// update the map title cvar
- strlcpy(sv.worldmessage, PRVM_GetString(PRVM_serveredictstring(prog->edicts, message)), sizeof(sv.worldmessage)); // map title (not related to filename)
+ strlcpy(sv.worldmessage, PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message)), sizeof(sv.worldmessage)); // map title (not related to filename)
Cvar_SetQuick(&sv_worldmessage, sv.worldmessage);
Con_DPrint("Server spawned.\n");
NetConn_Heartbeat (2);
- SV_VM_End();
+ if(cls.state == ca_dedicated)
+ Sys_MakeProcessMean();
+
+// SV_UnlockThreadMutex();
}
/////////////////////////////////////////////////////
// SV VM stuff
-static void SV_VM_CB_BeginIncreaseEdicts(void)
+static void SVVM_begin_increase_edicts(prvm_prog_t *prog)
{
// links don't survive the transition, so unlink everything
World_UnlinkAll(&sv.world);
}
-static void SV_VM_CB_EndIncreaseEdicts(void)
+static void SVVM_end_increase_edicts(prvm_prog_t *prog)
{
int i;
prvm_edict_t *ent;
SV_LinkEdict(ent);
}
-static void SV_VM_CB_InitEdict(prvm_edict_t *e)
+static void SVVM_init_edict(prvm_prog_t *prog, prvm_edict_t *e)
{
// LordHavoc: for consistency set these here
int num = PRVM_NUM_FOR_EDICT(e) - 1;
// set netname/clientcolors back to client values so that
// DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS will not immediately
// reset them
- PRVM_serveredictstring(e, netname) = PRVM_SetEngineString(svs.clients[num].name);
+ PRVM_serveredictstring(e, netname) = PRVM_SetEngineString(prog, svs.clients[num].name);
PRVM_serveredictfloat(e, clientcolors) = svs.clients[num].colors;
// NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
- PRVM_serveredictstring(e, playermodel) = PRVM_SetEngineString(svs.clients[num].playermodel);
- PRVM_serveredictstring(e, playerskin) = PRVM_SetEngineString(svs.clients[num].playerskin);
+ PRVM_serveredictstring(e, playermodel) = PRVM_SetEngineString(prog, svs.clients[num].playermodel);
+ PRVM_serveredictstring(e, playerskin) = PRVM_SetEngineString(prog, svs.clients[num].playerskin);
// Assign netaddress (IP Address, etc)
if(svs.clients[num].netconnection != NULL)
{
// Acquire Readable Address
LHNETADDRESS_ToString(&svs.clients[num].netconnection->peeraddress, svs.clients[num].netaddress, sizeof(svs.clients[num].netaddress), false);
- PRVM_serveredictstring(e, netaddress) = PRVM_SetEngineString(svs.clients[num].netaddress);
+ PRVM_serveredictstring(e, netaddress) = PRVM_SetEngineString(prog, svs.clients[num].netaddress);
}
else
- PRVM_serveredictstring(e, netaddress) = PRVM_SetEngineString("null/botclient");
+ PRVM_serveredictstring(e, netaddress) = PRVM_SetEngineString(prog, "null/botclient");
if(svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.client_idfp[0])
- PRVM_serveredictstring(e, crypto_idfp) = PRVM_SetEngineString(svs.clients[num].netconnection->crypto.client_idfp);
+ PRVM_serveredictstring(e, crypto_idfp) = PRVM_SetEngineString(prog, svs.clients[num].netconnection->crypto.client_idfp);
else
PRVM_serveredictstring(e, crypto_idfp) = 0;
if(svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.client_keyfp[0])
- PRVM_serveredictstring(e, crypto_keyfp) = PRVM_SetEngineString(svs.clients[num].netconnection->crypto.client_keyfp);
+ PRVM_serveredictstring(e, crypto_keyfp) = PRVM_SetEngineString(prog, svs.clients[num].netconnection->crypto.client_keyfp);
else
PRVM_serveredictstring(e, crypto_keyfp) = 0;
if(svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.server_keyfp[0])
- PRVM_serveredictstring(e, crypto_mykeyfp) = PRVM_SetEngineString(svs.clients[num].netconnection->crypto.server_keyfp);
+ PRVM_serveredictstring(e, crypto_mykeyfp) = PRVM_SetEngineString(prog, svs.clients[num].netconnection->crypto.server_keyfp);
else
PRVM_serveredictstring(e, crypto_mykeyfp) = 0;
if(svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated && svs.clients[num].netconnection->crypto.use_aes)
- PRVM_serveredictstring(e, crypto_encryptmethod) = PRVM_SetEngineString("AES128");
+ PRVM_serveredictstring(e, crypto_encryptmethod) = PRVM_SetEngineString(prog, "AES128");
else
PRVM_serveredictstring(e, crypto_encryptmethod) = 0;
if(svs.clients[num].netconnection != NULL && svs.clients[num].netconnection->crypto.authenticated)
- PRVM_serveredictstring(e, crypto_signmethod) = PRVM_SetEngineString("HMAC-SHA256");
+ PRVM_serveredictstring(e, crypto_signmethod) = PRVM_SetEngineString(prog, "HMAC-SHA256");
else
PRVM_serveredictstring(e, crypto_signmethod) = 0;
}
}
-static void SV_VM_CB_FreeEdict(prvm_edict_t *ed)
+static void SVVM_free_edict(prvm_prog_t *prog, prvm_edict_t *ed)
{
int i;
int e;
PRVM_serveredictfloat(ed, nextthink) = -1;
PRVM_serveredictfloat(ed, solid) = 0;
- VM_RemoveEdictSkeleton(ed);
+ VM_RemoveEdictSkeleton(prog, ed);
World_Physics_RemoveFromEntity(&sv.world, ed);
World_Physics_RemoveJointFromEntity(&sv.world, ed);
}
}
-static void SV_VM_CB_CountEdicts(void)
+static void SVVM_count_edicts(prvm_prog_t *prog)
{
int i;
prvm_edict_t *ent;
Con_Printf("step :%3i\n", step);
}
-static qboolean SV_VM_CB_LoadEdict(prvm_edict_t *ent)
+static qboolean SVVM_load_edict(prvm_prog_t *prog, prvm_edict_t *ent)
{
// remove things from different skill levels or deathmatch
if (gamemode != GAME_TRANSFUSION) //Transfusion does this in QC
static void SV_VM_Setup(void)
{
- PRVM_Begin;
- PRVM_InitProg( PRVM_SERVERPROG );
+ prvm_prog_t *prog = SVVM_prog;
+ PRVM_Prog_Init(prog);
// allocate the mempools
// TODO: move the magic numbers/constants into #defines [9/13/2006 Black]
prog->extensionstring = vm_sv_extensions;
prog->loadintoworld = true;
- prog->begin_increase_edicts = SV_VM_CB_BeginIncreaseEdicts;
- prog->end_increase_edicts = SV_VM_CB_EndIncreaseEdicts;
- prog->init_edict = SV_VM_CB_InitEdict;
- prog->free_edict = SV_VM_CB_FreeEdict;
- prog->count_edicts = SV_VM_CB_CountEdicts;
- prog->load_edict = SV_VM_CB_LoadEdict;
- prog->init_cmd = VM_SV_Cmd_Init;
- prog->reset_cmd = VM_SV_Cmd_Reset;
- prog->error_cmd = Host_Error;
- prog->ExecuteProgram = SVVM_ExecuteProgram;
+ // all callbacks must be defined (pointers are not checked before calling)
+ prog->begin_increase_edicts = SVVM_begin_increase_edicts;
+ prog->end_increase_edicts = SVVM_end_increase_edicts;
+ prog->init_edict = SVVM_init_edict;
+ prog->free_edict = SVVM_free_edict;
+ prog->count_edicts = SVVM_count_edicts;
+ prog->load_edict = SVVM_load_edict;
+ prog->init_cmd = SVVM_init_cmd;
+ prog->reset_cmd = SVVM_reset_cmd;
+ prog->error_cmd = Host_Error;
+ prog->ExecuteProgram = SVVM_ExecuteProgram;
- PRVM_LoadProgs( sv_progs.string, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals);
+ PRVM_Prog_Load(prog, sv_progs.string, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals);
// some mods compiled with scrambling compilers lack certain critical
// global names and field names such as "self" and "time" and "nextthink"
// PRVM_ED_FindGlobalOffset_FromStruct(globalvars_t, SetChangeParms);
}
else
- Con_DPrintf("%s: %s system vars have been modified (CRC %i != engine %i), will not load in other engines", PRVM_NAME, sv_progs.string, prog->progs_crc, PROGHEADER_CRC);
+ Con_DPrintf("%s: %s system vars have been modified (CRC %i != engine %i), will not load in other engines", prog->name, sv_progs.string, prog->progs_crc, PROGHEADER_CRC);
// OP_STATE is always supported on server because we add fields/globals for it
prog->flag |= PRVM_OP_STATE;
VM_CustomStats_Clear();//[515]: csqc
- PRVM_End;
-
SV_Prepare_CSQC();
}
-void SV_VM_Begin(void)
+extern cvar_t host_maxwait;
+extern cvar_t host_framerate;
+static int SV_ThreadFunc(void *voiddata)
{
- PRVM_Begin;
- PRVM_SetProg( PRVM_SERVERPROG );
+ prvm_prog_t *prog = SVVM_prog;
+ qboolean playing = false;
+ double sv_timer = 0;
+ double sv_deltarealtime, sv_oldrealtime, sv_realtime;
+ double wait;
+ int i;
+ char vabuf[1024];
+ sv_realtime = Sys_DirtyTime();
+ while (!svs.threadstop)
+ {
+ // FIXME: we need to handle Host_Error in the server thread somehow
+// if (setjmp(sv_abortframe))
+// continue; // something bad happened in the server game
+
+ sv_oldrealtime = sv_realtime;
+ sv_realtime = Sys_DirtyTime();
+ sv_deltarealtime = sv_realtime - sv_oldrealtime;
+ if (sv_deltarealtime < 0 || sv_deltarealtime >= 1800) sv_deltarealtime = 0;
+
+ sv_timer += sv_deltarealtime;
+
+ svs.perf_acc_realtime += sv_deltarealtime;
+
+ // at this point we start doing real server work, and must block on any client activity pertaining to the server (such as executing SV_SpawnServer)
+ SV_LockThreadMutex();
+
+ // Look for clients who have spawned
+ playing = false;
+ if (sv.active)
+ for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
+ if(host_client->spawned)
+ if(host_client->netconnection)
+ playing = true;
+ if(!playing)
+ {
+ // Nobody is looking? Then we won't do timing...
+ // Instead, reset it to zero
+ svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
+ }
+ else if(svs.perf_acc_realtime > 5)
+ {
+ svs.perf_cpuload = 1 - svs.perf_acc_sleeptime / svs.perf_acc_realtime;
+ svs.perf_lost = svs.perf_acc_lost / svs.perf_acc_realtime;
+ if(svs.perf_acc_offset_samples > 0)
+ {
+ svs.perf_offset_max = svs.perf_acc_offset_max;
+ svs.perf_offset_avg = svs.perf_acc_offset / svs.perf_acc_offset_samples;
+ svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg);
+ }
+ if(svs.perf_lost > 0 && developer_extra.integer)
+ Con_DPrintf("Server can't keep up: %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
+ svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
+ }
- PRVM_serverglobalfloat(time) = (float) sv.time;
+ // get new packets
+ if (sv.active)
+ NetConn_ServerFrame();
+
+ // if the accumulators haven't become positive yet, wait a while
+ wait = sv_timer * -1000000.0;
+ if (wait >= 1)
+ {
+ double time0, delta;
+ SV_UnlockThreadMutex(); // don't keep mutex locked while sleeping
+ if (host_maxwait.value <= 0)
+ wait = min(wait, 1000000.0);
+ else
+ wait = min(wait, host_maxwait.value * 1000.0);
+ if(wait < 1)
+ wait = 1; // because we cast to int
+ time0 = Sys_DirtyTime();
+ Sys_Sleep((int)wait);
+ delta = Sys_DirtyTime() - time0;if (delta < 0 || delta >= 1800) delta = 0;
+ svs.perf_acc_sleeptime += delta;
+ continue;
+ }
+
+ if (sv.active && sv_timer > 0)
+ {
+ // execute one server frame
+ double advancetime;
+ float offset;
+
+ if (sys_ticrate.value <= 0)
+ advancetime = min(sv_timer, 0.1); // don't step more than 100ms
+ else
+ advancetime = sys_ticrate.value;
+
+ if(advancetime > 0)
+ {
+ offset = sv_timer + (Sys_DirtyTime() - sv_realtime); // LordHavoc: FIXME: I don't understand this line
+ ++svs.perf_acc_offset_samples;
+ svs.perf_acc_offset += offset;
+ svs.perf_acc_offset_squared += offset * offset;
+ if(svs.perf_acc_offset_max < offset)
+ svs.perf_acc_offset_max = offset;
+ }
+
+ // only advance time if not paused
+ // the game also pauses in singleplayer when menu or console is used
+ sv.frametime = advancetime * slowmo.value;
+ if (host_framerate.value)
+ sv.frametime = host_framerate.value;
+ if (sv.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused)))
+ sv.frametime = 0;
+
+ sv_timer -= advancetime;
+
+ // move things around and think unless paused
+ if (sv.frametime)
+ SV_Physics();
+
+ // send all messages to the clients
+ SV_SendClientMessages();
+
+ if (sv.paused == 1 && sv_realtime > sv.pausedstart && sv.pausedstart > 0)
+ {
+ PRVM_serverglobalfloat(time) = sv.time;
+ prog->globals.generic[OFS_PARM0] = sv_realtime - sv.pausedstart;
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing");
+ }
+
+ // send an heartbeat if enough time has passed since the last one
+ NetConn_Heartbeat(0);
+
+ }
+
+ // we're back to safe code now
+ SV_UnlockThreadMutex();
+
+ // if there is some time remaining from this frame, reset the timers
+ if (sv_timer >= 0)
+ {
+ svs.perf_acc_lost += sv_timer;
+ sv_timer = 0;
+ }
+ }
+ return 0;
}
-void SV_VM_End(void)
+void SV_StartThread(void)
{
- PRVM_End;
+ if (!sv_threaded.integer || !Thread_HasThreads())
+ return;
+ svs.threaded = true;
+ svs.threadstop = false;
+ svs.threadmutex = Thread_CreateMutex();
+ svs.thread = Thread_CreateThread(SV_ThreadFunc, NULL);
+}
+
+void SV_StopThread(void)
+{
+ if (!svs.threaded)
+ return;
+ svs.threadstop = true;
+ Thread_WaitThread(svs.thread, 0);
+ Thread_DestroyMutex(svs.threadmutex);
+ svs.threaded = false;
}
qboolean SV_CheckBottom (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t mins, maxs, start, stop;
trace_t trace;
int x, y;
*/
qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
{
+ prvm_prog_t *prog = SVVM_prog;
float dz;
vec3_t oldorg, neworg, end, traceendpos;
trace_t trace;
======================
*/
-void VM_changeyaw (void);
-qboolean SV_StepDirection (prvm_edict_t *ent, float yaw, float dist)
+static qboolean SV_StepDirection (prvm_edict_t *ent, float yaw, float dist)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t move, oldorigin;
float delta;
PRVM_serveredictfloat(ent, ideal_yaw) = yaw;
- VM_changeyaw();
+ VM_changeyaw(prog);
yaw = yaw*M_PI*2 / 360;
move[0] = cos(yaw)*dist;
======================
*/
-void SV_FixCheckBottom (prvm_edict_t *ent)
+static void SV_FixCheckBottom (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_PARTIALGROUND;
}
================
*/
#define DI_NODIR -1
-void SV_NewChaseDir (prvm_edict_t *actor, prvm_edict_t *enemy, float dist)
+static void SV_NewChaseDir (prvm_edict_t *actor, prvm_edict_t *enemy, float dist)
{
+ prvm_prog_t *prog = SVVM_prog;
float deltax,deltay;
float d[3];
float tdir, olddir, turnaround;
======================
*/
-qboolean SV_CloseEnough (prvm_edict_t *ent, prvm_edict_t *goal, float dist)
+static qboolean SV_CloseEnough (prvm_edict_t *ent, prvm_edict_t *goal, float dist)
{
int i;
======================
*/
-void SV_MoveToGoal (void)
+void VM_SV_MoveToGoal(prvm_prog_t *prog)
{
prvm_edict_t *ent, *goal;
float dist;
// sv_phys.c
#include "quakedef.h"
+#include "prvm_cmds.h"
/*
void SV_Physics_Toss (prvm_edict_t *ent);
-int SV_GetPitchSign(prvm_edict_t *ent)
+int SV_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
{
dp_model_t *model;
if (
int SV_GenericHitSuperContentsMask(const prvm_edict_t *passedict)
{
+ prvm_prog_t *prog = SVVM_prog;
if (passedict)
{
int dphitcontentsmask = (int)PRVM_serveredictfloat(passedict, dphitcontentsmask);
*/
trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, bodysupercontents;
int passedictprog;
float pitchsign = 1;
// clip to entities
// because this uses World_EntitiestoBox, we know all entity boxes overlap
// the clip region, so we can skip culling checks in the loop below
- numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
{
model = SV_GetModelFromEdict(touch);
- pitchsign = SV_GetPitchSign(touch);
+ pitchsign = SV_GetPitchSign(prog, touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
else
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
- VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipstart, hitsupercontentsmask);
else
trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask)
#endif
{
+ prvm_prog_t *prog = SVVM_prog;
int i, bodysupercontents;
int passedictprog;
float pitchsign = 1;
// clip to entities
// because this uses World_EntitiestoBox, we know all entity boxes overlap
// the clip region, so we can skip culling checks in the loop below
- numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
{
model = SV_GetModelFromEdict(touch);
- pitchsign = SV_GetPitchSign(touch);
+ pitchsign = SV_GetPitchSign(prog, touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
else
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
- VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
#endif
#endif
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t hullmins, hullmaxs;
int i, bodysupercontents;
int passedictprog;
// clip to entities
// because this uses World_EntitiestoBox, we know all entity boxes overlap
// the clip region, so we can skip culling checks in the loop below
- numtouchedicts = World_EntitiesInBox(&sv.world, clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
if ((int) PRVM_serveredictfloat(touch, solid) == SOLID_BSP || type == MOVE_HITMODEL)
{
model = SV_GetModelFromEdict(touch);
- pitchsign = SV_GetPitchSign(touch);
+ pitchsign = SV_GetPitchSign(prog, touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2], pitchsign * PRVM_serveredictvector(touch, angles)[0], PRVM_serveredictvector(touch, angles)[1], PRVM_serveredictvector(touch, angles)[2], 1);
else
Matrix4x4_CreateTranslate(&matrix, PRVM_serveredictvector(touch, origin)[0], PRVM_serveredictvector(touch, origin)[1], PRVM_serveredictvector(touch, origin)[2]);
Matrix4x4_Invert_Simple(&imatrix, &matrix);
- VM_GenerateFrameGroupBlend(touch->priv.server->framegroupblend, touch);
+ VM_GenerateFrameGroupBlend(prog, touch->priv.server->framegroupblend, touch);
VM_FrameBlendFromFrameGroupBlend(touch->priv.server->frameblend, touch->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(touch, model, touch->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, touch, model, touch->priv.server->frameblend);
if (type == MOVE_MISSILE && (int)PRVM_serveredictfloat(touch, flags) & FL_MONSTER)
Collision_ClipToGenericEntity(&trace, model, touch->priv.server->frameblend, &touch->priv.server->skeleton, PRVM_serveredictvector(touch, mins), PRVM_serveredictvector(touch, maxs), bodysupercontents, &matrix, &imatrix, clipstart, clipmins2, clipmaxs2, clipend, hitsupercontentsmask);
else
int SV_PointSuperContents(const vec3_t point)
{
+ prvm_prog_t *prog = SVVM_prog;
int supercontents = 0;
int i;
prvm_edict_t *touch;
return supercontents;
// get list of entities at this point
- numtouchedicts = World_EntitiesInBox(&sv.world, point, point, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(point, point, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
===============================================================================
*/
+int SV_EntitiesInBox(const vec3_t mins, const vec3_t maxs, int maxedicts, prvm_edict_t **resultedicts)
+{
+ prvm_prog_t *prog = SVVM_prog;
+ vec3_t paddedmins, paddedmaxs;
+ if (maxedicts < 1 || resultedicts == NULL)
+ return 0;
+ VectorSet(paddedmins, mins[0] - 10, mins[1] - 10, mins[2] - 1);
+ VectorSet(paddedmaxs, maxs[0] + 10, maxs[1] + 10, maxs[2] + 1);
+ if (sv_areadebug.integer)
+ {
+ int numresultedicts = 0;
+ int edictindex;
+ prvm_edict_t *ed;
+ for (edictindex = 1;edictindex < prog->num_edicts;edictindex++)
+ {
+ ed = PRVM_EDICT_NUM(edictindex);
+ if (!ed->priv.required->free && BoxesOverlap(PRVM_serveredictvector(ed, absmin), PRVM_serveredictvector(ed, absmax), paddedmins, paddedmaxs))
+ {
+ resultedicts[numresultedicts++] = ed;
+ if (numresultedicts == maxedicts)
+ break;
+ }
+ }
+ return numresultedicts;
+ }
+ else
+ return World_EntitiesInBox(&sv.world, paddedmins, paddedmaxs, maxedicts, resultedicts);
+}
+
void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(touch);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(ent);
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(trace_dphitcontents) = 0;
PRVM_serverglobalfloat(trace_dphitq3surfaceflags) = 0;
PRVM_serverglobalstring(trace_dphittexturename) = 0;
- PRVM_ExecuteProgram (PRVM_serveredictfunction(touch, touch), "QC function self.touch is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(touch, touch), "QC function self.touch is missing");
}
void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, numtouchedicts, old_self, old_other;
prvm_edict_t *touch;
static prvm_edict_t *touchedicts[MAX_EDICTS];
// build a list of edicts to touch, because the link loop can be corrupted
// by IncreaseEdicts called during touch functions
- numtouchedicts = World_EntitiesInBox(&sv.world, ent->priv.server->areamins, ent->priv.server->areamaxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(ent->priv.server->areamins, ent->priv.server->areamaxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
*/
void SV_LinkEdict (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
dp_model_t *model;
vec3_t mins, maxs;
int modelindex;
}
model = SV_GetModelByIndex(modelindex);
- VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
+ VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
// set the abs box
*/
static int SV_TestEntityPosition (prvm_edict_t *ent, vec3_t offset)
{
+ prvm_prog_t *prog = SVVM_prog;
int contents;
vec3_t org;
trace_t trace;
contents = SV_GenericHitSuperContentsMask(ent);
VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
- trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, origin), MOVE_NOMONSTERS, ent, contents);
+ trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, origin), ((PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), ent, contents);
if (trace.startsupercontents & contents)
return true;
else
return false;
}
-/*
-================
-SV_CheckAllEnts
-================
-*/
-void SV_CheckAllEnts (void)
-{
- int e;
- prvm_edict_t *check;
-
- // see if any solid entities are inside the final position
- check = PRVM_NEXT_EDICT(prog->edicts);
- for (e = 1;e < prog->num_edicts;e++, check = PRVM_NEXT_EDICT(check))
- {
- if (check->priv.server->free)
- continue;
- if (PRVM_serveredictfloat(check, movetype) == MOVETYPE_PUSH
- || PRVM_serveredictfloat(check, movetype) == MOVETYPE_NONE
- || PRVM_serveredictfloat(check, movetype) == MOVETYPE_FOLLOW
- || PRVM_serveredictfloat(check, movetype) == MOVETYPE_NOCLIP)
- continue;
-
- if (SV_TestEntityPosition (check, vec3_origin))
- Con_Print("entity in invalid position\n");
- }
-}
-
// DRESK - Support for Entity Contents Transition Event
/*
================
returns true if entity had a valid contentstransition function call
================
*/
-int SV_CheckContentsTransition(prvm_edict_t *ent, const int nContents)
+static int SV_CheckContentsTransition(prvm_edict_t *ent, const int nContents)
{
+ prvm_prog_t *prog = SVVM_prog;
int bValidFunctionCall;
// Default Valid Function Call to False
// Assign Valid Function
bValidFunctionCall = true;
// Prepare Parameters (Original Contents, New Contents)
- // Original Contents
- PRVM_G_FLOAT(OFS_PARM0) = PRVM_serveredictfloat(ent, watertype);
- // New Contents
- PRVM_G_FLOAT(OFS_PARM1) = nContents;
- // Assign Self
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // Original Contents
+ PRVM_G_FLOAT(OFS_PARM0) = PRVM_serveredictfloat(ent, watertype);
+ // New Contents
+ PRVM_G_FLOAT(OFS_PARM1) = nContents;
+ // Assign Self
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // Set Time
+ PRVM_serverglobalfloat(time) = sv.time;
// Execute VM Function
- PRVM_ExecuteProgram(PRVM_serveredictfunction(ent, contentstransition), "contentstransition: NULL function");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, contentstransition), "contentstransition: NULL function");
}
}
*/
void SV_CheckVelocity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
float wishspeed;
{
if (IS_NAN(PRVM_serveredictvector(ent, velocity)[i]))
{
- Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
PRVM_serveredictvector(ent, velocity)[i] = 0;
}
if (IS_NAN(PRVM_serveredictvector(ent, origin)[i]))
{
- Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
PRVM_serveredictvector(ent, origin)[i] = 0;
}
}
Returns false if the entity removed itself.
=============
*/
-qboolean SV_RunThink (prvm_edict_t *ent)
+static qboolean SV_RunThink (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int iterations;
// don't let things stay in the past.
PRVM_serveredictfloat(ent, nextthink) = 0;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
// mods often set nextthink to time to cause a think every frame,
// we don't want to loop in that case, so exit if the new nextthink is
// <= the time the qc was told, also exit if it is past the end of the
Two entities have touched, so run their touch functions
==================
*/
-extern void VM_SetTraceGlobals(const trace_t *trace);
-extern sizebuf_t vm_tempstringsbuf;
-void SV_Impact (prvm_edict_t *e1, trace_t *trace)
+static void SV_Impact (prvm_edict_t *e1, trace_t *trace)
{
+ prvm_prog_t *prog = SVVM_prog;
int restorevm_tempstringsbuf_cursize;
int old_self, old_other;
prvm_edict_t *e2 = (prvm_edict_t *)trace->ent;
old_self = PRVM_serverglobaledict(self);
old_other = PRVM_serverglobaledict(other);
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
- VM_SetTraceGlobals(trace);
+ VM_SetTraceGlobals(prog, trace);
- PRVM_serverglobalfloat(time) = sv.time;
if (!e1->priv.server->free && !e2->priv.server->free && PRVM_serveredictfunction(e1, touch) && PRVM_serveredictfloat(e1, solid) != SOLID_NOT)
{
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(e1);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(e2);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(e1, touch), "QC function self.touch is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(e1, touch), "QC function self.touch is missing");
}
if (!e1->priv.server->free && !e2->priv.server->free && PRVM_serveredictfunction(e2, touch) && PRVM_serveredictfloat(e2, solid) != SOLID_NOT)
{
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(e2);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(e1);
VectorCopy(PRVM_serveredictvector(e2, origin), PRVM_serverglobalvector(trace_endpos));
PRVM_serverglobalfloat(trace_dphitcontents) = 0;
PRVM_serverglobalfloat(trace_dphitq3surfaceflags) = 0;
PRVM_serverglobalstring(trace_dphittexturename) = 0;
- PRVM_ExecuteProgram (PRVM_serveredictfunction(e2, touch), "QC function self.touch is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(e2, touch), "QC function self.touch is missing");
}
PRVM_serverglobaledict(self) = old_self;
PRVM_serverglobaledict(other) = old_other;
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
}
==================
*/
#define STOP_EPSILON 0.1
-void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
+static void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
{
int i;
float backoff;
#define MAX_CLIP_PLANES 5
static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, float *stepnormal, int hitsupercontentsmask, float stepheight)
{
+ prvm_prog_t *prog = SVVM_prog;
int blocked, bumpcount;
int i, j, numplanes;
float d, time_left, gravity;
*/
static float SV_Gravity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
float ent_gravity;
ent_gravity = PRVM_serveredictfloat(ent, gravity);
===============================================================================
*/
+static qboolean SV_NudgeOutOfSolid_PivotIsKnownGood(prvm_edict_t *ent, vec3_t pivot)
+{
+ prvm_prog_t *prog = SVVM_prog;
+ int bump;
+ trace_t stucktrace;
+ vec3_t stuckorigin;
+ vec3_t stuckmins, stuckmaxs;
+ vec3_t goodmins, goodmaxs;
+ vec3_t testorigin;
+ vec_t nudge;
+ vec3_t move;
+ VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
+ VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
+ VectorCopy(pivot, goodmins);
+ VectorCopy(pivot, goodmaxs);
+ for (bump = 0;bump < 6;bump++)
+ {
+ int coord = 2-(bump >> 1);
+ //int coord = (bump >> 1);
+ int dir = (bump & 1);
+ int subbump;
+
+ for(subbump = 0; ; ++subbump)
+ {
+ VectorCopy(stuckorigin, testorigin);
+ if(dir)
+ {
+ // pushing maxs
+ testorigin[coord] += stuckmaxs[coord] - goodmaxs[coord];
+ }
+ else
+ {
+ // pushing mins
+ testorigin[coord] += stuckmins[coord] - goodmins[coord];
+ }
+
+ stucktrace = SV_TraceBox(stuckorigin, goodmins, goodmaxs, testorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
+ if (stucktrace.bmodelstartsolid)
+ {
+ // BAD BAD, can't fix that
+ return false;
+ }
+
+ if (stucktrace.fraction >= 1)
+ break; // it WORKS!
+
+ if(subbump >= 10)
+ {
+ // BAD BAD, can't fix that
+ return false;
+ }
+
+ // we hit something... let's move out of it
+ VectorSubtract(stucktrace.endpos, testorigin, move);
+ nudge = DotProduct(stucktrace.plane.normal, move) + 0.03125f; // FIXME cvar this constant
+ VectorMA(stuckorigin, nudge, stucktrace.plane.normal, stuckorigin);
+ }
+ /*
+ if(subbump > 0)
+ Con_Printf("subbump: %d\n", subbump);
+ */
+
+ if(dir)
+ {
+ // pushing maxs
+ goodmaxs[coord] = stuckmaxs[coord];
+ }
+ else
+ {
+ // pushing mins
+ goodmins[coord] = stuckmins[coord];
+ }
+ }
+
+ // WE WIN
+ VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
+
+ return true;
+}
+
+static qboolean SV_NudgeOutOfSolid(prvm_edict_t *ent)
+{
+ prvm_prog_t *prog = SVVM_prog;
+ int bump;
+ trace_t stucktrace;
+ vec3_t stuckorigin;
+ vec3_t stuckmins, stuckmaxs;
+ vec_t nudge;
+ vec_t separation = sv_gameplayfix_nudgeoutofsolid_separation.value;
+ if (sv.worldmodel && sv.worldmodel->brushq1.numclipnodes)
+ separation = 0.0f; // when using hulls, it can not be enlarged
+ VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
+ VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
+ VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
+ stuckmins[0] -= separation;
+ stuckmins[1] -= separation;
+ stuckmins[2] -= separation;
+ stuckmaxs[0] += separation;
+ stuckmaxs[1] += separation;
+ stuckmaxs[2] += separation;
+ for (bump = 0;bump < 10;bump++)
+ {
+ stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
+ if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0)
+ {
+ // found a good location, use it
+ VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
+ return true;
+ }
+ nudge = -stucktrace.startdepth;
+ VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin);
+ }
+ return false;
+}
+
/*
============
SV_PushEntity
*/
static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink)
{
+ prvm_prog_t *prog = SVVM_prog;
int solid;
int movetype;
int type;
- int bump;
vec3_t mins, maxs;
- vec3_t original, original_velocity;
vec3_t start;
vec3_t end;
// move start position out of solids
if (sv_gameplayfix_nudgeoutofsolid.integer && sv_gameplayfix_nudgeoutofsolid_separation.value >= 0)
{
- trace_t stucktrace;
- vec3_t stuckorigin;
- vec3_t stuckmins, stuckmaxs;
- vec_t nudge;
- vec_t separation = sv_gameplayfix_nudgeoutofsolid_separation.value;
- if (sv.worldmodel && sv.worldmodel->brushq1.numclipnodes)
- separation = 0.0f; // when using hulls, it can not be enlarged
- VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
- VectorCopy(mins, stuckmins);
- VectorCopy(maxs, stuckmaxs);
- stuckmins[0] -= separation;
- stuckmins[1] -= separation;
- stuckmins[2] -= separation;
- stuckmaxs[0] += separation;
- stuckmaxs[1] += separation;
- stuckmaxs[2] += separation;
- for (bump = 0;bump < 10;bump++)
- {
- stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
- if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0)
- {
- // found a good location, use it
- VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
- break;
- }
- nudge = -stucktrace.startdepth;
- VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin);
- }
+ SV_NudgeOutOfSolid(ent);
}
VectorCopy(PRVM_serveredictvector(ent, origin), start);
if (movetype == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
+ else if (movetype == MOVETYPE_FLY_WORLDONLY)
+ type = MOVE_WORLDONLY;
else if (solid == SOLID_TRIGGER || solid == SOLID_NOT)
type = MOVE_NOMONSTERS; // only clip against bmodels
else
VectorCopy(trace->endpos, PRVM_serveredictvector(ent, origin));
- VectorCopy(PRVM_serveredictvector(ent, origin), original);
- VectorCopy(PRVM_serveredictvector(ent, velocity), original_velocity);
+ ent->priv.required->mark = PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN; // -2: setorigin running
SV_LinkEdict(ent);
if((PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace->ent && (!((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND) || PRVM_serveredictedict(ent, groundentity) != PRVM_EDICT_TO_PROG(trace->ent))))
SV_Impact (ent, trace);
- return VectorCompare(PRVM_serveredictvector(ent, origin), original) && VectorCompare(PRVM_serveredictvector(ent, velocity), original_velocity);
+ if(ent->priv.required->mark == PRVM_EDICT_MARK_SETORIGIN_CAUGHT)
+ {
+ ent->priv.required->mark = 0;
+ return false;
+ }
+ else if(ent->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
+ {
+ ent->priv.required->mark = 0;
+ return true;
+ }
+ else
+ {
+ Con_Printf("The edict mark had been overwritten! Please debug this.\n");
+ return true;
+ }
}
============
*/
-void SV_PushMove (prvm_edict_t *pusher, float movetime)
+static void SV_PushMove (prvm_edict_t *pusher, float movetime)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, e, index;
int pusherowner, pusherprog;
int checkcontents;
trace_t trace, trace2;
matrix4x4_t pusherfinalmatrix, pusherfinalimatrix;
static unsigned short moved_edicts[MAX_EDICTS];
+ vec3_t pivot;
if (!PRVM_serveredictvector(pusher, velocity)[0] && !PRVM_serveredictvector(pusher, velocity)[1] && !PRVM_serveredictvector(pusher, velocity)[2] && !PRVM_serveredictvector(pusher, avelocity)[0] && !PRVM_serveredictvector(pusher, avelocity)[1] && !PRVM_serveredictvector(pusher, avelocity)[2])
{
// see if any solid entities are inside the final position
num_moved = 0;
- numcheckentities = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, checkentities);
+ if (PRVM_serveredictfloat(pusher, movetype) == MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push...
+ numcheckentities = 0;
+ else // MOVETYPE_PUSH
+ numcheckentities = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, checkentities);
for (e = 0;e < numcheckentities;e++)
{
prvm_edict_t *check = checkentities[e];
case MOVETYPE_PUSH:
case MOVETYPE_FOLLOW:
case MOVETYPE_NOCLIP:
- case MOVETYPE_FAKEPUSH:
+ case MOVETYPE_FLY_WORLDONLY:
continue;
default:
break;
}
}
+ VectorLerp(PRVM_serveredictvector(check, mins), 0.5f, PRVM_serveredictvector(check, maxs), pivot);
+ //VectorClear(pivot);
+
if (rotated)
{
vec3_t org2;
VectorSubtract (PRVM_serveredictvector(check, origin), PRVM_serveredictvector(pusher, origin), org);
+ VectorAdd (org, pivot, org);
org2[0] = DotProduct (org, forward);
org2[1] = DotProduct (org, left);
org2[2] = DotProduct (org, up);
Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
if (trace.startsolid)
{
- // try moving the contacted entity a tiny bit further to account for precision errors
vec3_t move2;
- PRVM_serveredictfloat(pusher, solid) = SOLID_NOT;
- VectorScale(move, 1.1, move2);
- VectorCopy (check->priv.server->moved_from, PRVM_serveredictvector(check, origin));
- VectorCopy (check->priv.server->moved_fromangles, PRVM_serveredictvector(check, angles));
- if(!SV_PushEntity (&trace2, check, move2, true, true))
- {
- // entity "check" got teleported
- continue;
- }
- PRVM_serveredictfloat(pusher, solid) = savesolid;
- Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
- if (trace.startsolid)
+ if(SV_NudgeOutOfSolid_PivotIsKnownGood(check, pivot))
{
- // try moving the contacted entity a tiny bit less to account for precision errors
- PRVM_serveredictfloat(pusher, solid) = SOLID_NOT;
- VectorScale(move, 0.9, move2);
- VectorCopy (check->priv.server->moved_from, PRVM_serveredictvector(check, origin));
- VectorCopy (check->priv.server->moved_fromangles, PRVM_serveredictvector(check, angles));
- if(!SV_PushEntity (&trace2, check, move2, true, true))
+ // hack to invoke all necessary movement triggers
+ VectorClear(move2);
+ if(!SV_PushEntity(&trace2, check, move2, true, true))
{
// entity "check" got teleported
continue;
}
- PRVM_serveredictfloat(pusher, solid) = savesolid;
- Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents);
- if (trace.startsolid)
- {
- // still inside pusher, so it's really blocked
-
- // fail the move
- if (PRVM_serveredictvector(check, mins)[0] == PRVM_serveredictvector(check, maxs)[0])
- continue;
- if (PRVM_serveredictfloat(check, solid) == SOLID_NOT || PRVM_serveredictfloat(check, solid) == SOLID_TRIGGER)
- {
- // corpse
- PRVM_serveredictvector(check, mins)[0] = PRVM_serveredictvector(check, mins)[1] = 0;
- VectorCopy (PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs));
- continue;
- }
-
- VectorCopy (pushorig, PRVM_serveredictvector(pusher, origin));
- VectorCopy (pushang, PRVM_serveredictvector(pusher, angles));
- PRVM_serveredictfloat(pusher, ltime) = pushltime;
- SV_LinkEdict(pusher);
-
- // move back any entities we already moved
- for (i = 0;i < num_moved;i++)
- {
- prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]);
- VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin));
- VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles));
- SV_LinkEdict(ed);
- }
-
- // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
- if (PRVM_serveredictfunction(pusher, blocked))
- {
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(pusher);
- PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(check);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(pusher, blocked), "QC function self.blocked is missing");
- }
- break;
- }
+ // we could fix it
+ continue;
+ }
+
+ // still inside pusher, so it's really blocked
+
+ // fail the move
+ if (PRVM_serveredictvector(check, mins)[0] == PRVM_serveredictvector(check, maxs)[0])
+ continue;
+ if (PRVM_serveredictfloat(check, solid) == SOLID_NOT || PRVM_serveredictfloat(check, solid) == SOLID_TRIGGER)
+ {
+ // corpse
+ PRVM_serveredictvector(check, mins)[0] = PRVM_serveredictvector(check, mins)[1] = 0;
+ VectorCopy (PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs));
+ continue;
+ }
+
+ VectorCopy (pushorig, PRVM_serveredictvector(pusher, origin));
+ VectorCopy (pushang, PRVM_serveredictvector(pusher, angles));
+ PRVM_serveredictfloat(pusher, ltime) = pushltime;
+ SV_LinkEdict(pusher);
+
+ // move back any entities we already moved
+ for (i = 0;i < num_moved;i++)
+ {
+ prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]);
+ VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin));
+ VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles));
+ SV_LinkEdict(ed);
+ }
+
+ // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone
+ if (PRVM_serveredictfunction(pusher, blocked))
+ {
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(pusher);
+ PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(check);
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(pusher, blocked), "QC function self.blocked is missing");
}
+ break;
}
}
PRVM_serveredictvector(pusher, angles)[0] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[0] * (1.0 / 360.0));
================
*/
-void SV_Physics_Pusher (prvm_edict_t *ent)
+static void SV_Physics_Pusher (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
float thinktime, oldltime, movetime;
oldltime = PRVM_serveredictfloat(ent, ltime);
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
- PRVM_ExecuteProgram (PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, think), "QC function self.think is missing");
}
}
}
unstickresult_t;
-unstickresult_t SV_UnstickEntityReturnOffset (prvm_edict_t *ent, vec3_t offset)
+static unstickresult_t SV_UnstickEntityReturnOffset (prvm_edict_t *ent, vec3_t offset)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, maxunstick;
// if not stuck in a bmodel, just return
qboolean SV_UnstickEntity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t offset;
switch(SV_UnstickEntityReturnOffset(ent, offset))
{
case UNSTICK_GOOD:
return true;
case UNSTICK_UNSTUCK:
- Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
+ Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
return true;
case UNSTICK_STUCK:
if (developer_extra.integer)
- Con_DPrintf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_DPrintf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
return false;
default:
Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n");
clipping hull.
=============
*/
-void SV_CheckStuck (prvm_edict_t *ent)
+static void SV_CheckStuck (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t offset;
switch(SV_UnstickEntityReturnOffset(ent, offset))
VectorCopy (PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, oldorigin));
break;
case UNSTICK_UNSTUCK:
- Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
+ Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]);
break;
case UNSTICK_STUCK:
VectorSubtract(PRVM_serveredictvector(ent, oldorigin), PRVM_serveredictvector(ent, origin), offset);
if (!SV_TestEntityPosition(ent, offset))
{
- Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
SV_LinkEdict(ent);
//SV_LinkEdict_TouchAreaGrid(ent);
}
else
- Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(PRVM_serveredictstring(ent, classname)));
+ Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)));
break;
default:
Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n");
SV_CheckWater
=============
*/
-qboolean SV_CheckWater (prvm_edict_t *ent)
+static qboolean SV_CheckWater (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int cont;
int nNativeContents;
vec3_t point;
============
*/
-void SV_WallFriction (prvm_edict_t *ent, float *stepnormal)
+static void SV_WallFriction (prvm_edict_t *ent, float *stepnormal)
{
+ prvm_prog_t *prog = SVVM_prog;
float d, i;
vec3_t forward, into, side;
Only used by players
======================
*/
-void SV_WalkMove (prvm_edict_t *ent)
+static void SV_WalkMove (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int clip;
int oldonground;
//int originalmove_clip;
if (sv.frametime <= 0)
return;
- SV_CheckStuck (ent);
+ if (sv_gameplayfix_unstickplayers.integer)
+ SV_CheckStuck (ent);
applygravity = !SV_CheckWater (ent) && PRVM_serveredictfloat(ent, movetype) == MOVETYPE_WALK && ! ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP);
VectorSet(downmove, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2] - 1);
if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLYMISSILE)
type = MOVE_MISSILE;
+ else if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY)
+ type = MOVE_WORLDONLY;
else if (PRVM_serveredictfloat(ent, solid) == SOLID_TRIGGER || PRVM_serveredictfloat(ent, solid) == SOLID_NOT)
type = MOVE_NOMONSTERS; // only clip against bmodels
else
Entities that are "stuck" to another entity
=============
*/
-void SV_Physics_Follow (prvm_edict_t *ent)
+static void SV_Physics_Follow (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t vf, vr, vu, angles, v;
prvm_edict_t *e;
=============
*/
-void SV_CheckWaterTransition (prvm_edict_t *ent)
+static void SV_CheckWaterTransition (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
+ // LordHavoc: bugfixes in this function are keyed to the sv_gameplayfix_bugfixedcheckwatertransition cvar - if this cvar is 0 then all the original bugs should be reenabled for compatibility
int cont;
cont = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_serveredictvector(ent, origin)));
if (!PRVM_serveredictfloat(ent, watertype))
{
// just spawned here
- PRVM_serveredictfloat(ent, watertype) = cont;
- PRVM_serveredictfloat(ent, waterlevel) = 1;
- return;
+ if (!sv_gameplayfix_fixedcheckwatertransition.integer)
+ {
+ PRVM_serveredictfloat(ent, watertype) = cont;
+ PRVM_serveredictfloat(ent, waterlevel) = 1;
+ return;
+ }
}
-
// DRESK - Support for Entity Contents Transition Event
// NOTE: Call here BEFORE updating the watertype below,
// and suppress watersplash sound if a valid function
// call was made to allow for custom "splash" sounds.
- if( !SV_CheckContentsTransition(ent, cont) )
+ else if( !SV_CheckContentsTransition(ent, cont) )
{ // Contents Transition Function Invalid; Potentially Play Water Sound
// check if the entity crossed into or out of water
if (sv_sound_watersplash.string && ((PRVM_serveredictfloat(ent, watertype) == CONTENTS_WATER || PRVM_serveredictfloat(ent, watertype) == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME)))
- SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, false);
+ SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, false, 1.0f);
}
if (cont <= CONTENTS_WATER)
else
{
PRVM_serveredictfloat(ent, watertype) = CONTENTS_EMPTY;
- PRVM_serveredictfloat(ent, waterlevel) = 0;
+ PRVM_serveredictfloat(ent, waterlevel) = sv_gameplayfix_fixedcheckwatertransition.integer ? 0 : cont;
}
}
Toss, bounce, and fly movement. When onground, do nothing.
=============
*/
+
void SV_Physics_Toss (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
trace_t trace;
vec3_t move;
vec_t movetime;
int bump;
prvm_edict_t *groundentity;
+ float d, ent_gravity;
+ float bouncefactor;
+ float bouncestop;
// if onground, return without moving
if ((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND)
for (bump = 0;bump < MAX_CLIP_PLANES && movetime > 0;bump++)
{
// move origin
- VectorScale (PRVM_serveredictvector(ent, velocity), movetime, move);
- if(!SV_PushEntity (&trace, ent, move, true, true))
+ VectorScale(PRVM_serveredictvector(ent, velocity), movetime, move);
+ if(!SV_PushEntity(&trace, ent, move, true, true))
return; // teleported
if (ent->priv.server->free)
return;
if (trace.bmodelstartsolid)
{
// try to unstick the entity
- SV_UnstickEntity(ent);
- if(!SV_PushEntity (&trace, ent, move, false, true))
+ if (sv_gameplayfix_unstickentities.integer)
+ SV_UnstickEntity(ent);
+ if(!SV_PushEntity(&trace, ent, move, false, true))
return; // teleported
if (ent->priv.server->free)
return;
if (trace.fraction == 1)
break;
movetime *= 1 - min(1, trace.fraction);
- if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_BOUNCEMISSILE)
+ switch((int)PRVM_serveredictfloat(ent, movetype))
{
- float bouncefactor;
+ case MOVETYPE_BOUNCEMISSILE:
bouncefactor = PRVM_serveredictfloat(ent, bouncefactor);
if (!bouncefactor)
bouncefactor = 1.0f;
- ClipVelocity (PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
+ ClipVelocity(PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
- }
- else if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_BOUNCE)
- {
- float d, ent_gravity;
- float bouncefactor;
- float bouncestop;
-
+ if (!sv_gameplayfix_slidemoveprojectiles.integer)
+ movetime = 0;
+ break;
+ case MOVETYPE_BOUNCE:
bouncefactor = PRVM_serveredictfloat(ent, bouncefactor);
if (!bouncefactor)
bouncefactor = 0.5f;
if (!bouncestop)
bouncestop = 60.0f / 800.0f;
- ClipVelocity (PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
+ ClipVelocity(PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1 + bouncefactor);
ent_gravity = PRVM_serveredictfloat(ent, gravity);
if (!ent_gravity)
ent_gravity = 1.0f;
// LordHavoc: fixed grenades not bouncing when fired down a slope
if (sv_gameplayfix_grenadebouncedownslopes.integer)
+ d = fabs(DotProduct(trace.plane.normal, PRVM_serveredictvector(ent, velocity)));
+ else
+ d = PRVM_serveredictvector(ent, velocity)[2];
+ if (trace.plane.normal[2] > 0.7 && d < sv_gravity.value * bouncestop * ent_gravity)
{
- d = DotProduct(trace.plane.normal, PRVM_serveredictvector(ent, velocity));
- if (trace.plane.normal[2] > 0.7 && fabs(d) < sv_gravity.value * bouncestop * ent_gravity)
- {
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
- PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
- VectorClear (PRVM_serveredictvector(ent, velocity));
- VectorClear (PRVM_serveredictvector(ent, avelocity));
- }
- else
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
+ PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
+ PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
+ VectorClear(PRVM_serveredictvector(ent, velocity));
+ VectorClear(PRVM_serveredictvector(ent, avelocity));
+ movetime = 0;
}
else
{
- if (trace.plane.normal[2] > 0.7 && PRVM_serveredictvector(ent, velocity)[2] < sv_gravity.value * bouncestop * ent_gravity)
- {
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
- PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
- VectorClear (PRVM_serveredictvector(ent, velocity));
- VectorClear (PRVM_serveredictvector(ent, avelocity));
- }
- else
- PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
+ PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
+ if (!sv_gameplayfix_slidemoveprojectiles.integer)
+ movetime = 0;
}
- }
- else
- {
+ break;
+ default:
ClipVelocity (PRVM_serveredictvector(ent, velocity), trace.plane.normal, PRVM_serveredictvector(ent, velocity), 1.0);
if (trace.plane.normal[2] > 0.7)
{
}
else
PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
- }
- if (!sv_gameplayfix_slidemoveprojectiles.integer || (PRVM_serveredictfloat(ent, movetype) != MOVETYPE_BOUNCE && PRVM_serveredictfloat(ent, movetype) == MOVETYPE_BOUNCEMISSILE) || ((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND))
+ movetime = 0;
break;
+ }
}
// check for in water
will fall if the floor is pulled out from under them.
=============
*/
-void SV_Physics_Step (prvm_edict_t *ent)
+static void SV_Physics_Step (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
int flags = (int)PRVM_serveredictfloat(ent, flags);
// DRESK
if(PRVM_serveredictfunction(ent, movetypesteplandevent))
{ // Valid Function; Execute
// Prepare Parameters
- // Assign Velocity at Impact
- PRVM_G_VECTOR(OFS_PARM0)[0] = backupVelocity[0];
- PRVM_G_VECTOR(OFS_PARM0)[1] = backupVelocity[1];
- PRVM_G_VECTOR(OFS_PARM0)[2] = backupVelocity[2];
- // Assign Self
- PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // Assign Velocity at Impact
+ PRVM_G_VECTOR(OFS_PARM0)[0] = backupVelocity[0];
+ PRVM_G_VECTOR(OFS_PARM0)[1] = backupVelocity[1];
+ PRVM_G_VECTOR(OFS_PARM0)[2] = backupVelocity[2];
+ // Assign Self
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
+ // Set Time
+ PRVM_serverglobalfloat(time) = sv.time;
// Execute VM Function
- PRVM_ExecuteProgram(PRVM_serveredictfunction(ent, movetypesteplandevent), "movetypesteplandevent: NULL function");
+ prog->ExecuteProgram(prog, PRVM_serveredictfunction(ent, movetypesteplandevent), "movetypesteplandevent: NULL function");
}
else
// Check for Engine Landing Sound
if(sv_sound_land.string)
- SV_StartSound(ent, 0, sv_sound_land.string, 255, 1, false);
+ SV_StartSound(ent, 0, sv_sound_land.string, 255, 1, false, 1.0f);
}
ent->priv.server->waterposition_forceupdate = true;
}
static void SV_Physics_Entity (prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// don't run think/move on newly spawned projectiles as it messes up
// movement interpolation and rocket trails, and is inconsistent with
// respect to entities spawned in the same frame
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
// regular thinking
if (SV_RunThink (ent))
SV_Physics_Toss (ent);
void SV_Physics_ClientMove(void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *ent;
ent = host_client->edict;
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(frametime) = 0;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
PRVM_serverglobalfloat(frametime) = sv.frametime;
// make sure the velocity is sane (not a NaN)
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(frametime) = 0;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
PRVM_serverglobalfloat(frametime) = sv.frametime;
if(PRVM_serveredictfloat(ent, fixangle))
static void SV_Physics_ClientEntity_PreThink(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
if (!host_client->spawned)
return;
// call standard client pre-think
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram(PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPreThink), "QC function PlayerPreThink is missing");
// make sure the velocity is still sane (not a NaN)
SV_CheckVelocity(ent);
static void SV_Physics_ClientEntity_PostThink(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
if (!host_client->spawned)
return;
// call standard player post-think
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram(PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PlayerPostThink), "QC function PlayerPostThink is missing");
// make sure the velocity is still sane (not a NaN)
SV_CheckVelocity(ent);
static void SV_Physics_ClientEntity(prvm_edict_t *ent)
{
+ prvm_prog_t *prog = SVVM_prog;
// don't do physics on disconnected clients, FrikBot relies on this
if (!host_client->spawned)
{
SV_Physics_Toss (ent);
break;
case MOVETYPE_FLY:
+ case MOVETYPE_FLY_WORLDONLY:
SV_RunThink (ent);
SV_WalkMove (ent);
break;
*/
void SV_Physics (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
prvm_edict_t *ent;
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobalfloat(frametime) = sv.frametime;
- PRVM_ExecuteProgram (PRVM_serverfunction(StartFrame), "QC function StartFrame is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(StartFrame), "QC function StartFrame is missing");
// run physics engine
World_Physics_Frame(&sv.world, sv.frametime, sv_gravity.value);
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(prog->edicts);
PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(prog->edicts);
PRVM_serverglobalfloat(time) = sv.time;
- PRVM_ExecuteProgram (PRVM_serverfunction(EndFrame), "QC function EndFrame is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(EndFrame), "QC function EndFrame is missing");
}
// decrement prog->num_edicts if the highest number entities died
- for (;PRVM_ED_CanAlloc(PRVM_EDICT_NUM(prog->num_edicts - 1));prog->num_edicts--);
+ for (;PRVM_ED_CanAlloc(prog, PRVM_EDICT_NUM(prog->num_edicts - 1));prog->num_edicts--);
if (!sv_freezenonclients.integer)
sv.time += sv.frametime;
#define MAX_FORWARD 6
void SV_SetIdealPitch (void)
{
+ prvm_prog_t *prog = SVVM_prog;
float angleval, sinval, cosval, step, dir;
trace_t tr;
vec3_t top, bottom;
==================
*/
-void SV_UserFriction (void)
+static void SV_UserFriction (void)
{
+ prvm_prog_t *prog = SVVM_prog;
float speed, newspeed, control, friction;
vec3_t start, stop;
trace_t trace;
SV_Accelerate
==============
*/
-void SV_Accelerate (void)
+static void SV_Accelerate (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
float addspeed, accelspeed, currentspeed;
}
extern cvar_t sv_gameplayfix_q2airaccelerate;
-void SV_AirAccelerate (vec3_t wishveloc)
+static void SV_AirAccelerate (vec3_t wishveloc)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
float addspeed, wishspd, accelspeed, currentspeed;
}
-void DropPunchAngle (void)
+static void DropPunchAngle (void)
{
+ prvm_prog_t *prog = SVVM_prog;
float len;
vec3_t v;
VectorCopy(v, PRVM_serveredictvector(host_client->edict, punchvector));
}
-/*
-===================
-SV_FreeMove
-===================
-*/
-void SV_FreeMove (void)
-{
- int i;
- float wishspeed;
-
- AngleVectors (PRVM_serveredictvector(host_client->edict, v_angle), forward, right, up);
-
- for (i = 0; i < 3; i++)
- PRVM_serveredictvector(host_client->edict, velocity)[i] = forward[i] * cmd.forwardmove + right[i] * cmd.sidemove;
-
- PRVM_serveredictvector(host_client->edict, velocity)[2] += cmd.upmove;
-
- wishspeed = VectorLength(PRVM_serveredictvector(host_client->edict, velocity));
- if (wishspeed > sv_maxspeed.value)
- VectorScale(PRVM_serveredictvector(host_client->edict, velocity), sv_maxspeed.value / wishspeed, PRVM_serveredictvector(host_client->edict, velocity));
-}
-
/*
===================
SV_WaterMove
===================
*/
-void SV_WaterMove (void)
+static void SV_WaterMove (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
vec3_t wishvel;
float speed, newspeed, wishspeed, addspeed, accelspeed, temp;
PRVM_serveredictvector(host_client->edict, velocity)[i] += accelspeed * wishvel[i];
}
-void SV_WaterJump (void)
+static void SV_WaterJump (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (sv.time > PRVM_serveredictfloat(host_client->edict, teleport_time) || !PRVM_serveredictfloat(host_client->edict, waterlevel))
{
PRVM_serveredictfloat(host_client->edict, flags) = (int)PRVM_serveredictfloat(host_client->edict, flags) & ~FL_WATERJUMP;
===================
*/
-void SV_AirMove (void)
+static void SV_AirMove (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
vec3_t wishvel;
float fmove, smove, temp;
*/
void SV_ClientThink (void)
{
+ prvm_prog_t *prog = SVVM_prog;
vec3_t v_angle;
//Con_Printf("clientthink for %ims\n", (int) (sv.frametime * 1000));
{
PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (PRVM_serverfunction(SV_PlayerPhysics), "QC function SV_PlayerPhysics is missing");
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PlayerPhysics), "QC function SV_PlayerPhysics is missing");
SV_CheckVelocity(host_client->edict);
return;
}
*/
int sv_numreadmoves = 0;
usercmd_t sv_readmoves[CL_MAX_USERCMDS];
-void SV_ReadClientMove (void)
+static void SV_ReadClientMove (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
usercmd_t newmove;
usercmd_t *move = &newmove;
memset(move, 0, sizeof(*move));
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// read ping time
if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6)
- move->sequence = MSG_ReadLong ();
- move->time = move->clienttime = MSG_ReadFloat ();
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ move->sequence = MSG_ReadLong(&sv_message);
+ move->time = move->clienttime = MSG_ReadFloat(&sv_message);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
move->receivetime = (float)sv.time;
#if DEBUGMOVES
for (i = 0;i < 3;i++)
{
if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
- move->viewangles[i] = MSG_ReadAngle8i();
+ move->viewangles[i] = MSG_ReadAngle8i(&sv_message);
else if (sv.protocol == PROTOCOL_DARKPLACES1)
- move->viewangles[i] = MSG_ReadAngle16i();
+ move->viewangles[i] = MSG_ReadAngle16i(&sv_message);
else if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
- move->viewangles[i] = MSG_ReadAngle32f();
+ move->viewangles[i] = MSG_ReadAngle32f(&sv_message);
else
- move->viewangles[i] = MSG_ReadAngle16i();
+ move->viewangles[i] = MSG_ReadAngle16i(&sv_message);
}
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// read movement
- move->forwardmove = MSG_ReadCoord16i ();
- move->sidemove = MSG_ReadCoord16i ();
- move->upmove = MSG_ReadCoord16i ();
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ move->forwardmove = MSG_ReadCoord16i(&sv_message);
+ move->sidemove = MSG_ReadCoord16i(&sv_message);
+ move->upmove = MSG_ReadCoord16i(&sv_message);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// read buttons
// be sure to bitwise OR them into the move->buttons because we want to
// accumulate button presses from multiple packets per actual move
if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
- move->buttons = MSG_ReadByte ();
+ move->buttons = MSG_ReadByte(&sv_message);
else
- move->buttons = MSG_ReadLong ();
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ move->buttons = MSG_ReadLong(&sv_message);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// read impulse
- move->impulse = MSG_ReadByte ();
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ move->impulse = MSG_ReadByte(&sv_message);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// PRYDON_CLIENTCURSOR
if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5)
{
// 30 bytes
- move->cursor_screen[0] = MSG_ReadShort() * (1.0f / 32767.0f);
- move->cursor_screen[1] = MSG_ReadShort() * (1.0f / 32767.0f);
- move->cursor_start[0] = MSG_ReadFloat();
- move->cursor_start[1] = MSG_ReadFloat();
- move->cursor_start[2] = MSG_ReadFloat();
- move->cursor_impact[0] = MSG_ReadFloat();
- move->cursor_impact[1] = MSG_ReadFloat();
- move->cursor_impact[2] = MSG_ReadFloat();
- move->cursor_entitynumber = (unsigned short)MSG_ReadShort();
+ move->cursor_screen[0] = MSG_ReadShort(&sv_message) * (1.0f / 32767.0f);
+ move->cursor_screen[1] = MSG_ReadShort(&sv_message) * (1.0f / 32767.0f);
+ move->cursor_start[0] = MSG_ReadFloat(&sv_message);
+ move->cursor_start[1] = MSG_ReadFloat(&sv_message);
+ move->cursor_start[2] = MSG_ReadFloat(&sv_message);
+ move->cursor_impact[0] = MSG_ReadFloat(&sv_message);
+ move->cursor_impact[1] = MSG_ReadFloat(&sv_message);
+ move->cursor_impact[2] = MSG_ReadFloat(&sv_message);
+ move->cursor_entitynumber = (unsigned short)MSG_ReadShort(&sv_message);
if (move->cursor_entitynumber >= prog->max_edicts)
{
Con_DPrintf("SV_ReadClientMessage: client send bad cursor_entitynumber\n");
// entity is free at time of receipt
if (PRVM_EDICT_NUM(move->cursor_entitynumber)->priv.server->free)
move->cursor_entitynumber = 0;
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
}
// if the previous move has not been applied yet, we need to accumulate
}
}
-void SV_ExecuteClientMoves(void)
+static void SV_ExecuteClientMoves(void)
{
+ prvm_prog_t *prog = SVVM_prog;
int moveindex;
float moveframetime;
double oldframetime;
void SV_ApplyClientMove (void)
{
+ prvm_prog_t *prog = SVVM_prog;
usercmd_t *move = &host_client->cmd;
int j, movementloss, packetloss;
PRVM_serveredictfloat(host_client->edict, ping_movementloss) = movementloss / (float) NETGRAPH_PACKETS;
}
-void SV_FrameLost(int framenum)
+static void SV_FrameLost(int framenum)
{
if (host_client->entitydatabase5)
{
}
}
-void SV_FrameAck(int framenum)
+static void SV_FrameAck(int framenum)
{
if (host_client->entitydatabase)
EntityFrame_AckFrame(host_client->entitydatabase, framenum);
SV_ReadClientMessage
===================
*/
-extern void SV_SendServerinfo(client_t *client);
-extern sizebuf_t vm_tempstringsbuf;
void SV_ReadClientMessage(void)
{
+ prvm_prog_t *prog = SVVM_prog;
int cmd, num, start;
char *s, *p, *q;
return;
}
- if (msg_badread)
+ if (sv_message.badread)
{
Con_Print("SV_ReadClientMessage: badread\n");
SV_DropClient (false);
return;
}
- cmd = MSG_ReadByte ();
+ cmd = MSG_ReadByte(&sv_message);
if (cmd == -1)
{
// end of message
switch (cmd)
{
default:
- Con_Printf("SV_ReadClientMessage: unknown command char %i (at offset 0x%x)\n", cmd, msg_readcount);
+ Con_Printf("SV_ReadClientMessage: unknown command char %i (at offset 0x%x)\n", cmd, sv_message.readcount);
if (developer_networking.integer)
- Com_HexDumpToConsole(net_message.data, net_message.cursize);
+ Com_HexDumpToConsole(sv_message.data, sv_message.cursize);
SV_DropClient (false);
return;
// allow reliable messages now as the client is done with initial loading
if (host_client->sendsignon == 2)
host_client->sendsignon = 0;
- s = MSG_ReadString ();
+ s = MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring));
q = NULL;
for(p = s; *p; ++p) switch(*p)
{
if (strncasecmp(s, "spawn", 5) == 0
|| strncasecmp(s, "begin", 5) == 0
|| strncasecmp(s, "prespawn", 8) == 0)
- Cmd_ExecuteString (s, src_client);
+ Cmd_ExecuteString (s, src_client, true);
else if (PRVM_serverfunction(SV_ParseClientCommand))
{
int restorevm_tempstringsbuf_cursize;
- restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
- PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(s);
+ restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
+ PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s);
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (PRVM_serverfunction(SV_ParseClientCommand), "QC function SV_ParseClientCommand is missing");
- vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ParseClientCommand), "QC function SV_ParseClientCommand is missing");
+ prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
}
else
- Cmd_ExecuteString (s, src_client);
+ Cmd_ExecuteString (s, src_client, true);
break;
clc_stringcmd_invalid:
break;
case clc_ackdownloaddata:
- start = MSG_ReadLong();
- num = MSG_ReadShort();
+ start = MSG_ReadLong(&sv_message);
+ num = MSG_ReadShort(&sv_message);
if (host_client->download_file && host_client->download_started)
{
if (host_client->download_expectedposition == start)
break;
case clc_ackframe:
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
- num = MSG_ReadLong();
- if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
+ num = MSG_ReadLong(&sv_message);
+ if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
if (developer_networkentities.integer >= 10)
Con_Printf("recv clc_ackframe %i\n", num);
// if the client hasn't progressed through signons yet,
"DP_CON_STARTMAP "
"DP_CRYPTO "
"DP_CSQC_BINDMAPS "
-"DP_CSQC_ENTITYNOCULL "
+"DP_CSQC_ENTITYWORLDOBJECT "
+"DP_CSQC_ENTITYMODELLIGHT "
"DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
+"DP_CSQC_MAINVIEW "
"DP_CSQC_MULTIFRAME_INTERPOLATION "
"DP_CSQC_BOXPARTICLES "
"DP_CSQC_SPAWNPARTICLE "
"DP_ENT_SCALE "
"DP_ENT_TRAILEFFECTNUM "
"DP_ENT_VIEWMODEL "
-"DP_GECKO_SUPPORT "
"DP_GFX_EXTERNALTEXTURES "
"DP_GFX_EXTERNALTEXTURES_PERMAP "
"DP_GFX_FOG "
"DP_LITSUPPORT "
"DP_MONSTERWALK "
"DP_MOVETYPEBOUNCEMISSILE "
+"DP_MOVETYPEFLYWORLDONLY "
"DP_MOVETYPEFOLLOW "
"DP_NULL_MODEL "
"DP_QC_ASINACOSATANATAN2TAN "
"DP_QC_CVAR_DESCRIPTION "
"DP_QC_CVAR_STRING "
"DP_QC_CVAR_TYPE "
+"DP_QC_DIGEST "
+"DP_QC_DIGEST_SHA256 "
"DP_QC_EDICT_NUM "
"DP_QC_ENTITYDATA "
"DP_QC_ENTITYSTRING "
"DP_QC_GETTAGINFO_BONEPROPERTIES "
"DP_QC_GETTIME "
"DP_QC_GETTIME_CDTRACK "
+"DP_QC_I18N "
"DP_QC_LOG "
"DP_QC_MINMAXBOUND "
"DP_QC_MULTIPLETEMPSTRINGS "
"DP_SND_DIRECTIONLESSATTNNONE "
"DP_SND_FAKETRACKS "
"DP_SND_SOUND7_WIP1 "
+"DP_SND_SOUND7_WIP2 "
"DP_SND_OGGVORBIS "
"DP_SND_SETPARAMS "
"DP_SND_STEREOWAV "
setorigin (entity, origin)
=================
*/
-static void VM_SV_setorigin (void)
+static void VM_SV_setorigin(prvm_prog_t *prog)
{
prvm_edict_t *e;
float *org;
e = PRVM_G_EDICT(OFS_PARM0);
if (e == prog->edicts)
{
- VM_Warning("setorigin: can not modify world entity\n");
+ VM_Warning(prog, "setorigin: can not modify world entity\n");
return;
}
if (e->priv.server->free)
{
- VM_Warning("setorigin: can not modify free entity\n");
+ VM_Warning(prog, "setorigin: can not modify free entity\n");
return;
}
org = PRVM_G_VECTOR(OFS_PARM1);
VectorCopy (org, PRVM_serveredictvector(e, origin));
+ if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
+ e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
SV_LinkEdict(e);
}
// TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
-static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
+static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qboolean rotate)
{
int i;
for (i=0 ; i<3 ; i++)
if (min[i] > max[i])
- PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
+ prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
// set derived values
VectorCopy (min, PRVM_serveredictvector(e, mins));
setsize (entity, minvector, maxvector)
=================
*/
-static void VM_SV_setsize (void)
+static void VM_SV_setsize(prvm_prog_t *prog)
{
prvm_edict_t *e;
float *min, *max;
e = PRVM_G_EDICT(OFS_PARM0);
if (e == prog->edicts)
{
- VM_Warning("setsize: can not modify world entity\n");
+ VM_Warning(prog, "setsize: can not modify world entity\n");
return;
}
if (e->priv.server->free)
{
- VM_Warning("setsize: can not modify free entity\n");
+ VM_Warning(prog, "setsize: can not modify free entity\n");
return;
}
min = PRVM_G_VECTOR(OFS_PARM1);
max = PRVM_G_VECTOR(OFS_PARM2);
- SetMinMaxSize (e, min, max, false);
+ SetMinMaxSize(prog, e, min, max, false);
}
=================
*/
static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
-static void VM_SV_setmodel (void)
+static void VM_SV_setmodel(prvm_prog_t *prog)
{
prvm_edict_t *e;
dp_model_t *mod;
e = PRVM_G_EDICT(OFS_PARM0);
if (e == prog->edicts)
{
- VM_Warning("setmodel: can not modify world entity\n");
+ VM_Warning(prog, "setmodel: can not modify world entity\n");
return;
}
if (e->priv.server->free)
{
- VM_Warning("setmodel: can not modify free entity\n");
+ VM_Warning(prog, "setmodel: can not modify free entity\n");
return;
}
i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
- PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
+ PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
PRVM_serveredictfloat(e, modelindex) = i;
mod = SV_GetModelByIndex(i);
if (mod)
{
if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
- SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
+ SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
else
- SetMinMaxSize (e, quakemins, quakemaxs, true);
+ SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
}
else
- SetMinMaxSize (e, vec3_origin, vec3_origin, true);
+ SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
}
/*
sprint(clientent, value)
=================
*/
-static void VM_SV_sprint (void)
+static void VM_SV_sprint(prvm_prog_t *prog)
{
client_t *client;
int entnum;
char string[VM_STRINGTEMP_LENGTH];
- VM_VarString(1, string, sizeof(string));
-
VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
+ VM_VarString(prog, 1, string, sizeof(string));
+
entnum = PRVM_G_EDICTNUM(OFS_PARM0);
// LordHavoc: div0 requested that sprintto world operate like print
if (entnum == 0)
if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
{
- VM_Warning("tried to centerprint to a non-client\n");
+ VM_Warning(prog, "tried to centerprint to a non-client\n");
return;
}
centerprint(clientent, value)
=================
*/
-static void VM_SV_centerprint (void)
+static void VM_SV_centerprint(prvm_prog_t *prog)
{
client_t *client;
int entnum;
if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
{
- VM_Warning("tried to centerprint to a non-client\n");
+ VM_Warning(prog, "tried to centerprint to a non-client\n");
return;
}
if (!client->netconnection)
return;
- VM_VarString(1, string, sizeof(string));
+ VM_VarString(prog, 1, string, sizeof(string));
MSG_WriteChar(&client->netconnection->message,svc_centerprint);
MSG_WriteString(&client->netconnection->message, string);
}
particle(origin, color, count)
=================
*/
-static void VM_SV_particle (void)
+static void VM_SV_particle(prvm_prog_t *prog)
{
float *org, *dir;
float color;
=================
*/
-static void VM_SV_ambientsound (void)
+static void VM_SV_ambientsound(prvm_prog_t *prog)
{
const char *samp;
float *pos;
=================
*/
-static void VM_SV_sound (void)
+static void VM_SV_sound(prvm_prog_t *prog)
{
const char *sample;
int channel;
if (prog->argc < 6)
pitchchange = 0;
else
- pitchchange = PRVM_G_FLOAT(OFS_PARM5);
+ pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
if (prog->argc < 7)
{
if (volume < 0 || volume > 255)
{
- VM_Warning("SV_StartSound: volume must be in range 0-1\n");
+ VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
return;
}
if (attenuation < 0 || attenuation > 4)
{
- VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
+ VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
return;
}
if (!IS_CHAN(channel))
{
- VM_Warning("SV_StartSound: channel must be in range 0-127\n");
+ VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
return;
}
- SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE);
+ SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANFLAG_RELIABLE, pitchchange);
}
/*
=================
*/
-static void VM_SV_pointsound(void)
+static void VM_SV_pointsound(prvm_prog_t *prog)
{
const char *sample;
int volume;
float attenuation;
+ float pitchchange;
vec3_t org;
- VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
+ VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
sample = PRVM_G_STRING(OFS_PARM1);
volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
attenuation = PRVM_G_FLOAT(OFS_PARM3);
+ pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
if (volume < 0 || volume > 255)
{
- VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
+ VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
return;
}
if (attenuation < 0 || attenuation > 4)
{
- VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
+ VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
return;
}
- SV_StartPointSound (org, sample, volume, attenuation);
+ SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
}
/*
traceline (vector1, vector2, movetype, ignore)
=================
*/
-static void VM_SV_traceline (void)
+static void VM_SV_traceline(prvm_prog_t *prog)
{
float *v1, *v2;
trace_t trace;
ent = PRVM_G_EDICT(OFS_PARM3);
if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
- PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
+ prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
- VM_SetTraceGlobals(&trace);
+ VM_SetTraceGlobals(prog, &trace);
}
=================
*/
// LordHavoc: added this for my own use, VERY useful, similar to traceline
-static void VM_SV_tracebox (void)
+static void VM_SV_tracebox(prvm_prog_t *prog)
{
float *v1, *v2, *m1, *m2;
trace_t trace;
ent = PRVM_G_EDICT(OFS_PARM5);
if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
- PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
+ prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
- VM_SetTraceGlobals(&trace);
+ VM_SetTraceGlobals(prog, &trace);
}
-static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
+static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
{
int i;
float gravity;
return trace;
}
-static void VM_SV_tracetoss (void)
+static void VM_SV_tracetoss(prvm_prog_t *prog)
{
trace_t trace;
prvm_edict_t *ent;
ent = PRVM_G_EDICT(OFS_PARM0);
if (ent == prog->edicts)
{
- VM_Warning("tracetoss: can not use world entity\n");
+ VM_Warning(prog, "tracetoss: can not use world entity\n");
return;
}
ignore = PRVM_G_EDICT(OFS_PARM1);
- trace = SV_Trace_Toss (ent, ignore);
+ trace = SV_Trace_Toss(prog, ent, ignore);
- VM_SetTraceGlobals(&trace);
+ VM_SetTraceGlobals(prog, &trace);
}
//============================================================================
static int checkpvsbytes;
static unsigned char checkpvs[MAX_MAP_LEAFS/8];
-static int VM_SV_newcheckclient (int check)
+static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
{
int i;
prvm_edict_t *ent;
=================
*/
int c_invis, c_notvis;
-static void VM_SV_checkclient (void)
+static void VM_SV_checkclient(prvm_prog_t *prog)
{
prvm_edict_t *ent, *self;
vec3_t view;
// find a new check if on a new frame
if (sv.time - sv.lastchecktime >= 0.1)
{
- sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
+ sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
sv.lastchecktime = sv.time;
}
float checkpvs(vector viewpos, entity viewee) = #240;
=================
*/
-static void VM_SV_checkpvs (void)
+static void VM_SV_checkpvs(prvm_prog_t *prog)
{
vec3_t viewpos;
prvm_edict_t *viewee;
if(viewee->priv.server->free)
{
- VM_Warning("checkpvs: can not check free entity\n");
+ VM_Warning(prog, "checkpvs: can not check free entity\n");
PRVM_G_FLOAT(OFS_RETURN) = 4;
return;
}
stuffcmd (clientent, value, ...)
=================
*/
-static void VM_SV_stuffcmd (void)
+static void VM_SV_stuffcmd(prvm_prog_t *prog)
{
int entnum;
client_t *old;
entnum = PRVM_G_EDICTNUM(OFS_PARM0);
if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
{
- VM_Warning("Can't stuffcmd to a non-client\n");
+ VM_Warning(prog, "Can't stuffcmd to a non-client\n");
return;
}
- VM_VarString(1, string, sizeof(string));
+ VM_VarString(prog, 1, string, sizeof(string));
old = host_client;
host_client = svs.clients + entnum-1;
findradius (origin, radius)
=================
*/
-static void VM_SV_findradius (void)
+static void VM_SV_findradius(prvm_prog_t *prog)
{
prvm_edict_t *ent, *chain;
vec_t radius, radius2;
else
chainfield = prog->fieldoffsets.chain;
if (chainfield < 0)
- PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
+ prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
chain = (prvm_edict_t *)prog->edicts;
maxs[0] = org[0] + (radius + 1);
maxs[1] = org[1] + (radius + 1);
maxs[2] = org[2] + (radius + 1);
- numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
+ numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
if (numtouchedicts > MAX_EDICTS)
{
// this never happens
VM_RETURN_EDICT(chain);
}
-static void VM_SV_precache_sound (void)
+static void VM_SV_precache_sound(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
}
-static void VM_SV_precache_model (void)
+static void VM_SV_precache_model(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
float(float yaw, float dist[, settrace]) walkmove
===============
*/
-static void VM_SV_walkmove (void)
+static void VM_SV_walkmove(prvm_prog_t *prog)
{
prvm_edict_t *ent;
float yaw, dist;
ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
if (ent == prog->edicts)
{
- VM_Warning("walkmove: can not modify world entity\n");
+ VM_Warning(prog, "walkmove: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("walkmove: can not modify free entity\n");
+ VM_Warning(prog, "walkmove: can not modify free entity\n");
return;
}
yaw = PRVM_G_FLOAT(OFS_PARM0);
void() droptofloor
===============
*/
-static void VM_SV_droptofloor (void)
+
+static void VM_SV_droptofloor(prvm_prog_t *prog)
{
prvm_edict_t *ent;
vec3_t end;
ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
if (ent == prog->edicts)
{
- VM_Warning("droptofloor: can not modify world entity\n");
+ VM_Warning(prog, "droptofloor: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("droptofloor: can not modify free entity\n");
+ VM_Warning(prog, "droptofloor: can not modify free entity\n");
return;
}
end[2] -= 256;
if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
- SV_UnstickEntity(ent);
+ if (sv_gameplayfix_unstickentities.integer)
+ SV_UnstickEntity(ent);
trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
if (trace.startsolid)
{
Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
- SV_UnstickEntity(ent);
+ if (sv_gameplayfix_unstickentities.integer)
+ SV_UnstickEntity(ent);
SV_LinkEdict(ent);
PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
PRVM_serveredictedict(ent, groundentity) = 0;
{
Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
- SV_UnstickEntity(ent);
+ if (sv_gameplayfix_unstickentities.integer)
+ SV_UnstickEntity(ent);
SV_LinkEdict(ent);
PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
void(float style, string value) lightstyle
===============
*/
-static void VM_SV_lightstyle (void)
+static void VM_SV_lightstyle(prvm_prog_t *prog)
{
int style;
const char *val;
val = PRVM_G_STRING(OFS_PARM1);
if( (unsigned) style >= MAX_LIGHTSTYLES ) {
- PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
+ prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
}
// change the string in sv
VM_SV_checkbottom
=============
*/
-static void VM_SV_checkbottom (void)
+static void VM_SV_checkbottom(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
VM_SV_pointcontents
=============
*/
-static void VM_SV_pointcontents (void)
+static void VM_SV_pointcontents(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
vector aim(entity, missilespeed)
=============
*/
-static void VM_SV_aim (void)
+static void VM_SV_aim(prvm_prog_t *prog)
{
prvm_edict_t *ent, *check, *bestent;
vec3_t start, dir, end, bestdir;
ent = PRVM_G_EDICT(OFS_PARM0);
if (ent == prog->edicts)
{
- VM_Warning("aim: can not use world entity\n");
+ VM_Warning(prog, "aim: can not use world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("aim: can not use free entity\n");
+ VM_Warning(prog, "aim: can not use free entity\n");
return;
}
//speed = PRVM_G_FLOAT(OFS_PARM1);
#define MSG_INIT 3 // write to the init string
#define MSG_ENTITY 5
-sizebuf_t *WriteDest (void)
+static sizebuf_t *WriteDest(prvm_prog_t *prog)
{
int entnum;
int dest;
entnum = PRVM_NUM_FOR_EDICT(ent);
if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
{
- VM_Warning ("WriteDest: tried to write to non-client\n");
+ VM_Warning(prog, "WriteDest: tried to write to non-client\n");
return &sv.reliable_datagram;
}
else
return &svs.clients[entnum-1].netconnection->message;
default:
- VM_Warning ("WriteDest: bad destination\n");
+ VM_Warning(prog, "WriteDest: bad destination\n");
case MSG_ALL:
return &sv.reliable_datagram;
//return NULL;
}
-static void VM_SV_WriteByte (void)
+static void VM_SV_WriteByte(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
- MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
+ MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
}
-static void VM_SV_WriteChar (void)
+static void VM_SV_WriteChar(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
- MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
+ MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
}
-static void VM_SV_WriteShort (void)
+static void VM_SV_WriteShort(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
- MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
+ MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
}
-static void VM_SV_WriteLong (void)
+static void VM_SV_WriteLong(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
- MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
+ MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
}
-static void VM_SV_WriteAngle (void)
+static void VM_SV_WriteAngle(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
- MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
+ MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
}
-static void VM_SV_WriteCoord (void)
+static void VM_SV_WriteCoord(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
- MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
+ MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
}
-static void VM_SV_WriteString (void)
+static void VM_SV_WriteString(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
- MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
+ MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
}
-static void VM_SV_WriteUnterminatedString (void)
+static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
- MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
+ MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
}
-static void VM_SV_WriteEntity (void)
+static void VM_SV_WriteEntity(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
- MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
+ MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
}
// writes a picture as at most size bytes of data
// if failed to read/compress:
// IMGNAME \0 \0 \0
//#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
-static void VM_SV_WritePicture (void)
+static void VM_SV_WritePicture(prvm_prog_t *prog)
{
const char *imgname;
void *buf;
if(size > 65535)
size = 65535;
- MSG_WriteString(WriteDest(), imgname);
+ MSG_WriteString(WriteDest(prog), imgname);
if(Image_Compress(imgname, size, &buf, &size))
{
// actual picture
- MSG_WriteShort(WriteDest(), size);
- SZ_Write(WriteDest(), (unsigned char *) buf, size);
+ MSG_WriteShort(WriteDest(prog), size);
+ SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
}
else
{
// placeholder
- MSG_WriteShort(WriteDest(), 0);
+ MSG_WriteShort(WriteDest(prog), 0);
}
}
//////////////////////////////////////////////////////////
-static void VM_SV_makestatic (void)
+static void VM_SV_makestatic(prvm_prog_t *prog)
{
prvm_edict_t *ent;
int i, large;
ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
if (ent == prog->edicts)
{
- VM_Warning("makestatic: can not modify world entity\n");
+ VM_Warning(prog, "makestatic: can not modify world entity\n");
return;
}
if (ent->priv.server->free)
{
- VM_Warning("makestatic: can not modify free entity\n");
+ VM_Warning(prog, "makestatic: can not modify free entity\n");
return;
}
}
// throw the entity away now
- PRVM_ED_Free (ent);
+ PRVM_ED_Free(prog, ent);
}
//=============================================================================
VM_SV_setspawnparms
==============
*/
-static void VM_SV_setspawnparms (void)
+static void VM_SV_setspawnparms(prvm_prog_t *prog)
{
prvm_edict_t *ent;
int i;
getlight(vector)
=================
*/
-static void VM_SV_getlight (void)
+static void VM_SV_getlight(prvm_prog_t *prog)
{
vec3_t ambientcolor, diffusecolor, diffusenormal;
vec_t *p;
void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
char s[17];
// 1: string (4 stats carrying a total of 16 charactures)
// 2: float (one stat, float converted to an integer for transportation)
// 8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
-static void VM_SV_AddStat (void)
+static void VM_SV_AddStat(prvm_prog_t *prog)
{
int off, i;
unsigned char type;
vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
if(!vm_customstats)
{
- VM_Warning("PF_SV_AddStat: not enough memory\n");
+ VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
return;
}
}
if(i < 0)
{
- VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
+ VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
return;
}
if(i >= (MAX_CL_STATS-32))
{
- VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
+ VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
return;
}
if(i > (MAX_CL_STATS-32-4) && type == 1)
{
- VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
+ VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
return;
}
vm_customstats[i].type = type;
copyentity(src, dst)
=================
*/
-static void VM_SV_copyentity (void)
+static void VM_SV_copyentity(prvm_prog_t *prog)
{
prvm_edict_t *in, *out;
VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
in = PRVM_G_EDICT(OFS_PARM0);
if (in == prog->edicts)
{
- VM_Warning("copyentity: can not read world entity\n");
+ VM_Warning(prog, "copyentity: can not read world entity\n");
return;
}
if (in->priv.server->free)
{
- VM_Warning("copyentity: can not read free entity\n");
+ VM_Warning(prog, "copyentity: can not read free entity\n");
return;
}
out = PRVM_G_EDICT(OFS_PARM1);
if (out == prog->edicts)
{
- VM_Warning("copyentity: can not modify world entity\n");
+ VM_Warning(prog, "copyentity: can not modify world entity\n");
return;
}
if (out->priv.server->free)
{
- VM_Warning("copyentity: can not modify free entity\n");
+ VM_Warning(prog, "copyentity: can not modify free entity\n");
return;
}
memcpy(out->fields.vp, in->fields.vp, prog->entityfields * 4);
setcolor(clientent, value)
=================
*/
-static void VM_SV_setcolor (void)
+static void VM_SV_setcolor(prvm_prog_t *prog)
{
client_t *client;
int entnum, i;
effect(origin, modelname, startframe, framecount, framerate)
=================
*/
-static void VM_SV_effect (void)
+static void VM_SV_effect(prvm_prog_t *prog)
{
int i;
const char *s;
s = PRVM_G_STRING(OFS_PARM1);
if (!s[0])
{
- VM_Warning("effect: no model specified\n");
+ VM_Warning(prog, "effect: no model specified\n");
return;
}
i = SV_ModelIndex(s, 1);
if (!i)
{
- VM_Warning("effect: model not precached\n");
+ VM_Warning(prog, "effect: model not precached\n");
return;
}
if (PRVM_G_FLOAT(OFS_PARM3) < 1)
{
- VM_Warning("effect: framecount < 1\n");
+ VM_Warning(prog, "effect: framecount < 1\n");
return;
}
if (PRVM_G_FLOAT(OFS_PARM4) < 1)
{
- VM_Warning("effect: framerate < 1\n");
+ VM_Warning(prog, "effect: framerate < 1\n");
return;
}
SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
}
-static void VM_SV_te_blood (void)
+static void VM_SV_te_blood(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
if (PRVM_G_FLOAT(OFS_PARM2) < 1)
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_bloodshower (void)
+static void VM_SV_te_bloodshower(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
if (PRVM_G_FLOAT(OFS_PARM3) < 1)
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_explosionrgb (void)
+static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_particlecube (void)
+static void VM_SV_te_particlecube(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
if (PRVM_G_FLOAT(OFS_PARM3) < 1)
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_particlerain (void)
+static void VM_SV_te_particlerain(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
if (PRVM_G_FLOAT(OFS_PARM3) < 1)
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_particlesnow (void)
+static void VM_SV_te_particlesnow(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
if (PRVM_G_FLOAT(OFS_PARM3) < 1)
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_spark (void)
+static void VM_SV_te_spark(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
if (PRVM_G_FLOAT(OFS_PARM2) < 1)
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_gunshotquad (void)
+static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_spikequad (void)
+static void VM_SV_te_spikequad(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_superspikequad (void)
+static void VM_SV_te_superspikequad(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_explosionquad (void)
+static void VM_SV_te_explosionquad(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_smallflash (void)
+static void VM_SV_te_smallflash(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_customflash (void)
+static void VM_SV_te_customflash(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_gunshot (void)
+static void VM_SV_te_gunshot(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_spike (void)
+static void VM_SV_te_spike(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_superspike (void)
+static void VM_SV_te_superspike(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_explosion (void)
+static void VM_SV_te_explosion(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_tarexplosion (void)
+static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_wizspike (void)
+static void VM_SV_te_wizspike(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_knightspike (void)
+static void VM_SV_te_knightspike(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_lavasplash (void)
+static void VM_SV_te_lavasplash(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_teleport (void)
+static void VM_SV_te_teleport(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_explosion2 (void)
+static void VM_SV_te_explosion2(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_lightning1 (void)
+static void VM_SV_te_lightning1(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_lightning2 (void)
+static void VM_SV_te_lightning2(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_lightning3 (void)
+static void VM_SV_te_lightning3(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_beam (void)
+static void VM_SV_te_beam(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_plasmaburn (void)
+static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
SV_FlushBroadcastMessages();
}
-static void VM_SV_te_flamejet (void)
+static void VM_SV_te_flamejet(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
MSG_WriteByte(&sv.datagram, svc_temp_entity);
//void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
//this function originally written by KrimZon, made shorter by LordHavoc
-static void VM_SV_clientcommand (void)
+static void VM_SV_clientcommand(prvm_prog_t *prog)
{
client_t *temp_client;
int i;
temp_client = host_client;
host_client = svs.clients + i;
- Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
+ Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
host_client = temp_client;
}
//void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
-static void VM_SV_setattachment (void)
+static void VM_SV_setattachment(prvm_prog_t *prog)
{
prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
if (e == prog->edicts)
{
- VM_Warning("setattachment: can not modify world entity\n");
+ VM_Warning(prog, "setattachment: can not modify world entity\n");
return;
}
if (e->priv.server->free)
{
- VM_Warning("setattachment: can not modify free entity\n");
+ VM_Warning(prog, "setattachment: can not modify free entity\n");
return;
}
/////////////////////////////////////////
// DP_MD3_TAGINFO extension coded by VorteX
-int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
+static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
{
int i;
return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
}
-int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
{
int r;
dp_model_t *model;
return 1;
}
-void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
+void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
{
float scale;
float pitchsign = 1;
Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2] + PRVM_serveredictvector(ent, view_ofs)[2], PRVM_serveredictvector(ent, v_angle)[0], PRVM_serveredictvector(ent, v_angle)[1], PRVM_serveredictvector(ent, v_angle)[2], scale * cl_viewmodel_scale.value);
else
{
- pitchsign = SV_GetPitchSign(ent);
+ pitchsign = SV_GetPitchSign(prog, ent);
Matrix4x4_CreateFromQuakeEntity(out, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], pitchsign * PRVM_serveredictvector(ent, angles)[0], PRVM_serveredictvector(ent, angles)[1], PRVM_serveredictvector(ent, angles)[2], scale);
}
}
-int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
+static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
{
dp_model_t *model;
if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
{
- VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
+ VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
}
*out = identitymatrix;
extern cvar_t cl_bob;
extern cvar_t cl_bobcycle;
extern cvar_t cl_bobup;
-int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
+static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
{
int ret;
int modelindex, attachloop;
model = SV_GetModelByIndex(modelindex);
- VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
+ VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
+ VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
tagmatrix = identitymatrix;
// DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
return 5;
// apply transformation by child's tagindex on parent entity and then
// by parent entity itself
- ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
+ ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
if (ret && attachloop == 0)
return ret;
- SV_GetEntityMatrix(ent, &entitymatrix, false);
+ SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
// next iteration we process the parent entity
Matrix4x4_Copy(&tagmatrix, out);
ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
- SV_GetEntityMatrix(ent, &entitymatrix, true);
+ SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
/*
//float(entity ent, string tagname) gettagindex;
-static void VM_SV_gettagindex (void)
+static void VM_SV_gettagindex(prvm_prog_t *prog)
{
prvm_edict_t *ent;
const char *tag_name;
if (ent == prog->edicts)
{
- VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
+ VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
return;
}
if (ent->priv.server->free)
{
- VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
+ VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
return;
}
Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
else
{
- tag_index = SV_GetTagIndex(ent, tag_name);
+ tag_index = SV_GetTagIndex(prog, ent, tag_name);
if (tag_index == 0)
if(developer_extra.integer)
Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
}
//vector(entity ent, float tagindex) gettaginfo;
-static void VM_SV_gettaginfo (void)
+static void VM_SV_gettaginfo(prvm_prog_t *prog)
{
prvm_edict_t *e;
int tagindex;
e = PRVM_G_EDICT(OFS_PARM0);
tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
- returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
+ returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
Matrix4x4_ToVectors(&tag_matrix, PRVM_serverglobalvector(v_forward), le, PRVM_serverglobalvector(v_up), PRVM_G_VECTOR(OFS_RETURN));
VectorScale(le, -1, PRVM_serverglobalvector(v_right));
model = SV_GetModelFromEdict(e);
- VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
+ VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
- VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
- SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
+ VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
+ SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
- PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(tagname) : 0;
+ PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
VectorCopy(trans, PRVM_serverglobalvector(gettaginfo_offset));
VectorCopy(fo, PRVM_serverglobalvector(gettaginfo_forward));
VectorScale(le, -1, PRVM_serverglobalvector(gettaginfo_right));
switch(returncode)
{
case 1:
- VM_Warning("gettagindex: can't affect world entity\n");
+ VM_Warning(prog, "gettagindex: can't affect world entity\n");
break;
case 2:
- VM_Warning("gettagindex: can't affect free entity\n");
+ VM_Warning(prog, "gettagindex: can't affect free entity\n");
break;
case 3:
Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
}
//void(entity clent) dropclient (DP_SV_DROPCLIENT)
-static void VM_SV_dropclient (void)
+static void VM_SV_dropclient(prvm_prog_t *prog)
{
int clientnum;
client_t *oldhostclient;
clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
if (clientnum < 0 || clientnum >= svs.maxclients)
{
- VM_Warning("dropclient: not a client\n");
+ VM_Warning(prog, "dropclient: not a client\n");
return;
}
if (!svs.clients[clientnum].active)
{
- VM_Warning("dropclient: that client slot is not connected\n");
+ VM_Warning(prog, "dropclient: that client slot is not connected\n");
return;
}
oldhostclient = host_client;
}
//entity() spawnclient (DP_SV_BOTCLIENT)
-static void VM_SV_spawnclient (void)
+static void VM_SV_spawnclient(prvm_prog_t *prog)
{
int i;
prvm_edict_t *ed;
}
//float(entity clent) clienttype (DP_SV_BOTCLIENT)
-static void VM_SV_clienttype (void)
+static void VM_SV_clienttype(prvm_prog_t *prog)
{
int clientnum;
VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
string(string key) serverkey
===============
*/
-void VM_SV_serverkey(void)
+static void VM_SV_serverkey(prvm_prog_t *prog)
{
char string[VM_STRINGTEMP_LENGTH];
VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
}
//#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
-static void VM_SV_setmodelindex (void)
+static void VM_SV_setmodelindex(prvm_prog_t *prog)
{
prvm_edict_t *e;
dp_model_t *mod;
e = PRVM_G_EDICT(OFS_PARM0);
if (e == prog->edicts)
{
- VM_Warning("setmodelindex: can not modify world entity\n");
+ VM_Warning(prog, "setmodelindex: can not modify world entity\n");
return;
}
if (e->priv.server->free)
{
- VM_Warning("setmodelindex: can not modify free entity\n");
+ VM_Warning(prog, "setmodelindex: can not modify free entity\n");
return;
}
i = (int)PRVM_G_FLOAT(OFS_PARM1);
if (i <= 0 || i >= MAX_MODELS)
{
- VM_Warning("setmodelindex: invalid modelindex\n");
+ VM_Warning(prog, "setmodelindex: invalid modelindex\n");
return;
}
if (!sv.model_precache[i][0])
{
- VM_Warning("setmodelindex: model not precached\n");
+ VM_Warning(prog, "setmodelindex: model not precached\n");
return;
}
- PRVM_serveredictstring(e, model) = PRVM_SetEngineString(sv.model_precache[i]);
+ PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
PRVM_serveredictfloat(e, modelindex) = i;
mod = SV_GetModelByIndex(i);
if (mod)
{
if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
- SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
+ SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
else
- SetMinMaxSize (e, quakemins, quakemaxs, true);
+ SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
}
else
- SetMinMaxSize (e, vec3_origin, vec3_origin, true);
+ SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
}
//#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
-static void VM_SV_modelnameforindex (void)
+static void VM_SV_modelnameforindex(prvm_prog_t *prog)
{
int i;
VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
i = (int)PRVM_G_FLOAT(OFS_PARM0);
if (i <= 0 || i >= MAX_MODELS)
{
- VM_Warning("modelnameforindex: invalid modelindex\n");
+ VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
return;
}
if (!sv.model_precache[i][0])
{
- VM_Warning("modelnameforindex: model not precached\n");
+ VM_Warning(prog, "modelnameforindex: model not precached\n");
return;
}
- PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
}
//#335 float(string effectname) particleeffectnum (EXT_CSQC)
-static void VM_SV_particleeffectnum (void)
+static void VM_SV_particleeffectnum(prvm_prog_t *prog)
{
int i;
VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
}
// #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
-static void VM_SV_trailparticles (void)
+static void VM_SV_trailparticles(prvm_prog_t *prog)
{
VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
}
//#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
-static void VM_SV_pointparticles (void)
+static void VM_SV_pointparticles(prvm_prog_t *prog)
{
int effectnum, count;
vec3_t org, vel;
}
//PF_setpause, // void(float pause) setpause = #531;
-static void VM_SV_setpause(void) {
+static void VM_SV_setpause(prvm_prog_t *prog) {
int pauseValue;
pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
if (pauseValue != 0) { //pause the game
sv.paused = 1;
- sv.pausedstart = Sys_DoubleTime();
+ sv.pausedstart = realtime;
} else { //disable pause, in case it was enabled
if (sv.paused != 0) {
sv.paused = 0;
}
// #263 float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
-static void VM_SV_skel_create(void)
+static void VM_SV_skel_create(prvm_prog_t *prog)
{
int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
dp_model_t *model = SV_GetModelByIndex(modelindex);
}
// #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
-static void VM_SV_skel_build(void)
+static void VM_SV_skel_build(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
skeleton_t *skeleton;
firstbone = max(0, firstbone);
lastbone = min(lastbone, model->num_bones - 1);
lastbone = min(lastbone, skeleton->model->num_bones - 1);
- VM_GenerateFrameGroupBlend(framegroupblend, ed);
+ VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
blendfrac = 1.0f - retainfrac;
for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
}
// #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
-static void VM_SV_skel_get_numbones(void)
+static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
skeleton_t *skeleton;
}
// #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
-static void VM_SV_skel_get_bonename(void)
+static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
return;
if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
return;
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
}
// #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
-static void VM_SV_skel_get_boneparent(void)
+static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #268 float(float skel, string tagname) skel_find_bone = #268; // (FTE_CSQC_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
-static void VM_SV_skel_find_bone(void)
+static void VM_SV_skel_find_bone(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
const char *tagname = PRVM_G_STRING(OFS_PARM1);
}
// #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
-static void VM_SV_skel_get_bonerel(void)
+static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
-static void VM_SV_skel_get_boneabs(void)
+static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-static void VM_SV_skel_set_bone(void)
+static void VM_SV_skel_set_bone(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
-static void VM_SV_skel_mul_bone(void)
+static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
-static void VM_SV_skel_mul_bones(void)
+static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
-static void VM_SV_skel_copybones(void)
+static void VM_SV_skel_copybones(prvm_prog_t *prog)
{
int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
}
// #275 void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
-static void VM_SV_skel_delete(void)
+static void VM_SV_skel_delete(prvm_prog_t *prog)
{
int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
skeleton_t *skeleton;
}
// #276 float(float modlindex, string framename) frameforname = #276; // (FTE_CSQC_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
-static void VM_SV_frameforname(void)
+static void VM_SV_frameforname(prvm_prog_t *prog)
{
int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
dp_model_t *model = SV_GetModelByIndex(modelindex);
}
// #277 float(float modlindex, float framenum) frameduration = #277; // (FTE_CSQC_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
-static void VM_SV_frameduration(void)
+static void VM_SV_frameduration(prvm_prog_t *prog)
{
int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
dp_model_t *model = SV_GetModelByIndex(modelindex);
VM_SV_tracetoss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
VM_etos, // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
NULL, // #66 (QUAKE)
-SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
+VM_SV_MoveToGoal, // #67 void(float step) movetogoal (QUAKE)
VM_precache_file, // #68 string(string s) precache_file (QUAKE)
VM_SV_makestatic, // #69 void(entity e) makestatic (QUAKE)
VM_changelevel, // #70 void(string s) changelevel (QUAKE)
VM_getsurfacenumtriangles, // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
VM_getsurfacetriangle, // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
NULL, // #630
+NULL, // #631
+NULL, // #632
+NULL, // #633
+NULL, // #634
+NULL, // #635
+NULL, // #636
+NULL, // #637
+NULL, // #638
+VM_digest_hex, // #639
+NULL, // #640
};
const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
-void VM_SV_Cmd_Init(void)
+void SVVM_init_cmd(prvm_prog_t *prog)
{
- VM_Cmd_Init();
+ VM_Cmd_Init(prog);
}
-void VM_SV_Cmd_Reset(void)
+void SVVM_reset_cmd(prvm_prog_t *prog)
{
World_End(&sv.world);
if(PRVM_serverfunction(SV_Shutdown))
{
func_t s = PRVM_serverfunction(SV_Shutdown);
+ PRVM_serverglobalfloat(time) = sv.time;
PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
- PRVM_ExecuteProgram(s,"SV_Shutdown() required");
+ prog->ExecuteProgram(prog, s,"SV_Shutdown() required");
}
- VM_Cmd_Reset();
+ VM_Cmd_Reset(prog);
}
-
/// (may) output text to terminal which launched program
void Sys_PrintToTerminal(const char *text);
+void Sys_PrintfToTerminal(const char *fmt, ...);
/// INFO: This is only called by Host_Shutdown so we dont need testing for recursion
void Sys_Shutdown (void);
*/
void Sys_AllowProfiling (qboolean enable);
-double Sys_DoubleTime (void);
+typedef struct sys_cleantime_s
+{
+ double dirtytime; // last value gotten from Sys_DirtyTime()
+ double cleantime; // sanitized linearly increasing time since app start
+}
+sys_cleantime_t;
+
+double Sys_DirtyTime(void);
void Sys_ProvideSelfFD (void);
unsigned int Sys_SDL_GetTicks (void); // wrapper to call SDL_GetTicks
void Sys_SDL_Delay (unsigned int milliseconds); // wrapper to call SDL_Delay
+/// called to set process priority for dedicated servers
+void Sys_InitProcessNice (void);
+void Sys_MakeProcessNice (void);
+void Sys_MakeProcessMean (void);
+
#endif
char *Sys_ConsoleInput(void)
{
- if (cls.state == ca_dedicated)
+// if (cls.state == ca_dedicated)
{
static char text[MAX_INPUTLINE];
int len = 0;
static cvar_t sys_useclockgettime = {CVAR_SAVE, "sys_useclockgettime", "0", "use POSIX clock_gettime function (which has issues if the system clock speed is far off, as it can't get fixed by NTP) for timing rather than gettimeofday (which has issues if the system time is stepped by ntpdate, or apparently on some Xen installations)"};
#endif
-static unsigned long benchmark_time;
+static double benchmark_time; // actually always contains an integer amount of milliseconds, will eventually "overflow"
void Sys_Init_Commands (void)
{
#endif
}
-double Sys_DoubleTime(void)
+double Sys_DirtyTime(void)
{
- static int first = true;
- static double oldtime = 0.0, curtime = 0.0;
- double newtime;
+ // first all the OPTIONAL timers
+
+ // benchmark timer (fake clock)
if(sys_usenoclockbutbenchmark.integer)
{
+ double old_benchmark_time = benchmark_time;
benchmark_time += 1;
- return ((double) benchmark_time) / 1e6;
+ if(benchmark_time == old_benchmark_time)
+ Sys_Error("sys_usenoclockbutbenchmark cannot run any longer, sorry");
+ return benchmark_time * 0.000001;
}
-
- // first all the OPTIONAL timers
-
#if HAVE_QUERYPERFORMANCECOUNTER
- else if (sys_usequeryperformancecounter.integer)
+ if (sys_usequeryperformancecounter.integer)
{
// LordHavoc: note to people modifying this code, DWORD is specifically defined as an unsigned 32bit number, therefore the 65536.0 * 65536.0 is fine.
// QueryPerformanceCounter
LARGE_INTEGER PerformanceFreq;
LARGE_INTEGER PerformanceCount;
- if (!QueryPerformanceFrequency (&PerformanceFreq))
+ if (QueryPerformanceFrequency (&PerformanceFreq))
+ {
+ QueryPerformanceCounter (&PerformanceCount);
+
+ #ifdef __BORLANDC__
+ timescale = 1.0 / ((double) PerformanceFreq.u.LowPart + (double) PerformanceFreq.u.HighPart * 65536.0 * 65536.0);
+ return ((double) PerformanceCount.u.LowPart + (double) PerformanceCount.u.HighPart * 65536.0 * 65536.0) * timescale;
+ #else
+ timescale = 1.0 / ((double) PerformanceFreq.LowPart + (double) PerformanceFreq.HighPart * 65536.0 * 65536.0);
+ return ((double) PerformanceCount.LowPart + (double) PerformanceCount.HighPart * 65536.0 * 65536.0) * timescale;
+ #endif
+ }
+ else
{
- Con_Printf ("No hardware timer available\n");
- // fall back to timeGetTime
+ Con_Printf("No hardware timer available\n");
+ // fall back to other clock sources
Cvar_SetValueQuick(&sys_usequeryperformancecounter, false);
- return Sys_DoubleTime();
}
- QueryPerformanceCounter (&PerformanceCount);
-
- #ifdef __BORLANDC__
- timescale = 1.0 / ((double) PerformanceFreq.u.LowPart + (double) PerformanceFreq.u.HighPart * 65536.0 * 65536.0);
- newtime = ((double) PerformanceCount.u.LowPart + (double) PerformanceCount.u.HighPart * 65536.0 * 65536.0) * timescale;
- #else
- timescale = 1.0 / ((double) PerformanceFreq.LowPart + (double) PerformanceFreq.HighPart * 65536.0 * 65536.0);
- newtime = ((double) PerformanceCount.LowPart + (double) PerformanceCount.HighPart * 65536.0 * 65536.0) * timescale;
- #endif
}
#endif
#if HAVE_CLOCKGETTIME
- else if (sys_useclockgettime.integer)
+ if (sys_useclockgettime.integer)
{
struct timespec ts;
# ifdef CLOCK_MONOTONIC
// sunos
clock_gettime(CLOCK_HIGHRES, &ts);
# endif
- newtime = (double) ts.tv_sec + ts.tv_nsec / 1000000000.0;
+ return (double) ts.tv_sec + ts.tv_nsec / 1000000000.0;
}
#endif
// now all the FALLBACK timers
- else if(sys_supportsdlgetticks && sys_usesdlgetticks.integer)
- {
- newtime = (double) Sys_SDL_GetTicks() / 1000.0;
- }
+ if(sys_supportsdlgetticks && sys_usesdlgetticks.integer)
+ return (double) Sys_SDL_GetTicks() / 1000.0;
#if HAVE_GETTIMEOFDAY
- else
{
struct timeval tp;
gettimeofday(&tp, NULL);
- newtime = (double) tp.tv_sec + tp.tv_usec / 1000000.0;
+ return (double) tp.tv_sec + tp.tv_usec / 1000000.0;
}
#elif HAVE_TIMEGETTIME
- else
{
static int firsttimegettime = true;
// timeGetTime
// make sure the timer is high precision, otherwise different versions of windows have varying accuracy
if (firsttimegettime)
{
- timeBeginPeriod (1);
+ timeBeginPeriod(1);
firsttimegettime = false;
}
- newtime = (double) timeGetTime () / 1000.0;
+ return (double) timeGetTime() / 1000.0;
}
#else
// fallback for using the SDL timer if no other timer is available
- else
- {
- newtime = (double) Sys_SDL_GetTicks() / 1000.0;
- // this calls Sys_Error() if not linking against SDL
- }
+ // this calls Sys_Error() if not linking against SDL
+ return (double) Sys_SDL_GetTicks() / 1000.0;
#endif
-
- if (first)
- {
- first = false;
- oldtime = newtime;
- }
-
- if (newtime < oldtime)
- {
- // warn if it's significant
- if (newtime - oldtime < -0.01)
- Con_Printf("Sys_DoubleTime: time stepped backwards (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
- }
- else if (newtime > oldtime + 1800)
- {
- Con_Printf("Sys_DoubleTime: time stepped forward (went from %f to %f, difference %f)\n", oldtime, newtime, newtime - oldtime);
- }
- else
- curtime += newtime - oldtime;
- oldtime = newtime;
-
- return curtime;
}
void Sys_Sleep(int microseconds)
double t = 0;
if(sys_usenoclockbutbenchmark.integer)
{
- benchmark_time += microseconds;
+ if(microseconds)
+ {
+ double old_benchmark_time = benchmark_time;
+ benchmark_time += microseconds;
+ if(benchmark_time == old_benchmark_time)
+ Sys_Error("sys_usenoclockbutbenchmark cannot run any longer, sorry");
+ }
return;
}
if(sys_debugsleep.integer)
{
- t = Sys_DoubleTime();
+ t = Sys_DirtyTime();
}
if(sys_supportsdlgetticks && sys_usesdldelay.integer)
{
#endif
if(sys_debugsleep.integer)
{
- t = Sys_DoubleTime() - t;
- printf("%d %d # debugsleep\n", microseconds, (unsigned int)(t * 1000000));
+ t = Sys_DirtyTime() - t;
+ Sys_PrintfToTerminal("%d %d # debugsleep\n", microseconds, (unsigned int)(t * 1000000));
}
}
-const char *Sys_FindInPATH(const char *name, char namesep, const char *PATH, char pathsep, char *buf, size_t bufsize)
+void Sys_PrintfToTerminal(const char *fmt, ...)
+{
+ va_list argptr;
+ char msg[MAX_INPUTLINE];
+
+ va_start(argptr,fmt);
+ dpvsnprintf(msg,sizeof(msg),fmt,argptr);
+ va_end(argptr);
+
+ Sys_PrintToTerminal(msg);
+}
+
+#ifndef WIN32
+static const char *Sys_FindInPATH(const char *name, char namesep, const char *PATH, char pathsep, char *buf, size_t bufsize)
{
const char *p = PATH;
const char *q;
}
return name;
}
+#endif
-const char *Sys_FindExecutableName(void)
+static const char *Sys_FindExecutableName(void)
{
#if defined(WIN32)
return com_argv[0];
return false;
}
#endif
+
+/// called to set process priority for dedicated servers
+#if defined(__linux__)
+#include <sys/resource.h>
+#include <errno.h>
+static int nicelevel;
+static qboolean nicepossible;
+static qboolean isnice;
+void Sys_InitProcessNice (void)
+{
+ struct rlimit lim;
+ nicepossible = false;
+ if(COM_CheckParm("-nonice"))
+ return;
+ errno = 0;
+ nicelevel = getpriority(PRIO_PROCESS, 0);
+ if(errno)
+ {
+ Con_Printf("Kernel does not support reading process priority - cannot use niceness\n");
+ return;
+ }
+ if(getrlimit(RLIMIT_NICE, &lim))
+ {
+ Con_Printf("Kernel does not support lowering nice level again - cannot use niceness\n");
+ return;
+ }
+ if(lim.rlim_cur != RLIM_INFINITY && nicelevel < (int) (20 - lim.rlim_cur))
+ {
+ Con_Printf("Current nice level is below the soft limit - cannot use niceness\n");
+ return;
+ }
+ nicepossible = true;
+ isnice = false;
+}
+void Sys_MakeProcessNice (void)
+{
+ if(!nicepossible)
+ return;
+ if(isnice)
+ return;
+ Con_DPrintf("Process is becoming 'nice'...\n");
+ if(setpriority(PRIO_PROCESS, 0, 19))
+ Con_Printf("Failed to raise nice level to %d\n", 19);
+ isnice = true;
+}
+void Sys_MakeProcessMean (void)
+{
+ if(!nicepossible)
+ return;
+ if(!isnice)
+ return;
+ Con_DPrintf("Process is becoming 'mean'...\n");
+ if(setpriority(PRIO_PROCESS, 0, nicelevel))
+ Con_Printf("Failed to lower nice level to %d\n", nicelevel);
+ isnice = false;
+}
+#else
+void Sys_InitProcessNice (void)
+{
+}
+void Sys_MakeProcessNice (void)
+{
+}
+void Sys_MakeProcessMean (void)
+{
+}
+#endif
#ifndef THREAD_H
+// enable Sys_PrintfToTerminal calls on nearly every threading call
+//#define THREADDEBUG
+// use recursive mutex (non-posix) extensions in thread_pthread
+#define THREADRECURSIVE
+
+#define Thread_CreateMutex() (_Thread_CreateMutex(__FILE__, __LINE__))
+#define Thread_DestroyMutex(m) (_Thread_DestroyMutex(m, __FILE__, __LINE__))
+#define Thread_LockMutex(m) (_Thread_LockMutex(m, __FILE__, __LINE__))
+#define Thread_UnlockMutex(m) (_Thread_UnlockMutex(m, __FILE__, __LINE__))
+#define Thread_CreateCond() (_Thread_CreateCond(__FILE__, __LINE__))
+#define Thread_DestroyCond(cond) (_Thread_DestroyCond(cond, __FILE__, __LINE__))
+#define Thread_CondSignal(cond) (_Thread_CondSignal(cond, __FILE__, __LINE__))
+#define Thread_CondBroadcast(cond) (_Thread_CondBroadcast(cond, __FILE__, __LINE__))
+#define Thread_CondWait(cond, mutex) (_Thread_CondWait(cond, mutex, __FILE__, __LINE__))
+#define Thread_CreateThread(fn, data) (_Thread_CreateThread(fn, data, __FILE__, __LINE__))
+#define Thread_WaitThread(thread, retval) (_Thread_WaitThread(thread, retval, __FILE__, __LINE__))
+
int Thread_Init(void);
void Thread_Shutdown(void);
qboolean Thread_HasThreads(void);
-void *Thread_CreateMutex(void);
-void Thread_DestroyMutex(void *mutex);
-int Thread_LockMutex(void *mutex);
-int Thread_UnlockMutex(void *mutex);
-void *Thread_CreateCond(void);
-void Thread_DestroyCond(void *cond);
-int Thread_CondSignal(void *cond);
-int Thread_CondBroadcast(void *cond);
-int Thread_CondWait(void *cond, void *mutex);
-void *Thread_CreateThread(int (*fn)(void *), void *data);
-int Thread_WaitThread(void *thread, int retval);
+void *_Thread_CreateMutex(const char *filename, int fileline);
+void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline);
+int _Thread_LockMutex(void *mutex, const char *filename, int fileline);
+int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline);
+void *_Thread_CreateCond(const char *filename, int fileline);
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline);
+int _Thread_CondSignal(void *cond, const char *filename, int fileline);
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline);
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline);
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline);
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline);
#endif
return false;
}
-void *Thread_CreateMutex(void)
+void *_Thread_CreateMutex(const char *filename, int fileline)
{
return NULL;
}
-void Thread_DestroyMutex(void *mutex)
+void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
{
}
-int Thread_LockMutex(void *mutex)
+int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
{
return -1;
}
-int Thread_UnlockMutex(void *mutex)
+int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
{
return -1;
}
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
return NULL;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
return -1;
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
return -1;
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
return -1;
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
return NULL;
}
-int Thread_WaitThread(void *thread, int retval)
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
{
return retval;
}
-
#include "quakedef.h"
#include "thread.h"
+#ifdef THREADRECURSIVE
+#define __USE_UNIX98
#include <pthread.h>
+#endif
#include <stdint.h>
+
int Thread_Init(void)
{
return 0;
return true;
}
-void *Thread_CreateMutex(void)
+void *_Thread_CreateMutex(const char *filename, int fileline)
{
+#ifdef THREADRECURSIVE
+ pthread_mutexattr_t attr;
+#endif
pthread_mutex_t *mutexp = (pthread_mutex_t *) Z_Malloc(sizeof(pthread_mutex_t));
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutexp, filename, fileline);
+#endif
+#ifdef THREADRECURSIVE
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(mutexp, &attr);
+#else
pthread_mutex_init(mutexp, NULL);
+#endif
return mutexp;
}
-void Thread_DestroyMutex(void *mutex)
+void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
{
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
+#endif
pthread_mutex_destroy(mutexp);
Z_Free(mutexp);
}
-int Thread_LockMutex(void *mutex)
+int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
{
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex lock %s:%i\n" , mutex, filename, fileline);
+#endif
return pthread_mutex_lock(mutexp);
}
-int Thread_UnlockMutex(void *mutex)
+int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
{
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
+#endif
return pthread_mutex_unlock(mutexp);
}
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) Z_Malloc(sizeof(pthread_cond_t));
pthread_cond_init(condp, NULL);
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond create %s:%i\n" , condp, filename, fileline);
+#endif
return condp;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond destroy %s:%i\n" , cond, filename, fileline);
+#endif
pthread_cond_destroy(condp);
Z_Free(condp);
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond signal %s:%i\n" , cond, filename, fileline);
+#endif
return pthread_cond_signal(condp);
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond broadcast %s:%i\n" , cond, filename, fileline);
+#endif
return pthread_cond_broadcast(condp);
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
pthread_cond_t *condp = (pthread_cond_t *) cond;
pthread_mutex_t *mutexp = (pthread_mutex_t *) mutex;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond wait %s:%i\n" , cond, filename, fileline);
+#endif
return pthread_cond_wait(condp, mutexp);
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
pthread_t *threadp = (pthread_t *) Z_Malloc(sizeof(pthread_t));
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread create %s:%i\n" , threadp, filename, fileline);
+#endif
int r = pthread_create(threadp, NULL, (void * (*) (void *)) fn, data);
if(r)
{
return threadp;
}
-int Thread_WaitThread(void *thread, int retval)
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
{
pthread_t *threadp = (pthread_t *) thread;
void *status = (void *) (intptr_t) retval;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread wait %s:%i\n" , thread, filename, fileline);
+#endif
pthread_join(*threadp, &status);
Z_Free(threadp);
return (int) (intptr_t) status;
return true;
}
-void *Thread_CreateMutex(void)
+void *_Thread_CreateMutex(const char *filename, int fileline)
{
- return SDL_CreateMutex();
+ void *mutex = SDL_CreateMutex();
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutex, filename, fileline);
+#endif
+ return mutex;
}
-void Thread_DestroyMutex(void *mutex)
+void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
+#endif
SDL_DestroyMutex((SDL_mutex *)mutex);
}
-int Thread_LockMutex(void *mutex)
+int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex lock %s:%i\n" , mutex, filename, fileline);
+#endif
return SDL_LockMutex((SDL_mutex *)mutex);
}
-int Thread_UnlockMutex(void *mutex)
+int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
+#endif
return SDL_UnlockMutex((SDL_mutex *)mutex);
}
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
- return SDL_CreateCond();
+ void *cond = (void *)SDL_CreateCond();
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond create %s:%i\n" , cond, filename, fileline);
+#endif
+ return cond;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond destroy %s:%i\n" , cond, filename, fileline);
+#endif
SDL_DestroyCond((SDL_cond *)cond);
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond signal %s:%i\n" , cond, filename, fileline);
+#endif
return SDL_CondSignal((SDL_cond *)cond);
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond broadcast %s:%i\n" , cond, filename, fileline);
+#endif
return SDL_CondBroadcast((SDL_cond *)cond);
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond wait %s:%i\n" , cond, filename, fileline);
+#endif
return SDL_CondWait((SDL_cond *)cond, (SDL_mutex *)mutex);
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
- return SDL_CreateThread(fn, data);
+ void *thread = (void *)SDL_CreateThread(fn, data);
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread create %s:%i\n" , thread, filename, fileline);
+#endif
+ return thread;
}
-int Thread_WaitThread(void *thread, int retval)
+int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
{
int status = retval;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread wait %s:%i\n" , thread, filename, fileline);
+#endif
SDL_WaitThread((SDL_Thread *)thread, &status);
return status;
}
return true;
}
-void *Thread_CreateMutex(void)
+void *_Thread_CreateMutex(const char *filename, int fileline)
{
- return (void *)CreateMutex(NULL, FALSE, NULL);
+ void *mutex = (void *)CreateMutex(NULL, FALSE, NULL);
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutex, filename, fileline);
+#endif
+ return mutex;
}
-void Thread_DestroyMutex(void *mutex)
+void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
+#endif
CloseHandle(mutex);
}
-int Thread_LockMutex(void *mutex)
+int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex lock %s:%i\n" , mutex, filename, fileline);
+#endif
return (WaitForSingleObject(mutex, INFINITE) == WAIT_FAILED) ? -1 : 0;
}
-int Thread_UnlockMutex(void *mutex)
+int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
{
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
+#endif
return (ReleaseMutex(mutex) == FALSE) ? -1 : 0;
}
}
thread_cond_t;
-void *Thread_CreateCond(void)
+void *_Thread_CreateCond(const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)calloc(sizeof(*c), 1);
c->mutex = CreateMutex(NULL, FALSE, NULL);
c->done = Thread_CreateSemaphore(0);
c->waiting = 0;
c->signals = 0;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond create %s:%i\n" , c, filename, fileline);
+#endif
return c;
}
-void Thread_DestroyCond(void *cond)
+void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond destroy %s:%i\n" , cond, filename, fileline);
+#endif
Thread_DestroySemaphore(c->sem);
Thread_DestroySemaphore(c->done);
CloseHandle(c->mutex);
}
-int Thread_CondSignal(void *cond)
+int _Thread_CondSignal(void *cond, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
int n;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond signal %s:%i\n" , cond, filename, fileline);
+#endif
WaitForSingleObject(c->mutex, INFINITE);
n = c->waiting - c->signals;
if (n > 0)
return 0;
}
-int Thread_CondBroadcast(void *cond)
+int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
int i = 0;
int n = 0;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond broadcast %s:%i\n" , cond, filename, fileline);
+#endif
WaitForSingleObject(c->mutex, INFINITE);
n = c->waiting - c->signals;
if (n > 0)
return 0;
}
-int Thread_CondWait(void *cond, void *mutex)
+int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
{
thread_cond_t *c = (thread_cond_t *)cond;
int waitresult;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p cond wait %s:%i\n" , cond, filename, fileline);
+#endif
WaitForSingleObject(c->mutex, INFINITE);
c->waiting++;
return w->result;
}
-void *Thread_CreateThread(int (*fn)(void *), void *data)
+void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
{
threadwrapper_t *w = (threadwrapper_t *)calloc(sizeof(*w), 1);
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread create %s:%i\n" , w, filename, fileline);
+#endif
w->fn = fn;
w->data = data;
w->threadid = 0;
return (void *)w;
}
-int Thread_WaitThread(void *d, int retval)
+int _Thread_WaitThread(void *d, int retval, const char *filename, int fileline)
{
threadwrapper_t *w = (threadwrapper_t *)d;
+#ifdef THREADDEBUG
+ Sys_PrintfToTerminal("%p thread wait %s:%i\n" , w, filename, fileline);
+#endif
WaitForSingleObject(w->handle, INFINITE);
CloseHandle(w->handle);
retval = w->result;
#if defined(DO_TIMING)
-#define TIMING_BEGIN double _timing_end_, _timing_start_ = Sys_DoubleTime();
+#define TIMING_BEGIN double _timing_end_, _timing_start_ = Sys_DirtyTime();
#define TIMING_END_STR(S) \
- _timing_end_ = Sys_DoubleTime(); \
+ _timing_end_ = Sys_DirtyTime(); \
Con_Printf ("%s: %.3g s\n", S, _timing_end_ - _timing_start_);
#define TIMING_END TIMING_END_STR(__FUNCTION__)
#define TIMING_INTERMEDIATE(S) \
{ \
- double currentTime = Sys_DoubleTime(); \
+ double currentTime = Sys_DirtyTime(); \
Con_Printf ("%s: %.3g s\n", S, currentTime - _timing_start_); \
}
* @param l The number of bytes without the terminating null.
* @return A statically allocated buffer containing the character's utf8 representation, or NULL if it fails.
*/
-char *u8_encodech(Uchar ch, size_t *l)
+char *u8_encodech(Uchar ch, size_t *l, char *buf16)
{
- static char buf[16];
size_t len;
- len = u8_fromchar(ch, buf, sizeof(buf));
+ len = u8_fromchar(ch, buf16, 16);
if (len > 0)
{
if (l) *l = len;
- return buf;
+ return buf16;
}
return NULL;
}
Uchar u8_getchar_utf8_enabled(const char*, const char**);
Uchar u8_getnchar_utf8_enabled(const char*, const char**, size_t);
int u8_fromchar(Uchar, char*, size_t);
+size_t u8_mbstowcs(Uchar *, const char *, size_t);
size_t u8_wcstombs(char*, const Uchar*, size_t);
size_t u8_COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid);
// returns a static buffer, use this for inlining
-char *u8_encodech(Uchar ch, size_t*);
+char *u8_encodech(Uchar ch, size_t*, char*buf16);
size_t u8_strpad(char *out, size_t outsize, const char *in, qboolean leftalign, size_t minwidth, size_t maxwidth);
qboolean amd_texture_texture4;
qboolean arb_depth_texture;
qboolean arb_draw_buffers;
+ qboolean arb_framebuffer_object;
qboolean arb_multitexture;
qboolean arb_occlusion_query;
qboolean arb_shadow;
qboolean ext_blend_subtract;
qboolean ext_draw_range_elements;
qboolean ext_framebuffer_object;
+ qboolean ext_packed_depth_stencil;
qboolean ext_stencil_two_side;
qboolean ext_texture_3d;
qboolean ext_texture_compression_s3tc;
extern cvar_t vid_resizable;
extern cvar_t vid_minwidth;
extern cvar_t vid_minheight;
+extern cvar_t vid_sRGB;
+extern cvar_t vid_sRGB_fallback;
extern cvar_t gl_finish;
// name of driver library (opengl32.dll, libGL.so.1, or whatever)
extern char gl_driver[256];
-// compatibility hacks
-extern qboolean isG200;
-extern qboolean isRagePro;
-
void *GL_GetProcAddress(const char *name);
qboolean GL_CheckExtension(const char *minglver_or_ext, const dllfunction_t *funcs, const char *disableparm, int silent);
void VID_Restart_f(void);
void VID_Start(void);
+void VID_Stop(void);
extern unsigned int vid_gammatables_serial; // so other subsystems can poll if gamma parameters have changed; this starts with 0 and gets increased by 1 each time the gamma parameters get changed and VID_BuildGammaTables should be called again
extern qboolean vid_gammatables_trivial; // this is set to true if all color control values are at default setting, and it therefore would make no sense to use the gamma table
size_t VID_ListModes(vid_mode_t *modes, size_t maxcount);
size_t VID_SortModes(vid_mode_t *modes, size_t count, qboolean usebpp, qboolean userefreshrate, qboolean useaspect);
void VID_Soft_SharedSetup(void);
+
#endif
void signal_handler(int sig)
{
- printf("Received signal %d, exiting...\n", sig);
+ Sys_PrintfToTerminal("Received signal %d, exiting...\n", sig);
VID_RestoreSystemGamma();
Sys_Quit(1);
}
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#if !defined(__APPLE__) && !defined(__MACH__) && !defined(SUNOS)
+//#define USEDGA
+#endif
+
#include <signal.h>
#include <dlfcn.h>
#include <X11/xpm.h>
#include <X11/extensions/XShm.h>
-#if !defined(__APPLE__) && !defined(__MACH__) && !defined(SUNOS)
+#ifdef USEDGA
#include <X11/extensions/xf86dga.h>
#endif
#include <X11/extensions/xf86vmode.h>
static qboolean vid_usingvsync = false;
static qboolean vid_usevsync = false;
static qboolean vid_x11_hardwaregammasupported = false;
+#ifdef USEDGA
static qboolean vid_x11_dgasupported = false;
+#endif
static int vid_x11_gammarampsize = 0;
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
cvar_t vid_dgamouse = {CVAR_SAVE, "vid_dgamouse", "0", "make use of DGA mouse input"};
static qboolean vid_usingdgamouse = false;
#endif
/*-----------------------------------------------------------------------*/
//
-long keysym2ucs(KeySym keysym);
-void DP_Xutf8LookupString(XKeyEvent * ev,
+extern long keysym2ucs(KeySym keysym); // LordHavoc: suppress warning just in this case, it's not worth having a header file for this...
+static void DP_Xutf8LookupString(XKeyEvent * ev,
Uchar *uch,
KeySym * keysym_return,
Status * status_return)
static int originalmouseparms_threshold;
static qboolean restore_spi;
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
qboolean usedgamouse;
#endif
if (!mouse_avail)
fullscreengrab = relative = hidecursor = false;
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
usedgamouse = relative && vid_dgamouse.integer;
if (!vid_x11_dgasupported)
usedgamouse = false;
attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK;
XChangeWindowAttributes(vidx11_display, win, CWEventMask, &attribs_2);
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
vid_usingdgamouse = usedgamouse;
if (usedgamouse)
{
XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2);
// COMMANDLINEOPTION: X11 Input: -noforcemparms disables setting of mouse parameters (not used with DGA, windows only)
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
if (!COM_CheckParm ("-noforcemparms") && !usedgamouse)
#else
if (!COM_CheckParm ("-noforcemparms"))
{
if (vid_usingmouse)
{
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
if (vid_usingdgamouse)
XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), 0);
vid_usingdgamouse = false;
// mouse moved
if (vid_usingmouse)
{
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
if (vid_usingdgamouse)
{
in_mouse_x += event.xmotion.x_root;
Key_ClearStates ();
}
-void signal_handler(int sig)
+static void signal_handler(int sig)
{
Con_Printf("Received signal %d, exiting...\n", sig);
VID_RestoreSystemGamma();
Sys_Quit(1);
}
-void InitSig(void)
+static void InitSig(void)
{
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
void VID_Init(void)
{
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
Cvar_RegisterVariable (&vid_dgamouse);
#endif
Cvar_RegisterVariable (&vid_netwmfullscreen);
vidx11_shminfo[1].shmid = -1;
}
-void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer, int samples)
+static void VID_BuildGLXAttrib(int *attrib, qboolean stencil, qboolean stereobuffer, int samples)
{
*attrib++ = GLX_RGBA;
*attrib++ = GLX_RED_SIZE;*attrib++ = stencil ? 8 : 5;
*attrib++ = None;
}
-qboolean VID_InitModeSoft(viddef_mode_t *mode)
+static qboolean VID_InitModeSoft(viddef_mode_t *mode)
{
int i, j;
XSetWindowAttributes attr;
unsigned char *data;
XGCValues gcval;
const char *dpyname;
+ char vabuf[1024];
vid_isfullscreen = false;
vid_isnetwmfullscreen = false;
}
++i;
Mem_Free(data);
- data = loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
+ data = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "darkplaces-icon%d", i), false, false, false, NULL);
}
XChangeProperty(vidx11_display, win, net_wm_icon, cardinal, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
}
vid_hidden = false;
vid_activewindow = true;
vid_x11_hardwaregammasupported = XF86VidModeGetGammaRampSize(vidx11_display, vidx11_screen, &vid_x11_gammarampsize) != 0;
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
vid_x11_dgasupported = XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion);
if (!vid_x11_dgasupported)
Con_Print( "Failed to detect XF86DGA Mouse extension\n" );
return true;
}
-qboolean VID_InitModeGL(viddef_mode_t *mode)
+
+static qboolean VID_InitModeGL(viddef_mode_t *mode)
{
int i, j;
int attrib[32];
char *xpm;
char **idata;
unsigned char *data;
+ char vabuf[1024];
vid_isfullscreen = false;
vid_isnetwmfullscreen = false;
}
++i;
Mem_Free(data);
- data = loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
+ data = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "darkplaces-icon%d", i), false, false, false, NULL);
}
XChangeProperty(vidx11_display, win, net_wm_icon, cardinal, 32, PropModeReplace, (const unsigned char *) netwm_icon, pos);
}
vid_hidden = false;
vid_activewindow = true;
vid_x11_hardwaregammasupported = XF86VidModeGetGammaRampSize(vidx11_display, vidx11_screen, &vid_x11_gammarampsize) != 0;
-#if !defined(__APPLE__) && !defined(SUNOS)
+#ifdef USEDGA
vid_x11_dgasupported = XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion);
if (!vid_x11_dgasupported)
Con_Print( "Failed to detect XF86DGA Mouse extension\n" );
{
}
-void signal_handler(int sig)
+static void signal_handler(int sig)
{
Con_Printf("Received signal %d, exiting...\n", sig);
Sys_Quit(1);
}
-void InitSig(void)
+static void InitSig(void)
{
#ifndef WIN32
signal(SIGHUP, signal_handler);
qboolean vid_supportrefreshrate = false;
-#ifdef USE_GLES2
-# define SETVIDEOMODE 0
+#if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
+# define SETVIDEOMODE 1
#else
-# if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
-# define SETVIDEOMODE 1
+# ifdef USE_GLES2
+# define SETVIDEOMODE 0
# else
// LordHavoc: SDL 1.3's SDL_CreateWindow API is not finished enough to use yet, but you can set this to 0 if you want to try it...
-# ifndef SETVIDEOMODE
-# define SETVIDEOMODE 1
+# ifndef SETVIDEOMODE
+# define SETVIDEOMODE 1
+# endif
# endif
# endif
-#endif
static qboolean vid_usingmouse = false;
static qboolean vid_usinghidecursor = false;
int SDL_iPhoneKeyboardToggle(SDL_Window * window); // toggles the visibility of the onscreen keyboard. Returns 0 on success and -1 on error.
#endif
-void VID_ShowKeyboard(qboolean show)
+static void VID_ShowKeyboard(qboolean show)
{
#ifdef __IPHONEOS__
if (show)
#define MAXFINGERS 11
int multitouch[MAXFINGERS][3];
-qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float *resultmove, qboolean *resultbutton, keynum_t key)
+static qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float *resultmove, qboolean *resultbutton, keynum_t key)
{
int finger;
float fx, fy, fwidth, fheight;
////
#ifdef USE_GLES2
+#ifndef qglClear
#ifdef __IPHONEOS__
#include <OpenGLES/ES2/gl.h>
#else
#include <SDL_opengles.h>
#endif
-GLboolean wrapglIsBuffer(GLuint buffer) {return glIsBuffer(buffer);}
-GLboolean wrapglIsEnabled(GLenum cap) {return glIsEnabled(cap);}
-GLboolean wrapglIsFramebuffer(GLuint framebuffer) {return glIsFramebuffer(framebuffer);}
-//GLboolean wrapglIsQuery(GLuint qid) {return glIsQuery(qid);}
-GLboolean wrapglIsRenderbuffer(GLuint renderbuffer) {return glIsRenderbuffer(renderbuffer);}
-//GLboolean wrapglUnmapBuffer(GLenum target) {return glUnmapBuffer(target);}
-GLenum wrapglCheckFramebufferStatus(GLenum target) {return glCheckFramebufferStatus(target);}
-GLenum wrapglGetError(void) {return glGetError();}
-GLuint wrapglCreateProgram(void) {return glCreateProgram();}
-GLuint wrapglCreateShader(GLenum shaderType) {return glCreateShader(shaderType);}
-//GLuint wrapglGetHandle(GLenum pname) {return glGetHandle(pname);}
-GLint wrapglGetAttribLocation(GLuint programObj, const GLchar *name) {return glGetAttribLocation(programObj, name);}
-GLint wrapglGetUniformLocation(GLuint programObj, const GLchar *name) {return glGetUniformLocation(programObj, name);}
-//GLvoid* wrapglMapBuffer(GLenum target, GLenum access) {return glMapBuffer(target, access);}
-const GLubyte* wrapglGetString(GLenum name) {return glGetString(name);}
-void wrapglActiveStencilFace(GLenum e) {Con_Printf("glActiveStencilFace(e)\n");}
-void wrapglActiveTexture(GLenum e) {glActiveTexture(e);}
-void wrapglAlphaFunc(GLenum func, GLclampf ref) {Con_Printf("glAlphaFunc(func, ref)\n");}
-void wrapglArrayElement(GLint i) {Con_Printf("glArrayElement(i)\n");}
-void wrapglAttachShader(GLuint containerObj, GLuint obj) {glAttachShader(containerObj, obj);}
-//void wrapglBegin(GLenum mode) {Con_Printf("glBegin(mode)\n");}
-//void wrapglBeginQuery(GLenum target, GLuint qid) {glBeginQuery(target, qid);}
-void wrapglBindAttribLocation(GLuint programObj, GLuint index, const GLchar *name) {glBindAttribLocation(programObj, index, name);}
-void wrapglBindFragDataLocation(GLuint programObj, GLuint index, const GLchar *name) {glBindFragDataLocation(programObj, index, name);}
-void wrapglBindBuffer(GLenum target, GLuint buffer) {glBindBuffer(target, buffer);}
-void wrapglBindFramebuffer(GLenum target, GLuint framebuffer) {glBindFramebuffer(target, framebuffer);}
-void wrapglBindRenderbuffer(GLenum target, GLuint renderbuffer) {glBindRenderbuffer(target, renderbuffer);}
-void wrapglBindTexture(GLenum target, GLuint texture) {glBindTexture(target, texture);}
-void wrapglBlendEquation(GLenum e) {glBlendEquation(e);}
-void wrapglBlendFunc(GLenum sfactor, GLenum dfactor) {glBlendFunc(sfactor, dfactor);}
-void wrapglBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) {glBufferData(target, size, data, usage);}
-void wrapglBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) {glBufferSubData(target, offset, size, data);}
-void wrapglClear(GLbitfield mask) {glClear(mask);}
-void wrapglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {glClearColor(red, green, blue, alpha);}
-void wrapglClearDepth(GLclampd depth) {glClearDepthf((float)depth);}
-void wrapglClearStencil(GLint s) {glClearStencil(s);}
-void wrapglClientActiveTexture(GLenum target) {Con_Printf("glClientActiveTexture(target)\n");}
-void wrapglColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {Con_Printf("glColor4f(red, green, blue, alpha)\n");}
-void wrapglColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {Con_Printf("glColor4ub(red, green, blue, alpha)\n");}
-void wrapglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {glColorMask(red, green, blue, alpha);}
-void wrapglColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glColorPointer(size, type, stride, ptr)\n");}
-void wrapglCompileShader(GLuint shaderObj) {glCompileShader(shaderObj);}
-void wrapglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);}
-void wrapglCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {Con_Printf("glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data)\n");}
-void wrapglCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);}
-void wrapglCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) {Con_Printf("glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data)\n");}
-void wrapglCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);}
-void wrapglCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);}
-void wrapglCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {Con_Printf("glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height)\n");}
-void wrapglCullFace(GLenum mode) {glCullFace(mode);}
-void wrapglDeleteBuffers(GLsizei n, const GLuint *buffers) {glDeleteBuffers(n, buffers);}
-void wrapglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) {glDeleteFramebuffers(n, framebuffers);}
-void wrapglDeleteShader(GLuint obj) {glDeleteShader(obj);}
-void wrapglDeleteProgram(GLuint obj) {glDeleteProgram(obj);}
-//void wrapglDeleteQueries(GLsizei n, const GLuint *ids) {glDeleteQueries(n, ids);}
-void wrapglDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) {glDeleteRenderbuffers(n, renderbuffers);}
-void wrapglDeleteTextures(GLsizei n, const GLuint *textures) {glDeleteTextures(n, textures);}
-void wrapglDepthFunc(GLenum func) {glDepthFunc(func);}
-void wrapglDepthMask(GLboolean flag) {glDepthMask(flag);}
-void wrapglDepthRange(GLclampd near_val, GLclampd far_val) {glDepthRangef((float)near_val, (float)far_val);}
-void wrapglDetachShader(GLuint containerObj, GLuint attachedObj) {glDetachShader(containerObj, attachedObj);}
-void wrapglDisable(GLenum cap) {glDisable(cap);}
-void wrapglDisableClientState(GLenum cap) {Con_Printf("glDisableClientState(cap)\n");}
-void wrapglDisableVertexAttribArray(GLuint index) {glDisableVertexAttribArray(index);}
-void wrapglDrawArrays(GLenum mode, GLint first, GLsizei count) {glDrawArrays(mode, first, count);}
-void wrapglDrawBuffer(GLenum mode) {Con_Printf("glDrawBuffer(mode)\n");}
-void wrapglDrawBuffers(GLsizei n, const GLenum *bufs) {Con_Printf("glDrawBuffers(n, bufs)\n");}
-void wrapglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {glDrawElements(mode, count, type, indices);}
-//void wrapglDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {glDrawRangeElements(mode, start, end, count, type, indices);}
-//void wrapglDrawRangeElementsEXT(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {glDrawRangeElements(mode, start, end, count, type, indices);}
-void wrapglEnable(GLenum cap) {glEnable(cap);}
-void wrapglEnableClientState(GLenum cap) {Con_Printf("glEnableClientState(cap)\n");}
-void wrapglEnableVertexAttribArray(GLuint index) {glEnableVertexAttribArray(index);}
-//void wrapglEnd(void) {Con_Printf("glEnd()\n");}
-//void wrapglEndQuery(GLenum target) {glEndQuery(target);}
-void wrapglFinish(void) {glFinish();}
-void wrapglFlush(void) {glFlush();}
-void wrapglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);}
-void wrapglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {glFramebufferTexture2D(target, attachment, textarget, texture, level);}
-void wrapglFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {Con_Printf("glFramebufferTexture3D()\n");}
-void wrapglGenBuffers(GLsizei n, GLuint *buffers) {glGenBuffers(n, buffers);}
-void wrapglGenFramebuffers(GLsizei n, GLuint *framebuffers) {glGenFramebuffers(n, framebuffers);}
-//void wrapglGenQueries(GLsizei n, GLuint *ids) {glGenQueries(n, ids);}
-void wrapglGenRenderbuffers(GLsizei n, GLuint *renderbuffers) {glGenRenderbuffers(n, renderbuffers);}
-void wrapglGenTextures(GLsizei n, GLuint *textures) {glGenTextures(n, textures);}
-void wrapglGenerateMipmap(GLenum target) {glGenerateMipmap(target);}
-void wrapglGetActiveAttrib(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {glGetActiveAttrib(programObj, index, maxLength, length, size, type, name);}
-void wrapglGetActiveUniform(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {glGetActiveUniform(programObj, index, maxLength, length, size, type, name);}
-void wrapglGetAttachedShaders(GLuint containerObj, GLsizei maxCount, GLsizei *count, GLuint *obj) {glGetAttachedShaders(containerObj, maxCount, count, obj);}
-void wrapglGetBooleanv(GLenum pname, GLboolean *params) {glGetBooleanv(pname, params);}
-void wrapglGetCompressedTexImage(GLenum target, GLint lod, void *img) {Con_Printf("glGetCompressedTexImage(target, lod, img)\n");}
-void wrapglGetDoublev(GLenum pname, GLdouble *params) {Con_Printf("glGetDoublev(pname, params)\n");}
-void wrapglGetFloatv(GLenum pname, GLfloat *params) {glGetFloatv(pname, params);}
-void wrapglGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params) {glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);}
-void wrapglGetShaderInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {glGetShaderInfoLog(obj, maxLength, length, infoLog);}
-void wrapglGetProgramInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {glGetProgramInfoLog(obj, maxLength, length, infoLog);}
-void wrapglGetIntegerv(GLenum pname, GLint *params) {glGetIntegerv(pname, params);}
-void wrapglGetShaderiv(GLuint obj, GLenum pname, GLint *params) {glGetShaderiv(obj, pname, params);}
-void wrapglGetProgramiv(GLuint obj, GLenum pname, GLint *params) {glGetProgramiv(obj, pname, params);}
-//void wrapglGetQueryObjectiv(GLuint qid, GLenum pname, GLint *params) {glGetQueryObjectiv(qid, pname, params);}
-//void wrapglGetQueryObjectuiv(GLuint qid, GLenum pname, GLuint *params) {glGetQueryObjectuiv(qid, pname, params);}
-//void wrapglGetQueryiv(GLenum target, GLenum pname, GLint *params) {glGetQueryiv(target, pname, params);}
-void wrapglGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) {glGetRenderbufferParameteriv(target, pname, params);}
-void wrapglGetShaderSource(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *source) {glGetShaderSource(obj, maxLength, length, source);}
-void wrapglGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) {Con_Printf("glGetTexImage(target, level, format, type, pixels)\n");}
-void wrapglGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) {Con_Printf("glGetTexLevelParameterfv(target, level, pname, params)\n");}
-void wrapglGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {Con_Printf("glGetTexLevelParameteriv(target, level, pname, params)\n");}
-void wrapglGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {glGetTexParameterfv(target, pname, params);}
-void wrapglGetTexParameteriv(GLenum target, GLenum pname, GLint *params) {glGetTexParameteriv(target, pname, params);}
-void wrapglGetUniformfv(GLuint programObj, GLint location, GLfloat *params) {glGetUniformfv(programObj, location, params);}
-void wrapglGetUniformiv(GLuint programObj, GLint location, GLint *params) {glGetUniformiv(programObj, location, params);}
-void wrapglHint(GLenum target, GLenum mode) {glHint(target, mode);}
-void wrapglLineWidth(GLfloat width) {glLineWidth(width);}
-void wrapglLinkProgram(GLuint programObj) {glLinkProgram(programObj);}
-void wrapglLoadIdentity(void) {Con_Printf("glLoadIdentity()\n");}
-void wrapglLoadMatrixf(const GLfloat *m) {Con_Printf("glLoadMatrixf(m)\n");}
-void wrapglMatrixMode(GLenum mode) {Con_Printf("glMatrixMode(mode)\n");}
-void wrapglMultiTexCoord1f(GLenum target, GLfloat s) {Con_Printf("glMultiTexCoord1f(target, s)\n");}
-void wrapglMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t) {Con_Printf("glMultiTexCoord2f(target, s, t)\n");}
-void wrapglMultiTexCoord3f(GLenum target, GLfloat s, GLfloat t, GLfloat r) {Con_Printf("glMultiTexCoord3f(target, s, t, r)\n");}
-void wrapglMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {Con_Printf("glMultiTexCoord4f(target, s, t, r, q)\n");}
-void wrapglNormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glNormalPointer(type, stride, ptr)\n");}
-void wrapglPixelStorei(GLenum pname, GLint param) {glPixelStorei(pname, param);}
-void wrapglPointSize(GLfloat size) {Con_Printf("glPointSize(size)\n");}
-//void wrapglPolygonMode(GLenum face, GLenum mode) {Con_Printf("glPolygonMode(face, mode)\n");}
-void wrapglPolygonOffset(GLfloat factor, GLfloat units) {glPolygonOffset(factor, units);}
-void wrapglPolygonStipple(const GLubyte *mask) {Con_Printf("glPolygonStipple(mask)\n");}
-void wrapglReadBuffer(GLenum mode) {Con_Printf("glReadBuffer(mode)\n");}
-void wrapglReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {glReadPixels(x, y, width, height, format, type, pixels);}
-void wrapglRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {glRenderbufferStorage(target, internalformat, width, height);}
-void wrapglScissor(GLint x, GLint y, GLsizei width, GLsizei height) {glScissor(x, y, width, height);}
-void wrapglShaderSource(GLuint shaderObj, GLsizei count, const GLchar **string, const GLint *length) {glShaderSource(shaderObj, count, string, length);}
-void wrapglStencilFunc(GLenum func, GLint ref, GLuint mask) {glStencilFunc(func, ref, mask);}
-void wrapglStencilFuncSeparate(GLenum func1, GLenum func2, GLint ref, GLuint mask) {Con_Printf("glStencilFuncSeparate(func1, func2, ref, mask)\n");}
-void wrapglStencilMask(GLuint mask) {glStencilMask(mask);}
-void wrapglStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {glStencilOp(fail, zfail, zpass);}
-void wrapglStencilOpSeparate(GLenum e1, GLenum e2, GLenum e3, GLenum e4) {Con_Printf("glStencilOpSeparate(e1, e2, e3, e4)\n");}
-void wrapglTexCoord1f(GLfloat s) {Con_Printf("glTexCoord1f(s)\n");}
-void wrapglTexCoord2f(GLfloat s, GLfloat t) {Con_Printf("glTexCoord2f(s, t)\n");}
-void wrapglTexCoord3f(GLfloat s, GLfloat t, GLfloat r) {Con_Printf("glTexCoord3f(s, t, r)\n");}
-void wrapglTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) {Con_Printf("glTexCoord4f(s, t, r, q)\n");}
-void wrapglTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glTexCoordPointer(size, type, stride, ptr)\n");}
-void wrapglTexEnvf(GLenum target, GLenum pname, GLfloat param) {Con_Printf("glTexEnvf(target, pname, param)\n");}
-void wrapglTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) {Con_Printf("glTexEnvfv(target, pname, params)\n");}
-void wrapglTexEnvi(GLenum target, GLenum pname, GLint param) {Con_Printf("glTexEnvi(target, pname, param)\n");}
-void wrapglTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels);}
-void wrapglTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {Con_Printf("glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels)\n");}
-void wrapglTexParameterf(GLenum target, GLenum pname, GLfloat param) {glTexParameterf(target, pname, param);}
-void wrapglTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {glTexParameterfv(target, pname, params);}
-void wrapglTexParameteri(GLenum target, GLenum pname, GLint param) {glTexParameteri(target, pname, param);}
-void wrapglTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);}
-void wrapglTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) {Con_Printf("glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels)\n");}
-void wrapglUniform1f(GLint location, GLfloat v0) {glUniform1f(location, v0);}
-void wrapglUniform1fv(GLint location, GLsizei count, const GLfloat *value) {glUniform1fv(location, count, value);}
-void wrapglUniform1i(GLint location, GLint v0) {glUniform1i(location, v0);}
-void wrapglUniform1iv(GLint location, GLsizei count, const GLint *value) {glUniform1iv(location, count, value);}
-void wrapglUniform2f(GLint location, GLfloat v0, GLfloat v1) {glUniform2f(location, v0, v1);}
-void wrapglUniform2fv(GLint location, GLsizei count, const GLfloat *value) {glUniform2fv(location, count, value);}
-void wrapglUniform2i(GLint location, GLint v0, GLint v1) {glUniform2i(location, v0, v1);}
-void wrapglUniform2iv(GLint location, GLsizei count, const GLint *value) {glUniform2iv(location, count, value);}
-void wrapglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {glUniform3f(location, v0, v1, v2);}
-void wrapglUniform3fv(GLint location, GLsizei count, const GLfloat *value) {glUniform3fv(location, count, value);}
-void wrapglUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {glUniform3i(location, v0, v1, v2);}
-void wrapglUniform3iv(GLint location, GLsizei count, const GLint *value) {glUniform3iv(location, count, value);}
-void wrapglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {glUniform4f(location, v0, v1, v2, v3);}
-void wrapglUniform4fv(GLint location, GLsizei count, const GLfloat *value) {glUniform4fv(location, count, value);}
-void wrapglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {glUniform4i(location, v0, v1, v2, v3);}
-void wrapglUniform4iv(GLint location, GLsizei count, const GLint *value) {glUniform4iv(location, count, value);}
-void wrapglUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {glUniformMatrix2fv(location, count, transpose, value);}
-void wrapglUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {glUniformMatrix3fv(location, count, transpose, value);}
-void wrapglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {glUniformMatrix4fv(location, count, transpose, value);}
-void wrapglUseProgram(GLuint programObj) {glUseProgram(programObj);}
-void wrapglValidateProgram(GLuint programObj) {glValidateProgram(programObj);}
-void wrapglVertex2f(GLfloat x, GLfloat y) {Con_Printf("glVertex2f(x, y)\n");}
-void wrapglVertex3f(GLfloat x, GLfloat y, GLfloat z) {Con_Printf("glVertex3f(x, y, z)\n");}
-void wrapglVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {Con_Printf("glVertex4f(x, y, z, w)\n");}
-void wrapglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) {glVertexAttribPointer(index, size, type, normalized, stride, pointer);}
-void wrapglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {Con_Printf("glVertexPointer(size, type, stride, ptr)\n");}
-void wrapglViewport(GLint x, GLint y, GLsizei width, GLsizei height) {glViewport(x, y, width, height);}
-void wrapglVertexAttrib1f(GLuint index, GLfloat v0) {glVertexAttrib1f(index, v0);}
-//void wrapglVertexAttrib1s(GLuint index, GLshort v0) {glVertexAttrib1s(index, v0);}
-//void wrapglVertexAttrib1d(GLuint index, GLdouble v0) {glVertexAttrib1d(index, v0);}
-void wrapglVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {glVertexAttrib2f(index, v0, v1);}
-//void wrapglVertexAttrib2s(GLuint index, GLshort v0, GLshort v1) {glVertexAttrib2s(index, v0, v1);}
-//void wrapglVertexAttrib2d(GLuint index, GLdouble v0, GLdouble v1) {glVertexAttrib2d(index, v0, v1);}
-void wrapglVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {glVertexAttrib3f(index, v0, v1, v2);}
-//void wrapglVertexAttrib3s(GLuint index, GLshort v0, GLshort v1, GLshort v2) {glVertexAttrib3s(index, v0, v1, v2);}
-//void wrapglVertexAttrib3d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2) {glVertexAttrib3d(index, v0, v1, v2);}
-void wrapglVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {glVertexAttrib4f(index, v0, v1, v2, v3);}
-//void wrapglVertexAttrib4s(GLuint index, GLshort v0, GLshort v1, GLshort v2, GLshort v3) {glVertexAttrib4s(index, v0, v1, v2, v3);}
-//void wrapglVertexAttrib4d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) {glVertexAttrib4d(index, v0, v1, v2, v3);}
-//void wrapglVertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {glVertexAttrib4Nub(index, x, y, z, w);}
-void wrapglVertexAttrib1fv(GLuint index, const GLfloat *v) {glVertexAttrib1fv(index, v);}
-//void wrapglVertexAttrib1sv(GLuint index, const GLshort *v) {glVertexAttrib1sv(index, v);}
-//void wrapglVertexAttrib1dv(GLuint index, const GLdouble *v) {glVertexAttrib1dv(index, v);}
-void wrapglVertexAttrib2fv(GLuint index, const GLfloat *v) {glVertexAttrib2fv(index, v);}
-//void wrapglVertexAttrib2sv(GLuint index, const GLshort *v) {glVertexAttrib2sv(index, v);}
-//void wrapglVertexAttrib2dv(GLuint index, const GLdouble *v) {glVertexAttrib2dv(index, v);}
-void wrapglVertexAttrib3fv(GLuint index, const GLfloat *v) {glVertexAttrib3fv(index, v);}
-//void wrapglVertexAttrib3sv(GLuint index, const GLshort *v) {glVertexAttrib3sv(index, v);}
-//void wrapglVertexAttrib3dv(GLuint index, const GLdouble *v) {glVertexAttrib3dv(index, v);}
-void wrapglVertexAttrib4fv(GLuint index, const GLfloat *v) {glVertexAttrib4fv(index, v);}
-//void wrapglVertexAttrib4sv(GLuint index, const GLshort *v) {glVertexAttrib4sv(index, v);}
-//void wrapglVertexAttrib4dv(GLuint index, const GLdouble *v) {glVertexAttrib4dv(index, v);}
-//void wrapglVertexAttrib4iv(GLuint index, const GLint *v) {glVertexAttrib4iv(index, v);}
-//void wrapglVertexAttrib4bv(GLuint index, const GLbyte *v) {glVertexAttrib4bv(index, v);}
-//void wrapglVertexAttrib4ubv(GLuint index, const GLubyte *v) {glVertexAttrib4ubv(index, v);}
-//void wrapglVertexAttrib4usv(GLuint index, const GLushort *v) {glVertexAttrib4usv(index, GLushort v);}
-//void wrapglVertexAttrib4uiv(GLuint index, const GLuint *v) {glVertexAttrib4uiv(index, v);}
-//void wrapglVertexAttrib4Nbv(GLuint index, const GLbyte *v) {glVertexAttrib4Nbv(index, v);}
-//void wrapglVertexAttrib4Nsv(GLuint index, const GLshort *v) {glVertexAttrib4Nsv(index, v);}
-//void wrapglVertexAttrib4Niv(GLuint index, const GLint *v) {glVertexAttrib4Niv(index, v);}
-//void wrapglVertexAttrib4Nubv(GLuint index, const GLubyte *v) {glVertexAttrib4Nubv(index, v);}
-//void wrapglVertexAttrib4Nusv(GLuint index, const GLushort *v) {glVertexAttrib4Nusv(index, GLushort v);}
-//void wrapglVertexAttrib4Nuiv(GLuint index, const GLuint *v) {glVertexAttrib4Nuiv(index, v);}
-//void wrapglGetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) {glGetVertexAttribdv(index, pname, params);}
-void wrapglGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) {glGetVertexAttribfv(index, pname, params);}
-void wrapglGetVertexAttribiv(GLuint index, GLenum pname, GLint *params) {glGetVertexAttribiv(index, pname, params);}
-void wrapglGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) {glGetVertexAttribPointerv(index, pname, pointer);}
+//#define PRECALL //Con_Printf("GLCALL %s:%i\n", __FILE__, __LINE__)
+#define PRECALL
+#define POSTCALL
+GLboolean wrapglIsBuffer(GLuint buffer) {PRECALL;return glIsBuffer(buffer);POSTCALL;}
+GLboolean wrapglIsEnabled(GLenum cap) {PRECALL;return glIsEnabled(cap);POSTCALL;}
+GLboolean wrapglIsFramebuffer(GLuint framebuffer) {PRECALL;return glIsFramebuffer(framebuffer);POSTCALL;}
+//GLboolean wrapglIsQuery(GLuint qid) {PRECALL;return glIsQuery(qid);POSTCALL;}
+GLboolean wrapglIsRenderbuffer(GLuint renderbuffer) {PRECALL;return glIsRenderbuffer(renderbuffer);POSTCALL;}
+//GLboolean wrapglUnmapBuffer(GLenum target) {PRECALL;return glUnmapBuffer(target);POSTCALL;}
+GLenum wrapglCheckFramebufferStatus(GLenum target) {PRECALL;return glCheckFramebufferStatus(target);POSTCALL;}
+GLenum wrapglGetError(void) {PRECALL;return glGetError();POSTCALL;}
+GLuint wrapglCreateProgram(void) {PRECALL;return glCreateProgram();POSTCALL;}
+GLuint wrapglCreateShader(GLenum shaderType) {PRECALL;return glCreateShader(shaderType);POSTCALL;}
+//GLuint wrapglGetHandle(GLenum pname) {PRECALL;return glGetHandle(pname);POSTCALL;}
+GLint wrapglGetAttribLocation(GLuint programObj, const GLchar *name) {PRECALL;return glGetAttribLocation(programObj, name);POSTCALL;}
+GLint wrapglGetUniformLocation(GLuint programObj, const GLchar *name) {PRECALL;return glGetUniformLocation(programObj, name);POSTCALL;}
+//GLvoid* wrapglMapBuffer(GLenum target, GLenum access) {PRECALL;return glMapBuffer(target, access);POSTCALL;}
+const GLubyte* wrapglGetString(GLenum name) {PRECALL;return (const GLubyte*)glGetString(name);POSTCALL;}
+void wrapglActiveStencilFace(GLenum e) {PRECALL;Con_Printf("glActiveStencilFace(e)\n");POSTCALL;}
+void wrapglActiveTexture(GLenum e) {PRECALL;glActiveTexture(e);POSTCALL;}
+void wrapglAlphaFunc(GLenum func, GLclampf ref) {PRECALL;Con_Printf("glAlphaFunc(func, ref)\n");POSTCALL;}
+void wrapglArrayElement(GLint i) {PRECALL;Con_Printf("glArrayElement(i)\n");POSTCALL;}
+void wrapglAttachShader(GLuint containerObj, GLuint obj) {PRECALL;glAttachShader(containerObj, obj);POSTCALL;}
+//void wrapglBegin(GLenum mode) {PRECALL;Con_Printf("glBegin(mode)\n");POSTCALL;}
+//void wrapglBeginQuery(GLenum target, GLuint qid) {PRECALL;glBeginQuery(target, qid);POSTCALL;}
+void wrapglBindAttribLocation(GLuint programObj, GLuint index, const GLchar *name) {PRECALL;glBindAttribLocation(programObj, index, name);POSTCALL;}
+//void wrapglBindFragDataLocation(GLuint programObj, GLuint index, const GLchar *name) {PRECALL;glBindFragDataLocation(programObj, index, name);POSTCALL;}
+void wrapglBindBuffer(GLenum target, GLuint buffer) {PRECALL;glBindBuffer(target, buffer);POSTCALL;}
+void wrapglBindFramebuffer(GLenum target, GLuint framebuffer) {PRECALL;glBindFramebuffer(target, framebuffer);POSTCALL;}
+void wrapglBindRenderbuffer(GLenum target, GLuint renderbuffer) {PRECALL;glBindRenderbuffer(target, renderbuffer);POSTCALL;}
+void wrapglBindTexture(GLenum target, GLuint texture) {PRECALL;glBindTexture(target, texture);POSTCALL;}
+void wrapglBlendEquation(GLenum e) {PRECALL;glBlendEquation(e);POSTCALL;}
+void wrapglBlendFunc(GLenum sfactor, GLenum dfactor) {PRECALL;glBlendFunc(sfactor, dfactor);POSTCALL;}
+void wrapglBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) {PRECALL;glBufferData(target, size, data, usage);POSTCALL;}
+void wrapglBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) {PRECALL;glBufferSubData(target, offset, size, data);POSTCALL;}
+void wrapglClear(GLbitfield mask) {PRECALL;glClear(mask);POSTCALL;}
+void wrapglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {PRECALL;glClearColor(red, green, blue, alpha);POSTCALL;}
+void wrapglClearDepth(GLclampd depth) {PRECALL;/*Con_Printf("glClearDepth(%f)\n", depth);glClearDepthf((float)depth);*/POSTCALL;}
+void wrapglClearStencil(GLint s) {PRECALL;glClearStencil(s);POSTCALL;}
+void wrapglClientActiveTexture(GLenum target) {PRECALL;Con_Printf("glClientActiveTexture(target)\n");POSTCALL;}
+void wrapglColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {PRECALL;Con_Printf("glColor4f(red, green, blue, alpha)\n");POSTCALL;}
+void wrapglColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {PRECALL;Con_Printf("glColor4ub(red, green, blue, alpha)\n");POSTCALL;}
+void wrapglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {PRECALL;glColorMask(red, green, blue, alpha);POSTCALL;}
+void wrapglColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {PRECALL;Con_Printf("glColorPointer(size, type, stride, ptr)\n");POSTCALL;}
+void wrapglCompileShader(GLuint shaderObj) {PRECALL;glCompileShader(shaderObj);POSTCALL;}
+void wrapglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {PRECALL;glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);POSTCALL;}
+void wrapglCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {PRECALL;Con_Printf("glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data)\n");POSTCALL;}
+void wrapglCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {PRECALL;glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);POSTCALL;}
+void wrapglCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) {PRECALL;Con_Printf("glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data)\n");POSTCALL;}
+void wrapglCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {PRECALL;glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);POSTCALL;}
+void wrapglCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);POSTCALL;}
+void wrapglCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;Con_Printf("glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height)\n");POSTCALL;}
+void wrapglCullFace(GLenum mode) {PRECALL;glCullFace(mode);POSTCALL;}
+void wrapglDeleteBuffers(GLsizei n, const GLuint *buffers) {PRECALL;glDeleteBuffers(n, buffers);POSTCALL;}
+void wrapglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) {PRECALL;glDeleteFramebuffers(n, framebuffers);POSTCALL;}
+void wrapglDeleteShader(GLuint obj) {PRECALL;glDeleteShader(obj);POSTCALL;}
+void wrapglDeleteProgram(GLuint obj) {PRECALL;glDeleteProgram(obj);POSTCALL;}
+//void wrapglDeleteQueries(GLsizei n, const GLuint *ids) {PRECALL;glDeleteQueries(n, ids);POSTCALL;}
+void wrapglDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) {PRECALL;glDeleteRenderbuffers(n, renderbuffers);POSTCALL;}
+void wrapglDeleteTextures(GLsizei n, const GLuint *textures) {PRECALL;glDeleteTextures(n, textures);POSTCALL;}
+void wrapglDepthFunc(GLenum func) {PRECALL;glDepthFunc(func);POSTCALL;}
+void wrapglDepthMask(GLboolean flag) {PRECALL;glDepthMask(flag);POSTCALL;}
+//void wrapglDepthRange(GLclampd near_val, GLclampd far_val) {PRECALL;glDepthRangef((float)near_val, (float)far_val);POSTCALL;}
+void wrapglDepthRangef(GLclampf near_val, GLclampf far_val) {PRECALL;glDepthRangef(near_val, far_val);POSTCALL;}
+void wrapglDetachShader(GLuint containerObj, GLuint attachedObj) {PRECALL;glDetachShader(containerObj, attachedObj);POSTCALL;}
+void wrapglDisable(GLenum cap) {PRECALL;glDisable(cap);POSTCALL;}
+void wrapglDisableClientState(GLenum cap) {PRECALL;Con_Printf("glDisableClientState(cap)\n");POSTCALL;}
+void wrapglDisableVertexAttribArray(GLuint index) {PRECALL;glDisableVertexAttribArray(index);POSTCALL;}
+void wrapglDrawArrays(GLenum mode, GLint first, GLsizei count) {PRECALL;glDrawArrays(mode, first, count);POSTCALL;}
+void wrapglDrawBuffer(GLenum mode) {PRECALL;Con_Printf("glDrawBuffer(mode)\n");POSTCALL;}
+void wrapglDrawBuffers(GLsizei n, const GLenum *bufs) {PRECALL;Con_Printf("glDrawBuffers(n, bufs)\n");POSTCALL;}
+void wrapglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {PRECALL;glDrawElements(mode, count, type, indices);POSTCALL;}
+//void wrapglDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {PRECALL;glDrawRangeElements(mode, start, end, count, type, indices);POSTCALL;}
+//void wrapglDrawRangeElementsEXT(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) {PRECALL;glDrawRangeElements(mode, start, end, count, type, indices);POSTCALL;}
+void wrapglEnable(GLenum cap) {PRECALL;glEnable(cap);POSTCALL;}
+void wrapglEnableClientState(GLenum cap) {PRECALL;Con_Printf("glEnableClientState(cap)\n");POSTCALL;}
+void wrapglEnableVertexAttribArray(GLuint index) {PRECALL;glEnableVertexAttribArray(index);POSTCALL;}
+//void wrapglEnd(void) {PRECALL;Con_Printf("glEnd()\n");POSTCALL;}
+//void wrapglEndQuery(GLenum target) {PRECALL;glEndQuery(target);POSTCALL;}
+void wrapglFinish(void) {PRECALL;glFinish();POSTCALL;}
+void wrapglFlush(void) {PRECALL;glFlush();POSTCALL;}
+void wrapglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {PRECALL;glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);POSTCALL;}
+void wrapglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {PRECALL;glFramebufferTexture2D(target, attachment, textarget, texture, level);POSTCALL;}
+void wrapglFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {PRECALL;Con_Printf("glFramebufferTexture3D()\n");POSTCALL;}
+void wrapglGenBuffers(GLsizei n, GLuint *buffers) {PRECALL;glGenBuffers(n, buffers);POSTCALL;}
+void wrapglGenFramebuffers(GLsizei n, GLuint *framebuffers) {PRECALL;glGenFramebuffers(n, framebuffers);POSTCALL;}
+//void wrapglGenQueries(GLsizei n, GLuint *ids) {PRECALL;glGenQueries(n, ids);POSTCALL;}
+void wrapglGenRenderbuffers(GLsizei n, GLuint *renderbuffers) {PRECALL;glGenRenderbuffers(n, renderbuffers);POSTCALL;}
+void wrapglGenTextures(GLsizei n, GLuint *textures) {PRECALL;glGenTextures(n, textures);POSTCALL;}
+void wrapglGenerateMipmap(GLenum target) {PRECALL;glGenerateMipmap(target);POSTCALL;}
+void wrapglGetActiveAttrib(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {PRECALL;glGetActiveAttrib(programObj, index, maxLength, length, size, type, name);POSTCALL;}
+void wrapglGetActiveUniform(GLuint programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {PRECALL;glGetActiveUniform(programObj, index, maxLength, length, size, type, name);POSTCALL;}
+void wrapglGetAttachedShaders(GLuint containerObj, GLsizei maxCount, GLsizei *count, GLuint *obj) {PRECALL;glGetAttachedShaders(containerObj, maxCount, count, obj);POSTCALL;}
+void wrapglGetBooleanv(GLenum pname, GLboolean *params) {PRECALL;glGetBooleanv(pname, params);POSTCALL;}
+void wrapglGetCompressedTexImage(GLenum target, GLint lod, void *img) {PRECALL;Con_Printf("glGetCompressedTexImage(target, lod, img)\n");POSTCALL;}
+void wrapglGetDoublev(GLenum pname, GLdouble *params) {PRECALL;Con_Printf("glGetDoublev(pname, params)\n");POSTCALL;}
+void wrapglGetFloatv(GLenum pname, GLfloat *params) {PRECALL;glGetFloatv(pname, params);POSTCALL;}
+void wrapglGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params) {PRECALL;glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);POSTCALL;}
+void wrapglGetShaderInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {PRECALL;glGetShaderInfoLog(obj, maxLength, length, infoLog);POSTCALL;}
+void wrapglGetProgramInfoLog(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {PRECALL;glGetProgramInfoLog(obj, maxLength, length, infoLog);POSTCALL;}
+void wrapglGetIntegerv(GLenum pname, GLint *params) {PRECALL;glGetIntegerv(pname, params);POSTCALL;}
+void wrapglGetShaderiv(GLuint obj, GLenum pname, GLint *params) {PRECALL;glGetShaderiv(obj, pname, params);POSTCALL;}
+void wrapglGetProgramiv(GLuint obj, GLenum pname, GLint *params) {PRECALL;glGetProgramiv(obj, pname, params);POSTCALL;}
+//void wrapglGetQueryObjectiv(GLuint qid, GLenum pname, GLint *params) {PRECALL;glGetQueryObjectiv(qid, pname, params);POSTCALL;}
+//void wrapglGetQueryObjectuiv(GLuint qid, GLenum pname, GLuint *params) {PRECALL;glGetQueryObjectuiv(qid, pname, params);POSTCALL;}
+//void wrapglGetQueryiv(GLenum target, GLenum pname, GLint *params) {PRECALL;glGetQueryiv(target, pname, params);POSTCALL;}
+void wrapglGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params) {PRECALL;glGetRenderbufferParameteriv(target, pname, params);POSTCALL;}
+void wrapglGetShaderSource(GLuint obj, GLsizei maxLength, GLsizei *length, GLchar *source) {PRECALL;glGetShaderSource(obj, maxLength, length, source);POSTCALL;}
+void wrapglGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) {PRECALL;Con_Printf("glGetTexImage(target, level, format, type, pixels)\n");POSTCALL;}
+void wrapglGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) {PRECALL;Con_Printf("glGetTexLevelParameterfv(target, level, pname, params)\n");POSTCALL;}
+void wrapglGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {PRECALL;Con_Printf("glGetTexLevelParameteriv(target, level, pname, params)\n");POSTCALL;}
+void wrapglGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {PRECALL;glGetTexParameterfv(target, pname, params);POSTCALL;}
+void wrapglGetTexParameteriv(GLenum target, GLenum pname, GLint *params) {PRECALL;glGetTexParameteriv(target, pname, params);POSTCALL;}
+void wrapglGetUniformfv(GLuint programObj, GLint location, GLfloat *params) {PRECALL;glGetUniformfv(programObj, location, params);POSTCALL;}
+void wrapglGetUniformiv(GLuint programObj, GLint location, GLint *params) {PRECALL;glGetUniformiv(programObj, location, params);POSTCALL;}
+void wrapglHint(GLenum target, GLenum mode) {PRECALL;glHint(target, mode);POSTCALL;}
+void wrapglLineWidth(GLfloat width) {PRECALL;glLineWidth(width);POSTCALL;}
+void wrapglLinkProgram(GLuint programObj) {PRECALL;glLinkProgram(programObj);POSTCALL;}
+void wrapglLoadIdentity(void) {PRECALL;Con_Printf("glLoadIdentity()\n");POSTCALL;}
+void wrapglLoadMatrixf(const GLfloat *m) {PRECALL;Con_Printf("glLoadMatrixf(m)\n");POSTCALL;}
+void wrapglMatrixMode(GLenum mode) {PRECALL;Con_Printf("glMatrixMode(mode)\n");POSTCALL;}
+void wrapglMultiTexCoord1f(GLenum target, GLfloat s) {PRECALL;Con_Printf("glMultiTexCoord1f(target, s)\n");POSTCALL;}
+void wrapglMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t) {PRECALL;Con_Printf("glMultiTexCoord2f(target, s, t)\n");POSTCALL;}
+void wrapglMultiTexCoord3f(GLenum target, GLfloat s, GLfloat t, GLfloat r) {PRECALL;Con_Printf("glMultiTexCoord3f(target, s, t, r)\n");POSTCALL;}
+void wrapglMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {PRECALL;Con_Printf("glMultiTexCoord4f(target, s, t, r, q)\n");POSTCALL;}
+void wrapglNormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr) {PRECALL;Con_Printf("glNormalPointer(type, stride, ptr)\n");POSTCALL;}
+void wrapglPixelStorei(GLenum pname, GLint param) {PRECALL;glPixelStorei(pname, param);POSTCALL;}
+void wrapglPointSize(GLfloat size) {PRECALL;Con_Printf("glPointSize(size)\n");POSTCALL;}
+//void wrapglPolygonMode(GLenum face, GLenum mode) {PRECALL;Con_Printf("glPolygonMode(face, mode)\n");POSTCALL;}
+void wrapglPolygonOffset(GLfloat factor, GLfloat units) {PRECALL;glPolygonOffset(factor, units);POSTCALL;}
+void wrapglPolygonStipple(const GLubyte *mask) {PRECALL;Con_Printf("glPolygonStipple(mask)\n");POSTCALL;}
+void wrapglReadBuffer(GLenum mode) {PRECALL;Con_Printf("glReadBuffer(mode)\n");POSTCALL;}
+void wrapglReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {PRECALL;glReadPixels(x, y, width, height, format, type, pixels);POSTCALL;}
+void wrapglRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {PRECALL;glRenderbufferStorage(target, internalformat, width, height);POSTCALL;}
+void wrapglScissor(GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;glScissor(x, y, width, height);POSTCALL;}
+void wrapglShaderSource(GLuint shaderObj, GLsizei count, const GLchar **string, const GLint *length) {PRECALL;glShaderSource(shaderObj, count, string, length);POSTCALL;}
+void wrapglStencilFunc(GLenum func, GLint ref, GLuint mask) {PRECALL;glStencilFunc(func, ref, mask);POSTCALL;}
+void wrapglStencilFuncSeparate(GLenum func1, GLenum func2, GLint ref, GLuint mask) {PRECALL;Con_Printf("glStencilFuncSeparate(func1, func2, ref, mask)\n");POSTCALL;}
+void wrapglStencilMask(GLuint mask) {PRECALL;glStencilMask(mask);POSTCALL;}
+void wrapglStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {PRECALL;glStencilOp(fail, zfail, zpass);POSTCALL;}
+void wrapglStencilOpSeparate(GLenum e1, GLenum e2, GLenum e3, GLenum e4) {PRECALL;Con_Printf("glStencilOpSeparate(e1, e2, e3, e4)\n");POSTCALL;}
+void wrapglTexCoord1f(GLfloat s) {PRECALL;Con_Printf("glTexCoord1f(s)\n");POSTCALL;}
+void wrapglTexCoord2f(GLfloat s, GLfloat t) {PRECALL;Con_Printf("glTexCoord2f(s, t)\n");POSTCALL;}
+void wrapglTexCoord3f(GLfloat s, GLfloat t, GLfloat r) {PRECALL;Con_Printf("glTexCoord3f(s, t, r)\n");POSTCALL;}
+void wrapglTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) {PRECALL;Con_Printf("glTexCoord4f(s, t, r, q)\n");POSTCALL;}
+void wrapglTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {PRECALL;Con_Printf("glTexCoordPointer(size, type, stride, ptr)\n");POSTCALL;}
+void wrapglTexEnvf(GLenum target, GLenum pname, GLfloat param) {PRECALL;Con_Printf("glTexEnvf(target, pname, param)\n");POSTCALL;}
+void wrapglTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) {PRECALL;Con_Printf("glTexEnvfv(target, pname, params)\n");POSTCALL;}
+void wrapglTexEnvi(GLenum target, GLenum pname, GLint param) {PRECALL;Con_Printf("glTexEnvi(target, pname, param)\n");POSTCALL;}
+void wrapglTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels);POSTCALL;}
+void wrapglTexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;Con_Printf("glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels)\n");POSTCALL;}
+void wrapglTexParameterf(GLenum target, GLenum pname, GLfloat param) {PRECALL;glTexParameterf(target, pname, param);POSTCALL;}
+void wrapglTexParameterfv(GLenum target, GLenum pname, GLfloat *params) {PRECALL;glTexParameterfv(target, pname, params);POSTCALL;}
+void wrapglTexParameteri(GLenum target, GLenum pname, GLint param) {PRECALL;glTexParameteri(target, pname, param);POSTCALL;}
+void wrapglTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);POSTCALL;}
+void wrapglTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) {PRECALL;Con_Printf("glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels)\n");POSTCALL;}
+void wrapglUniform1f(GLint location, GLfloat v0) {PRECALL;glUniform1f(location, v0);POSTCALL;}
+void wrapglUniform1fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform1fv(location, count, value);POSTCALL;}
+void wrapglUniform1i(GLint location, GLint v0) {PRECALL;glUniform1i(location, v0);POSTCALL;}
+void wrapglUniform1iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform1iv(location, count, value);POSTCALL;}
+void wrapglUniform2f(GLint location, GLfloat v0, GLfloat v1) {PRECALL;glUniform2f(location, v0, v1);POSTCALL;}
+void wrapglUniform2fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform2fv(location, count, value);POSTCALL;}
+void wrapglUniform2i(GLint location, GLint v0, GLint v1) {PRECALL;glUniform2i(location, v0, v1);POSTCALL;}
+void wrapglUniform2iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform2iv(location, count, value);POSTCALL;}
+void wrapglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {PRECALL;glUniform3f(location, v0, v1, v2);POSTCALL;}
+void wrapglUniform3fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform3fv(location, count, value);POSTCALL;}
+void wrapglUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {PRECALL;glUniform3i(location, v0, v1, v2);POSTCALL;}
+void wrapglUniform3iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform3iv(location, count, value);POSTCALL;}
+void wrapglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {PRECALL;glUniform4f(location, v0, v1, v2, v3);POSTCALL;}
+void wrapglUniform4fv(GLint location, GLsizei count, const GLfloat *value) {PRECALL;glUniform4fv(location, count, value);POSTCALL;}
+void wrapglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {PRECALL;glUniform4i(location, v0, v1, v2, v3);POSTCALL;}
+void wrapglUniform4iv(GLint location, GLsizei count, const GLint *value) {PRECALL;glUniform4iv(location, count, value);POSTCALL;}
+void wrapglUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {PRECALL;glUniformMatrix2fv(location, count, transpose, value);POSTCALL;}
+void wrapglUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {PRECALL;glUniformMatrix3fv(location, count, transpose, value);POSTCALL;}
+void wrapglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {PRECALL;glUniformMatrix4fv(location, count, transpose, value);POSTCALL;}
+void wrapglUseProgram(GLuint programObj) {PRECALL;glUseProgram(programObj);POSTCALL;}
+void wrapglValidateProgram(GLuint programObj) {PRECALL;glValidateProgram(programObj);POSTCALL;}
+void wrapglVertex2f(GLfloat x, GLfloat y) {PRECALL;Con_Printf("glVertex2f(x, y)\n");POSTCALL;}
+void wrapglVertex3f(GLfloat x, GLfloat y, GLfloat z) {PRECALL;Con_Printf("glVertex3f(x, y, z)\n");POSTCALL;}
+void wrapglVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {PRECALL;Con_Printf("glVertex4f(x, y, z, w)\n");POSTCALL;}
+void wrapglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) {PRECALL;glVertexAttribPointer(index, size, type, normalized, stride, pointer);POSTCALL;}
+void wrapglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) {PRECALL;Con_Printf("glVertexPointer(size, type, stride, ptr)\n");POSTCALL;}
+void wrapglViewport(GLint x, GLint y, GLsizei width, GLsizei height) {PRECALL;glViewport(x, y, width, height);POSTCALL;}
+void wrapglVertexAttrib1f(GLuint index, GLfloat v0) {PRECALL;glVertexAttrib1f(index, v0);POSTCALL;}
+//void wrapglVertexAttrib1s(GLuint index, GLshort v0) {PRECALL;glVertexAttrib1s(index, v0);POSTCALL;}
+//void wrapglVertexAttrib1d(GLuint index, GLdouble v0) {PRECALL;glVertexAttrib1d(index, v0);POSTCALL;}
+void wrapglVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {PRECALL;glVertexAttrib2f(index, v0, v1);POSTCALL;}
+//void wrapglVertexAttrib2s(GLuint index, GLshort v0, GLshort v1) {PRECALL;glVertexAttrib2s(index, v0, v1);POSTCALL;}
+//void wrapglVertexAttrib2d(GLuint index, GLdouble v0, GLdouble v1) {PRECALL;glVertexAttrib2d(index, v0, v1);POSTCALL;}
+void wrapglVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {PRECALL;glVertexAttrib3f(index, v0, v1, v2);POSTCALL;}
+//void wrapglVertexAttrib3s(GLuint index, GLshort v0, GLshort v1, GLshort v2) {PRECALL;glVertexAttrib3s(index, v0, v1, v2);POSTCALL;}
+//void wrapglVertexAttrib3d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2) {PRECALL;glVertexAttrib3d(index, v0, v1, v2);POSTCALL;}
+void wrapglVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {PRECALL;glVertexAttrib4f(index, v0, v1, v2, v3);POSTCALL;}
+//void wrapglVertexAttrib4s(GLuint index, GLshort v0, GLshort v1, GLshort v2, GLshort v3) {PRECALL;glVertexAttrib4s(index, v0, v1, v2, v3);POSTCALL;}
+//void wrapglVertexAttrib4d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) {PRECALL;glVertexAttrib4d(index, v0, v1, v2, v3);POSTCALL;}
+//void wrapglVertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) {PRECALL;glVertexAttrib4Nub(index, x, y, z, w);POSTCALL;}
+void wrapglVertexAttrib1fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib1fv(index, v);POSTCALL;}
+//void wrapglVertexAttrib1sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib1sv(index, v);POSTCALL;}
+//void wrapglVertexAttrib1dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib1dv(index, v);POSTCALL;}
+void wrapglVertexAttrib2fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib2fv(index, v);POSTCALL;}
+//void wrapglVertexAttrib2sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib2sv(index, v);POSTCALL;}
+//void wrapglVertexAttrib2dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib2dv(index, v);POSTCALL;}
+void wrapglVertexAttrib3fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib3fv(index, v);POSTCALL;}
+//void wrapglVertexAttrib3sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib3sv(index, v);POSTCALL;}
+//void wrapglVertexAttrib3dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib3dv(index, v);POSTCALL;}
+void wrapglVertexAttrib4fv(GLuint index, const GLfloat *v) {PRECALL;glVertexAttrib4fv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4sv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib4sv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4dv(GLuint index, const GLdouble *v) {PRECALL;glVertexAttrib4dv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4iv(GLuint index, const GLint *v) {PRECALL;glVertexAttrib4iv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4bv(GLuint index, const GLbyte *v) {PRECALL;glVertexAttrib4bv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4ubv(GLuint index, const GLubyte *v) {PRECALL;glVertexAttrib4ubv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4usv(GLuint index, const GLushort *v) {PRECALL;glVertexAttrib4usv(index, GLushort v);POSTCALL;}
+//void wrapglVertexAttrib4uiv(GLuint index, const GLuint *v) {PRECALL;glVertexAttrib4uiv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4Nbv(GLuint index, const GLbyte *v) {PRECALL;glVertexAttrib4Nbv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4Nsv(GLuint index, const GLshort *v) {PRECALL;glVertexAttrib4Nsv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4Niv(GLuint index, const GLint *v) {PRECALL;glVertexAttrib4Niv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4Nubv(GLuint index, const GLubyte *v) {PRECALL;glVertexAttrib4Nubv(index, v);POSTCALL;}
+//void wrapglVertexAttrib4Nusv(GLuint index, const GLushort *v) {PRECALL;glVertexAttrib4Nusv(index, GLushort v);POSTCALL;}
+//void wrapglVertexAttrib4Nuiv(GLuint index, const GLuint *v) {PRECALL;glVertexAttrib4Nuiv(index, v);POSTCALL;}
+//void wrapglGetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) {PRECALL;glGetVertexAttribdv(index, pname, params);POSTCALL;}
+void wrapglGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) {PRECALL;glGetVertexAttribfv(index, pname, params);POSTCALL;}
+void wrapglGetVertexAttribiv(GLuint index, GLenum pname, GLint *params) {PRECALL;glGetVertexAttribiv(index, pname, params);POSTCALL;}
+void wrapglGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) {PRECALL;glGetVertexAttribPointerv(index, pname, pointer);POSTCALL;}
+#endif
+
+#if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2
+#define SDL_GL_ExtensionSupported(x) (strstr(gl_extensions, x) || strstr(gl_platformextensions, x))
+#endif
void GLES_Init(void)
{
+#ifndef qglClear
qglIsBufferARB = wrapglIsBuffer;
qglIsEnabled = wrapglIsEnabled;
qglIsFramebufferEXT = wrapglIsFramebuffer;
// qglBegin = wrapglBegin;
// qglBeginQueryARB = wrapglBeginQuery;
qglBindAttribLocation = wrapglBindAttribLocation;
- qglBindFragDataLocation = wrapglBindFragDataLocation;
+// qglBindFragDataLocation = wrapglBindFragDataLocation;
qglBindBufferARB = wrapglBindBuffer;
qglBindFramebufferEXT = wrapglBindFramebuffer;
qglBindRenderbufferEXT = wrapglBindRenderbuffer;
qglDeleteTextures = wrapglDeleteTextures;
qglDepthFunc = wrapglDepthFunc;
qglDepthMask = wrapglDepthMask;
- qglDepthRange = wrapglDepthRange;
+ qglDepthRangef = wrapglDepthRangef;
qglDetachShader = wrapglDetachShader;
qglDisable = wrapglDisable;
qglDisableClientState = wrapglDisableClientState;
qglGetVertexAttribfv = wrapglGetVertexAttribfv;
qglGetVertexAttribiv = wrapglGetVertexAttribiv;
qglGetVertexAttribPointerv = wrapglGetVertexAttribPointerv;
+#endif
gl_renderer = (const char *)qglGetString(GL_RENDERER);
gl_vendor = (const char *)qglGetString(GL_VENDOR);
vid.support.ext_blend_subtract = true;
vid.support.ext_draw_range_elements = true;
vid.support.ext_framebuffer_object = false;//true;
+ vid.support.ext_packed_depth_stencil = false;
vid.support.ext_stencil_two_side = false;
- vid.support.ext_texture_3d = false;//SDL_GL_ExtensionSupported("GL_OES_texture_3D"); // iPhoneOS does not support 3D textures, odd...
- vid.support.ext_texture_compression_s3tc = false;
+ vid.support.ext_texture_3d = SDL_GL_ExtensionSupported("GL_OES_texture_3D");
+ vid.support.ext_texture_compression_s3tc = SDL_GL_ExtensionSupported("GL_EXT_texture_compression_s3tc");
vid.support.ext_texture_edge_clamp = true;
vid.support.ext_texture_filter_anisotropic = false; // probably don't want to use it...
vid.support.ext_texture_srgb = false;
if (vid.support.ext_texture_filter_anisotropic)
qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*)&vid.max_anisotropy);
if (vid.support.arb_texture_cube_map)
- qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&vid.maxtexturesize_cubemap);
+ qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_cubemap);
+#ifdef GL_MAX_3D_TEXTURE_SIZE
if (vid.support.ext_texture_3d)
qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d);
+#endif
Con_Printf("GL_MAX_CUBE_MAP_TEXTURE_SIZE = %i\n", vid.maxtexturesize_cubemap);
Con_Printf("GL_MAX_3D_TEXTURE_SIZE = %i\n", vid.maxtexturesize_3d);
+ {
+#define GL_ALPHA_BITS 0x0D55
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+ int fb_r = -1, fb_g = -1, fb_b = -1, fb_a = -1, fb_d = -1, fb_s = -1;
+ qglGetIntegerv(GL_RED_BITS , &fb_r);
+ qglGetIntegerv(GL_GREEN_BITS , &fb_g);
+ qglGetIntegerv(GL_BLUE_BITS , &fb_b);
+ qglGetIntegerv(GL_ALPHA_BITS , &fb_a);
+ qglGetIntegerv(GL_DEPTH_BITS , &fb_d);
+ qglGetIntegerv(GL_STENCIL_BITS, &fb_s);
+ Con_Printf("Framebuffer depth is R%iG%iB%iA%iD%iS%i\n", fb_r, fb_g, fb_b, fb_a, fb_d, fb_s);
+ }
// verify that cubemap textures are really supported
if (vid.support.arb_texture_cube_map && vid.maxtexturesize_cubemap < 256)
// reallocate with malloc, as this is in tempmempool (do not want)
xpm = data;
- data = malloc(width * height * 4);
+ data = (char *) malloc(width * height * 4);
memcpy(data, xpm, width * height * 4);
Mem_Free(xpm);
xpm = NULL;
static long netwm_icon[MAX_NETWM_ICON];
int pos = 0;
int i = 1;
+ char vabuf[1024];
while(data)
{
}
++i;
Mem_Free(data);
- data = (char *) loadimagepixelsbgra(va("darkplaces-icon%d", i), false, false, false, NULL);
+ data = (char *) loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "darkplaces-icon%d", i), false, false, false, NULL);
}
info.info.x11.lock_func();
version->major, version->minor, version->patch );
}
-qboolean VID_InitModeGL(viddef_mode_t *mode)
+static qboolean VID_InitModeGL(viddef_mode_t *mode)
{
int i;
#if SETVIDEOMODE
notfirstvideomode = true;
#endif
+#ifndef USE_GLES2
// SDL usually knows best
drivername = NULL;
Con_Printf("Unable to load GL driver \"%s\": %s\n", drivername, SDL_GetError());
return false;
}
+#endif
#ifdef __IPHONEOS__
// mobile platforms are always fullscreen, we'll get the resolution after opening the window
extern cvar_t gl_info_platform;
extern cvar_t gl_info_driver;
-qboolean VID_InitModeSoft(viddef_mode_t *mode)
+static qboolean VID_InitModeSoft(viddef_mode_t *mode)
{
#if SETVIDEOMODE
int flags = SDL_HWSURFACE;
int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
k = 0;
- for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); vidmodes && *vidmodes; ++vidmodes)
+ for(vidmodes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); vidmodes && vidmodes != (SDL_Rect**)(-1) && *vidmodes; ++vidmodes)
{
if(k >= maxcount)
break;
#include "quakedef.h"
#include "cdaudio.h"
+#include "image.h"
#ifdef SUPPORTD3D
#include <d3d9.h>
// global video state
viddef_t vid;
-// LordHavoc: these are only set in wgl
-qboolean isG200 = false; // LordHavoc: the Matrox G200 can't do per pixel alpha, and it uses a D3D driver for GL... ugh...
-qboolean isRagePro = false; // LordHavoc: the ATI Rage Pro has limitations with per pixel alpha (the color scaler does not apply to per pixel alpha images...), although not as bad as a G200.
-
// AK FIXME -> input_dest
qboolean in_client_mouse = true;
// cvars for DPSOFTRAST
cvar_t vid_soft = {CVAR_SAVE, "vid_soft", "0", "enables use of the DarkPlaces Software Rasterizer rather than OpenGL or Direct3D"};
-cvar_t vid_soft_threads = {CVAR_SAVE, "vid_soft_threads", "2", "the number of threads the DarkPlaces Software Rasterizer should use"};
+cvar_t vid_soft_threads = {CVAR_SAVE, "vid_soft_threads", "8", "the number of threads the DarkPlaces Software Rasterizer should use"};
cvar_t vid_soft_interlace = {CVAR_SAVE, "vid_soft_interlace", "1", "whether the DarkPlaces Software Rasterizer should interlace the screen bands occupied by each thread"};
// we don't know until we try it!
cvar_t vid_gl20 = {0, "vid_gl20", "1", "enables faster rendering using OpenGL 2.0 features (such as GL_ARB_fragment_shader extension)"};
cvar_t gl_finish = {0, "gl_finish", "0", "make the cpu wait for the graphics processor at the end of each rendered frame (can help with strange input or video lag problems on some machines)"};
cvar_t vid_sRGB = {CVAR_SAVE, "vid_sRGB", "0", "if hardware is capable, modify rendering to be gamma corrected for the sRGB color standard (computer monitors, TVs), recommended"};
+cvar_t vid_sRGB_fallback = {CVAR_SAVE, "vid_sRGB_fallback", "0", "do an approximate sRGB fallback if not properly supported by hardware (2: also use the fallback if framebuffer is 8bit, 3: always use the fallback even if sRGB is supported)"};
cvar_t vid_touchscreen = {0, "vid_touchscreen", "0", "Use touchscreen-style input (no mouse grab, track mouse motion only while button is down, screen areas for mimicing joystick axes and buttons"};
cvar_t vid_stick_mouse = {CVAR_SAVE, "vid_stick_mouse", "0", "have the mouse stuck in the center of the screen" };
cvar_t v_color_white_b = {CVAR_SAVE, "v_color_white_b", "1", "desired color of white"};
cvar_t v_hwgamma = {CVAR_SAVE, "v_hwgamma", "0", "enables use of hardware gamma correction ramps if available (note: does not work very well on Windows2000 and above), values are 0 = off, 1 = attempt to use hardware gamma, 2 = use hardware gamma whether it works or not"};
cvar_t v_glslgamma = {CVAR_SAVE, "v_glslgamma", "1", "enables use of GLSL to apply gamma correction ramps if available (note: overrides v_hwgamma)"};
+cvar_t v_glslgamma_2d = {CVAR_SAVE, "v_glslgamma_2d", "0", "applies GLSL gamma to 2d pictures (HUD, fonts)"};
cvar_t v_psycho = {0, "v_psycho", "0", "easter egg"};
// brand of graphics chip
// name of driver library (opengl32.dll, libGL.so.1, or whatever)
char gl_driver[256];
+#ifndef USE_GLES2
// GL_ARB_multitexture
void (GLAPIENTRY *qglMultiTexCoord1f) (GLenum, GLfloat);
void (GLAPIENTRY *qglMultiTexCoord2f) (GLenum, GLfloat, GLfloat);
void (GLAPIENTRY *qglDepthFunc)(GLenum func);
void (GLAPIENTRY *qglDepthMask)(GLboolean flag);
void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val);
+void (GLAPIENTRY *qglDepthRangef)(GLclampf near_val, GLclampf far_val);
void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
void (GLAPIENTRY *qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
void (GLAPIENTRY *qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
-//GL_EXT_framebuffer_object
-GLboolean (GLAPIENTRY *qglIsRenderbufferEXT)(GLuint renderbuffer);
-void (GLAPIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint renderbuffer);
-void (GLAPIENTRY *qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint *renderbuffers);
-void (GLAPIENTRY *qglGenRenderbuffersEXT)(GLsizei n, GLuint *renderbuffers);
-void (GLAPIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-void (GLAPIENTRY *qglGetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint *params);
-GLboolean (GLAPIENTRY *qglIsFramebufferEXT)(GLuint framebuffer);
-void (GLAPIENTRY *qglBindFramebufferEXT)(GLenum target, GLuint framebuffer);
-void (GLAPIENTRY *qglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers);
-void (GLAPIENTRY *qglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers);
-GLenum (GLAPIENTRY *qglCheckFramebufferStatusEXT)(GLenum target);
-//void (GLAPIENTRY *qglFramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-void (GLAPIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-void (GLAPIENTRY *qglFramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-void (GLAPIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-void (GLAPIENTRY *qglGetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-void (GLAPIENTRY *qglGenerateMipmapEXT)(GLenum target);
+//GL_ARB_framebuffer_object
+GLboolean (GLAPIENTRY *qglIsRenderbuffer)(GLuint renderbuffer);
+GLvoid (GLAPIENTRY *qglBindRenderbuffer)(GLenum target, GLuint renderbuffer);
+GLvoid (GLAPIENTRY *qglDeleteRenderbuffers)(GLsizei n, const GLuint *renderbuffers);
+GLvoid (GLAPIENTRY *qglGenRenderbuffers)(GLsizei n, GLuint *renderbuffers);
+GLvoid (GLAPIENTRY *qglRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLvoid (GLAPIENTRY *qglRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLvoid (GLAPIENTRY *qglGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint *params);
+GLboolean (GLAPIENTRY *qglIsFramebuffer)(GLuint framebuffer);
+GLvoid (GLAPIENTRY *qglBindFramebuffer)(GLenum target, GLuint framebuffer);
+GLvoid (GLAPIENTRY *qglDeleteFramebuffers)(GLsizei n, const GLuint *framebuffers);
+GLvoid (GLAPIENTRY *qglGenFramebuffers)(GLsizei n, GLuint *framebuffers);
+GLenum (GLAPIENTRY *qglCheckFramebufferStatus)(GLenum target);
+GLvoid (GLAPIENTRY *qglFramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLvoid (GLAPIENTRY *qglFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLvoid (GLAPIENTRY *qglFramebufferTexture3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer);
+GLvoid (GLAPIENTRY *qglFramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLvoid (GLAPIENTRY *qglFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLvoid (GLAPIENTRY *qglGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLvoid (GLAPIENTRY *qglBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLvoid (GLAPIENTRY *qglGenerateMipmap)(GLenum target);
void (GLAPIENTRY *qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
void (GLAPIENTRY *qglGetQueryObjectuivARB)(GLuint qid, GLenum pname, GLuint *params);
void (GLAPIENTRY *qglSampleCoverageARB)(GLclampf value, GLboolean invert);
+#endif
#if _MSC_VER >= 1400
#define sscanf sscanf_s
return true;
}
+#ifndef USE_GLES2
static dllfunction_t opengl110funcs[] =
{
{"glClearColor", (void **) &qglClearColor},
{NULL, NULL}
};
-static dllfunction_t fbofuncs[] =
+static dllfunction_t arbfbofuncs[] =
{
- {"glIsRenderbufferEXT" , (void **) &qglIsRenderbufferEXT},
- {"glBindRenderbufferEXT" , (void **) &qglBindRenderbufferEXT},
- {"glDeleteRenderbuffersEXT" , (void **) &qglDeleteRenderbuffersEXT},
- {"glGenRenderbuffersEXT" , (void **) &qglGenRenderbuffersEXT},
- {"glRenderbufferStorageEXT" , (void **) &qglRenderbufferStorageEXT},
- {"glGetRenderbufferParameterivEXT" , (void **) &qglGetRenderbufferParameterivEXT},
- {"glIsFramebufferEXT" , (void **) &qglIsFramebufferEXT},
- {"glBindFramebufferEXT" , (void **) &qglBindFramebufferEXT},
- {"glDeleteFramebuffersEXT" , (void **) &qglDeleteFramebuffersEXT},
- {"glGenFramebuffersEXT" , (void **) &qglGenFramebuffersEXT},
- {"glCheckFramebufferStatusEXT" , (void **) &qglCheckFramebufferStatusEXT},
-// {"glFramebufferTexture1DEXT" , (void **) &qglFramebufferTexture1DEXT},
- {"glFramebufferTexture2DEXT" , (void **) &qglFramebufferTexture2DEXT},
- {"glFramebufferTexture3DEXT" , (void **) &qglFramebufferTexture3DEXT},
- {"glFramebufferRenderbufferEXT" , (void **) &qglFramebufferRenderbufferEXT},
- {"glGetFramebufferAttachmentParameterivEXT" , (void **) &qglGetFramebufferAttachmentParameterivEXT},
- {"glGenerateMipmapEXT" , (void **) &qglGenerateMipmapEXT},
+ {"glIsRenderbufferARB" , (void **) &qglIsRenderbuffer},
+ {"glBindRenderbufferARB" , (void **) &qglBindRenderbuffer},
+ {"glDeleteRenderbuffersARB" , (void **) &qglDeleteRenderbuffers},
+ {"glGenRenderbuffersARB" , (void **) &qglGenRenderbuffers},
+ {"glRenderbufferStorageARB" , (void **) &qglRenderbufferStorage},
+ {"glRenderbufferStorageMultisampleARB" , (void **) &qglRenderbufferStorageMultisample}, // not in GL_EXT_framebuffer_object
+ {"glGetRenderbufferParameterivARB" , (void **) &qglGetRenderbufferParameteriv},
+ {"glIsFramebufferARB" , (void **) &qglIsFramebuffer},
+ {"glBindFramebufferARB" , (void **) &qglBindFramebuffer},
+ {"glDeleteFramebuffersARB" , (void **) &qglDeleteFramebuffers},
+ {"glGenFramebuffersARB" , (void **) &qglGenFramebuffers},
+ {"glCheckFramebufferStatusARB" , (void **) &qglCheckFramebufferStatus},
+ {"glFramebufferTexture1DARB" , (void **) &qglFramebufferTexture1D},
+ {"glFramebufferTexture2DARB" , (void **) &qglFramebufferTexture2D},
+ {"glFramebufferTexture3DARB" , (void **) &qglFramebufferTexture3D},
+ {"glFramebufferTextureLayerARB" , (void **) &qglFramebufferTextureLayer}, // not in GL_EXT_framebuffer_object
+ {"glFramebufferRenderbufferARB" , (void **) &qglFramebufferRenderbuffer},
+ {"glGetFramebufferAttachmentParameterivARB" , (void **) &qglGetFramebufferAttachmentParameteriv},
+ {"glBlitFramebufferARB" , (void **) &qglBlitFramebuffer}, // not in GL_EXT_framebuffer_object
+ {"glGenerateMipmapARB" , (void **) &qglGenerateMipmap},
+ {NULL, NULL}
+};
+
+static dllfunction_t extfbofuncs[] =
+{
+ {"glIsRenderbufferEXT" , (void **) &qglIsRenderbuffer},
+ {"glBindRenderbufferEXT" , (void **) &qglBindRenderbuffer},
+ {"glDeleteRenderbuffersEXT" , (void **) &qglDeleteRenderbuffers},
+ {"glGenRenderbuffersEXT" , (void **) &qglGenRenderbuffers},
+ {"glRenderbufferStorageEXT" , (void **) &qglRenderbufferStorage},
+ {"glGetRenderbufferParameterivEXT" , (void **) &qglGetRenderbufferParameteriv},
+ {"glIsFramebufferEXT" , (void **) &qglIsFramebuffer},
+ {"glBindFramebufferEXT" , (void **) &qglBindFramebuffer},
+ {"glDeleteFramebuffersEXT" , (void **) &qglDeleteFramebuffers},
+ {"glGenFramebuffersEXT" , (void **) &qglGenFramebuffers},
+ {"glCheckFramebufferStatusEXT" , (void **) &qglCheckFramebufferStatus},
+ {"glFramebufferTexture1DEXT" , (void **) &qglFramebufferTexture1D},
+ {"glFramebufferTexture2DEXT" , (void **) &qglFramebufferTexture2D},
+ {"glFramebufferTexture3DEXT" , (void **) &qglFramebufferTexture3D},
+ {"glFramebufferRenderbufferEXT" , (void **) &qglFramebufferRenderbuffer},
+ {"glGetFramebufferAttachmentParameterivEXT" , (void **) &qglGetFramebufferAttachmentParameteriv},
+ {"glGenerateMipmapEXT" , (void **) &qglGenerateMipmap},
{NULL, NULL}
};
{"glSampleCoverageARB", (void **) &qglSampleCoverageARB},
{NULL, NULL}
};
+#endif
void VID_ClearExtensions(void)
{
vid.max_anisotropy = 1;
vid.maxdrawbuffers = 1;
+#ifndef USE_GLES2
// this is a complete list of all functions that are directly checked in the renderer
qglDrawRangeElements = NULL;
qglDrawBuffer = NULL;
qglFlush = NULL;
qglActiveTexture = NULL;
qglGetCompressedTexImageARB = NULL;
- qglFramebufferTexture2DEXT = NULL;
+ qglFramebufferTexture2D = NULL;
qglDrawBuffersARB = NULL;
+#endif
}
+#ifndef USE_GLES2
void VID_CheckExtensions(void)
{
if (!GL_CheckExtension("glbase", opengl110funcs, NULL, false))
vid.support.ext_blend_minmax = GL_CheckExtension("GL_EXT_blend_minmax", blendequationfuncs, "-noblendminmax", false);
vid.support.ext_blend_subtract = GL_CheckExtension("GL_EXT_blend_subtract", blendequationfuncs, "-noblendsubtract", false);
vid.support.ext_draw_range_elements = GL_CheckExtension("drawrangeelements", drawrangeelementsfuncs, "-nodrawrangeelements", true) || GL_CheckExtension("GL_EXT_draw_range_elements", drawrangeelementsextfuncs, "-nodrawrangeelements", false);
- vid.support.ext_framebuffer_object = GL_CheckExtension("GL_EXT_framebuffer_object", fbofuncs, "-nofbo", false);
+ vid.support.arb_framebuffer_object = GL_CheckExtension("GL_ARB_framebuffer_object", arbfbofuncs, "-nofbo", false);
+ if (vid.support.arb_framebuffer_object)
+ vid.support.ext_framebuffer_object = true;
+ else
+ vid.support.ext_framebuffer_object = GL_CheckExtension("GL_EXT_framebuffer_object", extfbofuncs, "-nofbo", false);
+ vid.support.ext_packed_depth_stencil = GL_CheckExtension("GL_EXT_packed_depth_stencil", NULL, "-nopackeddepthstencil", false);
vid.support.ext_stencil_two_side = GL_CheckExtension("GL_EXT_stencil_two_side", stenciltwosidefuncs, "-nostenciltwoside", false);
vid.support.ext_texture_3d = GL_CheckExtension("GL_EXT_texture3D", texture3dextfuncs, "-notexture3d", false);
vid.support.ext_texture_compression_s3tc = GL_CheckExtension("GL_EXT_texture_compression_s3tc", NULL, "-nos3tc", false);
if (vid.support.ext_texture_filter_anisotropic)
qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*)&vid.max_anisotropy);
if (vid.support.arb_texture_cube_map)
- qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&vid.maxtexturesize_cubemap);
+ qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_cubemap);
if (vid.support.ext_texture_3d)
qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d);
vid.texunits = vid.teximageunits = vid.texarrayunits = 1;
if (vid.support.arb_multitexture)
- qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&vid.texunits);
+ qglGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&vid.texunits);
if (vid_gl20.integer && vid.support.gl20shaders)
{
- qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&vid.texunits);
+ qglGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&vid.texunits);
qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (int *)&vid.teximageunits);CHECKGLERROR
qglGetIntegerv(GL_MAX_TEXTURE_COORDS, (int *)&vid.texarrayunits);CHECKGLERROR
vid.texunits = bound(4, vid.texunits, MAX_TEXTUREUNITS);
vid.sRGBcapable3D = true;
vid.useinterleavedarrays = false;
Con_Printf("vid.support.arb_multisample %i\n", vid.support.arb_multisample);
- Con_Printf("vid.mode.samples %i\n", vid.mode.samples);
Con_Printf("vid.support.gl20shaders %i\n", vid.support.gl20shaders);
vid.allowalphatocoverage = true; // but see below, it may get turned to false again if GL_SAMPLES_ARB is <= 1
}
else if (vid.support.arb_texture_env_combine && vid.texunits >= 2 && vid_gl13.integer)
{
- qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&vid.texunits);
+ qglGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&vid.texunits);
vid.texunits = bound(1, vid.texunits, MAX_TEXTUREUNITS);
vid.teximageunits = vid.texunits;
vid.texarrayunits = vid.texunits;
{
int samples = 0;
qglGetIntegerv(GL_SAMPLES_ARB, &samples);
+ vid.samples = samples;
if (samples > 1)
qglEnable(GL_MULTISAMPLE_ARB);
else
vid.allowalphatocoverage = false;
}
else
+ {
vid.allowalphatocoverage = false;
+ vid.samples = 1;
+ }
// VorteX: set other info (maybe place them in VID_InitMode?)
Cvar_SetQuick(&gl_info_vendor, gl_vendor);
Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : "");
Cvar_SetQuick(&gl_info_driver, gl_driver);
}
+#endif
float VID_JoyState_GetAxis(const vid_joystate_t *joystate, int axis, float sensitivity, float deadzone)
{
joystate->button[35] = r < 0.0f;
}
-void VID_KeyEventForButton(qboolean oldbutton, qboolean newbutton, int key, double *timer)
+static void VID_KeyEventForButton(qboolean oldbutton, qboolean newbutton, int key, double *timer)
{
if (oldbutton)
{
}
-void Force_CenterView_f (void)
+static void Force_CenterView_f (void)
{
cl.viewangles[PITCH] = 0;
}
qboolean vid_gammatables_trivial = true;
void VID_BuildGammaTables(unsigned short *ramps, int rampsize)
{
- float srgbmul = (vid.sRGB2D || vid.sRGB3D) ? 2.2f : 1.0f;
if (cachecolorenable)
{
- BuildGammaTable16(1.0f, invpow(0.5, 1 - cachegrey[0]) * srgbmul, cachewhite[0], cacheblack[0], cachecontrastboost, ramps, rampsize);
- BuildGammaTable16(1.0f, invpow(0.5, 1 - cachegrey[1]) * srgbmul, cachewhite[1], cacheblack[1], cachecontrastboost, ramps + rampsize, rampsize);
- BuildGammaTable16(1.0f, invpow(0.5, 1 - cachegrey[2]) * srgbmul, cachewhite[2], cacheblack[2], cachecontrastboost, ramps + rampsize*2, rampsize);
+ BuildGammaTable16(1.0f, invpow(0.5, 1 - cachegrey[0]), cachewhite[0], cacheblack[0], cachecontrastboost, ramps, rampsize);
+ BuildGammaTable16(1.0f, invpow(0.5, 1 - cachegrey[1]), cachewhite[1], cacheblack[1], cachecontrastboost, ramps + rampsize, rampsize);
+ BuildGammaTable16(1.0f, invpow(0.5, 1 - cachegrey[2]), cachewhite[2], cacheblack[2], cachecontrastboost, ramps + rampsize*2, rampsize);
}
else
{
- BuildGammaTable16(1.0f, cachegamma * srgbmul, cachecontrast, cachebrightness, cachecontrastboost, ramps, rampsize);
- BuildGammaTable16(1.0f, cachegamma * srgbmul, cachecontrast, cachebrightness, cachecontrastboost, ramps + rampsize, rampsize);
- BuildGammaTable16(1.0f, cachegamma * srgbmul, cachecontrast, cachebrightness, cachecontrastboost, ramps + rampsize*2, rampsize);
+ BuildGammaTable16(1.0f, cachegamma, cachecontrast, cachebrightness, cachecontrastboost, ramps, rampsize);
+ BuildGammaTable16(1.0f, cachegamma, cachecontrast, cachebrightness, cachecontrastboost, ramps + rampsize, rampsize);
+ BuildGammaTable16(1.0f, cachegamma, cachecontrast, cachebrightness, cachecontrastboost, ramps + rampsize*2, rampsize);
+ }
+
+ if(vid.sRGB2D || vid.sRGB3D)
+ {
+ int i;
+ for(i = 0; i < 3*rampsize; ++i)
+ ramps[i] = (int)floor(bound(0.0f, Image_sRGBFloatFromLinearFloat(ramps[i] / 65535.0f), 1.0f) * 65535.0f + 0.5f);
}
// LordHavoc: this code came from Ben Winslow and Zinx Verituse, I have
Cvar_RegisterVariable(&v_hwgamma);
Cvar_RegisterVariable(&v_glslgamma);
+ Cvar_RegisterVariable(&v_glslgamma_2d);
Cvar_RegisterVariable(&v_psycho);
Cvar_RegisterVariable(&vid_gl20);
Cvar_RegisterVariable(&gl_finish);
Cvar_RegisterVariable(&vid_sRGB);
+ Cvar_RegisterVariable(&vid_sRGB_fallback);
Cvar_RegisterVariable(&joy_active);
#ifdef WIN32
Cmd_AddCommand("vid_restart", VID_Restart_f, "restarts video system (closes and reopens the window, restarts renderer)");
}
-int VID_Mode(int fullscreen, int width, int height, int bpp, float refreshrate, int stereobuffer, int samples)
+static int VID_Mode(int fullscreen, int width, int height, int bpp, float refreshrate, int stereobuffer, int samples)
{
viddef_mode_t mode;
+ char vabuf[1024];
memset(&mode, 0, sizeof(mode));
mode.fullscreen = fullscreen != 0;
mode.samples = samples;
cl_ignoremousemoves = 2;
VID_ClearExtensions();
+
+ vid.samples = vid.mode.samples;
if (VID_InitMode(&mode))
{
// accept the (possibly modified) mode
vid.refreshrate = vid.mode.refreshrate;
vid.userefreshrate = vid.mode.userefreshrate;
vid.stereobuffer = vid.mode.stereobuffer;
- vid.samples = vid.mode.samples;
vid.stencil = vid.mode.bitsperpixel > 16;
vid.sRGB2D = vid_sRGB.integer >= 1 && vid.sRGBcapable2D;
vid.sRGB3D = vid_sRGB.integer >= 1 && vid.sRGBcapable3D;
- Con_Printf("Video Mode: %s %dx%dx%dx%.2fhz%s%s\n", mode.fullscreen ? "fullscreen" : "window", mode.width, mode.height, mode.bitsperpixel, mode.refreshrate, mode.stereobuffer ? " stereo" : "", mode.samples > 1 ? va(" (%ix AA)", mode.samples) : "");
+ if(
+ (vid_sRGB_fallback.integer >= 3) // force fallback
+ ||
+ (vid_sRGB_fallback.integer >= 2 && // fallback if framebuffer is 8bit
+ !(r_viewfbo.integer >= 2 && vid.support.ext_framebuffer_object && vid.samples < 2))
+ )
+ vid.sRGB2D = vid.sRGB3D = false;
+
+ if(vid.samples != vid.mode.samples)
+ Con_Printf("NOTE: requested %dx AA, got %dx AA\n", vid.mode.samples, vid.samples);
+
+ Con_Printf("Video Mode: %s %dx%dx%dx%.2fhz%s%s\n", mode.fullscreen ? "fullscreen" : "window", mode.width, mode.height, mode.bitsperpixel, mode.refreshrate, mode.stereobuffer ? " stereo" : "", mode.samples > 1 ? va(vabuf, sizeof(vabuf), " (%ix AA)", mode.samples) : "");
Cvar_SetValueQuick(&vid_fullscreen, vid.mode.fullscreen);
Cvar_SetValueQuick(&vid_width, vid.mode.width);
void VID_Restart_f(void)
{
+ char vabuf[1024];
+ char vabuf2[1024];
// don't crash if video hasn't started yet
if (vid_commandlinecheck)
return;
}
Con_Printf("VID_Restart: changing from %s %dx%dx%dbpp%s%s, to %s %dx%dx%dbpp%s%s.\n",
- vid.mode.fullscreen ? "fullscreen" : "window", vid.mode.width, vid.mode.height, vid.mode.bitsperpixel, vid.mode.fullscreen && vid.mode.userefreshrate ? va("x%.2fhz", vid.mode.refreshrate) : "", vid.mode.samples > 1 ? va(" (%ix AA)", vid.mode.samples) : "",
- vid_fullscreen.integer ? "fullscreen" : "window", vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_fullscreen.integer && vid_userefreshrate.integer ? va("x%.2fhz", vid_refreshrate.value) : "", vid_samples.integer > 1 ? va(" (%ix AA)", vid_samples.integer) : "");
+ vid.mode.fullscreen ? "fullscreen" : "window", vid.mode.width, vid.mode.height, vid.mode.bitsperpixel, vid.mode.fullscreen && vid.mode.userefreshrate ? va(vabuf, sizeof(vabuf), "x%.2fhz", vid.mode.refreshrate) : "", vid.mode.samples > 1 ? va(vabuf2, sizeof(vabuf2), " (%ix AA)", vid.mode.samples) : "",
+ vid_fullscreen.integer ? "fullscreen" : "window", vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_fullscreen.integer && vid_userefreshrate.integer ? va(vabuf, sizeof(vabuf), "x%.2fhz", vid_refreshrate.value) : "", vid_samples.integer > 1 ? va(vabuf2, sizeof(vabuf2), " (%ix AA)", vid_samples.integer) : "");
VID_CloseSystems();
VID_Shutdown();
if (!VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.value, vid_stereobuffer.integer, vid_samples.integer))
VID_Shutdown();
}
-int VID_SortModes_Compare(const void *a_, const void *b_)
+static int VID_SortModes_Compare(const void *a_, const void *b_)
{
vid_mode_t *a = (vid_mode_t *) a_;
vid_mode_t *b = (vid_mode_t *) b_;
if (vid_begunscene)
IDirect3DDevice9_EndScene(vid_d3d9dev);
vid_begunscene = false;
-// Cmd_ExecuteString("r_texturestats", src_command);
-// Cmd_ExecuteString("memlist", src_command);
+// Cmd_ExecuteString("r_texturestats", src_command, true);
+// Cmd_ExecuteString("memlist", src_command, true);
IDirect3DDevice9_Release(vid_d3d9dev);
}
vid_d3d9dev = NULL;
#include "cl_collision.h"
#include "image.h"
-void CL_VM_UpdateDmgGlobals (int dmg_take, int dmg_save, vec3_t dmg_origin);
-
/*
The view is allowed to move slightly from it's true position for bobbing,
//float side;
float count;
- armor = MSG_ReadByte ();
- blood = MSG_ReadByte ();
- MSG_ReadVector(from, cls.protocol);
+ armor = MSG_ReadByte(&cl_message);
+ blood = MSG_ReadByte(&cl_message);
+ MSG_ReadVector(&cl_message, from, cls.protocol);
// Send the Dmg Globals to CSQC
CL_VM_UpdateDmgGlobals(blood, armor, from);
out[2] = highpass_limited(value[2], fracz, limitz, &store[2]);
}
-void V_CalcRefdef (void)
+void V_CalcRefdefUsing (const matrix4x4_t *entrendermatrix, const vec3_t clviewangles, qboolean teleported, qboolean clonground, qboolean clcmdjump)
{
- entity_t *ent;
float vieworg[3], viewangles[3], smoothtime;
float gunorg[3], gunangles[3];
matrix4x4_t tmpmatrix;
// end of chase camera bounding box size for proper collisions by Alexander Zubov
#endif
trace_t trace;
+
+ // react to clonground state changes (for gun bob)
+ if (clonground)
+ {
+ if (!cl.oldonground)
+ cl.hitgroundtime = cl.movecmd[0].time;
+ cl.lastongroundtime = cl.movecmd[0].time;
+ }
+ cl.oldonground = clonground;
+
VectorClear(gunorg);
viewmodelmatrix_nobob = identitymatrix;
viewmodelmatrix_withbob = identitymatrix;
r_refdef.view.matrix = identitymatrix;
- if (cls.state == ca_connected && cls.signon == SIGNONS)
- {
- // ent is the view entity (visible when out of body)
- ent = &cl.entities[cl.viewentity];
- // player can look around, so take the origin from the entity,
- // and the angles from the input system
- Matrix4x4_OriginFromMatrix(&ent->render.matrix, vieworg);
- VectorCopy(cl.viewangles, viewangles);
- // calculate how much time has passed since the last V_CalcRefdef
- smoothtime = bound(0, cl.time - cl.stairsmoothtime, 0.1);
- cl.stairsmoothtime = cl.time;
+ // player can look around, so take the origin from the entity,
+ // and the angles from the input system
+ Matrix4x4_OriginFromMatrix(entrendermatrix, vieworg);
+ VectorCopy(clviewangles, viewangles);
+
+ // calculate how much time has passed since the last V_CalcRefdef
+ smoothtime = bound(0, cl.time - cl.stairsmoothtime, 0.1);
+ cl.stairsmoothtime = cl.time;
- // fade damage flash
- if (v_dmg_time > 0)
- v_dmg_time -= bound(0, smoothtime, 0.1);
+ // fade damage flash
+ if (v_dmg_time > 0)
+ v_dmg_time -= bound(0, smoothtime, 0.1);
- if (cl.intermission)
+ if (cl.intermission)
+ {
+ // entity is a fixed camera, just copy the matrix
+ if (cls.protocol == PROTOCOL_QUAKEWORLD)
+ Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.qw_intermission_origin[0], cl.qw_intermission_origin[1], cl.qw_intermission_origin[2], cl.qw_intermission_angles[0], cl.qw_intermission_angles[1], cl.qw_intermission_angles[2], 1);
+ else
{
- // entity is a fixed camera, just copy the matrix
- if (cls.protocol == PROTOCOL_QUAKEWORLD)
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.qw_intermission_origin[0], cl.qw_intermission_origin[1], cl.qw_intermission_origin[2], cl.qw_intermission_angles[0], cl.qw_intermission_angles[1], cl.qw_intermission_angles[2], 1);
- else
- {
- r_refdef.view.matrix = ent->render.matrix;
- Matrix4x4_AdjustOrigin(&r_refdef.view.matrix, 0, 0, cl.stats[STAT_VIEWHEIGHT]);
- }
- Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
- Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);
- Matrix4x4_Copy(&viewmodelmatrix_withbob, &viewmodelmatrix_nobob);
+ r_refdef.view.matrix = *entrendermatrix;
+ Matrix4x4_AdjustOrigin(&r_refdef.view.matrix, 0, 0, cl.stats[STAT_VIEWHEIGHT]);
}
+ Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
+ Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);
+ Matrix4x4_Copy(&viewmodelmatrix_withbob, &viewmodelmatrix_nobob);
+ }
+ else
+ {
+ // smooth stair stepping, but only if clonground and enabled
+ if (!clonground || cl_stairsmoothspeed.value <= 0 || teleported)
+ cl.stairsmoothz = vieworg[2];
else
{
- // smooth stair stepping, but only if onground and enabled
- if (!cl.onground || cl_stairsmoothspeed.value <= 0 || !ent->persistent.trail_allowed) // FIXME use a better way to detect teleport/warp
- cl.stairsmoothz = vieworg[2];
- else
- {
- if (cl.stairsmoothz < vieworg[2])
- vieworg[2] = cl.stairsmoothz = bound(vieworg[2] - cl.movevars_stepheight, cl.stairsmoothz + smoothtime * cl_stairsmoothspeed.value, vieworg[2]);
- else if (cl.stairsmoothz > vieworg[2])
- vieworg[2] = cl.stairsmoothz = bound(vieworg[2], cl.stairsmoothz - smoothtime * cl_stairsmoothspeed.value, vieworg[2] + cl.movevars_stepheight);
- }
+ if (cl.stairsmoothz < vieworg[2])
+ vieworg[2] = cl.stairsmoothz = bound(vieworg[2] - cl.movevars_stepheight, cl.stairsmoothz + smoothtime * cl_stairsmoothspeed.value, vieworg[2]);
+ else if (cl.stairsmoothz > vieworg[2])
+ vieworg[2] = cl.stairsmoothz = bound(vieworg[2], cl.stairsmoothz - smoothtime * cl_stairsmoothspeed.value, vieworg[2] + cl.movevars_stepheight);
+ }
- // apply qw weapon recoil effect (this did not work in QW)
- // TODO: add a cvar to disable this
- viewangles[PITCH] += cl.qw_weaponkick;
+ // apply qw weapon recoil effect (this did not work in QW)
+ // TODO: add a cvar to disable this
+ viewangles[PITCH] += cl.qw_weaponkick;
- // apply the viewofs (even if chasecam is used)
- // Samual: Lets add smoothing for this too so that things like crouching are done with a transition.
- viewheight = bound(0, (cl.time - cl.oldtime) / max(0.0001, cl_smoothviewheight.value), 1);
- viewheightavg = viewheightavg * (1 - viewheight) + cl.stats[STAT_VIEWHEIGHT] * viewheight;
- vieworg[2] += viewheightavg;
+ // apply the viewofs (even if chasecam is used)
+ // Samual: Lets add smoothing for this too so that things like crouching are done with a transition.
+ viewheight = bound(0, (cl.time - cl.oldtime) / max(0.0001, cl_smoothviewheight.value), 1);
+ viewheightavg = viewheightavg * (1 - viewheight) + cl.stats[STAT_VIEWHEIGHT] * viewheight;
+ vieworg[2] += viewheightavg;
- if (chase_active.value)
- {
- // observing entity from third person. Added "campitch" by Alexander "motorsep" Zubov
- vec_t camback, camup, dist, campitch, forward[3], chase_dest[3];
+ if (chase_active.value)
+ {
+ // observing entity from third person. Added "campitch" by Alexander "motorsep" Zubov
+ vec_t camback, camup, dist, campitch, forward[3], chase_dest[3];
- camback = chase_back.value;
- camup = chase_up.value;
- campitch = chase_pitchangle.value;
+ camback = chase_back.value;
+ camup = chase_up.value;
+ campitch = chase_pitchangle.value;
- AngleVectors(viewangles, forward, NULL, NULL);
+ AngleVectors(viewangles, forward, NULL, NULL);
- if (chase_overhead.integer)
- {
+ if (chase_overhead.integer)
+ {
#if 1
- vec3_t offset;
- vec3_t bestvieworg;
+ vec3_t offset;
+ vec3_t bestvieworg;
#endif
- vec3_t up;
- viewangles[PITCH] = 0;
- AngleVectors(viewangles, forward, NULL, up);
- // trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
- chase_dest[0] = vieworg[0] - forward[0] * camback + up[0] * camup;
- chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup;
- chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup;
+ vec3_t up;
+ viewangles[PITCH] = 0;
+ AngleVectors(viewangles, forward, NULL, up);
+ // trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
+ chase_dest[0] = vieworg[0] - forward[0] * camback + up[0] * camup;
+ chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup;
+ chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup;
#if 0
#if 1
- //trace = CL_TraceLine(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
- trace = CL_TraceLine(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+ //trace = CL_TraceLine(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+ trace = CL_TraceLine(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#else
- //trace = CL_TraceBox(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
- trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+ //trace = CL_TraceBox(vieworg, eyeboxmins, eyeboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+ trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#endif
- VectorCopy(trace.endpos, vieworg);
- vieworg[2] -= 8;
+ VectorCopy(trace.endpos, vieworg);
+ vieworg[2] -= 8;
#else
- // trace from first person view location to our chosen third person view location
+ // trace from first person view location to our chosen third person view location
#if 1
- trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
+ trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
#else
- trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+ trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#endif
- VectorCopy(trace.endpos, bestvieworg);
- offset[2] = 0;
- for (offset[0] = -16;offset[0] <= 16;offset[0] += 8)
+ VectorCopy(trace.endpos, bestvieworg);
+ offset[2] = 0;
+ for (offset[0] = -16;offset[0] <= 16;offset[0] += 8)
+ {
+ for (offset[1] = -16;offset[1] <= 16;offset[1] += 8)
{
- for (offset[1] = -16;offset[1] <= 16;offset[1] += 8)
- {
- AngleVectors(viewangles, NULL, NULL, up);
- chase_dest[0] = vieworg[0] - forward[0] * camback + up[0] * camup + offset[0];
- chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup + offset[1];
- chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup + offset[2];
+ AngleVectors(viewangles, NULL, NULL, up);
+ chase_dest[0] = vieworg[0] - forward[0] * camback + up[0] * camup + offset[0];
+ chase_dest[1] = vieworg[1] - forward[1] * camback + up[1] * camup + offset[1];
+ chase_dest[2] = vieworg[2] - forward[2] * camback + up[2] * camup + offset[2];
#if 1
- trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
+ trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
#else
- trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
+ trace = CL_TraceBox(vieworg, camboxmins, camboxmaxs, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false);
#endif
- if (bestvieworg[2] > trace.endpos[2])
- bestvieworg[2] = trace.endpos[2];
- }
+ if (bestvieworg[2] > trace.endpos[2])
+ bestvieworg[2] = trace.endpos[2];
}
- bestvieworg[2] -= 8;
- VectorCopy(bestvieworg, vieworg);
-#endif
- viewangles[PITCH] = campitch;
}
- else
+ bestvieworg[2] -= 8;
+ VectorCopy(bestvieworg, vieworg);
+#endif
+ viewangles[PITCH] = campitch;
+ }
+ else
+ {
+ if (gamemode == GAME_GOODVSBAD2 && chase_stevie.integer)
{
- if (gamemode == GAME_GOODVSBAD2 && chase_stevie.integer)
- {
- // look straight down from high above
- viewangles[PITCH] = 90;
- camback = 2048;
- VectorSet(forward, 0, 0, -1);
- }
-
- // trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
- dist = -camback - 8;
- chase_dest[0] = vieworg[0] + forward[0] * dist;
- chase_dest[1] = vieworg[1] + forward[1] * dist;
- chase_dest[2] = vieworg[2] + forward[2] * dist + camup;
- trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
- VectorMAMAM(1, trace.endpos, 8, forward, 4, trace.plane.normal, vieworg);
+ // look straight down from high above
+ viewangles[PITCH] = 90;
+ camback = 2048;
+ VectorSet(forward, 0, 0, -1);
}
+
+ // trace a little further so it hits a surface more consistently (to avoid 'snapping' on the edge of the range)
+ dist = -camback - 8;
+ chase_dest[0] = vieworg[0] + forward[0] * dist;
+ chase_dest[1] = vieworg[1] + forward[1] * dist;
+ chase_dest[2] = vieworg[2] + forward[2] * dist + camup;
+ trace = CL_TraceLine(vieworg, chase_dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_SKY, true, false, NULL, false, true);
+ VectorMAMAM(1, trace.endpos, 8, forward, 4, trace.plane.normal, vieworg);
}
- else
+ }
+ else
+ {
+ // first person view from entity
+ // angles
+ if (cl.stats[STAT_HEALTH] <= 0 && v_deathtilt.integer)
+ viewangles[ROLL] = v_deathtiltangle.value;
+ VectorAdd(viewangles, cl.punchangle, viewangles);
+ viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.velocity);
+ if (v_dmg_time > 0)
+ {
+ viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
+ viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
+ }
+ // origin
+ VectorAdd(vieworg, cl.punchvector, vieworg);
+ if (cl.stats[STAT_HEALTH] > 0)
{
- // first person view from entity
- // angles
- if (cl.stats[STAT_HEALTH] <= 0 && v_deathtilt.integer)
- viewangles[ROLL] = v_deathtiltangle.value;
- VectorAdd(viewangles, cl.punchangle, viewangles);
- viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.velocity);
- if (v_dmg_time > 0)
+ double xyspeed, bob, bobfall;
+ float cycle;
+ vec_t frametime;
+
+ //frametime = cl.realframetime * cl.movevars_timescale;
+ frametime = (cl.time - cl.oldtime) * cl.movevars_timescale;
+
+ // 1. if we teleported, clear the frametime... the lowpass will recover the previous value then
+ if(teleported)
{
- viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
- viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
+ // try to fix the first highpass; result is NOT
+ // perfect! TODO find a better fix
+ VectorCopy(viewangles, cl.gunangles_prev);
+ VectorCopy(vieworg, cl.gunorg_prev);
}
- // origin
- VectorAdd(vieworg, cl.punchvector, vieworg);
- if (cl.stats[STAT_HEALTH] > 0)
+
+ // 2. for the gun origin, only keep the high frequency (non-DC) parts, which is "somewhat like velocity"
+ VectorAdd(cl.gunorg_highpass, cl.gunorg_prev, cl.gunorg_highpass);
+ highpass3_limited(vieworg, frametime*cl_followmodel_side_highpass1.value, cl_followmodel_side_limit.value, frametime*cl_followmodel_side_highpass1.value, cl_followmodel_side_limit.value, frametime*cl_followmodel_up_highpass1.value, cl_followmodel_up_limit.value, cl.gunorg_highpass, gunorg);
+ VectorCopy(vieworg, cl.gunorg_prev);
+ VectorSubtract(cl.gunorg_highpass, cl.gunorg_prev, cl.gunorg_highpass);
+
+ // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
+ VectorAdd(cl.gunangles_highpass, cl.gunangles_prev, cl.gunangles_highpass);
+ cl.gunangles_highpass[PITCH] += 360 * floor((viewangles[PITCH] - cl.gunangles_highpass[PITCH]) / 360 + 0.5);
+ cl.gunangles_highpass[YAW] += 360 * floor((viewangles[YAW] - cl.gunangles_highpass[YAW]) / 360 + 0.5);
+ cl.gunangles_highpass[ROLL] += 360 * floor((viewangles[ROLL] - cl.gunangles_highpass[ROLL]) / 360 + 0.5);
+ highpass3_limited(viewangles, frametime*cl_leanmodel_up_highpass1.value, cl_leanmodel_up_limit.value, frametime*cl_leanmodel_side_highpass1.value, cl_leanmodel_side_limit.value, 0, 0, cl.gunangles_highpass, gunangles);
+ VectorCopy(viewangles, cl.gunangles_prev);
+ VectorSubtract(cl.gunangles_highpass, cl.gunangles_prev, cl.gunangles_highpass);
+
+ // 3. calculate the RAW adjustment vectors
+ gunorg[0] *= (cl_followmodel.value ? -cl_followmodel_side_speed.value : 0);
+ gunorg[1] *= (cl_followmodel.value ? -cl_followmodel_side_speed.value : 0);
+ gunorg[2] *= (cl_followmodel.value ? -cl_followmodel_up_speed.value : 0);
+
+ gunangles[PITCH] *= (cl_leanmodel.value ? -cl_leanmodel_up_speed.value : 0);
+ gunangles[YAW] *= (cl_leanmodel.value ? -cl_leanmodel_side_speed.value : 0);
+ gunangles[ROLL] = 0;
+
+ // 4. perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
+ // trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
+ highpass3(gunorg, frametime*cl_followmodel_side_highpass.value, frametime*cl_followmodel_side_highpass.value, frametime*cl_followmodel_up_highpass.value, cl.gunorg_adjustment_highpass, gunorg);
+ lowpass3(gunorg, frametime*cl_followmodel_side_lowpass.value, frametime*cl_followmodel_side_lowpass.value, frametime*cl_followmodel_up_lowpass.value, cl.gunorg_adjustment_lowpass, gunorg);
+ // we assume here: PITCH = 0, YAW = 1, ROLL = 2
+ highpass3(gunangles, frametime*cl_leanmodel_up_highpass.value, frametime*cl_leanmodel_side_highpass.value, 0, cl.gunangles_adjustment_highpass, gunangles);
+ lowpass3(gunangles, frametime*cl_leanmodel_up_lowpass.value, frametime*cl_leanmodel_side_lowpass.value, 0, cl.gunangles_adjustment_lowpass, gunangles);
+
+ // 5. use the adjusted vectors
+ VectorAdd(vieworg, gunorg, gunorg);
+ VectorAdd(viewangles, gunangles, gunangles);
+
+ // bounded XY speed, used by several effects below
+ xyspeed = bound (0, sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]), 400);
+
+ // vertical view bobbing code
+ if (cl_bob.value && cl_bobcycle.value)
{
- double xyspeed, bob, bobfall;
- float cycle;
- vec_t frametime;
-
- //frametime = cl.realframetime * cl.movevars_timescale;
- frametime = (cl.time - cl.oldtime) * cl.movevars_timescale;
-
- // 1. if we teleported, clear the frametime... the lowpass will recover the previous value then
- if(!ent->persistent.trail_allowed) // FIXME improve this check
- {
- // try to fix the first highpass; result is NOT
- // perfect! TODO find a better fix
- VectorCopy(viewangles, cl.gunangles_prev);
- VectorCopy(vieworg, cl.gunorg_prev);
- }
+ // LordHavoc: this code is *weird*, but not replacable (I think it
+ // should be done in QC on the server, but oh well, quake is quake)
+ // LordHavoc: figured out bobup: the time at which the sin is at 180
+ // degrees (which allows lengthening or squishing the peak or valley)
+ cycle = cl.time / cl_bobcycle.value;
+ cycle -= (int) cycle;
+ if (cycle < cl_bobup.value)
+ cycle = sin(M_PI * cycle / cl_bobup.value);
+ else
+ cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
+ // bob is proportional to velocity in the xy plane
+ // (don't count Z, or jumping messes it up)
+ bob = xyspeed * bound(0, cl_bob.value, 0.05);
+ bob = bob*0.3 + bob*0.7*cycle;
+ vieworg[2] += bob;
+ // we also need to adjust gunorg, or this appears like pushing the gun!
+ // In the old code, this was applied to vieworg BEFORE copying to gunorg,
+ // but this is not viable with the new followmodel code as that would mean
+ // that followmodel would work on the munged-by-bob vieworg and do feedback
+ gunorg[2] += bob;
+ }
- // 2. for the gun origin, only keep the high frequency (non-DC) parts, which is "somewhat like velocity"
- VectorAdd(cl.gunorg_highpass, cl.gunorg_prev, cl.gunorg_highpass);
- highpass3_limited(vieworg, frametime*cl_followmodel_side_highpass1.value, cl_followmodel_side_limit.value, frametime*cl_followmodel_side_highpass1.value, cl_followmodel_side_limit.value, frametime*cl_followmodel_up_highpass1.value, cl_followmodel_up_limit.value, cl.gunorg_highpass, gunorg);
- VectorCopy(vieworg, cl.gunorg_prev);
- VectorSubtract(cl.gunorg_highpass, cl.gunorg_prev, cl.gunorg_highpass);
-
- // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
- VectorAdd(cl.gunangles_highpass, cl.gunangles_prev, cl.gunangles_highpass);
- cl.gunangles_highpass[PITCH] += 360 * floor((viewangles[PITCH] - cl.gunangles_highpass[PITCH]) / 360 + 0.5);
- cl.gunangles_highpass[YAW] += 360 * floor((viewangles[YAW] - cl.gunangles_highpass[YAW]) / 360 + 0.5);
- cl.gunangles_highpass[ROLL] += 360 * floor((viewangles[ROLL] - cl.gunangles_highpass[ROLL]) / 360 + 0.5);
- highpass3_limited(viewangles, frametime*cl_leanmodel_up_highpass1.value, cl_leanmodel_up_limit.value, frametime*cl_leanmodel_side_highpass1.value, cl_leanmodel_side_limit.value, 0, 0, cl.gunangles_highpass, gunangles);
- VectorCopy(viewangles, cl.gunangles_prev);
- VectorSubtract(cl.gunangles_highpass, cl.gunangles_prev, cl.gunangles_highpass);
-
- // 3. calculate the RAW adjustment vectors
- gunorg[0] *= (cl_followmodel.value ? -cl_followmodel_side_speed.value : 0);
- gunorg[1] *= (cl_followmodel.value ? -cl_followmodel_side_speed.value : 0);
- gunorg[2] *= (cl_followmodel.value ? -cl_followmodel_up_speed.value : 0);
-
- gunangles[PITCH] *= (cl_leanmodel.value ? -cl_leanmodel_up_speed.value : 0);
- gunangles[YAW] *= (cl_leanmodel.value ? -cl_leanmodel_side_speed.value : 0);
- gunangles[ROLL] = 0;
-
- // 4. perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
- // trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
- highpass3(gunorg, frametime*cl_followmodel_side_highpass.value, frametime*cl_followmodel_side_highpass.value, frametime*cl_followmodel_up_highpass.value, cl.gunorg_adjustment_highpass, gunorg);
- lowpass3(gunorg, frametime*cl_followmodel_side_lowpass.value, frametime*cl_followmodel_side_lowpass.value, frametime*cl_followmodel_up_lowpass.value, cl.gunorg_adjustment_lowpass, gunorg);
- // we assume here: PITCH = 0, YAW = 1, ROLL = 2
- highpass3(gunangles, frametime*cl_leanmodel_up_highpass.value, frametime*cl_leanmodel_side_highpass.value, 0, cl.gunangles_adjustment_highpass, gunangles);
- lowpass3(gunangles, frametime*cl_leanmodel_up_lowpass.value, frametime*cl_leanmodel_side_lowpass.value, 0, cl.gunangles_adjustment_lowpass, gunangles);
-
- // 5. use the adjusted vectors
- VectorAdd(vieworg, gunorg, gunorg);
- VectorAdd(viewangles, gunangles, gunangles);
-
- // bounded XY speed, used by several effects below
- xyspeed = bound (0, sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]), 400);
-
- // vertical view bobbing code
- if (cl_bob.value && cl_bobcycle.value)
+ // horizontal view bobbing code
+ if (cl_bob2.value && cl_bob2cycle.value)
+ {
+ vec3_t bob2vel;
+ vec3_t forward, right, up;
+ float side, front;
+
+ cycle = cl.time / cl_bob2cycle.value;
+ cycle -= (int) cycle;
+ if (cycle < 0.5)
+ cycle = cos(M_PI * cycle / 0.5); // cos looks better here with the other view bobbing using sin
+ else
+ cycle = cos(M_PI + M_PI * (cycle-0.5)/0.5);
+ bob = bound(0, cl_bob2.value, 0.05) * cycle;
+
+ // this value slowly decreases from 1 to 0 when we stop touching the ground.
+ // The cycle is later multiplied with it so the view smooths back to normal
+ if (clonground && !clcmdjump) // also block the effect while the jump button is pressed, to avoid twitches when bunny-hopping
+ cl.bob2_smooth = 1;
+ else
{
- // LordHavoc: this code is *weird*, but not replacable (I think it
- // should be done in QC on the server, but oh well, quake is quake)
- // LordHavoc: figured out bobup: the time at which the sin is at 180
- // degrees (which allows lengthening or squishing the peak or valley)
- cycle = cl.time / cl_bobcycle.value;
- cycle -= (int) cycle;
- if (cycle < cl_bobup.value)
- cycle = sin(M_PI * cycle / cl_bobup.value);
+ if(cl.bob2_smooth > 0)
+ cl.bob2_smooth -= bound(0, cl_bob2smooth.value, 1);
else
- cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
- // bob is proportional to velocity in the xy plane
- // (don't count Z, or jumping messes it up)
- bob = xyspeed * bound(0, cl_bob.value, 0.05);
- bob = bob*0.3 + bob*0.7*cycle;
- vieworg[2] += bob;
- // we also need to adjust gunorg, or this appears like pushing the gun!
- // In the old code, this was applied to vieworg BEFORE copying to gunorg,
- // but this is not viable with the new followmodel code as that would mean
- // that followmodel would work on the munged-by-bob vieworg and do feedback
- gunorg[2] += bob;
+ cl.bob2_smooth = 0;
}
- // horizontal view bobbing code
- if (cl_bob2.value && cl_bob2cycle.value)
- {
- vec3_t bob2vel;
- vec3_t forward, right, up;
- float side, front;
-
- cycle = cl.time / cl_bob2cycle.value;
- cycle -= (int) cycle;
- if (cycle < 0.5)
- cycle = cos(M_PI * cycle / 0.5); // cos looks better here with the other view bobbing using sin
- else
- cycle = cos(M_PI + M_PI * (cycle-0.5)/0.5);
- bob = bound(0, cl_bob2.value, 0.05) * cycle;
+ // calculate the front and side of the player between the X and Y axes
+ AngleVectors(viewangles, forward, right, up);
+ // now get the speed based on those angles. The bounds should match the same value as xyspeed's
+ side = bound(-400, DotProduct (cl.velocity, right) * cl.bob2_smooth, 400);
+ front = bound(-400, DotProduct (cl.velocity, forward) * cl.bob2_smooth, 400);
+ VectorScale(forward, bob, forward);
+ VectorScale(right, bob, right);
+ // we use side with forward and front with right, so the bobbing goes
+ // to the side when we walk forward and to the front when we strafe
+ VectorMAMAM(side, forward, front, right, 0, up, bob2vel);
+ vieworg[0] += bob2vel[0];
+ vieworg[1] += bob2vel[1];
+ // we also need to adjust gunorg, or this appears like pushing the gun!
+ // In the old code, this was applied to vieworg BEFORE copying to gunorg,
+ // but this is not viable with the new followmodel code as that would mean
+ // that followmodel would work on the munged-by-bob vieworg and do feedback
+ gunorg[0] += bob2vel[0];
+ gunorg[1] += bob2vel[1];
+ }
- // this value slowly decreases from 1 to 0 when we stop touching the ground.
- // The cycle is later multiplied with it so the view smooths back to normal
- if (cl.onground && !cl.cmd.jump) // also block the effect while the jump button is pressed, to avoid twitches when bunny-hopping
- cl.bob2_smooth = 1;
+ // fall bobbing code
+ // causes the view to swing down and back up when touching the ground
+ if (cl_bobfall.value && cl_bobfallcycle.value)
+ {
+ if (!clonground)
+ {
+ cl.bobfall_speed = bound(-400, cl.velocity[2], 0) * bound(0, cl_bobfall.value, 0.1);
+ if (cl.velocity[2] < -cl_bobfallminspeed.value)
+ cl.bobfall_swing = 1;
else
- {
- if(cl.bob2_smooth > 0)
- cl.bob2_smooth -= bound(0, cl_bob2smooth.value, 1);
- else
- cl.bob2_smooth = 0;
- }
-
- // calculate the front and side of the player between the X and Y axes
- AngleVectors(viewangles, forward, right, up);
- // now get the speed based on those angles. The bounds should match the same value as xyspeed's
- side = bound(-400, DotProduct (cl.velocity, right) * cl.bob2_smooth, 400);
- front = bound(-400, DotProduct (cl.velocity, forward) * cl.bob2_smooth, 400);
- VectorScale(forward, bob, forward);
- VectorScale(right, bob, right);
- // we use side with forward and front with right, so the bobbing goes
- // to the side when we walk forward and to the front when we strafe
- VectorMAMAM(side, forward, front, right, 0, up, bob2vel);
- vieworg[0] += bob2vel[0];
- vieworg[1] += bob2vel[1];
- // we also need to adjust gunorg, or this appears like pushing the gun!
- // In the old code, this was applied to vieworg BEFORE copying to gunorg,
- // but this is not viable with the new followmodel code as that would mean
- // that followmodel would work on the munged-by-bob vieworg and do feedback
- gunorg[0] += bob2vel[0];
- gunorg[1] += bob2vel[1];
+ cl.bobfall_swing = 0; // TODO really?
}
-
- // fall bobbing code
- // causes the view to swing down and back up when touching the ground
- if (cl_bobfall.value && cl_bobfallcycle.value)
+ else
{
- if (!cl.onground)
- {
- cl.bobfall_speed = bound(-400, cl.velocity[2], 0) * bound(0, cl_bobfall.value, 0.1);
- if (cl.velocity[2] < -cl_bobfallminspeed.value)
- cl.bobfall_swing = 1;
- else
- cl.bobfall_swing = 0; // TODO really?
- }
- else
- {
- cl.bobfall_swing = max(0, cl.bobfall_swing - cl_bobfallcycle.value * frametime);
+ cl.bobfall_swing = max(0, cl.bobfall_swing - cl_bobfallcycle.value * frametime);
- bobfall = sin(M_PI * cl.bobfall_swing) * cl.bobfall_speed;
- vieworg[2] += bobfall;
- gunorg[2] += bobfall;
- }
+ bobfall = sin(M_PI * cl.bobfall_swing) * cl.bobfall_speed;
+ vieworg[2] += bobfall;
+ gunorg[2] += bobfall;
}
+ }
- // gun model bobbing code
- if (cl_bobmodel.value)
+ // gun model bobbing code
+ if (cl_bobmodel.value)
+ {
+ // calculate for swinging gun model
+ // the gun bobs when running on the ground, but doesn't bob when you're in the air.
+ // Sajt: I tried to smooth out the transitions between bob and no bob, which works
+ // for the most part, but for some reason when you go through a message trigger or
+ // pick up an item or anything like that it will momentarily jolt the gun.
+ vec3_t forward, right, up;
+ float bspeed;
+ float s;
+ float t;
+
+ s = cl.time * cl_bobmodel_speed.value;
+ if (clonground)
{
- // calculate for swinging gun model
- // the gun bobs when running on the ground, but doesn't bob when you're in the air.
- // Sajt: I tried to smooth out the transitions between bob and no bob, which works
- // for the most part, but for some reason when you go through a message trigger or
- // pick up an item or anything like that it will momentarily jolt the gun.
- vec3_t forward, right, up;
- float bspeed;
- float s;
- float t;
-
- s = cl.time * cl_bobmodel_speed.value;
- if (cl.onground)
- {
- if (cl.time - cl.hitgroundtime < 0.2)
- {
- // just hit the ground, speed the bob back up over the next 0.2 seconds
- t = cl.time - cl.hitgroundtime;
- t = bound(0, t, 0.2);
- t *= 5;
- }
- else
- t = 1;
- }
- else
+ if (cl.time - cl.hitgroundtime < 0.2)
{
- // recently left the ground, slow the bob down over the next 0.2 seconds
- t = cl.time - cl.lastongroundtime;
- t = 0.2 - bound(0, t, 0.2);
+ // just hit the ground, speed the bob back up over the next 0.2 seconds
+ t = cl.time - cl.hitgroundtime;
+ t = bound(0, t, 0.2);
t *= 5;
}
-
- bspeed = xyspeed * 0.01f;
- AngleVectors (gunangles, forward, right, up);
- bob = bspeed * cl_bobmodel_side.value * cl_viewmodel_scale.value * sin (s) * t;
- VectorMA (gunorg, bob, right, gunorg);
- bob = bspeed * cl_bobmodel_up.value * cl_viewmodel_scale.value * cos (s * 2) * t;
- VectorMA (gunorg, bob, up, gunorg);
+ else
+ t = 1;
+ }
+ else
+ {
+ // recently left the ground, slow the bob down over the next 0.2 seconds
+ t = cl.time - cl.lastongroundtime;
+ t = 0.2 - bound(0, t, 0.2);
+ t *= 5;
}
+
+ bspeed = xyspeed * 0.01f;
+ AngleVectors (gunangles, forward, right, up);
+ bob = bspeed * cl_bobmodel_side.value * cl_viewmodel_scale.value * sin (s) * t;
+ VectorMA (gunorg, bob, right, gunorg);
+ bob = bspeed * cl_bobmodel_up.value * cl_viewmodel_scale.value * cos (s * 2) * t;
+ VectorMA (gunorg, bob, up, gunorg);
}
}
- // calculate a view matrix for rendering the scene
- if (v_idlescale.value)
- {
- viewangles[0] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
- viewangles[1] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
- viewangles[2] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
- }
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2], 1);
+ }
+ // calculate a view matrix for rendering the scene
+ if (v_idlescale.value)
+ {
+ viewangles[0] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
+ viewangles[1] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
+ viewangles[2] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
+ }
+ Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2], 1);
- // calculate a viewmodel matrix for use in view-attached entities
- Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
- Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);
+ // calculate a viewmodel matrix for use in view-attached entities
+ Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
+ Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);
- Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix_withbob, gunorg[0], gunorg[1], gunorg[2], gunangles[0], gunangles[1], gunangles[2], cl_viewmodel_scale.value);
- VectorCopy(vieworg, cl.csqc_vieworiginfromengine);
- VectorCopy(viewangles, cl.csqc_viewanglesfromengine);
+ Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix_withbob, gunorg[0], gunorg[1], gunorg[2], gunangles[0], gunangles[1], gunangles[2], cl_viewmodel_scale.value);
+ VectorCopy(vieworg, cl.csqc_vieworiginfromengine);
+ VectorCopy(viewangles, cl.csqc_viewanglesfromengine);
- Matrix4x4_Invert_Simple(&tmpmatrix, &r_refdef.view.matrix);
- Matrix4x4_Concat(&cl.csqc_viewmodelmatrixfromengine, &tmpmatrix, &viewmodelmatrix_withbob);
- }
+ Matrix4x4_Invert_Simple(&tmpmatrix, &r_refdef.view.matrix);
+ Matrix4x4_Concat(&cl.csqc_viewmodelmatrixfromengine, &tmpmatrix, &viewmodelmatrix_withbob);
+ }
+}
+
+void V_CalcRefdef (void)
+{
+ entity_t *ent;
+
+ if (cls.state == ca_connected && cls.signon == SIGNONS && !cl.csqc_server2csqcentitynumber[cl.playerentity])
+ {
+ // ent is the view entity (visible when out of body)
+ ent = &cl.entities[cl.viewentity];
+
+ V_CalcRefdefUsing(&ent->render.matrix, cl.viewangles, !ent->persistent.trail_allowed, cl.onground, cl.cmd.jump); // FIXME use a better way to detect teleport/warp than trail_allowed
+ }
+ else
+ {
+ viewmodelmatrix_nobob = identitymatrix;
+ viewmodelmatrix_withbob = identitymatrix;
+ cl.csqc_viewmodelmatrixfromengine = identitymatrix;
+ r_refdef.view.matrix = identitymatrix;
+ VectorClear(cl.csqc_vieworiginfromengine);
+ VectorCopy(cl.viewangles, cl.csqc_viewanglesfromengine);
}
}
===============
*/
-void World_SetSize(world_t *world, const char *filename, const vec3_t mins, const vec3_t maxs)
+void World_SetSize(world_t *world, const char *filename, const vec3_t mins, const vec3_t maxs, prvm_prog_t *prog)
{
int i;
strlcpy(world->filename, filename, sizeof(world->filename));
VectorCopy(mins, world->mins);
VectorCopy(maxs, world->maxs);
+ world->prog = prog;
// the areagrid_marknumber is not allowed to be 0
if (world->areagrid_marknumber < 1)
*/
void World_UnlinkAll(world_t *world)
{
+ prvm_prog_t *prog = world->prog;
int i;
link_t *grid;
// unlink all entities one by one
}
}
-int World_EntitiesInBox(world_t *world, const vec3_t mins, const vec3_t maxs, int maxlist, prvm_edict_t **list)
+int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t requestmaxs, int maxlist, prvm_edict_t **list)
{
+ prvm_prog_t *prog = world->prog;
int numlist;
link_t *grid;
link_t *l;
prvm_edict_t *ent;
+ vec3_t paddedmins, paddedmaxs;
int igrid[3], igridmins[3], igridmaxs[3];
+ VectorSet(paddedmins, requestmins[0] - 1.0f, requestmins[1] - 1.0f, requestmins[2] - 1.0f);
+ VectorSet(paddedmaxs, requestmaxs[0] + 1.0f, requestmaxs[1] + 1.0f, requestmaxs[2] + 1.0f);
+
// FIXME: if areagrid_marknumber wraps, all entities need their
// ent->priv.server->areagridmarknumber reset
world->areagrid_stats_calls++;
world->areagrid_marknumber++;
- igridmins[0] = (int) floor((mins[0] + world->areagrid_bias[0]) * world->areagrid_scale[0]);
- igridmins[1] = (int) floor((mins[1] + world->areagrid_bias[1]) * world->areagrid_scale[1]);
- //igridmins[2] = (int) ((mins[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]);
- igridmaxs[0] = (int) floor((maxs[0] + world->areagrid_bias[0]) * world->areagrid_scale[0]) + 1;
- igridmaxs[1] = (int) floor((maxs[1] + world->areagrid_bias[1]) * world->areagrid_scale[1]) + 1;
- //igridmaxs[2] = (int) ((maxs[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]) + 1;
+ igridmins[0] = (int) floor((paddedmins[0] + world->areagrid_bias[0]) * world->areagrid_scale[0]);
+ igridmins[1] = (int) floor((paddedmins[1] + world->areagrid_bias[1]) * world->areagrid_scale[1]);
+ //igridmins[2] = (int) ((paddedmins[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]);
+ igridmaxs[0] = (int) floor((paddedmaxs[0] + world->areagrid_bias[0]) * world->areagrid_scale[0]) + 1;
+ igridmaxs[1] = (int) floor((paddedmaxs[1] + world->areagrid_bias[1]) * world->areagrid_scale[1]) + 1;
+ //igridmaxs[2] = (int) ((paddedmaxs[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]) + 1;
igridmins[0] = max(0, igridmins[0]);
igridmins[1] = max(0, igridmins[1]);
//igridmins[2] = max(0, igridmins[2]);
igridmaxs[1] = min(AREA_GRID, igridmaxs[1]);
//igridmaxs[2] = min(AREA_GRID, igridmaxs[2]);
+ // paranoid debugging
+ //VectorSet(igridmins, 0, 0, 0);VectorSet(igridmaxs, AREA_GRID, AREA_GRID, AREA_GRID);
+
numlist = 0;
// add entities not linked into areagrid because they are too big or
// outside the grid bounds
- if (world->areagrid_outside.next != &world->areagrid_outside)
+ if (world->areagrid_outside.next)
{
grid = &world->areagrid_outside;
for (l = grid->next;l != grid;l = l->next)
if (ent->priv.server->areagridmarknumber != world->areagrid_marknumber)
{
ent->priv.server->areagridmarknumber = world->areagrid_marknumber;
- if (!ent->priv.server->free && BoxesOverlap(mins, maxs, ent->priv.server->areamins, ent->priv.server->areamaxs))
+ if (!ent->priv.server->free && BoxesOverlap(paddedmins, paddedmaxs, ent->priv.server->areamins, ent->priv.server->areamaxs))
{
if (numlist < maxlist)
list[numlist] = ent;
grid = world->areagrid + igrid[1] * AREA_GRID + igridmins[0];
for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++)
{
- if (grid->next != grid)
+ if (grid->next)
{
for (l = grid->next;l != grid;l = l->next)
{
if (ent->priv.server->areagridmarknumber != world->areagrid_marknumber)
{
ent->priv.server->areagridmarknumber = world->areagrid_marknumber;
- if (!ent->priv.server->free && BoxesOverlap(mins, maxs, ent->priv.server->areamins, ent->priv.server->areamaxs))
+ if (!ent->priv.server->free && BoxesOverlap(paddedmins, paddedmaxs, ent->priv.server->areamins, ent->priv.server->areamaxs))
{
if (numlist < maxlist)
list[numlist] = ent;
return numlist;
}
-void World_LinkEdict_AreaGrid(world_t *world, prvm_edict_t *ent)
+static void World_LinkEdict_AreaGrid(world_t *world, prvm_edict_t *ent)
{
+ prvm_prog_t *prog = world->prog;
link_t *grid;
int igrid[3], igridmins[3], igridmaxs[3], gridnum, entitynumber = PRVM_NUM_FOR_EDICT(ent);
*/
void World_LinkEdict(world_t *world, prvm_edict_t *ent, const vec3_t mins, const vec3_t maxs)
{
+ prvm_prog_t *prog = world->prog;
// unlink from old position first
if (ent->priv.server->areagrid[0].prev)
World_UnlinkEdict(ent);
#define USEODE 1
#endif
-// recent ODE trunk has dWorldStepFast1 removed
-//#define ODE_USE_STEPFAST
-
#ifdef USEODE
cvar_t physics_ode_quadtree_depth = {0, "physics_ode_quadtree_depth","5", "desired subdivision level of quadtree culling space"};
cvar_t physics_ode_contactsurfacelayer = {0, "physics_ode_contactsurfacelayer","1", "allows objects to overlap this many units to reduce jitter"};
-cvar_t physics_ode_worldstep = {0, "physics_ode_worldstep","2", "step function to use, 0 - dWorldStep, 1 - dWorldStepFast1, 2 - dWorldQuickStep"};
-cvar_t physics_ode_worldstep_iterations = {0, "physics_ode_worldstep_iterations", "20", "parameter to dWorldQuickStep and dWorldStepFast1"};
+cvar_t physics_ode_worldstep_iterations = {0, "physics_ode_worldstep_iterations", "20", "parameter to dWorldQuickStep"};
cvar_t physics_ode_contact_mu = {0, "physics_ode_contact_mu", "1", "contact solver mu parameter - friction pyramid approximation 1 (see ODE User Guide)"};
cvar_t physics_ode_contact_erp = {0, "physics_ode_contact_erp", "0.96", "contact solver erp parameter - Error Restitution Percent (see ODE User Guide)"};
cvar_t physics_ode_contact_cfm = {0, "physics_ode_contact_cfm", "0", "contact solver cfm parameter - Constraint Force Mixing (see ODE User Guide)"};
cvar_t physics_ode_world_damping_linear_threshold = {0, "physics_ode_world_damping_linear_threshold", "0.01", "world linear damping threshold (see ODE User Guide); use defaults when set to -1"};
cvar_t physics_ode_world_damping_angular = {0, "physics_ode_world_damping_angular", "0.005", "world angular damping scale (see ODE User Guide); use defaults when set to -1"};
cvar_t physics_ode_world_damping_angular_threshold = {0, "physics_ode_world_damping_angular_threshold", "0.01", "world angular damping threshold (see ODE User Guide); use defaults when set to -1"};
+cvar_t physics_ode_world_gravitymod = {0, "physics_ode_world_gravitymod", "1", "multiplies gravity got from sv_gravity, this may be needed to tweak if strong damping is used"};
cvar_t physics_ode_iterationsperframe = {0, "physics_ode_iterationsperframe", "1", "divisor for time step, runs multiple physics steps per frame"};
-cvar_t physics_ode_constantstep = {0, "physics_ode_constantstep", "1", "use constant step (sys_ticrate value) instead of variable step which tends to increase stability"};
+cvar_t physics_ode_constantstep = {0, "physics_ode_constantstep", "1", "use constant step instead of variable step which tends to increase stability, if set to 1 uses sys_ticrate, instead uses it's own value"};
cvar_t physics_ode_autodisable = {0, "physics_ode_autodisable", "1", "automatic disabling of objects which dont move for long period of time, makes object stacking a lot faster"};
cvar_t physics_ode_autodisable_steps = {0, "physics_ode_autodisable_steps", "10", "how many steps object should be dormant to be autodisabled"};
cvar_t physics_ode_autodisable_time = {0, "physics_ode_autodisable_time", "0", "how many seconds object should be dormant to be autodisabled"};
//void (ODE_API *dMassSetCapsule)(dMass *, dReal density, int direction, dReal radius, dReal length);
void (ODE_API *dMassSetCapsuleTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length);
//void (ODE_API *dMassSetCylinder)(dMass *, dReal density, int direction, dReal radius, dReal length);
-//void (ODE_API *dMassSetCylinderTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length);
+void (ODE_API *dMassSetCylinderTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length);
//void (ODE_API *dMassSetBox)(dMass *, dReal density, dReal lx, dReal ly, dReal lz);
void (ODE_API *dMassSetBoxTotal)(dMass *, dReal total_mass, dReal lx, dReal ly, dReal lz);
//void (ODE_API *dMassSetTrimesh)(dMass *, dReal density, dGeomID g);
//dReal (ODE_API *dWorldGetERP)(dWorldID);
void (ODE_API *dWorldSetCFM)(dWorldID, dReal cfm);
//dReal (ODE_API *dWorldGetCFM)(dWorldID);
-void (ODE_API *dWorldStep)(dWorldID, dReal stepsize);
+//void (ODE_API *dWorldStep)(dWorldID, dReal stepsize);
//void (ODE_API *dWorldImpulseToForce)(dWorldID, dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force);
void (ODE_API *dWorldQuickStep)(dWorldID w, dReal stepsize);
void (ODE_API *dWorldSetQuickStepNumIterations)(dWorldID, int num);
//dReal (ODE_API *dWorldGetContactMaxCorrectingVel)(dWorldID);
void (ODE_API *dWorldSetContactSurfaceLayer)(dWorldID, dReal depth);
//dReal (ODE_API *dWorldGetContactSurfaceLayer)(dWorldID);
-#ifdef ODE_USE_STEPFAST
-void (ODE_API *dWorldStepFast1)(dWorldID, dReal stepsize, int maxiterations);
-#endif
+//void (ODE_API *dWorldStepFast1)(dWorldID, dReal stepsize, int maxiterations);
//void (ODE_API *dWorldSetAutoEnableDepthSF1)(dWorldID, int autoEnableDepth);
//int (ODE_API *dWorldGetAutoEnableDepthSF1)(dWorldID);
//dReal (ODE_API *dWorldGetAutoDisableLinearThreshold)(dWorldID);
//void (ODE_API *dGeomCapsuleGetParams)(dGeomID ccylinder, dReal *radius, dReal *length);
//dReal (ODE_API *dGeomCapsulePointDepth)(dGeomID ccylinder, dReal x, dReal y, dReal z);
//
-//dGeomID (ODE_API *dCreateCylinder)(dSpaceID space, dReal radius, dReal length);
+dGeomID (ODE_API *dCreateCylinder)(dSpaceID space, dReal radius, dReal length);
//void (ODE_API *dGeomCylinderSetParams)(dGeomID cylinder, dReal radius, dReal length);
//void (ODE_API *dGeomCylinderGetParams)(dGeomID cylinder, dReal *radius, dReal *length);
//
// {"dMassSetCapsule", (void **) &dMassSetCapsule},
{"dMassSetCapsuleTotal", (void **) &dMassSetCapsuleTotal},
// {"dMassSetCylinder", (void **) &dMassSetCylinder},
-// {"dMassSetCylinderTotal", (void **) &dMassSetCylinderTotal},
+ {"dMassSetCylinderTotal", (void **) &dMassSetCylinderTotal},
// {"dMassSetBox", (void **) &dMassSetBox},
{"dMassSetBoxTotal", (void **) &dMassSetBoxTotal},
// {"dMassSetTrimesh", (void **) &dMassSetTrimesh},
// {"dWorldGetERP", (void **) &dWorldGetERP},
{"dWorldSetCFM", (void **) &dWorldSetCFM},
// {"dWorldGetCFM", (void **) &dWorldGetCFM},
- {"dWorldStep", (void **) &dWorldStep},
+// {"dWorldStep", (void **) &dWorldStep},
// {"dWorldImpulseToForce", (void **) &dWorldImpulseToForce},
{"dWorldQuickStep", (void **) &dWorldQuickStep},
{"dWorldSetQuickStepNumIterations", (void **) &dWorldSetQuickStepNumIterations},
// {"dWorldGetContactMaxCorrectingVel", (void **) &dWorldGetContactMaxCorrectingVel},
{"dWorldSetContactSurfaceLayer", (void **) &dWorldSetContactSurfaceLayer},
// {"dWorldGetContactSurfaceLayer", (void **) &dWorldGetContactSurfaceLayer},
-#ifdef ODE_USE_STEPFAST
- {"dWorldStepFast1", (void **) &dWorldStepFast1},
-#endif
+// {"dWorldStepFast1", (void **) &dWorldStepFast1},
// {"dWorldSetAutoEnableDepthSF1", (void **) &dWorldSetAutoEnableDepthSF1},
// {"dWorldGetAutoEnableDepthSF1", (void **) &dWorldGetAutoEnableDepthSF1},
// {"dWorldGetAutoDisableLinearThreshold", (void **) &dWorldGetAutoDisableLinearThreshold},
// {"dGeomCapsuleSetParams", (void **) &dGeomCapsuleSetParams},
// {"dGeomCapsuleGetParams", (void **) &dGeomCapsuleGetParams},
// {"dGeomCapsulePointDepth", (void **) &dGeomCapsulePointDepth},
-// {"dCreateCylinder", (void **) &dCreateCylinder},
+ {"dCreateCylinder", (void **) &dCreateCylinder},
// {"dGeomCylinderSetParams", (void **) &dGeomCylinderSetParams},
// {"dGeomCylinderGetParams", (void **) &dGeomCylinderGetParams},
// {"dCreateRay", (void **) &dCreateRay},
Cvar_RegisterVariable(&physics_ode_quadtree_depth);
Cvar_RegisterVariable(&physics_ode_contactsurfacelayer);
- Cvar_RegisterVariable(&physics_ode_worldstep);
Cvar_RegisterVariable(&physics_ode_worldstep_iterations);
Cvar_RegisterVariable(&physics_ode_contact_mu);
Cvar_RegisterVariable(&physics_ode_contact_erp);
Cvar_RegisterVariable(&physics_ode_world_damping_linear_threshold);
Cvar_RegisterVariable(&physics_ode_world_damping_angular);
Cvar_RegisterVariable(&physics_ode_world_damping_angular_threshold);
+ Cvar_RegisterVariable(&physics_ode_world_gravitymod);
Cvar_RegisterVariable(&physics_ode_iterationsperframe);
Cvar_RegisterVariable(&physics_ode_constantstep);
Cvar_RegisterVariable(&physics_ode_movelimit);
#ifdef USEODE
static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed)
{
+ prvm_prog_t *prog = world->prog;
const dReal *avel;
const dReal *o;
const dReal *r; // for some reason dBodyGetRotation returns a [3][4] matrix
{
float pitchsign = 1;
- if(!strcmp(prog->name, "server")) // FIXME some better way?
+ if(prog == SVVM_prog) // FIXME some better way?
{
- pitchsign = SV_GetPitchSign(ed);
+ pitchsign = SV_GetPitchSign(prog, ed);
}
- else if(!strcmp(prog->name, "client"))
+ else if(prog == CLVM_prog)
{
- pitchsign = CL_GetPitchSign(ed);
+ pitchsign = CL_GetPitchSign(prog, ed);
}
angles[PITCH] *= pitchsign;
avelocity[PITCH] *= pitchsign;
VectorCopy(avelocity, ed->priv.server->ode_avelocity);
ed->priv.server->ode_gravity = dBodyGetGravityMode(body) != 0;
- if(!strcmp(prog->name, "server")) // FIXME some better way?
+ if(prog == SVVM_prog) // FIXME some better way?
{
SV_LinkEdict(ed);
SV_LinkEdict_TouchAreaGrid(ed);
static void World_Physics_Frame_JointFromEntity(world_t *world, prvm_edict_t *ed)
{
+ prvm_prog_t *prog = world->prog;
dJointID j = 0;
dBodyID b1 = 0;
dBodyID b2 = 0;
static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
{
+ prvm_prog_t *prog = world->prog;
const float *iv;
const int *ie;
dBodyID body = (dBodyID)ed->priv.server->ode_body;
movetype = (int)PRVM_gameedictfloat(ed, movetype);
scale = PRVM_gameedictfloat(ed, scale);if (!scale) scale = 1.0f;
modelindex = 0;
- if (world == &sv.world)
- mempool = sv_mempool;
- else if (world == &cl.world)
- mempool = cls.levelmempool;
- else
- mempool = NULL;
+ mempool = prog->progs_mempool;
model = NULL;
switch(solid)
{
case SOLID_BSP:
+ case SOLID_PHYSICS_TRIMESH:
modelindex = (int)PRVM_gameedictfloat(ed, modelindex);
if (world == &sv.world)
model = SV_GetModelByIndex(modelindex);
if (movetype != MOVETYPE_PHYSICS)
massval = 1.0f;
+ // get friction from entity
+ if (PRVM_gameedictfloat(ed, friction))
+ ed->priv.server->ode_friction = PRVM_gameedictfloat(ed, friction);
+ else
+ ed->priv.server->ode_friction = 1.0;
+
// check if we need to create or replace the geom
if (!ed->priv.server->ode_physics
|| !VectorCompare(ed->priv.server->ode_mins, entmins)
ed->priv.server->ode_mass = massval;
ed->priv.server->ode_modelindex = modelindex;
VectorMAM(0.5f, entmins, 0.5f, entmaxs, geomcenter);
+ if (PRVM_gameedictvector(ed, massofs))
+ VectorCopy(geomcenter, PRVM_gameedictvector(ed, massofs));
+ else
+ VectorMAM(0.5f, entmins, 0.5f, entmaxs, geomcenter);
ed->priv.server->ode_movelimit = min(geomsize[0], min(geomsize[1], geomsize[2]));
-
if (massval * geomsize[0] * geomsize[1] * geomsize[2] == 0)
{
if (movetype == MOVETYPE_PHYSICS)
- Con_Printf("entity %i (classname %s) .mass * .size_x * .size_y * .size_z == 0\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_gameedictstring(ed, classname)));
+ Con_Printf("entity %i (classname %s) .mass * .size_x * .size_y * .size_z == 0\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)));
massval = 1.0f;
VectorSet(geomsize, 1.0f, 1.0f, 1.0f);
}
switch(solid)
{
case SOLID_BSP:
+ case SOLID_PHYSICS_TRIMESH:
ed->priv.server->ode_offsetmatrix = identitymatrix;
if (!model)
{
- Con_Printf("entity %i (classname %s) has no model\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_gameedictstring(ed, classname)));
+ Con_Printf("entity %i (classname %s) has no model\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)));
goto treatasbox;
}
// add an optimized mesh to the model containing only the SUPERCONTENTS_SOLID surfaces
Mod_CreateCollisionMesh(model);
if (!model->brush.collisionmesh || !model->brush.collisionmesh->numtriangles)
{
- Con_Printf("entity %i (classname %s) has no geometry\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_gameedictstring(ed, classname)));
+ Con_Printf("entity %i (classname %s) has no geometry\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)));
goto treatasbox;
}
// ODE requires persistent mesh storage, so we need to copy out
dMassSetSphereTotal(&mass, massval, geomsize[0] * 0.5f);
break;
case SOLID_PHYSICS_CAPSULE:
+ case SOLID_PHYSICS_CYLINDER:
axisindex = 0;
if (geomsize[axisindex] < geomsize[1])
axisindex = 1;
// because we want to support more than one axisindex, we have to
// create a transform, and turn on its cleanup setting (which will
// cause the child to be destroyed when it is destroyed)
- ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length);
- dMassSetCapsuleTotal(&mass, massval, axisindex+1, radius, length);
+ if (solid == SOLID_PHYSICS_CAPSULE)
+ {
+ ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length);
+ dMassSetCapsuleTotal(&mass, massval, axisindex+1, radius, length);
+ }
+ else
+ {
+ ed->priv.server->ode_geom = (void *)dCreateCylinder((dSpaceID)world->physics.ode_space, radius, length);
+ dMassSetCylinderTotal(&mass, massval, axisindex+1, radius, length);
+ }
break;
default:
Sys_Error("World_Physics_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid);
memcpy(ed->priv.server->ode_massbuf, &mass, sizeof(dMass));
}
- if(ed->priv.server->ode_geom)
+ if (ed->priv.server->ode_geom)
dGeomSetData((dGeomID)ed->priv.server->ode_geom, (void*)ed);
if (movetype == MOVETYPE_PHYSICS && ed->priv.server->ode_geom)
{
VectorCopy(angles, qangles);
VectorCopy(avelocity, qavelocity);
- if(!strcmp(prog->name, "server")) // FIXME some better way?
+ if(prog == SVVM_prog) // FIXME some better way?
{
- pitchsign = SV_GetPitchSign(ed);
+ pitchsign = SV_GetPitchSign(prog, ed);
}
- else if(!strcmp(prog->name, "client"))
+ else if(prog == CLVM_prog)
{
- pitchsign = CL_GetPitchSign(ed);
+ pitchsign = CL_GetPitchSign(prog, ed);
}
qangles[PITCH] *= pitchsign;
qavelocity[PITCH] *= pitchsign;
modified = true;
//Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .axis_forward = '%f %f %f' .axis_left = '%f %f %f' .axis_up = %f %f %f' .spinvelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_gameedictstring(ed, classname)), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], forward[0], forward[1], forward[2], left[0], left[1], left[2], up[0], up[1], up[2], spinvelocity[0], spinvelocity[1], spinvelocity[2]);
if (physics_ode_trick_fixnan.integer >= 2)
- Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .angles = '%f %f %f' .avelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_gameedictstring(ed, classname)), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], angles[0], angles[1], angles[2], avelocity[0], avelocity[1], avelocity[2]);
+ Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .angles = '%f %f %f' .avelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], angles[0], angles[1], angles[2], avelocity[0], avelocity[1], avelocity[2]);
test = VectorLength2(origin);
if (IS_NAN(test))
VectorClear(origin);
if(gravity != ed->priv.server->ode_gravity)
Con_Printf(" gravity: %i -> %i\n", ed->priv.server->ode_gravity, gravity);
#endif
-
// values for BodyFromEntity to check if the qc modified anything later
VectorCopy(origin, ed->priv.server->ode_origin);
VectorCopy(velocity, ed->priv.server->ode_velocity);
static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
world_t *world = (world_t *)data;
+ prvm_prog_t *prog = world->prog;
dContact contact[MAX_CONTACTS]; // max contacts per collision pair
dBodyID b1;
dBodyID b2;
bouncestop2 = 60.0f / 800.0f;
}
- if(!strcmp(prog->name, "server"))
+ if(prog == SVVM_prog)
{
if(ed1 && PRVM_serveredictfunction(ed1, touch))
{
for (i = 0;i < numcontacts;i++)
{
contact[i].surface.mode = (physics_ode_contact_mu.value != -1 ? dContactApprox1 : 0) | (physics_ode_contact_erp.value != -1 ? dContactSoftERP : 0) | (physics_ode_contact_cfm.value != -1 ? dContactSoftCFM : 0) | (bouncefactor1 > 0 ? dContactBounce : 0);
- contact[i].surface.mu = physics_ode_contact_mu.value;
+ contact[i].surface.mu = physics_ode_contact_mu.value * ed1->priv.server->ode_friction * ed2->priv.server->ode_friction;
contact[i].surface.soft_erp = physics_ode_contact_erp.value;
contact[i].surface.soft_cfm = physics_ode_contact_cfm.value;
contact[i].surface.bounce = bouncefactor1;
void World_Physics_Frame(world_t *world, double frametime, double gravity)
{
+ prvm_prog_t *prog = world->prog;
double tdelta, tdelta2, tdelta3, simulationtime, collisiontime;
- tdelta = Sys_DoubleTime();
+ tdelta = Sys_DirtyTime();
#ifdef USEODE
if (world->physics.ode && physics_ode.integer)
{
prvm_edict_t *ed;
world->physics.ode_iterations = bound(1, physics_ode_iterationsperframe.integer, 1000);
- if (physics_ode_constantstep.integer)
- world->physics.ode_step = sys_ticrate.value / world->physics.ode_iterations;
+ if (physics_ode_constantstep.integer > 0 && physics_ode_constantstep.integer < 1)
+ world->physics.ode_step = physics_ode_constantstep.integer / world->physics.ode_iterations;
+ else if (physics_ode_constantstep.integer)
+ world->physics.ode_step = sys_ticrate.integer / world->physics.ode_iterations;
else
world->physics.ode_step = frametime / world->physics.ode_iterations;
world->physics.ode_movelimit = physics_ode_movelimit.value / world->physics.ode_step;
World_Physics_Frame_JointFromEntity(world, ed);
}
- tdelta2 = Sys_DoubleTime();
+ tdelta2 = Sys_DirtyTime();
collisiontime = 0;
for (i = 0;i < world->physics.ode_iterations;i++)
{
// set the gravity
- dWorldSetGravity((dWorldID)world->physics.ode_world, 0, 0, -gravity);
+ dWorldSetGravity((dWorldID)world->physics.ode_world, 0, 0, -gravity * physics_ode_world_gravitymod.value);
// set the tolerance for closeness of objects
dWorldSetContactSurfaceLayer((dWorldID)world->physics.ode_world, max(0, physics_ode_contactsurfacelayer.value));
// run collisions for the current world state, creating JointGroup
- tdelta3 = Sys_DoubleTime();
+ tdelta3 = Sys_DirtyTime();
dSpaceCollide((dSpaceID)world->physics.ode_space, (void *)world, nearCallback);
- collisiontime += (Sys_DoubleTime() - tdelta3)*10000;
+ collisiontime += (Sys_DirtyTime() - tdelta3)*10000;
// run physics (move objects, calculate new velocities)
- if (physics_ode_worldstep.integer == 2)
- {
- dWorldSetQuickStepNumIterations((dWorldID)world->physics.ode_world, bound(1, physics_ode_worldstep_iterations.integer, 200));
+ // be sure not to pass 0 as step time because that causes an ODE error
+ dWorldSetQuickStepNumIterations((dWorldID)world->physics.ode_world, bound(1, physics_ode_worldstep_iterations.integer, 200));
+ if (world->physics.ode_step > 0)
dWorldQuickStep((dWorldID)world->physics.ode_world, world->physics.ode_step);
- }
-#ifdef ODE_USE_STEPFAST
- else if (physics_ode_worldstep.integer == 1)
- dWorldStepFast1((dWorldID)world->physics.ode_world, world->physics.ode_step, bound(1, physics_ode_worldstep_iterations.integer, 200));
-#endif
- else
- dWorldStep((dWorldID)world->physics.ode_world, world->physics.ode_step);
// clear the JointGroup now that we're done with it
dJointGroupEmpty((dJointGroupID)world->physics.ode_contactgroup);
}
- simulationtime = (Sys_DoubleTime() - tdelta2)*10000;
+ simulationtime = (Sys_DirtyTime() - tdelta2)*10000;
// copy physics properties from physics engine to entities and do some stats
if (prog)
if (dBodyIsEnabled(body))
world->physics.ode_activeovjects++;
}
- Con_Printf("ODE Stats(%s): %3.01f (%3.01f collision) %3.01f total : %i objects %i active %i disabled\n", prog->name, simulationtime, collisiontime, (Sys_DoubleTime() - tdelta)*10000, world->physics.ode_numobjects, world->physics.ode_activeovjects, (world->physics.ode_numobjects - world->physics.ode_activeovjects));
+ Con_Printf("ODE Stats(%s): %3.01f (%3.01f collision) %3.01f total : %i objects %i active %i disabled\n", prog->name, simulationtime, collisiontime, (Sys_DirtyTime() - tdelta)*10000, world->physics.ode_numobjects, world->physics.ode_activeovjects, (world->physics.ode_numobjects - world->physics.ode_activeovjects));
}
}
}
void *ode_world;
void *ode_space;
void *ode_contactgroup;
- // number of constraint solver iterations to use (for dWorldStepFast)
+ // number of constraint solver iterations to use (for dWorldQuickStep)
int ode_iterations;
// actual step (server frametime / ode_iterations)
vec_t ode_step;
}
world_physics_t;
+struct prvm_prog_s;
+
typedef struct world_s
{
// convenient fields
char filename[MAX_QPATH];
vec3_t mins;
vec3_t maxs;
+ struct prvm_prog_s *prog;
int areagrid_stats_calls;
int areagrid_stats_nodechecks;
void World_Shutdown(void);
/// called after the world model has been loaded, before linking any entities
-void World_SetSize(world_t *world, const char *filename, const vec3_t mins, const vec3_t maxs);
+void World_SetSize(world_t *world, const char *filename, const vec3_t mins, const vec3_t maxs, struct prvm_prog_s *prog);
/// unlinks all entities (used before reallocation of edicts)
void World_UnlinkAll(world_t *world);
// change physics properties of entity
struct prvm_edict_s;
struct edict_odefunc_s;
-//void World_Physics_ApplyCmd(prvm_edict_s *ed, edict_odefunc_s *f);
+void World_Physics_ApplyCmd(struct prvm_edict_s *ed, struct edict_odefunc_s *f);
// remove physics data from entity
// this is called by entity removal
// Z_zone.c
#include "quakedef.h"
+#include "thread.h"
#ifdef WIN32
#include <windows.h>
unsigned int sentinel_seed;
qboolean mem_bigendian = false;
+void *mem_mutex = NULL;
// LordHavoc: enables our own low-level allocator (instead of malloc)
#define MEMCLUMPING 0
}
if (pool == NULL)
Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
+ if (mem_mutex)
+ Thread_LockMutex(mem_mutex);
if (developer_memory.integer)
Con_DPrintf("Mem_Alloc: pool %s, file %s:%i, size %i bytes\n", pool->name, filename, fileline, (int)size);
//if (developer.integer > 0 && developer_memorydebug.integer)
if (mem->next)
mem->next->prev = mem;
+ if (mem_mutex)
+ Thread_UnlockMutex(mem_mutex);
+
// copy the shared portion in the case of a realloc, then memset the rest
sharedsize = 0;
remainsize = size;
// unlink memheader from doubly linked list
if ((mem->prev ? mem->prev->next != mem : pool->chain != mem) || (mem->next && mem->next->prev != mem))
Sys_Error("Mem_Free: not allocated or double freed (free at %s:%i)", filename, fileline);
+ if (mem_mutex)
+ Thread_LockMutex(mem_mutex);
if (mem->prev)
mem->prev->next = mem->next;
else
pool->totalsize -= size;
pool->realsize -= realsize;
Clump_FreeBlock(mem->baseaddress, realsize);
+ if (mem_mutex)
+ Thread_UnlockMutex(mem_mutex);
}
void _Mem_Free(void *data, const char *filename, int fileline)
void *Mem_ExpandableArray_AllocRecordAtIndex(memexpandablearray_t *l, size_t index)
{
size_t j;
- if (index == l->numarrays)
+ if (index >= l->numarrays)
{
if (l->numarrays == l->maxarrays)
{
}
}
-void MemList_f(void)
+static void MemList_f(void)
{
switch(Cmd_Argc())
{
}
}
-extern void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean printtotal);
-void MemStats_f(void)
+static void MemStats_f(void)
{
Mem_CheckSentinelsGlobal();
R_TextureStats_Print(false, false, true);
poolchain = NULL;
tempmempool = Mem_AllocPool("Temporary Memory", POOLFLAG_TEMP, NULL);
zonemempool = Mem_AllocPool("Zone", 0, NULL);
+
+ if (Thread_HasThreads())
+ mem_mutex = Thread_CreateMutex();
}
void Memory_Shutdown (void)
{
// Mem_FreePool (&zonemempool);
// Mem_FreePool (&tempmempool);
+
+ if (mem_mutex)
+ Thread_DestroyMutex(mem_mutex);
+ mem_mutex = NULL;
}
void Memory_Init_Commands (void)