1
0
Fork 0
forked from fte/fteqw

playdemo should now play older protocol versions.

some more tweaks for xonotic
rcon-over-xmpp, because I can. Server might see your rcon password, so watch out for that.
qcc tweaks.
updated q1qvm api stuff to api version 15.
android port updated. egl now handled by native code, which means we now have proper control over everything and can default to gles2. requires android 2.0+. vulkan-on-android renderer added, but not tested.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5153 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-10-12 12:02:25 +00:00
parent 8e44dde063
commit 696c7e8260
50 changed files with 4017 additions and 1879 deletions

View file

@ -591,7 +591,7 @@ qboolean CL_GetDemoMessage (void)
if (msglength > net_message.maxsize)
{
Con_Printf ("Demo message > MAX_MSGLEN");
Con_Printf ("Demo message > MAX_MSGLEN\n");
CL_StopPlayback ();
return 0;
}

View file

@ -4606,7 +4606,7 @@ void CL_ParsePlayerinfo (void)
if (flags & PF_COMMAND)
{
MSG_ReadDeltaUsercmd (&nullcmd, &state->command);
MSG_ReadDeltaUsercmd (&nullcmd, &state->command, cl.protocol_qw);
state->viewangles[0] = state->command.angles[0] * (360.0/65536);
state->viewangles[1] = state->command.angles[1] * (360.0/65536);

View file

@ -1613,6 +1613,7 @@ void CL_ClearState (void)
CL_ResetFog(0);
CL_ResetFog(1);
cl.protocol_qw = PROTOCOL_VERSION_QW; //until we get an svc_serverdata
cl.allocated_client_slots = QWMAX_CLIENTS;
#ifndef CLIENTONLY
//FIXME: we should just set it to 0 to make sure its set up properly elsewhere.
@ -5964,6 +5965,7 @@ void CL_ExecInitialConfigs(char *resetcommand)
void Host_FinishLoading(void)
{
extern qboolean r_forceheadless;
extern int r_blockvidrestart;
if (r_blockvidrestart == true)
{
@ -6016,12 +6018,9 @@ void Host_FinishLoading(void)
if (PM_IsApplying(true))
return;
#ifdef ANDROID
//android needs to wait a bit longer before it's allowed to init its video properly.
extern int sys_glesversion;
if (!sys_glesversion)
//android may find that it has no renderer at various points.
if (r_forceheadless)
return;
#endif
if (r_blockvidrestart == 2)
{ //2 is part of the initial startup

View file

@ -3101,6 +3101,7 @@ static void CLQW_ParseServerData (void)
Stats_NewMap();
#endif
cl.servercount = svcnt;
cl.protocol_qw = protover;
Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc"));
@ -3216,17 +3217,33 @@ static void CLQW_ParseServerData (void)
str = MSG_ReadString ();
Q_strncpyz (cl.levelname, str, sizeof(cl.levelname));
// get the movevars
movevars.gravity = MSG_ReadFloat();
movevars.stopspeed = MSG_ReadFloat();
maxspeed = MSG_ReadFloat();
movevars.spectatormaxspeed = MSG_ReadFloat();
movevars.accelerate = MSG_ReadFloat();
movevars.airaccelerate = MSG_ReadFloat();
movevars.wateraccelerate = MSG_ReadFloat();
movevars.friction = MSG_ReadFloat();
movevars.waterfriction = MSG_ReadFloat();
entgrav = MSG_ReadFloat();
if (cl.protocol_qw >= 25)
{
// get the movevars
movevars.gravity = MSG_ReadFloat();
movevars.stopspeed = MSG_ReadFloat();
maxspeed = MSG_ReadFloat();
movevars.spectatormaxspeed = MSG_ReadFloat();
movevars.accelerate = MSG_ReadFloat();
movevars.airaccelerate = MSG_ReadFloat();
movevars.wateraccelerate = MSG_ReadFloat();
movevars.friction = MSG_ReadFloat();
movevars.waterfriction = MSG_ReadFloat();
entgrav = MSG_ReadFloat();
}
else
{
movevars.gravity = 800;
movevars.stopspeed = 100;
maxspeed = 320;
movevars.spectatormaxspeed = 500;
movevars.accelerate = 10;
movevars.airaccelerate = 0.7f;
movevars.wateraccelerate = 10;
movevars.friction = 6.0f;
movevars.waterfriction = 1;
entgrav = 1;
}
for (clnum = 0; clnum < cl.splitclients; clnum++)
{
@ -3973,7 +3990,7 @@ static void CL_ParseSoundlist (qboolean lots)
if (lots)
numsounds = MSG_ReadShort();
else
numsounds = MSG_ReadByte();
numsounds = (cl.protocol_qw>=26)?MSG_ReadByte():0;
for (;;)
{
@ -3991,7 +4008,7 @@ static void CL_ParseSoundlist (qboolean lots)
strcpy (cl.sound_name[numsounds], str);
}
n = MSG_ReadByte();
n = (cl.protocol_qw>=26)?MSG_ReadByte():0;
if (n)
{
@ -4047,7 +4064,7 @@ static void CL_ParseModellist (qboolean lots)
if (lots)
nummodels = MSG_ReadShort();
else
nummodels = MSG_ReadByte();
nummodels = (cl.protocol_qw>=26)?MSG_ReadByte():0;
for (;;)
{
@ -4089,7 +4106,7 @@ static void CL_ParseModellist (qboolean lots)
if (nummodels)
SCR_ImageName(cl.model_name[1]);
n = MSG_ReadByte();
n = (cl.protocol_qw>=26)?MSG_ReadByte():0;
if (n)
{

View file

@ -2810,6 +2810,8 @@ static void SCR_ScreenShot_VR_f(void)
VectorCopy(cl.playerview->simangles, cl.playerview->viewangles);
//FIXME: it should be possible to do this more inteligently, and get both strips with a single render.
//FIXME: we should render to a PBO instead, so that the gpu+cpu don't need to sync until the very end.
//FIXME: we should be using scissoring to avoid redrawing the entire screen (also tweak cull planes)
ang = M_PI*2*(baseang[1]/360.0 + (lx+0.5*(rx-lx))/width);
r_refdef.eyeoffset[0] = sin(ang) * r_stereo_separation.value * 0.5;

View file

@ -440,10 +440,10 @@ typedef struct
/*QuakeWorld protocol flags*/
#ifdef PROTOCOLEXTENSIONS
unsigned long fteprotocolextensions;
unsigned long fteprotocolextensions2;
unsigned int fteprotocolextensions;
unsigned int fteprotocolextensions2;
#endif
unsigned long z_ext;
unsigned int z_ext;
/*NQ Protocol flags*/
enum
@ -453,7 +453,7 @@ typedef struct
CPNQ_BJP1, //16bit models, strict 8bit sounds (otherwise based on nehahra)
CPNQ_BJP2, //16bit models, strict 16bit sounds
CPNQ_BJP3, //16bit models, flagged 16bit sounds, 8bit static sounds.
CPNQ_FITZ666, /*and rmqe999 protocol*/
CPNQ_FITZ666, /*and rmqe999 protocol, which is a strict superset*/
CPNQ_DP5,
CPNQ_DP6,
CPNQ_DP7
@ -739,6 +739,8 @@ typedef struct
int fpd;
int servercount; // server identification for prespawns
int protocol_qw;
float gamespeed;
qboolean csqcdebug;
qboolean allowsendpacket;

View file

@ -980,6 +980,7 @@ extern redirect_t sv_redirected;
extern char sv_redirected_buf[8000];
void SV_FlushRedirect (void);
#endif
vfsfile_t *con_pipe;
#define MAXPRINTMSG 4096
static void Con_PrintFromThread (void *ctx, void *data, size_t a, size_t b)
@ -988,6 +989,18 @@ static void Con_PrintFromThread (void *ctx, void *data, size_t a, size_t b)
BZ_Free(data);
}
vfsfile_t *Con_POpen(char *conname)
{
if (!conname || !*conname)
{
if (con_pipe)
VFS_CLOSE(con_pipe);
con_pipe = VFSPIPE_Open(2, false);
return con_pipe;
}
return NULL;
}
// FIXME: make a buffer size safe vsprintf?
void VARGS Con_Printf (const char *fmt, ...)
{
@ -1021,6 +1034,9 @@ void VARGS Con_Printf (const char *fmt, ...)
// log all messages to file
Con_Log (msg);
if (con_pipe)
VFS_PUTS(con_pipe, msg);
if (!con_initialized)
return;
@ -1029,7 +1045,7 @@ void VARGS Con_Printf (const char *fmt, ...)
}
void VARGS Con_SafePrintf (const char *fmt, ...)
{
{ //obsolete version of the function
va_list argptr;
char msg[MAXPRINTMSG];

View file

@ -1741,6 +1741,12 @@ static void QCBUILTIN PF_cs_project (pubprogfuncs_t *prinst, struct globalvars_s
out[0] = out[0]*r_refdef.vrect.width + r_refdef.vrect.x;
out[1] = out[1]*r_refdef.vrect.height + r_refdef.vrect.y;
if (csqc_isdarkplaces)
{
out[0] *= (float)vid.pixelwidth / vid.width;
out[1] *= (float)vid.pixelheight / vid.height;
}
if (tempv[3] < 0)
out[2] *= -1;
}
@ -1753,12 +1759,18 @@ static void QCBUILTIN PF_cs_unproject (pubprogfuncs_t *prinst, struct globalvars
{
float *in = G_VECTOR(OFS_PARM0);
float *out = G_VECTOR(OFS_RETURN);
float tx, ty;
float tx = in[0], ty = in[1];
float v[4], tempv[4];
tx = ((in[0]-r_refdef.vrect.x)/r_refdef.vrect.width);
ty = ((in[1]-r_refdef.vrect.y)/r_refdef.vrect.height);
if (csqc_isdarkplaces)
{
tx *= (float)vid.width / vid.pixelwidth;
ty *= (float)vid.height / vid.pixelheight;
}
tx = ((tx-r_refdef.vrect.x)/r_refdef.vrect.width);
ty = ((ty-r_refdef.vrect.y)/r_refdef.vrect.height);
ty = 1-ty;
v[0] = tx*2-1;
v[1] = ty*2-1;

View file

@ -16,6 +16,7 @@ vec3_t r_origin, vpn, vright, vup;
entity_t r_worldentity;
entity_t *currententity; //nnggh
int r_framecount;
qboolean r_forceheadless;
struct texture_s *r_notexture_mip;
int r_blockvidrestart; //'block' is a bit of a misnomer. 0=filesystem, configs, cinematics, video are all okay as they are. 1=starting up, waiting for filesystem, will restart after. 2=configs execed, but still need cinematics. 3=video will be restarted without any other init needed
@ -301,8 +302,11 @@ extern cvar_t r_novis;
extern cvar_t r_speeds;
extern cvar_t r_waterwarp;
cvar_t r_polygonoffset_submodel_factor = CVAR("r_polygonoffset_submodel_factor", "0");
cvar_t r_polygonoffset_submodel_offset = CVAR("r_polygonoffset_submodel_offset", "0");
#ifdef BEF_PUSHDEPTH
cvar_t r_polygonoffset_submodel_factor = CVARD("r_polygonoffset_submodel_factor", "0", "z-fighting avoidance. Pushes submodel depth values slightly towards the camera depending on the slope of the surface.");
cvar_t r_polygonoffset_submodel_offset = CVARD("r_polygonoffset_submodel_offset", "0", "z-fighting avoidance. Pushes submodel depth values slightly towards the camera by a consistent distance.");
cvar_t r_polygonoffset_submodel_maps = CVARD("r_polygonoffset_submodel_map", "e?m? r?m? hip?m?", "List of maps on which z-fighting reduction should be used. wildcards accepted.");
#endif
cvar_t r_polygonoffset_shadowmap_offset = CVAR("r_polygonoffset_shadowmap_factor", "0.05");
cvar_t r_polygonoffset_shadowmap_factor = CVAR("r_polygonoffset_shadowmap_offset", "0");
@ -329,7 +333,7 @@ cvar_t gl_ati_truform_type = CVAR ("gl_ati_truform_type", "1");
cvar_t r_tessellation_level = CVAR ("r_tessellation_level", "5");
cvar_t gl_blend2d = CVAR ("gl_blend2d", "1");
cvar_t gl_blendsprites = CVARD ("gl_blendsprites", "0", "Blend sprites instead of alpha testing them");
cvar_t r_deluxmapping_cvar = CVARAFD ("r_deluxmapping", "0", "r_deluxemapping", //fixme: rename to r_glsl_deluxmapping once configs catch up
cvar_t r_deluxmapping_cvar = CVARAFD ("r_deluxemapping", "0", "r_glsl_deluxemapping",
CVAR_ARCHIVE, "Enables bumpmapping based upon precomputed light directions.\n0=off\n1=use if available\n2=auto-generate (if possible)");
qboolean r_deluxmapping;
cvar_t r_shaderblobs = CVARD ("r_shaderblobs", "0", "If enabled, can massively accelerate vid restarts / loading (especially with the d3d renderer). Can cause issues when upgrading engine versions, so this is disabled by default.");
@ -375,10 +379,11 @@ cvar_t gl_savecompressedtex = CVARD ("gl_savecompressedtex", "0", "Write ou
//cvar_t gl_schematics = CVARD ("gl_schematics", "0", "Gimmick rendering mode that draws the length of various world edges.");
cvar_t gl_skyboxdist = CVARD ("gl_skyboxdist", "0", "The distance of the skybox. If 0, the engine will determine it based upon the far clip plane distance."); //0 = guess.
cvar_t gl_smoothcrosshair = CVAR ("gl_smoothcrosshair", "1");
cvar_t gl_maxdist = CVARD ("gl_maxdist", "0", "The distance of the far clip plane. If set to 0, some fancy maths will be used to place it at an infinite distance.");
cvar_t gl_maxdist = CVARAD ("gl_maxdist", "0", "gl_farclip", "The distance of the far clip plane. If set to 0, some fancy maths will be used to place it at an infinite distance.");
#ifdef SPECULAR
cvar_t gl_specular = CVARF ("gl_specular", "0.3", CVAR_ARCHIVE);
cvar_t gl_specular = CVARF ("gl_specular", "0.3", CVAR_ARCHIVE|CVAR_SHADERSYSTEM);
cvar_t gl_specular_power = CVARF ("gl_specular_power", "32", CVAR_ARCHIVE|CVAR_SHADERSYSTEM);
cvar_t gl_specular_fallback = CVARF ("gl_specular_fallback", "0.05", CVAR_ARCHIVE|CVAR_RENDERERLATCH);
cvar_t gl_specular_fallbackexp = CVARF ("gl_specular_fallbackexp", "1", CVAR_ARCHIVE|CVAR_RENDERERLATCH);
#endif
@ -836,6 +841,7 @@ void Renderer_Init(void)
Cvar_Register (&r_flashblend, GRAPHICALNICETIES);
Cvar_Register (&r_flashblendscale, GRAPHICALNICETIES);
Cvar_Register (&gl_specular, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_power, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_fallback, GRAPHICALNICETIES);
Cvar_Register (&gl_specular_fallbackexp, GRAPHICALNICETIES);
@ -957,9 +963,10 @@ void Renderer_Init(void)
Cvar_Register (&r_showbboxes, GLRENDEREROPTIONS);
Cvar_Register (&r_showfields, GLRENDEREROPTIONS);
Cvar_Register (&r_showshaders, GLRENDEREROPTIONS);
#ifndef NOLEGACY
#ifdef BEF_PUSHDEPTH
Cvar_Register (&r_polygonoffset_submodel_factor, GLRENDEREROPTIONS);
Cvar_Register (&r_polygonoffset_submodel_offset, GLRENDEREROPTIONS);
Cvar_Register (&r_polygonoffset_submodel_maps, GLRENDEREROPTIONS);
#endif
Cvar_Register (&r_polygonoffset_shadowmap_factor, GLRENDEREROPTIONS);
Cvar_Register (&r_polygonoffset_shadowmap_offset, GLRENDEREROPTIONS);
@ -1132,7 +1139,7 @@ extern rendererinfo_t nvvkrendererinfo;
extern rendererinfo_t headlessrenderer;
#endif
rendererinfo_t *rendererinfo[] =
rendererinfo_t *rendererinfo[16] =
{
#ifdef GLQUAKE
#ifdef FTE_RPI
@ -1174,6 +1181,24 @@ rendererinfo_t *rendererinfo[] =
#endif
};
void R_RegisterRenderer(rendererinfo_t *ri)
{
size_t i;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{ //already registered
if (rendererinfo[i] == ri)
return;
}
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{ //register it in the first empty slot
if (!rendererinfo[i])
{
rendererinfo[i] = ri;
return;
}
}
Sys_Printf("unable to register renderer %s\n", ri->description);
}
void R_SetRenderer(rendererinfo_t *ri)
{
@ -1353,7 +1378,8 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
isDedicated = false;
#endif
if (newr)
Con_TPrintf("Setting mode %i*%i*%i*%i %s\n", newr->width, newr->height, newr->bpp, newr->rate, newr->renderer->description);
if (!r_forceheadless || newr->renderer->rtype != QR_HEADLESS)
Con_TPrintf("Setting mode %i*%i*%i*%i %s\n", newr->width, newr->height, newr->bpp, newr->rate, newr->renderer->description);
vid.fullbright=0;
@ -1674,7 +1700,8 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
if (newr && qrenderer != QR_NONE)
{
Con_TPrintf("%s renderer initialized\n", newr->renderer->description);
if (!r_forceheadless || newr->renderer->rtype != QR_HEADLESS)
Con_TPrintf("%s renderer initialized\n", newr->renderer->description);
}
TRACE(("dbg: R_ApplyRenderer: done\n"));
@ -1728,11 +1755,22 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
newr->renderer = NULL;
rendererstring = COM_Parse(rendererstring);
if (!*com_token)
if (r_forceheadless)
{ //special hack so that android doesn't weird out when not focused.
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (rendererinfo[i] && rendererinfo[i]->name[0] && !stricmp(rendererinfo[i]->name[0], "headless"))
{
newr->renderer = rendererinfo[i];
break;
}
}
}
else if (!*com_token)
{
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (rendererinfo[i]->name[0] && stricmp(rendererinfo[i]->name[0], "none"))
if (rendererinfo[i] && rendererinfo[i]->name[0] && stricmp(rendererinfo[i]->name[0], "none"))
{
newr->renderer = rendererinfo[i];
break;
@ -1744,7 +1782,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
int count;
for (i = 0, count = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (!rendererinfo[i]->description)
if (!rendererinfo[i] || !rendererinfo[i]->description)
continue; //not valid in this build. :(
if (rendererinfo[i]->rtype == QR_NONE || //dedicated servers are not useful
rendererinfo[i]->rtype == QR_HEADLESS || //headless appears buggy
@ -1755,7 +1793,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
count = rand()%count;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (!rendererinfo[i]->description)
if (!rendererinfo[i] || !rendererinfo[i]->description)
continue; //not valid in this build. :(
if (rendererinfo[i]->rtype == QR_NONE ||
rendererinfo[i]->rtype == QR_HEADLESS ||
@ -1773,7 +1811,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
{
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (!rendererinfo[i]->description)
if (!rendererinfo[i] || !rendererinfo[i]->description)
continue; //not valid in this build. :(
for (j = 4-1; j >= 0; j--)
{
@ -1954,7 +1992,7 @@ void R_SetRenderer_f (void)
Con_Printf ("\nValid setrenderer parameters are:\n");
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (rendererinfo[i]->description)
if (rendererinfo[i] && rendererinfo[i]->description)
Con_Printf("^[%s\\type\\/setrenderer %s^]^7: %s%s\n", rendererinfo[i]->name[0], rendererinfo[i]->name[0], rendererinfo[i]->description, (currentrendererstate.renderer == rendererinfo[i])?" ^2(current)":"");
}
return;

View file

@ -162,7 +162,7 @@ fte_inline conchar_t *Font_Decode(conchar_t *start, unsigned int *codeflags, uns
if (*start & CON_LONGCHAR)
if (!(*start & CON_RICHFORECOLOUR))
{
*codeflags = start[1];
*codeflags = start[1] & CON_FLAGSMASK;
*codepoint = ((start[0] & CON_CHARMASK)<<16) | (start[1] & CON_CHARMASK);
return start+2;
}

File diff suppressed because it is too large Load diff

View file

@ -1790,7 +1790,7 @@ float MSG_ReadAngle (void)
}
}
void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move)
void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move, int protover)
{
int bits;
@ -1798,31 +1798,61 @@ void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move)
bits = MSG_ReadByte ();
// read current angles
if (bits & CM_ANGLE1)
move->angles[0] = MSG_ReadShort ();
if (bits & CM_ANGLE2)
move->angles[1] = MSG_ReadShort ();
if (bits & CM_ANGLE3)
move->angles[2] = MSG_ReadShort ();
if (protover <= 26)
{
if (bits & CM_ANGLE1)
move->angles[0] = MSG_ReadShort();
if (1)
move->angles[1] = MSG_ReadShort();
if (bits & CM_ANGLE3)
move->angles[2] = MSG_ReadShort();
// read movement
if (bits & CM_FORWARD)
move->forwardmove = MSG_ReadShort ();
if (bits & CM_SIDE)
move->sidemove = MSG_ReadShort ();
if (bits & CM_UP)
move->upmove = MSG_ReadShort ();
if (bits & CM_FORWARD)
move->forwardmove = MSG_ReadByte()<<3;
if (bits & CM_SIDE)
move->sidemove = MSG_ReadByte()<<3;
if (bits & CM_UP)
move->upmove = MSG_ReadByte()<<3;
// read buttons
if (bits & CM_BUTTONS)
move->buttons = MSG_ReadByte ();
// read buttons
if (bits & CM_BUTTONS)
move->buttons = MSG_ReadByte();
if (bits & CM_IMPULSE)
move->impulse = MSG_ReadByte ();
if (bits & CM_IMPULSE)
move->impulse = MSG_ReadByte();
// read time to run command
move->msec = MSG_ReadByte ();
if (bits & CM_ANGLE2)
move->msec = MSG_ReadByte();
}
else
{
// read current angles
if (bits & CM_ANGLE1)
move->angles[0] = MSG_ReadShort();
if (bits & CM_ANGLE2)
move->angles[1] = MSG_ReadShort();
if (bits & CM_ANGLE3)
move->angles[2] = MSG_ReadShort();
// read movement
if (bits & CM_FORWARD)
move->forwardmove = MSG_ReadShort();
if (bits & CM_SIDE)
move->sidemove = MSG_ReadShort();
if (bits & CM_UP)
move->upmove = MSG_ReadShort();
// read buttons
if (bits & CM_BUTTONS)
move->buttons = MSG_ReadByte();
if (bits & CM_IMPULSE)
move->impulse = MSG_ReadByte();
// read time to run command
move->msec = MSG_ReadByte();
}
}
void MSGQ2_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move)
@ -3159,6 +3189,9 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
conchar_t ext;
conchar_t *oldout = out;
#ifndef NOLEGACY
extern cvar_t dpcompat_console;
#endif
if (flags & PFS_EZQUAKEMARKUP)
{
@ -3182,7 +3215,11 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
return out;
#endif
if (*str == 1 || *str == 2)
if (*str == 1 || *str == 2
#ifndef NOLEGACY
|| (*str == 3 && dpcompat_console.ival)
#endif
)
{
defaultflags ^= CON_2NDCHARSETTEXT;
str++;
@ -5833,6 +5870,316 @@ unsigned int COM_RemapMapChecksum(model_t *model, unsigned int checksum)
return checksum;
}
/*
Info Buffers
*/
/*
typedef struct
{
struct infobuf_s
{
char *name;
char *value;
} *keys;
size_t numkeys;
qboolean nolegacy; //no \\ or \" limitations.
} infobuf_t;
char *InfoBuf_GetValue (infobuf_t *info, const char *key, char *outbuf, size_t outsize)
{
size_t k;
for (k = 0; k < info->numkeys; k++)
{
if (!strcmp(info->keys[k].name, key))
{
Q_strncpyz(outbuf, info->keys[k].value, outsize);
return outbuf;
}
}
*outbuf = 0;
return outbuf;
}
char *InfoBuf_GetValueTmp (infobuf_t *info, const char *key)
{
static char value[4][1024]; // use multiple buffers so compares work without stomping on each other
static int valueindex;
COM_AssertMainThread("InfoBuf_GetValue");
valueindex = (valueindex+1)&3;
return InfoBuf_GetValue(info, key, value[valueindex], sizeof(value[valueindex]));
}
qboolean InfoBuf_RemoveKey (infobuf_t *info, const char *key)
{
size_t k;
for (k = 0; k < info->numkeys; k++)
{
if (!strcmp(info->keys[k].name, key))
{
Z_Free(info->keys[k].name);
Z_Free(info->keys[k].value);
info->numkeys--;
memmove(info->keys+k+0, info->keys+k+1, sizeof(*info->keys) * (info->numkeys-k));
return true; //only one entry per key, so we can give up here
}
}
return false;
}
void InfoBuf_SetKey (infobuf_t *info, const char *key, const char *val, qboolean force)
{
qboolean removed;
size_t k;
if (!val)
val = "";
if (!info->nolegacy)
{
//block invalid keys
//\\ makes parsing really really messy and isn't supported by most clients (although we could do it anyway)
//\" requires string escapes, again compat issues.
//0xff bugs out vanilla.
if (strchr(key, '\\') || strchr(key, '\"') || strchr(key, 0xff))
return;
if (strchr(val, '\\') || strchr(val, '\"') || strchr(val, 0xff))
return;
if (strlen(key) >= 64)
return; //key length limits is a thing in vanilla qw.
if (strlen(val) >= 512)
return; //value length limits is a thing in vanilla qw.
//note that qw reads values up to 512, but only sets them up to 64 bytes...
//probably just so that people don't spot buffer overflows so easily.
}
// *keys are meant to be secure (or rather unsettable by the user, preventing spoofing of stuff like *ip)
// but note that this is pointless as a hacked client can send whatever initial *keys it wants (they are blocked mid-connection at least)
// * userinfos are always sent even to clients that can't support large infokey blobs
if (*key == '*' && !force)
return;
removed = InfoBuf_RemoveKey(info, key);
if (*val)
{
k = info->numkeys;
if (removed)
info->numkeys+=1; //the memory is still allocated, because we're too lazy to free it.
else
{
if (!ZF_ReallocElements((void**)&info->keys, &info->numkeys, info->numkeys+1, sizeof(*info->keys)))
return; //out of memory!
}
info->keys[k].name = Z_StrDup(key);
info->keys[k].value = Z_StrDup(val);
}
}
void InfoBuf_Clear(infobuf_t *info, qboolean all)
{//if all is false, leaves *keys
size_t k;
for (k = info->numkeys-1; k >= 0; k--)
{
if (all || *info->keys[k].name != '*')
{
Z_Free(info->keys[k].name);
Z_Free(info->keys[k].value);
info->numkeys--;
memmove(info->keys+k+0, info->keys+k+1, sizeof(*info->keys) * (info->numkeys-k));
}
}
if (!info->numkeys)
{
Z_Free(info->keys);
info->keys = NULL;
}
}
void InfoBuf_FromString(infobuf_t *info, const char *infostring)
{
if (*infostring++ != '\\')
return; //invalid... not an info string
while (*infostring)
{
const char *keystart = infostring;
const char *keyend;
const char *valstart;
const char *valend;
char *key;
char *val;
char *o;
while (*infostring)
{
if (*infostring == '\\')
{
if (infostring[1] == '\\')
infostring += 2;
break;
}
else infostring += 1;
}
keyend = infostring;
if (*infostring++ != '\\')
break; //missing value...
valstart = infostring;
while (*infostring)
{
if (*infostring == '\\')
{
if (infostring[1] == '\\')
infostring += 2;
break;
}
else infostring += 1;
}
valend = infostring;
// *infostring might be '\\' or '\0'. doesn't really matter
if (!strncmp(keystart, " \\\\", 3))
keystart += 3;
if (!strncmp(valstart, " \\\\", 3))
valstart += 3;
key = Z_Malloc(1+keyend-keystart);
for (o = key; keystart < keyend; )
{
if (keystart[0] == '\\')
keystart+=1;
*o++ = *keystart++;
}
*o=0;
val = Z_Malloc(1+valend-valstart);
for (o = val; valstart < valend; )
{
if (valstart[0] == '\\')
valstart+=1;
*o++ = *valstart++;
}
*o=0;
InfoBuf_SetKey(info, key, val, true);
Z_Free(key);
Z_Free(val);
}
}
static size_t InfoBuf_ToStringToken(const char *n, char *out, char *end)
{
size_t r = 1;
if (out < end)
*out++ = '\\';
if (*n == '\\' || (n[0] == ' ' && n[1] == '\\'))
{ //" \\" prefix is stripped by the reader, and present to allow keys or values with a leading \\ in a well-defined-but-annoying way
// (vanilla qw doesn't allow double-backslash anywhere in infostrings)
r += 3;
if (out < end)
*out++ = ' ';
if (out < end)
*out++ = '\\';
if (out < end)
*out++ = '\\';
}
while (*n)
{
if (*n == '\\')
{
if (out < end)
*out++ = '\\';
}
if (out < end)
*out++ = *n;
n++;
}
return r;
}
size_t InfoBuf_ToString(infobuf_t *info, char *infostring, size_t maxsize, const char **priority, const char **ignore, const char **exclusive)
{
//if infostring is null, returns the needed buffer size
//\foo\\\bar is ambiguous. and interpreted as foo\ + bar
//\foo\ \\\\bar is interpreted as foo + \bar - leading " \\" is ignored if present.
//FIXME: add a filter, for short/compated buffers. prioritisation or something
size_t k, r = 1, l;
char *o = infostring;
char *e = infostring?infostring + maxsize-1:infostring;
int pri, p;
for (pri = 0; pri < 2; pri++)
{
for (k = 0; k < info->numkeys; k++)
{
if (exclusive)
{
for (l = 0; exclusive[l]; l++)
if (!strcmp(exclusive[l], info->keys[k].name))
break;
if (!exclusive[l])
continue; //ignore when not in the list
}
if (ignore)
{
for (l = 0; ignore[l]; l++)
if (!strcmp(ignore[l], info->keys[k].name))
break;
if (ignore[l])
continue; //ignore when in the list
}
if (priority)
{
for (l = 0; priority[l]; l++)
if (!strcmp(priority[l], info->keys[k].name))
break;
if (priority[l])
p = 0; //high priority
else
p = 1; //low priority
}
else
{
if (*info->keys[k].name == '*')
p = 0; //keys that cannot be changed always have the highest priority (fixme: useless stuff like version doesn't need to be in here
else
p = 1;
}
if (pri != p)
continue;
l = InfoBuf_ToStringToken(info->keys[k].name, o, e);
l += InfoBuf_ToStringToken(info->keys[k].value, o, e);
r += l;
if (o && o + l < e)
o += l;
}
}
*o = 0;
return r;
}
void InfoBuf_WriteToFile(vfsfile_t *f, infobuf_t *info, const char *commandname, int cvarflags)
{
char buffer[1024];
const char *key;
const char *val;
cvar_t *var;
size_t k;
for (k = 0; k < info->numkeys; k++)
{
key = info->keys[k].name;
val = info->keys[k].value;
if (*key == '*') //unsettable, so don't write it for later setting.
continue;
if (cvarflags)
{
var = Cvar_FindVar(key);
if (var && var->flags & cvarflags)
continue; //this is saved via a cvar.
}
VFS_WRITE(f, commandname, strlen(commandname));
VFS_WRITE(f, " ", 1);
key = COM_QuotedString(key, buffer, sizeof(buffer), false);
VFS_WRITE(f, key, strlen(key));
VFS_WRITE(f, " ", 1);
val = COM_QuotedString(val, buffer, sizeof(buffer), false);
VFS_WRITE(f, val, strlen(val));
VFS_WRITE(f, "\n", 1);
}
}
*/
/*
=====================================================================

View file

@ -37,11 +37,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdint.h>
#define qintptr_t intptr_t
#define quintptr_t uintptr_t
#define qint16_t int16_t
#define quint16_t uint16_t
#define qint32_t int32_t
#define quint32_t uint32_t
#define qint64_t int64_t
#define quint64_t uint64_t
#else
#define qint16_t short
#define quint16_t unsigned short
#define qint32_t int
#define quint32_t unsigned qint32_t
#if defined(_WIN64)
@ -289,7 +293,7 @@ float MSG_ReadCoord (void);
void MSG_ReadPos (float *pos);
float MSG_ReadAngle (void);
float MSG_ReadAngle16 (void);
void MSG_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *cmd);
void MSG_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *cmd, int qwprotocolver);
void MSGQ2_ReadDeltaUsercmd (struct usercmd_s *from, struct usercmd_s *move);
void MSG_ReadData (void *data, int len);
void MSG_ReadSkip (int len);
@ -753,8 +757,9 @@ void T_FreeInfoStrings(void);
char *T_GetInfoString(int num);
struct po_s;
struct po_s *PO_Create(void);
void PO_Merge(struct po_s *po, vfsfile_t *file);
const char *PO_GetText(struct po_s *po, const char *msg);
struct po_s *PO_Load(vfsfile_t *file);
void PO_Close(struct po_s *po);
//

View file

@ -239,7 +239,7 @@ void Con_ToggleConsole_Force(void);
int Con_ExecuteLine(console_t *con, char *line); //takes normal console commands
int Con_Navigate(console_t *con, char *line); //special webbrowser hacks
vfsfile_t *Con_POpen(char *conname);
void Con_CycleConsole (void);
int Con_IsActive (console_t *con);
void Con_Destroy (console_t *con);

View file

@ -775,10 +775,11 @@ qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize)
memcpy(ctx->cert, cert, certsize);
strcpy(ctx->hostname, hostname);
//FIXME: display some sort of fingerprint
if (!l)
M_Menu_Prompt(CertLog_Add_Prompted, ctx, "Server certificate is new", "Trust", NULL, "Disconnect");
M_Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\nServer certificate is\nself-signed", hostname), "Trust", NULL, "Disconnect");
else
M_Menu_Prompt(CertLog_Add_Prompted, ctx, "^1Server certificate HAS CHANGED\nZomg\nFlee in Terror", "ReTrust", NULL, "Disconnect");
M_Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\n^1Server certificate HAS CHANGED\nZomg\n^bFlee in Terror", hostname), "ReTrust", NULL, "Disconnect");
}
return false; //can't connect yet...
}

View file

@ -405,12 +405,14 @@ char *narrowen(char *out, size_t outlen, wchar_t *wide);
static DWORD VerifyKnownCertificates(DWORD status, wchar_t *domain, qbyte *data, size_t datasize, qboolean datagram)
{
int i;
#ifndef SERVERONLY
char realdomain[256];
#endif
if (datagram)
{
if (status == CERT_E_UNTRUSTEDROOT || SUCCEEDED(status))
{
#ifndef SERVERONLY
char realdomain[256];
if (CertLog_ConnectOkay(narrowen(realdomain, sizeof(realdomain), domain), data, datasize))
status = SEC_E_OK;
else
@ -455,6 +457,15 @@ static DWORD VerifyKnownCertificates(DWORD status, wchar_t *domain, qbyte *data,
}
}
}
#ifndef SERVERONLY
//self-signed and expired certs are understandable in many situations.
//prompt and cache (although this connection attempt will fail).
if (status == CERT_E_UNTRUSTEDROOT || status == CERT_E_UNTRUSTEDTESTROOT || status == CERT_E_EXPIRED)
if (CertLog_ConnectOkay(narrowen(realdomain, sizeof(realdomain), domain), data, datasize))
return SEC_E_OK;
#endif
return status;
}

View file

@ -1155,6 +1155,17 @@ static void Plug_DownloadComplete(struct dl_download *dl)
}
#endif
static qintptr_t VARGS Plug_Con_POpen(void *offset, quintptr_t mask, const qintptr_t *arg)
{
char *conname = VM_POINTER(arg[0]);
int handle;
if (!currentplug)
return -3; //streams depend upon current plugin context. which isn't valid in a thread.
handle = Plug_NewStreamHandle(STREAM_VFS);
pluginstreamarray[handle].vfs = Con_POpen(conname);
return handle;
}
qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr_t *arg)
{
//modes:
@ -1613,6 +1624,7 @@ void Plug_Initialise(qboolean fromgamedir)
Plug_RegisterBuiltin("Plug_ExportNative", Plug_ExportNative, PLUG_BIF_DLLONLY);
Plug_RegisterBuiltin("Plug_GetPluginName", Plug_GetPluginName, 0);
Plug_RegisterBuiltin("Con_Print", Plug_Con_Print, 0); //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles.
Plug_RegisterBuiltin("Con_POpen", Plug_Con_POpen, PLUG_BIF_DLLONLY);
Plug_RegisterBuiltin("Sys_Error", Plug_Sys_Error, 0);
Plug_RegisterBuiltin("Sys_Milliseconds", Plug_Sys_Milliseconds, 0);
Plug_RegisterBuiltin("Com_Error", Plug_Sys_Error, 0); //make zquake programmers happy.

View file

@ -18,7 +18,7 @@ cvar_t sv_gameplayfix_nolinknonsolid = CVARD("sv_gameplayfix_nolinknonsolid", "1
cvar_t sv_gameplayfix_blowupfallenzombies = CVARD("sv_gameplayfix_blowupfallenzombies", "0", "Allow findradius to find non-solid entities. This may break certain mods.");
cvar_t dpcompat_findradiusarealinks = CVARD("dpcompat_findradiusarealinks", "0", "Use the world collision info to accelerate findradius instead of looping through every single entity. May actually be slower for large radiuses, or fail to find entities which have not been linked properly with setorigin.");
#ifndef NOLEGACY
cvar_t dpcompat_strcatlimitation = CVARD("dpcompat_crippledstrcat", "", "When set, cripples strcat (and related function) string lengths to the value specified.\nSet to 16383 to replicate DP's limit, otherwise leave as 0 to avoid limits.");
cvar_t dpcompat_strcat_limit = CVARD("dpcompat_strcat_limit", "", "When set, cripples strcat (and related function) string lengths to the value specified.\nSet to 16383 to replicate DP's limit, otherwise leave as 0 to avoid limits.");
#endif
cvar_t pr_droptofloorunits = CVARD("pr_droptofloorunits", "256", "Distance that droptofloor is allowed to drop to be considered successul.");
cvar_t pr_brokenfloatconvert = CVAR("pr_brokenfloatconvert", "0");
@ -51,7 +51,7 @@ void PF_Common_RegisterCvars(void)
Cvar_Register (&sv_gameplayfix_nolinknonsolid, cvargroup_progs);
Cvar_Register (&dpcompat_findradiusarealinks, cvargroup_progs);
#ifndef NOLEGACY
Cvar_Register (&dpcompat_strcatlimitation, cvargroup_progs);
Cvar_Register (&dpcompat_strcat_limit, cvargroup_progs);
#endif
Cvar_Register (&pr_droptofloorunits, cvargroup_progs);
Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs);
@ -3600,10 +3600,10 @@ void QCBUILTIN PF_strcat (pubprogfuncs_t *prinst, struct globalvars_s *pr_global
len += l[i];
#ifndef NOLEGACY
if (dpcompat_strcatlimitation.ival && len > dpcompat_strcatlimitation.ival)
if (dpcompat_strcat_limit.ival && len > dpcompat_strcat_limit.ival)
{
l[i] -= len-dpcompat_strcatlimitation.ival;
len -= len-dpcompat_strcatlimitation.ival;
l[i]-= len-dpcompat_strcat_limit.ival;
len -= len-dpcompat_strcat_limit.ival;
}
#endif
}
@ -6251,7 +6251,7 @@ void PDECL PR_FoundDoTranslateGlobal(pubprogfuncs_t *progfuncs, char *name, eval
//called after each progs is loaded
void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
{
vfsfile_t *f = NULL;
vfsfile_t *f = NULL, *f2 = NULL;
char lang[64], *h;
extern cvar_t language;
if (!prinst || newprogs < 0)
@ -6265,8 +6265,11 @@ void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
{
if (!*lang)
break;
f = FS_OpenVFS(va("%s.%s.po", modulename, lang), "rb", FS_GAME);
if (f)
if (!f)
f = FS_OpenVFS(va("%s.%s.po", modulename, lang), "rb", FS_GAME);
if (!f2)
f2 = FS_OpenVFS(va("common.%s.po", lang), "rb", FS_GAME);
if (f && f2)
break;
h = strchr(lang, '_');
if (h)
@ -6276,9 +6279,11 @@ void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
}
}
if (f)
if (f || f2)
{
void *pofile = PO_Load(f);
void *pofile = PO_Create();
PO_Merge(pofile, f);
PO_Merge(pofile, f2);
prinst->FindPrefixGlobals (prinst, newprogs, "dotranslate_", PR_FoundDoTranslateGlobal, pofile);
PO_Close(pofile);
}

View file

@ -1136,7 +1136,7 @@ qintptr_t VARGS VM_Call(vm_t *vm, qintptr_t instruction, ...)
arg[3]=va_arg(argptr, qintptr_t);
arg[4]=va_arg(argptr, qintptr_t);
arg[5]=va_arg(argptr, qintptr_t);
arg[6]=va_arg(argptr, qintptr_t);
arg[6]=va_arg(argptr, qintptr_t);
arg[7]=va_arg(argptr, qintptr_t);
va_end(argptr);

View file

@ -23,7 +23,7 @@ static void QDECL TL_LanguageChanged(struct cvar_s *var, char *oldvalue)
#endif
}
cvar_t language = CVARFC("lang", sys_language, CVAR_USERINFO, TL_LanguageChanged);
cvar_t language = CVARAFC("lang", sys_language, "prvm_language", CVAR_USERINFO, TL_LanguageChanged);
void TranslateInit(void)
{
@ -77,7 +77,13 @@ static int TL_LoadLanguage(char *lang)
return TL_LoadLanguage(lang);
}
languages[j].name = strdup(lang);
languages[j].po = f?PO_Load(f):NULL;
languages[j].po = NULL;
if (f)
{
languages[j].po = PO_Create();
PO_Merge(languages[j].po, f);
}
return j;
}
@ -328,19 +334,16 @@ static void PO_AddText(struct po_s *po, const char *orig, const char *trans)
line->next = po->lines;
po->lines = line;
}
struct po_s *PO_Load(vfsfile_t *file)
void PO_Merge(struct po_s *po, vfsfile_t *file)
{
struct po_s *po;
unsigned int buckets = 1024;
char *instart, *in, *end;
int inlen;
char msgid[32768];
char msgstr[32768];
qboolean allowblanks = !!COM_CheckParm("-translatetoblank");
po = Z_Malloc(sizeof(*po) + Hash_BytesForBuckets(buckets));
Hash_InitTable(&po->hash, buckets, po+1);
if (!file)
return;
inlen = file?VFS_GETLEN(file):0;
instart = in = BZ_Malloc(inlen+1);
@ -409,6 +412,14 @@ struct po_s *PO_Load(vfsfile_t *file)
}
BZ_Free(instart);
}
struct po_s *PO_Create(void)
{
struct po_s *po;
unsigned int buckets = 1024;
po = Z_Malloc(sizeof(*po) + Hash_BytesForBuckets(buckets));
Hash_InitTable(&po->hash, buckets, po+1);
return po;
}
void PO_Close(struct po_s *po)

View file

@ -1418,7 +1418,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
OutputFile="../../fteqwsv64.exe"
OutputFile="../../fteqwsv_dbg64.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../libs/dxsdk7/lib"
@ -1597,9 +1597,6 @@
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="quakedef.h"
PrecompiledHeaderFile=".\MDebug/qwcl.pch"
AssemblerListingLocation=".\MDebug/"
ObjectFile=".\MDebug/"
ProgramDataBaseFileName=".\MDebug/"
BrowseInformation="1"
BrowseInformationFile=".\MDebug/"
WarningLevel="3"
@ -19771,250 +19768,6 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\server\svmodel.c"
>
<FileConfiguration
Name="MinGLDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="VkDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="VkDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="VkRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="VkRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="nonwin"
@ -25930,7 +25683,6 @@
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"

View file

@ -236,6 +236,10 @@ static struct
vec3_t reflectcolour;
float wateralpha;
//FIXME: rtlights can't respond to these
int offsetmappingmode;
float offsetmappingscale;
float offsetmappingbias;
float specularexpscale; //*32 ish
float specularvalscale; //*1 ish
} parsestate;
@ -1149,7 +1153,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
int cvartypes[64];
int cvarcount = 0;
qboolean onefailed = false;
extern cvar_t gl_specular;
extern cvar_t gl_specular, gl_specular_power;
#endif
#ifdef VKQUAKE
@ -1461,7 +1465,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
if (gl_specular.value)
{
if (nummodifiers < MAXMODIFIERS)
permutationdefines[nummodifiers++] = Z_StrDup("#define SPECULAR\n");
permutationdefines[nummodifiers++] = Z_StrDup(va("#define SPECULAR\n#define SPECULAR_BASE_MUL %f\n#define SPECULAR_BASE_POW %f\n", 1.0*gl_specular.value, max(1,gl_specular_power.value)));
}
for (end = strchr(name, '#'); end && *end; )
{
@ -2363,23 +2367,23 @@ static void Shader_DP_OffsetMapping(shader_t *shader, shaderpass_t *pass, char *
{
char *token = Shader_ParseString(ptr);
if (!strcmp(token, "disable") || !strcmp(token, "none") || !strcmp(token, "off"))
;
parsestate.offsetmappingmode = 0;
else if (!strcmp(token, "default") || !strcmp(token, "normal"))
;
parsestate.offsetmappingmode = -1;
else if (!strcmp(token, "linear"))
;
parsestate.offsetmappingmode = 1;
else if (!strcmp(token, "relief"))
;
/*scale = */Shader_ParseFloat(shader, ptr, 1);
parsestate.offsetmappingmode = 2;
parsestate.offsetmappingscale = Shader_ParseFloat(shader, ptr, 1);
token = Shader_ParseString(ptr);
if (!strcmp(token, "bias"))
/*bias = */Shader_ParseFloat(shader, ptr, 0.5);
parsestate.offsetmappingbias = Shader_ParseFloat(shader, ptr, 0.5);
else if (!strcmp(token, "match"))
/*bias = 1.0 - */Shader_ParseFloat(shader, ptr, 0.5);
parsestate.offsetmappingbias = 1.0 - Shader_ParseFloat(shader, ptr, 0.5);
else if (!strcmp(token, "match8"))
/*bias = 1.0 - (1.0/255) * */Shader_ParseFloat(shader, ptr, 128);
parsestate.offsetmappingbias = 1.0 - (1.0/255) * Shader_ParseFloat(shader, ptr, 128);
else if (!strcmp(token, "match16"))
/*bias = 1.0 - (1.0/65535) * */Shader_ParseFloat(shader, ptr, 32768);
parsestate.offsetmappingbias = 1.0 - (1.0/65535) * Shader_ParseFloat(shader, ptr, 32768);
}
static void Shader_DP_GlossScale(shader_t *shader, shaderpass_t *pass, char **ptr)
{
@ -4470,7 +4474,23 @@ void Shader_Programify (shader_t *s)
Q_strncatz(args, va("#specmul=%g", parsestate.specularvalscale), sizeof(args));
if (parsestate.specularexpscale != 1)
Q_strncatz(args, va("#specexp=%g", parsestate.specularexpscale), sizeof(args));
/* switch(parsestate.offsetmappingmode)
{
case 0: //force off.
Q_strncatz(args, va("#NOOFFSETMAPPING", parsestate.specularexpscale), sizeof(args));
break;
case 1: //force linear
Q_strncatz(args, va("#NORELIEFMAPPING", parsestate.specularexpscale), sizeof(args));
break;
case 2: //force relief
Q_strncatz(args, va("#RELIEFMAPPING", parsestate.specularexpscale), sizeof(args));
break;
}
if (parsestate.offsetmappingscale != 1)
Q_strncatz(args, va("#OFFSETMAPPING_SCALE=%g", parsestate.offsetmappingscale), sizeof(args));
if (parsestate.offsetmappingbias != 0)
Q_strncatz(args, va("#OFFSETMAPPING_BIAS=%g", parsestate.offsetmappingbias), sizeof(args));
*/
mask = strchr(s->name, '#');
if (mask)
Q_strncatz(args, mask, sizeof(args));

View file

@ -1251,11 +1251,15 @@ static const char *glsl_hdrs[] =
"#ifndef SPECEXP\n"
"#define SPECEXP 1.0\n"
"#endif\n"
"#define FTE_SPECULAR_EXPONENT (32.0*float(SPECEXP))\n"
"#ifndef SPECULAR_BASE_POW\n"
"#define SPECULAR_BASE_POW 32.0\n"
"#define SPECULAR_BASE_MUL 1.0\n"
"#endif\n"
"#define FTE_SPECULAR_EXPONENT (SPECULAR_BASE_POW*float(SPECEXP))\n"
"#ifndef SPECMUL\n"
"#define SPECMUL 1.0\n"
"#endif\n"
"#define FTE_SPECULAR_MULTIPLIER (cvar_gl_specular*float(SPECMUL))\n"
"#define FTE_SPECULAR_MULTIPLIER (SPECULAR_BASE_MUL*float(SPECMUL))\n"
#ifndef NOLEGACY
"uniform sampler2DShadow s_shadowmap;"
"uniform samplerCube s_projectionmap;"
@ -1633,6 +1637,9 @@ static const char *glsl_hdrs[] =
"#if !defined(OFFSETMAPPING_SCALE)\n"
"#define OFFSETMAPPING_SCALE 1.0\n"
"#endif\n"
"#if !defined(OFFSETMAPPING_BIAS)\n"
"#define OFFSETMAPPING_BIAS 0.0\n"
"#endif\n"
"#if defined(RELIEFMAPPING) && !defined(GL_ES)\n"
"float i, f;\n"
"vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * OFFSETMAPPING_SCALE * vec2(-1.0, 1.0), -1.0);\n"

View file

@ -5695,7 +5695,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!permu SPECULAR\n"
"!!permu REFLECTCUBEMASK\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvarf gl_specular\n"
"!!cvardf r_tessellation_level=5\n"
"!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3\n"
@ -5917,9 +5916,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#define s_colourmap s_t0\n"
"uniform sampler2D s_colourmap;\n"
"#ifdef SPECULAR\n"
"uniform float cvar_gl_specular;\n"
"#endif\n"
"#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n"
"#endif\n"
@ -5999,7 +5995,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef SPECULAR\n"
"vec4 specs = texture2D(s_specular, tc);\n"
"vec3 halfdir = normalize(normalize(eyevector) + delux); //this norm should be the deluxemap info instead\n"
"float spec = pow(max(dot(halfdir, norm), 0.0), 2.0*FTE_SPECULAR_EXPONENT * specs.a);\n"
"float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * specs.a);\n"
"spec *= FTE_SPECULAR_MULTIPLIER;\n"
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
//As not all maps will have deluxemapping, and the double-cos from the light util makes everything far too dark anyway,
@ -6009,7 +6005,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"vec3 rtc = reflect(-eyevector, norm);\n"
"vec3 rtc = reflect(normalize(-eyevector), norm);\n"
"rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];\n"
"rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;\n"
"gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;\n"
@ -6051,6 +6047,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"}\n"
"#endif\n"
},
#endif
#ifdef VKQUAKE
@ -8440,6 +8437,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"uniform sampler2DShadow s_shadowmap;\n"
//FIXME: shadowmaps need to be atlased!
"uniform vec4 l_shadowmapproj; //light projection matrix info\n"
"uniform vec2 l_shadowmapscale; //xy are the texture scale, z is 1, w is the scale.\n"
"vec3 ShadowmapCoord(vec4 cubeproj)\n"
@ -8585,6 +8583,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"float nDotL = dot(norm, lightDir);\n"
"float lightDiffuse = max(0.0, nDotL) * atten;\n"
/*calc specular term*/
//fixme
//fixme: apply fog
//fixme: output a specular term
//fixme: cubemap filters

View file

@ -427,6 +427,7 @@ enum qcop_e {
OP_BITXOR_V,
OP_POW_F,
OP_CROSS_V,
OP_EQ_FLD,
OP_NE_FLD,
@ -461,10 +462,10 @@ typedef struct qtest_function_s
int unused1;
int locals; // assumed! (always 0 in real qtest progs)
int profile; // assumed! (always 0 in real qtest progs)
int s_name;
int s_file;
int numparms;
int parm_start; // different order
int parm_size[MAX_PARMS]; // ints instead of bytes...
@ -540,12 +541,12 @@ typedef struct
int first_statement; // negative numbers are builtins
int parm_start;
int locals; // total ints of parms + locals
int profile; // runtime
string_t s_name;
string_t s_file; // source file defined in
int numparms;
qbyte parm_size[MAX_PARMS];
} dfunction_t;
@ -555,14 +556,14 @@ typedef struct
int first_statement; // negative numbers are builtins
int parm_start;
int locals; // total ints of parms + locals
int profile; //number of qc instructions executed.
prclocks_t profiletime; //total time inside (cpu cycles)
prclocks_t profilechildtime; //time inside children (excluding builtins, cpu cycles)
string_t s_name;
string_t s_file; // source file defined in
int numparms;
qbyte parm_size[MAX_PARMS];
} mfunction_t;
@ -577,25 +578,25 @@ typedef struct
{
int version;
int crc; // check of header file
unsigned int ofs_statements; //comp 1
unsigned int numstatements; // statement 0 is an error
unsigned int ofs_globaldefs; //comp 2
unsigned int numglobaldefs;
unsigned int ofs_fielddefs; //comp 4
unsigned int numfielddefs;
unsigned int ofs_functions; //comp 8
unsigned int numfunctions; // function 0 is an empty
unsigned int ofs_strings; //comp 16
unsigned int numstrings; // first string is a null string
unsigned int ofs_globals; //comp 32
unsigned int numglobals;
unsigned int entityfields;
//debug / version 7 extensions

View file

@ -378,8 +378,8 @@ typedef struct QCC_def_s
struct QCC_function_s *scope; // function the var was defined in, or NULL
struct QCC_def_s *deftail; // arrays and structs create multiple globaldef objects providing different types at the different parts of the single object (struct), or alternative names (vectors). this allows us to correctly set the const type based upon how its initialised.
struct QCC_def_s *generatedfor;
int initialized; // 1 when a declaration included "= immediate". 2 = extern. 3 = don't warn (unless actually used)
int constant; // 1 says we can use the value over and over again
int initialized; // 1 when a declaration included "= immediate". 2 = extern.
int constant; // 1 says we can use the value over and over again. 2 is used on fields, for some reason.
struct QCC_def_s *symbolheader; //this is the original symbol within which the def is stored.
union QCC_eval_s *symboldata; //null if uninitialised. use sym->symboldata[sym->ofs] to index.
@ -402,14 +402,17 @@ typedef struct QCC_def_s
pbool saved:1; //def may be saved to saved games.
pbool isstatic:1; //global, even if scoped. also specific to the file it was seen in.
pbool subscoped_away:1; //this local is no longer linked into the locals hash table. don't do remove it twice.
// pbool followptr:1;
// pbool followptr:1; //float &foo;
pbool strip:1; //info about this def should be stripped. it may still consume globals space however, and its storage can still be used, its just not visible.
pbool allowinline:1; //calls to this function will attempt to inline the specified function. requires const, supposedly.
pbool used:1; //if it remains 0, it may be stripped. this is forced for functions and fields. commonly 0 on fields.
pbool unused:1; //silently strip it if it wasn't referenced.
pbool localscope:1; //is a local, as opposed to a static (which is only visible within its scope)
pbool arraylengthprefix:1; //hexen2 style arrays have a length prefixed to them for auto bounds checks. this can only work reliably for simple non-struct arrays.
pbool assumedtype:1; //#merged. the type is not reliable.
pbool weak:1; //ignore any initialiser value (only permitted on functions)
pbool accumulate:1; //don't finalise the function's statements.
pbool nofold:1;
int fromstatement; //statement that it is valid from.
temp_t *temp;
@ -470,6 +473,7 @@ struct QCC_function_s
string_t s_filed; // source file with definition
const char *filen;
int line;
int line_end;
char *name; //internal name of function
struct QCC_function_s *parentscope; //for nested functions
struct QCC_type_s *type; //same as the def's type
@ -478,6 +482,9 @@ struct QCC_function_s
QCC_sref_t returndef; //default return value
pbool privatelocals; //false means locals may overlap with other functions, true is needed for compat if stuff is uninitialised.
// unsigned int parm_ofs[MAX_PARMS]; // always contiguous, right?
QCC_statement_t *statements; //if set, then this function isn't finialised yet.
size_t numstatements;
};
@ -578,6 +585,7 @@ extern pbool keyword_strip; //don't write the def to the output.
extern pbool keyword_union; //you surly know what a union is!
extern pbool keyword_wrap;
extern pbool keyword_weak;
extern pbool keyword_accumulate;
extern pbool keyword_unused;
extern pbool keyword_used;
@ -670,6 +678,7 @@ extern pbool type_inlinefunction;
QCC_type_t *QCC_TypeForName(char *name);
QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype);
QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype);
QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, struct QCC_typeparam_s *args, int numargs);
char *QCC_PR_ParseName (void);
CompilerConstant_t *QCC_PR_DefineName(char *name);
@ -752,6 +761,7 @@ enum {
WARN_NOTSTANDARDBEHAVIOUR,
WARN_DUPLICATEPRECOMPILER,
WARN_IDENTICALPRECOMPILER,
WARN_GMQCC_SPECIFIC, //extension created by gmqcc that conflicts or isn't properly implemented.
WARN_FTE_SPECIFIC, //extension that only FTEQCC will have a clue about.
WARN_EXTENSION_USED, //extension that frikqcc also understands
WARN_IFSTRING_USED,
@ -938,8 +948,9 @@ void QCC_PR_NewLine (pbool incomment);
#define GDF_INLINE 32 //attempt to inline calls to this function
#define GDF_USED 64 //don't strip this, ever.
#define GDF_BASICTYPE 128 //don't care about #merge types not being known correctly.
QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags);
QCC_sref_t QCC_PR_GetSRef (QCC_type_t *type, char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags);
#define GDF_SCANLOCAL 256 //don't use the locals hash table
QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, const char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags);
QCC_sref_t QCC_PR_GetSRef (QCC_type_t *type, const char *name, struct QCC_function_s *scope, pbool allocate, int arraysize, unsigned int flags);
void QCC_FreeTemp(QCC_sref_t t);
void QCC_FreeDef(QCC_def_t *def);
char *QCC_PR_CheckCompConstTooltip(char *word, char *outstart, char *outend);
@ -973,8 +984,9 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char
void QCC_PR_EmitArraySetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char *arrayname);
void QCC_PR_EmitClassFromFunction(QCC_def_t *defscope, QCC_type_t *basetype);
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope, int arraysize, QCC_def_t *rootsymbol, unsigned int ofs, int referable, unsigned int flags);
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, const char *name, QCC_function_t *scope, int arraysize, QCC_def_t *rootsymbol, unsigned int ofs, int referable, unsigned int flags);
void QCC_PR_ParseInitializerDef(QCC_def_t *def, unsigned int flags);
void QCC_PR_FinaliseFunctions(void);
void PostCompile(void);

File diff suppressed because it is too large Load diff

View file

@ -71,13 +71,13 @@ static void Q_strlcpy(char *dest, const char *src, int sizeofdest)
char *pr_punctuation[] =
// longer symbols must be before a shorter partial match
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "&=", "++", "--", "->", "^=", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "><", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^^", "^", "~", ":", NULL};
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "&=", "++", "--", "->", "^=", "::", ";", ",", "!", "*^", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "><", "<<=", "<<", "<", ">>=", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^^", "^", "~", ":", NULL};
char *pr_punctuationremap[] = //a nice bit of evilness.
//(+) -> |=
//-> -> .
//(-) -> &~=
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "&=", "++", "--", ".", "^=", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "><", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^^", "^", "~", ":", NULL};
{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "&=", "++", "--", ".", "^=", "::", ";", ",", "!", "*^", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "><", "<<=", "<<", "<", ">>=", ">>", ">" , "?", "#" , "@", "&" , "|", "%", "^^", "^", "~", ":", NULL};
// simple types. function types are dynamically allocated
QCC_type_t *type_void; //void
@ -473,7 +473,7 @@ static void QCC_PR_GetDefinesListEnumerate(void *vctx, void *data)
QC_snprintfz(term, sizeof(term), "\n%s", def->name);
if (def->numparams >= 0)
{
unsigned int i;
int i;
QC_strlcat(term, "(", sizeof(term));
for (i = 0; i < def->numparams; i++)
{
@ -989,11 +989,10 @@ pbool QCC_PR_Precompiler(void)
pr_file_p++;
}
msg[a] = 0;
pr_file_p++;
QCC_FindBestInclude(msg, compilingfile, false);
pr_file_p++;
QCC_PR_SkipToEndOfLine(true);
}
else if (!strncmp(directive, "datafile", 8))
@ -1866,6 +1865,7 @@ void QCC_PR_LexString (void)
if (qccwarningaction[WARN_NOTUTF8])
{
size_t c;
for (c = 0; c < pr_immediate_strlen; )
{
len = utf8_check(&pr_token[c], &code);
@ -2243,8 +2243,9 @@ void QCC_PR_LexPunctuation (void)
pr_token_type = tt_punct;
if (pr_file_p[0] == '*' && pr_file_p[1] == '*' && flag_dblstarexp)
{
strcpy (pr_token, "**");
{ //for compat with gmqcc. fteqcc uses *^ internally (which does not conflict with multiplying by dereferenced pointers - sucks for MSCLR c++ syntax)
QCC_PR_ParseWarning(WARN_GMQCC_SPECIFIC, "** operator conflicts with pointers. Consider using *^ instead.", pr_token);
strcpy (pr_token, "*^");
pr_file_p += 2;
return;
}
@ -2896,7 +2897,7 @@ void QCC_PR_PreProcessor_Define(pbool append)
{
char *exploitcheck;
s++;
QCC_PR_NewLine(false);
QCC_PR_NewLine(true);
s++;
if( s[-1] == '\r' && s[0] == '\n' )
{
@ -2921,7 +2922,7 @@ foo\nbar\nmoo
so if present, the preceeding \\\n and following \\\n must become an actual \n instead of being stripped.
*/
for (exploitcheck = s; *exploitcheck && qcc_iswhite(*exploitcheck); exploitcheck++)
for (exploitcheck = s; *exploitcheck && qcc_iswhitesameline(*exploitcheck); exploitcheck++)
;
if (*exploitcheck == '#')
{
@ -3454,7 +3455,12 @@ int QCC_PR_CheckCompConst(void)
}
}
else
QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without argument list");
{
//QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without argument list");
pr_file_p = initial_file_p;
pr_source_line = initial_line;
return false;
}
}
else
{
@ -3726,7 +3732,11 @@ static void QCC_PR_PrintMacro (qcc_includechunk_t *chunk)
QCC_PR_PrintMacro(chunk->prev);
if (chunk->cnst)
{
#if 1
printf ("%s:%i: %s is defined here\n", chunk->cnst->fromfile, chunk->cnst->fromline, chunk->cnst->name);
#else
printf ("%s:%i: expanding %s\n", chunk->currentfilename, chunk->currentlinenumber, chunk->cnst->name);
#endif
if (verbose)
printf ("%s\n", chunk->datastart);
}
@ -4877,8 +4887,13 @@ QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, struct QCC_typeparam_s
ftype->vargcount = false;
for (i = 0; i < numargs; i++, p++)
{
p->paramname = qccHunkAlloc(strlen(args[i].paramname)+1);
strcpy(p->paramname, args[i].paramname);
if (args[i].paramname)
{
p->paramname = qccHunkAlloc(strlen(args[i].paramname)+1);
strcpy(p->paramname, args[i].paramname);
}
else
p->paramname = "";
p->type = args[i].type;
p->out = args[i].out;
p->optional = args[i].optional;
@ -5395,7 +5410,6 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
{
pr_classtype = newt;
QCC_PR_ParseInitializerDef(def, 0);
QCC_FreeDef(def);
pr_classtype = NULL;
/*
f = QCC_PR_ParseImmediateStatements (def, newparm);

View file

@ -281,6 +281,10 @@ typedef struct editor_s {
int savefmt;
time_t filemodifiedtime;
struct editor_s *next;
//for avoiding silly redraws etc when titles don't actually change...
int oldsavefmt;
int oldline;
} editor_t;
editor_t *editors;
@ -2530,6 +2534,11 @@ static void UpdateEditorTitle(editor_t *editor)
{
char title[2048];
char *encoding = "unknown";
if (editor->oldsavefmt == editor->savefmt && editor->oldline == editor->curline)
return; //nothing changed.
editor->oldsavefmt = editor->savefmt;
editor->oldline = editor->curline;
switch(editor->savefmt)
{
case UTF8_RAW:
@ -2633,7 +2642,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
editor->tooltip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP|TTS_ALWAYSTIP|TTS_NOPREFIX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, NULL, ghInstance, NULL);
if (editor->tooltip)
{
{
TOOLINFO toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hWnd;
@ -2844,7 +2853,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message,
SendMessage(editor->editpane, SCI_CALLTIPCANCEL, 0, 0);
break;
}
UpdateEditorTitle(editor);
//UpdateEditorTitle(editor);
}
else
{
@ -5513,6 +5522,7 @@ void OptionsDialog(void)
tipwnd = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, optionsmenu, NULL, ghInstance, NULL);
SetWindowPos(tipwnd, HWND_TOPMOST,0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
SendMessage(tipwnd, TTM_SETMAXTIPWIDTH, 0, 500);
subsection = CreateWindow("BUTTON", "Optimisations", WS_CHILD|WS_VISIBLE|BS_GROUPBOX,
0, 0, 400, height-40*4+24, optionsmenu, NULL, ghInstance, NULL);
@ -6941,6 +6951,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
ghInstance= hInstance;
GUI_SetDefaultOpts();
GUI_ParseCommandLine(lpCmdLine);
strcpy(enginebinary, "");
strcpy(enginebasedir, "");

View file

@ -213,6 +213,7 @@ struct {
{" F318", WARN_DUPLICATEMACRO},
{" F319", WARN_CONSTANTCOMPARISON},
{" F320", WARN_PARAMWITHNONAME},
{" F321", WARN_GMQCC_SPECIFIC},
{" F208", WARN_NOTREFERENCEDCONST},
{" F209", WARN_EXTRAPRECACHE},
@ -335,6 +336,7 @@ compiler_flag_t compiler_flag[] = {
{&keyword_vector, defaultkeyword, "vector", "Keyword: vector", "Disables the 'vector' keyword."},
{&keyword_wrap, defaultkeyword, "wrap", "Keyword: wrap", "Disables the 'wrap' keyword."},
{&keyword_weak, defaultkeyword, "weak", "Keyword: weak", "Disables the 'weak' keyword."},
{&keyword_accumulate, nondefaultkeyword,"accumulate", "Keyword: accumulate", "Disables the 'accumulate' keyword."},
//options
{&keywords_coexist, FLAG_ASDEFAULT, "kce", "Keywords Coexist", "If you want keywords to NOT be disabled when they a variable by the same name is defined, check here."},
@ -936,6 +938,8 @@ void QCC_DetermineNeededSymbols(QCC_def_t *endsyssym)
{
for (; sym; sym = sym->next)
{
if (sym->unused && !sym->initialized)
sym->initialized = 1; //even if its not.
sym->used = true;
sym->referenced = true; //silence warnings about unreferenced things that can't be stripped
if (sym == endsyssym)
@ -973,9 +977,22 @@ void QCC_DetermineNeededSymbols(QCC_def_t *endsyssym)
}
}
const QCC_eval_t *QCC_SRef_EvalConst(QCC_sref_t ref);
//allocates final space for the def, making it a true def
void QCC_FinaliseDef(QCC_def_t *def)
{
//#define DEBUG_DUMP_GLOBALMAP
#if defined(DEBUG_DUMP) || defined(DEBUG_DUMP_GLOBALMAP)
int ssize = def->symbolsize;
const QCC_eval_t *v;
QCC_sref_t sr;
#endif
if (def->symboldata == qcc_pr_globals + def->ofs)
return; //was already finalised.
if (def->symbolheader != def)
QCC_FinaliseDef(def->symbolheader);
if (def->symbolheader == def && def->deftail)
{
//for head symbols, we go through and touch all of their children
@ -1068,8 +1085,17 @@ void QCC_FinaliseDef(QCC_def_t *def)
def->ofs += def->symbolheader->ofs;
else
{
/* globalspertype[def->type->type].size += def->symbolsize;
globalspertype[def->type->type].entries += 1;
globalspertype[def->type->type].vars += !def->constant;
globalspertype[def->type->type].consts += def->constant;
*/
if (def->ofs)
QCC_Error(ERR_INTERNAL, "root symbol %s has an offset", def->name);
if (def->arraylengthprefix)
{
//for hexen2 arrays, we need to emit a length first
if (numpr_globals+1+def->symbolsize >= MAX_REGS)
{
if (!opt_overlaptemps || !opt_locals_overlapping)
@ -1077,20 +1103,21 @@ void QCC_FinaliseDef(QCC_def_t *def)
else
QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS");
}
//for hexen2 arrays, we need to emit a length first
if (def->type->type == ev_vector)
((int *)qcc_pr_globals)[numpr_globals] = def->arraysize-1;
else
((int *)qcc_pr_globals)[numpr_globals] = (def->arraysize*def->type->size)-1; //using float arrays for structs.
numpr_globals+=1;
}
else if (numpr_globals+def->symbolsize >= MAX_REGS)
else
{
if (!opt_overlaptemps || !opt_locals_overlapping)
QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS - you'll need to use more optimisations");
else
QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS");
if (numpr_globals+def->symbolsize >= MAX_REGS)
{
if (!opt_overlaptemps || !opt_locals_overlapping)
QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS - you'll need to use more optimisations");
else
QCC_Error(ERR_TOOMANYGLOBALS, "numpr_globals exceeded MAX_REGS");
}
}
def->ofs += numpr_globals;
numpr_globals += def->symbolsize;
@ -1103,10 +1130,27 @@ void QCC_FinaliseDef(QCC_def_t *def)
def->symboldata = qcc_pr_globals + def->ofs;
def->symbolsize = numpr_globals - def->ofs;
#ifdef DEBUG_DUMP
#ifdef DEBUG_DUMP_GLOBALMAP
if (!def->referenced)
printf("Unreferenced ");
printf("Finalise %s(%p) @ %i+%i\n", def->name, def, def->ofs, ssize);
sr.sym = def;
sr.ofs = 0;
sr.cast = def->type;
v = QCC_SRef_EvalConst(sr);
if (v && def->type->type == ev_float)
printf("Finalise %s(%f) @ %i+%i\n", def->name, v->_float, def->ofs, ssize);
else if (v && def->type->type == ev_vector)
printf("Finalise %s(%f %f %f) @ %i+%i\n", def->name, v->vector[0], v->vector[1], v->vector[2], def->ofs, ssize);
else if (v && def->type->type == ev_integer)
printf("Finalise %s(%i) @ %i+%i\n", def->name, v->_int, def->ofs, ssize);
else if (v && def->type->type == ev_function)
printf("Finalise %s(@%i) @ %i+%i\n", def->name, v->_int, def->ofs, ssize);
else if (v && def->type->type == ev_field)
printf("Finalise %s(.%i) @ %i+%i\n", def->name, v->_int, def->ofs, ssize);
else if (v && def->type->type == ev_string)
printf("Finalise %s(%s) @ %i+%i\n", def->name, strings+v->_int, def->ofs, ssize);
else
printf("Finalise %s @ %i+%i\n", def->name, def->ofs, ssize);
#endif
}
@ -1115,9 +1159,29 @@ void QCC_FinaliseDef(QCC_def_t *def)
void QCC_UnmarshalLocals(void)
{
QCC_def_t *d;
unsigned int onum, biggest, eog = numpr_globals;
unsigned int onum, biggest, eog;
size_t i;
//first, finalize private locals.
//finalise all the globals that we've seen so far
for (d = pr.def_head.next ; d ; d = d->next)
{
if (!d->localscope || d->isstatic)
QCC_FinaliseDef(d);
}
//first, finalize all static locals that shouldn't form part of the local defs.
for (i=0 ; i<numfunctions ; i++)
{
if (functions[i].privatelocals)
{
for (d = functions[i].firstlocal; d; d = d->nextlocal)
if (d->isstatic || (d->constant && d->initialized))
QCC_FinaliseDef(d);
}
}
eog = numpr_globals;
//next, finalize non-static locals.
for (i=0 ; i<numfunctions ; i++)
{
if (functions[i].privatelocals)
@ -1127,7 +1191,8 @@ void QCC_UnmarshalLocals(void)
printf("function %s locals:\n", functions[i].name);
#endif
for (d = functions[i].firstlocal; d; d = d->nextlocal)
QCC_FinaliseDef(d);
if (!d->isstatic && !(d->constant && d->initialized))
QCC_FinaliseDef(d);
if (verbose >= VERBOSE_DEBUG)
{
if (onum == numpr_globals)
@ -1294,13 +1359,10 @@ pbool QCC_WriteData (int crc)
def = QCC_PR_GetDef(NULL, "end_sys_fields", NULL, false, 0, false);
if (def)
def->referenced = true;
QCC_PR_FinaliseFunctions();
QCC_DetermineNeededSymbols(def);
for (def = pr.def_head.next ; def ; def = def->next)
{
if (!def->localscope)
QCC_FinaliseDef(def);
}
QCC_UnmarshalLocals();
QCC_FinaliseTemps();
@ -2003,7 +2065,7 @@ strofs = (strofs+3)&~3;
{
char line[2048];
QC_snprintfz(line, sizeof(line), "code: %s:%i: @%i %s t%i t%i %i (%s", QCC_FileForStatement(i), statements[i].linenum, i, pr_opcodes[statements[i].op].opname, a, b, c, QCC_VarAtOffset(statements[i].a));
QC_snprintfz(line, sizeof(line), "code: %s:%i: @%i %s %i %i %i (%s", QCC_FileForStatement(i), statements[i].linenum, i, pr_opcodes[statements[i].op].opname, a, b, c, QCC_VarAtOffset(statements[i].a));
QC_snprintfz(line+strlen(line), sizeof(line)-strlen(line), " %s", QCC_VarAtOffset(statements[i].b));
QC_snprintfz(line+strlen(line), sizeof(line)-strlen(line), " %s)\n", QCC_VarAtOffset(statements[i].c));
printf("%s", line);
@ -2518,7 +2580,6 @@ static void QCC_MergeStatements16(dstatement16_t *in, unsigned int num)
out->linenum = 0;
numstatements++;
}
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope, int arraysize, QCC_def_t *rootsymbol, unsigned int ofs, int referable, unsigned int flags);
static etype_t QCC_MergeFindFieldType(unsigned int ofs, const char *fldname, ddef16_t *fields, size_t numfields)
{
size_t i;
@ -3120,6 +3181,11 @@ int QCC_PR_FinishCompilation (void)
continue;
}
}
if (d->unused)
{
d->initialized = 1;
continue;
}
QCC_PR_Warning(ERR_NOFUNC, d->filen, d->s_line, "function %s has no body",d->name);
QCC_PR_ParsePrintDef(ERR_NOFUNC, d);
bodylessfuncs = true;
@ -4027,7 +4093,21 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
else
*compiler_flag[p].enabled = false;
}
if (!strcmp(myargv[i]+5, "fteqcc"))
if (!strcmp(myargv[i]+5, "qccx"))
{
flag_qccx = true; //fixme: extra stuff
qccwarningaction[WARN_DENORMAL] = WA_IGNORE; //this is just too spammy
qccwarningaction[WARN_LAXCAST] = WA_IGNORE; //more plausable, but still too spammy. easier to fix at least.
}
else if (!strcmp(myargv[i]+5, "preqcc"))
{
flag_hashonly = true;
}
else if (!strcmp(myargv[i]+5, "reacc"))
{
flag_acc = true;
}
else if (!strcmp(myargv[i]+5, "fteqcc"))
; //as above, its the default.
else if (!strcmp(myargv[i]+5, "id"))
{
@ -4537,10 +4617,11 @@ pbool QCC_main (int argc, char **argv) //as part of the quake engine
MAX_GLOBALS = 1<<17;
MAX_FIELDS = 1<<12;
MAX_STATEMENTS = 0x80000;
MAX_FUNCTIONS = 16384;
MAX_FUNCTIONS = 32768;
maxtypeinfos = 32768;
MAX_CONSTANTS = 4096;
strcpy(destfile, "");
compressoutput = 0;
p = externs->FileSize("qcc.cfg");

View file

@ -686,7 +686,7 @@ void PR_Deinit(void)
PRSV_ClearThreads();
#ifdef VM_Q1
Q1QVM_Shutdown();
Q1QVM_Shutdown(true);
#endif
if (svprogfuncs)
{
@ -4197,7 +4197,12 @@ int PF_precache_sound_Internal (pubprogfuncs_t *prinst, const char *s)
{
if (!sv.strings.sound_precache[i])
{
sv.strings.sound_precache[i] = PR_AddString(prinst, s, 0, false);
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
sv.strings.sound_precache[i] = s;
else
#endif
sv.strings.sound_precache[i] = PR_AddString(prinst, s, 0, false);
/*touch the file, so any packs will be referenced*/
FS_FLocateFile(s, FSLF_IFFOUND, NULL);

View file

@ -109,8 +109,8 @@ static struct
qboolean triedlib;
dllhandle_t lib;
lua_State * (QDECL *newstate) (lua_Alloc f, void *ud);
lua_CFunction (QDECL *atpanic) (lua_State *L, lua_CFunction panicf);
lua_State * (QDECL *newstate) (lua_Alloc f, void *ud);
lua_CFunction (QDECL *atpanic) (lua_State *L, lua_CFunction panicf);
void (QDECL *close) (lua_State *L);
int (QDECL *load) (lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode);
int (QDECL *pcallk) (lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k);
@ -150,22 +150,22 @@ static struct
int (QDECL *Lcallmeta) (lua_State *L, int obj, const char *e);
int (QDECL *Lnewmetatable) (lua_State *L, const char *tname);
} lua;
} lua;
#define pcall(L,n,r,f) pcallk(L, (n), (r), (f), 0, NULL)
#define call(L,n,r) callk(L, (n), (r), 0, NULL)
#define pop(L,n) settop(L, -(n)-1)
#define pushstring(L,s) pushfstring(L,"%s",s)
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
#define LUA_NUMTAGS 9
#define LUA_REGISTRYINDEX (-1000000 - 1000)
@ -506,13 +506,13 @@ static int my_lua_entity_get(lua_State *L) //__index
lua.pushinteger(L, eval->_int);
return 1;
case ev_vector:
lua.createtable(L, 0, 0);
//FIXME: should provide a metatable with a __tostring
lua.pushnumber(L, eval->_vector[0]);
lua.setfield (L, -2, "x");
lua.pushnumber(L, eval->_vector[1]);
lua.setfield (L, -2, "y");
lua.pushnumber(L, eval->_vector[2]);
lua.createtable(L, 0, 0);
//FIXME: should provide a metatable with a __tostring
lua.pushnumber(L, eval->_vector[0]);
lua.setfield (L, -2, "x");
lua.pushnumber(L, eval->_vector[1]);
lua.setfield (L, -2, "y");
lua.pushnumber(L, eval->_vector[2]);
lua.setfield (L, -2, "z");
return 1;
case ev_function:
@ -1147,13 +1147,13 @@ static int bi_lua_vectoangles(lua_State *L)
}
VectorAngles(forward, up, ret);
lua.createtable(L, 0, 0);
//FIXME: should provide a metatable with a __tostring
lua.pushnumber(L, ret[0]);
lua.setfield (L, -2, "x");
lua.pushnumber(L, ret[1]);
lua.setfield (L, -2, "y");
lua.pushnumber(L, ret[2]);
lua.createtable(L, 0, 0);
//FIXME: should provide a metatable with a __tostring
lua.pushnumber(L, ret[0]);
lua.setfield (L, -2, "x");
lua.pushnumber(L, ret[1]);
lua.setfield (L, -2, "y");
lua.pushnumber(L, ret[2]);
lua.setfield (L, -2, "z");
return 1;
}
@ -1509,35 +1509,35 @@ static int bi_lua_loadlua(lua_State *L)
#define registerfunc(n) lua.pushcclosure(L, bi_lua_##n, 0); lua.setglobal(L, #n);
static void my_lua_registerbuiltins(lua_State *L)
{
lua.atpanic (L, my_lua_panic);
//standard lua library replacement
//this avoids the risk of including any way to access os.execute etc, or other file access.
lua.pushcclosure(L, my_lua_tostring, 0);
lua.setglobal(L, "tostring");
lua.pushcclosure(L, my_lua_print, 0);
lua.setglobal(L, "print");
lua.pushcclosure(L, my_lua_conprint, 0); //for the luls.
lua.setglobal(L, "conprint");
registerfunc(loadlua);
registerfunc(setmodel);
registerfunc(precache_model);
registerfunc(precache_sound);
registerfunc(lightstyle);
registerfunc(spawn);
registerfunc(remove);
{
lua.atpanic (L, my_lua_panic);
//standard lua library replacement
//this avoids the risk of including any way to access os.execute etc, or other file access.
lua.pushcclosure(L, my_lua_tostring, 0);
lua.setglobal(L, "tostring");
lua.pushcclosure(L, my_lua_print, 0);
lua.setglobal(L, "print");
lua.pushcclosure(L, my_lua_conprint, 0); //for the luls.
lua.setglobal(L, "conprint");
registerfunc(loadlua);
registerfunc(setmodel);
registerfunc(precache_model);
registerfunc(precache_sound);
registerfunc(lightstyle);
registerfunc(spawn);
registerfunc(remove);
registerfunc(nextent);
registerfunc(nextclient);
//registerfunc(AIM);
registerfunc(makestatic);
registerfunc(setorigin);
registerfunc(setsize);
registerfunc(dprint);
registerfunc(makestatic);
registerfunc(setorigin);
registerfunc(setsize);
registerfunc(dprint);
registerfunc(bprint);
registerfunc(sprint);
registerfunc(centerprint);
@ -1602,20 +1602,20 @@ static void my_lua_registerbuiltins(lua_State *L)
//registerfunc(PRECACHE_VWEP_MODEL);
//registerfunc(SETPAUSE);
lua.createtable(L, 0, 0);
if (lua.Lnewmetatable(L, "globals"))
{
lua.pushcclosure(L, my_lua_global_set, 0); //for the luls.
lua.setfield (L, -2, "__newindex");
lua.pushcclosure(L, my_lua_global_get, 0); //for the luls.
lua.setfield (L, -2, "__index");
}
lua.setmetatable(L, -2);
lua.setglobal(L, "glob");
lua.createtable(L, 0, 0);
if (lua.Lnewmetatable(L, "globals"))
{
lua.pushcclosure(L, my_lua_global_set, 0); //for the luls.
lua.setfield (L, -2, "__newindex");
lua.pushcclosure(L, my_lua_global_get, 0); //for the luls.
lua.setfield (L, -2, "__index");
}
lua.setmetatable(L, -2);
lua.setglobal(L, "glob");
}
@ -1692,21 +1692,21 @@ static edict_t *Lua_DoRespawn(pubprogfuncs_t *pf, edict_t *e, int num)
//create a new table for the entity, give it a suitable metatable, and store it into the registry (avoiding GC and allowing us to actually hold on to it).
lua.pushlightuserdata(L, lua.edicttable[num]);
lua.createtable(L, 0, 0);
if (lua.Lnewmetatable(L, "entity"))
{
lua.pushcclosure(L, my_lua_entity_set, 0); //known writes should change the internal info so the engine can use the information.
lua.setfield (L, -2, "__newindex");
lua.pushcclosure(L, my_lua_entity_get, 0); //we need to de-translate the engine's fields too.
lua.setfield (L, -2, "__index");
lua.pushcclosure(L, my_lua_entity_tostring, 0); //cos its prettier than seeing 'table 0x5425729' all over the place
lua.setfield (L, -2, "__tostring");
lua.pushcclosure(L, my_lua_entity_eq, 0); //for comparisons, you know?
lua.setfield (L, -2, "__eq");
}
lua.createtable(L, 0, 0);
if (lua.Lnewmetatable(L, "entity"))
{
lua.pushcclosure(L, my_lua_entity_set, 0); //known writes should change the internal info so the engine can use the information.
lua.setfield (L, -2, "__newindex");
lua.pushcclosure(L, my_lua_entity_get, 0); //we need to de-translate the engine's fields too.
lua.setfield (L, -2, "__index");
lua.pushcclosure(L, my_lua_entity_tostring, 0); //cos its prettier than seeing 'table 0x5425729' all over the place
lua.setfield (L, -2, "__tostring");
lua.pushcclosure(L, my_lua_entity_eq, 0); //for comparisons, you know?
lua.setfield (L, -2, "__eq");
}
lua.setmetatable(L, -2);
lua.pushinteger(L, num);
lua.setfield (L, -2, "entnum"); //so we know which entity it is.

View file

@ -43,22 +43,20 @@ oh, wait, ktx no longer supports those properly.
#include "pr_common.h"
#define GAME_API_VERSION 13
/*version changes:
13: 2009/june gamecode no longer aware of edict_t data (just 'qc' fields).
14: 2017/march gamedata_t.maxentities added
15: 2017/june for-64bit string indirection changes. added GAME_CLEAR_EDICT.
*/
#define GAME_API_VERSION 15
#define GAME_API_VERSION_MIN 8
#define MAX_Q1QVM_EDICTS 768 //according to ktx at api version 12 (fte's protocols go to 2048)
#define MAPNAME_LEN 64
void PR_SV_FillWorldGlobals(world_t *w);
#if GAME_API_VERSION >= 13
#define WASTED_EDICT_T_SIZE (VM_NonNative(q1qvm)?sizeof(int):sizeof(void*))
//in version 13, the actual edict_t struct is gone, and there's a pointer to it in its place (which we don't need, but it changes size based on vm/native).
#else
//this is probably broken on 64bit native code
#define WASTED_EDICT_T_SIZE 114
//qclib has split edict_t and entvars_t.
//mvdsv and the api we're implementing has them in one lump
//so we need to bias our entvars_t and fake the offsets a little.
#endif
static int qvm_api_version;
static size_t wasted_edict_t_size;
//===============================================================
@ -209,6 +207,8 @@ typedef enum
GAME_EDICT_BLOCKED, //(self,other)
GAME_CLIENT_SAY, //(int isteam)
GAME_PAUSED_TIC, //(int milliseconds)
GAME_CLEAR_EDICT, //v15 (sets self.fields to safe values after they're cleared)
} q1qvmgameExport_t;
@ -320,6 +320,9 @@ typedef struct
unsigned int global;
unsigned int fields;
int APIversion;
#if GAME_API_VERSION >= 14
unsigned int maxentities;
#endif
} gameData32_t;
typedef struct
@ -329,6 +332,9 @@ typedef struct
quintptr_t global;
quintptr_t fields;
int APIversion;
#if GAME_API_VERSION >= 14
unsigned int maxentities;
#endif
} gameDataN_t;
typedef enum {
@ -354,10 +360,18 @@ typedef enum {
#define emufields \
emufield(gravity, F_FLOAT) \
emufield(maxspeed, F_FLOAT) \
emufield(movement, F_VECTOR) \
emufield(vw_index, F_FLOAT)
emufield(gravity, F_FLOAT) \
emufield(maxspeed, F_FLOAT) \
emufield(movement, F_VECTOR) \
emufield(vw_index, F_FLOAT) \
emufield(isBot, F_INT)
// emufield(items2, F_FLOAT)
// emufield(brokenankle, F_FLOAT)
// emufield(mod_admin, F_INT)
// emufield(hideentity, F_INT)
// emufield(trackent, F_INT)
// emufield(hideplayers, F_INT)
// emufield(visclients, F_INT)
struct
{
@ -371,7 +385,7 @@ static const char *q1qvmentstring;
static vm_t *q1qvm;
static pubprogfuncs_t q1qvmprogfuncs;
static q1qvmglobalvars_t *gvars;
static void *evars; //pointer to the gamecodes idea of an edict_t
static quintptr_t vevars; //offset into the vm base of evars
@ -399,7 +413,7 @@ static edict_t *QDECL Q1QVMPF_EdictNum(pubprogfuncs_t *pf, unsigned int num)
if (!e)
{
e = q1qvmprogfuncs.edicttable[num] = Z_TagMalloc(sizeof(edict_t)+sizeof(extentvars_t), VMFSID_Q1QVM);
e->v = (stdentvars_t*)((char*)evars + (num * sv.world.edict_size) + WASTED_EDICT_T_SIZE);
e->v = (stdentvars_t*)((char*)evars + (num * sv.world.edict_size) + wasted_edict_t_size);
e->xv = (extentvars_t*)(e+1);
e->entnum = num;
}
@ -428,7 +442,14 @@ static void Q1QVMED_ClearEdict (edict_t *e, qboolean wipe)
{
int num = e->entnum;
if (wipe)
memset (e->v, 0, sv.world.edict_size - WASTED_EDICT_T_SIZE);
memset (e->v, 0, sv.world.edict_size - wasted_edict_t_size);
if (qvm_api_version >= 15)
{
int oself = pr_global_struct->self;
pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, e);
VM_Call(q1qvm, GAME_CLEAR_EDICT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
pr_global_struct->self = oself;
}
e->ereftype = ER_ENTITY;
e->entnum = num;
}
@ -520,7 +541,7 @@ static eval_t *QDECL Q1QVMPF_GetEdictFieldValue(pubprogfuncs_t *pf, edict_t *e,
{
if (cache && !cache->varname)
{
return (eval_t*)((char*)e->v + cache->spare[0]-WASTED_EDICT_T_SIZE);
return (eval_t*)((char*)e->v + cache->spare[0]-wasted_edict_t_size);
}
if (!strcmp(fieldname, "message"))
{
@ -560,13 +581,149 @@ static void *ASMCALL QDECL Q1QVMPF_PointerToNative(pubprogfuncs_t *prinst, quint
static const char *ASMCALL QDECL Q1QVMPF_StringToNative(pubprogfuncs_t *prinst, string_t str)
{
char *ret;
quintptr_t ref;
if (str == ~0)
return " "; //models are weird. yes, this is a hack.
if (!str || (quintptr_t)str >= VM_MemoryMask(q1qvm))
if (qvm_api_version >= 15)
{
qboolean stringishacky = sizeof(quintptr_t) != sizeof(string_t) && qvm_api_version >= 15 && !VM_NonNative(q1qvm); //silly bullshit. Really, native gamecode should have its own implementation of this builtin or something, especially as its pretty much only ever used for classnames.
if (!str)
return ""; //invalid...
else if (stringishacky)
{
if (str >= 0 && str < sv.world.edict_size*sv.world.max_edicts - sizeof(quintptr_t))
ref = *(quintptr_t*)((char*)evars + (int)str); //extra indirection added in api 15.
else
return ""; //error
}
else
{
if (str >= 0 && str < sv.world.edict_size*sv.world.max_edicts - sizeof(quintptr_t))
ref = *(string_t*)((char*)evars + (int)str); //extra indirection added in api 15.
else
return ""; //error
}
}
else
ref = str;
if (!ref || (quintptr_t)ref >= VM_MemoryMask(q1qvm))
return ""; //null or invalid pointers.
ret = (char*)VM_MemoryBase(q1qvm) + str;
return ret;
return (char*)VM_MemoryBase(q1qvm) + ref;
}
static void QDECL Q1QVMPF_SetStringField(pubprogfuncs_t *progfuncs, struct edict_s *ed, string_t *fld, const char *str, pbool str_is_static)
{
if (!str_is_static)
return;
if (qvm_api_version >= 15)
{
qboolean stringishacky = sizeof(quintptr_t) != sizeof(string_t) && qvm_api_version >= 15 && !VM_NonNative(q1qvm); //silly bullshit. Really, native gamecode should have its own implementation of this builtin or something, especially as its pretty much only ever used for classnames.
quintptr_t nval = (str - (char*)VM_MemoryBase(q1qvm));
if (nval >= VM_MemoryMask(q1qvm))
return;
if (!*fld)
Con_DPrintf("Ignoring string set. mod pointer not set.\n");
else if (stringishacky)
{
if (*fld >= 0 && *fld < sv.world.edict_size*sv.world.max_edicts - sizeof(quintptr_t))
*(quintptr_t*)((char*)evars + *fld) = nval;
else
Con_DPrintf("Ignoring string set outside of progs VM\n");
}
else
{
if (nval >= 0xffffffff)
return; //invalid string! blame 64bit.
if (*fld >= 0 && *fld < sv.world.edict_size*sv.world.max_edicts - sizeof(string_t))
*(string_t*)((char*)evars + *fld) = (string_t)nval;
else
Con_DPrintf("Ignoring string set outside of progs VM\n");
}
}
else
{
string_t newval = progfuncs->StringToProgs(progfuncs, str);
if (newval || !str)
*fld = newval;
else if (!str)
*fld = 0;
else
{
*fld = ~0;
//Con_DPrintf("Ignoring string set outside of progs VM\n");
}
}
}
static void Q1QVMPF_SetStringGlobal(pubprogfuncs_t *progfuncs, string_t *fld, const char *str, size_t copysize)
{
if (qvm_api_version >= 15)
{
qboolean stringishacky = sizeof(quintptr_t) != sizeof(string_t) && qvm_api_version >= 15 && !VM_NonNative(q1qvm); //silly bullshit. Really, native gamecode should have its own implementation of this builtin or something, especially as its pretty much only ever used for classnames.
if (!*fld)
Con_Printf("Q1QVM: string reference not set. Fix the mod.\n");
else if (stringishacky)
{ //quintptr_t
// if (*fld >= 0 && *fld < sv.world.edict_size*sv.world.max_edicts - sizeof(intptr_t))
{
if (!*(quintptr_t*)((char*)gvars + *fld))
{
Con_DPrintf("String buffer not set. Hacking the data in instead.\n");
*(quintptr_t*)((char*)gvars + *fld) = (str - (char*)VM_MemoryBase(q1qvm));
}
else
{
char *ptr = (char*)*(quintptr_t*)((char*)gvars + *fld);
Q_strncpyz(ptr, str, copysize);
}
}
}
else
{ //string_t
// if (*fld >= 0 && *fld < sv.world.edict_size*sv.world.max_edicts - sizeof(string_t))
{
if (!*(quintptr_t*)((char*)gvars + *fld))
{
quintptr_t nval = (str - (char*)VM_MemoryBase(q1qvm));;
if (nval > VM_MemoryMask(q1qvm))
{
Con_Printf("Q1QVM: String buffer not set. Data out of QVM memory space. Fix the mod.\n");
}
else
{
Con_DPrintf("String buffer not set. Hacking the data in instead.\n");
*(quintptr_t*)((char*)gvars + *fld) = (str - (char*)VM_MemoryBase(q1qvm));;
}
}
else
{
char *ptr = (char*)*(quintptr_t*)((char*)gvars + *fld);
Q_strncpyz(ptr, str, copysize);
}
}
}
}
else
{
if (!*fld)
{
quintptr_t nval = (str - (char*)VM_MemoryBase(q1qvm));
if (nval > VM_MemoryMask(q1qvm))
{
Con_Printf("Q1QVM: String buffer not set. Data out of QVM memory space. Fix the mod.\n");
}
else
{
Con_DPrintf("String buffer not set. Hacking the data in instead.\n");
*fld = (str - (char*)VM_MemoryBase(q1qvm));
}
}
else
{
char *ptr = (char*)VM_MemoryBase(q1qvm) + *fld;
Q_strncpyz(ptr, str, copysize);
}
}
}
static int WrapQCBuiltin(builtin_t func, void *offset, quintptr_t mask, const qintptr_t *arg, char *argtypes)
@ -607,7 +764,7 @@ static int WrapQCBuiltin(builtin_t func, void *offset, quintptr_t mask, const qi
#define VALIDATEPOINTER(o,l) if ((qintptr_t)o + l >= mask || VM_POINTER(o) < offset) SV_Error("Call to game trap passes invalid pointer\n"); //out of bounds.
static qintptr_t QVM_GetAPIVersion (void *offset, quintptr_t mask, const qintptr_t *arg)
{
return GAME_API_VERSION;
return qvm_api_version;
}
static qintptr_t QVM_DPrint (void *offset, quintptr_t mask, const qintptr_t *arg)
@ -1245,26 +1402,30 @@ static qintptr_t QVM_strnicmp (void *offset, quintptr_t mask, const qintptr_t *a
static qintptr_t QVM_Find (void *offset, quintptr_t mask, const qintptr_t *arg)
{
edict_t *e = VM_POINTER(arg[0]);
int ofs = VM_LONG(arg[1]) - WASTED_EDICT_T_SIZE;
int ofs = (VM_LONG(arg[1]) - wasted_edict_t_size);
char *match = VM_POINTER(arg[2]);
char *field;
int first = e?((char*)e - (char*)evars)/sv.world.edict_size:0;
int i;
qboolean stringishacky = sizeof(quintptr_t) != sizeof(string_t) && qvm_api_version >= 15 && !VM_NonNative(q1qvm); //silly bullshit. Really, native gamecode should have its own implementation of this builtin or something, especially as its pretty much only ever used for classnames.
if (!match)
match = "";
for (i = first+1; i < sv.world.num_edicts; i++)
{
e = q1qvmprogfuncs.edicttable[i];
field = VM_POINTER(*((string_t*)e->v + ofs/4));
if (stringishacky)
field = VM_POINTER(*(quintptr_t*)((char*)e->v + ofs));
else
field = VM_POINTER(*(string_t*)((char*)e->v + ofs));
if (field == NULL)
{
if (*match == '\0')
return ((char*)e->v - (char*)offset)-WASTED_EDICT_T_SIZE;
return ((char*)e->v - (char*)offset)-wasted_edict_t_size;
}
else
{
if (!strcmp(field, match))
return ((char*)e->v - (char*)offset)-WASTED_EDICT_T_SIZE;
return ((char*)e->v - (char*)offset)-wasted_edict_t_size;
}
}
return 0;
@ -1346,26 +1507,93 @@ static qintptr_t QVM_RedirectCmd (void *offset, quintptr_t mask, const qintptr_t
}
static qintptr_t QVM_Add_Bot (void *offset, quintptr_t mask, const qintptr_t *arg)
{
char *name = VM_POINTER(arg[0]);
int bottom = VM_LONG(arg[1]);
int top = VM_LONG(arg[2]);
char *skin = VM_POINTER(arg[3]);
#if 1
extern int nextuserid;
int i;
for (i = 0; i < sv.allocated_client_slots; i++)
{
client_t *cl = &svs.clients[i];
if (!*cl->name && !cl->protocol && cl->state == cs_free)
{
cl->userid = ++nextuserid;
cl->protocol = SCP_BAD; //marker for bots
cl->state = cs_spawned;
cl->spawned = true;
sv.spawned_client_slots++;
cl->netchan.message.allowoverflow = true;
cl->netchan.message.maxsize = 0;
cl->datagram.allowoverflow = true;
cl->datagram.maxsize = 0;
cl->edict = EDICT_NUM(sv.world.progs, i+1);
Info_SetValueForKey(cl->userinfo, "name", name, sizeof(cl->userinfo));
Info_SetValueForKey(cl->userinfo, "topcolor", va("%i", top), sizeof(cl->userinfo));
Info_SetValueForKey(cl->userinfo, "bottomcolor", va("%i", bottom), sizeof(cl->userinfo));
Info_SetValueForKey(cl->userinfo, "skin", skin, sizeof(cl->userinfo));
Info_SetValueForStarKey(cl->userinfo, "*bot", "1", sizeof(cl->userinfo));
SV_ExtractFromUserinfo(cl, true);
SV_SetUpClientEdict (cl, cl->edict);
SV_FullClientUpdate(cl, NULL);
Q1QVM_ClientConnect(cl);
return cl->edict->entnum;
}
}
#else
//FIXME: not implemented, always returns failure.
//the other bot functions only ever work on bots anyway, so don't need to be implemented until this one is
//return WrapQCBuiltin(PF_spawnclient, offset, mask, arg, "");
Con_DPrintf("QVM_Add_Bot: not implemented\n");
#endif
return 0;
}
static qintptr_t QVM_Remove_Bot (void *offset, quintptr_t mask, const qintptr_t *arg)
{
//fixme: should become general kick
//kicks NOW. which generally makes it unsafe for players (calling from StartFrame should be okay).
int entnum = VM_LONG(arg[0]);
if (entnum >= 1 && entnum <= svs.allocated_client_slots)
{
client_t *cl = &svs.clients[entnum-1];
SV_DropClient(cl);
}
Con_DPrintf("QVM_Remove_Bot: not implemented\n");
//WrapQCBuiltin(PF_dropclient, offset, mask, arg, "n");
return 0;
}
static qintptr_t QVM_SetBotCMD (void *offset, quintptr_t mask, const qintptr_t *arg)
{
//in mvdsv, this is run *after* the frame.
Con_DPrintf("QVM_SetBotCMD: not implemented\n");
//this just queues the command for later, even in mvdsv. ignore the msecs value because its basically pointless
int edn = VM_LONG(arg[0]);
int msec = VM_LONG(arg[1]);
float angles_x = VM_FLOAT(arg[2]);
float angles_y = VM_FLOAT(arg[3]);
float angles_z = VM_FLOAT(arg[4]);
int forwardmove = VM_LONG(arg[5]);
int sidemove = VM_LONG(arg[6]);
int upmove = VM_LONG(arg[7]);
int buttons = VM_LONG(arg[8]);
int impulse = VM_LONG(arg[9]);
if (edn >= 1 && edn <= svs.allocated_client_slots)
{
client_t *cl = &svs.clients[edn-1];
cl->lastcmd.msec = msec;
cl->lastcmd.angles[0] = ANGLE2SHORT(angles_x);
cl->lastcmd.angles[1] = ANGLE2SHORT(angles_y);
cl->lastcmd.angles[2] = ANGLE2SHORT(angles_z);
cl->lastcmd.forwardmove = forwardmove;
cl->lastcmd.sidemove = sidemove;
cl->lastcmd.upmove = upmove;
cl->lastcmd.buttons = buttons;
cl->lastcmd.impulse = impulse;
}
return 0;
}
static qintptr_t QVM_SetUserInfo (void *offset, quintptr_t mask, const qintptr_t *arg)
@ -1551,19 +1779,19 @@ static qintptr_t QVM_uri_query (void *offset, quintptr_t mask, const qintptr_t *
if (!pr_enable_uriget.ival)
{
Con_Printf("QVM_uri_query(\"%s\",%"PRIxPTR"): %s disabled\n", url, (qintptr_t)cb_context, pr_enable_uriget.name);
Con_Printf("QVM_uri_query(\"%s\"): %s disabled\n", url, pr_enable_uriget.name);
return 0;
}
if (mimetype && *mimetype)
{
VALIDATEPOINTER(arg[4],datasize);
Con_DPrintf("QVM_uri_query(%s,%"PRIxPTR")\n", url, (qintptr_t)cb_context);
Con_DPrintf("QVM_uri_query(%s)\n", url);
dl = HTTP_CL_Put(url, mimetype, data, datasize, QVM_uri_query_callback);
}
else
{
Con_DPrintf("QVM_uri_query(%s,%"PRIxPTR")\n", url, (qintptr_t)cb_context);
Con_DPrintf("QVM_uri_query(%s)\n", url);
dl = HTTP_CL_Get(url, NULL, QVM_uri_query_callback);
}
if (dl)
@ -1740,8 +1968,8 @@ struct
//sql?
//model querying?
//skeletal objects/tags?
//heightmap / brush editing?
//custom stats (mod can always writebyte, I guess, sounds horrible though)
//csqc ents
{NULL, NULL}
};
@ -1823,7 +2051,7 @@ static qintptr_t EXPORT_FN syscallnative (qintptr_t arg, ...)
return traps[arg](NULL, ~(quintptr_t)0, args);
}
void Q1QVM_Shutdown(void)
void Q1QVM_Shutdown(qboolean notifygame)
{
int i;
if (q1qvm)
@ -1834,7 +2062,8 @@ void Q1QVM_Shutdown(void)
Q_strncpyz(svs.clients[i].namebuf, svs.clients[i].name, sizeof(svs.clients[i].namebuf));
svs.clients[i].name = svs.clients[i].namebuf;
}
VM_Call(q1qvm, GAME_SHUTDOWN, 0, 0, 0);
if (notifygame)
VM_Call(q1qvm, GAME_SHUTDOWN, 0, 0, 0);
VM_Destroy(q1qvm);
q1qvm = NULL;
VM_fcloseall(VMFSID_Q1QVM);
@ -1850,6 +2079,25 @@ void Q1QVM_Shutdown(void)
}
}
static void QDECL Q1QVM_Get_FrameState(world_t *w, wedict_t *ent, framestate_t *fstate)
{
memset(fstate, 0, sizeof(*fstate));
fstate->g[FS_REG].frame[0] = ent->v->frame;
fstate->g[FS_REG].frametime[0] = ent->xv->frame1time;
fstate->g[FS_REG].lerpweight[0] = 1;
fstate->g[FS_REG].endbone = 0x7fffffff;
fstate->g[FST_BASE].frame[0] = ent->xv->baseframe;
fstate->g[FST_BASE].frametime[0] = ent->xv->/*base*/frame1time;
fstate->g[FST_BASE].lerpweight[0] = 1;
fstate->g[FST_BASE].endbone = ent->xv->basebone;
#if defined(SKELETALOBJECTS) || defined(RAGDOLL)
if (ent->xv->skeletonindex)
skel_lookup(w, ent->xv->skeletonindex, fstate);
#endif
}
static void QDECL Q1QVM_Event_Touch(world_t *w, wedict_t *s, wedict_t *o)
{
int oself = pr_global_struct->self;
@ -1876,20 +2124,6 @@ static qboolean QDECL Q1QVM_Event_ContentsTransition(world_t *w, wedict_t *ent,
return false; //always do legacy behaviour
}
static void QDECL Q1QVMPF_SetStringField(pubprogfuncs_t *progfuncs, struct edict_s *ed, string_t *fld, const char *str, pbool str_is_static)
{
string_t newval = progfuncs->StringToProgs(progfuncs, str);
if (newval || !str)
*fld = newval;
else if (!str)
*fld = 0;
else
{
*fld = ~0;
// Con_DPrintf("Ignoring string set outside of progs VM\n");
}
}
qboolean PR_LoadQ1QVM(void)
{
static int writable_int;
@ -1902,12 +2136,11 @@ qboolean PR_LoadQ1QVM(void)
gameDataPrivate_t gd;
gameDataN_t *gdn;
gameData32_t *gd32;
q1qvmglobalvars_t *global;
qintptr_t ret;
qintptr_t limit;
extern cvar_t pr_maxedicts;
Q1QVM_Shutdown();
Q1QVM_Shutdown(true);
q1qvm = VM_Create("qwprogs", com_nogamedirnativecode.ival?NULL:syscallnative, syscallqvm);
if (!q1qvm)
@ -1955,6 +2188,7 @@ qboolean PR_LoadQ1QVM(void)
sv.world.Event_Sound = SVQ1_StartSound;
sv.world.Event_ContentsTransition = Q1QVM_Event_ContentsTransition;
sv.world.Get_CModel = SVPR_GetCModel;
sv.world.Get_FrameState = Q1QVM_Get_FrameState;
sv.world.num_edicts = 0; //we're not ready for most of the builtins yet
sv.world.max_edicts = 0; //so clear these out, just in case
@ -1964,10 +2198,12 @@ qboolean PR_LoadQ1QVM(void)
q1qvmprogfuncs.stringtable = VM_MemoryBase(q1qvm);
qvm_api_version = GAME_API_VERSION;
ret = VM_Call(q1qvm, GAME_INIT, (qintptr_t)(sv.time*1000), rand(), 0, 0, 0);
if (!ret)
{
Q1QVM_Shutdown();
Q1QVM_Shutdown(false);
return false;
}
@ -1982,7 +2218,10 @@ qboolean PR_LoadQ1QVM(void)
gd.global = gd32->global;
gd.fields = gd32->fields;
gd.maxedicts = pr_maxedicts.ival; //FIXME
if (qvm_api_version >= 14)
gd.maxedicts = gd32->maxentities;
else
gd.maxedicts = MAX_Q1QVM_EDICTS;
}
else
{
@ -1994,7 +2233,30 @@ qboolean PR_LoadQ1QVM(void)
gd.global = gdn->global;
gd.fields = gdn->fields;
gd.maxedicts = pr_maxedicts.ival; //FIXME
if (qvm_api_version >= 14)
gd.maxedicts = gdn->maxentities;
else
gd.maxedicts = MAX_Q1QVM_EDICTS;
}
gd.maxedicts = bound(1, pr_maxedicts.ival, gd.maxedicts);
qvm_api_version = gd.APIversion;
if (!(GAME_API_VERSION_MIN <= qvm_api_version && qvm_api_version <= GAME_API_VERSION))
{
Con_Printf("QVM-API version %i not supported\n", qvm_api_version);
Q1QVM_Shutdown(false);
return false;
}
//in version 13, the actual edict_t struct is gone, and there's a pointer to it in its place (which is unusable, and changes depending on modes).
if (qvm_api_version)
wasted_edict_t_size = (VM_NonNative(q1qvm)?sizeof(int):sizeof(void*));
else
{
//fte/qclib has split edict_t and entvars_t.
//older versions of the qvm api has them in one lump
//so we need to bias the mod's entvars_t offsets a little.
wasted_edict_t_size = 114;
}
sv.world.num_edicts = 1;
@ -2014,21 +2276,21 @@ qboolean PR_LoadQ1QVM(void)
sv.world.edict_size = gd.sizeofent;
vevars = gd.ents;
evars = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, vevars);
global = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, gd.global);
gvars = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, gd.global);
if (!evars || !global)
if (!evars || !gvars)
{
Q1QVM_Shutdown();
Q1QVM_Shutdown(false);
return false;
}
//WARNING: global is not remapped yet...
//This code is written evilly, but works well enough
#define globalint(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name) //the logic of this is somewhat crazy
#define globalfloat(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
#define globalstring(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
#define globalvec(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
#define globalfunc(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&global->name)
#define globalint(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&gvars->name) //the logic of this is somewhat crazy
#define globalfloat(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&gvars->name)
#define globalstring(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&gvars->name)
#define globalvec(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&gvars->name)
#define globalfunc(required, name) pr_global_ptrs->name = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, (qintptr_t)&gvars->name)
#define globalnull(required, name) pr_global_ptrs->name = NULL
globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about.
globalint (true, other);
@ -2084,6 +2346,9 @@ qboolean PR_LoadQ1QVM(void)
pr_global_ptrs->physics_mode = &physics_mode;
pr_global_ptrs->trace_brush_id = &writable_int;
pr_global_ptrs->trace_brush_faceid = &writable_int;
pr_global_ptrs->trace_surface_id = &writable_int;
pr_global_ptrs->trace_bone_id = &writable_int;
pr_global_ptrs->trace_triangle_id = &writable_int;
pr_global_ptrs->global_gravitydir = &defaultgravity;
// ensureglobal(input_timelength, input_timelength_default);
@ -2094,12 +2359,12 @@ qboolean PR_LoadQ1QVM(void)
dimensionsend = dimensiondefault = 255;
for (i = 0; i < 16; i++)
pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&global->parm1 + i));
pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gvars->parm1 + i));
for (; i < NUM_SPAWN_PARMS; i++)
pr_global_ptrs->spawnparamglobals[i] = NULL;
pr_global_ptrs->parm_string = NULL;
#define emufield(n,t) if (field[i].type == t && !strcmp(#n, fname)) {fofs.n = (field[i].ofs - WASTED_EDICT_T_SIZE)/sizeof(float); continue;}
#define emufield(n,t) if (field[i].type == t && !strcmp(#n, fname)) {fofs.n = (field[i].ofs - wasted_edict_t_size)/sizeof(float); continue;}
if (VM_NonNative(q1qvm))
{
field32_t *field = Q1QVMPF_PointerToNative(&q1qvmprogfuncs, gd.fields);
@ -2127,10 +2392,26 @@ qboolean PR_LoadQ1QVM(void)
sv.world.edicts = (wedict_t*)Q1QVMPF_EdictNum(svprogfuncs, 0);
sv.world.usesolidcorpse = true;
if ((quintptr_t)global->mapname && (quintptr_t)global->mapname+MAPNAME_LEN < VM_MemoryMask(q1qvm))
Q_strncpyz((char*)VM_MemoryBase(q1qvm) + global->mapname, svs.name, MAPNAME_LEN);
if (qvm_api_version >= 15)
{
int e;
for (e = 0; e <= 32; e++)
{
pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, Q1QVMPF_EdictNum(svprogfuncs, e));
VM_Call(q1qvm, GAME_CLEAR_EDICT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
pr_global_struct->self = 0;
Q1QVMPF_SetStringGlobal(sv.world.progs, &gvars->mapname, svs.name, MAPNAME_LEN);
}
else
global->mapname = Q1QVMPF_StringToProgs(sv.world.progs, svs.name);
{
if ((quintptr_t)gvars->mapname && (quintptr_t)gvars->mapname+MAPNAME_LEN < VM_MemoryMask(q1qvm))
Q_strncpyz((char*)VM_MemoryBase(q1qvm) + gvars->mapname, svs.name, MAPNAME_LEN);
else
gvars->mapname = Q1QVMPF_StringToProgs(sv.world.progs, svs.name);
}
PR_SV_FillWorldGlobals(&sv.world);
return true;
@ -2141,12 +2422,25 @@ qboolean PR_LoadQ1QVM(void)
void Q1QVM_ClientConnect(client_t *cl)
{
if (cl->edict->v->netname)
if (qvm_api_version >= 15 && !VM_NonNative(q1qvm))
{
strcpy(cl->namebuf, cl->name);
cl->name = (char*)Q1QVMPF_StringToNative(svprogfuncs, cl->edict->v->netname);
//FIXME: check this pointer
strcpy(cl->name, cl->namebuf);
Q_strncpyz(cl->namebuf, cl->name, sizeof(cl->namebuf));
Q1QVMPF_SetStringField(sv.world.progs, cl->edict, &cl->edict->v->netname, cl->namebuf, true);
}
else if (cl->edict->v->netname)
{
char *name;
char *base = VM_MemoryBase(q1qvm);
quintptr_t mask = VM_MemoryMask(q1qvm);
name = (char*)Q1QVMPF_StringToNative(svprogfuncs, cl->edict->v->netname);
if (cl->name > base && cl->name < base+mask)
{
Q_strncpyz(cl->namebuf, name, sizeof(cl->namebuf));
strcpy(name, cl->namebuf);
cl->name = name; //so the gamecode can do changes if it wants.
}
else
Con_Printf("WARNING: Mod provided no netname buffer. Player names will not be set properly.\n");
}
else if (!VM_NonNative(q1qvm))
{
@ -2160,9 +2454,11 @@ void Q1QVM_ClientConnect(client_t *cl)
Con_Printf("WARNING: Mod provided no netname buffer. Player names will not be set properly.\n");
if (fofs.gravity)
((float*)sv_player->v)[fofs.gravity] = sv_player->xv->gravity;
((float*)cl->edict->v)[fofs.gravity] = cl->edict->xv->gravity;
if (fofs.maxspeed)
((float*)sv_player->v)[fofs.maxspeed] = sv_player->xv->maxspeed;
((float*)cl->edict->v)[fofs.maxspeed] = cl->edict->xv->maxspeed;
if (fofs.isBot)
((float*)cl->edict->v)[fofs.isBot] = !cl->protocol;
// call the spawn function
pr_global_struct->time = sv.world.physicstime;
@ -2251,9 +2547,11 @@ void Q1QVM_PostThink(void)
sv_player->xv->vw_index = ((float*)sv_player->v)[fofs.vw_index];
}
void Q1QVM_StartFrame(void)
void Q1QVM_StartFrame(qboolean botsarespecialsnowflakes)
{
VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000), 0, 0, 0);
if (botsarespecialsnowflakes && qvm_api_version < 15)
return; //this stupidity brought to you with api 15!
VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000), botsarespecialsnowflakes, 0, 0);
}
void Q1QVM_Blocked(void)

View file

@ -132,7 +132,7 @@ qboolean PR_LoadLua(void);
#ifdef VM_Q1
#define VMFSID_Q1QVM 57235 //the q1qvm zone tag that is freed when the module is purged.
struct client_s;
void Q1QVM_Shutdown(void);
void Q1QVM_Shutdown(qboolean notifygame);
qboolean PR_LoadQ1QVM(void);
void Q1QVM_ClientConnect(struct client_s *cl);
qboolean Q1QVM_GameConsoleCommand(void);
@ -141,7 +141,7 @@ qboolean Q1QVM_UserInfoChanged(edict_t *player);
void Q1QVM_PlayerPreThink(void);
void Q1QVM_RunPlayerThink(void);
void Q1QVM_PostThink(void);
void Q1QVM_StartFrame(void);
void Q1QVM_StartFrame(qboolean botsarespecialsnowflakes);
void Q1QVM_Blocked(void);
void Q1QVM_SetNewParms(void);
void Q1QVM_SetChangeParms(void);

View file

@ -622,7 +622,7 @@ void SV_UnspawnServer (void) //terminate the running server.
SVHL_ShutdownGame();
#endif
#ifdef VM_Q1
Q1QVM_Shutdown();
Q1QVM_Shutdown(true);
#endif
sv.world.worldmodel = NULL;
sv.state = ss_dead;
@ -1147,7 +1147,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
#endif
#ifdef VM_Q1
if (newgametype != GT_Q1QVM)
Q1QVM_Shutdown();
Q1QVM_Shutdown(true);
#endif
SV_UpdateMaxPlayers(0);

View file

@ -4647,7 +4647,7 @@ void SV_Impulse_f (void)
SV_SetUpClientEdict(&svs.clients[i], svs.clients[i].edict);
svs.clients[i].edict->v->netname = PR_SetString(svprogfuncs, "Console");
svprogfuncs->SetStringField(svprogfuncs, svs.clients[i].edict, &svs.clients[i].edict->v->netname, "Console", true);
sv.skipbprintclient = &svs.clients[i];
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, svs.clients[i].edict);
@ -5439,7 +5439,7 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
}
}
if (!cl->drop && strncmp(val, cl->name, sizeof(cl->namebuf)-1))
if (!cl->drop && strncmp(val, cl->name, sizeof(cl->namebuf)-1) && cl->state > cs_zombie)
{
if (*cl->name && cl->state >= cs_spawned && !cl->spectator && verbose)
{

View file

@ -156,6 +156,19 @@ Handles cursor positioning, line wrapping, etc
#define MAXPRINTMSG 4096
// FIXME: make a buffer size safe vsprintf?
#ifdef SERVERONLY
vfsfile_t *con_pipe;
vfsfile_t *Con_POpen(char *conname)
{
if (!conname || !*conname)
{
if (con_pipe)
VFS_CLOSE(con_pipe);
con_pipe = VFSPIPE_Open(2, false);
return con_pipe;
}
return NULL;
}
static void Con_PrintFromThread (void *ctx, void *data, size_t a, size_t b)
{
Con_Printf("%s", (char*)data);
@ -188,6 +201,9 @@ void VARGS Con_Printf (const char *fmt, ...)
Sys_Printf ("%s", msg); // also echo to debugging console
Con_Log(msg); // log to console
if (con_pipe)
VFS_PUTS(con_pipe, msg);
}
void Con_TPrintf (translation_t stringnum, ...)
{
@ -227,6 +243,9 @@ void Con_TPrintf (translation_t stringnum, ...)
Sys_Printf ("%s", msg); // also echo to debugging console
Con_Log(msg); // log to console
if (con_pipe)
VFS_PUTS(con_pipe, msg);
}
/*
================
@ -2706,9 +2725,10 @@ qboolean SV_SendClientDatagram (client_t *client)
#endif
}
msg.maxsize = clientlimit;
// copy the accumulated multicast datagram
// for this client out to the message
if (!client->datagram.overflowed && msg.cursize + client->datagram.cursize <= clientlimit)
if (!client->datagram.overflowed && !msg.overflowed && msg.cursize + client->datagram.cursize <= clientlimit)
{
SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
SZ_Clear (&client->datagram);

View file

@ -1110,34 +1110,64 @@ void ApplyColour(unsigned int chr)
//this could be much more efficient.
static void Sys_PrintColouredChars(conchar_t *start, conchar_t *end)
{
conchar_t m;
wchar_t wc[256];
int l;
DWORD dummy;
unsigned int cp, flags, m;
m = CON_WHITEMASK;
l = 0;
while(start < end)
{
l = 0;
m = *start & CON_FLAGSMASK;
for (;;)
start = Font_Decode(start, &flags, &cp);
if (l+2 >= countof(wc) || flags != m)
{
if (start == end || m != (*start & CON_FLAGSMASK) || l >= countof(wc))
ApplyColour(m);
if (WinNT)
WriteConsoleW(hconsoleout, wc, l, &dummy, NULL);
else
{
ApplyColour(m);
if (WinNT)
WriteConsoleW(hconsoleout, wc, l, &dummy, NULL);
else
{
//win95 doesn't support wide chars *sigh*. blank consoles suck.
char ac[256];
l = WideCharToMultiByte(CP_ACP, 0, wc, l, ac, sizeof(ac), NULL, NULL);
WriteConsole(hconsoleout, ac, l, &dummy, NULL);
}
break;
//win95 doesn't support wide chars *sigh*. blank consoles suck.
char ac[256];
l = WideCharToMultiByte(CP_ACP, 0, wc, l, ac, sizeof(ac), NULL, NULL);
WriteConsole(hconsoleout, ac, l, &dummy, NULL);
}
if (!(*start & CON_HIDDEN))
wc[l++] = *start & CON_CHARMASK;
start++;
l = 0;
}
if (!(flags & CON_HIDDEN))
{
if (cp >= 0xe000 && cp < 0xe100)
{
cp -= 0xe000;
if (cp >= 0x80)
{
char c1[32] = "---..........> " "[]0123456789.---";
cp -= 0x80;
if (cp <= countof(c1))
cp = c1[cp];
}
}
if (cp > 0xffff)
cp = '?'; //too lazy for utf-16 crap when its mostly smilies anyway.
wc[l++] = cp;
}
}
//and flush it.
if (l)
{
ApplyColour(m);
if (WinNT)
WriteConsoleW(hconsoleout, wc, l, &dummy, NULL);
else
{
//win95 doesn't support wide chars *sigh*. blank consoles suck.
char ac[256];
l = WideCharToMultiByte(CP_ACP, 0, wc, l, ac, sizeof(ac), NULL, NULL);
WriteConsole(hconsoleout, ac, l, &dummy, NULL);
}
}

View file

@ -5393,7 +5393,7 @@ static void SVNQ_Spawn_f (void)
ent->v->colormap = NUM_FOR_EDICT(svprogfuncs, ent);
ent->v->team = 0; // FIXME
ent->v->netname = PR_SetString(svprogfuncs, host_client->name);
svprogfuncs->SetStringField(svprogfuncs, ent, &ent->v->netname, host_client->name, true);
host_client->entgravity = ent->xv->gravity = 1.0;
host_client->entgravity*=sv_gravity.value;
@ -7585,9 +7585,9 @@ void SV_ExecuteClientMessage (client_t *cl)
if (split)
split->lossage = cl->lossage;
}
MSG_ReadDeltaUsercmd (&nullcmd, &oldest);
MSG_ReadDeltaUsercmd (&oldest, &oldcmd);
MSG_ReadDeltaUsercmd (&oldcmd, &newcmd);
MSG_ReadDeltaUsercmd (&nullcmd, &oldest, PROTOCOL_VERSION_QW);
MSG_ReadDeltaUsercmd (&oldest, &oldcmd, PROTOCOL_VERSION_QW);
MSG_ReadDeltaUsercmd (&oldcmd, &newcmd, PROTOCOL_VERSION_QW);
if (!split)
break; // either someone is trying to cheat, or they sent input commands for splitscreen clients they no longer own.

View file

@ -8,7 +8,6 @@
!!permu SPECULAR
!!permu REFLECTCUBEMASK
!!cvarf r_glsl_offsetmapping_scale
!!cvarf gl_specular
!!cvardf r_tessellation_level=5
!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3
@ -230,9 +229,6 @@ void main()
#define s_colourmap s_t0
uniform sampler2D s_colourmap;
#ifdef SPECULAR
uniform float cvar_gl_specular;
#endif
#ifdef OFFSETMAPPING
#include "sys/offsetmapping.h"
#endif
@ -298,7 +294,7 @@ void main ()
vec3 delux = (texture2D(s_deluxmap, lm0).rgb-0.5);
#ifdef BUMPMODELSPACE
delux = normalize(delux*invsurface);
#else
#else
lightmaps *= 2.0 / max(0.25, delux.z); //counter the darkening from deluxmaps
#endif
lightmaps *= dot(norm, delux);
@ -312,7 +308,7 @@ void main ()
#ifdef SPECULAR
vec4 specs = texture2D(s_specular, tc);
vec3 halfdir = normalize(normalize(eyevector) + delux); //this norm should be the deluxemap info instead
float spec = pow(max(dot(halfdir, norm), 0.0), 2.0*FTE_SPECULAR_EXPONENT * specs.a);
float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * specs.a);
spec *= FTE_SPECULAR_MULTIPLIER;
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
//As not all maps will have deluxemapping, and the double-cos from the light util makes everything far too dark anyway,
@ -322,7 +318,7 @@ void main ()
#endif
#ifdef REFLECTCUBEMASK
vec3 rtc = reflect(-eyevector, norm);
vec3 rtc = reflect(normalize(-eyevector), norm);
rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];
rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;
gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;
@ -364,3 +360,4 @@ void main ()
#endif
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
#include "xmpp.h"
#ifdef JINGLE
static struct c2c_s *JCL_JingleAddContentToSession(jclient_t *jcl, struct c2c_s *c2c, char *with, bresource_t *bres, qboolean creator, char *sid, char *cname, int method, int mediatype)
static struct c2c_s *JCL_JingleAddContentToSession(jclient_t *jcl, struct c2c_s *c2c, const char *with, bresource_t *bres, qboolean creator, const char *sid, const char *cname, int method, int mediatype)
{
struct icestate_s *ice = NULL;
char generatedname[64];
@ -186,7 +186,7 @@ enum
JE_UNKNOWNSESSION,
JE_UNSUPPORTEDINFO
};
static void JCL_JingleError(jclient_t *jcl, xmltree_t *tree, char *from, char *id, int type)
static void JCL_JingleError(jclient_t *jcl, xmltree_t *tree, const char *from, const char *id, int type)
{
switch(type)
{
@ -522,7 +522,7 @@ void JCL_JingleTimeouts(jclient_t *jcl, qboolean killall)
}
}
void JCL_Join(jclient_t *jcl, char *target, char *sid, qboolean allow, int protocol)
void JCL_Join(jclient_t *jcl, const char *target, const char *sid, qboolean allow, int protocol)
{
struct c2c_s *c2c = NULL, **link;
char autotarget[256];
@ -618,7 +618,7 @@ void JCL_Join(jclient_t *jcl, char *target, char *sid, qboolean allow, int proto
}
}
static void JCL_JingleParsePeerPorts(jclient_t *jcl, struct c2c_s *c2c, xmltree_t *inj, char *from, char *sid)
static void JCL_JingleParsePeerPorts(jclient_t *jcl, struct c2c_s *c2c, xmltree_t *inj, const char *from, const char *sid)
{
xmltree_t *incontent;
xmltree_t *intransport;
@ -626,7 +626,7 @@ static void JCL_JingleParsePeerPorts(jclient_t *jcl, struct c2c_s *c2c, xmltree_
struct icecandinfo_s rem;
struct icestate_s *ice;
int i, contid;
char *cname;
const char *cname;
if (!c2c->sid)
return;
@ -665,7 +665,7 @@ static void JCL_JingleParsePeerPorts(jclient_t *jcl, struct c2c_s *c2c, xmltree_
for (i = 0; (incandidate = XML_ChildOfTree(intransport, "candidate", i)); i++)
{
char *s;
const char *s;
memset(&rem, 0, sizeof(rem));
Q_strlcpy(rem.addr, XML_GetParameter(incandidate, "ip", ""), sizeof(rem.addr));
Q_strlcpy(rem.candidateid, XML_GetParameter(incandidate, "id", ""), sizeof(rem.candidateid));
@ -869,12 +869,12 @@ static qboolean JCL_JingleHandleInitiate_GoogleSession(jclient_t *jcl, xmltree_t
return true;
}
#endif
static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, char *from)
static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, const char *from)
{
char *sid = XML_GetParameter(inj, "sid", "");
const char *sid = XML_GetParameter(inj, "sid", "");
qboolean okay;
char *initiator;
const char *initiator;
struct c2c_s *c2c = NULL;
int mt = ICEP_INVALID;
@ -894,12 +894,12 @@ static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, ch
for (i = 0; ; i++)
{
xmltree_t *incontent = XML_ChildOfTree(inj, "content", i);
char *cname = XML_GetParameter(incontent, "name", "");
const char *cname = XML_GetParameter(incontent, "name", "");
xmltree_t *intransport = XML_ChildOfTree(incontent, "transport", 0);
xmltree_t *indescription = XML_ChildOfTree(incontent, "description", 0);
char *transportxmlns = intransport?intransport->xmlns:"";
char *descriptionxmlns = indescription?indescription->xmlns:"";
char *descriptionmedia = XML_GetParameter(indescription, "media", "");
const char *transportxmlns = intransport?intransport->xmlns:"";
const char *descriptionxmlns = indescription?indescription->xmlns:"";
const char *descriptionmedia = XML_GetParameter(indescription, "media", "");
if (!incontent)
break;
@ -907,7 +907,7 @@ static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, ch
if (incontent && !strcmp(descriptionmedia, MEDIATYPE_QUAKE) && !strcmp(descriptionxmlns, QUAKEMEDIAXMLNS))
{
char *host = XML_GetParameter(indescription, "host", "you");
const char *host = XML_GetParameter(indescription, "host", "you");
if (!strcmp(host, "you"))
mt = ICEP_QWSERVER;
else if (!strcmp(host, "me"))
@ -938,9 +938,9 @@ static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, ch
//chuck it at the engine and see what sticks. at least one must...
while((payload = XML_ChildOfTree(indescription, "payload-type", i++)))
{
char *name = XML_GetParameter(payload, "name", "");
char *clock = XML_GetParameter(payload, "clockrate", "");
char *id = XML_GetParameter(payload, "id", "");
const char *name = XML_GetParameter(payload, "name", "");
const char *clock = XML_GetParameter(payload, "clockrate", "");
const char *id = XML_GetParameter(payload, "id", "");
char parm[64];
char val[64];
//note: the engine will ignore codecs it does not support, returning false.
@ -1028,7 +1028,7 @@ static qboolean JCL_JingleHandleSessionTerminate(jclient_t *jcl, xmltree_t *tree
free(c2c);
return true;
}
static qboolean JCL_JingleHandleSessionAccept(jclient_t *jcl, xmltree_t *tree, char *from, struct c2c_s *c2c, buddy_t *b)
static qboolean JCL_JingleHandleSessionAccept(jclient_t *jcl, xmltree_t *tree, const char *from, struct c2c_s *c2c, buddy_t *b)
{
//peer accepted our session
//make sure it actually was ours, and not theirs. sneaky sneaky.
@ -1053,7 +1053,7 @@ static qboolean JCL_JingleHandleSessionAccept(jclient_t *jcl, xmltree_t *tree, c
}
else
{
char *responder = XML_GetParameter(tree, "responder", from);
const char *responder = XML_GetParameter(tree, "responder", from);
int c;
if (strcmp(responder, from))
{
@ -1134,10 +1134,10 @@ qboolean JCL_HandleGoogleSession(jclient_t *jcl, xmltree_t *tree, char *from, ch
return true;
}
#endif
qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, char *from, char *id)
qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, const char *from, const char *id)
{
char *action = XML_GetParameter(tree, "action", "");
char *sid = XML_GetParameter(tree, "sid", "");
const char *action = XML_GetParameter(tree, "action", "");
const char *sid = XML_GetParameter(tree, "sid", "");
struct c2c_s *c2c = NULL, **link;
buddy_t *b;

View file

@ -210,7 +210,7 @@ void XMPP_FT_AcceptFile(jclient_t *jcl, int fileid, qboolean accept)
static qboolean XMPP_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
{
char *from = XML_GetParameter(x, "from", jcl->domain);
const char *from = XML_GetParameter(x, "from", jcl->domain);
struct ft_s *ft = iq->usrptr, **link, *v;
for (link = &jcl->ft; (v=*link); link = &(*link)->next)
{
@ -267,7 +267,7 @@ static qboolean XMPP_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq
static qboolean XMPP_FT_IBBBegun(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
{
struct ft_s *ft = iq->usrptr, **link, *v;
char *from = XML_GetParameter(x, "from", jcl->domain);
const char *from = XML_GetParameter(x, "from", jcl->domain);
for (link = &jcl->ft; (v=*link); link = &(*link)->next)
{
if (v == ft && !strcmp(ft->with, from))
@ -296,7 +296,7 @@ static qboolean XMPP_FT_IBBBegun(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
qboolean XMPP_FT_OfferAcked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
{
struct ft_s *ft = iq->usrptr, **link, *v;
char *from = XML_GetParameter(x, "from", jcl->domain);
const char *from = XML_GetParameter(x, "from", jcl->domain);
for (link = &jcl->ft; (v=*link); link = &(*link)->next)
{
if (v == ft && !strcmp(ft->with, from))
@ -328,7 +328,7 @@ qboolean XMPP_FT_OfferAcked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
return false;
}
void XMPP_FT_SendFile(jclient_t *jcl, char *console, char *to, char *fname)
void XMPP_FT_SendFile(jclient_t *jcl, const char *console, const char *to, const char *fname)
{
xmltree_t *xsi, *xfile, *c;
struct ft_s *ft;
@ -371,7 +371,7 @@ void XMPP_FT_SendFile(jclient_t *jcl, char *console, char *to, char *fname)
JCL_SendIQNode(jcl, XMPP_FT_OfferAcked, "set", to, xsi, true)->usrptr = ft;
}
qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t *tree)
qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, const char *iqfrom, const char *iqid, xmltree_t *tree)
{
xmltree_t *ot;
@ -384,17 +384,17 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t
{
xmltree_t *c;
struct ft_s *ft;
char *sid = XML_GetParameter(ot, "sid", "");
const char *sid = XML_GetParameter(ot, "sid", "");
for (ft = jcl->ft; ft; ft = ft->next)
{
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, iqfrom))
{
if (ft->allowed && !ft->begun && ft->transmitting == false)
{
char *jid;
char *host;
const char *jid;
const char *host;
int port;
char *mode = XML_GetParameter(ot, "mode", "tcp");
const char *mode = XML_GetParameter(ot, "mode", "tcp");
int i;
if (strcmp(mode, "tcp"))
break;
@ -432,9 +432,9 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t
if (ot)
{
struct ft_s *ft;
char *sid = XML_GetParameter(ot, "sid", "");
const char *sid = XML_GetParameter(ot, "sid", "");
int blocksize = atoi(XML_GetParameter(ot, "block-size", "4096")); //technically this is required.
char *stanza = XML_GetParameter(ot, "stanza", "iq");
const char *stanza = XML_GetParameter(ot, "stanza", "iq");
for (ft = jcl->ft; ft; ft = ft->next)
{
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, iqfrom))
@ -480,7 +480,7 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t
if (ot)
{
struct ft_s **link, *ft;
char *sid = XML_GetParameter(ot, "sid", "");
const char *sid = XML_GetParameter(ot, "sid", "");
for (link = &jcl->ft; *link; link = &(*link)->next)
{
ft = *link;
@ -522,7 +522,7 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t
if (ot)
{
char block[65536];
char *sid = XML_GetParameter(ot, "sid", "");
const char *sid = XML_GetParameter(ot, "sid", "");
// unsigned short seq = atoi(XML_GetParameter(ot, "seq", "0"));
int blocksize;
struct ft_s *ft;
@ -549,16 +549,16 @@ qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/si", "si", 0);
if (ot)
{
char *profile = XML_GetParameter(ot, "profile", "");
const char *profile = XML_GetParameter(ot, "profile", "");
if (!strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer"))
{
// char *mimetype = XML_GetParameter(ot, "mime-type", "text/plain");
char *sid = XML_GetParameter(ot, "id", "");
const char *sid = XML_GetParameter(ot, "id", "");
xmltree_t *file = XML_ChildOfTreeNS(ot, "http://jabber.org/protocol/si/profile/file-transfer", "file", 0);
char *fname = XML_GetParameter(file, "name", "file.txt");
const char *fname = XML_GetParameter(file, "name", "file.txt");
// char *date = XML_GetParameter(file, "date", "");
char *md5hash = XML_GetParameter(file, "hash", "");
const char *md5hash = XML_GetParameter(file, "hash", "");
int fsize = strtoul(XML_GetParameter(file, "size", "0"), NULL, 0);
// char *desc = XML_GetChildBody(file, "desc", "");
char authlink[512];

View file

@ -7,7 +7,7 @@ void (*Con_TrySubPrint)(const char *conname, const char *message);
void XML_Destroy(xmltree_t *t);
char *XML_GetParameter(xmltree_t *t, char *paramname, char *def)
const char *XML_GetParameter(xmltree_t *t, const char *paramname, const char *def)
{
xmlparams_t *p;
if (t)
@ -18,11 +18,11 @@ char *XML_GetParameter(xmltree_t *t, char *paramname, char *def)
}
return def;
}
void XML_AddParameter(xmltree_t *t, char *paramname, char *value)
void XML_AddParameter(xmltree_t *t, const char *paramname, const char *value)
{
xmlparams_t *p = malloc(sizeof(xmlparams_t));
Q_strlcpy(p->name, paramname, sizeof(p->name));
Q_strlcpy(p->val, value, sizeof(p->val));
Q_strlcpy(p->val, value?value:"", sizeof(p->val));
if (t->params) //reverse insert
{
@ -38,17 +38,24 @@ void XML_AddParameter(xmltree_t *t, char *paramname, char *value)
t->params = p;
}
}
void XML_AddParameteri(xmltree_t *t, char *paramname, int value)
void XML_AddParameteri(xmltree_t *t, const char *paramname, int value)
{
char svalue[64];
Q_snprintf(svalue, sizeof(svalue), "%i", value);
XML_AddParameter(t, paramname, svalue);
}
xmltree_t *XML_CreateNode(xmltree_t *parent, char *name, char *xmlns, char *body)
xmltree_t *XML_CreateNode(xmltree_t *parent, const char *name, const char *xmlns, const char *body)
{
int bodylen = strlen(body);
int bodylen;
struct subtree_s *node = malloc(sizeof(*node));
if (!body)
body = "";
if (!xmlns)
xmlns = "";
bodylen = strlen(body);
//clear out links
node->params = NULL;
node->child = NULL;
@ -101,7 +108,7 @@ const struct
};
//converts < to &lt; etc.
//returns the end of d.
char *XML_Markup(char *s, char *d, int dlen)
char *XML_Markup(const char *s, char *d, int dlen)
{
int i;
dlen--;
@ -248,7 +255,7 @@ char *XML_GenerateString(xmltree_t *root, qboolean readable)
buf_cat(&buf, "", 1);
return buf.buf;
}
xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronly, char *defaultnamespace)
xmltree_t *XML_Parse(const char *buffer, int *startpos, int maxpos, qboolean headeronly, const char *defaultnamespace)
{
xmlparams_t *p;
xmltree_t *child;
@ -258,8 +265,8 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
int bodymax = 0;
int pos, i;
char *tagend;
char *tagstart;
char *ns;
const char *tagstart;
const char *ns;
char token[1024];
pos = *startpos;
while (buffer[pos] >= '\0' && buffer[pos] <= ' ')
@ -337,11 +344,9 @@ skippedcomment:
ns = strchr(token, ':');
if (ns)
{
*ns = 0;
ns++;
memcpy(ret->xmlns, "xmlns:", 6);
Q_strlcpy(ret->xmlns+6, token, sizeof(ret->xmlns)-6);
Q_strlncpy(ret->xmlns+6, token, sizeof(ret->xmlns)-6, ns-token);
ns++;
Q_strlcpy(ret->name, ns, sizeof(ret->name));
}
else
@ -589,7 +594,7 @@ void XML_Destroy(xmltree_t *t)
free(t);
}
xmltree_t *XML_ChildOfTree(xmltree_t *t, char *name, int childnum)
xmltree_t *XML_ChildOfTree(xmltree_t *t, const char *name, int childnum)
{
if (t)
{
@ -604,7 +609,7 @@ xmltree_t *XML_ChildOfTree(xmltree_t *t, char *name, int childnum)
}
return NULL;
}
xmltree_t *XML_ChildOfTreeNS(xmltree_t *t, char *xmlns, char *name, int childnum)
xmltree_t *XML_ChildOfTreeNS(xmltree_t *t, const char *xmlns, const char *name, int childnum)
{
if (t)
{
@ -619,7 +624,7 @@ xmltree_t *XML_ChildOfTreeNS(xmltree_t *t, char *xmlns, char *name, int childnum
}
return NULL;
}
char *XML_GetChildBody(xmltree_t *t, char *paramname, char *def)
const char *XML_GetChildBody(xmltree_t *t, const char *paramname, const char *def)
{
xmltree_t *c = XML_ChildOfTree(t, paramname, 0);
if (c)
@ -627,7 +632,7 @@ char *XML_GetChildBody(xmltree_t *t, char *paramname, char *def)
return def;
}
void XML_ConPrintTree(xmltree_t *t, char *subconsole, int indent)
void XML_ConPrintTree(xmltree_t *t, const char *subconsole, int indent)
{
int start, c, chunk;
struct buf_ctx buf = {NULL, 0, 0};
@ -653,7 +658,7 @@ void XML_ConPrintTree(xmltree_t *t, char *subconsole, int indent)
}
static void XML_SkipWhite(char *msg, int *pos, int max)
static void XML_SkipWhite(const char *msg, int *pos, int max)
{
while (*pos < max && (
msg[*pos] == ' ' ||
@ -663,7 +668,7 @@ static void XML_SkipWhite(char *msg, int *pos, int max)
))
*pos+=1;
}
static qboolean XML_ParseString(char *msg, int *pos, int max, char *out, int outlen)
static qboolean XML_ParseString(const char *msg, int *pos, int max, char *out, int outlen)
{
*out = 0;
if (*pos < max && msg[*pos] == '\"')
@ -712,7 +717,7 @@ static qboolean XML_ParseString(char *msg, int *pos, int max, char *out, int out
}
return false;
}
xmltree_t *XML_FromJSON(xmltree_t *t, char *name, char *json, int *jsonpos, int jsonlen)
xmltree_t *XML_FromJSON(xmltree_t *t, const char *name, const char *json, int *jsonpos, int jsonlen)
{
char child[4096];
XML_SkipWhite(json, jsonpos, jsonlen);

View file

@ -20,18 +20,18 @@ typedef struct subtree_s
char *XML_GetParameter(xmltree_t *t, char *paramname, char *def);
void XML_AddParameter(xmltree_t *t, char *paramname, char *value);
void XML_AddParameteri(xmltree_t *t, char *paramname, int value);
xmltree_t *XML_CreateNode(xmltree_t *parent, char *name, char *xmlns, char *body);
char *XML_Markup(char *s, char *d, int dlen);
const char *XML_GetParameter(xmltree_t *t, const char *paramname, const char *def);
void XML_AddParameter(xmltree_t *t, const char *paramname, const char *value);
void XML_AddParameteri(xmltree_t *t, const char *paramname, int value);
xmltree_t *XML_CreateNode(xmltree_t *parent, const char *name, const char *xmlns, const char *body);
char *XML_Markup(const char *s, char *d, int dlen);
void XML_Unmark(char *s);
char *XML_GenerateString(xmltree_t *root, qboolean readable);
xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronly, char *defaultnamespace);
xmltree_t *XML_Parse(const char *buffer, int *startpos, int maxpos, qboolean headeronly, const char *defaultnamespace);
void XML_Destroy(xmltree_t *t);
xmltree_t *XML_ChildOfTree(xmltree_t *t, char *name, int childnum);
xmltree_t *XML_ChildOfTreeNS(xmltree_t *t, char *xmlns, char *name, int childnum);
char *XML_GetChildBody(xmltree_t *t, char *paramname, char *def);
void XML_ConPrintTree(xmltree_t *t, char *subconsole, int indent);
xmltree_t *XML_ChildOfTree(xmltree_t *t, const char *name, int childnum);
xmltree_t *XML_ChildOfTreeNS(xmltree_t *t, const char *xmlns, const char *name, int childnum);
const char *XML_GetChildBody(xmltree_t *t, const char *paramname, const char *def);
void XML_ConPrintTree(xmltree_t *t, const char *subconsole, int indent);
xmltree_t *XML_FromJSON(xmltree_t *t, char *name, char *json, int *jsonpos, int jsonlen);
xmltree_t *XML_FromJSON(xmltree_t *t, const char *name, const char *json, int *jsonpos, int jsonlen);

View file

@ -76,12 +76,22 @@ typedef struct bresource_s
typedef struct buddy_s
{
bresource_t *resources;
bresource_t *defaultresource; //this is the one that last replied
bresource_t *defaultresource; //this is the one that last replied (must be null for chatrooms, so we only talk to the room in general)
bresource_t *ourselves; //this is set back to ourselves when in a chatroom
int defaulttimestamp;
qboolean askfriend;
qboolean friended;
qboolean chatroom; //chatrooms are bizzare things that need special handling.
qboolean vcardphotochanged;
enum {
BT_UNKNOWN, //this buddy isn't known...
BT_ROSTER, //this is a friend! or at least on our list of potential friends anyway.
BT_CHATROOM //we're treating this 'guy' as a MUC, each of their resources is a different person. which is weird.
} btype;
qboolean room_autojoin;
char *room_nick;
char *room_password;
char *room_topic;
char name[256];
char vcardphotohash[41];
@ -110,6 +120,9 @@ typedef struct jclient_s
qhandle_t socket;
qhandle_t rcon_pipe; //contains console prints
char rcon_peer[256]; //the name of the guy currently receiving console prints
//we buffer output for times when the outgoing socket is full.
//mostly this only happens at the start of the connection when the socket isn't actually open yet.
char *outbuf;
@ -226,6 +239,7 @@ typedef struct jclient_s
qboolean accepted; //connection is going
qboolean creator; //true if we're the creator.
unsigned int peercaps;
qboolean displayed; //temp flag for displaying jingle sessions with people that are not on our buddy list for whatever reasons
struct
{
@ -313,32 +327,33 @@ extern icefuncs_t *piceapi;
#endif
qboolean NET_DNSLookup_SRV(char *host, char *out, int outlen);
qboolean NET_DNSLookup_SRV(const char *host, char *out, int outlen);
//xmpp functionality
struct iq_s *JCL_SendIQNode(jclient_t *jcl, qboolean (*callback) (jclient_t *jcl, xmltree_t *tree, struct iq_s *iq), char *iqtype, char *target, xmltree_t *node, qboolean destroynode);
void JCL_AddClientMessagef(jclient_t *jcl, char *fmt, ...);
void JCL_AddClientMessageString(jclient_t *jcl, char *msg);
qboolean JCL_FindBuddy(jclient_t *jcl, char *jid, buddy_t **buddy, bresource_t **bres, qboolean create);
struct iq_s *JCL_SendIQNode(jclient_t *jcl, qboolean (*callback) (jclient_t *jcl, xmltree_t *tree, struct iq_s *iq), const char *iqtype, const char *target, xmltree_t *node, qboolean destroynode);
void JCL_AddClientMessagef(jclient_t *jcl, const char *fmt, ...);
void JCL_AddClientMessageString(jclient_t *jcl, const char *msg);
qboolean JCL_FindBuddy(jclient_t *jcl, const char *jid, buddy_t **buddy, bresource_t **bres, qboolean create);
void JCL_ForgetBuddy(jclient_t *jcl, buddy_t *buddy, bresource_t *bres);
//quake functionality
void JCL_GenLink(jclient_t *jcl, char *out, int outlen, char *action, char *context, char *contextres, char *sid, char *txtfmt, ...);
void Con_SubPrintf(const char *subname, char *format, ...);
void JCL_GenLink(jclient_t *jcl, char *out, int outlen, const char *action, const char *context, const char *contextres, const char *sid, const char *txtfmt, ...);
void Con_SubPrintf(const char *subname, const char *format, ...);
void XMPP_ConversationPrintf(const char *context, const char *title, char *format, ...);
//jingle functions
void JCL_Join(jclient_t *jcl, char *target, char *sid, qboolean allow, int protocol);
void JCL_Join(jclient_t *jcl, const char *target, const char *sid, qboolean allow, int protocol);
void JCL_JingleTimeouts(jclient_t *jcl, qboolean killall);
//jingle iq message handlers
qboolean JCL_HandleGoogleSession(jclient_t *jcl, xmltree_t *tree, char *from, char *id);
qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, char *from, char *id);
qboolean JCL_HandleGoogleSession(jclient_t *jcl, xmltree_t *tree, const char *from, const char *id);
qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, const char *from, const char *id);
void XMPP_FT_AcceptFile(jclient_t *jcl, int fileid, qboolean accept);
qboolean XMPP_FT_OfferAcked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq);
qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, char *iqfrom, char *iqid, xmltree_t *tree);
void XMPP_FT_SendFile(jclient_t *jcl, char *console, char *to, char *fname);
qboolean XMPP_FT_ParseIQSet(jclient_t *jcl, const char *iqfrom, const char *iqid, xmltree_t *tree);
void XMPP_FT_SendFile(jclient_t *jcl, const char *console, const char *to, const char *fname);
void XMPP_FT_Frame(jclient_t *jcl);
void Base64_Add(char *s, int len);
void Base64_Add(const char *s, int len);
char *Base64_Finish(void);
int Base64_Decode(char *out, int outlen, char *src, int srclen);
int Base64_Decode(char *out, int outlen, const char *src, int srclen);

View file

@ -59,6 +59,9 @@ BUILTINR(void *, Plug_GetNativePointer, (const char *funcname));
BUILTIN(void, Con_Print, (const char *text)); //on to main console.
#undef ARGNAMES
#define ARGNAMES ,conname,flags
BUILTINR(qhandle_t, Con_POpen, (const char *conname, unsigned int flags));
#undef ARGNAMES
#define ARGNAMES ,conname,text
BUILTIN(void, Con_SubPrint, (const char *conname, const char *text)); //on to named sub console (creating it too).
#undef ARGNAMES
@ -528,6 +531,7 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(Con_SetConsoleFloat);
CHECKBUILTIN(Con_GetConsoleString);
CHECKBUILTIN(Con_SetConsoleString);
CHECKBUILTIN(Con_POpen);
}
#ifndef Q3_VM

View file

@ -140,6 +140,7 @@ extern "C" {
#endif
extern qintptr_t (QDECL *plugin_syscall)( qintptr_t arg, ... );
void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs);
void Q_strlcpy(char *d, const char *s, int n);
void Q_strlcat(char *d, const char *s, int n);
int Q_snprintf(char *buffer, size_t maxlen, const char *format, ...);
@ -198,6 +199,7 @@ EBUILTIN(void *, Plug_GetNativePointer, (const char *funcname));
#endif
EBUILTIN(void, Con_Print, (const char *text)); //on to main console.
EBUILTIN(qhandle_t, Con_POpen, (const char *conname, unsigned int flags));
EBUILTIN(void, Con_SubPrint, (const char *subname, const char *text)); //on to sub console.
EBUILTIN(void, Con_RenameSub, (const char *oldname, const char *newname)); //rename a console.
EBUILTIN(int, Con_IsActive, (const char *conname));

View file

@ -235,13 +235,13 @@ void QI_RefreshMapList(qboolean forcedisplay)
for (file = thedatabase->child; file; file = file->sibling)
{
char *id = XML_GetParameter(file, "id", "unnamed");
char *rating = XML_GetParameter(file, "rating", "");
const char *id = XML_GetParameter(file, "id", "unnamed");
const char *rating = XML_GetParameter(file, "rating", "");
int ratingnum = atoi(rating);
char *author = XML_GetChildBody(file, "author", "unknown");
char *desc = XML_GetChildBody(file, "description", "<NO DESCRIPTION>");
char *type;
char *date;
const char *author = XML_GetChildBody(file, "author", "unknown");
const char *desc = XML_GetChildBody(file, "description", "<NO DESCRIPTION>");
const char *type;
const char *date;
int year, month, day;
int startmapnum, i;
char ratingtext[65];
@ -397,7 +397,7 @@ static xmltree_t *QI_FindArchive(const char *name)
xmltree_t *file;
for (file = thedatabase->child; file; file = file->sibling)
{
char *id = XML_GetParameter(file, "id", "unnamed");
const char *id = XML_GetParameter(file, "id", "unnamed");
if (strcmp(file->name, "file"))
continue; //erk?
@ -408,7 +408,7 @@ static xmltree_t *QI_FindArchive(const char *name)
}
static void QI_AddPackages(xmltree_t *qifile)
{
char *id;
const char *id;
char extra[1024];
char clean[512];
unsigned int i;

View file

@ -567,6 +567,22 @@ int rand(void)
}
#endif
void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs)
{
int i;
sizeofd--;
if (sizeofd < 0)
return; //this could be an error
for (i=0; lenofs-- > 0; i++)
{
if (i == sizeofd)
break;
*d++ = *s++;
}
*d='\0';
}
void Q_strlcpy(char *d, const char *s, int n)
{
int i;