remove the old SCVAR macro

server: my attempt at mvd recording fixes. there's a couple of other issues, at least with nq mods.
client: properly support recording .dems mid-map for 15+666
client: server browser now queries nq servers for players+rules.
renderer: add support for single-image dual-layer skies that some other engines use.
qcc: add #merge, along with __wrap + __weak keywords. fix a symboldata issue revealed by this.
qcc: added a flag to write the sourcecode into the .dat (zip format compatible with any zip program that can deal with 'self extractors').
qccgui: can be told to open a .dat file instead of .src, showing/using any embedded sourcecode.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5017 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2016-09-08 19:04:35 +00:00
parent 57dfaea5fd
commit b749d8356a
62 changed files with 2359 additions and 1306 deletions

View File

@ -51,14 +51,14 @@ static void QDECL CL_AutoTrackChanged(cvar_t *v, char *oldval)
Cam_AutoTrack_Update(v->string);
}
// track high fragger
cvar_t cl_autotrack_team = CVARD("cl_autotrack_team", "", "Specifies a team name that should be auto-tracked (players on other teams will not be candidates for autotracking). Accepts * and ? wildcards for awkward chars.");
cvar_t cl_autotrack = CVARCD("cl_autotrack", "auto", CL_AutoTrackChanged, "Specifies the default tracking mode at the start of the map. Use the 'autotrack' command to reset/apply an auto-tracking mode without changing the default.\nValid values are: high, ^hkiller^h, mod, user. Other values are treated as weighting scripts for mvd playback, where available.");
cvar_t cl_hightrack = CVARD("cl_hightrack", "0", "Obsolete. If you want hightrack, use '[cl_]autotrack high' instead.");
cvar_t cl_autotrack_team = CVARD("cl_autotrack_team", "", "Specifies a team name that should be auto-tracked (players on other teams will not be candidates for autotracking). Accepts * and ? wildcards for awkward chars.");
cvar_t cl_autotrack = CVARCD("cl_autotrack", "auto", CL_AutoTrackChanged, "Specifies the default tracking mode at the start of the map. Use the 'autotrack' command to reset/apply an auto-tracking mode without changing the default.\nValid values are: high, ^hkiller^h, mod, user. Other values are treated as weighting scripts for mvd playback, where available.");
cvar_t cl_hightrack = CVARD("cl_hightrack", "0", "Obsolete. If you want hightrack, use '[cl_]autotrack high' instead.");
//cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" };
//cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" };
cvar_t cl_chasecam = SCVAR("cl_chasecam", "1");
cvar_t cl_selfcam = SCVAR("cl_selfcam", "1");
cvar_t cl_chasecam = CVAR("cl_chasecam", "1");
cvar_t cl_selfcam = CVAR("cl_selfcam", "1");
void Cam_AutoTrack_Update(const char *mode)
{

View File

@ -585,7 +585,7 @@ qboolean CL_GetDemoMessage (void)
olddemotime = demtime;
if (msglength > MAX_NQMSGLEN)
if (msglength > net_message.maxsize)
{
Con_Printf ("Demo message > MAX_MSGLEN");
CL_StopPlayback ();
@ -684,7 +684,7 @@ readnext:
cls.td_starttime = Sys_DoubleTime();
demtime = demotime; // warp
}
else if (!cl.paused && cls.state >= ca_onserver)
else if (!(cl.paused&~4) && cls.state >= ca_onserver)
{ // always grab until fully connected
if (demtime + 1.0 < demotime)
{
@ -993,7 +993,7 @@ void CL_WriteRecordQ2DemoMessage(sizebuf_t *msg)
====================
CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
Dumps the specified net message as part of initial mid-map demo writing.
====================
*/
void CL_WriteRecordDemoMessage (sizebuf_t *msg, int seq)
@ -1008,21 +1008,35 @@ void CL_WriteRecordDemoMessage (sizebuf_t *msg, int seq)
if (!cls.demorecording)
return;
fl = LittleFloat(Sys_DoubleTime()-recdemostart);
VFS_WRITE (cls.demooutfile, &fl, sizeof(fl));
if (cls.demorecording == DPB_NETQUAKE)
{
len = LittleLong (msg->cursize);
VFS_WRITE(cls.demooutfile, &len, sizeof(len));
for (i=0 ; i<3 ; i++)
{
float f = LittleFloat (cl.playerview[0].viewangles[i]);
VFS_WRITE(cls.demooutfile, &f, sizeof(f));
}
}
else
{
fl = LittleFloat(Sys_DoubleTime()-recdemostart);
VFS_WRITE (cls.demooutfile, &fl, sizeof(fl));
c = dem_read;
VFS_WRITE (cls.demooutfile, &c, sizeof(c));
c = dem_read;
VFS_WRITE (cls.demooutfile, &c, sizeof(c));
len = LittleLong (msg->cursize + 8);
VFS_WRITE (cls.demooutfile, &len, 4);
i = LittleLong(seq);
VFS_WRITE (cls.demooutfile, &i, 4);
VFS_WRITE (cls.demooutfile, &i, 4);
len = LittleLong (msg->cursize + 8);
VFS_WRITE (cls.demooutfile, &len, 4);
i = LittleLong(seq);
VFS_WRITE (cls.demooutfile, &i, 4);
VFS_WRITE (cls.demooutfile, &i, 4);
}
VFS_WRITE (cls.demooutfile, msg->data, msg->cursize);
SZ_Clear(msg);
if (record_flush.ival)
VFS_FLUSH (cls.demooutfile);
}
@ -1110,6 +1124,353 @@ void CL_RecordMap_f (void)
}
#endif
//qw-specific serverdata
static void CLQW_RecordServerData(sizebuf_t *buf)
{
extern char gamedirfile[];
unsigned int i;
// send the serverdata
MSG_WriteByte (buf, svc_serverdata);
#ifdef PROTOCOL_VERSION_FTE
if (cls.fteprotocolextensions) //maintain demo compatability
{
MSG_WriteLong (buf, PROTOCOL_VERSION_FTE);
MSG_WriteLong (buf, cls.fteprotocolextensions);
}
if (cls.fteprotocolextensions2) //maintain demo compatability
{
MSG_WriteLong (buf, PROTOCOL_VERSION_FTE2);
MSG_WriteLong (buf, cls.fteprotocolextensions2);
}
#endif
MSG_WriteLong (buf, PROTOCOL_VERSION_QW);
MSG_WriteLong (buf, cl.servercount);
MSG_WriteString (buf, gamedirfile);
if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{
MSG_WriteByte (buf, cl.allocated_client_slots);
MSG_WriteByte (buf, cl.splitclients | (cl.spectator?128:0));
for (i = 0; i < cl.splitclients; i++)
MSG_WriteByte (buf, cl.playerview[i].playernum);
}
else
{
for (i = 0; i < cl.splitclients; i++)
{
if (cl.spectator)
MSG_WriteByte (buf, cl.playerview[i].playernum | 128);
else
MSG_WriteByte (buf, cl.playerview[i].playernum);
}
if (cls.fteprotocolextensions & PEXT_SPLITSCREEN)
MSG_WriteByte (buf, 128);
}
// send full levelname
MSG_WriteString (buf, cl.levelname);
// send the movevars
MSG_WriteFloat(buf, movevars.gravity);
MSG_WriteFloat(buf, movevars.stopspeed);
MSG_WriteFloat(buf, movevars.maxspeed);
MSG_WriteFloat(buf, movevars.spectatormaxspeed);
MSG_WriteFloat(buf, movevars.accelerate);
MSG_WriteFloat(buf, movevars.airaccelerate);
MSG_WriteFloat(buf, movevars.wateraccelerate);
MSG_WriteFloat(buf, movevars.friction);
MSG_WriteFloat(buf, movevars.waterfriction);
MSG_WriteFloat(buf, movevars.entgravity);
// send server info string
MSG_WriteByte (buf, svc_stufftext);
MSG_WriteString (buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );
}
void CLNQ_WriteServerData(sizebuf_t *buf)
{
unsigned int protmain;
unsigned int protfl = 0;
unsigned int i;
const char *val;
val = Info_ValueForKey(cl.serverinfo, "*csprogs");
if (*val)
{
MSG_WriteByte(buf, svc_stufftext);
MSG_WriteString(buf, va("csqc_progcrc \"%s\"\n", val));
}
val = Info_ValueForKey(cl.serverinfo, "*csprogssize");
if (*val)
{
MSG_WriteByte(buf, svc_stufftext);
MSG_WriteString(buf, va("csqc_progsize \"%s\"\n", val));
}
val = Info_ValueForKey(cl.serverinfo, "*csprogsname");
if (*val)
{
MSG_WriteByte(buf, svc_stufftext);
MSG_WriteString(buf, va("csqc_progname \"%s\"\n", val));
}
MSG_WriteByte(buf, svc_serverdata);
if (cls.fteprotocolextensions)
{
MSG_WriteLong (buf, PROTOCOL_VERSION_FTE);
MSG_WriteLong (buf, cls.fteprotocolextensions);
}
if (cls.fteprotocolextensions2)
{
MSG_WriteLong (buf, PROTOCOL_VERSION_FTE2);
MSG_WriteLong (buf, cls.fteprotocolextensions2);
}
if (cls.netchan.message.prim.anglesize == 2)
protfl |= RMQFL_SHORTANGLE;
if (cls.netchan.message.prim.anglesize == 4)
protfl |= RMQFL_FLOATANGLE;
if (cls.netchan.message.prim.coordsize == 3)
protfl |= RMQFL_24BITCOORD;
if (cls.netchan.message.prim.coordsize == 4)
protfl |= RMQFL_FLOATCOORD;
switch(cls.protocol_nq)
{
default:
case CPNQ_ID: protmain = PROTOCOL_VERSION_NQ; break;
case CPNQ_BJP1: protmain = PROTOCOL_VERSION_BJP1; break;
case CPNQ_BJP2: protmain = PROTOCOL_VERSION_BJP2; break;
case CPNQ_BJP3: protmain = PROTOCOL_VERSION_BJP3; break;
case CPNQ_FITZ666: protmain = protfl?PROTOCOL_VERSION_RMQ:PROTOCOL_VERSION_FITZ; break; //this might break .scale, fte doesn't care, other engines might.
case CPNQ_DP5: protmain = PROTOCOL_VERSION_DP5; break;
case CPNQ_DP6: protmain = PROTOCOL_VERSION_DP6; break;
case CPNQ_DP7: protmain = PROTOCOL_VERSION_DP7; break;
}
MSG_WriteLong (buf, protmain);
if (protmain == PROTOCOL_VERSION_RMQ)
MSG_WriteLong (buf, protfl);
MSG_WriteByte (buf, cl.allocated_client_slots);
MSG_WriteByte (buf, cl.deathmatch?GAME_DEATHMATCH:GAME_COOP);
MSG_WriteString (buf, cl.levelname);
for (i = 1; *cl.model_name[i] && i < MAX_PRECACHE_MODELS; i++)
MSG_WriteString (buf, cl.model_name[i]);
MSG_WriteByte (buf, 0);
for (i = 1; *cl.sound_name[i] && i < MAX_PRECACHE_SOUNDS ; i++)
MSG_WriteString (buf, cl.sound_name[i]);
MSG_WriteByte (buf, 0);
}
void CL_Record_Baseline(sizebuf_t *buf, entity_state_t *state, unsigned int bits)
{
unsigned int j;
if (bits & FITZ_B_LARGEMODEL)
MSG_WriteShort (buf, state->modelindex);
else
MSG_WriteByte (buf, state->modelindex);
if (bits & FITZ_B_LARGEFRAME)
MSG_WriteShort (buf, state->frame);
else
MSG_WriteByte (buf, state->frame);
MSG_WriteByte (buf, state->colormap);
MSG_WriteByte (buf, state->skinnum);
for (j=0 ; j<3 ; j++)
{
MSG_WriteCoord (buf, state->origin[j]);
MSG_WriteAngle (buf, state->angles[j]);
}
if (bits & FITZ_B_ALPHA)
MSG_WriteByte(buf, state->trans);
if (bits & RMQFITZ_B_SCALE)
MSG_WriteByte(buf, state->scale);
}
//nq+qw generic stuff.
static int CL_Record_ParticlesStaticsBaselines(sizebuf_t *buf, int seq)
{
unsigned int i;
entity_state_t *es;
//particleeffectnum stuff
for (i = 1; i < MAX_SSPARTICLESPRE; i++)
{
if (!cl.particle_ssname[i])
break;
MSG_WriteByte(buf, svcfte_precache);
MSG_WriteShort(buf, PC_PARTICLE | i);
MSG_WriteString(buf, cl.particle_ssname[i]);
if (buf->cursize > buf->maxsize/2)
CL_WriteRecordDemoMessage (buf, seq++);
}
//custom tents (needed for hexen2, if nothing else)
for (i = 0; ; i++)
{
if (!CL_WriteCustomTEnt(buf, i))
break;
if (buf->cursize > buf->maxsize/2)
CL_WriteRecordDemoMessage (buf, seq++);
}
// spawnstatic
for (i = 0; i < cl.num_statics; i++)
{
es = &cl_static_entities[i].state;
#ifndef CLIENTONLY //FIXME
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
MSG_WriteByte(buf, svcfte_spawnstatic2);
SVFTE_EmitBaseline(es, false, buf, cls.fteprotocolextensions2);
}
//else if (cls.fteprotocolextensions & PEXT_SPAWNSTATIC2) //qw deltas
else
#endif
{
unsigned int bits = 0;
#ifdef NQPROT
if (es->modelindex > 255)
bits |= FITZ_B_LARGEMODEL;
if (es->frame > 255)
bits |= FITZ_B_LARGEFRAME;
if (es->trans != 255)
bits |= FITZ_B_ALPHA;
if (es->scale != 16)
bits |= RMQFITZ_B_SCALE;
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_BJP)
{
MSG_WriteByte (buf, svc_spawnstatic);
bits = FITZ_B_LARGEMODEL; //bjp always uses shorts for models.
}
else if (cls.protocol == CP_NETQUAKE && cls.protocol_nq == CPNQ_FITZ666 && bits)
{
MSG_WriteByte (buf, svcfitz_spawnstatic2);
MSG_WriteByte (buf, bits);
}
// else if (baselinetype2 >= CPNQ_DP5 && baselinetype2 <= CPNQ_DP7 && (bits & (FITZ_B_LARGEMODEL|FITZ_B_LARGEFRAME)))
// {
// MSG_WriteByte (buf, svcdp_spawnstatic2);
// bits = FITZ_B_LARGEMODEL|FITZ_B_LARGEFRAME; //dp's baseline2 always has these (regular baseline is unmodified)
// }
else
#endif
{
//classic protocol
MSG_WriteByte (buf, svc_spawnstatic);
bits = 0;
}
CL_Record_Baseline(buf, es, bits);
}
if (buf->cursize > buf->maxsize/2)
CL_WriteRecordDemoMessage (buf, seq++);
}
// FIXME: static sounds
// static sounds are skipped in demos, life is hard
// baselines
for (i = 0; i < cl_baselines_count; i++)
{
es = cl_baselines + i;
if (memcmp(es, &nullentitystate, sizeof(nullentitystate)))
{
#ifndef CLIENTONLY //FIXME
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
MSG_WriteByte(buf, svcfte_spawnbaseline2);
SVFTE_EmitBaseline(es, true, buf, cls.fteprotocolextensions2);
}
//else if (cls.fteprotocolextensions & PEXT_SPAWNSTATIC2) //qw deltas
else
#endif
{
unsigned int bits = 0;
#ifdef NQPROT
if (es->modelindex > 255)
bits |= FITZ_B_LARGEMODEL;
if (es->frame > 255)
bits |= FITZ_B_LARGEFRAME;
if (es->trans != 255)
bits |= FITZ_B_ALPHA;
if (es->scale != 16)
bits |= RMQFITZ_B_SCALE;
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_BJP)
{
MSG_WriteByte (buf, svc_spawnbaseline);
bits = FITZ_B_LARGEMODEL; //bjp always uses shorts for models.
}
else if (cls.protocol == CP_NETQUAKE && cls.protocol_nq == CPNQ_FITZ666 && bits)
{
MSG_WriteByte (buf, svcfitz_spawnbaseline2);
MSG_WriteByte (buf, bits);
}
else if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP && (bits & (FITZ_B_LARGEMODEL|FITZ_B_LARGEFRAME)))
{
MSG_WriteByte (buf, svcdp_spawnbaseline2);
bits = FITZ_B_LARGEMODEL|FITZ_B_LARGEFRAME; //dp's baseline2 always has these (regular baseline is unmodified)
}
else
#endif
{
MSG_WriteByte (buf,svc_spawnbaseline);
bits = 0;
}
MSG_WriteEntity (buf, i);
CL_Record_Baseline(buf, es, bits);
}
if (buf->cursize > buf->maxsize/2)
CL_WriteRecordDemoMessage (buf, seq++);
}
}
return seq;
}
static int CL_Record_Lightstyles(sizebuf_t *buf, int seq)
{
unsigned int i;
// send all current light styles
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
if (i >= MAX_STANDARDLIGHTSTYLES)
if (!*cl_lightstyle[i].map)
continue;
#ifdef PEXT_LIGHTSTYLECOL
if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (cl_lightstyle[i].colours[0]!=1||cl_lightstyle[i].colours[1]!=1||cl_lightstyle[i].colours[2]!=1) && *cl_lightstyle[i].map)
{
MSG_WriteByte (buf, svcfte_lightstylecol);
MSG_WriteByte (buf, (unsigned char)i);
MSG_WriteByte (buf, 0x87);
MSG_WriteShort (buf, cl_lightstyle[i].colours[0]*1024);
MSG_WriteShort (buf, cl_lightstyle[i].colours[1]*1024);
MSG_WriteShort (buf, cl_lightstyle[i].colours[2]*1024);
MSG_WriteString (buf, cl_lightstyle[i].map);
}
else
#endif
{
MSG_WriteByte (buf, svc_lightstyle);
MSG_WriteByte (buf, (unsigned char)i);
MSG_WriteString (buf, cl_lightstyle[i].map);
}
if (buf->cursize > buf->maxsize/2)
CL_WriteRecordDemoMessage (buf, seq++);
}
return seq;
}
const char *Get_Q2ConfigString(int i);
/*
@ -1124,11 +1485,9 @@ void CL_Record_f (void)
int c;
char name[MAX_OSPATH];
sizebuf_t buf;
char buf_data[MAX_QWMSGLEN];
int n, i, j, seat;
char buf_data[MAX_OVERALLMSGLEN];
int n, i, seat;
char *s, *p, *fname;
entity_t *ent;
entity_state_t *es;
player_info_t *player;
extern char gamedirfile[];
int seq = 1;
@ -1153,8 +1512,8 @@ void CL_Record_f (void)
if (cls.protocol == CP_QUAKE2)
defaultext = ".dm2";
// else if (cls.protocol == CP_NETQUAKE)
// defaultext = ".dem";
else if (cls.protocol == CP_NETQUAKE && !CPNQ_IS_DP)
defaultext = ".dem";
else if (cls.protocol == CP_QUAKEWORLD)
defaultext = ".qwd";
else
@ -1169,6 +1528,9 @@ void CL_Record_f (void)
if (c == 2) //user supplied a name
{
fname = Cmd_Argv(1);
s = strrchr(fname, '.');
if (!Q_strcasecmp(s, defaultext))
*s = 0; //hack away that extension that they added.
}
else
{ //automagically generate a name
@ -1230,8 +1592,7 @@ void CL_Record_f (void)
|| c=='<' || c=='>' || c=='"' || c=='.')
*p = '_';
}
strncpy(name, fname, sizeof(name)-1-8);
name[sizeof(name)-1-8] = '\0';
Q_strncpyz(name, fname, sizeof(name)-8);
//make a unique name (unless the user specified it).
strcat (name, defaultext); //we have the space
@ -1242,9 +1603,11 @@ void CL_Record_f (void)
f = FS_OpenVFS (name, "rb", FS_GAME);
if (f)
{
COM_StripExtension(name, name, sizeof(name));
//remove the extension again
Q_strncpyz(name, fname, sizeof(name)-8);
p = name + strlen(name);
strcat(p, "_XX.qwd");
strcat(p, "_XX");
strcat(p, defaultext);
p++;
i = 0;
do
@ -1282,67 +1645,12 @@ void CL_Record_f (void)
switch(cls.protocol)
{
case CP_QUAKEWORLD:
if (!cls.fteprotocolextensions && !cls.fteprotocolextensions2)
buf.maxsize = MAX_QWMSGLEN; //poo compatibility... :P
cls.demorecording = DPB_QUAKEWORLD;
// serverdata
// send the info about the new client to all connected clients
// send the serverdata
MSG_WriteByte (&buf, svc_serverdata);
#ifdef PROTOCOL_VERSION_FTE
if (cls.fteprotocolextensions) //maintain demo compatability
{
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE);
MSG_WriteLong (&buf, cls.fteprotocolextensions);
}
if (cls.fteprotocolextensions2) //maintain demo compatability
{
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE2);
MSG_WriteLong (&buf, cls.fteprotocolextensions2);
}
#endif
MSG_WriteLong (&buf, PROTOCOL_VERSION_QW);
MSG_WriteLong (&buf, cl.servercount);
MSG_WriteString (&buf, gamedirfile);
if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{
MSG_WriteByte (&buf, cl.allocated_client_slots);
MSG_WriteByte (&buf, cl.splitclients | (cl.spectator?128:0));
for (i = 0; i < cl.splitclients; i++)
MSG_WriteByte (&buf, cl.playerview[i].playernum);
}
else
{
for (i = 0; i < cl.splitclients; i++)
{
if (cl.spectator)
MSG_WriteByte (&buf, cl.playerview[i].playernum | 128);
else
MSG_WriteByte (&buf, cl.playerview[i].playernum);
}
if (cls.fteprotocolextensions & PEXT_SPLITSCREEN)
MSG_WriteByte (&buf, 128);
}
// send full levelname
MSG_WriteString (&buf, cl.levelname);
// send the movevars
MSG_WriteFloat(&buf, movevars.gravity);
MSG_WriteFloat(&buf, movevars.stopspeed);
MSG_WriteFloat(&buf, movevars.maxspeed);
MSG_WriteFloat(&buf, movevars.spectatormaxspeed);
MSG_WriteFloat(&buf, movevars.accelerate);
MSG_WriteFloat(&buf, movevars.airaccelerate);
MSG_WriteFloat(&buf, movevars.wateraccelerate);
MSG_WriteFloat(&buf, movevars.friction);
MSG_WriteFloat(&buf, movevars.waterfriction);
MSG_WriteFloat(&buf, movevars.entgravity);
// send server info string
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );
CLQW_RecordServerData(&buf);
// send music
Media_WriteCurrentTrack(&buf);
@ -1378,7 +1686,7 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, svc_setpause);
MSG_WriteByte (&buf, cl.paused);
MSG_WriteByte (&buf, !!cl.paused);
#ifdef PEXT_SETVIEW
if (cl.playerview[0].viewentity != cl.playerview[0].playernum+1) //tell the player if we have a different view entity
@ -1389,7 +1697,6 @@ void CL_Record_f (void)
#endif
// flush packet
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
// soundlist
MSG_WriteByte (&buf, svc_soundlist);
@ -1405,7 +1712,7 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
if (n + 1 > 0xff)
{
MSG_WriteByte (&buf, svcfte_soundlistshort);
@ -1425,7 +1732,6 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
//FIXME: vweps
@ -1444,7 +1750,7 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
if (n + 1 > 0xff)
{
MSG_WriteByte (&buf, svcfte_modellistshort);
@ -1464,131 +1770,15 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
//particleeffectnum stuff
for (i = 1; i < MAX_SSPARTICLESPRE; i++)
{
if (!cl.particle_ssname[i])
break;
MSG_WriteByte(&buf, svcfte_precache);
MSG_WriteShort(&buf, PC_PARTICLE | i);
MSG_WriteString(&buf, cl.particle_ssname[i]);
if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
//custom tents (needed for hexen2, if nothing else)
for (i = 0; ; i++)
{
if (!CL_WriteCustomTEnt(&buf, i))
break;
if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
// spawnstatic
for (i = 0; i < cl.num_statics; i++)
{
ent = &cl_static_entities[i].ent;
#ifndef CLIENTONLY //FIXME
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
MSG_WriteByte(&buf, svcfte_spawnstatic2);
SVFTE_EmitBaseline(&cl_static_entities[i].state, false, &buf, cls.fteprotocolextensions2);
}
//else if (cls.fteprotocolextensions & PEXT_SPAWNSTATIC2) //qw deltas
else
#endif
{
MSG_WriteByte (&buf, svc_spawnstatic);
for (j = 1; j < MAX_PRECACHE_MODELS; j++)
if (ent->model == cl.model_precache[j])
break;
if (j == MAX_PRECACHE_MODELS)
MSG_WriteByte (&buf, 0);
else
MSG_WriteByte (&buf, j);
MSG_WriteByte (&buf, ent->framestate.g[FS_REG].frame[0]);
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, ent->skinnum);
for (j=0 ; j<3 ; j++)
{
MSG_WriteCoord (&buf, ent->origin[j]);
MSG_WriteAngle (&buf, ent->angles[j]);
}
}
if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
// FIXME: static sounds
// static sounds are skipped in demos, life is hard
// baselines
for (i = 0; i < cl_baselines_count; i++)
{
es = cl_baselines + i;
if (memcmp(es, &nullentitystate, sizeof(nullentitystate)))
{
#ifndef CLIENTONLY //FIXME
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
MSG_WriteByte(&buf, svcfte_spawnbaseline2);
SVFTE_EmitBaseline(es, true, &buf, cls.fteprotocolextensions2);
}
//else if (cls.fteprotocolextensions & PEXT_SPAWNSTATIC2) //qw deltas
else
#endif
{
MSG_WriteByte (&buf,svc_spawnbaseline);
MSG_WriteEntity (&buf, i);
MSG_WriteByte (&buf, es->modelindex);
MSG_WriteByte (&buf, es->frame);
MSG_WriteByte (&buf, es->colormap);
MSG_WriteByte (&buf, es->skinnum);
for (j=0 ; j<3 ; j++)
{
MSG_WriteCoord(&buf, es->origin[j]);
MSG_WriteAngle(&buf, es->angles[j]);
}
}
if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
}
seq = CL_Record_ParticlesStaticsBaselines(&buf, seq);
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("cmd spawn %i\n", cl.servercount) );
if (buf.cursize)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
// send current status of all other players
@ -1633,44 +1823,10 @@ void CL_Record_f (void)
}
if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
// send all current light styles
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
if (i >= MAX_STANDARDLIGHTSTYLES)
if (!*cl_lightstyle[i].map)
continue;
#ifdef PEXT_LIGHTSTYLECOL
if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (cl_lightstyle[i].colours[0]!=1||cl_lightstyle[i].colours[1]!=1||cl_lightstyle[i].colours[2]!=1) && *cl_lightstyle[i].map)
{
MSG_WriteByte (&buf, svcfte_lightstylecol);
MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteByte (&buf, 0x87);
MSG_WriteShort (&buf, cl_lightstyle[i].colours[0]*1024);
MSG_WriteShort (&buf, cl_lightstyle[i].colours[1]*1024);
MSG_WriteShort (&buf, cl_lightstyle[i].colours[2]*1024);
MSG_WriteString (&buf, cl_lightstyle[i].map);
}
else
#endif
{
MSG_WriteByte (&buf, svc_lightstyle);
MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteString (&buf, cl_lightstyle[i].map);
}
if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
seq = CL_Record_Lightstyles(&buf, seq);
for (seat = 0; seat < cl.splitclients; seat++)
{
@ -1712,10 +1868,7 @@ void CL_Record_f (void)
}
if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
}
@ -1775,8 +1928,37 @@ void CL_Record_f (void)
CL_WriteRecordQ2DemoMessage (&buf);
break;
#endif
case CP_NETQUAKE: //FIXME
#ifdef NQPROT
case CP_NETQUAKE:
//csqc stuff
cls.demorecording = DPB_NETQUAKE;
VFS_WRITE(cls.demooutfile, "-1\n", 3); //stupid lame header thing.
CLNQ_WriteServerData(&buf);
MSG_WriteByte (&buf, svc_setpause);
MSG_WriteByte (&buf, !!cl.paused);
MSG_WriteByte (&buf, svc_setview);
MSG_WriteEntity (&buf, cl.playerview[0].viewentity);
MSG_WriteByte (&buf, svc_signonnum);
MSG_WriteByte (&buf, 1);
CL_WriteRecordDemoMessage (&buf, seq++);
seq = CL_Record_ParticlesStaticsBaselines(&buf, seq);
//fixme: brushes...
MSG_WriteByte (&buf, svc_signonnum);
MSG_WriteByte (&buf, 2);
CL_WriteRecordDemoMessage (&buf, seq++);
//fixme: clients
seq = CL_Record_Lightstyles(&buf, seq);
//fixme: stats
MSG_WriteByte (&buf, svc_signonnum);
MSG_WriteByte (&buf, 3);
CL_WriteRecordDemoMessage (&buf, seq++);
break;
#endif
default:
//this should have been caught earlier
Con_Printf("Unable to begin demo recording with this network protocol\n");
CL_Stop_f();
break;
@ -1820,6 +2002,8 @@ void CL_ReRecord_f (void)
Q_snprintfz (name, sizeof(name), "%s", s);
CL_Disconnect();
//
// open the demo file
//
@ -1854,7 +2038,9 @@ void CL_ReRecord_f (void)
Con_Printf ("recording to %s.\n", name);
CL_Disconnect();
if (cls.demorecording == DPB_NETQUAKE) //nq demos have some silly header.
VFS_WRITE(cls.demooutfile, "-1\n", 3);
CL_BeginServerReconnect();
}

View File

@ -33,7 +33,7 @@ cvar_t cl_nodelta = CVAR("cl_nodelta","0");
cvar_t cl_c2sdupe = CVAR("cl_c2sdupe", "0");
cvar_t cl_c2spps = CVAR("cl_c2spps", "0");
cvar_t cl_c2sImpulseBackup = SCVAR("cl_c2sImpulseBackup","3");
cvar_t cl_c2sImpulseBackup = CVAR("cl_c2sImpulseBackup","3");
cvar_t cl_netfps = CVAR("cl_netfps", "150");
cvar_t cl_sparemsec = CVARC("cl_sparemsec", "10", CL_SpareMsec_Callback);
cvar_t cl_queueimpulses = CVAR("cl_queueimpulses", "0");
@ -555,17 +555,17 @@ void CL_ProxyMenuHooks(void)
//==========================================================================
cvar_t cl_upspeed = SCVARF("cl_upspeed","400", CVAR_ARCHIVE);
cvar_t cl_forwardspeed = SCVARF("cl_forwardspeed","400", CVAR_ARCHIVE);
cvar_t cl_upspeed = CVARF("cl_upspeed","400", CVAR_ARCHIVE);
cvar_t cl_forwardspeed = CVARF("cl_forwardspeed","400", CVAR_ARCHIVE);
cvar_t cl_backspeed = CVARFD("cl_backspeed","", CVAR_ARCHIVE, "The base speed that you move backwards at. If empty, uses the value of cl_forwardspeed instead.");
cvar_t cl_sidespeed = SCVARF("cl_sidespeed","400", CVAR_ARCHIVE);
cvar_t cl_sidespeed = CVARF("cl_sidespeed","400", CVAR_ARCHIVE);
cvar_t cl_movespeedkey = SCVAR("cl_movespeedkey","2.0");
cvar_t cl_movespeedkey = CVAR("cl_movespeedkey","2.0");
cvar_t cl_yawspeed = SCVAR("cl_yawspeed","140");
cvar_t cl_pitchspeed = SCVAR("cl_pitchspeed","150");
cvar_t cl_yawspeed = CVAR("cl_yawspeed","140");
cvar_t cl_pitchspeed = CVAR("cl_pitchspeed","150");
cvar_t cl_anglespeedkey = SCVAR("cl_anglespeedkey","1.5");
cvar_t cl_anglespeedkey = CVAR("cl_anglespeedkey","1.5");
void CL_GatherButtons (usercmd_t *cmd, int pnum)

View File

@ -45,11 +45,11 @@ qboolean noclip_anglehack; // remnant from old quake
void Host_FinishLoading(void);
cvar_t rcon_password = SCVARF("rcon_password", "", CVAR_NOUNSAFEEXPAND);
cvar_t rcon_password = CVARF("rcon_password", "", CVAR_NOUNSAFEEXPAND);
cvar_t rcon_address = SCVARF("rcon_address", "", CVAR_NOUNSAFEEXPAND);
cvar_t rcon_address = CVARF("rcon_address", "", CVAR_NOUNSAFEEXPAND);
cvar_t cl_timeout = SCVAR("cl_timeout", "60");
cvar_t cl_timeout = CVAR("cl_timeout", "60");
cvar_t cl_shownet = CVARD("cl_shownet","0", "Debugging var. 0 shows nothing. 1 shows incoming packet sizes. 2 shows individual messages. 3 shows entities too."); // can be 0, 1, or 2
@ -271,11 +271,11 @@ int host_framecount;
qbyte *host_basepal;
qbyte *h2playertranslations;
cvar_t host_speeds = SCVAR("host_speeds","0"); // set for running times
cvar_t host_speeds = CVAR("host_speeds","0"); // set for running times
#ifdef CRAZYDEBUGGING
cvar_t developer = SCVAR("developer","1");
cvar_t developer = CVAR("developer","1");
#else
cvar_t developer = SCVAR("developer","0");
cvar_t developer = CVAR("developer","0");
#endif
int fps_count;
@ -5824,6 +5824,7 @@ void Host_Shutdown(void)
COM_DestroyWorkerThread();
P_ShutdownParticleSystem();
Cvar_Shutdown();
Validation_FlushFileList();

View File

@ -173,6 +173,8 @@ extern struct selectedserver_s
qboolean inuse;
netadr_t adr;
float refreshtime;
int lastplayer;
char lastrule[64];
serverdetailedinfo_t *detail;

View File

@ -2842,7 +2842,7 @@ void CLQW_ParseServerData (void)
CL_DownloadFailed(cls.download->remotename, cls.download);
}
Con_DPrintf ("Serverdata packet received.\n");
Con_DPrintf ("Serverdata packet %s.\n", cls.demoplayback?"read":"received");
//
// wipe the client_state_t struct
//
@ -3132,7 +3132,7 @@ void CLQ2_ParseServerData (void)
cls.fteprotocolextensions2 = 0;
cls.demohadkeyframe = true; //assume that it did, so this stuff all gets recorded.
Con_DPrintf ("Serverdata packet received.\n");
Con_DPrintf ("Serverdata packet %s.\n", cls.demoplayback?"read":"received");
//
// wipe the client_state_t struct
//
@ -3427,8 +3427,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
int nummodels, numsounds;
char *str;
int gametype;
if (developer.ival)
Con_TPrintf ("Serverdata packet received.\n");
Con_DPrintf ("Serverdata packet %s.\n", cls.demoplayback?"read":"received");
SCR_SetLoadingStage(LS_CLIENT);
CL_ClearState ();
Stats_NewMap();
@ -3436,8 +3435,10 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
CLNQ_ParseProtoVersion();
if (MSG_ReadByte() > MAX_CLIENTS)
cl.allocated_client_slots = MSG_ReadByte();
if (cl.allocated_client_slots > MAX_CLIENTS)
{
cl.allocated_client_slots = MAX_CLIENTS;
Con_Printf ("\nWarning, this server supports more than %i clients, additional clients will do bad things\n", MAX_CLIENTS);
}

View File

@ -23,8 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
cvar_t cl_predict_extrapolate = CVARD("cl_predict_extrapolate", "", "If 1, enables prediction based upon partial input frames which can change over time resulting in a swimmy feel but does not need to interpolate. If 0, prediction will stay in the past and thus use only completed frames. Interpolation will then be used to smooth movement.\nThis cvar only applies when video and input frames are independant (ie: cl_netfps is set).");
cvar_t cl_predict_timenudge = CVARD("cl_predict_timenudge", "0", "A debug feature. You should normally leave this as 0. Nudges local player prediction into the future if positive (resulting in extrapolation), or into the past if negative (resulting in laggy interpolation). Value is in seconds, so small decimals are required. This cvar applies even if input frames are tied to video frames.");
cvar_t cl_predict_smooth = CVARD("cl_lerp_smooth", "2", "If 2, will act as 1 when playing demos and otherwise act as if set to 0.\nIf 1, interpolation will run in the past, resulting in really smooth movement at the cost of latency (even on bunchy german ISDNs).\nIf 0, interpolation will be based upon packet arrival times and may judder due to packet loss.");
cvar_t cl_nopred = SCVAR("cl_nopred","0");
cvar_t cl_pushlatency = SCVAR("pushlatency","-999");
cvar_t cl_nopred = CVAR("cl_nopred","0");
cvar_t cl_pushlatency = CVAR("pushlatency","-999");
extern float pm_airaccelerate;

View File

@ -224,19 +224,19 @@ float scr_disabled_time;
float oldsbar = 0;
cvar_t con_stayhidden = CVARFD("con_stayhidden", "0", CVAR_NOTFROMSERVER, "0: allow console to pounce on the user\n1: console stays hidden unless explicitly invoked\n2:toggleconsole command no longer works\n3: shift+escape key no longer works");
cvar_t show_fps = SCVARF("show_fps", "0", CVAR_ARCHIVE);
cvar_t show_fps_x = SCVAR("show_fps_x", "-1");
cvar_t show_fps_y = SCVAR("show_fps_y", "-1");
cvar_t show_clock = SCVAR("cl_clock", "0");
cvar_t show_clock_x = SCVAR("cl_clock_x", "0");
cvar_t show_clock_y = SCVAR("cl_clock_y", "-1");
cvar_t show_gameclock = SCVAR("cl_gameclock", "0");
cvar_t show_gameclock_x = SCVAR("cl_gameclock_x", "0");
cvar_t show_gameclock_y = SCVAR("cl_gameclock_y", "-1");
cvar_t show_speed = SCVAR("show_speed", "0");
cvar_t show_speed_x = SCVAR("show_speed_x", "-1");
cvar_t show_speed_y = SCVAR("show_speed_y", "-9");
cvar_t scr_loadingrefresh = SCVAR("scr_loadingrefresh", "0");
cvar_t show_fps = CVARF("show_fps", "0", CVAR_ARCHIVE);
cvar_t show_fps_x = CVAR("show_fps_x", "-1");
cvar_t show_fps_y = CVAR("show_fps_y", "-1");
cvar_t show_clock = CVAR("cl_clock", "0");
cvar_t show_clock_x = CVAR("cl_clock_x", "0");
cvar_t show_clock_y = CVAR("cl_clock_y", "-1");
cvar_t show_gameclock = CVAR("cl_gameclock", "0");
cvar_t show_gameclock_x = CVAR("cl_gameclock_x", "0");
cvar_t show_gameclock_y = CVAR("cl_gameclock_y", "-1");
cvar_t show_speed = CVAR("show_speed", "0");
cvar_t show_speed_x = CVAR("show_speed_x", "-1");
cvar_t show_speed_y = CVAR("show_speed_y", "-9");
cvar_t scr_loadingrefresh = CVAR("scr_loadingrefresh", "0");
cvar_t scr_showloading = CVAR("scr_showloading", "1");
cvar_t scr_showobituaries = CVAR("scr_showobituaries", "0");

View File

@ -58,14 +58,14 @@ qterm_t *activeqterm;
float con_cursorspeed = 4;
cvar_t con_numnotifylines = SCVAR("con_notifylines","4"); //max lines to show
cvar_t con_notifytime = SCVAR("con_notifytime","3"); //seconds
cvar_t con_notify_x = SCVAR("con_notify_x","0");
cvar_t con_notify_y = SCVAR("con_notify_y","0");
cvar_t con_notify_w = SCVAR("con_notify_w","1");
cvar_t con_centernotify = SCVAR("con_centernotify", "0");
cvar_t con_displaypossibilities = SCVAR("con_displaypossibilities", "1");
cvar_t con_maxlines = SCVAR("con_maxlines", "1024");
cvar_t con_numnotifylines = CVAR("con_notifylines","4"); //max lines to show
cvar_t con_notifytime = CVAR("con_notifytime","3"); //seconds
cvar_t con_notify_x = CVAR("con_notify_x","0");
cvar_t con_notify_y = CVAR("con_notify_y","0");
cvar_t con_notify_w = CVAR("con_notify_w","1");
cvar_t con_centernotify = CVAR("con_centernotify", "0");
cvar_t con_displaypossibilities = CVAR("con_displaypossibilities", "1");
cvar_t con_maxlines = CVAR("con_maxlines", "1024");
cvar_t cl_chatmode = CVARD("cl_chatmode", "2", "0(nq) - everything is assumed to be a console command. prefix with 'say', or just use a messagemode bind\n1(q3) - everything is assumed to be chat, unless its prefixed with a /\n2(qw) - anything explicitly recognised as a command will be used as a command, anything unrecognised will be a chat message.\n/ prefix is supported in all cases.\nctrl held when pressing enter always makes any implicit chat into team chat instead.");
cvar_t con_numnotifylines_chat = CVAR("con_numnotifylines_chat", "8");
cvar_t con_notifytime_chat = CVAR("con_notifytime_chat", "8");

View File

@ -213,6 +213,10 @@ static void PM_FreePackage(package_t *p)
for (i = 0; i < countof(p->mirror); i++)
Z_Free(p->mirror[i]);
Z_Free(p->description);
Z_Free(p->author);
Z_Free(p->license);
Z_Free(p->previewimage);
Z_Free(p->qhash);
Z_Free(p->arch);
Z_Free(p);

View File

@ -407,6 +407,7 @@ static void SL_PreDraw (menu_t *menu)
info->numslots = Master_NumSorted();
snprintf(info->refreshtext, sizeof(info->refreshtext), "Refresh - %u/%u/%u\n", info->numslots, Master_NumAlive(), Master_TotalCount());
}
void NET_SendPollPacket(int len, void *data, netadr_t to);
static void SL_PostDraw (menu_t *menu)
{
static char *helpstrings[] =
@ -436,7 +437,32 @@ static void SL_PostDraw (menu_t *menu)
{
selectedserver.refreshtime = realtime + 4;
server->sends++;
Master_QueryServer(server);
#ifdef NQPROT
//we might have gotten stuck. reset the poll
if ((server->special&SS_PROTOCOLMASK) == SS_NETQUAKE)
{ //start spamming the server to get all of its details. silly protocols.
selectedserver.lastplayer = 0;
*selectedserver.lastrule = 0;
SZ_Clear(&net_message);
net_message.packing = SZ_RAWBYTES;
net_message.currentbit = 0;
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
MSG_WriteByte(&net_message, selectedserver.lastplayer);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
NET_SendPollPacket(net_message.cursize, net_message.data, server->adr);
SZ_Clear(&net_message);
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
MSG_WriteString(&net_message, selectedserver.lastrule);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
NET_SendPollPacket(net_message.cursize, net_message.data, server->adr);
SZ_Clear(&net_message);
}
else
#endif
Master_QueryServer(server);
}
R2D_ImageColours(1,1,1,1);
if (server && server->moreinfo)

View File

@ -256,10 +256,10 @@ qboolean Media_EvaluateNextTrack(void);
int lasttrackplayed;
cvar_t media_shuffle = SCVAR("media_shuffle", "1");
cvar_t media_repeat = SCVAR("media_repeat", "1");
cvar_t media_shuffle = CVAR("media_shuffle", "1");
cvar_t media_repeat = CVAR("media_repeat", "1");
#ifdef WINAMP
cvar_t media_hijackwinamp = SCVAR("media_hijackwinamp", "0");
cvar_t media_hijackwinamp = CVAR("media_hijackwinamp", "0");
#endif
int selectedoption=-1;

View File

@ -756,6 +756,7 @@ const char *presetexec[] =
"seta r_part_classic_opaque 0;"
"seta r_stains 0;"
"seta r_drawflat 1;"
"seta r_lightmap 0;"
"seta r_nolerp 1;"
"seta r_nolightdir 1;"
"seta r_dynamic 0;"

View File

@ -209,7 +209,7 @@ qboolean m_recursiveDraw;
void M_ConfigureNetSubsystem(void);
cvar_t m_helpismedia = SCVAR("m_helpismedia", "0");
cvar_t m_helpismedia = CVAR("m_helpismedia", "0");
cvar_t m_preset_chosen = CVARF("m_preset_chosen", "0", CVAR_ARCHIVE);
//=============================================================================

View File

@ -123,7 +123,7 @@ net_masterlist_t net_masterlist[] = {
// {MP_QUAKEWORLD, CVARFC("net_qwmasterextraHistoric", "telefrag.me:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "telefrag.me"},
// {MP_QUAKEWORLD, CVARFC("net_qwmasterextraHistoric", "master.teamdamage.com:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "master.teamdamage.com"},
{MP_DPMASTER, CVARFC("net_masterextra1", "ghdigital.com:27950 69.59.212.88:27950", CVAR_NOSAVE, Net_Masterlist_Callback)}, //69.59.212.88 (admin: LordHavoc)
{MP_DPMASTER, CVARFC("net_masterextra1", "ghdigital.com:27950 207.55.114.154:27950", CVAR_NOSAVE, Net_Masterlist_Callback)}, //207.55.114.154 (was 69.59.212.88 (admin: LordHavoc)
{MP_DPMASTER, CVARFC("net_masterextra2", "dpmaster.deathmask.net:27950 107.161.23.68:27950 [2604:180::4ac:98c1]:27950", CVAR_NOSAVE, Net_Masterlist_Callback)}, //107.161.23.68 (admin: Willis)
{MP_DPMASTER, CVARFC("net_masterextra3", "dpmaster.tchr.no:27950 92.62.40.73:27950", CVAR_NOSAVE, Net_Masterlist_Callback)}, //92.62.40.73 (admin: tChr)
@ -560,8 +560,8 @@ typedef int SOCKET;
//the number of servers should be limited only by memory.
cvar_t slist_cacheinfo = SCVAR("slist_cacheinfo", "0"); //this proves dangerous, memory wise.
cvar_t slist_writeserverstxt = SCVAR("slist_writeservers", "0");
cvar_t slist_cacheinfo = CVAR("slist_cacheinfo", "0"); //this proves dangerous, memory wise.
cvar_t slist_writeserverstxt = CVAR("slist_writeservers", "0");
void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad);
int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favorite);
@ -1904,6 +1904,7 @@ int Master_CheckPollSockets(void)
int users, maxusers;
int control;
int ccrep;
MSG_BeginReading (msg_nullnetprim);
control = BigLong(*((int *)net_message.data));
@ -1915,23 +1916,94 @@ int Master_CheckPollSockets(void)
if ((control & NETFLAG_LENGTH_MASK) != ret)
continue;
if (MSG_ReadByte() != CCREP_SERVER_INFO)
continue;
ccrep = MSG_ReadByte();
/*this is an address string sent from the server. its not usable. if its replying to serverinfos, its possible to send it connect requests, while the address that it claims is 50% bugged*/
MSG_ReadString();
Q_strncpyz(name, MSG_ReadString(), sizeof(name));
Q_strncpyz(map, MSG_ReadString(), sizeof(map));
users = MSG_ReadByte();
maxusers = MSG_ReadByte();
if (MSG_ReadByte() != NQ_NETCHAN_VERSION)
if (ccrep == CCREP_PLAYER_INFO)
{
// Q_strcpy(name, "*");
// Q_strcat(name, name);
}
serverinfo_t *selserver = selectedserver.inuse?Master_InfoForServer(&selectedserver.adr):NULL;
serverinfo_t *info = Master_InfoForServer(&net_from);
info = Master_InfoForServer(&net_from);
if (selserver == info)
{
int playernum = MSG_ReadByte();
char *playername = MSG_ReadString();
int playercolor = MSG_ReadLong();
int playerfrags = MSG_ReadLong();
int secsonserver = MSG_ReadLong();
//char *playeraddr = MSG_ReadString();
if (msg_badread)
continue;
CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i\\clients\\%i", name, map, maxusers, users), MP_NETQUAKE, false);
selectedserver.lastplayer = playernum+1;
memset(&info->moreinfo->players[playernum], 0, sizeof(info->moreinfo->players[playernum]));
info->moreinfo->players[playernum].userid = 0;
info->moreinfo->players[playernum].frags = playerfrags;
info->moreinfo->players[playernum].time = secsonserver;
info->moreinfo->players[playernum].ping = 0; //*sigh*
Q_strncpyz(info->moreinfo->players[playernum].name, playername, sizeof(info->moreinfo->players[playernum].name));
Q_strncpyz(info->moreinfo->players[playernum].skin, "", sizeof(info->moreinfo->players[playernum].skin));
Q_strncpyz(info->moreinfo->players[playernum].team, "", sizeof(info->moreinfo->players[playernum].team));
info->moreinfo->players[playernum].topc = playercolor>>4;
info->moreinfo->players[playernum].botc = playercolor&15;
info->moreinfo->players[playernum].isspec = false;
info->moreinfo->numplayers = max(info->moreinfo->numplayers, playernum+1);
//... and now try to query the next one... because everyone gives up after the first, right?... dude... I hate this shit.
SZ_Clear(&net_message);
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
MSG_WriteByte(&net_message, selectedserver.lastplayer);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
NET_SendPollPacket(net_message.cursize, net_message.data, info->adr);
SZ_Clear(&net_message);
}
}
else if (ccrep == CCREP_RULE_INFO)
{
serverinfo_t *selserver = selectedserver.inuse?Master_InfoForServer(&selectedserver.adr):NULL;
serverinfo_t *info = Master_InfoForServer(&net_from);
char *s, *old;
info = Master_InfoForServer(&net_from);
if (selserver == info)
{
s = MSG_ReadString();
if (msg_badread)
continue;
Q_strncpyz(selectedserver.lastrule, s, sizeof(selectedserver.lastrule));
s = MSG_ReadString();
old = Info_ValueForKey(info->moreinfo->info, selectedserver.lastrule);
if (strcmp(s, old))
Info_SetValueForStarKey(info->moreinfo->info, selectedserver.lastrule, s, sizeof(info->moreinfo->info));
//... and now try to query the next one... because everyone gives up after the first, right?... dude... I hate this shit.
SZ_Clear(&net_message);
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
MSG_WriteString(&net_message, selectedserver.lastrule);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
NET_SendPollPacket(net_message.cursize, net_message.data, info->adr);
SZ_Clear(&net_message);
}
}
else if (ccrep == CCREP_SERVER_INFO)
{
/*this is an address string sent from the server. its not usable. if its replying to serverinfos, its possible to send it connect requests, while the address that it claims is 50% bugged*/
MSG_ReadString();
Q_strncpyz(name, MSG_ReadString(), sizeof(name));
Q_strncpyz(map, MSG_ReadString(), sizeof(map));
users = MSG_ReadByte();
maxusers = MSG_ReadByte();
if (MSG_ReadByte() != NQ_NETCHAN_VERSION)
{
// Q_strcpy(name, "*");
// Q_strcat(name, name);
}
CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i\\clients\\%i", name, map, maxusers, users), MP_NETQUAKE, false);
}
}
#endif
continue;
@ -1994,6 +2066,29 @@ void SListOptionChanged(serverinfo_t *newserver)
selectedserver.refreshtime = realtime+4;
newserver->sends++;
Master_QueryServer(newserver);
#ifdef NQPROT
selectedserver.lastplayer = 0;
*selectedserver.lastrule = 0;
if ((newserver->special&SS_PROTOCOLMASK) == SS_NETQUAKE)
{ //start spamming the server to get all of its details. silly protocols.
SZ_Clear(&net_message);
net_message.packing = SZ_RAWBYTES;
net_message.currentbit = 0;
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
MSG_WriteByte(&net_message, selectedserver.lastplayer);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
NET_SendPollPacket(net_message.cursize, net_message.data, newserver->adr);
SZ_Clear(&net_message);
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
MSG_WriteString(&net_message, selectedserver.lastrule);
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
NET_SendPollPacket(net_message.cursize, net_message.data, newserver->adr);
SZ_Clear(&net_message);
}
#endif
}
}
@ -2475,7 +2570,10 @@ void Master_QueryServer(serverinfo_t *server)
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255);
break;
case SS_DARKPLACES:
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetinfo", 255, 255, 255, 255);
if (server->moreinfo)
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255);
else
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetinfo", 255, 255, 255, 255);
break;
#ifdef NQPROT
case SS_NETQUAKE:
@ -2841,8 +2939,6 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
}
}
MasterInfo_RemovePlayers(&info->adr);
name = Info_ValueForKey(msg, "hostname");
if (!*name)
name = Info_ValueForKey(msg, "sv_hostname");
@ -2939,178 +3035,189 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
strcpy(details.info, msg);
msg = msg+strlen(msg)+1;
info->players=details.numplayers = 0;
if (!strchr(msg, '\n'))
//clear player info. unless its an NQ server, which have some really annoying protocol to find out the players.
if ((info->special & SS_PROTOCOLMASK) == SS_NETQUAKE)
{
if (!info->moreinfo && ((slist_cacheinfo.value == 2 || NET_CompareAdr(&info->adr, &selectedserver.adr)) || (info->special & SS_KEEPINFO)))
info->moreinfo = Z_Malloc(sizeof(serverdetailedinfo_t));
info->numhumans = info->players = atoi(Info_ValueForKey(details.info, "clients"));
}
else
{
int clnum;
for (clnum=0; clnum < MAX_CLIENTS; clnum++)
MasterInfo_RemovePlayers(&info->adr);
info->players=details.numplayers = 0;
if (!strchr(msg, '\n'))
info->numhumans = info->players = atoi(Info_ValueForKey(details.info, "clients"));
else
{
nl = strchr(msg, '\n');
if (!nl)
break;
*nl = '\0';
int clnum;
details.players[clnum].isspec = 0;
details.players[clnum].team[0] = 0;
details.players[clnum].skin[0] = 0;
token = msg;
if (!token)
break;
details.players[clnum].userid = atoi(token);
token = strchr(token+1, ' ');
if (!token)
break;
details.players[clnum].frags = atoi(token);
token = strchr(token+1, ' ');
if (!token)
break;
details.players[clnum].time = atoi(token);
msg = token;
token = strchr(msg+1, ' ');
if (!token) //probably q2 response
for (clnum=0; clnum < MAX_CLIENTS; clnum++)
{
//see if this is actually a Quake2 server.
token = strchr(msg+1, '\"');
if (!token) //it wasn't.
nl = strchr(msg, '\n');
if (!nl)
break;
*nl = '\0';
details.players[clnum].ping = details.players[clnum].frags;
details.players[clnum].frags = details.players[clnum].userid;
details.players[clnum].isspec = 0;
details.players[clnum].team[0] = 0;
details.players[clnum].skin[0] = 0;
msg = strchr(token+1, '\"');
if (!msg)
break;
len = msg - token;
if (len >= sizeof(details.players[clnum].name))
len = sizeof(details.players[clnum].name);
Q_strncpyz(details.players[clnum].name, token+1, len);
details.players[clnum].skin[0] = '\0';
details.players[clnum].topc = 0;
details.players[clnum].botc = 0;
details.players[clnum].time = 0;
}
else //qw response
{
details.players[clnum].ping = atoi(token);
msg = token;
token = strchr(msg+1, ' ');
token = msg;
if (!token)
break;
token = strchr(token+1, '\"');
if (!token)
break;
msg = strchr(token+1, '\"');
if (!msg)
break;
len = msg - token;
if (len >= sizeof(details.players[clnum].name))
len = sizeof(details.players[clnum].name);
if (!strncmp(token, "\"\\s\\", 4))
{
details.players[clnum].isspec |= 1;
Q_strncpyz(details.players[clnum].name, token+4, len-3);
}
else
Q_strncpyz(details.players[clnum].name, token+1, len);
details.players[clnum].name[len] = '\0';
token = strchr(msg+1, '\"');
if (!token)
break;
msg = strchr(token+1, '\"');
if (!msg)
break;
len = msg - token;
if (len >= sizeof(details.players[clnum].skin))
len = sizeof(details.players[clnum].skin);
Q_strncpyz(details.players[clnum].skin, token+1, len);
details.players[clnum].skin[len] = '\0';
token = strchr(msg+1, ' ');
if (!token)
break;
details.players[clnum].topc = atoi(token);
details.players[clnum].userid = atoi(token);
token = strchr(token+1, ' ');
if (!token)
break;
details.players[clnum].botc = atoi(token);
token = strchr(msg+1, '\"');
Q_strncpyz(details.players[clnum].team, "", sizeof(details.players[clnum].team));
if (token)
details.players[clnum].frags = atoi(token);
token = strchr(token+1, ' ');
if (!token)
break;
details.players[clnum].time = atoi(token);
msg = token;
token = strchr(msg+1, ' ');
if (!token) //probably q2 response
{
//see if this is actually a Quake2 server.
token = strchr(msg+1, '\"');
if (!token) //it wasn't.
break;
details.players[clnum].ping = details.players[clnum].frags;
details.players[clnum].frags = details.players[clnum].userid;
msg = strchr(token+1, '\"');
if (msg)
if (!msg)
break;
len = msg - token;
if (len >= sizeof(details.players[clnum].name))
len = sizeof(details.players[clnum].name);
Q_strncpyz(details.players[clnum].name, token+1, len);
details.players[clnum].skin[0] = '\0';
details.players[clnum].topc = 0;
details.players[clnum].botc = 0;
details.players[clnum].time = 0;
}
else //qw response
{
details.players[clnum].ping = atoi(token);
msg = token;
token = strchr(msg+1, ' ');
if (!token)
break;
token = strchr(token+1, '\"');
if (!token)
break;
msg = strchr(token+1, '\"');
if (!msg)
break;
len = msg - token;
if (len >= sizeof(details.players[clnum].name))
len = sizeof(details.players[clnum].name);
if (!strncmp(token, "\"\\s\\", 4))
{
len = msg - token;
if (len >= sizeof(details.players[clnum].team))
len = sizeof(details.players[clnum].team);
Q_strncpyz(details.players[clnum].team, token+1, len);
details.players[clnum].team[len] = '\0';
details.players[clnum].isspec |= 1;
Q_strncpyz(details.players[clnum].name, token+4, len-3);
}
else
Q_strncpyz(details.players[clnum].name, token+1, len);
details.players[clnum].name[len] = '\0';
token = strchr(msg+1, '\"');
if (!token)
break;
msg = strchr(token+1, '\"');
if (!msg)
break;
len = msg - token;
if (len >= sizeof(details.players[clnum].skin))
len = sizeof(details.players[clnum].skin);
Q_strncpyz(details.players[clnum].skin, token+1, len);
details.players[clnum].skin[len] = '\0';
token = strchr(msg+1, ' ');
if (!token)
break;
details.players[clnum].topc = atoi(token);
token = strchr(token+1, ' ');
if (!token)
break;
details.players[clnum].botc = atoi(token);
token = strchr(msg+1, '\"');
Q_strncpyz(details.players[clnum].team, "", sizeof(details.players[clnum].team));
if (token)
{
msg = strchr(token+1, '\"');
if (msg)
{
len = msg - token;
if (len >= sizeof(details.players[clnum].team))
len = sizeof(details.players[clnum].team);
Q_strncpyz(details.players[clnum].team, token+1, len);
details.players[clnum].team[len] = '\0';
}
}
}
}
MasterInfo_AddPlayer(&info->adr, details.players[clnum].name, details.players[clnum].ping, details.players[clnum].frags, details.players[clnum].topc*4 | details.players[clnum].botc, details.players[clnum].skin, details.players[clnum].team);
MasterInfo_AddPlayer(&info->adr, details.players[clnum].name, details.players[clnum].ping, details.players[clnum].frags, details.players[clnum].topc*4 | details.players[clnum].botc, details.players[clnum].skin, details.players[clnum].team);
//WallFly is some q2 bot
//[ServeMe] is some qw bot
if (!strncmp(details.players[clnum].name, "WallFly", 7) || !strcmp(details.players[clnum].name, "[ServeMe]"))
{
//not players nor real people. they don't count towards any metric
details.players[clnum].isspec |= 3;
}
//807 excludes the numerous bot names on some annoying qwtf server
//BOT: excludes fte's botclients (which always have a bot: prefix)
else if (details.players[clnum].ping == 807 || !strncmp(details.players[clnum].name, "BOT:", 4))
{
info->numbots++;
details.players[clnum].isspec |= 2;
}
else if (details.players[clnum].isspec & 1)
{
info->numspectators++;
}
else
info->numhumans++;
for (k = clnum, j = clnum-1; j >= 0; j--)
{
if ((details.players[k].isspec != details.players[j].isspec && !details.players[k].isspec) ||
details.players[k].frags > details.players[j].frags)
//WallFly is some q2 bot
//[ServeMe] is some qw bot
if (!strncmp(details.players[clnum].name, "WallFly", 7) || !strcmp(details.players[clnum].name, "[ServeMe]"))
{
struct serverdetailedplayerinfo_s t = details.players[j];
details.players[j] = details.players[k];
details.players[k] = t;
k = j;
//not players nor real people. they don't count towards any metric
details.players[clnum].isspec |= 3;
}
//807 excludes the numerous bot names on some annoying qwtf server
//BOT: excludes fte's botclients (which always have a bot: prefix)
else if (details.players[clnum].ping == 807 || !strncmp(details.players[clnum].name, "BOT:", 4))
{
info->numbots++;
details.players[clnum].isspec |= 2;
}
else if (details.players[clnum].isspec & 1)
{
info->numspectators++;
}
else
break;
info->numhumans++;
for (k = clnum, j = clnum-1; j >= 0; j--)
{
if ((details.players[k].isspec != details.players[j].isspec && !details.players[k].isspec) ||
details.players[k].frags > details.players[j].frags)
{
struct serverdetailedplayerinfo_s t = details.players[j];
details.players[j] = details.players[k];
details.players[k] = t;
k = j;
}
else
break;
}
details.numplayers++;
info->players++;
msg = nl;
if (!msg)
break; //erm...
msg++;
}
details.numplayers++;
info->players++;
msg = nl;
if (!msg)
break; //erm...
msg++;
}
}
if (!info->moreinfo && ((slist_cacheinfo.value == 2 || NET_CompareAdr(&info->adr, &selectedserver.adr)) || (info->special & SS_KEEPINFO)))
info->moreinfo = Z_Malloc(sizeof(serverdetailedinfo_t));
if (NET_CompareAdr(&info->adr, &selectedserver.adr))
selectedserver.detail = info->moreinfo;
if (!info->moreinfo && ((slist_cacheinfo.value == 2 || NET_CompareAdr(&info->adr, &selectedserver.adr)) || (info->special & SS_KEEPINFO)))
info->moreinfo = Z_Malloc(sizeof(serverdetailedinfo_t));
if (NET_CompareAdr(&info->adr, &selectedserver.adr))
selectedserver.detail = info->moreinfo;
if (info->moreinfo)
memcpy(info->moreinfo, &details, sizeof(serverdetailedinfo_t));
if (info->moreinfo)
memcpy(info->moreinfo, &details, sizeof(serverdetailedinfo_t));
}
return true;
}

View File

@ -1182,8 +1182,8 @@ int menuentsize;
// cvars
#define MENUPROGSGROUP "Menu progs control"
cvar_t forceqmenu = SCVAR("forceqmenu", "0");
cvar_t pr_menuqc_coreonerror = SCVAR("pr_menuqc_coreonerror", "1");
cvar_t forceqmenu = CVAR("forceqmenu", "0");
cvar_t pr_menuqc_coreonerror = CVAR("pr_menuqc_coreonerror", "1");
//new generic functions.

View File

@ -627,6 +627,13 @@ cvar_t r_part_maxdecals = CVAR("r_part_maxdecals", "8192");
particleengine_t *pe;
static struct partalias_s
{
struct partalias_s *next;
const char *from;
const char *to;
} *partaliaslist;
void P_ParticleEffect_f(void);
static void P_ParticleEffectAlias_f(void);
@ -673,12 +680,18 @@ void P_InitParticleSystem(void)
R_Clutter_Init();
}
static struct partalias_s
void P_ShutdownParticleSystem(void)
{
struct partalias_s *next;
const char *from;
const char *to;
} *partaliaslist;
struct partalias_s *l;
while (partaliaslist)
{
l = partaliaslist;
partaliaslist = l->next;
Z_Free(l);
}
}
static void P_ParticleEffectAlias_f(void)
{
struct partalias_s **link, *l;

View File

@ -87,46 +87,48 @@ extern cvar_t r_forceprogramify;
cvar_t mod_md3flags = CVARD ("mod_md3flags", "1", "The flags field of md3s was never officially defined. If this is set to 1, the flags will be treated identically to mdl files. Otherwise they will be ignored. Naturally, this is required to provide rotating pickups in quake.");
cvar_t r_ambient = CVARF ("r_ambient", "0",
CVAR_CHEAT);
CVAR_CHEAT);
cvar_t r_bloodstains = CVARF ("r_bloodstains", "1", CVAR_ARCHIVE);
cvar_t r_bouncysparks = CVARFD ("r_bouncysparks", "1",
CVAR_ARCHIVE,
"Enables particle interaction with world surfaces, allowing for bouncy particles, stains, and decals.");
CVAR_ARCHIVE,
"Enables particle interaction with world surfaces, allowing for bouncy particles, stains, and decals.");
cvar_t r_drawentities = CVAR ("r_drawentities", "1");
cvar_t r_drawflat = CVARAF ("r_drawflat", "0", "gl_textureless",
CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM);
CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM);
cvar_t r_lightmap = CVARF ("r_lightmap", "0",
CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM);
cvar_t r_wireframe = CVARFD ("r_wireframe", "0",
CVAR_CHEAT, "Developer feature where everything is drawn with wireframe over the top. Only active where cheats are permitted.");
CVAR_CHEAT, "Developer feature where everything is drawn with wireframe over the top. Only active where cheats are permitted.");
cvar_t r_wireframe_smooth = CVAR ("r_wireframe_smooth", "0");
cvar_t r_refract_fbo = CVARD ("r_refract_fbo", "1", "Use an fbo for refraction. If 0, just renders as a portal and uses a copy of the current framebuffer.");
cvar_t gl_miptexLevel = CVAR ("gl_miptexLevel", "0");
cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE);
cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0");
cvar_t r_dynamic = CVARF ("r_dynamic", IFMINIMAL("0","1"),
CVAR_ARCHIVE);
CVAR_ARCHIVE);
cvar_t r_fastturb = CVARF ("r_fastturb", "0",
CVAR_SHADERSYSTEM);
CVAR_SHADERSYSTEM);
cvar_t r_fastsky = CVARF ("r_fastsky", "0",
CVAR_ARCHIVE | CVAR_SHADERSYSTEM);
CVAR_ARCHIVE | CVAR_SHADERSYSTEM);
cvar_t r_fastskycolour = CVARF ("r_fastskycolour", "0",
CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);
CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);
cvar_t r_fb_bmodels = CVARAF("r_fb_bmodels", "1",
"gl_fb_bmodels", CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_fb_models = CVARAFD ("r_fb_models", "1",
"gl_fb_models", CVAR_SEMICHEAT, "Force all non-player models to be fullbright in deathmatch. Because if you don't enable these cheats then you'll go splat because everone else uses them. QuakeWorld players suck.");
cvar_t r_skin_overlays = SCVARF ("r_skin_overlays", "1",
CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_globalskin_first = CVARFD ("r_globalskin_first", "100", CVAR_RENDERERLATCH, "Specifies the first .skin value that is a global skin. Entities within this range will use the shader/image called 'gfx/skinSKIN.lmp' instead of their regular skin. See also: r_globalskin_count.");
cvar_t r_globalskin_count = CVARFD ("r_globalskin_count", "10", CVAR_RENDERERLATCH, "Specifies how many globalskins there are.");
cvar_t r_skin_overlays = CVARF ("r_skin_overlays", "1",
CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_globalskin_first = CVARFD ("r_globalskin_first", "100", CVAR_RENDERERLATCH, "Specifies the first .skin value that is a global skin. Entities within this range will use the shader/image called 'gfx/skinSKIN.lmp' instead of their regular skin. See also: r_globalskin_count.");
cvar_t r_globalskin_count = CVARFD ("r_globalskin_count", "10", CVAR_RENDERERLATCH, "Specifies how many globalskins there are.");
cvar_t r_coronas = CVARFD ("r_coronas", "0", CVAR_ARCHIVE, "Draw coronas on realtime lights. Overrides glquake-esque flashblends.");
cvar_t r_coronas_occlusion = CVARFD ("r_coronas_occlusion", "", CVAR_ARCHIVE, "Specifies that coronas should be occluded more carefully.\n0: No occlusion, at all.\n1: BSP occlusion only (simple tracelines).\n2: non-bsp occlusion also (complex tracelines).\n3: Depthbuffer reads (forces synchronisation).\n4: occlusion queries.");
cvar_t r_coronas_mindist = CVARFD ("r_coronas_mindist", "128", CVAR_ARCHIVE, "Coronas closer than this will be invisible, preventing near clip plane issues.");
cvar_t r_coronas_fadedist = CVARFD ("r_coronas_fadedist", "256", CVAR_ARCHIVE, "Coronas will fade out over this distance.");
cvar_t r_flashblend = SCVARF ("gl_flashblend", "0",
CVAR_ARCHIVE);
cvar_t r_flashblendscale = SCVARF ("gl_flashblendscale", "0.35",
CVAR_ARCHIVE);
cvar_t r_flashblend = CVARF ("gl_flashblend", "0",
CVAR_ARCHIVE);
cvar_t r_flashblendscale = CVARF ("gl_flashblendscale", "0.35",
CVAR_ARCHIVE);
cvar_t r_floorcolour = CVARAF ("r_floorcolour", "64 64 128",
"r_floorcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);
//cvar_t r_floortexture = SCVARF ("r_floortexture", "",
@ -135,11 +137,11 @@ cvar_t r_fullbright = CVARFD ("r_fullbright", "0",
CVAR_CHEAT|CVAR_SHADERSYSTEM, "Ignore world lightmaps, drawing everything fully lit.");
cvar_t r_fullbrightSkins = CVARF ("r_fullbrightSkins", "0.8", /*don't default to 1, as it looks a little ugly (too bright), but don't default to 0 either because then you're handicapped in the dark*/
CVAR_SEMICHEAT|CVAR_SHADERSYSTEM);
cvar_t r_lightmap_saturation = SCVAR ("r_lightmap_saturation", "1");
cvar_t r_lightmap_saturation = CVAR ("r_lightmap_saturation", "1");
cvar_t r_lightstylesmooth = CVARF ("r_lightstylesmooth", "0", CVAR_ARCHIVE);
cvar_t r_lightstylesmooth_limit = SCVAR ("r_lightstylesmooth_limit", "2");
cvar_t r_lightstylespeed = SCVAR ("r_lightstylespeed", "10");
cvar_t r_lightstylescale = SCVAR ("r_lightstylescale", "1");
cvar_t r_lightstylesmooth_limit = CVAR ("r_lightstylesmooth_limit", "2");
cvar_t r_lightstylespeed = CVAR ("r_lightstylespeed", "10");
cvar_t r_lightstylescale = CVAR ("r_lightstylescale", "1");
cvar_t r_hdr_irisadaptation = CVARF ("r_hdr_irisadaptation", "0", CVAR_ARCHIVE);
cvar_t r_hdr_irisadaptation_multiplier = CVAR ("r_hdr_irisadaptation_multiplier", "2");
cvar_t r_hdr_irisadaptation_minvalue = CVAR ("r_hdr_irisadaptation_minvalue", "0.5");
@ -162,9 +164,9 @@ cvar_t r_skyboxname = CVARFC ("r_skybox", "",
CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM, R_SkyBox_Changed);
cvar_t r_softwarebanding_cvar = CVARFD ("r_softwarebanding", "0", CVAR_SHADERSYSTEM, "Utilise the Quake colormap in order to emulate 8bit software rendering. This results in banding as well as other artifacts that some believe adds character. Also forces nearest sampling on affected surfaces (palette indicies do not interpolate well).");
qboolean r_softwarebanding;
cvar_t r_speeds = SCVAR ("r_speeds", "0");
cvar_t r_stainfadeammount = SCVAR ("r_stainfadeammount", "1");
cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1");
cvar_t r_speeds = CVAR ("r_speeds", "0");
cvar_t r_stainfadeammount = CVAR ("r_stainfadeammount", "1");
cvar_t r_stainfadetime = CVAR ("r_stainfadetime", "1");
cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"),
CVAR_ARCHIVE,
Cvar_Limiter_ZeroToOne_Callback);
@ -207,13 +209,13 @@ cvar_t scr_conspeed = CVAR ("scr_conspeed", "2000");
cvar_t scr_fov = CVARFDC("fov", "90",
CVAR_ARCHIVE, "field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108.",
SCR_Fov_Callback);
cvar_t scr_printspeed = SCVAR ("scr_printspeed", "16");
cvar_t scr_showpause = SCVAR ("showpause", "1");
cvar_t scr_showturtle = SCVAR ("showturtle", "0");
cvar_t scr_turtlefps = SCVAR ("scr_turtlefps", "10");
cvar_t scr_sshot_compression = SCVAR ("scr_sshot_compression", "75");
cvar_t scr_sshot_type = SCVAR ("scr_sshot_type", "png");
cvar_t scr_sshot_prefix = SCVAR ("scr_sshot_prefix", "screenshots/fte-");
cvar_t scr_printspeed = CVAR ("scr_printspeed", "16");
cvar_t scr_showpause = CVAR ("showpause", "1");
cvar_t scr_showturtle = CVAR ("showturtle", "0");
cvar_t scr_turtlefps = CVAR ("scr_turtlefps", "10");
cvar_t scr_sshot_compression = CVAR ("scr_sshot_compression", "75");
cvar_t scr_sshot_type = CVAR ("scr_sshot_type", "png");
cvar_t scr_sshot_prefix = CVAR ("scr_sshot_prefix", "screenshots/fte-");
cvar_t scr_viewsize = CVARFC("viewsize", "100",
CVAR_ARCHIVE,
SCR_Viewsize_Callback);
@ -278,7 +280,7 @@ extern cvar_t r_drawworld;
extern cvar_t r_fullbright;
cvar_t r_mirroralpha = CVARFD("r_mirroralpha","1", CVAR_CHEAT|CVAR_SHADERSYSTEM, "Specifies how the default shader is generated for the 'window02_1' texture. Values less than 1 will turn it into a mirror.");
extern cvar_t r_netgraph;
cvar_t r_norefresh = SCVAR("r_norefresh","0");
cvar_t r_norefresh = CVAR("r_norefresh","0");
extern cvar_t r_novis;
extern cvar_t r_speeds;
extern cvar_t r_waterwarp;
@ -341,7 +343,7 @@ cvar_t gl_lateswap = CVAR ("gl_lateswap", "0");
cvar_t gl_lerpimages = CVARFD ("gl_lerpimages", "1", CVAR_ARCHIVE, "Enables smoother resampling for images which are not power-of-two, when the drivers do not support non-power-of-two textures.");
//cvar_t gl_lightmapmode = SCVARF("gl_lightmapmode", "",
// CVAR_ARCHIVE);
cvar_t gl_load24bit = SCVARF ("gl_load24bit", "1",
cvar_t gl_load24bit = CVARF ("gl_load24bit", "1",
CVAR_ARCHIVE);
cvar_t r_clear = CVARAF("r_clear","0",
@ -353,13 +355,13 @@ cvar_t gl_menutint_shader = CVARD ("gl_menutint_shader", "1", "Controls the
cvar_t gl_mindist = CVARAD ("gl_mindist", "1", "r_nearclip",
"Distance to the near clip plane. Smaller values may damage depth precision, high values can potentialy be used to see through walls...");
cvar_t gl_motionblur = SCVARF ("gl_motionblur", "0",
cvar_t gl_motionblur = CVARF ("gl_motionblur", "0",
CVAR_ARCHIVE);
cvar_t gl_motionblurscale = SCVAR ("gl_motionblurscale", "1");
cvar_t gl_motionblurscale = CVAR ("gl_motionblurscale", "1");
cvar_t gl_overbright = CVARFC ("gl_overbright", "1",
CVAR_ARCHIVE,
Surf_RebuildLightmap_Callback);
cvar_t gl_overbright_all = SCVARF ("gl_overbright_all", "0",
cvar_t gl_overbright_all = CVARF ("gl_overbright_all", "0",
CVAR_ARCHIVE);
cvar_t gl_picmip = CVARFD ("gl_picmip", "0", CVAR_ARCHIVE, "Reduce world/model texture sizes by some exponential factor.");
cvar_t gl_picmip2d = CVARFD ("gl_picmip2d", "0", CVAR_ARCHIVE, "Reduce hud/menu texture sizes by some exponential factor.");
@ -367,7 +369,7 @@ cvar_t gl_nohwblend = CVARD ("gl_nohwblend","1", "If 1, don't use hardwar
cvar_t gl_savecompressedtex = CVARD ("gl_savecompressedtex", "0", "Write out a copy of textures in a compressed format. The driver will do the compression on the fly, thus this setting is likely inferior to software which does not care so much about compression times.");
//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 = SCVAR ("gl_smoothcrosshair", "1");
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.");
#ifdef SPECULAR
@ -395,8 +397,8 @@ cvar_t vid_triplebuffer = CVARAFD ("vid_triplebuffer", "1", "gl_triplebuffe
cvar_t r_portalrecursion = CVARD ("r_portalrecursion", "1", "The number of portals the camera is allowed to recurse through.");
cvar_t r_portaldrawplanes = CVARD ("r_portaldrawplanes", "0", "Draw front and back planes in portals. Debug feature.");
cvar_t r_portalonly = CVARD ("r_portalonly", "0", "Don't draw things which are not portals. Debug feature.");
cvar_t dpcompat_psa_ungroup = SCVAR ("dpcompat_psa_ungroup", "0");
cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE);
cvar_t dpcompat_psa_ungroup = CVAR ("dpcompat_psa_ungroup", "0");
cvar_t r_noaliasshadows = CVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE);
cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blob shadows underneath entities without using realtime lighting.");
cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground.");
cvar_t r_showfields = CVARD("r_showfields", "0", "Debugging. Shows entity fields boxes (entity closest to crosshair). 1=ssqc, 2=csqc.");
@ -431,7 +433,7 @@ cvar_t vid_desktopgamma = CVARFD ("vid_desktopgamma", "0",
cvar_t r_fog_exp2 = CVARD ("r_fog_exp2", "1", "Expresses how fog fades with distance. 0 (matching DarkPlaces's default) is typically more realistic, while 1 (matching FitzQuake and others) is more common.");
extern cvar_t gl_dither;
cvar_t gl_screenangle = SCVAR("gl_screenangle", "0");
cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
#endif
#ifdef VKQUAKE
@ -885,6 +887,7 @@ void Renderer_Init(void)
Cvar_Register (&gl_mipcap, GLRENDEREROPTIONS);
Cvar_Register (&gl_texture_anisotropic_filtering, GLRENDEREROPTIONS);
Cvar_Register (&r_drawflat, GRAPHICALNICETIES);
Cvar_Register (&r_lightmap, GRAPHICALNICETIES);
Cvar_Register (&r_menutint, GRAPHICALNICETIES);
Cvar_Register (&r_fb_bmodels, GRAPHICALNICETIES);

View File

@ -37,7 +37,7 @@ cvar_t scr_scoreboard_showflags = CVARD("scr_scoreboard_showflags", "2", "Displa
cvar_t scr_scoreboard_fillalpha = CVARD("scr_scoreboard_fillalpha", "0.7", "Transparency amount for newstyle scoreboard.");
cvar_t scr_scoreboard_teamscores = CVARD("scr_scoreboard_teamscores", "1", "Makes +showscores act as +showteamscores. Because reasons.");
cvar_t scr_scoreboard_teamsort = CVARD("scr_scoreboard_teamsort", "0", "On the scoreboard, sort players by their team BEFORE their personal score.");
cvar_t scr_scoreboard_titleseperator = SCVAR("scr_scoreboard_titleseperator", "1");
cvar_t scr_scoreboard_titleseperator = CVAR("scr_scoreboard_titleseperator", "1");
cvar_t sbar_teamstatus = CVARD("sbar_teamstatus", "1", "Display the last team say from each of your team members just above the sbar area.");
//===========================================
@ -3426,7 +3426,7 @@ void Sbar_DeathmatchOverlay (int start)
}
x = startx;
#define COLUMN(title, width, code, fill) if (showcolumns & (1<<COLUMN##title)) {Draw_FunString(x, y, #title); x += width+8;}
#define COLUMN(title, width, code, fill) if (width && (showcolumns & (1<<COLUMN##title))) {Draw_FunString(x, y, #title); x += width+8;}
ALLCOLUMNS
#undef COLUMN

View File

@ -21,8 +21,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "glquake.h"
cvar_t baseskin = SCVAR("baseskin", "");
cvar_t noskins = SCVAR("noskins", "0");
cvar_t baseskin = CVAR("baseskin", "");
cvar_t noskins = CVAR("noskins", "0");
extern cvar_t cl_teamskin;
extern cvar_t cl_enemyskin;

View File

@ -928,8 +928,8 @@ int *debug;
HHOOK llkeyboardhook;
cvar_t sys_disableWinKeys = SCVAR("sys_disableWinKeys", "0");
cvar_t sys_disableTaskSwitch = SCVARF("sys_disableTaskSwitch", "0", CVAR_NOTFROMSERVER); // please don't encourage people to use this...
cvar_t sys_disableWinKeys = CVAR("sys_disableWinKeys", "0");
cvar_t sys_disableTaskSwitch = CVARF("sys_disableTaskSwitch", "0", CVAR_NOTFROMSERVER); // please don't encourage people to use this...
LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam)
{

View File

@ -20,16 +20,16 @@ static void QDECL rulesetcallback(cvar_t *var, char *oldval)
Validation_Apply_Ruleset();
}
cvar_t allow_f_version = SCVAR("allow_f_version", "1");
cvar_t allow_f_server = SCVAR("allow_f_server", "1");
cvar_t allow_f_modified = SCVAR("allow_f_modified", "1");
cvar_t allow_f_skins = SCVAR("allow_f_skins", "1");
cvar_t allow_f_ruleset = SCVAR("allow_f_ruleset", "1");
cvar_t allow_f_scripts = SCVAR("allow_f_scripts", "1");
cvar_t allow_f_fakeshaft = SCVAR("allow_f_fakeshaft", "1");
cvar_t allow_f_system = SCVAR("allow_f_system", "0");
cvar_t allow_f_cmdline = SCVAR("allow_f_cmdline", "0");
cvar_t auth_validateclients = SCVAR("auth_validateclients", "1");
cvar_t allow_f_version = CVAR("allow_f_version", "1");
cvar_t allow_f_server = CVAR("allow_f_server", "1");
cvar_t allow_f_modified = CVAR("allow_f_modified", "1");
cvar_t allow_f_skins = CVAR("allow_f_skins", "1");
cvar_t allow_f_ruleset = CVAR("allow_f_ruleset", "1");
cvar_t allow_f_scripts = CVAR("allow_f_scripts", "1");
cvar_t allow_f_fakeshaft = CVAR("allow_f_fakeshaft", "1");
cvar_t allow_f_system = CVAR("allow_f_system", "0");
cvar_t allow_f_cmdline = CVAR("allow_f_cmdline", "0");
cvar_t auth_validateclients = CVAR("auth_validateclients", "1");
cvar_t ruleset = CVARC("ruleset", "none", rulesetcallback);
@ -82,7 +82,7 @@ static void Validation_Version(void)
else if (r_shadow_realtime_dlight.ival)
*s++ = 'S';
#endif
if (r_drawflat.ival)
if (r_drawflat.ival || r_lightmap.ival)
*s++ = 'F';
if (gl_load24bit.ival)
*s++ = 'H';

View File

@ -44,62 +44,62 @@ when crossing a water boudnary.
*/
#ifdef SIDEVIEWS
cvar_t vsec_enabled[SIDEVIEWS] = {SCVAR("v2_enabled", "2"), SCVAR("v3_enabled", "0"), SCVAR("v4_enabled", "0"), SCVAR("v5_enabled", "0")};
cvar_t vsec_x[SIDEVIEWS] = {SCVAR("v2_x", "0"), SCVAR("v3_x", "0.25"), SCVAR("v4_x", "0.5"), SCVAR("v5_x", "0.75")};
cvar_t vsec_y[SIDEVIEWS] = {SCVAR("v2_y", "0"), SCVAR("v3_y", "0"), SCVAR("v4_y", "0"), SCVAR("v5_y", "0")};
cvar_t vsec_scalex[SIDEVIEWS] = {SCVAR("v2_scalex", "0.25"), SCVAR("v3_scalex", "0.25"), SCVAR("v4_scalex", "0.25"), SCVAR("v5_scalex", "0.25")};
cvar_t vsec_scaley[SIDEVIEWS] = {SCVAR("v2_scaley", "0.25"), SCVAR("v3_scaley", "0.25"), SCVAR("v4_scaley", "0.25"), SCVAR("v5_scaley", "0.25")};
cvar_t vsec_yaw[SIDEVIEWS] = {SCVAR("v2_yaw", "180"), SCVAR("v3_yaw", "90"), SCVAR("v4_yaw", "270"), SCVAR("v5_yaw", "0")};
cvar_t vsec_enabled[SIDEVIEWS] = {CVAR("v2_enabled", "2"), CVAR("v3_enabled", "0"), CVAR("v4_enabled", "0"), CVAR("v5_enabled", "0")};
cvar_t vsec_x[SIDEVIEWS] = {CVAR("v2_x", "0"), CVAR("v3_x", "0.25"), CVAR("v4_x", "0.5"), CVAR("v5_x", "0.75")};
cvar_t vsec_y[SIDEVIEWS] = {CVAR("v2_y", "0"), CVAR("v3_y", "0"), CVAR("v4_y", "0"), CVAR("v5_y", "0")};
cvar_t vsec_scalex[SIDEVIEWS] = {CVAR("v2_scalex", "0.25"), CVAR("v3_scalex", "0.25"), CVAR("v4_scalex", "0.25"), CVAR("v5_scalex", "0.25")};
cvar_t vsec_scaley[SIDEVIEWS] = {CVAR("v2_scaley", "0.25"), CVAR("v3_scaley", "0.25"), CVAR("v4_scaley", "0.25"), CVAR("v5_scaley", "0.25")};
cvar_t vsec_yaw[SIDEVIEWS] = {CVAR("v2_yaw", "180"), CVAR("v3_yaw", "90"), CVAR("v4_yaw", "270"), CVAR("v5_yaw", "0")};
#endif
cvar_t cl_rollspeed = SCVAR("cl_rollspeed", "200");
cvar_t cl_rollangle = SCVAR("cl_rollangle", "2.0");
cvar_t v_deathtilt = SCVAR("v_deathtilt", "1");
cvar_t cl_rollspeed = CVAR("cl_rollspeed", "200");
cvar_t cl_rollangle = CVAR("cl_rollangle", "2.0");
cvar_t v_deathtilt = CVAR("v_deathtilt", "1");
cvar_t cl_bob = SCVAR("cl_bob","0.02");
cvar_t cl_bobcycle = SCVAR("cl_bobcycle","0.6");
cvar_t cl_bobup = SCVAR("cl_bobup","0.5");
cvar_t cl_bob = CVAR("cl_bob","0.02");
cvar_t cl_bobcycle = CVAR("cl_bobcycle","0.6");
cvar_t cl_bobup = CVAR("cl_bobup","0.5");
cvar_t v_kicktime = SCVAR("v_kicktime", "0.5");
cvar_t v_kickroll = SCVAR("v_kickroll", "0.6");
cvar_t v_kickpitch = SCVAR("v_kickpitch", "0.6");
cvar_t v_kicktime = CVAR("v_kicktime", "0.5");
cvar_t v_kickroll = CVAR("v_kickroll", "0.6");
cvar_t v_kickpitch = CVAR("v_kickpitch", "0.6");
cvar_t v_iyaw_cycle = SCVAR("v_iyaw_cycle", "2");
cvar_t v_iroll_cycle = SCVAR("v_iroll_cycle", "0.5");
cvar_t v_ipitch_cycle = SCVAR("v_ipitch_cycle", "1");
cvar_t v_iyaw_level = SCVAR("v_iyaw_level", "0.3");
cvar_t v_iroll_level = SCVAR("v_iroll_level", "0.1");
cvar_t v_ipitch_level = SCVAR("v_ipitch_level", "0.3");
cvar_t v_idlescale = SCVAR("v_idlescale", "0");
cvar_t v_iyaw_cycle = CVAR("v_iyaw_cycle", "2");
cvar_t v_iroll_cycle = CVAR("v_iroll_cycle", "0.5");
cvar_t v_ipitch_cycle = CVAR("v_ipitch_cycle", "1");
cvar_t v_iyaw_level = CVAR("v_iyaw_level", "0.3");
cvar_t v_iroll_level = CVAR("v_iroll_level", "0.1");
cvar_t v_ipitch_level = CVAR("v_ipitch_level", "0.3");
cvar_t v_idlescale = CVAR("v_idlescale", "0");
cvar_t crosshair = SCVARF("crosshair", "1", CVAR_ARCHIVE);
cvar_t crosshaircolor = SCVARF("crosshaircolor", "255 255 255", CVAR_ARCHIVE);
cvar_t crosshairsize = SCVARF("crosshairsize", "8", CVAR_ARCHIVE);
cvar_t crosshair = CVARF("crosshair", "1", CVAR_ARCHIVE);
cvar_t crosshaircolor = CVARF("crosshaircolor", "255 255 255", CVAR_ARCHIVE);
cvar_t crosshairsize = CVARF("crosshairsize", "8", CVAR_ARCHIVE);
cvar_t cl_crossx = SCVARF("cl_crossx", "0", CVAR_ARCHIVE);
cvar_t cl_crossy = SCVARF("cl_crossy", "0", CVAR_ARCHIVE);
cvar_t crosshaircorrect = SCVARF("crosshaircorrect", "0", CVAR_SEMICHEAT);
cvar_t crosshairimage = SCVAR("crosshairimage", "");
cvar_t crosshairalpha = SCVAR("crosshairalpha", "1");
cvar_t cl_crossx = CVARF("cl_crossx", "0", CVAR_ARCHIVE);
cvar_t cl_crossy = CVARF("cl_crossy", "0", CVAR_ARCHIVE);
cvar_t crosshaircorrect = CVARF("crosshaircorrect", "0", CVAR_SEMICHEAT);
cvar_t crosshairimage = CVAR("crosshairimage", "");
cvar_t crosshairalpha = CVAR("crosshairalpha", "1");
cvar_t gl_cshiftpercent = SCVAR("gl_cshiftpercent", "100");
cvar_t gl_cshiftenabled = CVARF("gl_polyblend", "1", CVAR_ARCHIVE);
cvar_t gl_cshiftpercent = CVAR("gl_cshiftpercent", "100");
cvar_t gl_cshiftenabled = CVARF("gl_polyblend", "1", CVAR_ARCHIVE);
cvar_t v_bonusflash = SCVAR("v_bonusflash", "1");
cvar_t v_bonusflash = CVAR("v_bonusflash", "1");
cvar_t v_contentblend = SCVARF("v_contentblend", "1", CVAR_ARCHIVE);
cvar_t v_damagecshift = SCVAR("v_damagecshift", "1");
cvar_t v_quadcshift = SCVAR("v_quadcshift", "1");
cvar_t v_suitcshift = SCVAR("v_suitcshift", "1");
cvar_t v_ringcshift = SCVAR("v_ringcshift", "1");
cvar_t v_pentcshift = SCVAR("v_pentcshift", "1");
cvar_t v_gunkick = SCVAR("v_gunkick", "0");
cvar_t v_gunkick_q2 = SCVAR("v_gunkick_q2", "1");
cvar_t v_contentblend = CVARF("v_contentblend", "1", CVAR_ARCHIVE);
cvar_t v_damagecshift = CVAR("v_damagecshift", "1");
cvar_t v_quadcshift = CVAR("v_quadcshift", "1");
cvar_t v_suitcshift = CVAR("v_suitcshift", "1");
cvar_t v_ringcshift = CVAR("v_ringcshift", "1");
cvar_t v_pentcshift = CVAR("v_pentcshift", "1");
cvar_t v_gunkick = CVAR("v_gunkick", "0");
cvar_t v_gunkick_q2 = CVAR("v_gunkick_q2", "1");
cvar_t v_viewheight = SCVAR("v_viewheight", "0");
cvar_t v_projectionmode = SCVAR("v_projectionmode", "0");
cvar_t v_viewheight = CVAR("v_viewheight", "0");
cvar_t v_projectionmode = CVAR("v_projectionmode", "0");
cvar_t v_depthsortentities = CVARAD("v_depthsortentities", "0", "v_reorderentitiesrandomly", "Reorder entities for transparency such that the furthest entities are drawn first, allowing nearer transparent entities to draw over the top of them.");
cvar_t v_depthsortentities = CVARAD("v_depthsortentities", "0", "v_reorderentitiesrandomly", "Reorder entities for transparency such that the furthest entities are drawn first, allowing nearer transparent entities to draw over the top of them.");
cvar_t scr_autoid = CVARD("scr_autoid", "1", "Display nametags above all players while spectating.");
cvar_t scr_autoid_team = CVARD("scr_autoid_team", "1", "Display nametags above team members. 0: off. 1: display with half-alpha if occluded. 2: hide when occluded.");
@ -109,9 +109,9 @@ cvar_t scr_autoid_weapon = CVARD("scr_autoid_weapon", "1", "Display the player'
cvar_t scr_autoid_teamcolour = CVARD("scr_autoid_teamcolour", STRINGIFY(COLOR_BLUE), "The colour for the text on the nametags of team members.");
cvar_t scr_autoid_enemycolour = CVARD("scr_autoid_enemycolour", STRINGIFY(COLOR_WHITE), "The colour for the text on the nametags of non-team members.");
cvar_t chase_active = CVAR("chase_active", "0");
cvar_t chase_back = CVAR("chase_back", "48");
cvar_t chase_up = CVAR("chase_up", "24");
cvar_t chase_active = CVAR("chase_active", "0");
cvar_t chase_back = CVAR("chase_back", "48");
cvar_t chase_up = CVAR("chase_up", "24");
extern cvar_t cl_chasecam;
@ -197,8 +197,8 @@ float V_CalcBob (playerview_t *pv, qboolean queryold)
//=============================================================================
cvar_t v_centermove = SCVAR("v_centermove", "0.15");
cvar_t v_centerspeed = SCVAR("v_centerspeed","500");
cvar_t v_centermove = CVAR("v_centermove", "0.15");
cvar_t v_centerspeed = CVAR("v_centerspeed","500");
void V_StartPitchDrift (playerview_t *pv)

View File

@ -22,10 +22,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "fs.h"
cvar_t ruleset_allow_in = SCVAR("ruleset_allow_in", "1");
cvar_t rcon_level = SCVAR("rcon_level", "20");
cvar_t cmd_maxbuffersize = SCVAR("cmd_maxbuffersize", "65536");
cvar_t dpcompat_set = SCVAR("dpcompat_set", "0");
cvar_t ruleset_allow_in = CVAR("ruleset_allow_in", "1");
cvar_t rcon_level = CVAR("rcon_level", "20");
cvar_t cmd_maxbuffersize = CVAR("cmd_maxbuffersize", "65536");
cvar_t dpcompat_set = CVAR("dpcompat_set", "0");
int Cmd_ExecLevel;
qboolean cmd_didwait;
qboolean cmd_blockwait;
@ -2614,28 +2614,33 @@ static const char *If_Token_Term(const char *func, const char **end)
}
else if (*com_token == '!')
{
func = If_Token(s, end, 0);
func = If_Token(s, &s, 0);
s2 = retbool(!is_true(func));
}
else if (*com_token == '~')
{
func = If_Token(s, end, 0);
func = If_Token(s, &s, 0);
s2 = retbool(~atoi(func));
}
else if (*com_token == '-')
{
func = If_Token(s, &s, 0);
s2 = retfloat(-atof(func));
}
else if (!strcmp(com_token, "int"))
{
func = If_Token(s, end, 0);
func = If_Token(s, &s, 0);
s2 = retint(atoi(func));
}
else if (!strcmp(com_token, "strlen"))
{
func = If_Token(s, end, 0);
func = If_Token(s, &s, 0);
s2 = retfloat(strlen(func));
}
else if (!strcmp(com_token, "eval"))
{
//read the stuff to the right
func = If_Token(s, end, IF_PRI_MAX);
func = If_Token(s, &s, IF_PRI_MAX);
//and evaluate it
s2 = If_Token(func, &func, IF_PRI_MAX);
}
@ -2824,19 +2829,22 @@ static const char *If_Token(const char *func, const char **end, int pri)
s2 = If_Token_Term(func, &s);
*end = s;
while (*s == ' ' || *s == '\t')
s++;
for (i = 0; i < countof(ifops); i++)
if (s)
{
if (!strncmp(s, ifops[i].opname, ifops[i].opnamelen))
while (*s == ' ' || *s == '\t')
s++;
for (i = 0; i < countof(ifops); i++)
{
if (pri == ifops[i].pri)
if (!strncmp(s, ifops[i].opname, ifops[i].opnamelen))
{
s = If_Token(s + ifops[i].opnamelen, end, pri);
s2 = If_Operator(ifops[i].op, s2, s);
if (pri == ifops[i].pri)
{
s = If_Token(s + ifops[i].opnamelen, end, pri);
s2 = If_Operator(ifops[i].op, s2, s);
}
break;
}
break;
}
}
return s2;

View File

@ -25,6 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <ctype.h>
#include <errno.h>
//by adding 'extern' to one definition of a function in a translation unit, then the definition in that TU is NOT considered an inline definition. meaning non-inlined references in other TUs can link to it instead of their own if needed.
fte_inlinebody conchar_t *Font_Decode(conchar_t *start, unsigned int *codeflags, unsigned int *codepoint);
// These 4 libraries required for the version command
#if defined(MINGW)

View File

@ -103,8 +103,6 @@ typedef struct cvar_s
#define CVARD(ConsoleName,Value,Description) CVARAFDC(ConsoleName, Value, NULL, 0, Description, NULL)
#define CVAR(ConsoleName,Value) CVARD(ConsoleName, Value, NULL)
#define SCVAR(ConsoleName,Value) CVAR(ConsoleName,Value)
#define SCVARF(ConsoleName,Value,Flags) CVARF(ConsoleName,Value,Flags)
#define CVARDP4(Flags,ConsoleName,Value,Description) CVARFD(ConsoleName, Value, Flags,Description)
typedef struct cvar_group_s

View File

@ -386,10 +386,10 @@ typedef struct cminfo_s
static q2mapsurface_t nullsurface;
cvar_t map_noareas = SCVAR("map_noareas", "0"); //1 for lack of mod support.
cvar_t map_noCurves = SCVARF("map_noCurves", "0", CVAR_CHEAT);
cvar_t map_noareas = CVAR("map_noareas", "0"); //1 for lack of mod support.
cvar_t map_noCurves = CVARF("map_noCurves", "0", CVAR_CHEAT);
cvar_t map_autoopenportals = CVARD("map_autoopenportals", "0", "When set to 1, force-opens all area portals. Normally these start closed and are opened by doors when they move, but this requires the gamecode to signal this."); //1 for lack of mod support.
cvar_t r_subdivisions = SCVAR("r_subdivisions", "2");
cvar_t r_subdivisions = CVAR("r_subdivisions", "2");
static int CM_NumInlineModels (model_t *model);
static cmodel_t *CM_InlineModel (model_t *model, char *name);

View File

@ -81,8 +81,8 @@ fragmentation works like IP, offset and morefrags. offset is *8 (decode: (offset
*/
int net_drop;
cvar_t showpackets = SCVAR("showpackets", "0");
cvar_t showdrop = SCVAR("showdrop", "0");
cvar_t showpackets = CVAR("showpackets", "0");
cvar_t showdrop = CVAR("showdrop", "0");
cvar_t qport = CVARF("qport_", "0", CVAR_NOSAVE);
cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets.");

View File

@ -2785,6 +2785,19 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(neterrno()));
//ipv6 sockets need to add themselves to a multicast group, so that we can receive broadcasts on a lan
#if defined(IPPROTO_IPV6)
if (family == AF_INET6 || hybrid || isserver)
{
struct ipv6_mreq req;
memset(&req, 0, sizeof(req));
req.ipv6mr_multiaddr.s6_addr[0] = 0xff;
req.ipv6mr_multiaddr.s6_addr[1] = 0x02;
req.ipv6mr_multiaddr.s6_addr[15]= 0x01;
req.ipv6mr_interface = 0;
setsockopt(newsocket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&req, sizeof(req));
}
#endif
//
// determine my name & address if we don't already know it

View File

@ -201,6 +201,7 @@ struct model_s;
struct msurface_s;
void P_InitParticleSystem(void);
void P_ShutdownParticleSystem(void);
void P_Shutdown(void);
void P_LoadedModel(struct model_s *mod); /*checks a model's various effects*/
void P_DefaultTrail (unsigned int entityeffects, unsigned int modelflags, int *trailid, int *trailpalidx);

View File

@ -13,7 +13,7 @@
#ifdef PLUGINS
cvar_t plug_sbar = CVARD("plug_sbar", "3", "Controls whether plugins are allowed to draw the hud, rather than the engine (when allowed by csqc). This is typically used to permit the ezhud plugin without needing to bother unloading it.\n=0: never use hud plugins.\n&1: Use hud plugins in deathmatch.\n&2: Use hud plugins in singleplayer/coop.\n=3: Always use hud plugins (when loaded).");
cvar_t plug_loaddefault = SCVAR("plug_loaddefault", "1");
cvar_t plug_loaddefault = CVAR("plug_loaddefault", "1");
qintptr_t Plug_Bullet_Init(qintptr_t *args);
qintptr_t Plug_ODE_Init(qintptr_t *args);

View File

@ -1337,7 +1337,7 @@ void Shader_LightPass(const char *shortname, shader_t *s, const void *args)
{
char shadertext[8192*2];
extern cvar_t r_drawflat;
sprintf(shadertext, LIGHTPASS_SHADER, r_drawflat.ival?"#FLAT":"");
sprintf(shadertext, LIGHTPASS_SHADER, (r_lightmap.ival||r_drawflat.ival)?"#FLAT":"");
Shader_DefaultScript(shortname, s, shadertext);
}

View File

@ -31,10 +31,6 @@ struct font_s *font_tiny;
static int font_be_flags;
extern unsigned int r2d_be_flags;
//by adding 'extern' to one definition of a function in a translation unit, then the definition in that TU is NOT considered an inline definition. meaning non-inlined references in other TUs can link to it instead of their own if needed.
fte_inlinebody conchar_t *Font_Decode(conchar_t *start, unsigned int *codeflags, unsigned int *codepoint);
#ifdef AVAIL_FREETYPE
#include <ft2build.h>
#include FT_FREETYPE_H

View File

@ -53,9 +53,9 @@ extern cvar_t gl_part_flame;
extern cvar_t r_bloom;
extern cvar_t r_wireframe_smooth;
cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0");
cvar_t gl_finish = SCVAR("gl_finish","0");
cvar_t gl_dither = SCVAR("gl_dither", "1");
cvar_t gl_affinemodels = CVAR("gl_affinemodels","0");
cvar_t gl_finish = CVAR("gl_finish","0");
cvar_t gl_dither = CVAR("gl_dither", "1");
extern cvar_t r_stereo_separation;
extern cvar_t r_stereo_convergence;
extern cvar_t r_stereo_method;
@ -80,7 +80,7 @@ extern cvar_t r_portaldrawplanes;
extern cvar_t r_portalonly;
#ifdef R_XFLIP
cvar_t r_xflip = SCVAR("leftisright", "0");
cvar_t r_xflip = CVAR("leftisright", "0");
#endif
extern cvar_t scr_fov;

View File

@ -4985,6 +4985,19 @@ void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args)
char *builtin = NULL;
if (Shader_ParseShader("defaultwall", s))
return;
if (!builtin && r_lightmap.ival)
builtin = (
"{\n"
"program drawflat_wall\n"
"{\n"
"map $lightmap\n"
"tcgen lightmap\n"
"rgbgen const 255 255 255\n"
"}\n"
"}\n"
);
if (!builtin && r_drawflat.ival)
builtin = (
"{\n"

View File

@ -786,17 +786,18 @@ static void GL_DrawSkyBox (texid_t *texnums, batch_t *s)
=============
R_InitSky
A sky texture is 256*128, with the right side being a masked overlay
A sky image is 256*128 and comprises two logical textures.
the left is the transparent/blended part. the right is the opaque/background part.
==============
*/
void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int width, unsigned int height)
{
int i, j, p;
unsigned trans[128*128];
unsigned *temp;
unsigned transpix, alphamask;
int r, g, b;
unsigned *rgba;
char name[MAX_QPATH];
char name[MAX_QPATH*2];
unsigned int stride = width;
width /= 2;
@ -804,15 +805,64 @@ void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int
if (width < 1 || height < 1 || stride != width*2 || !src)
return;
if (width*height > countof(trans))
//try to load dual-layer-single-image skies.
//this is always going to be lame special case crap
{
unsigned int wibuf[16] = {0};
shader->defaulttextures->base = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
shader->defaulttextures->base = R_LoadReplacementTexture(skyname, NULL, 0, src, stride, height, TF_SOLID8);
shader->defaulttextures->fullbright = shader->defaulttextures->base;
return;
size_t filesize = 0;
qbyte *filedata = NULL;
if (!filedata)
{
Q_snprintfz(name, sizeof(name), "textures/%s.tga", skyname);
filedata = FS_LoadMallocFile(name, &filesize);
}
if (!filedata)
{
Q_snprintfz(name, sizeof(name), "textures/%s.png", skyname);
filedata = FS_LoadMallocFile(name, &filesize);
}
if (filedata)
{
int imagewidth, imageheight;
qboolean hasalpha; //fixme, if this is false, is it worth all this code?
unsigned int *imagedata = (unsigned int*)Read32BitImageFile(filedata, filesize, &imagewidth, &imageheight, &hasalpha, name);
Z_Free(filedata);
if (imagedata && !(imagewidth&1))
{
imagewidth>>=1;
temp = BZF_Malloc(imagewidth*imageheight*sizeof(*temp));
if (temp)
{
for (i=0 ; i<height ; i++)
for (j=0 ; j<width ; j++)
{
temp[i*width+j] = imagedata[i*(width<<1)+j+width];
}
Q_snprintfz(name, sizeof(name), "%s_solid", skyname);
Q_strlwr(name);
shader->defaulttextures->base = R_LoadReplacementTexture(name, NULL, IF_NOALPHA, temp, imagewidth, imageheight, TF_RGBX32);
for (i=0 ; i<height ; i++)
for (j=0 ; j<width ; j++)
{
temp[i*width+j] = imagedata[i*(width<<1)+j];
}
BZ_Free(imagedata);
Q_snprintfz(name, sizeof(name), "%s_alpha:%s_trans", skyname, skyname);
Q_strlwr(name);
shader->defaulttextures->fullbright = R_LoadReplacementTexture(name, NULL, 0, temp, imagewidth, imageheight, TF_RGBA32);
BZ_Free(temp);
return;
}
}
BZ_Free(imagedata);
}
}
temp = BZ_Malloc(width*height*sizeof(*temp));
// make an average value for the back to avoid
// a fringe on the top level
@ -822,7 +872,7 @@ void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int
{
p = src[i*stride + j + width];
rgba = &d_8to24rgbtable[p];
trans[(i*width) + j] = *rgba;
temp[(i*width) + j] = *rgba;
r += ((qbyte *)rgba)[0];
g += ((qbyte *)rgba)[1];
b += ((qbyte *)rgba)[2];
@ -832,11 +882,12 @@ void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int
{
Q_snprintfz(name, sizeof(name), "%s_solid", skyname);
Q_strlwr(name);
shader->defaulttextures->base = R_LoadReplacementTexture(name, NULL, IF_NOALPHA, trans, width, height, TF_RGBX32);
shader->defaulttextures->base = R_LoadReplacementTexture(name, NULL, IF_NOALPHA, temp, width, height, TF_RGBX32);
}
if (!shader->defaulttextures->fullbright)
{
//fixme: use premultiplied alpha here.
((qbyte *)&transpix)[0] = r/(width*height);
((qbyte *)&transpix)[1] = g/(width*height);
((qbyte *)&transpix)[2] = b/(width*height);
@ -847,15 +898,16 @@ void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int
{
p = src[i*stride + j];
if (p == 0)
trans[(i*width) + j] = transpix;
temp[(i*width) + j] = transpix;
else
trans[(i*width) + j] = d_8to24rgbtable[p] & alphamask;
temp[(i*width) + j] = d_8to24rgbtable[p] & alphamask;
}
//FIXME: support _trans
Q_snprintfz(name, sizeof(name), "%s_alpha", skyname);
Q_snprintfz(name, sizeof(name), "%s_alpha:%s_trans", skyname, skyname);
Q_strlwr(name);
shader->defaulttextures->fullbright = R_LoadReplacementTexture(name, NULL, 0, trans, width, height, TF_RGBA32);
shader->defaulttextures->fullbright = R_LoadReplacementTexture(name, NULL, 0, temp, width, height, TF_RGBA32);
}
BZ_Free(temp);
}
#endif

View File

@ -373,13 +373,13 @@ IWEBFILE *IWebFOpenRead(char *name) //fread(name, "rb");
#else
#ifndef CLIENTONLY
cvar_t ftpserver = SCVAR("sv_ftp", "0");
cvar_t ftpserver_port = SCVAR("sv_ftp_port", "21");
cvar_t httpserver = SCVAR("sv_http", "0");
cvar_t httpserver_port = SCVAR("sv_http_port", "80");
cvar_t sv_readlevel = SCVAR("sv_readlevel", "0"); //default to allow anyone
cvar_t sv_writelevel = SCVAR("sv_writelevel", "35"); //allowed to write to uploads/uname
cvar_t sv_fulllevel = SCVAR("sv_fulllevel", "51"); //allowed to write anywhere, replace any file...
cvar_t ftpserver = CVAR("sv_ftp", "0");
cvar_t ftpserver_port = CVAR("sv_ftp_port", "21");
cvar_t httpserver = CVAR("sv_http", "0");
cvar_t httpserver_port = CVAR("sv_http_port", "80");
cvar_t sv_readlevel = CVAR("sv_readlevel", "0"); //default to allow anyone
cvar_t sv_writelevel = CVAR("sv_writelevel", "35"); //allowed to write to uploads/uname
cvar_t sv_fulllevel = CVAR("sv_fulllevel", "51"); //allowed to write anywhere, replace any file...
#endif
//this file contains functions called from each side.

View File

@ -76,7 +76,7 @@ int CheckParm (char *check);
int SafeOpenWrite (char *filename, int maxsize);
int SafeOpenRead (char *filename);
void SafeRead (int handle, void *buffer, long count);
void SafeWrite (int handle, void *buffer, long count);
void SafeWrite (int handle, const void *buffer, long count);
pbool SafeClose(int hand);
int SafeSeek(int hand, int ofs, int mode);
void *SafeMalloc (long size);

View File

@ -242,7 +242,7 @@ int QC_strncasecmp(const char *s1, const char *s2, int n)
return -1;
}
void editbadfile(char *fname, int line)
void editbadfile(const char *fname, int line)
{
if (!*errorfile)
{

View File

@ -1,6 +1,6 @@
void GoToDefinition(char *name);
int Grep(char *filename, char *string);
void EditFile(char *name, int line, pbool setcontrol);
void EditFile(const char *name, int line, pbool setcontrol);
void GUI_SetDefaultOpts(void);
int GUI_BuildParms(char *args, char **argv, pbool quick);

View File

@ -594,8 +594,6 @@ typedef struct
} dprograms_t;
#define standard_dprograms_t_size ((size_t)&((dprograms_t*)NULL)->ofsfiles)
#endif
@ -623,3 +621,5 @@ typedef struct typeinfo_s
int size;
string_t name;
} typeinfo_t;
#endif

View File

@ -1,3 +1,6 @@
#ifndef PROGSINT_H_INCLUDED
#define PROGSINT_H_INCLUDED
#ifdef _WIN32
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
@ -518,3 +521,5 @@ char *QCC_COM_Parse (const char *data);
extern char qcc_token[1024];
extern char *basictypenames[];
#endif
#endif

View File

@ -377,17 +377,18 @@ 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 called)
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
struct QCC_def_s *symbolheader; //this is the original symbol within which the def is stored.
union QCC_eval_s *symboldata; //null if uninitialised.
union QCC_eval_s *symboldata; //null if uninitialised. use sym->symboldata[sym->ofs] to index.
unsigned int symbolsize; //total byte size of symbol
int refcount; //if 0, temp can be reused. tracked on globals too in order to catch bugs that would otherwise be a little too obscure.
int timescalled; //part of the opt_stripfunctions optimisation.
int s_file;
const char *filen;
int s_filed;
int s_line;
int arraysize;
@ -406,6 +407,8 @@ typedef struct QCC_def_s
pbool used:1; //if it remains 0, it may be stripped. this is forced for functions and fields. commonly 0 on fields.
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)
int fromstatement; //statement that it is valid from.
temp_t *temp;
@ -462,8 +465,9 @@ struct QCC_function_s
{
int builtin; // the builtin number. >= 0
int code; // first statement. if -1, is a builtin.
string_t s_file; // source file with definition
const char *file;
dfunction_t *merged; // this function was merged. this is the index to use to ensure that the parms are sized correctly..
string_t s_filed; // source file with definition
const char *filen;
int line;
char *name; //internal name of function
struct QCC_function_s *parentscope; //for nested functions
@ -568,6 +572,8 @@ extern pbool keyword_nosave; //don't write the def to the output.
extern pbool keyword_inline; //don't write the def to the output.
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_unused;
extern pbool keyword_used;
@ -885,6 +891,8 @@ extern compiler_flag_t compiler_flag[];
extern unsigned char qccwarningaction[WARN_MAX];
extern jmp_buf pr_parse_abort; // longjump with this on parse error
extern const char *s_filen; //name of the file we're currently compiling.
extern QCC_string_t s_filed; //name of the file we're currently compiling, as seen by whoever reads the .dat
extern int pr_source_line;
extern char *pr_file_p;
@ -906,16 +914,18 @@ extern int pr_error_count, pr_warning_count;
void QCC_PR_NewLine (pbool incomment);
#define GDF_NONE 0
#define GDF_SAVED 1
#define GDF_STATIC 2
#define GDF_CONST 4
#define GDF_STRIP 8 //always stripped, regardless of optimisations. used for class member fields
#define GDF_SILENT 16 //used by the gui, to suppress ALL warnings associated with querying the def.
#define GDF_INLINE 32 //attempt to inline calls to this function
#define GDF_USED 64 //don't strip this, ever.
#define GDF_SAVED 1
#define GDF_STATIC 2
#define GDF_CONST 4
#define GDF_STRIP 8 //always stripped, regardless of optimisations. used for class member fields
#define GDF_SILENT 16 //used by the gui, to suppress ALL warnings associated with querying the def.
#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);
void QCC_FreeTemp(QCC_sref_t t);
void QCC_FreeDef(QCC_def_t *def);
char *QCC_PR_CheckCompConstTooltip(char *word, char *outstart, char *outend);
void QCC_PR_PrintDefs (void);
@ -940,8 +950,6 @@ void QCC_PR_ResetErrorScope(void);
extern pbool pr_dumpasm;
extern QCC_string_t s_file; // filename for function definition
extern QCC_def_t def_ret, def_parms[MAX_PARMS];
void QCC_PR_EmitArrayGetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char *arrayname);
@ -1006,7 +1014,7 @@ typedef struct
int block;
int used;
int fileline;
char *filename;
const char *filename;
} precache_t;
extern precache_t *precache_sound;
extern int numsounds;
@ -1060,7 +1068,7 @@ static bool inline QCC_PR_CheckToken (char *string)
return true;
}
static void inline QCC_PR_Expect (char *string)
static void inline QCC_PR_Expect (const char *string)
{
if (strcmp (string, pr_token))
QCC_PR_ParseError ("expected %s, found %s",string, pr_token);
@ -1068,12 +1076,13 @@ static void inline QCC_PR_Expect (char *string)
}
#endif
void editbadfile(char *fname, int line);
void editbadfile(const char *fname, int line);
char *TypeName(QCC_type_t *type, char *buffer, int buffersize);
void QCC_PR_AddIncludePath(const char *newinc);
void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename);
void QCC_PR_IncludeChunkEx(char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst);
void QCC_PR_CloseProcessor(void);
void QCC_FindBestInclude(char *newfile, char *currentfile, pbool verbose);
pbool QCC_PR_UnInclude(void);
extern void *(*pHash_Get)(hashtable_t *table, const char *name);
extern void *(*pHash_GetNext)(hashtable_t *table, const char *name, void *old);

View File

@ -568,7 +568,7 @@ void VARGS QCC_Error (int errortype, const char *error, ...)
printf ("\n************ ERROR ************\n%s\n", msg);
editbadfile(strings+s_file, pr_source_line);
editbadfile(s_filen, pr_source_line);
numsourcefiles = 0;
@ -890,7 +890,7 @@ void ResizeBuf(int hand, int newsize)
qccfile[hand].buff = nb;
qccfile[hand].buffsize = newsize;
}
void SafeWrite(int hand, void *buf, long count)
void SafeWrite(int hand, const void *buf, long count)
{
if (qccfile[hand].ofs +count >= qccfile[hand].buffsize)
ResizeBuf(hand, qccfile[hand].ofs + count+(64*1024));
@ -1242,6 +1242,7 @@ long QCC_LoadFile (char *filename, void **bufferptr)
mem += sizeof(qcc_cachedsourcefile_t);
externs->ReadFile(filename, mem, len+2, NULL);
mem[len] = 0;
mem = QCC_SanitizeCharSet(mem, &len, NULL, &orig);

View File

@ -78,6 +78,8 @@ pbool keyword_inline;
pbool keyword_strip;
pbool keyword_ignore;
pbool keyword_union; //you surly know what a union is!
pbool keyword_weak;
pbool keyword_wrap;
#define keyword_not 1 //hexenc support needs this, and fteqcc can optimise without it, but it adds an extra token after the if, so it can cause no namespace conflicts
@ -174,7 +176,7 @@ QCC_sref_t QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign, p
void QCC_Marshal_Locals(int firststatement, int laststatement);
QCC_sref_t QCC_PR_ParseArrayPointer (QCC_sref_t d, pbool allowarrayassign, pbool makestructpointers);
QCC_sref_t QCC_LoadFromArray(QCC_sref_t base, QCC_sref_t index, QCC_type_t *t, pbool preserve);
void QCC_PR_ParseInitializerDef(QCC_def_t *def);
void QCC_PR_ParseInitializerDef(QCC_def_t *def, unsigned int flags);
QCC_ref_t *QCC_DefToRef(QCC_ref_t *ref, QCC_sref_t def); //ref is a buffer to write into, to avoid excessive allocs
QCC_sref_t QCC_RefToDef(QCC_ref_t *ref, pbool freetemps);
@ -186,7 +188,7 @@ QCC_ref_t *QCC_PR_BuildAccessorRef(QCC_ref_t *retbuf, QCC_sref_t base, QCC_sref_
QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable, pbool preservedest);
QCC_sref_t QCC_StoreRefToRef(QCC_ref_t *dest, QCC_ref_t *source, pbool readable, pbool preservedest);
void QCC_PR_DiscardRef(QCC_ref_t *ref);
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *type);
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *type, pbool dowrap);
const char *QCC_VarAtOffset(QCC_sref_t ref, unsigned int size);
QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit);
@ -194,7 +196,7 @@ QCC_statement_t *QCC_Generate_OP_IFNOT(QCC_sref_t e, pbool preserve);
QCC_statement_t *QCC_Generate_OP_IF(QCC_sref_t e, pbool preserve);
QCC_statement_t *QCC_Generate_OP_GOTO(void);
QCC_sref_t QCC_PR_GenerateLogicalNot(QCC_sref_t e, const char *errormessage);
QCC_function_t *QCC_PR_GenerateQCFunction (QCC_def_t *def, QCC_type_t *type);
QCC_function_t *QCC_PR_GenerateQCFunction (QCC_def_t *def, QCC_type_t *type, pbool dowrap);
//NOTE: prints may use from the func argument's symbol, which can be awkward if its a temp.
QCC_sref_t QCC_PR_GenerateFunctionCallSref (QCC_sref_t newself, QCC_sref_t func, QCC_sref_t *arglist, int argcount);
@ -232,7 +234,8 @@ QCC_type_t *pr_assumetermtype; //undefined things get this time, with no warnin
QCC_function_t *pr_assumetermscope;
unsigned int pr_assumetermflags; //GDF_
pbool pr_dumpasm;
QCC_string_t s_file, s_file2; // filename for function definition
const char *s_filen;
QCC_string_t s_filed; // filename for function definition
unsigned int locals_marshalled; // largest local block size that needs to be allocated for locals overlapping.
@ -1482,7 +1485,7 @@ pbool QCC_StatementIsAJump(int stnum, int notifdest);
//typically used for debugging. Also used to determine function names for intrinsics.
const char *QCC_GetSRefName(QCC_sref_t ref)
{
if (ref.sym && ref.sym->name && !ref.ofs)
if (ref.sym && ref.sym->name/* && !ref.ofs*/)
{
if (ref.sym->temp)
return ref.cast->name;
@ -4259,7 +4262,7 @@ void QCC_PrecacheSound (const char *n, int ch)
// QCC_Error ("PrecacheSound: numsounds == MAX_SOUNDS");
strcpy (precache_sound[i].name, n);
precache_sound[i].block = ch;
precache_sound[i].filename = strings+s_file;
precache_sound[i].filename = s_filen;
precache_sound[i].fileline = pr_source_line;
numsounds++;
}
@ -4290,7 +4293,7 @@ void QCC_PrecacheModel (const char *n, int ch)
precache_model[i].block = ch - '0';
else
precache_model[i].block = 1;
precache_model[i].filename = strings+s_file;
precache_model[i].filename = s_filen;
precache_model[i].fileline = pr_source_line;
nummodels++;
}
@ -4313,7 +4316,7 @@ void QCC_SetModel (const char *n)
precache_model[i].block = 0;
precache_model[i].used=1;
precache_model[i].filename = strings+s_file;
precache_model[i].filename = s_filen;
precache_model[i].fileline = pr_source_line;
nummodels++;
}
@ -4335,7 +4338,7 @@ void QCC_SoundUsed (const char *n)
precache_sound[i].block = 0;
precache_sound[i].used=1;
precache_sound[i].filename = strings+s_file;
precache_sound[i].filename = s_filen;
precache_sound[i].fileline = pr_source_line;
numsounds++;
}
@ -6485,7 +6488,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype)
pr_source_line = pr_token_line_last = scope->s_line;
pr_scope = QCC_PR_GenerateQCFunction(scope, scope->type);
pr_scope = QCC_PR_GenerateQCFunction(scope, scope->type, false);
//reset the locals chain
pr.local_head.nextlocal = NULL;
pr.local_tail = &pr.local_head;
@ -7282,7 +7285,7 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
{
QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Class \"%s\" is not defined, cannot access memeber \"%s\"", assumeclass->name, name);
if (!autoprototype && !autoprototyped)
QCC_PR_Note(ERR_UNKNOWNVALUE, strings+s_file, pr_source_line, "Consider using #pragma autoproto");
QCC_PR_Note(ERR_UNKNOWNVALUE, s_filen, pr_source_line, "Consider using #pragma autoproto");
}
else
{
@ -7515,6 +7518,8 @@ QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit)
}
else if (!implicit && !typecmp_lax(src.cast, cast))
src.cast = cast;
else if (!implicit && cast->type == ev_void)
src.cast = type_void; //anything can be cast to void, but only do it explicitly.
else
{
char typea[256];
@ -7704,7 +7709,7 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
e = nullsref;
e.cast = type_float;
patch = QCC_Generate_OP_GOTO();
e = QCC_MakeIntConst(QCC_PR_ParseImmediateStatements (NULL, newtype) - functions);
e = QCC_MakeIntConst(QCC_PR_ParseImmediateStatements (NULL, newtype, false) - functions);
e.cast = newtype;
patch->a.ofs = &statements[numstatements] - patch;
@ -9590,7 +9595,7 @@ void QCC_PR_ParseStatement_For(void)
{
d = QCC_PR_GetDef (type, QCC_PR_ParseName(), pr_scope, true, 0, 0);
QCC_PR_Expect("=");
QCC_PR_ParseInitializerDef(d);
QCC_PR_ParseInitializerDef(d, 0);
QCC_FreeDef(d);
QCC_FreeDef(d);
}
@ -11114,7 +11119,7 @@ void QCC_CheckForDeadAndMissingReturns(int first, int last, int rettype)
}
if (st2 == last)
{
QCC_PR_Warning(WARN_UNREACHABLECODE, pr_scope->file, statements[st].linenum, "%s: contains unreachable code (line %i)", pr_scope->name, statements[st].linenum);
QCC_PR_Warning(WARN_UNREACHABLECODE, pr_scope->filen, statements[st].linenum, "%s: contains unreachable code (line %i)", pr_scope->name, statements[st].linenum);
}
continue;
}
@ -11287,12 +11292,12 @@ int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_def_t *
if (st->op == OP_DONE || st->op == OP_RETURN)
{
if (st->a.sym == def && st->a.ofs >= min && st->a.ofs < max)
if (st->a.sym && st->a.sym->symbolheader == def && st->a.ofs >= min && st->a.ofs < max)
return i;
return -2;
}
if (st->op == OP_GLOBALADDRESS && (st->a.sym == def || (st->a.sym == def->symbolheader)))
if (st->op == OP_GLOBALADDRESS && (st->a.sym->symbolheader == def || (st->a.sym->symbolheader == def)))
return -1; //assume taking a pointer to it is an initialisation.
// this code catches gotos, but can cause issues with while statements.
@ -11301,7 +11306,7 @@ int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_def_t *
if (pr_opcodes[st->op].type_a)
{
if (st->a.sym == def && st->a.ofs >= min && st->a.ofs < max)
if (st->a.sym && st->a.sym->symbolheader == def && st->a.ofs >= min && st->a.ofs < max)
{
if (OpAssignsToA(st->op))
return -1;
@ -11320,7 +11325,7 @@ int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_def_t *
if (pr_opcodes[st->op].type_b)
{
if (st->b.sym == def && st->b.ofs >= min && st->b.ofs < max)
if (st->b.sym && st->b.sym->symbolheader == def && st->b.ofs >= min && st->b.ofs < max)
{
if (OpAssignsToB(st->op))
return -1;
@ -11356,7 +11361,7 @@ int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_def_t *
continue;
}
if (pr_opcodes[st->op].type_c && st->c.sym == def && st->c.ofs >= min && st->c.ofs < max)
if (pr_opcodes[st->op].type_c && st->c.sym && st->c.sym->symbolheader == def && st->c.ofs >= min && st->c.ofs < max)
{
if (OpAssignsToC(st->op))
return -1;
@ -11407,7 +11412,7 @@ pbool QCC_CheckUninitialised(int firststatement, int laststatement)
err = QCC_CheckOneUninitialised(firststatement, laststatement, local, local->ofs, local->ofs + local->type->size * (local->arraysize?local->arraysize:1));
if (err > 0)
{
QCC_PR_Warning(WARN_UNINITIALIZED, strings+s_file, statements[err].linenum, "Potentially uninitialised variable %s", local->name);
QCC_PR_Warning(WARN_UNINITIALIZED, s_filen, statements[err].linenum, "Potentially uninitialised variable %s", local->name);
result = true;
// break;
}
@ -11448,13 +11453,13 @@ void QCC_Marshal_Locals(int firststatement, int laststatement)
//these matter when the function goes recursive (and locals marshalling counts as recursive every time).
if (local->symboldata[local->ofs]._int)
{
QCC_PR_Note(ERR_INTERNAL, strings+local->s_file, local->s_line, "Marshaling non-const initialised %s", local->name);
QCC_PR_Note(ERR_INTERNAL, local->filen, local->s_line, "Marshaling non-const initialised %s", local->name);
error = true;
}
if (local->constant)
{
QCC_PR_Note(ERR_INTERNAL, strings+local->s_file, local->s_line, "Marshaling const %s", local->name);
QCC_PR_Note(ERR_INTERNAL, local->filen, local->s_line, "Marshaling const %s", local->name);
error = true;
}
}
@ -11551,9 +11556,9 @@ void QCC_WriteGUIAsmFunction(QCC_function_t *sc, unsigned int firststatement)
}
}
if (currentsourcefile)
printf("code: %s:%i: %i:%s;\n", sc->file, statements[i].linenum, currentsourcefile, line);
printf("code: %s:%i: %i:%s;\n", sc->filen, statements[i].linenum, currentsourcefile, line);
else
printf("code: %s:%i: %s;\n", sc->file, statements[i].linenum, line);
printf("code: %s:%i: %s;\n", sc->filen, statements[i].linenum, line);
}
}
@ -11649,8 +11654,8 @@ QCC_function_t *QCC_PR_GenerateBuiltinFunction (QCC_def_t *def, int builtinnum)
if (numfunctions >= MAX_FUNCTIONS)
QCC_PR_ParseError(ERR_INTERNAL, "Too many functions - %i\nAdd \"MAX_FUNCTIONS\" \"%i\" to qcc.cfg", numfunctions, (numfunctions+4096)&~4095);
func = &functions[numfunctions++];
func->s_file = s_file2;
func->file = strings+s_file;
func->filen = s_filen;
func->s_filed = s_filed;
func->line = def->s_line; //FIXME
func->name = def->name;
func->builtin = builtinnum;
@ -11660,14 +11665,32 @@ QCC_function_t *QCC_PR_GenerateBuiltinFunction (QCC_def_t *def, int builtinnum)
func->def = def;
return func;
}
QCC_function_t *QCC_PR_GenerateQCFunction (QCC_def_t *def, QCC_type_t *type)
QCC_function_t *QCC_PR_GenerateQCFunction (QCC_def_t *def, QCC_type_t *type, pbool dowrap)
{
QCC_function_t *func;
if (numfunctions >= MAX_FUNCTIONS)
QCC_PR_ParseError(ERR_INTERNAL, "Too many functions - %i\nAdd \"MAX_FUNCTIONS\" \"%i\" to qcc.cfg", numfunctions, (numfunctions+4096)&~4095);
func = &functions[numfunctions++];
func->s_file = s_file2;
func->file = strings+s_file;
if (dowrap && def->symboldata[0].function)
{
QCC_def_t *locals;
QCC_function_t *prior = &functions[numfunctions++];
func = &functions[def->symboldata[0].function];
memcpy(prior, func, sizeof(*prior));
memset(func, 0, sizeof(*func));
for (locals = prior->firstlocal; locals; locals = locals->nextlocal)
{
if (locals->scope != func)
QCC_PR_ParseError(ERR_INTERNAL, "internal consistency check failed while wrapping %s", def->name);
locals->scope = prior;
}
}
else if (dowrap)
QCC_PR_ParseError(ERR_INTERNAL, "cannot wrap bodyless function %s", def->name);
else
func = &functions[numfunctions++];
func->filen = s_filen;
func->s_filed = s_filed;
func->line = pr_source_line;//def?def->s_line:0; //FIXME
func->name = def?def->name:"";
func->builtin = 0;
@ -11688,13 +11711,15 @@ Parse a function body
If def is set, allows stuff to refer back to a def for the function.
============
*/
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *type)
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *type, pbool dowrap)
{
unsigned int u, p;
QCC_function_t *f;
QCC_sref_t parm;
pbool needsdone=false;
QCC_def_t *prior = NULL;
conditional = 0;
expandedemptymacro = false;
@ -11735,7 +11760,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
// if (type->vargs)
// QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
pr_scope = f = QCC_PR_GenerateQCFunction(def, type);
pr_scope = f = QCC_PR_GenerateQCFunction(def, type, dowrap);
//reset the locals chain
pr.local_head.nextlocal = NULL;
@ -11799,6 +11824,20 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
QCC_FreeTemp(parm);
}
if (dowrap)
{ //if we're wrapping, then we moved the old function entry to the end and reused it for our function.
//so we need to define some local that refers to the prior def.
QCC_sref_t priorim = QCC_MakeIntConst(numfunctions-1);
prior;
prior = QCC_PR_DummyDef(f->type, "prior", f, 0, priorim.sym, 0, true, GDF_CONST); //create a union into it
prior->initialized = true;
prior->filen = functions[numfunctions-1].filen;
prior->s_filed = functions[numfunctions-1].s_filed;
prior->s_line = functions[numfunctions-1].line;
QCC_FreeTemp(priorim);
}
if (type->vargcount)
{
if (!pr_parm_argcount_name)
@ -11899,6 +11938,9 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
}
QCC_FreeTemps();
if (prior && !prior->referenced)
QCC_PR_ParseError(ERR_REDECLARATION, "Wrapper function does not refer to its prior function");
pr_token_line_last = pr_token_line;
// this is cheap
@ -12089,7 +12131,8 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_sref_t array)
numslots = array.sym->arraysize*array.cast->size;
numslots = (numslots+2)/3;
s_file = array.sym->s_file;
s_filen = array.sym->filen;
s_filed = array.sym->s_filed;
func = QCC_PR_GetDef(ftype, qcva("ArrayGetVec*%s", array.sym->name), NULL, true, 0, false);
pr_source_line = pr_token_line_last = array.sym->s_line; //thankfully these functions are emitted after compilation.
@ -12097,9 +12140,10 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_sref_t array)
if (numfunctions >= MAX_FUNCTIONS)
QCC_Error(ERR_INTERNAL, "Too many function defs");
pr_scope = QCC_PR_GenerateQCFunction(func, ftype);
pr_scope = QCC_PR_GenerateQCFunction(func, ftype, false);
pr_source_line = pr_token_line_last = pr_scope->line = array.sym->s_line; //thankfully these functions are emitted after compilation.
pr_scope->s_file = array.sym->s_file;
pr_scope->filen = array.sym->filen;
pr_scope->s_filed = array.sym->s_filed;
func->symboldata[func->ofs]._int = pr_scope - functions;
index = QCC_PR_GetSRef(type_float, "index___", pr_scope, true, 0, false);
@ -12143,7 +12187,8 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
// if (flag_fasttrackarrays && numslots > 6)
// fasttrackpossible = QCC_PR_GetSRef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false);
s_file = scope->s_file;
s_filen = scope->filen;
s_filed = scope->s_filed;
vectortrick = nullsref;
// if (numslots >= 15 && thearray.cast->type != ev_vector)
@ -12152,9 +12197,10 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
// vectortrick.cast = vectortrick.sym->type;
// }
pr_scope = QCC_PR_GenerateQCFunction(scope, scope->type);
pr_scope = QCC_PR_GenerateQCFunction(scope, scope->type, false);
pr_source_line = pr_token_line_last = pr_scope->line = thearray.sym->s_line; //thankfully these functions are emitted after compilation.
pr_scope->s_file = thearray.sym->s_file;
pr_scope->filen = thearray.sym->filen;
pr_scope->s_filed = thearray.sym->s_filed;
index = QCC_PR_GetSRef(type_float, "__indexg", pr_scope, true, 0, false);
@ -12334,10 +12380,12 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
if (numfunctions >= MAX_FUNCTIONS)
QCC_Error(ERR_INTERNAL, "Too many function defs");
s_file = arraydef->s_file;
pr_scope = QCC_PR_GenerateQCFunction(scope, scope->type);
s_filen = arraydef->filen;
s_filed = arraydef->s_filed;
pr_scope = QCC_PR_GenerateQCFunction(scope, scope->type, false);
pr_source_line = pr_token_line_last = pr_scope->line = thearray.sym->s_line; //thankfully these functions are emitted after compilation.
pr_scope->s_file = thearray.sym->s_file;
pr_scope->filen = thearray.sym->filen;
pr_scope->s_filed = thearray.sym->s_filed;
index = QCC_PR_GetSRef(type_float, "indexs___", pr_scope, true, 0, false);
value = QCC_PR_GetSRef(thearray.cast, "value___", pr_scope, true, 0, false);
@ -12467,7 +12515,8 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope,
}
def->s_line = pr_source_line;
def->s_file = s_file;
def->filen = s_filen;
def->s_filed = s_filed;
if (a>=0)
def->initialized = 1;
@ -12517,7 +12566,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_function_t *scope,
}
def->symbolheader = rootsymbol;
def->symboldata = rootsymbol->symboldata;
def->symboldata = rootsymbol->symboldata + def->ofs;
def->symbolsize = (def->arraysize?def->arraysize:1) * type->size;
if (type->type == ev_struct && (!arraysize || a>=0))
@ -12732,7 +12781,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
}
//ignore it if its static in some other file.
if (def->isstatic && strcmp(strings+def->s_file, strings+s_file))
if (def->isstatic && strcmp(def->filen, s_filen))
{
if (!foundstatic)
foundstatic = def; //save it off purely as a warning.
@ -12740,24 +12789,56 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
continue; // in a different function
}
if (def->assumedtype && !(flags & GDF_BASICTYPE))
{
if (allocate)
{ //if we're asserting a type for it in some def then it'll no longer be assumed.
if (def->type->type != type->type)
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. Basic types are different.",name);
def->type = type;
def->assumedtype = false;
def->filen = s_filen;
def->s_line = pr_source_line;
if (flags & GDF_CONST)
def->constant = true;
}
else
{ //we know enough of its type to write it out, but not enough to actually use it safely, so pretend this def isn't defined yet.
def = pHash_GetNext(&globalstable, name, def);
continue;
}
}
if (type && typecmp(def->type, type))
{
if (pr_scope || typecmp_lax(def->type, type))
{
if (!strcmp("droptofloor", def->name) || //vanilla
if (!pr_scope && (
!strcmp("droptofloor", def->name) || //vanilla
!strcmp("callfunction", def->name) || //should be (..., string name) but dpextensions gets this wrong.
!strcmp("trailparticles", def->name) //dp got the two arguments the wrong way. fteqw doesn't care any more, but dp is still wrong.
)
))
{
//this is a hack. droptofloor was wrongly declared in vanilla qc, which causes problems with replacement extensions.qc.
//yes, this is a selfish lazy hack for this, there's probably a better way, but at least we spit out a warning still.
QCC_PR_ParseWarning (WARN_COMPATIBILITYHACK, "%s builtin was wrongly defined as %s. ignoring invalid dupe definition",name, TypeName(type, typebuf1, sizeof(typebuf1)));
QCC_PR_ParseWarning (WARN_COMPATIBILITYHACK, "%s builtin was wrongly defined as %s. ignoring later definition",name, TypeName(type, typebuf1, sizeof(typebuf1)));
QCC_PR_ParsePrintDef(WARN_COMPATIBILITYHACK, def);
}
else
{
//unequal even when we're lax
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type, typebuf1, sizeof(typebuf1)), TypeName(def->type, typebuf2, sizeof(typebuf2)));
int flen = strlen(s_filen);
if (!pr_scope && flen >= 13 && !QC_strcasecmp(s_filen+flen-13, "extensions.qc") && def->type->type == ev_function)
{
//this is a hack. droptofloor was wrongly declared in vanilla qc, which causes problems with replacement extensions.qc.
//yes, this is a selfish lazy hack for this, there's probably a better way, but at least we spit out a warning still.
QCC_PR_ParseWarning (WARN_COMPATIBILITYHACK, "%s builtin was redefined as %s. ignoring alternative definition",name, TypeName(type, typebuf1, sizeof(typebuf1)));
QCC_PR_ParsePrintDef(WARN_COMPATIBILITYHACK, def);
}
else
{
//unequal even when we're lax
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type, typebuf1, sizeof(typebuf1)), TypeName(def->type, typebuf2, sizeof(typebuf2)));
}
}
}
else
@ -12919,7 +13000,7 @@ QCC_def_t *QCC_PR_DummyFieldDef(QCC_type_t *type, QCC_function_t *scope, int arr
def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
if (parttype->type == ev_function)
def->initialized = true;
def->symboldata->_int = *fieldofs;
def->symboldata[def->ofs]._int = *fieldofs;
*fieldofs += parttype->size;
}
else
@ -12954,7 +13035,9 @@ void QCC_PR_ExpandUnionToFields(QCC_type_t *type, unsigned int *fields)
QCC_PR_DummyFieldDef(pass, pr_scope, 1, fields, GDF_SAVED|GDF_CONST);
}
void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t def)
#define PIF_WRAP 1 //new initialisation is meant to wrap an existing one.
#define PIF_STRONGER 2 //previous initialisation was weak.
void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t def, unsigned int flags)
{
QCC_sref_t tmp;
int i;
@ -12967,7 +13050,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
{
for (i = 0; i < arraysize; i++)
{
QCC_PR_ParseInitializerType(0, basedef, def);
QCC_PR_ParseInitializerType(0, basedef, def, flags);
def.ofs += def.cast->size;
if (!QCC_PR_CheckToken(","))
{
@ -13020,10 +13103,18 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
{
for (i = 1; i < numfunctions; i++)
{
if (!strcmp(functions[i].name, fname) && functions[i].code == -1 && functions[i].builtin == binum)
if (functions[i].code == -1 && functions[i].builtin == binum)
{
tmp = QCC_MakeIntConst(i);
break;
if (!*functions[i].name)
{
functions[i].name = qccHunkAlloc(strlen(fname)+1);
strcpy(functions[i].name, fname);
}
if (!strcmp(functions[i].name, fname))
{
tmp = QCC_MakeIntConst(i);
break;
}
}
}
}
@ -13031,10 +13122,15 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
{
for (i = 1; i < numfunctions; i++)
{
if (!strcmp(functions[i].name, defname) && functions[i].code == -1 && functions[i].builtin == binum)
if (functions[i].code == -1 && functions[i].builtin == binum)
{
tmp = QCC_MakeIntConst(i);
break;
if (!*functions[i].name)
functions[i].name = (char*)defname;
if (!strcmp(functions[i].name, defname))
{
tmp = QCC_MakeIntConst(i);
break;
}
}
}
}
@ -13047,14 +13143,19 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
}
else
{
if (basedef->initialized == 1)
if (flags&PIF_WRAP)
{
if (!basedef->initialized || !def.sym->symboldata[def.ofs]._int)
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "wrapper function does not wrap anything");
}
else if (basedef->initialized == 1 && !(flags & PIF_STRONGER))
{
//normally this is an error, but to aid supporting new stuff with old, we convert it into a warning if a vanilla(ish) qc function replaces extension builtins.
//the qc function is the one that is used, but there is a warning so you know how to gain efficiency.
int bi = -1;
if (def.cast->type == ev_function && !arraysize)
{
if (!strcmp(defname, "anglemod"))
if (!strcmp(defname, "anglemod") || !strcmp(defname, "crossproduct"))
bi = def.sym->symboldata[def.ofs]._int;
}
if (bi <= 0 || bi >= numfunctions)
@ -13063,12 +13164,13 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
bi = functions[bi].code;
if (bi < 0)
{
QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "%s already declared as builtin", defname);
QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "%s already declared as a builtin", defname);
QCC_PR_ParsePrintSRef(WARN_NOTSTANDARDBEHAVIOUR, def);
basedef->initialized = 3;
}
else
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "redeclaration of function body");
}
if (pr_scope)
@ -13084,7 +13186,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
//generate a goto statement around the nested function, so that nothing is hurt.
patch = QCC_Generate_OP_GOTO();
f = QCC_PR_ParseImmediateStatements (NULL, type);
f = QCC_PR_ParseImmediateStatements (NULL, type, flags&PIF_WRAP);
patch->a.ofs = &statements[numstatements] - patch;
//make sure parent state is restored properly.
@ -13093,7 +13195,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
pr_scope = parent;
}
else
f = QCC_PR_ParseImmediateStatements (def.sym, type);
f = QCC_PR_ParseImmediateStatements (def.sym, type, flags&PIF_WRAP);
//allow dupes if its a builtin
if (!f->code && basedef->initialized)
@ -13158,7 +13260,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
def.cast = (type)->params[partnum].type;
def.ofs = offset + (type)->params[partnum].ofs;
QCC_PR_ParseInitializerType((type)->params[partnum].arraysize, basedef, def);
QCC_PR_ParseInitializerType((type)->params[partnum].arraysize, basedef, def, flags);
if (isunion || !QCC_PR_CheckToken(","))
{
QCC_PR_Expect("}");
@ -13189,7 +13291,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
QCC_PR_ParsePrintSRef(WARN_UNINITIALIZED, tmp);
}
if (basedef->initialized && basedef->initialized != 3)
if (basedef->initialized && basedef->initialized != 3 && !(flags & PIF_STRONGER))
{
for (i = 0; (unsigned)i < type->size; i++)
if (def.sym->symboldata[def.ofs+i]._int != tmp.sym->symboldata[tmp.ofs+i]._int)
@ -13201,6 +13303,11 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
QCC_PR_ParseWarning (WARN_COMPATIBILITYHACK, "incompatible redeclaration. Please validate builtin numbers. parseentitydata is #613");
QCC_PR_ParsePrintSRef(WARN_COMPATIBILITYHACK, tmp);
}
else if (!def.sym->arraysize && def.cast->type == ev_function && functions[def.sym->symboldata[def.ofs+i]._int].code>-1 && functions[tmp.sym->symboldata[tmp.ofs+i]._int].code==-1)
{
QCC_PR_ParseWarning (WARN_COMPATIBILITYHACK, "incompatible redeclaration. Ignoring replacement of qc function with builtin.");
QCC_PR_ParsePrintSRef(WARN_COMPATIBILITYHACK, tmp);
}
else
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "incompatible redeclaration");
}
@ -13300,9 +13407,9 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
}
}
void QCC_PR_ParseInitializerDef(QCC_def_t *def)
void QCC_PR_ParseInitializerDef(QCC_def_t *def, unsigned int flags)
{
QCC_PR_ParseInitializerType(def->arraysize, def, QCC_MakeSRef(def, def->ofs, def->type));
QCC_PR_ParseInitializerType(def->arraysize, def, QCC_MakeSRef(def, 0, def->type), flags);
if (!def->initialized || def->initialized == 3)
def->initialized = 1;
}
@ -13431,6 +13538,8 @@ void QCC_PR_ParseDefs (char *classname)
pbool inlinefunction = false;
pbool allowinline = false;
pbool dostrip = false;
pbool dowrap = false;
pbool doweak = false;
pbool forceused = false;
int arraysize;
unsigned int gd_flags;
@ -13666,6 +13775,10 @@ void QCC_PR_ParseDefs (char *classname)
allowinline = true;
else if (QCC_PR_CheckKeyword(keyword_ignore, "ignore"))
dostrip = true;
else if (QCC_PR_CheckKeyword(keyword_wrap, "wrap"))
dowrap = true;
else if (QCC_PR_CheckKeyword(keyword_weak, "weak"))
doweak = true;
else
break;
}
@ -13732,7 +13845,7 @@ void QCC_PR_ParseDefs (char *classname)
{
def->referenced = true;
f = QCC_PR_ParseImmediateStatements (def, type);
f = QCC_PR_ParseImmediateStatements (def, type, false);
def->initialized = 1;
def->isstatic = isstatic;
@ -13943,7 +14056,7 @@ void QCC_PR_ParseDefs (char *classname)
if (isstatic)
{
if (!strcmp(strings+def->s_file, strings+s_file))
if (!strcmp(def->filen, s_filen))
def->isstatic = isstatic;
else //if (type->type != ev_function && defaultstatic) //functions don't quite consitiute a definition
QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "can't redefine non-static as static");
@ -13978,21 +14091,11 @@ void QCC_PR_ParseDefs (char *classname)
QCC_type_t *parentclass;
if (def->shared)
QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name);
if (def->initialized == 1)
{
// if (def->type->type == ev_function)
// {
// i = G_FUNCTION(def->ofs);
// df = &functions[i];
// QCC_PR_ParseErrorPrintDef (ERR_REDECLARATION, def, "%s redeclared, prev instance is in %s", name, strings+df->s_file);
// }
// else
// QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
}
if (autoprototype || dostrip)
//if weak, only use the first non-weak version of the function
if (autoprototype || dostrip || (def->initialized && doweak) || (!def->initialized && doweak && dowrap))
{ //ignore the code and stuff
if (dostrip && !def->initialized)
if ((dostrip || doweak && dowrap) && !def->initialized)
def->initialized = 3;
if (dostrip)
def->referenced = true;
@ -14045,7 +14148,11 @@ void QCC_PR_ParseDefs (char *classname)
parentclass = pr_classtype;
pr_classtype = defclass?defclass:pr_classtype;
def->constant = (isconstant || (!isvar && !pr_scope));
QCC_PR_ParseInitializerDef(def);
QCC_PR_ParseInitializerDef(def, (dowrap?PIF_WRAP:0)|(def->weak?PIF_STRONGER:0));
if (doweak)
def->weak = true;
else
def->weak = false;
QCC_FreeDef(def);
pr_classtype = parentclass;
}
@ -14141,6 +14248,7 @@ compiles the 0 terminated text, adding defintions to the pr structure
*/
pbool QCC_PR_CompileFile (char *string, char *filename)
{
char *tmp;
jmp_buf oldjb;
if (!pr.memory)
QCC_Error (ERR_INTERNAL, "PR_CompileFile: Didn't clear");
@ -14149,18 +14257,16 @@ pbool QCC_PR_CompileFile (char *string, char *filename)
compilingfile = filename;
s_filen = tmp = qccHunkAlloc(strlen(filename)+1);
strcpy(tmp, filename);
if (opt_filenames)
{
optres_filenames += strlen(filename);
pr_file_p = qccHunkAlloc(strlen(filename)+1);
strcpy(pr_file_p, filename);
s_file = pr_file_p - strings;
s_file2 = 0;
s_filed = 0;
}
else
{
s_file = s_file2 = QCC_CopyString (filename);
}
s_filed = QCC_CopyString (filename);
pr_file_p = string;
pr_assumetermtype = NULL;
@ -14257,14 +14363,15 @@ pbool QCC_Include(char *filename)
char *newfile;
char fname[512];
char *opr_file_p;
QCC_string_t os_file, os_file2;
const char *os_filen;
QCC_string_t os_filed;
int opr_source_line;
char *ocompilingfile;
struct qcc_includechunk_s *oldcurrentchunk;
ocompilingfile = compilingfile;
os_file = s_file;
os_file2 = s_file2;
os_filen = s_filen;
os_filed = s_filed;
opr_source_line = pr_source_line;
opr_file_p = pr_file_p;
oldcurrentchunk = currentchunk;
@ -14277,8 +14384,8 @@ pbool QCC_Include(char *filename)
currentchunk = oldcurrentchunk;
compilingfile = ocompilingfile;
s_file = os_file;
s_file2 = os_file2;
s_filen = os_filen;
s_filed = os_filed;
pr_source_line = opr_source_line;
pr_file_p = opr_file_p;

View File

@ -113,12 +113,21 @@ void QCC_PR_CloseProcessor(void)
void QCC_PR_AddIncludePath(const char *newinc)
{
int i;
if (!*newinc)
{
QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Invalid include path.");
return;
}
for (i = 0; i < MAXINCLUDEDIRS; i++)
{
if (!*qccincludedir[i])
{
const char *e = newinc + strlen(newinc)-1;
QC_strlcpy(qccincludedir[i], newinc, sizeof(qccincludedir));
if (*e != '/' && *e != '\\')
QC_strlcat(qccincludedir[i], "/", sizeof(qccincludedir));
break;
}
if (!strcmp(qccincludedir[i], newinc))
@ -126,13 +135,10 @@ void QCC_PR_AddIncludePath(const char *newinc)
}
if (i == MAXINCLUDEDIRS)
{
if (!s_file)
QCC_PR_Warning(WARN_STRINGTOOLONG, "cmdline", 0, "Too many include dirs. Ignoring and hoping the stars align.");
else
QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Too many include dirs. Ignoring and hoping the stars align.");
QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Too many include dirs. Ignoring and hoping the stars align.");
}
}
void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst)
static void QCC_PR_IncludeChunkEx (char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst)
{
qcc_includechunk_t *chunk = qccHunkAlloc(sizeof(qcc_includechunk_t));
chunk->prev = currentchunk;
@ -181,7 +187,7 @@ pbool QCC_PR_UnInclude(void)
PR_PrintNextLine
==============
*/
void QCC_PR_PrintNextLine (void)
static void QCC_PR_PrintNextLine (void)
{
char *t;
@ -191,7 +197,7 @@ void QCC_PR_PrintNextLine (void)
printf ("\n");
}
void QCC_Canonicalize(char *fullname, size_t fullnamesize, char *newfile, char *base)
static void QCC_Canonicalize(char *fullname, size_t fullnamesize, char *newfile, char *base)
{
int doubledots;
char *end = fullname;
@ -269,10 +275,20 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, pbool verbose)
if (verbose)
{
if (autoprototype)
printf("prototyping include %s\n", fullname);
if (verbose == 2)
{
if (autoprototype)
printf("prototyping %s\n", fullname);
else
printf("compiling %s\n", fullname);
}
else
printf("including %s\n", fullname);
{
if (autoprototype)
printf("prototyping include %s\n", fullname);
else
printf("including %s\n", fullname);
}
}
QCC_Include(fullname);
}
@ -285,6 +301,7 @@ int QCC_PR_LexInteger (void);
void QCC_AddFile (char *filename);
void QCC_PR_LexString (void);
pbool QCC_PR_SimpleGetToken (void);
pbool QCC_PR_SimpleGetString(void);
#define PPI_VALUE 0
#define PPI_NOT 1
@ -800,9 +817,9 @@ pbool QCC_PR_Precompiler(void)
msg[a] = '\0';
if (flag_msvcstyle)
printf ("%s(%i) : #message: %s\n", strings + s_file, pr_source_line, msg);
printf ("%s(%i) : #message: %s\n", s_filen, pr_source_line, msg);
else
printf ("%s:%i: #message: %s\n", strings + s_file, pr_source_line, msg);
printf ("%s:%i: #message: %s\n", s_filen, pr_source_line, msg);
QCC_PR_SkipToEndOfLine(false);
}
else if (!strncmp(directive, "copyright", 9))
@ -852,6 +869,25 @@ pbool QCC_PR_Precompiler(void)
QCC_PR_SkipToEndOfLine(true);
}
else if (!strncmp(directive, "merge", 5))
{
extern char destfile[1024];
pr_file_p=directive+5;
while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++;
QCC_PR_SimpleGetString();
printf("Merging to %s\n", pr_token);
QCC_ImportProgs(pr_token);
if (!*destfile)
{
QCC_Canonicalize(destfile, sizeof(destfile), pr_token, compilingfile);
printf("Outputfile: %s\n", destfile);
}
QCC_PR_SkipToEndOfLine(true);
}
else if (!strncmp(directive, "includelist", 11))
{
int defines=0;
@ -946,7 +982,7 @@ pbool QCC_PR_Precompiler(void)
while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++;
QCC_PR_LexString();
QCC_PR_SimpleGetString();
printf("Including datafile: %s\n", pr_token);
QCC_AddFile(pr_token);
@ -970,21 +1006,11 @@ pbool QCC_PR_Precompiler(void)
while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++;
QCC_PR_LexString();
strcpy(destfile, pr_token);
printf("Outputfile: %s\n", destfile);
QCC_PR_SimpleGetString();
QCC_Canonicalize(destfile, sizeof(destfile), pr_token, compilingfile);
printf("Outputfile: %s\n", pr_token);
pr_file_p++;
for (a = 0; a < sizeof(msg)-1 && pr_file_p[a] != '\n' && pr_file_p[a] != '\0'; a++)
msg[a] = pr_file_p[a];
msg[a-1] = '\0';
while(*pr_file_p != '\n' && *pr_file_p != '\0') //read on until the end of the line
{
pr_file_p++;
}
QCC_PR_SkipToEndOfLine(true);
}
else if (!strncmp(directive, "pragma", 6))
{
@ -2327,6 +2353,83 @@ void QCC_PR_ExpandMacro(void)
pr_immediate._float = (float)i;
}
pbool QCC_PR_SimpleGetString(void)
{
int c;
int i = 0;
char *f;
pr_token[0] = 0;
// skip whitespace
while ((c = *pr_file_p) && qcc_iswhite(c))
{
if (c=='\n')
return false;
pr_file_p++;
}
if (c == 0) //eof
return false;
//abort if there's a comment.
if (pr_file_p[0] == '/')
{
if (pr_file_p[1] == '/')
{ //comment alert
while(*pr_file_p && *pr_file_p != '\n')
pr_file_p++;
return false;
}
if (pr_file_p[1] == '*')
return false;
}
if (*pr_file_p != '\"')
return false; //nope, not a string.
f = pr_file_p+1;
while (*f)
{
if (*f == '\n' || !*f)
{ //bad string
QCC_Error (ERR_INTERNAL, "new line inside string");
pr_token[0] = 0;
return false;
}
if (*f == '\"')
{ //end-of-string
pr_token[i] = 0;
pr_file_p = f+1;
return false;
}
if (i == sizeof(qcc_token)-1)
QCC_Error (ERR_INTERNAL, "token exceeds %i chars", i);
if (*f == '\\')
{
f++;
if (!*f)
f = "";
else if (*f == 'n')
{
pr_token[i++] = '\n';
f++;
}
else if (*f == 'r')
{
pr_token[i++] = '\r';
f++;
}
else if (*f == 't')
{
pr_token[i++] = '\t';
f++;
}
else
pr_token[i++] = *f++;
}
else
pr_token[i++] = *f++;
}
return true;
}
// just parses text, returning false if an eol is reached
pbool QCC_PR_SimpleGetToken (void)
{
@ -2872,7 +2975,7 @@ static char *QCC_PR_CheckBuiltinCompConst(char *constname, char *retbuf, size_t
}
if (!strcmp(constname, "__FILE__"))
{
QC_snprintfz(retbuf, retbufsize, "\"%s\"", strings + s_file);
QC_snprintfz(retbuf, retbufsize, "\"%s\"", s_filen);
return retbuf;
}
if (!strcmp(constname, "__LINE__"))
@ -3165,9 +3268,9 @@ int QCC_PR_CheckCompConst(void)
if (flag_debugmacros)
{
if (flag_msvcstyle)
printf ("%s(%i) : macro %s: %s\n", strings+s_file, pr_source_line, c->name, pr_file_p);
printf ("%s(%i) : macro %s: %s\n", s_filen, pr_source_line, c->name, pr_file_p);
else
printf ("%s:%i: macro %s: %s\n", strings+s_file, pr_source_line, c->name, pr_file_p);
printf ("%s:%i: macro %s: %s\n", s_filen, pr_source_line, c->name, pr_file_p);
}
}
else
@ -3399,14 +3502,14 @@ void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
{
if (!qccwarningaction[type])
return;
if (def->s_file)
if (def->filen)
{
char tybuffer[512];
char tmbuffer[512];
char *modifiers;
if (QCC_Temp_Describe(def, tmbuffer, sizeof(tmbuffer)))
{
printf ("%s:%i: (%s)(%s)\n", strings + def->s_file, def->s_line, TypeName(def->type, tybuffer, sizeof(tybuffer)), tmbuffer);
printf ("%s:%i: (%s)(%s)\n", def->filen, def->s_line, TypeName(def->type, tybuffer, sizeof(tybuffer)), tmbuffer);
}
else
{
@ -3416,9 +3519,9 @@ void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
else if (def->isstatic)
modifiers = "static ";
if (flag_msvcstyle)
printf ("%s(%i) : %s%s %s is defined here\n", strings + def->s_file, def->s_line, modifiers, TypeName(def->type, tybuffer, sizeof(tybuffer)), def->name);
printf ("%s(%i) : %s%s %s is defined here\n", def->filen, def->s_line, modifiers, TypeName(def->type, tybuffer, sizeof(tybuffer)), def->name);
else
printf ("%s:%i: %s%s %s is defined here\n", strings + def->s_file, def->s_line, modifiers, TypeName(def->type, tybuffer, sizeof(tybuffer)), def->name);
printf ("%s:%i: %s%s %s is defined here\n", def->filen, def->s_line, modifiers, TypeName(def->type, tybuffer, sizeof(tybuffer)), def->name);
}
}
}
@ -3455,7 +3558,7 @@ Aborts the current file load
============
*/
#ifndef QCC
void editbadfile(char *file, int line);
void editbadfile(const char *file, int line);
#endif
//will abort.
void VARGS QCC_PR_ParseError (int errortype, const char *error, ...)
@ -3468,14 +3571,14 @@ void VARGS QCC_PR_ParseError (int errortype, const char *error, ...)
va_end (argptr);
#ifndef QCC
editbadfile(strings+s_file, pr_source_line);
editbadfile(s_filen, pr_source_line);
#endif
QCC_PR_PrintScope();
if (flag_msvcstyle)
printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
printf ("%s(%i) : error: %s\n", s_filen, pr_source_line, string);
else
printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
printf ("%s:%i: error: %s\n", s_filen, pr_source_line, string);
longjmp (pr_parse_abort, 1);
}
@ -3490,13 +3593,13 @@ void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char
va_end (argptr);
#ifndef QCC
editbadfile(strings+s_file, pr_source_line);
editbadfile(s_filen, pr_source_line);
#endif
QCC_PR_PrintScope();
if (flag_msvcstyle)
printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
printf ("%s(%i) : error: %s\n", s_filen, pr_source_line, string);
else
printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
printf ("%s:%i: error: %s\n", s_filen, pr_source_line, string);
QCC_PR_ParsePrintDef(WARN_ERROR, def);
@ -3513,13 +3616,13 @@ void VARGS QCC_PR_ParseErrorPrintSRef (int errortype, QCC_sref_t def, const char
va_end (argptr);
#ifndef QCC
editbadfile(strings+s_file, pr_source_line);
editbadfile(s_filen, pr_source_line);
#endif
QCC_PR_PrintScope();
if (flag_msvcstyle)
printf ("%s(%i) : error: %s\n", strings + s_file, pr_source_line, string);
printf ("%s(%i) : error: %s\n", s_filen, pr_source_line, string);
else
printf ("%s:%i: error: %s\n", strings + s_file, pr_source_line, string);
printf ("%s:%i: error: %s\n", s_filen, pr_source_line, string);
QCC_PR_ParsePrintSRef(WARN_ERROR, def);
@ -3552,7 +3655,7 @@ pbool VARGS QCC_PR_PrintWarning (int type, const char *file, int line, const cha
if (!string)
;
else if (!file || !*file)
printf (": werror%s: %s\n", wnam, string);
printf (":: werror%s: %s\n", wnam, string);
else if (flag_msvcstyle)
printf ("%s(%i) : werror%s: %s\n", file, line, wnam, string);
else
@ -3564,7 +3667,7 @@ pbool VARGS QCC_PR_PrintWarning (int type, const char *file, int line, const cha
if (!string)
;
else if (!file || !*file)
printf (": warning%s: %s\n", wnam, string);
printf (":: warning%s: %s\n", wnam, string);
else if (flag_msvcstyle)
printf ("%s(%i) : warning%s: %s\n", file, line, wnam, string);
else
@ -3604,7 +3707,7 @@ pbool VARGS QCC_PR_ParseWarning (int type, const char *error, ...)
QC_vsnprintf (string,sizeof(string)-1, error,argptr);
va_end (argptr);
return QCC_PR_PrintWarning(type, strings + s_file, pr_source_line, string);
return QCC_PR_PrintWarning(type, s_filen, pr_source_line, string);
}
void VARGS QCC_PR_Note (int type, const char *file, int line, const char *error, ...)
@ -4607,8 +4710,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
{
if (!qcc_typeinfo[i].typedefed)
continue;
if (STRCMP(qcc_typeinfo[i].name, accessorname) == 0 && qcc_typeinfo[i].type == ev_accessor)
if (STRCMP(qcc_typeinfo[i].name, accessorname) == 0)
{
if (qcc_typeinfo[i].type != ev_accessor)
QCC_PR_ParseError(ERR_NOTANAME, "Type %s cannot be redefined as an accessor", accessorname);
newt = &qcc_typeinfo[i];
break;
}

View File

@ -321,6 +321,57 @@ static pbool QCC_RegSetValue(HKEY base, char *keyname, char *valuename, int type
}
*/
typedef struct vfile_s
{ //when originally running from a .dat, we load up all the functions and work from those rather than actual files.
//(these get re-written into the resulting .dat)
struct vfile_s *next;
void *fdata;
size_t fsize;
char name[1];
} vfile_t;
static vfile_t *qcc_vfiles;
vfile_t *QCC_FindVFile(const char *name)
{
vfile_t *f;
for (f = qcc_vfiles; f; f = f->next)
{
if (!strcmp(f->name, name))
return f;
}
//give it another go, for case
for (f = qcc_vfiles; f; f = f->next)
{
if (!QC_strcasecmp(f->name, name))
return f;
}
return NULL;
}
pbool QCC_AddVFile(const char *name, void *data, size_t size)
{
vfile_t *f = QCC_FindVFile(name);
if (!f)
{
f = malloc(sizeof(vfile_t) + strlen(name));
f->next = qcc_vfiles;
strcpy(f->name, name);
qcc_vfiles = f;
}
else
free(f->fdata);
f->fdata = malloc(size);
memcpy(f->fdata, data, size);
f->fsize = size;
return true;
}
void QCC_EnumerateFilesResult(const char *name, const void *compdata, size_t compsize, int method, size_t plainsize)
{
void *buffer = malloc(plainsize);
if (QC_decode(NULL, compsize, plainsize, method, compdata, buffer))
QCC_AddVFile(name, buffer, plainsize);
free(buffer);
}
/*
==============
LoadFile
@ -330,6 +381,17 @@ unsigned char *PDECL QCC_ReadFile (const char *fname, void *buffer, int len, siz
{
long length;
FILE *f;
vfile_t *v = QCC_FindVFile(fname);
if (v)
{
if (len > v->fsize)
len = v->fsize;
memcpy(buffer, v->fdata, len);
if (sz)
*sz = len;
return buffer;
}
f = fopen(fname, "rb");
if (!f)
return NULL;
@ -347,6 +409,11 @@ int PDECL QCC_RawFileSize (const char *fname)
{
long length;
FILE *f;
vfile_t *v = QCC_FindVFile(fname);
if (v)
return v->fsize;
f = fopen(fname, "rb");
if (!f)
return -1;
@ -499,7 +566,10 @@ pbool PDECL QCC_WriteFile (const char *name, void *data, int len)
return false;
#endif
}
if (QCC_FindVFile(name))
return QCC_AddVFile(name, data, len);
f = fopen(name, "wb");
if (!f)
return false;
@ -1241,7 +1311,7 @@ enum {
static void EditorReload(editor_t *editor);
int EditorSave(editor_t *edit);
void EditFile(char *name, int line, pbool setcontrol);
void EditFile(const char *name, int line, pbool setcontrol);
pbool EditorModified(editor_t *e);
void QueryOpenFile(void)
@ -1786,7 +1856,7 @@ char *GetTooltipText(editor_t *editor, int pos, pbool dwell)
{
if (line > functions[fno].line && bestline < functions[fno].line)
{
if (!strcmp(editor->filename, functions[fno].file))
if (!strcmp(editor->filename, functions[fno].filen))
{
best = fno;
bestline = functions[fno].line;
@ -2046,7 +2116,9 @@ static void UpdateEditorTitle(editor_t *editor)
encoding = "unknown";
break;
}
if (editor->modified)
if (QCC_FindVFile(editor->filename))
sprintf(title, "%s:%i - Virtual", editor->filename, 1+editor->curline);
else if (editor->modified)
sprintf(title, "*%s:%i - %s", editor->filename, 1+editor->curline, encoding);
else
sprintf(title, "%s:%i - %s", editor->filename, 1+editor->curline, encoding);
@ -2386,7 +2458,7 @@ static void EditorReload(editor_t *editor)
}
//line is 0-based. use -1 for no reselection
void EditFile(char *name, int line, pbool setcontrol)
void EditFile(const char *name, int line, pbool setcontrol)
{
char title[1024];
editor_t *neweditor;
@ -2714,7 +2786,7 @@ unsigned char *GUIReadFile(const char *fname, void *buffer, int blen, size_t *sz
//our qcc itself is fine with utf-16, so long as it has a BOM.
if (e->scintilla)
{
SendMessage(e->editpane, SCI_GETTEXT, blen, (LPARAM)buffer);
blen = SendMessage(e->editpane, SCI_GETTEXT, blen, (LPARAM)buffer);
}
else if (e->savefmt == UTF_ANSI)
{
@ -2738,7 +2810,9 @@ unsigned char *GUIReadFile(const char *fname, void *buffer, int blen, size_t *sz
SendMessage(e->editpane, SCI_SETSAVEPOINT, 0, 0); //tell the control that it was saved.
}
else
{
QCC_WriteFileW(e->filename, (wchar_t*)buffer+1, blen);
}
}
}
}
@ -5323,6 +5397,8 @@ void UpdateFileList(void)
int size;
char *buffer;
AddSourceFile(NULL, progssrcname);
f = fopen (progssrcname, "rb");
if (!f)
return;
@ -5343,14 +5419,15 @@ void UpdateFileList(void)
if (*qcc_token == '#')
{
//aaaahhh! newstyle!
AddSourceFile(NULL, progssrcname);
}
else
{
pr_file_p = QCC_COM_Parse(pr_file_p); //we dont care about the produced progs.dat
AddSourceFile(NULL, progssrcname);
while(pr_file_p)
{
if (*qcc_token == '#') //panic if there's preprocessor in there.
break;
AddSourceFile(progssrcname, qcc_token);
pr_file_p = QCC_COM_Parse(pr_file_p); //we dont care about the produced progs.dat
}
@ -5552,6 +5629,38 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
ShowWindow(mainwindow, SW_SHOWDEFAULT);
{
char *ext = strrchr(progssrcname, '.');
if (ext && !QC_strcasecmp(ext, ".dat"))
{
FILE *f = fopen(progssrcname, "rb");
if (f)
{
char *buf;
size_t size;
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
buf = malloc(size);
fread(buf, 1, size, f);
fclose(f);
QC_EnumerateFilesFromBlob(buf, size, QCC_EnumerateFilesResult);
free(buf);
}
strcpy(progssrcname, "progs.src");
for (i = 0; ; i++)
{
if (!strcmp("embedsrc", compiler_flag[i].abbrev))
{
compiler_flag[i].flags |= FLAG_SETINGUI;
break;
}
}
}
}
if (fl_compileonstart)
{
CreateOutputWindow(false);

View File

@ -99,21 +99,21 @@ void GoToDefinition(char *name)
if (fnum > 0 && fnum < numfunctions)
{
fnc = &functions[fnum];
if (fnc->code>=0 && fnc->s_file)
if (fnc->code>=0 && fnc->filen)
{
EditFile(strings+fnc->s_file, statements[fnc->code].linenum-1, false);
EditFile(fnc->filen, statements[fnc->code].linenum-1, false);
return;
}
}
}
if (!def->s_file)
if (!def->filen)
{
char msgbuffer[2048];
QC_snprintfz(msgbuffer, sizeof(msgbuffer), "Global definition of \"%s\" was not specified.", name);
GUI_DialogPrint("Not found", msgbuffer);
}
else
EditFile(def->s_file+strings, def->s_line-1, false);
EditFile(def->filen, def->s_line-1, false);
}
else
{
@ -413,6 +413,9 @@ void GUI_ParseCommandLine(char *args)
GUI_LoadConfig();
paramlen = strlen(parameters);
if (paramlen)
parameters[paramlen++] = ' ';
while(*args)
{
while (*args == ' ' || *args == '\t')
@ -686,7 +689,7 @@ void GUI_RevealOptions(void)
int GUI_BuildParms(char *args, char **argv, pbool quick)
int GUI_BuildParms(char *args, char **argv, pbool quick)//, char *forceoutputfile)
{
static char param[2048];
int paramlen = 0;
@ -770,6 +773,12 @@ int GUI_BuildParms(char *args, char **argv, pbool quick)
args=next;
}*/
// if (*forceoutputfile)
// {
// argv[argc++] = "-destfile";
// argv[argc++] = forceoutputfile;
// }
if (*progssrcname)
{
argv[argc++] = "-srcfile";

View File

@ -80,7 +80,7 @@ int numstatements;
QCC_function_t *functions;
dfunction_t *dfunctions;
//dfunction_t *dfunctions;
int numfunctions;
QCC_ddef_t *qcc_globals;
@ -200,6 +200,8 @@ struct {
{" F312", WARN_OVERFLOW},
{" F313", WARN_DENORMAL},
{" F314", WARN_LAXCAST},
{" F315", WARN_DUPLICATEPRECOMPILER},
{" F316", WARN_IDENTICALPRECOMPILER},
{" F208", WARN_NOTREFERENCEDCONST},
{" F209", WARN_EXTRAPRECACHE},
@ -319,7 +321,8 @@ compiler_flag_t compiler_flag[] = {
{&keyword_union, defaultkeyword, "union", "Keyword: union", "Disables the 'union' keyword."}, //you surly know what a union is!
{&keyword_var, defaultkeyword, "var", "Keyword: var", "Disables the 'var' keyword."},
{&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."},
//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."},
@ -767,7 +770,7 @@ int WriteSourceFiles(int h, pbool sourceaswell, pbool legacyembed)
#ifdef AVAIL_ZLIB
idf[num].compmethod = 2;
#else
idf[num].compmethod = 1;
idf[num].compmethod = 0;
#endif
idf[num].ofs = SafeSeek(h, 0, SEEK_CUR);
idf[num].compsize = QC_encode(progfuncs, f->size, idf[num].compmethod, f->file, h);
@ -879,13 +882,21 @@ int WriteBodylessFuncs (int handle)
int ret=0;
for (d=pr.def_head.next ; d ; d=d->next)
{
if (!d->used || !d->constant)
continue;
if (d->type->type == ev_function && !d->scope)// function parms are ok
{
if ((d->initialized == 2) && d->referenced)
if (d->initialized == 2)
{
SafeWrite(handle, d->name, strlen(d->name)+1);
ret++;
}
if (d->initialized == 0)
{
QCC_PR_Warning(ERR_NOFUNC, d->filen, d->s_line, "function %s has no body", d->name);
QCC_PR_ParsePrintDef(ERR_NOFUNC, d);
}
}
}
@ -1043,9 +1054,9 @@ void QCC_UnmarshalLocals(void)
if (verbose >= 3)
{
if (onum == numpr_globals)
printf("code: %s:%i: function %s no private locals\n", functions[i].file, functions[i].line, functions[i].name);
printf("code: %s:%i: function %s no private locals\n", functions[i].filen, functions[i].line, functions[i].name);
else
printf("code: %s:%i: function %s private locals %i-%i\n", functions[i].file, functions[i].line, functions[i].name, onum, numpr_globals);
printf("code: %s:%i: function %s private locals %i-%i\n", functions[i].filen, functions[i].line, functions[i].name, onum, numpr_globals);
}
}
}
@ -1065,14 +1076,14 @@ void QCC_UnmarshalLocals(void)
if (verbose >= 3)
{
if (onum == numpr_globals)
printf("code: %s:%i: function %s no locals\n", functions[i].file, functions[i].line, functions[i].name);
printf("code: %s:%i: function %s no locals\n", functions[i].filen, functions[i].line, functions[i].name);
else
{
printf("code: %s:%i: function %s overlapped locals %i-%i\n", functions[i].file, functions[i].line, functions[i].name, onum, numpr_globals);
printf("code: %s:%i: function %s overlapped locals %i-%i\n", functions[i].filen, functions[i].line, functions[i].name, onum, numpr_globals);
for (d = functions[i].firstlocal; d; d = d->nextlocal)
{
printf("code: %s:%i: %s @%i\n", functions[i].file, functions[i].line, d->name, d->ofs);
printf("code: %s:%i: %s @%i\n", functions[i].filen, functions[i].line, d->name, d->ofs);
}
}
}
@ -1296,7 +1307,7 @@ pbool QCC_WriteData (int crc)
funcs[i].first_statement = PRLittleLong (functions[i].code);
funcs[i].parm_start = 0;//PRLittleLong (functions[i].parm_start);
funcs[i].s_name = PRLittleLong (QCC_CopyString(functions[i].name));
funcs[i].s_file = PRLittleLong (functions[i].s_file);
funcs[i].s_file = PRLittleLong (functions[i].s_filed);
funcs[i].numparms = 0;//PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
funcs[i].locals = 0;//PRLittleLong (functions[i].locals);
for (j = 0; j < MAX_PARMS; j++)
@ -1327,9 +1338,17 @@ pbool QCC_WriteData (int crc)
}
else
funcs[i].s_name = PRLittleLong (QCC_CopyString(functions[i].name));
funcs[i].s_file = PRLittleLong (functions[i].s_file);
funcs[i].s_file = PRLittleLong (functions[i].s_filed);
if (functions[i].code == -1)
if (functions[i].merged)
{
funcs[i].parm_start = functions[i].merged->parm_start;
funcs[i].locals = functions[i].merged->locals;
funcs[i].numparms = functions[i].merged->numparms;
for(p = 0; p < funcs[i].numparms; p++)
funcs[i].parm_size[p] = functions[i].merged->parm_size[p];
}
else if (functions[i].code == -1)
{
funcs[i].parm_start = 0;
funcs[i].locals = 0;
@ -1346,7 +1365,7 @@ pbool QCC_WriteData (int crc)
{
if (!local->used)
{ //all params should have been assigned space. logically we could have safely omitted the last ones, but blurgh.
QCC_PR_Warning(ERR_INTERNAL, strings + local->s_file, local->s_line, "Argument %s was not marked used.\n", local->name);
QCC_PR_Warning(ERR_INTERNAL, local->filen, local->s_line, "Argument %s was not marked used.\n", local->name);
continue;
}
@ -1394,10 +1413,10 @@ pbool QCC_WriteData (int crc)
funcs[i].numparms = PRLittleLong(funcs[i].numparms);
if (funcs[i].locals && !funcs[i].parm_start)
QCC_PR_Warning(0, strings + funcs[i].s_file, functions[i].line, "%s:%i: func %s @%i locals@%i+%i, %i parms\n", functions[i].file, functions[i].line, strings+funcs[i].s_name, funcs[i].first_statement, funcs[i].parm_start, funcs[i].locals, funcs[i].numparms);
QCC_PR_Warning(0, strings + funcs[i].s_file, functions[i].line, "%s:%i: func %s @%i locals@%i+%i, %i parms\n", functions[i].filen, functions[i].line, strings+funcs[i].s_name, funcs[i].first_statement, funcs[i].parm_start, funcs[i].locals, funcs[i].numparms);
#ifdef DEBUG_DUMP
printf("code: %s:%i: func %s @%i locals@%i+%i, %i parms\n", functions[i].file, functions[i].line, strings+funcs[i].s_name, funcs[i].first_statement, funcs[i].parm_start, funcs[i].locals, funcs[i].numparms);
printf("code: %s:%i: func %s @%i locals@%i+%i, %i parms\n", functions[i].file, functions[i].line, strings+funcs[i].s_named, funcs[i].first_statement, funcs[i].parm_start, funcs[i].locals, funcs[i].numparms);
#endif
}
funcdata = funcs;
@ -1454,15 +1473,15 @@ pbool QCC_WriteData (int crc)
else if (strcmp(def->name, "IMMEDIATE") && qccwarningaction[wt] && !(def->type->type == ev_function && def->symbolheader->timescalled) && !def->symbolheader->used)
{
char typestr[256];
if (QC_strcasestr(strings + def->s_file, "extensions") && !verbose)
if (QC_strcasestr(def->filen, "extensions") && !verbose)
{ //try to avoid annoying warnings from dpextensions.qc
extwarncount++;
QCC_PR_Warning(wt, strings + def->s_file, def->s_line, NULL);
QCC_PR_Warning(wt, def->filen, def->s_line, NULL);
}
else if (def->arraysize)
QCC_PR_Warning(wt, strings + def->s_file, def->s_line, (dupewarncount++ >= 10 && !verbose)?NULL:"%s %s[%i] no references.", TypeName(def->type, typestr, sizeof(typestr)), def->name, def->arraysize);
QCC_PR_Warning(wt, def->filen, def->s_line, (dupewarncount++ >= 10 && !verbose)?NULL:"%s %s[%i] no references.", TypeName(def->type, typestr, sizeof(typestr)), def->name, def->arraysize);
else
QCC_PR_Warning(wt, strings + def->s_file, def->s_line, (dupewarncount++ >= 10 && !verbose)?NULL:"%s %s no references.", TypeName(def->type, typestr, sizeof(typestr)), def->name);
QCC_PR_Warning(wt, def->filen, def->s_line, (dupewarncount++ >= 10 && !verbose)?NULL:"%s %s no references.", TypeName(def->type, typestr, sizeof(typestr)), def->name);
}
pr_scope = NULL;
@ -1470,7 +1489,7 @@ pbool QCC_WriteData (int crc)
{
optres_unreferenced++;
#ifdef DEBUG_DUMP
printf("code: %s:%i: strip noref %s %s@%i;\n", strings+def->s_file, def->s_line, def->type->name, def->name, def->ofs);
printf("code: %s:%i: strip noref %s %s@%i;\n", def->filen, def->s_line, def->type->name, def->name, def->ofs);
#endif
continue;
}
@ -1478,7 +1497,7 @@ pbool QCC_WriteData (int crc)
if ((def->type->type == ev_struct || def->type->type == ev_union || def->arraysize) && def->deftail)
{
#ifdef DEBUG_DUMP
printf("code: %s:%i: strip struct %s %s@%i;\n", strings+def->s_file, def->s_line, def->type->name, def->name, def->ofs);
printf("code: %s:%i: strip struct %s %s@%i;\n", def->filen, def->s_line, def->type->name, def->name, def->ofs);
#endif
//the head of an array/struct is never written. only, its member fields are.
continue;
@ -2157,7 +2176,7 @@ strofs = (strofs+3)&~3;
printf("unable to write value for 'entity progs'\n"); //would not work anyway
else
{
QCC_PR_Warning(WARN_DENORMAL, strings + def->s_file, def->s_line, "'entity progs' is non-portable and will not work across engines nor cpus.");
QCC_PR_Warning(WARN_DENORMAL, def->filen, def->s_line, "'entity progs' is non-portable and will not work across engines nor cpus.");
if (def->initialized)
i = PRLittleLong(qcc_pr_globals[def->ofs]._int);
@ -2264,6 +2283,289 @@ strofs = (strofs+3)&~3;
return true;
}
/*
#merge "oldprogs"
wrap void() worldspawn =
{
print("hello world\n");
prior();
};
Progs merging is done by loading in an existing progs.dat and essentially appending new stuff on the end.
The resulting output should be the same, other than wraps (which replaces the previous function global with the new one).
*/
static void QCC_MergeStrings(char *in, unsigned int num)
{
memcpy(strings, in, num);
strofs = num;
}
int QCC_MergeValidateString(int str)
{
if (str < 0 || str >= strofs)
str = 0;
return str;
}
static void QCC_MergeFunctions(dfunction_t *in, unsigned int num)
{
numfunctions = 0;
while(num --> 0)
{
if (in->first_statement <= 0)
{
functions[numfunctions].builtin = -in->first_statement;
functions[numfunctions].code = -1;
}
else
{
functions[numfunctions].builtin = 0;
functions[numfunctions].code = in->first_statement;
}
functions[numfunctions].s_filed = QCC_MergeValidateString(in->s_file);
functions[numfunctions].filen = strings+functions[numfunctions].s_filed;
functions[numfunctions].line = 0;
functions[numfunctions].name = strings+QCC_MergeValidateString(in->s_name);
functions[numfunctions].parentscope = NULL;
functions[numfunctions].type = NULL;
functions[numfunctions].def = NULL;
functions[numfunctions].firstlocal = NULL;
functions[numfunctions].privatelocals = true;
functions[numfunctions].merged = in;
numfunctions++;
in++;
}
}
static void QCC_MergeStatements16(dstatement16_t *in, unsigned int num)
{
QCC_statement_t *out = statements;
numstatements = num;
for (; num --> 0; out++, in++)
{
out->op = in->op;
out->a.sym = NULL;
out->a.cast = NULL;
out->a.ofs = in->a;
out->b.sym = NULL;
out->b.cast = NULL;
out->b.ofs = in->b;
out->c.sym = NULL;
out->c.cast = NULL;
out->c.ofs = in->c;
out->linenum = 0;
}
out->op = OP_DONE;
out->a.ofs = 0;
out->b.ofs = 0;
out->c.ofs = 0;
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;
etype_t best = ev_void;
for (i = 0; i < numfields; i++)
{
if (fields[i].ofs == ofs)
{ //sometimes we have field unions. go for the exact name match if we can so we don't get confused over vectors/floats. otherwise just go with the first (and hope they're correctly ordered)
char *name = strings+QCC_MergeValidateString(fields[i].s_name);
if (!strcmp(name, fldname))
return fields[i].type;
if (best == ev_void)
best = fields[i].type;
}
}
return best;
}
static void QCC_MergeUnstrip(dfunction_t *in, unsigned int num)
{
size_t i;
char *name;
QCC_def_t *def;
//functions may have been stripped. this results in an annoying lack of errors, and will likely confuse function wrapping...
//generate a new def for each function, if it doesn't already exist.
//these are probably going to be wasteful dupes, but they'll just get stripped again if they're still not used.
for (i = 0; i < num; i++)
{
if (!in[i].s_name)
continue;
name = strings+QCC_MergeValidateString(in[i].s_name);
def = QCC_PR_GetDef(NULL, name, NULL, false, 0, GDF_BASICTYPE);
if (!def)
{
def = QCC_PR_GetDef(type_function, name, NULL, true, 0, GDF_BASICTYPE);
def->symboldata[def->ofs].function = i;
def->initialized = true;
def->referenced = true;
def->assumedtype = true;
}
QCC_FreeDef(def);
}
}
QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto);
static void QCC_MergeGlobalDefs16(ddef16_t *in, size_t num, void *values, size_t defscount, ddef16_t *fields, size_t numfields)
{
QCC_def_t *root, *def;
QCC_type_t *type;
etype_t evt;
char *name;
unsigned int flags;
pbool referrable;
numpr_globals = 0; //that root object will replace the normal reserved globals.
root = QCC_PR_GetDef(type_void, "", NULL, true, 0, GDF_USED);
root->symboldata = values;
root->symbolsize = defscount;
for (; num --> 0; in++)
{
name = strings+QCC_MergeValidateString(in->s_name);
flags = GDF_USED;
if (in->type & DEF_SAVEGLOBAL)
flags |= GDF_SAVED;
evt = in->type&~DEF_SAVEGLOBAL;
if (evt == ev_field)
evt = QCC_MergeFindFieldType(root->symboldata[in->ofs]._int, name, fields, numfields);
switch(evt)
{
case ev_void:
type = type_void;
break;
case ev_vector:
type = type_vector;
break;
case ev_float:
type = type_float;
break;
case ev_string:
type = type_string;
break;
case ev_entity:
type = type_entity;
break;
case ev_integer:
type = type_integer;
break;
case ev_function:
type = type_function;
break;
default:
type = type_variant;
break;
}
if ((in->type&~DEF_SAVEGLOBAL) == ev_field)
{
type = QCC_PR_FieldType(type);
flags |= GDF_CONST;
}
referrable = true; //fixme: disable if this appears to be within a function's local storage
def = QCC_PR_DummyDef(type, name, NULL, 0, root, in->ofs, referrable, flags);
def->initialized = 1;
def->referenced = true;
def->assumedtype = true;
if (evt == ev_vector)
{
int j = 3;
if ((in->type&~DEF_SAVEGLOBAL) == ev_field)
{
for (j = 0; j < 3; j++)
{
if (in[j+1].ofs == in->ofs+j && (in[j+1].type&~DEF_SAVEGLOBAL) == ev_field && QCC_MergeFindFieldType(root->symboldata[in[j+1].ofs]._int, strings+QCC_MergeValidateString(in[j+1].s_name), fields, numfields) == ev_float)
continue;
break;
}
}
else
{
for (j = 0; j < 3; j++)
{
if (in[j+1].ofs == in->ofs+j && (in[j+1].type&~DEF_SAVEGLOBAL) == ev_float)
continue;
break;
}
}
in += j;
num -= j;
}
}
QCC_FreeDef(root);
}
/*load a progs into the current compile state.*/
void QCC_ImportProgs(const char *filename)
{
int flen;
dprograms_t *prog;
//these keywords are implicitly enabled by #merge
keyword_weak = true;
keyword_wrap = true;
// if (strofs != 0) //could be fixed with relocs
// QCC_Error(ERR_BADEXTENSION, "#merge used too late. It must be used before any other definitions.");
if (numstatements != 1) //should be easy to deal with.
QCC_Error(ERR_BADEXTENSION, "#merge used too late. It must be used before any other definitions.");
if (numfunctions != 1) //could be fixed with relocs
QCC_Error(ERR_BADEXTENSION, "#merge used too late. It must be used before any other definitions.");
if (numglobaldefs != 1) //could be fixed by inserting it properly. any already-defined defs must have their parentdef changed to union them with imported ones.
QCC_Error(ERR_BADEXTENSION, "#merge used too late. It must be used before any other definitions (globals).");
if (numfielddefs != 1) //could be fixed with relocs
QCC_Error(ERR_BADEXTENSION, "#merge used too late. It must be used before any other definitions (fields).");
if (numpr_globals != RESERVED_OFS) //not normally changed until after compiling
QCC_Error(ERR_BADEXTENSION, "#merge used too late. It must be used before any other definitions (regs).");
flen = externs->FileSize(filename);
if (flen < 0)
{
QCC_Error(ERR_COULDNTOPENFILE, "Couldn't open file %s", filename);
return;
}
printf ("\nnote: The #merge feature is still experimental\n\n");
//FIXME: find overlapped locals. strip them. merge with new ones.
//FIXME: find temps. strip them. you get the idea.
//FIXME: find immediates. set up hash tables for them for reuse. HAH!
prog = qccHunkAlloc(flen);
externs->ReadFile(filename, prog, flen, NULL);
if (prog->version == 7 && prog->secondaryversion == PROG_SECONDARYVERSION16 && !prog->blockscompressed && !prog->numtypes)
;
else if (prog->version == 7 && prog->secondaryversion == PROG_SECONDARYVERSION32 && !prog->blockscompressed && !prog->numtypes)
;
else if (prog->version != 6)
{
QCC_Error(ERR_COULDNTOPENFILE, "Unsupported version: %s", filename);
return;
}
QCC_MergeStrings(((char*)prog+prog->ofs_strings), prog->numstrings);
QCC_MergeFunctions((dfunction_t*)((char*)prog+prog->ofs_functions), prog->numfunctions);
pr.size_fields = prog->entityfields;
if (prog->version == 7 && prog->secondaryversion == PROG_SECONDARYVERSION32)
{
// QCC_MergeStatements32((dstatement32_t*)((char*)prog+prog->ofs_statements), prog->numstatements);
// QCC_MergeGlobalDefs32((ddef32_t*)((char*)prog+prog->ofs_globaldefs), prog->numglobaldefs, ((char*)prog)+prog->ofs_globals, prog->numglobals, (ddef16_t*)((char*)prog+prog->ofs_fielddefs), prog->numfielddefs);
QCC_Error(ERR_COULDNTOPENFILE, "32bit versions not supported: %s", filename);
}
else
{
QCC_MergeStatements16((dstatement16_t*)((char*)prog+prog->ofs_statements), prog->numstatements);
QCC_MergeGlobalDefs16((ddef16_t*)((char*)prog+prog->ofs_globaldefs), prog->numglobaldefs, ((char*)prog)+prog->ofs_globals, prog->numglobals, (ddef16_t*)((char*)prog+prog->ofs_fielddefs), prog->numfielddefs);
}
QCC_MergeUnstrip((dfunction_t*)((char*)prog+prog->ofs_functions), prog->numfunctions);
}
/*
@ -2618,8 +2920,13 @@ int QCC_PR_FinishCompilation (void)
QCC_type_t *t;
int errors;
pbool externokay = false;
errors = false;
if (qcc_targetformat == QCF_FTE || qcc_targetformat == QCF_FTEDEBUG || qcc_targetformat == QCF_FTEH2)
externokay = true;
// check to make sure all functions prototyped have code
for (d=pr.def_head.next ; d ; d=d->next)
{
@ -2652,13 +2959,21 @@ int QCC_PR_FinishCompilation (void)
continue;
}
}
QCC_PR_Warning(ERR_NOFUNC, strings + d->s_file, d->s_line, "function %s has no body",d->name);
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;
errors = true;
}
else if (d->initialized==2)
{
if (!externokay)
{
QCC_PR_Warning(ERR_NOFUNC, d->filen, d->s_line, "extern is not supported with this target format",d->name);
QCC_PR_ParsePrintDef(ERR_NOFUNC, d);
errors = true;
}
bodylessfuncs = true;
}
}
}
pr_scope = NULL;
@ -2819,7 +3134,9 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
{
if (!strcmp (d->name, "end_sys_globals"))
break;
// if (d->ofs<RESERVED_OFS)
if (!*d->name)
continue;
// if (d->symbolheader->ofs<RESERVED_OFS)
// continue;
switch (d->type->type)
@ -3389,6 +3706,11 @@ void QCC_CopyFiles (void)
//============================================================================
#ifdef _WIN32
#define WINDOWSARG(x) x
#else
#define WINDOWSARG(x) false
#endif
void QCC_PR_CommandLinePrecompilerOptions (void)
{
@ -3400,6 +3722,47 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
for (i = 1;i<myargc;i++)
{
if ( !strcmp(myargv[i], "-v") )
verbose++; //verbose
else if ( !strcmp(myargv[i], "-srcfile") )
{
if (++i == myargc)
break;
for (j = 0; j < numsourcefiles; j++)
{
if (!strcmp(sourcefileslist[j], myargv[i]))
break;
}
if (j == numsourcefiles)
{
if (numsourcefiles < MAXSOURCEFILESLIST)
strcpy(sourcefileslist[numsourcefiles++], myargv[i]);
else
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "too many -srcfile arguments");
}
}
else if ( !strcmp(myargv[i], "-src") )
{
i++;
strcpy (qccmsourcedir, myargv[i]);
strcat (qccmsourcedir, "/");
}
else if ( !strcmp(myargv[i], "-o") )
; //explicit output file
else if ( !strcmp(myargv[i], "-qc") )
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Argument %s is experimental", myargv[i]); //compile without linking. output cannot be read by engines.
else if ( !strcmp(myargv[i], "-progdefs") )
; //write progdefs.h
else if ( !strcmp(myargv[i], "-copy") )
; //copy files / write pak files
else if ( !strcmp(myargv[i], "-bspmodels") )
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Argument %s is not supported", myargv[i]);
else if ( !strcmp(myargv[i], "-h2") || !strcmp(myargv[i], "-fteh2") || !strcmp(myargv[i], "-fte") || !strcmp(myargv[i], "-dp") )
; //various targets
else if ( !strcmp(myargv[i], "-pak") || !strcmp(myargv[i], "-pak2") )
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Argument %s is not supported", myargv[i]);
else
//compiler constant
if ( !strncmp(myargv[i], "-D", 2) )
{
@ -3427,7 +3790,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
}
//optimisations.
else if ( !strnicmp(myargv[i], "-O", 2) || !strnicmp(myargv[i], "/O", 2) )
else if ( !strnicmp(myargv[i], "-O", 2) || WINDOWSARG(!strnicmp(myargv[i], "/O", 2)) )
{
qcc_nopragmaoptimise = true;
p = 0;
@ -3462,7 +3825,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised optimisation parameter (%s)", myargv[i]);
}
else if ( !strnicmp(myargv[i], "-K", 2) || !strnicmp(myargv[i], "/K", 2) )
else if ( !strnicmp(myargv[i], "-K", 2) || WINDOWSARG(!strnicmp(myargv[i], "/K", 2)) )
{
p = 0;
if (!strnicmp(myargv[i]+2, "no-", 3))
@ -3487,7 +3850,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
if (!compiler_flag[p].enabled)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised keyword parameter (%s)", myargv[i]);
}
else if ( !strnicmp(myargv[i], "-F", 2) || !strnicmp(myargv[i], "/F", 2) )
else if ( !strnicmp(myargv[i], "-F", 2) || WINDOWSARG(!strnicmp(myargv[i], "/F", 2)) )
{
pbool state;
const char *arg;
@ -3527,7 +3890,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
}
else if ( !strncmp(myargv[i], "-T", 2) || !strncmp(myargv[i], "/T", 2) )
else if ( !strncmp(myargv[i], "-T", 2) || WINDOWSARG(!strncmp(myargv[i], "/T", 2)) )
{
p = 0;
if (!strcmp("parse", myargv[i]+2))
@ -3546,7 +3909,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
}
}
else if ( !strnicmp(myargv[i], "-W", 2) || !strnicmp(myargv[i], "/W", 2) )
else if ( !strnicmp(myargv[i], "-W", 2) || WINDOWSARG(!strnicmp(myargv[i], "/W", 2)) )
{
if (!stricmp(myargv[i]+2, "all"))
{
@ -3619,6 +3982,8 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised warning parameter (%s)", myargv[i]);
}
}
else if (*myargv[i] == '-' || WINDOWSARG(*myargv[i] == '/'))
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised parameter (%s)", myargv[i]);
}
if (werror)
@ -3661,6 +4026,9 @@ void QCC_SetDefaultProperties (void)
ForcedCRC = 0;
defaultstatic = 0;
verbose = 0;
*qccmsourcedir = 0;
QCC_PR_CloseProcessor();
QCC_PR_DefineName("FTEQCC");
@ -3728,6 +4096,7 @@ void QCC_SetDefaultProperties (void)
qccwarningaction[WARN_UNINITIALIZED] = WA_IGNORE; //not sure about this being ignored by default.
qccwarningaction[WARN_SELFNOTTHIS] = WA_IGNORE;
qccwarningaction[WARN_EVILPREPROCESSOR] = WA_WARN;//FIXME: make into WA_ERROR;
qccwarningaction[WARN_IDENTICALPRECOMPILER] = WA_IGNORE;
if (qcc_targetformat == QCF_HEXEN2 || qcc_targetformat == QCF_FTEH2)
qccwarningaction[WARN_CASEINSENSITIVEFRAMEMACRO] = WA_IGNORE; //hexenc consides these fair game.
@ -3891,11 +4260,17 @@ pbool QCC_main (int argc, char **argv) //as part of the quake engine
char *s;
s_filen = "cmdline";
s_filed = 0;
pr_source_line = 0;
if (numsourcefiles && currentsourcefile == numsourcefiles)
{
numsourcefiles = 0;
return false;
}
else if (!numsourcefiles)
currentsourcefile = 0;
if (currentsourcefile && qccpersisthunk && numsourcefiles)
QCC_PR_ResetErrorScope(); //don't clear the ram if we're retaining def info
@ -4033,7 +4408,6 @@ pbool QCC_main (int argc, char **argv) //as part of the quake engine
tempsused = 0;
s_file = 0;
QCC_PurgeTemps();
@ -4090,12 +4464,6 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
memset(&extra_parms, 0, sizeof(extra_parms));
#endif
for (p = 1; p<myargc; p++)
{
if ( !QC_strcasecmp("-v", myargv[p]) )
verbose++;
}
if ( QCC_CheckParm ("/?") || QCC_CheckParm ("?") || QCC_CheckParm ("-?") || QCC_CheckParm ("-help") || QCC_CheckParm ("--help"))
{
printf ("qcc looks for progs.src in the current directory.\n");
@ -4130,15 +4498,8 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
pHash_RemoveData = &Hash_RemoveDataInsensitive;
}
p = QCC_CheckParm ("-src");
if (p && p < argc-1 )
{
strcpy (qccmsourcedir, argv[p+1]);
strcat (qccmsourcedir, "/");
if (*qccmsourcedir)
printf ("Source directory: %s\n", qccmsourcedir);
}
else
*qccmsourcedir = '\0';
QCC_InitData ();
@ -4177,8 +4538,6 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
if (!numsourcefiles)
{
p = QCC_CheckParm ("-qc");
if (!p || p >= argc-1 || argv[p+1][0] == '-')
p = QCC_CheckParm ("-srcfile");
if (p && p < argc-1 )
sprintf (qccmprogsdat, "%s", argv[p+1]);
else
@ -4335,6 +4694,13 @@ void QCC_ContinueCompile(void)
return;
}
pr_file_p = qccmsrc;
s_filen = "";
s_filed = 0;
pr_source_line = 0;
QCC_PR_LexWhitespace(false);
qccmsrc = pr_file_p;
qccmsrc = QCC_COM_Parse(qccmsrc);
if (!qccmsrc)
{
@ -4371,18 +4737,51 @@ void QCC_ContinueCompile(void)
}
return;
}
QCC_GenerateRelativePath(qccmfilename, sizeof(qccmfilename), compilingrootfile, qcc_token);
QCC_FindBestInclude(qcc_token, compilingrootfile, 2);
/*
{
int includepath = 0;
while(1)
{
if (includepath)
{
if (includepath > MAXINCLUDEDIRS || !*qccincludedir[includepath-1])
{
QCC_GenerateRelativePath(qccmfilename, sizeof(qccmfilename), compilingrootfile, qcc_token);
break;
}
currentfile = qccincludedir[includepath-1];
}
QCC_Canonicalize(qccmfilename, sizeof(fullname), qcc_token, compilingrootfile);
{
extern progfuncs_t *qccprogfuncs;
if (qccprogfuncs->funcs.parms->FileSize(qccmfilename) == -1)
{
includepath++;
continue;
}
}
break;
}
}
QCC_GenerateRelativePath(qccmfilename, sizeof(qccmfilename), compilingrootfile, qcc_token);
if (autoprototype)
printf ("prototyping %s\n", qccmfilename);
else
{
printf ("compiling %s\n", qccmfilename);
}
QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
if (!QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
QCC_Error (ERR_PARSEERRORS, "Errors have occured\n");
*/
}
void QCC_FinishCompile(void)
{
@ -4394,7 +4793,8 @@ void QCC_FinishCompile(void)
if (setjmp(pr_parse_abort))
QCC_Error(ERR_INTERNAL, "");
s_file = 0;
s_filen = "";
s_filed = 0;
pr_source_line = 0;
if (!QCC_PR_FinishCompilation ())
@ -4510,7 +4910,6 @@ void QCC_FinishCompile(void)
extern QCC_string_t s_file, s_file2;
extern char *pr_file_p;
extern int pr_source_line;
void QCC_PR_ParseDefs (char *classname);
@ -4521,6 +4920,7 @@ void QCC_PR_ParseDefs (char *classname);
void StartNewStyleCompile(void)
{
char *tmp;
if (setjmp(pr_parse_abort))
{
if (++pr_error_count > MAX_ERRORS)
@ -4535,8 +4935,17 @@ void StartNewStyleCompile(void)
compilingfile = qccmprogsdat;
s_filen = tmp = qccHunkAlloc(strlen(compilingfile)+1);
strcpy(tmp, compilingfile);
if (opt_filenames)
{
optres_filenames += strlen(compilingfile)+1;
s_filed = 0;
}
else
s_filed = QCC_CopyString (compilingfile);
pr_file_p = qccmsrc;
s_file = s_file2 = QCC_CopyString (compilingfile);
pr_source_line = 0;
@ -4565,9 +4974,19 @@ void new_QCC_ContinueCompile(void)
if (autoprototype && !parseonly)
{
char *tmp;
qccmsrc = originalqccmsrc;
s_filen = tmp = qccHunkAlloc(strlen(compilingfile)+1);
strcpy(tmp, compilingfile);
if (opt_filenames)
{
optres_filenames += strlen(compilingfile)+1;
s_filed = 0;
}
else
s_filed = QCC_CopyString (compilingfile);
pr_file_p = qccmsrc;
s_file = s_file2 = QCC_CopyString (compilingfile);
autoprototyped = autoprototype;
QCC_SetDefaultProperties();

View File

@ -1,6 +1,7 @@
pbool QC_decodeMethodSupported(int method);
char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char *info, char *buffer);
int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle);
char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, const char *info, char *buffer);
int QC_encode(progfuncs_t *progfuncs, int len, int method, const char *in, int handle);
pbool QC_EnumerateFilesFromBlob(const void *blob, size_t blobsize, void (*cb)(const char *name, const void *compdata, size_t compsize, int method, size_t plainsize));
int QC_encodecrc(int len, char *in);
char *PDECL filefromprogs(pubprogfuncs_t *progfuncs, progsnum_t prnum, char *fname, size_t *size, char *buffer);

View File

@ -1,5 +1,5 @@
#include "progsint.h"
//#include "qcc.h"
#include "qcc.h"
#ifndef NO_ZLIB
#define AVAIL_ZLIB
@ -35,7 +35,7 @@ pbool QC_decodeMethodSupported(int method)
return false;
}
char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char *info, char *buffer)
char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, const char *info, char *buffer)
{
int i;
if (method == 0) //copy
@ -49,11 +49,11 @@ char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char *
for (i = 0; i < len; i++)
buffer[i] = info[i] ^ 0xA5;
}
else if (method == 2) //compression (ZLIB)
{
#ifdef AVAIL_ZLIB
else if (method == 2 || method == 8) //compression (ZLIB)
{
z_stream strm = {
info,
(char*)info,
complen,
0,
@ -73,12 +73,15 @@ char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char *
0
};
inflateInit(&strm);
if (method == 8)
inflateInit2(&strm, -MAX_WBITS);
else
inflateInit(&strm);
if (Z_STREAM_END != inflate(&strm, Z_FINISH)) //decompress it in one go.
Sys_Error("Failed block decompression\n");
inflateEnd(&strm);
#endif
}
#endif
//add your decryption/decompression routine here.
else
Sys_Error("Bad file encryption routine\n");
@ -96,10 +99,10 @@ int QC_encodecrc(int len, char *in)
return 0;
#endif
}
void SafeWrite(int hand, void *buf, long count);
void SafeWrite(int hand, const void *buf, long count);
int SafeSeek(int hand, int ofs, int mode);
//we are allowed to trash our input here.
int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle)
int QC_encode(progfuncs_t *progfuncs, int len, int method, const char *in, int handle)
{
int i;
if (method == 0) //copy, allows a lame pass-through.
@ -107,20 +110,20 @@ int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle)
SafeWrite(handle, in, len);
return len;
}
else if (method == 1) //xor encryption, not secure. maybe useful for the string table.
/*else if (method == 1) //xor encryption, not secure. maybe useful for the string table.
{
for (i = 0; i < len; i++)
in[i] = in[i] ^ 0xA5;
SafeWrite(handle, in, len);
return len;
}
}*/
else if (method == 2 || method == 8) //compression (ZLIB)
{
#ifdef AVAIL_ZLIB
char out[8192];
z_stream strm = {
in,
(char *)in,
len,
0,
@ -169,6 +172,75 @@ int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle)
}
#endif
static int QC_ReadRawInt(const unsigned char *blob)
{
return (blob[0]<<0) | (blob[1]<<8) | (blob[2]<<16) | (blob[3]<<24);
}
static int QC_ReadRawShort(const unsigned char *blob)
{
return (blob[0]<<0) | (blob[1]<<8);
}
pbool QC_EnumerateFilesFromBlob(const void *blob, size_t blobsize, void (*cb)(const char *name, const void *compdata, size_t compsize, int method, size_t plainsize))
{
unsigned int cdentries;
unsigned int cdlen;
const unsigned char *eocd;
const unsigned char *cd;
int nl,el,cl;
if (blobsize < 22)
return false;
eocd = blob;
eocd += blobsize-22;
if (QC_ReadRawInt(eocd+0) != 0x06054b50)
return false;
if (QC_ReadRawShort(eocd+4) || QC_ReadRawShort(eocd+6) || QC_ReadRawShort(eocd+20) || QC_ReadRawShort(eocd+8) != QC_ReadRawShort(eocd+10))
return false;
cd = blob;
cd += QC_ReadRawInt(eocd+16);
cdlen = QC_ReadRawInt(eocd+12);
cdentries = QC_ReadRawInt(eocd+10);
if (cd+cdlen>=(const unsigned char*)blob+blobsize)
return false;
for(; cdentries --> 0; cd += 46 + nl+el+cl)
{
if (QC_ReadRawInt(cd+0) != 0x02014b50)
break;
nl = QC_ReadRawShort(cd+28);
el = QC_ReadRawShort(cd+30);
cl = QC_ReadRawShort(cd+32);
if (QC_ReadRawShort(cd+8) != 0)
continue;
{
const unsigned char *le = (const unsigned char*)blob + QC_ReadRawInt(cd+42);
unsigned int csize, usize, method;
char name[256];
if (QC_ReadRawInt(le+0) != 0x04034b50)
continue;
if (QC_ReadRawShort(le+6) != 0) //general purpose flags
continue;
method = QC_ReadRawShort(le+8);
if (method != 0 && method != 8)
continue;
if (nl != QC_ReadRawShort(le+26))
continue; //name is weird...
if (el != QC_ReadRawShort(le+28))
continue; //name is weird...
csize = QC_ReadRawInt(le+18);
usize = QC_ReadRawInt(le+22);
QC_strlcpy(name, cd+46, (nl+1<sizeof(name))?nl+1:sizeof(name));
cb(name, le+30+QC_ReadRawShort(le+26)+QC_ReadRawShort(le+28), csize, method, usize);
}
}
return true;
}
char *PDECL filefromprogs(pubprogfuncs_t *ppf, progsnum_t prnum, char *fname, size_t *size, char *buffer)
{
progfuncs_t *progfuncs = (progfuncs_t*)ppf;

View File

@ -1,5 +1,8 @@
#if !defined(MINIMAL) && !defined(OMIT_QCC)
//decompiling a progs should normally be done by walking the function table and emitting each def leading up to the one that refers to the function in question.
//this of course assumes strict ordering
//#include "qcc.h"
#include "progsint.h"
#include "setjmp.h"
@ -861,7 +864,7 @@ pbool PDECL QC_Decompile(pubprogfuncs_t *ppf, char *fname)
f=SafeOpenWrite("qcdtest/defs.qc", 1024*512);
writes(f, "//Decompiled code can contain little type info.\r\n#define NOWARNINGS\r\n");
writes(f, "//Decompiled code can contain little type info.\r\n");
FigureOutTypes(progfuncs);

View File

@ -2070,28 +2070,6 @@ void QC_Clear(void)
{
}
int prnumforfile;
int PR_SizeOfFile(char *filename)
{
size_t sz;
// int size;
if (!svprogfuncs)
return -1;
prnumforfile=svs.numprogs-1;
while(prnumforfile>=0)
{
if ((qbyte *)svprogfuncs->filefromprogs(svprogfuncs, prnumforfile, filename, &sz, NULL)==(qbyte *)-1)
return sz;
prnumforfile--;
}
return -1;
}
qbyte *PR_OpenFile(char *filename, qbyte *buffer)
{
return svprogfuncs->filefromprogs(svprogfuncs, prnumforfile, filename, NULL, buffer);
}
//#define RETURN_EDICT(pf, e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(pf, e))
#define RETURN_SSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it.
@ -4314,7 +4292,7 @@ vector aim(entity, missilespeed)
=============
*/
//cvar_t sv_aim = {"sv_aim", "0.93"};
cvar_t sv_aim = SCVAR("sv_aim", "2");
cvar_t sv_aim = CVAR("sv_aim", "2");
static void QCBUILTIN PF_aim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
edict_t *ent, *check, *bestent;
@ -10951,6 +10929,26 @@ void PR_DumpPlatform_f(void)
#else
//eg: pr_dumpplatform -FFTE -TCS -O csplat
const char *keywords[] =
{
"ignore" //0
"qwqc", //qw
"nqqc", //nq
"ssqc" //qw|nq
"csqc" //cs
"csqwqc", //cs|qw
"csnqqc", //cs|nq
"gameqc" //cs|nq|qw
"menuonly" //mn
"mnqwqc", //mn|qw
"mnnqqc", //mn|nq
"mnssqc" //mn|qw|nq
"mncsqc" //mn|cs
"mncsqwqc", //mn|cs|qw
"mncsnqqc", //mn|cs|nq
"" //mn|cs|nq|qw
};
int idx;
int i, j;
int d = 0, nd, k;
@ -11345,11 +11343,11 @@ void PR_DumpPlatform_f(void)
{"CONTENTBIT_MONSTERCLIP", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_MONSTERCLIP)},
{"CONTENTBIT_BODY", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_BODY)},
{"CONTENTBIT_CORPSE", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_CORPSE)},
{"CONTENTBIT_Q2LADDER", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(Q2CONTENTS_LADDER)},
{"CONTENTBIT_SKY", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_SKY)},
{"CONTENTBITS_POINTSOLID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(MASK_POINTSOLID)},
{"CONTENTBITS_BOXSOLID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(MASK_BOXSOLID)},
{"CONTENTBITS_FLUID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_FLUID)},
{"CONTENTBIT_Q2LADDER", "const int", QW|NQ|CS, "Content bit specific to q2bsp", 0,STRINGIFY(Q2CONTENTS_LADDER)},
{"CONTENTBIT_SKY", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_SKY)"i"},
{"CONTENTBITS_POINTSOLID", "const int", QW|NQ|CS, "Bits that traceline would normally consider solid", 0,"CONTENTBIT_SOLID|"STRINGIFY(Q2CONTENTS_WINDOW)"|CONTENTBIT_BODY"},
{"CONTENTBITS_BOXSOLID", "const int", QW|NQ|CS, "Bits that tracebox would normally consider solid", 0,"CONTENTBIT_SOLID|"STRINGIFY(Q2CONTENTS_WINDOW)"|CONTENTBIT_BODY|CONTENTBIT_PLAYERCLIP"},
{"CONTENTBITS_FLUID", "const int", QW|NQ|CS, NULL, 0,"CONTENTBIT_WATER|CONTENTBIT_SLIME|CONTENTBIT_LAVA|CONTENTBIT_SKY"},
{"CHAN_AUTO", "const float", QW|NQ|CS, "The automatic channel, play as many sounds on this channel as you want, and they'll all play, however the other channels will replace each other.", CHAN_AUTO},
{"CHAN_WEAPON", "const float", QW|NQ|CS, NULL, CHAN_WEAPON},
@ -11889,22 +11887,28 @@ void PR_DumpPlatform_f(void)
VFS_PRINTF(f, "#define %s\n", QSG_Extensions[i].name);
}
VFS_PRINTF(f, "\n");
if (accessors)
{
VFS_PRINTF(f, "accessor strbuf : float;\n");
VFS_PRINTF(f, "accessor searchhandle : float;\n");
VFS_PRINTF(f, "accessor hashtable : float;\n");
VFS_PRINTF(f, "accessor infostring : string;\n");
VFS_PRINTF(f, "accessor filestream : float;\n");
}
else
{
VFS_PRINTF(f, "#define strbuf float\n");
VFS_PRINTF(f, "#define searchhandle float\n");
VFS_PRINTF(f, "#define hashtable float\n");
VFS_PRINTF(f, "#define infostring string\n");
VFS_PRINTF(f, "#define filestream float\n");
}
VFS_PRINTF(f, "#define _ACCESSORS;\n");
VFS_PRINTF(f,
"#ifdef _ACCESSORS\n"
"accessor strbuf : float;\n"
"accessor searchhandle : float;\n"
"accessor hashtable : float;\n"
"accessor infostring : string;\n"
"accessor filestream : float;\n"
"accessor filestream : float;\n"
"#else\n"
"#define strbuf float\n"
"#define searchhandle float\n"
"#define hashtable float\n"
"#define infostring string\n"
"#define filestream float\n"
"#endif\n"
);
VFS_PRINTF(f, "\n");
for (i = 0; knowndefs[i].name; i++)
@ -12238,6 +12242,7 @@ void PR_DumpPlatform_f(void)
if (accessors)
{
VFS_PRINTF(f, "#ifdef _ACCESSORS\n");
VFS_PRINTF(f,
"accessor strbuf : float\n{\n"
"\tinline get float asfloat[float idx] = {return stof(bufstr_get(this, idx));};\n"
@ -12274,6 +12279,7 @@ void PR_DumpPlatform_f(void)
"\tget string = fgets;\n"
"\tinline set string = {fputs(this,value);};\n"
"};\n");
VFS_PRINTF(f, "#endif\n");
}
VFS_PRINTF(f, "#pragma noref 0\n");

View File

@ -738,7 +738,7 @@ typedef struct {
int maxsize;
} dbuffer_t;
#define DEMO_FRAMES 64
#define DEMO_FRAMES 64 //why is this not just 2?
#define DEMO_FRAMES_MASK (DEMO_FRAMES - 1)
typedef struct
@ -758,6 +758,7 @@ typedef struct
qboolean fixangle[MAX_CLIENTS];
float fixangletime[MAX_CLIENTS];
vec3_t angles[MAX_CLIENTS];
qboolean resetdeltas;
int parsecount;
int lastwritten;
demo_frame_t frames[DEMO_FRAMES];
@ -1486,7 +1487,7 @@ char *SV_Demo_CurrentOutput(void);
void SV_MVDInit(void);
char *SV_MVDNum(char *buffer, int bufferlen, int num);
void SV_SendMVDMessage(void);
void SV_MVD_WriteReliables(void);
void SV_MVD_WriteReliables(qboolean writebroadcasts);
qboolean SV_ReadMVD (void);
void SV_FlushDemoSignon (void);
void DestFlush(qboolean compleate);

View File

@ -37,7 +37,7 @@ qboolean SV_MayCheat(void)
}
extern cvar_t cl_warncmd;
cvar_t sv_cheats = SCVARF("sv_cheats", "0", CVAR_LATCH);
cvar_t sv_cheats = CVARF("sv_cheats", "0", CVAR_LATCH);
extern redirect_t sv_redirected;
extern cvar_t sv_public;

View File

@ -46,32 +46,32 @@ client_t *host_client; // current client
// bound the size of the physics time tic
#ifdef SERVERONLY
cvar_t sv_mintic = CVARD("sv_mintic","0.013", "The minimum interval between running physics frames.");
cvar_t sv_mintic = CVARD("sv_mintic","0.013", "The minimum interval between running physics frames.");
#else
cvar_t sv_mintic = CVARD("sv_mintic","0", "The minimum interval between running physics frames."); //client builds can think as often as they want.
cvar_t sv_mintic = CVARD("sv_mintic","0", "The minimum interval between running physics frames."); //client builds can think as often as they want.
#endif
cvar_t sv_maxtic = CVARD("sv_maxtic","0.1", "The maximum interval between running physics frames. If the value is too low, multiple physics interations might be run at a time (based upon sv_limittics). Set identical to sv_mintic for fixed-interval ticks, which may be required if ODE is used.");//never run a tick slower than this
cvar_t sv_limittics = CVARD("sv_limittics","3", "The maximum number of ticks that may be run within a frame, to allow the server to catch up if it stalled or if sv_maxtic is too low.");//
cvar_t sv_maxtic = CVARD("sv_maxtic","0.1", "The maximum interval between running physics frames. If the value is too low, multiple physics interations might be run at a time (based upon sv_limittics). Set identical to sv_mintic for fixed-interval ticks, which may be required if ODE is used.");//never run a tick slower than this
cvar_t sv_limittics = CVARD("sv_limittics","3", "The maximum number of ticks that may be run within a frame, to allow the server to catch up if it stalled or if sv_maxtic is too low.");//
cvar_t sv_nailhack = CVARD("sv_nailhack","0", "If set to 1, disables the nail entity networking optimisation. This hack was popularised by qizmo which recommends it for better compression. Also allows clients to interplate nail positions and add trails.");
cvar_t sv_nopvs = CVARD("sv_nopvs", "0", "Set to 1 to ignore pvs on the server. This can make wallhacks more dangerous, so should only be used for debugging.");
cvar_t fraglog_public = CVARD("fraglog_public", "1", "Enables support for connectionless fraglog requests");
cvar_t fraglog_details = CVARD("fraglog_details", "1", "Bitmask\n1: killer+killee names.\n2: killer+killee teams\n4:timestamp.\n8:killer weapon\n16:killer+killee guid.\nFor compatibility, use 1(vanilla) or 7(mvdsv).");
cvar_t sv_nailhack = CVARD("sv_nailhack","0", "If set to 1, disables the nail entity networking optimisation. This hack was popularised by qizmo which recommends it for better compression. Also allows clients to interplate nail positions and add trails.");
cvar_t sv_nopvs = CVARD("sv_nopvs", "0", "Set to 1 to ignore pvs on the server. This can make wallhacks more dangerous, so should only be used for debugging.");
cvar_t fraglog_public = CVARD("fraglog_public", "1", "Enables support for connectionless fraglog requests");
cvar_t fraglog_details = CVARD("fraglog_details", "1", "Bitmask\n1: killer+killee names.\n2: killer+killee teams\n4:timestamp.\n8:killer weapon\n16:killer+killee guid.\nFor compatibility, use 1(vanilla) or 7(mvdsv).");
cvar_t timeout = SCVAR("timeout","65"); // seconds without any message
cvar_t zombietime = SCVAR("zombietime", "2"); // seconds to sink messages
cvar_t timeout = CVAR("timeout","65"); // seconds without any message
cvar_t zombietime = CVAR("zombietime", "2"); // seconds to sink messages
// after disconnect
#ifdef SERVERONLY
cvar_t developer = SCVAR("developer","0"); // show extra messages
cvar_t developer = CVAR("developer","0"); // show extra messages
cvar_t rcon_password = SCVARF("rcon_password", "", CVAR_NOUNSAFEEXPAND); // password for remote server commands
cvar_t password = SCVARF("password", "", CVAR_NOUNSAFEEXPAND); // password for entering the game
cvar_t rcon_password = CVARF("rcon_password", "", CVAR_NOUNSAFEEXPAND); // password for remote server commands
cvar_t password = CVARF("password", "", CVAR_NOUNSAFEEXPAND); // password for entering the game
#else
extern cvar_t developer;
extern cvar_t rcon_password;
extern cvar_t password;
#endif
cvar_t spectator_password = CVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator
cvar_t spectator_password = CVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator
cvar_t allow_download = CVARD("allow_download", "1", "If 1, permits downloading. Set to 0 to unconditionally block *ALL* downloads.");
cvar_t allow_download_skins = CVARD("allow_download_skins", "1", "0 blocks downloading of any file in the skins/ directory");
@ -88,46 +88,46 @@ cvar_t allow_download_packages = CVARD("allow_download_packages", "1", "if 1, p
cvar_t allow_download_refpackages = CVARD("allow_download_refpackages", "1", "If set to 1, packages that contain files needed during spawn functions will be become 'referenced' and automatically downloaded to clients.\nThis cvar should probably not be set if you have large packages that provide replacement pickup models on public servers.\nThe path command will show a '(ref)' tag next to packages which clients will automatically attempt to download.");
cvar_t allow_download_wads = CVARD("allow_download_wads", "1", "0 blocks downloading of any file in the wads/ directory, or is in the root directory with the extension .wad");
cvar_t allow_download_configs = CVARD("allow_download_configs", "0", "1 allows downloading of config files, either with the extension .cfg or in the subdir configs/.\n"CON_ERROR"THIS IS DANGEROUS AS IT CAN ALLOW PEOPLE TO READ YOUR RCON PASSWORD.");
cvar_t allow_download_locs = CVARD("allow_download_locs", "1", "0 blocks downloading of any file in the locs/ directory");
cvar_t allow_download_locs = CVARD("allow_download_locs", "1", "0 blocks downloading of any file in the locs/ directory");
cvar_t allow_download_copyrighted = CVARD("allow_download_copyrighted", "0", "0 blocks download of packages that are considered copyrighted. Specifically, this means packages with a leading 'pak' prefix on the filename.\nIf you take your copyrights seriously, you should also set allow_download_pakmaps 0 and allow_download_pakcontents 0.");
cvar_t allow_download_other = CVARD("allow_download_other", "0", "0 blocks downloading of any file that was not covered by any of the directory download blocks.");
extern cvar_t sv_allow_splitscreen;
cvar_t sv_serverip = CVARD("sv_serverip", "", "Set this cvar to the server's public ip address if the server is behind a firewall and cannot detect its own public address. Providing a port is required if the firewall/nat remaps it, but is otherwise optional.");
cvar_t sv_public = CVAR("sv_public", "0");
cvar_t sv_listen_qw = CVARAF("sv_listen_qw", "1", "sv_listen", 0);
cvar_t sv_listen_nq = CVARD("sv_listen_nq", "2", "Allow new (net)quake clients to connect to the server.\n0 = don't let them in.\n1 = allow them in (WARNING: this allows 'qsmurf' DOS attacks).\n2 = accept (net)quake clients by emulating a challenge (as secure as QW/Q2 but does not fully conform to the NQ protocol).");
cvar_t sv_listen_dp = CVARD("sv_listen_dp", "0", "Allows the server to respond with the DP-specific handshake protocol.\nWarning: this can potentially get confused with quake2, and results in race conditions with both vanilla netquake and quakeworld protocols.\nOn the plus side, DP clients can usually be identified correctly, enabling a model+sound limit boost.");
cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0");
cvar_t sv_reportheartbeats = CVAR("sv_reportheartbeats", "1");
cvar_t sv_highchars = CVAR("sv_highchars", "1");
cvar_t sv_maxrate = CVAR("sv_maxrate", "30000");
cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "500000",
"sv_maxdownloadrate", 0);
cvar_t sv_minping = CVARF("sv_minping", "", CVAR_SERVERINFO);
cvar_t sv_serverip = CVARD("sv_serverip", "", "Set this cvar to the server's public ip address if the server is behind a firewall and cannot detect its own public address. Providing a port is required if the firewall/nat remaps it, but is otherwise optional.");
cvar_t sv_public = CVAR("sv_public", "0");
cvar_t sv_listen_qw = CVARAF("sv_listen_qw", "1", "sv_listen", 0);
cvar_t sv_listen_nq = CVARD("sv_listen_nq", "2", "Allow new (net)quake clients to connect to the server.\n0 = don't let them in.\n1 = allow them in (WARNING: this allows 'qsmurf' DOS attacks).\n2 = accept (net)quake clients by emulating a challenge (as secure as QW/Q2 but does not fully conform to the NQ protocol).");
cvar_t sv_listen_dp = CVARD("sv_listen_dp", "0", "Allows the server to respond with the DP-specific handshake protocol.\nWarning: this can potentially get confused with quake2, and results in race conditions with both vanilla netquake and quakeworld protocols.\nOn the plus side, DP clients can usually be identified correctly, enabling a model+sound limit boost.");
cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0");
cvar_t sv_reportheartbeats = CVAR("sv_reportheartbeats", "1");
cvar_t sv_highchars = CVAR("sv_highchars", "1");
cvar_t sv_maxrate = CVAR("sv_maxrate", "30000");
cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "500000",
"sv_maxdownloadrate", 0);
cvar_t sv_minping = CVARF("sv_minping", "", CVAR_SERVERINFO);
cvar_t sv_bigcoords = CVARFD("sv_bigcoords", "1", 0, "Uses floats for coordinates instead of 16bit values.\nAlso boosts angle precision, so can be useful even on small maps.\nAffects clients thusly:\nQW: enforces a mandatory protocol extension\nDP: enables DPP7 protocol support\nNQ: uses RMQ protocol (protocol 999).");
cvar_t sv_calcphs = CVARFD("sv_calcphs", "2", CVAR_LATCH, "Enables culling of sound effects. 0=always skip phs. Sounds are globally broadcast. 1=always generate phs. Sounds are always culled. On large maps the phs will be dumped to disk. 2=On large single-player maps, generation of phs is skipped. Otherwise like option 1.");
cvar_t sv_bigcoords = CVARFD("sv_bigcoords", "1", 0, "Uses floats for coordinates instead of 16bit values.\nAlso boosts angle precision, so can be useful even on small maps.\nAffects clients thusly:\nQW: enforces a mandatory protocol extension\nDP: enables DPP7 protocol support\nNQ: uses RMQ protocol (protocol 999).");
cvar_t sv_calcphs = CVARFD("sv_calcphs", "2", CVAR_LATCH, "Enables culling of sound effects. 0=always skip phs. Sounds are globally broadcast. 1=always generate phs. Sounds are always culled. On large maps the phs will be dumped to disk. 2=On large single-player maps, generation of phs is skipped. Otherwise like option 1.");
cvar_t sv_showconnectionlessmessages = CVARD("sv_showconnectionlessmessages", "0", "Display a line describing each connectionless message that arrives on the server. Primarily a debugging feature, but also potentially useful to admins.");
cvar_t sv_cullplayers_trace = CVARFD("sv_cullplayers_trace", "", CVAR_SERVERINFO, "Attempt to cull player entities using tracelines as an anti-wallhack.");
cvar_t sv_cullentities_trace = CVARFD("sv_cullentities_trace", "", CVAR_SERVERINFO, "Attempt to cull non-player entities using tracelines as an extreeme anti-wallhack.");
cvar_t sv_phs = CVARD("sv_phs", "1", "If 1, do not use the phs. It is generally better to use sv_calcphs instead, and leave this as 1.");
cvar_t sv_resetparms = CVAR("sv_resetparms", "0");
cvar_t sv_pupglow = CVARFD("sv_pupglow", "", CVAR_SERVERINFO, "Instructs clients to enable hexen2-style powerup pulsing.");
cvar_t sv_showconnectionlessmessages = CVARD("sv_showconnectionlessmessages", "0", "Display a line describing each connectionless message that arrives on the server. Primarily a debugging feature, but also potentially useful to admins.");
cvar_t sv_cullplayers_trace = CVARFD("sv_cullplayers_trace", "", CVAR_SERVERINFO, "Attempt to cull player entities using tracelines as an anti-wallhack.");
cvar_t sv_cullentities_trace = CVARFD("sv_cullentities_trace", "", CVAR_SERVERINFO, "Attempt to cull non-player entities using tracelines as an extreeme anti-wallhack.");
cvar_t sv_phs = CVARD("sv_phs", "1", "If 1, do not use the phs. It is generally better to use sv_calcphs instead, and leave this as 1.");
cvar_t sv_resetparms = CVAR("sv_resetparms", "0");
cvar_t sv_pupglow = CVARFD("sv_pupglow", "", CVAR_SERVERINFO, "Instructs clients to enable hexen2-style powerup pulsing.");
cvar_t sv_master = CVAR("sv_master", "0");
cvar_t sv_masterport = CVAR("sv_masterport", "0");
cvar_t sv_master = CVAR("sv_master", "0");
cvar_t sv_masterport = CVAR("sv_masterport", "0");
cvar_t pext_ezquake_nochunks = CVARD("pext_ezquake_nochunks", "0", "Prevents ezquake clients from being able to use the chunked download extension. This sidesteps numerous ezquake issues, and will make downloads slower but more robust.");
cvar_t pext_ezquake_nochunks = CVARD("pext_ezquake_nochunks", "0", "Prevents ezquake clients from being able to use the chunked download extension. This sidesteps numerous ezquake issues, and will make downloads slower but more robust.");
cvar_t sv_gamespeed = CVARAF("sv_gamespeed", "1", "slowmo", 0);
cvar_t sv_csqcdebug = CVAR("sv_csqcdebug", "0");
cvar_t sv_csqc_progname = CVAR("sv_csqc_progname", "csprogs.dat");
cvar_t pausable = CVAR("pausable", "1");
cvar_t sv_banproxies = CVARD("sv_banproxies", "0", "If enabled, anyone connecting via known proxy software will be refused entry. This should aid with blocking aimbots, but is only reliable for certain public proxies.");
cvar_t sv_specprint = CVARD("sv_specprint", "3", "Bitfield that controls which player events spectators see when tracking that player.\n&1: spectators will see centerprints.\n&2: spectators will see sprints (pickup messages etc).\n&4: spectators will receive console commands, this is potentially risky.\nIndividual spectators can use 'setinfo sp foo' to limit this setting.");
cvar_t sv_gamespeed = CVARAF("sv_gamespeed", "1", "slowmo", 0);
cvar_t sv_csqcdebug = CVAR("sv_csqcdebug", "0");
cvar_t sv_csqc_progname = CVAR("sv_csqc_progname", "csprogs.dat");
cvar_t pausable = CVAR("pausable", "1");
cvar_t sv_banproxies = CVARD("sv_banproxies", "0", "If enabled, anyone connecting via known proxy software will be refused entry. This should aid with blocking aimbots, but is only reliable for certain public proxies.");
cvar_t sv_specprint = CVARD("sv_specprint", "3", "Bitfield that controls which player events spectators see when tracking that player.\n&1: spectators will see centerprints.\n&2: spectators will see sprints (pickup messages etc).\n&4: spectators will receive console commands, this is potentially risky.\nIndividual spectators can use 'setinfo sp foo' to limit this setting.");
//
@ -4415,6 +4415,11 @@ static void SV_PauseChanged(void)
ClientReliableWrite_Byte (cl, sv.paused!=0);
}
}
if (sv.mvdrecording)
{
ClientReliableWrite_Begin (&demo.recorder, svc_setpause, 2);
ClientReliableWrite_Byte (&demo.recorder, sv.paused!=0);
}
}
/*

View File

@ -40,7 +40,7 @@ cvar_t sv_demofps = CVAR("sv_demofps", "30");
cvar_t sv_demoPings = CVARD("sv_demoPings", "10", "Interval between ping updates in mvds");
cvar_t sv_demoMaxSize = CVARD("sv_demoMaxSize", "", "Demos will be truncated to be no larger than this size.");
cvar_t sv_demoExtraNames = CVAR("sv_demoExtraNames", "");
cvar_t sv_demoExtensions = CVARD("sv_demoExtensions", "0", "Enables protocol extensions within MVDs. This will cause older/non-fte clients to error upon playback");
cvar_t sv_demoExtensions = CVARD("sv_demoExtensions", "", "Enables protocol extensions within MVDs. This will cause older/non-fte clients to error upon playback.\n0: off.\n1: all extensions.\n2: extensions also supported by a certain other engine.");
cvar_t qtv_password = CVAR( "qtv_password", "");
cvar_t qtv_streamport = CVARAF( "qtv_streamport", "0",
@ -105,7 +105,7 @@ static void DestClose(mvddest_t *d, enum mvdclosereason_e reason)
else if (d->desttype != DEST_STREAM)
{
char buf[512];
SV_BroadcastPrintf (PRINT_CHAT, "Server recording complete\n/download demos/%s", COM_QuotedString(d->name, buf, sizeof(buf), false));
SV_BroadcastPrintf (PRINT_CHAT, "Server recording complete\n^[/download %s^]\n", COM_QuotedString(va("demos/%s",d->name), buf, sizeof(buf), false));
}
Z_Free(d);
@ -134,8 +134,11 @@ void DestFlush(qboolean compleate)
int len;
mvddest_t *d, *t;
//make sure everything is flushed.
MVDWrite_Begin(255, -1, 0);
if (compleate)
{
//make sure everything is flushed.
MVDWrite_Begin(255, -1, 0);
}
if (!demo.dest)
return;
@ -380,7 +383,7 @@ void SV_MVD_RunPendingConnections(void)
start = start+1;
while(*start == ' ' || *start == '\t')
start++;
Con_Printf("qtv, got (%s) (%s)\n", com_token, start);
Con_DPrintf("qtv, got (%s) (%s)\n", com_token, start);
if (!strcmp(com_token, "VERSION"))
{
start = COM_ParseToken(start, NULL);
@ -429,6 +432,14 @@ void SV_MVD_RunPendingConnections(void)
{
//compression not supported yet
}
else if (!strcmp(com_token, "QTV_EZQUAKE_EXT"))
{
//if we were treating this as a regular client over tcp (qizmo...)
}
else if (!strcmp(com_token, "USERINFO"))
{
//if we were treating this as a regular client over tcp (qizmo...)
}
else
{
//not recognised.
@ -865,77 +876,9 @@ void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
MSG_WriteString (msg, info);
}
#if 0
/*
==============
DemoWriteToDisk
Writes to disk a message meant for specifc client
or all messages if type == 0
Message is cleared from demobuf after that
==============
*/
static void SV_MVDWriteToDisk(int type, int to, float time)
{
int pos = 0, oldm, oldd;
header_t *p;
int size;
sizebuf_t msg;
p = (header_t *)demo.dbuf->sb.data;
demo.dbuf->h = NULL;
oldm = demo.dbuf->bufsize;
oldd = demobuffer->start;
while (pos < demo.dbuf->bufsize)
{
size = p->size;
pos += header + size;
// no type means we are writing to disk everything
if (!type || (p->type == type && p->to == to))
{
if (size)
{
msg.data = p->data;
msg.cursize = size;
SV_WriteMVDMessage(&msg, p->type, p->to, time);
}
// data is written so it need to be cleard from demobuf
if (demo.dbuf->sb.data != (qbyte*)p)
memmove(demo.dbuf->sb.data + size + header, demo.dbuf->sb.data, (qbyte*)p - demo.dbuf->sb.data);
demo.dbuf->bufsize -= size + header;
demo.dbuf->sb.data += size + header;
pos -= size + header;
demo.dbuf->sb.maxsize -= size + header;
demobuffer->start += size + header;
}
// move along
p = (header_t *)(p->data + size);
}
if (demobuffer->start == demobuffer->last)
{
if (demobuffer->start == demobuffer->end)
{
demobuffer->end = 0; // demobuffer is empty
demo.dbuf->sb.data = demobuffer->data;
}
// go back to begining of the buffer
demobuffer->last = demobuffer->end;
demobuffer->start = 0;
}
}
#endif
sizebuf_t *MVDWrite_Begin(qbyte type, int to, int size)
{
if (demomsg.cursize && demomsgtype != type && demomsgto != to && demomsg.cursize+size > sizeof(demomsgbuf))
if (demomsg.cursize && (demomsgtype != type || demomsgto != to || demomsg.cursize+size > sizeof(demomsgbuf)))
{
SV_WriteMVDMessage(&demomsg, demomsgtype, demomsgto, demo_prevtime);
demomsg.cursize = 0;
@ -945,51 +888,9 @@ sizebuf_t *MVDWrite_Begin(qbyte type, int to, int size)
demomsgto = to;
demomsg.maxsize = demomsg.cursize+size;
demomsg.cursize = 0;
demomsg.data = demomsgbuf;
demomsg.prim = demo.recorder.netchan.netprim;
return &demomsg;
#if 0
qbyte *p;
qboolean move = false;
// will it fit?
while (demo.dbuf->bufsize + size + header > demo.dbuf->sb.maxsize)
{
// if we reached the end of buffer move msgbuf to the begining
if (!move && demobuffer->end > demobuffer->start)
move = true;
if (!SV_MVDWritePackets(1))
return false;
if (move && demobuffer->start > demo.dbuf->bufsize + header + size)
MVDMoveBuf();
}
if (demo.dbuf->h == NULL || demo.dbuf->h->type != type || demo.dbuf->h->to != to || demo.dbuf->h->full) {
MVDSetBuf(type, to);
}
if (demo.dbuf->h->size + size > MAX_QWMSGLEN)
{
demo.dbuf->h->full = 1;
MVDSetBuf(type, to);
}
// we have to make room for new data
if (demo.dbuf->sb.cursize != demo.dbuf->bufsize) {
p = demo.dbuf->sb.data + demo.dbuf->sb.cursize;
memmove(p+size, p, demo.dbuf->bufsize - demo.dbuf->sb.cursize);
}
demo.dbuf->bufsize += size;
demo.dbuf->h->size += size;
if ((demobuffer->end += size) > demobuffer->last)
demobuffer->last = demobuffer->end;
return true;
#endif
}
/*
@ -1007,19 +908,30 @@ void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time)
if (!sv.mvdrecording)
return;
if (msg->overflowed)
{
msg->overflowed = false;
Con_Printf("SV_WriteMVDMessage: message overflowed\n");
return;
}
msec = (time - demo_prevtime)*1000;
if (abs(msec) > 1000)
{
//catastoptic slip. debugging? reset any sync
msec = 0;
msec = 1;
demo_prevtime = time;
}
else
{
if (msec > 255) msec = 255;
if (msec < 2) msec = 0;
else if (msec > 0)
{ //if there was any progress, make sure we write msecs >0
if (msec > 255)
msec = 255;
if (msec < 1)
msec = 1;
demo_prevtime += msec*0.001;
}
else
msec = 0;
c = msec;
DemoWrite(&c, sizeof(c));
@ -1065,20 +977,23 @@ void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time)
}
//if you use ClientReliable to write to demo.recorder's message buffer (for code reuse) call this function to ensure its flushed.
void SV_MVD_WriteReliables(void)
void SV_MVD_WriteReliables(qboolean writebroadcasts)
{
int i;
//chuck in the broadcast reliables
ClientReliableCheckBlock(&demo.recorder, sv.reliable_datagram.cursize);
ClientReliableWrite_SZ(&demo.recorder, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
//and the broadcast unreliables. everything is reliables when it comes to mvds
ClientReliableCheckBlock(&demo.recorder, sv.datagram.cursize);
ClientReliableWrite_SZ(&demo.recorder, sv.datagram.data, sv.datagram.cursize);
if (writebroadcasts)
{
//chuck in the broadcast reliables
ClientReliableCheckBlock(&demo.recorder, sv.reliable_datagram.cursize);
ClientReliableWrite_SZ(&demo.recorder, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
//and the broadcast unreliables. everything is reliables when it comes to mvds
ClientReliableCheckBlock(&demo.recorder, sv.datagram.cursize);
ClientReliableWrite_SZ(&demo.recorder, sv.datagram.data, sv.datagram.cursize);
}
if (demo.recorder.netchan.message.cursize)
{
SV_WriteMVDMessage(&demo.recorder.netchan.message, dem_all, 0, sv.time);
SV_WriteMVDMessage(&demo.recorder.netchan.message, dem_all, 0, demo_prevtime);
demo.recorder.netchan.message.cursize = 0;
}
for (i = 0; i < demo.recorder.num_backbuf; i++)
@ -1086,7 +1001,7 @@ void SV_MVD_WriteReliables(void)
demo.recorder.backbuf.data = demo.recorder.backbuf_data[i];
demo.recorder.backbuf.cursize = demo.recorder.backbuf_size[i];
if (demo.recorder.backbuf.cursize)
SV_WriteMVDMessage(&demo.recorder.backbuf, dem_all, 0, sv.time);
SV_WriteMVDMessage(&demo.recorder.backbuf, dem_all, 0, demo_prevtime);
demo.recorder.backbuf_size[i] = 0;
}
demo.recorder.num_backbuf = 0;
@ -1143,6 +1058,8 @@ qboolean SV_MVDWritePackets (int num)
//flush any intermediate data
MVDWrite_Begin(255, -1, 0);
msg.allowoverflow = true; //fixme
msg.overflowed = false;
msg.prim = svs.netprim;
msg.data = msg_buf;
msg.maxsize = sizeof(msg_buf);
@ -1714,6 +1631,7 @@ qboolean SV_MVD_Record (mvddest_t *dest)
if (!dest)
return false;
SV_MVD_WriteReliables(false);
DestFlush(true);
if (!sv.mvdrecording)
@ -1726,7 +1644,7 @@ qboolean SV_MVD_Record (mvddest_t *dest)
demo.datagram.data = demo.datagram_data;
demo.datagram.prim = demo.recorder.netchan.netprim;
if (sv_demoExtensions.ival == 2)
if (sv_demoExtensions.ival == 2 || !*sv_demoExtensions.string)
{ /*more limited subset supported by ezquake*/
demo.recorder.fteprotocolextensions = PEXT_CHUNKEDDOWNLOADS|PEXT_256PACKETENTITIES|PEXT_FLOATCOORDS|PEXT_MODELDBL|PEXT_ENTITYDBL|PEXT_ENTITYDBL2|PEXT_SPAWNSTATIC2;
// demo.recorder.fteprotocolextensions |= PEXT_HLBSP; /*ezquake DOES have this, but it is pointless and should have been in some feature mask rather than protocol extensions*/
@ -1773,6 +1691,7 @@ qboolean SV_MVD_Record (mvddest_t *dest)
SV_MVD_SendInitialGamestate(dest);
return true;
}
void SV_EnableClientsCSQC(void);
void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{
@ -1788,7 +1707,10 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (!demo.dest)
return;
SV_MVD_WriteReliables(false);
sv.mvdrecording = true;
demo.resetdeltas = true;
host_client = &demo.recorder;
if (host_client->fteprotocolextensions & PEXT_CSQC)
@ -1860,7 +1782,6 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
#if 1
demo.recorder.prespawn_stage = PRESPAWN_SERVERINFO;
demo.recorder.prespawn_idx = 0;
demo.recorder.netchan.message = buf;
@ -1875,181 +1796,10 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
demo.recorder.prespawn_allow_modellist = true; //normally set for the server to wait for ack. we don't want to wait.
SV_SendClientPrespawnInfo(&demo.recorder);
SV_WriteRecordMVDMessage (&demo.recorder.netchan.message);
SZ_Clear (&demo.recorder.netchan.message);
SV_MVD_WriteReliables(false);
}
memset(&demo.recorder.netchan.message, 0, sizeof(demo.recorder.netchan.message));
#else
// send music
MSG_WriteByte (&buf, svc_cdtrack);
MSG_WriteByte (&buf, 0); // none in demos
// send server info string
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", svs.info) );
// flush packet
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
// soundlist
MSG_WriteByte (&buf, svc_soundlist); /*FIXME: soundlist2*/
MSG_WriteByte (&buf, 0);
n = 0;
s = sv.strings.sound_precache[n+1];
while (*s)
{
MSG_WriteString (&buf, s);
if (buf.cursize > MAX_QWMSGLEN/2)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, n + 1);
}
n++;
s = sv.strings.sound_precache[n+1];
}
if (buf.cursize)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
}
// modellist
MSG_WriteByte (&buf, svc_modellist); /*FIXME: modellist2*/
MSG_WriteByte (&buf, 0);
n = 0;
s = sv.strings.model_precache[n+1];
while (s)
{
MSG_WriteString (&buf, s);
if (buf.cursize > MAX_QWMSGLEN/2)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_modellist);
MSG_WriteByte (&buf, n + 1);
}
n++;
s = sv.strings.model_precache[n+1];
}
if (buf.cursize)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
}
// baselines
{
entity_state_t from;
edict_t *ent;
entity_state_t *state;
memset(&from, 0, sizeof(from));
for (n = 0; n < sv.world.num_edicts; n++)
{
ent = EDICT_NUM(svprogfuncs, n);
state = &ent->baseline;
if (!state->number || !state->modelindex)
{ //ent doesn't have a baseline
continue;
}
if (demo.recorder.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
MSG_WriteByte(&buf, svcfte_spawnbaseline2);
SVFTE_EmitBaseline(state, true, &buf);
}
else if (!ent)
{
MSG_WriteByte(&buf, svc_spawnbaseline);
MSG_WriteShort (&buf, n);
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
for (i=0 ; i<3 ; i++)
{
MSG_WriteCoord(&buf, 0);
MSG_WriteAngle(&buf, 0);
}
}
else if (demo.recorder.fteprotocolextensions & PEXT_SPAWNSTATIC2)
{
MSG_WriteByte(&buf, svcfte_spawnbaseline2);
SVQW_WriteDelta(&from, state, &buf, true, demo.recorder.fteprotocolextensions);
}
else
{
MSG_WriteByte(&buf, svc_spawnbaseline);
MSG_WriteShort (&buf, n);
MSG_WriteByte (&buf, state->modelindex&255);
MSG_WriteByte (&buf, state->frame);
MSG_WriteByte (&buf, (int)state->colormap);
MSG_WriteByte (&buf, (int)state->skinnum);
for (i=0 ; i<3 ; i++)
{
MSG_WriteCoord(&buf, state->origin[i]);
MSG_WriteAngle(&buf, state->angles[i]);
}
}
if (buf.cursize > MAX_QWMSGLEN/2)
{
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
}
}
}
//prespawn
for (n = 0; n < sv.num_signon_buffers; n++)
{
if (buf.cursize+sv.signon_buffer_size[n] > MAX_QWMSGLEN/2)
{
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
}
SZ_Write (&buf,
sv.signon_buffers[n],
sv.signon_buffer_size[n]);
}
if (buf.cursize > MAX_QWMSGLEN/2)
{
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
}
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("cmd spawn %i\n",svs.spawncount) );
if (buf.cursize)
{
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
}
#endif
// send current status of all other players
for (i = 0; i < demo.recorder.max_net_clients && i < svs.allocated_client_slots; i++)
@ -2060,6 +1810,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (buf.cursize > MAX_QWMSGLEN/2)
{
//flush backbuffer
SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf);
}
@ -2096,8 +1847,8 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{
for (j = 0; j < MAX_CL_STATS; j++)
{
demo.statsi[i][j] ^= -1;
demo.statsf[i][j] *= -0.41426712; //randomish value
demo.statsi[i][j] = 0x7fffffff;
demo.statsf[i][j] = -0x7fffffff;
}
demo.playerreset[i] = true;
}
@ -2108,7 +1859,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
MSG_WriteString (&buf, "skins\n");
SV_WriteRecordMVDMessage (&buf);
SV_MVD_WriteReliables(false);
SV_WriteSetMVDMessage();
singledest = NULL;

View File

@ -42,18 +42,18 @@ solid_edge items only clip against bsp models.
*/
cvar_t sv_maxvelocity = SCVAR("sv_maxvelocity","10000");
cvar_t sv_maxvelocity = CVAR("sv_maxvelocity","10000");
cvar_t sv_gravity = SCVAR( "sv_gravity", "800");
cvar_t sv_stopspeed = SCVAR( "sv_stopspeed", "100");
cvar_t sv_maxspeed = SCVAR( "sv_maxspeed", "320");
cvar_t sv_spectatormaxspeed = SCVAR( "sv_spectatormaxspeed", "500");
cvar_t sv_accelerate = SCVAR( "sv_accelerate", "10");
cvar_t sv_airaccelerate = SCVAR( "sv_airaccelerate", "0.7");
cvar_t sv_wateraccelerate = SCVAR( "sv_wateraccelerate", "10");
cvar_t sv_friction = SCVAR( "sv_friction", "4");
cvar_t sv_waterfriction = SCVAR( "sv_waterfriction", "4");
cvar_t sv_gameplayfix_noairborncorpse = SCVAR( "sv_gameplayfix_noairborncorpse", "0");
cvar_t sv_gravity = CVAR( "sv_gravity", "800");
cvar_t sv_stopspeed = CVAR( "sv_stopspeed", "100");
cvar_t sv_maxspeed = CVAR( "sv_maxspeed", "320");
cvar_t sv_spectatormaxspeed = CVAR( "sv_spectatormaxspeed", "500");
cvar_t sv_accelerate = CVAR( "sv_accelerate", "10");
cvar_t sv_airaccelerate = CVAR( "sv_airaccelerate", "0.7");
cvar_t sv_wateraccelerate = CVAR( "sv_wateraccelerate", "10");
cvar_t sv_friction = CVAR( "sv_friction", "4");
cvar_t sv_waterfriction = CVAR( "sv_waterfriction", "4");
cvar_t sv_gameplayfix_noairborncorpse = CVAR( "sv_gameplayfix_noairborncorpse", "0");
cvar_t sv_gameplayfix_multiplethinks = CVARD( "sv_gameplayfix_multiplethinks", "1", "Enables multiple thinks per entity per frame so small nextthink times are accurate. QuakeWorld mods expect a value of 1.");
cvar_t sv_gameplayfix_stepdown = CVARD( "sv_gameplayfix_stepdown", "0", "Attempt to step down steps, instead of only up them. Affects non-predicted movetype_walk.");
#if !defined(CLIENTONLY) && defined(NQPROT) && !defined(NOLEGACY)

View File

@ -2634,7 +2634,7 @@ void SV_FlushBroadcasts (void)
}
}
SV_MVD_WriteReliables();
SV_MVD_WriteReliables(true);
SZ_Clear (&sv.reliable_datagram);
SZ_Clear (&sv.datagram);
@ -3322,8 +3322,6 @@ void SV_SendMVDMessage(void)
// possibly a nails update
msg.cursize = 0;
msg.prim = demo.recorder.netchan.netprim;
if (!demo.recorder.delta_sequence)
demo.recorder.delta_sequence = -1;
// copy the accumulated multicast datagram
// for this client out to the message
@ -3339,7 +3337,13 @@ void SV_SendMVDMessage(void)
SV_MVDWritePackets(1);
}
demo.recorder.delta_sequence = demo.recorder.netchan.incoming_sequence&255;
if (demo.resetdeltas)
{
demo.resetdeltas = false;
demo.recorder.delta_sequence = -1;
}
else
demo.recorder.delta_sequence = demo.recorder.netchan.incoming_sequence&255;
demo.recorder.netchan.incoming_sequence++;
demo.frames[demo.parsecount&DEMO_FRAMES_MASK].time = demo.time = sv.time;

View File

@ -102,11 +102,11 @@ static dllfunction_t sqlitefuncs[] =
dllhandle_t *sqlitehandle;
#endif
cvar_t sql_driver = SCVARF("sv_sql_driver", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_host = SCVARF("sv_sql_host", "127.0.0.1", CVAR_NOUNSAFEEXPAND);
cvar_t sql_username = SCVARF("sv_sql_username", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_password = SCVARF("sv_sql_password", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_defaultdb = SCVARF("sv_sql_defaultdb", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_driver = CVARF("sv_sql_driver", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_host = CVARF("sv_sql_host", "127.0.0.1", CVAR_NOUNSAFEEXPAND);
cvar_t sql_username = CVARF("sv_sql_username", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_password = CVARF("sv_sql_password", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_defaultdb = CVARF("sv_sql_defaultdb", "", CVAR_NOUNSAFEEXPAND);
void SQL_PushResult(sqlserver_t *server, queryresult_t *qres)
{

View File

@ -42,9 +42,9 @@ cvar_t cl_rollangle = SCVAR("cl_rollangle", "2.0");
extern cvar_t cl_rollspeed;
extern cvar_t cl_rollangle;
#endif
cvar_t sv_spectalk = SCVAR("sv_spectalk", "1");
cvar_t sv_spectalk = CVAR("sv_spectalk", "1");
cvar_t sv_mapcheck = SCVAR("sv_mapcheck", "1");
cvar_t sv_mapcheck = CVAR("sv_mapcheck", "1");
cvar_t sv_fullredirect = CVARD("sv_fullredirect", "", "This is the ip:port to redirect players to when the server is full");
cvar_t sv_antilag = CVARFD("sv_antilag", "", CVAR_SERVERINFO, "Attempt to backdate impacts to compensate for lag. 0=completely off. 1=mod-controlled. 2=forced, which might break certain uses of traceline.");
@ -60,9 +60,9 @@ cvar_t sv_protocol_nq = CVARD("sv_protocol_nq", "", "Specifies the default prot
cvar_t sv_minpitch = CVARAFD("minpitch", "", "sv_minpitch", CVAR_SERVERINFO, "Assumed to be -70");
cvar_t sv_maxpitch = CVARAFD("maxpitch", "", "sv_maxpitch", CVAR_SERVERINFO, "Assumed to be 80");
cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password.
cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server.
cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", STRINGIFY(RESTRICT_LOCAL)); //execution level which gamecode is told about (for unrecognised commands)
cvar_t sv_cmdlikercon = CVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password.
cvar_t cmd_allowaccess = CVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server.
cvar_t cmd_gamecodelevel = CVAR("cmd_gamecodelevel", STRINGIFY(RESTRICT_LOCAL)); //execution level which gamecode is told about (for unrecognised commands)
cvar_t sv_pure = CVARFD("sv_pure", "", CVAR_SERVERINFO, "The most evil cvar in the world, many clients will ignore this.\n0=standard quake rules.\n1=clients should prefer files within packages present on the server.\n2=clients should use *only* files within packages present on the server.\nDue to quake 1.01/1.06 differences, a setting of 2 only works in total conversions.");
cvar_t sv_nqplayerphysics = CVARAD("sv_nqplayerphysics", "0", "sv_nomsec", "Disable player prediction and run NQ-style player physics instead. This can be used for compatibility with mods that expect exact behaviour.");
@ -98,14 +98,14 @@ extern cvar_t pm_airstep;
extern cvar_t pm_walljump;
extern cvar_t pm_watersinkspeed;
extern cvar_t pm_flyfriction;
cvar_t sv_pushplayers = SCVAR("sv_pushplayers", "0");
cvar_t sv_pushplayers = CVAR("sv_pushplayers", "0");
//yes, realip cvars need to be fully initialised or realip will be disabled
cvar_t sv_getrealip = CVARD("sv_getrealip", "0", "Attempt to obtain a more reliable IP for clients, rather than just their proxy.");
cvar_t sv_realip_kick = SCVAR("sv_realip_kick", "0");
cvar_t sv_realip_kick = CVAR("sv_realip_kick", "0");
cvar_t sv_realiphostname_ipv4 = CVARD("sv_realiphostname_ipv4", "", "This is the server's public ip:port. This is needed for realip to work when the autodetected/local ip is not globally routable");
cvar_t sv_realiphostname_ipv6 = CVARD("sv_realiphostname_ipv6", "", "This is the server's public ip:port. This is needed for realip to work when the autodetected/local ip is not globally routable");
cvar_t sv_realip_timeout = SCVAR("sv_realip_timeout", "10");
cvar_t sv_realip_timeout = CVAR("sv_realip_timeout", "10");
#ifdef VOICECHAT
cvar_t sv_voip = CVARD("sv_voip", "1", "Enable reception of voice packets.");
@ -1015,7 +1015,7 @@ void SV_SendClientPrespawnInfo(client_t *client)
else if (client->prespawn_idx == 4)
{
ClientReliableWrite_Begin(client, svc_setpause, 2);
ClientReliableWrite_Byte (client, sv.paused);
ClientReliableWrite_Byte (client, sv.paused!=0);
}
else
{

View File

@ -2847,6 +2847,9 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
}
}
//create the platform-specific surface
createSurface();
//figure out which gpu we're going to use
{
uint32_t gpucount = 0, i;
@ -2863,7 +2866,24 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
for (i = 0; i < gpucount; i++)
{
VkPhysicalDeviceProperties props;
uint32_t j, queue_count;
vkGetPhysicalDeviceProperties(devs[i], &props);
vkGetPhysicalDeviceQueueFamilyProperties(devs[i], &queue_count, NULL);
for (j = 0; j < queue_count; j++)
{
VkBool32 supportsPresent;
VkAssert(vkGetPhysicalDeviceSurfaceSupportKHR(devs[i], j, vk.surface, &supportsPresent));
if (supportsPresent)
break; //okay, this one should be usable
}
if (j == queue_count)
{
//no queues can present to that surface, so I guess we can't use that device
Con_DPrintf("vulkan: ignoring device %s as it can't present to window\n", props.deviceName);
continue;
}
if (!vk.gpu)
vk.gpu = devs[i];
switch(props.deviceType)
@ -2954,9 +2974,6 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
);
}
//create the platform-specific surface
createSurface();
//figure out which of the device's queue's we're going to use
{
uint32_t queue_count, i;