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

@ -57,8 +57,8 @@ cvar_t cl_hightrack = CVARD("cl_hightrack", "0", "Obsolete. If you want hightrac
//cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" }; //cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" };
//cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" }; //cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" };
cvar_t cl_chasecam = SCVAR("cl_chasecam", "1"); cvar_t cl_chasecam = CVAR("cl_chasecam", "1");
cvar_t cl_selfcam = SCVAR("cl_selfcam", "1"); cvar_t cl_selfcam = CVAR("cl_selfcam", "1");
void Cam_AutoTrack_Update(const char *mode) void Cam_AutoTrack_Update(const char *mode)
{ {

View file

@ -585,7 +585,7 @@ qboolean CL_GetDemoMessage (void)
olddemotime = demtime; olddemotime = demtime;
if (msglength > MAX_NQMSGLEN) if (msglength > net_message.maxsize)
{ {
Con_Printf ("Demo message > MAX_MSGLEN"); Con_Printf ("Demo message > MAX_MSGLEN");
CL_StopPlayback (); CL_StopPlayback ();
@ -684,7 +684,7 @@ readnext:
cls.td_starttime = Sys_DoubleTime(); cls.td_starttime = Sys_DoubleTime();
demtime = demotime; // warp 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 { // always grab until fully connected
if (demtime + 1.0 < demotime) if (demtime + 1.0 < demotime)
{ {
@ -993,7 +993,7 @@ void CL_WriteRecordQ2DemoMessage(sizebuf_t *msg)
==================== ====================
CL_WriteDemoMessage 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) void CL_WriteRecordDemoMessage (sizebuf_t *msg, int seq)
@ -1008,6 +1008,18 @@ void CL_WriteRecordDemoMessage (sizebuf_t *msg, int seq)
if (!cls.demorecording) if (!cls.demorecording)
return; return;
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); fl = LittleFloat(Sys_DoubleTime()-recdemostart);
VFS_WRITE (cls.demooutfile, &fl, sizeof(fl)); VFS_WRITE (cls.demooutfile, &fl, sizeof(fl));
@ -1020,9 +1032,11 @@ void CL_WriteRecordDemoMessage (sizebuf_t *msg, int seq)
i = LittleLong(seq); i = LittleLong(seq);
VFS_WRITE (cls.demooutfile, &i, 4); VFS_WRITE (cls.demooutfile, &i, 4);
VFS_WRITE (cls.demooutfile, &i, 4); VFS_WRITE (cls.demooutfile, &i, 4);
}
VFS_WRITE (cls.demooutfile, msg->data, msg->cursize); VFS_WRITE (cls.demooutfile, msg->data, msg->cursize);
SZ_Clear(msg);
if (record_flush.ival) if (record_flush.ival)
VFS_FLUSH (cls.demooutfile); VFS_FLUSH (cls.demooutfile);
} }
@ -1110,6 +1124,353 @@ void CL_RecordMap_f (void)
} }
#endif #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); const char *Get_Q2ConfigString(int i);
/* /*
@ -1124,11 +1485,9 @@ void CL_Record_f (void)
int c; int c;
char name[MAX_OSPATH]; char name[MAX_OSPATH];
sizebuf_t buf; sizebuf_t buf;
char buf_data[MAX_QWMSGLEN]; char buf_data[MAX_OVERALLMSGLEN];
int n, i, j, seat; int n, i, seat;
char *s, *p, *fname; char *s, *p, *fname;
entity_t *ent;
entity_state_t *es;
player_info_t *player; player_info_t *player;
extern char gamedirfile[]; extern char gamedirfile[];
int seq = 1; int seq = 1;
@ -1153,8 +1512,8 @@ void CL_Record_f (void)
if (cls.protocol == CP_QUAKE2) if (cls.protocol == CP_QUAKE2)
defaultext = ".dm2"; defaultext = ".dm2";
// else if (cls.protocol == CP_NETQUAKE) else if (cls.protocol == CP_NETQUAKE && !CPNQ_IS_DP)
// defaultext = ".dem"; defaultext = ".dem";
else if (cls.protocol == CP_QUAKEWORLD) else if (cls.protocol == CP_QUAKEWORLD)
defaultext = ".qwd"; defaultext = ".qwd";
else else
@ -1169,6 +1528,9 @@ void CL_Record_f (void)
if (c == 2) //user supplied a name if (c == 2) //user supplied a name
{ {
fname = Cmd_Argv(1); fname = Cmd_Argv(1);
s = strrchr(fname, '.');
if (!Q_strcasecmp(s, defaultext))
*s = 0; //hack away that extension that they added.
} }
else else
{ //automagically generate a name { //automagically generate a name
@ -1230,8 +1592,7 @@ void CL_Record_f (void)
|| c=='<' || c=='>' || c=='"' || c=='.') || c=='<' || c=='>' || c=='"' || c=='.')
*p = '_'; *p = '_';
} }
strncpy(name, fname, sizeof(name)-1-8); Q_strncpyz(name, fname, sizeof(name)-8);
name[sizeof(name)-1-8] = '\0';
//make a unique name (unless the user specified it). //make a unique name (unless the user specified it).
strcat (name, defaultext); //we have the space strcat (name, defaultext); //we have the space
@ -1242,9 +1603,11 @@ void CL_Record_f (void)
f = FS_OpenVFS (name, "rb", FS_GAME); f = FS_OpenVFS (name, "rb", FS_GAME);
if (f) if (f)
{ {
COM_StripExtension(name, name, sizeof(name)); //remove the extension again
Q_strncpyz(name, fname, sizeof(name)-8);
p = name + strlen(name); p = name + strlen(name);
strcat(p, "_XX.qwd"); strcat(p, "_XX");
strcat(p, defaultext);
p++; p++;
i = 0; i = 0;
do do
@ -1282,67 +1645,12 @@ void CL_Record_f (void)
switch(cls.protocol) switch(cls.protocol)
{ {
case CP_QUAKEWORLD: case CP_QUAKEWORLD:
if (!cls.fteprotocolextensions && !cls.fteprotocolextensions2)
buf.maxsize = MAX_QWMSGLEN; //poo compatibility... :P
cls.demorecording = DPB_QUAKEWORLD; cls.demorecording = DPB_QUAKEWORLD;
// serverdata CLQW_RecordServerData(&buf);
// 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) );
// send music // send music
Media_WriteCurrentTrack(&buf); Media_WriteCurrentTrack(&buf);
@ -1378,7 +1686,7 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, svc_setpause); MSG_WriteByte (&buf, svc_setpause);
MSG_WriteByte (&buf, cl.paused); MSG_WriteByte (&buf, !!cl.paused);
#ifdef PEXT_SETVIEW #ifdef PEXT_SETVIEW
if (cl.playerview[0].viewentity != cl.playerview[0].playernum+1) //tell the player if we have a different view entity 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 #endif
// flush packet // flush packet
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
// soundlist // soundlist
MSG_WriteByte (&buf, svc_soundlist); MSG_WriteByte (&buf, svc_soundlist);
@ -1405,7 +1712,7 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n); MSG_WriteByte (&buf, n);
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
if (n + 1 > 0xff) if (n + 1 > 0xff)
{ {
MSG_WriteByte (&buf, svcfte_soundlistshort); MSG_WriteByte (&buf, svcfte_soundlistshort);
@ -1425,7 +1732,6 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
} }
//FIXME: vweps //FIXME: vweps
@ -1444,7 +1750,7 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n); MSG_WriteByte (&buf, n);
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
if (n + 1 > 0xff) if (n + 1 > 0xff)
{ {
MSG_WriteByte (&buf, svcfte_modellistshort); MSG_WriteByte (&buf, svcfte_modellistshort);
@ -1464,131 +1770,15 @@ void CL_Record_f (void)
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
} }
//particleeffectnum stuff seq = CL_Record_ParticlesStaticsBaselines(&buf, seq);
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);
}
}
}
MSG_WriteByte (&buf, svc_stufftext); MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("cmd spawn %i\n", cl.servercount) ); MSG_WriteString (&buf, va("cmd spawn %i\n", cl.servercount) );
if (buf.cursize) if (buf.cursize)
{
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
// send current status of all other players // send current status of all other players
@ -1633,44 +1823,10 @@ void CL_Record_f (void)
} }
if (buf.cursize > buf.maxsize/2) if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
} }
// send all current light styles seq = CL_Record_Lightstyles(&buf, seq);
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);
}
}
for (seat = 0; seat < cl.splitclients; seat++) for (seat = 0; seat < cl.splitclients; seat++)
{ {
@ -1712,10 +1868,7 @@ void CL_Record_f (void)
} }
if (buf.cursize > buf.maxsize/2) if (buf.cursize > buf.maxsize/2)
{
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
} }
} }
@ -1775,8 +1928,37 @@ void CL_Record_f (void)
CL_WriteRecordQ2DemoMessage (&buf); CL_WriteRecordQ2DemoMessage (&buf);
break; break;
#endif #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: default:
//this should have been caught earlier
Con_Printf("Unable to begin demo recording with this network protocol\n"); Con_Printf("Unable to begin demo recording with this network protocol\n");
CL_Stop_f(); CL_Stop_f();
break; break;
@ -1820,6 +2002,8 @@ void CL_ReRecord_f (void)
Q_snprintfz (name, sizeof(name), "%s", s); Q_snprintfz (name, sizeof(name), "%s", s);
CL_Disconnect();
// //
// open the demo file // open the demo file
// //
@ -1854,7 +2038,9 @@ void CL_ReRecord_f (void)
Con_Printf ("recording to %s.\n", name); 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(); 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_c2sdupe = CVAR("cl_c2sdupe", "0");
cvar_t cl_c2spps = CVAR("cl_c2spps", "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_netfps = CVAR("cl_netfps", "150");
cvar_t cl_sparemsec = CVARC("cl_sparemsec", "10", CL_SpareMsec_Callback); cvar_t cl_sparemsec = CVARC("cl_sparemsec", "10", CL_SpareMsec_Callback);
cvar_t cl_queueimpulses = CVAR("cl_queueimpulses", "0"); 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_upspeed = CVARF("cl_upspeed","400", CVAR_ARCHIVE);
cvar_t cl_forwardspeed = SCVARF("cl_forwardspeed","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_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_yawspeed = CVAR("cl_yawspeed","140");
cvar_t cl_pitchspeed = SCVAR("cl_pitchspeed","150"); 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) 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); 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 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 *host_basepal;
qbyte *h2playertranslations; 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 #ifdef CRAZYDEBUGGING
cvar_t developer = SCVAR("developer","1"); cvar_t developer = CVAR("developer","1");
#else #else
cvar_t developer = SCVAR("developer","0"); cvar_t developer = CVAR("developer","0");
#endif #endif
int fps_count; int fps_count;
@ -5824,6 +5824,7 @@ void Host_Shutdown(void)
COM_DestroyWorkerThread(); COM_DestroyWorkerThread();
P_ShutdownParticleSystem();
Cvar_Shutdown(); Cvar_Shutdown();
Validation_FlushFileList(); Validation_FlushFileList();

View file

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

View file

@ -2842,7 +2842,7 @@ void CLQW_ParseServerData (void)
CL_DownloadFailed(cls.download->remotename, cls.download); 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 // wipe the client_state_t struct
// //
@ -3132,7 +3132,7 @@ void CLQ2_ParseServerData (void)
cls.fteprotocolextensions2 = 0; cls.fteprotocolextensions2 = 0;
cls.demohadkeyframe = true; //assume that it did, so this stuff all gets recorded. 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 // wipe the client_state_t struct
// //
@ -3427,8 +3427,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
int nummodels, numsounds; int nummodels, numsounds;
char *str; char *str;
int gametype; int gametype;
if (developer.ival) Con_DPrintf ("Serverdata packet %s.\n", cls.demoplayback?"read":"received");
Con_TPrintf ("Serverdata packet received.\n");
SCR_SetLoadingStage(LS_CLIENT); SCR_SetLoadingStage(LS_CLIENT);
CL_ClearState (); CL_ClearState ();
Stats_NewMap(); Stats_NewMap();
@ -3436,8 +3435,10 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
CLNQ_ParseProtoVersion(); 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); 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_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_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_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_nopred = CVAR("cl_nopred","0");
cvar_t cl_pushlatency = SCVAR("pushlatency","-999"); cvar_t cl_pushlatency = CVAR("pushlatency","-999");
extern float pm_airaccelerate; extern float pm_airaccelerate;

View file

@ -224,19 +224,19 @@ float scr_disabled_time;
float oldsbar = 0; 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 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 = CVARF("show_fps", "0", CVAR_ARCHIVE);
cvar_t show_fps_x = SCVAR("show_fps_x", "-1"); cvar_t show_fps_x = CVAR("show_fps_x", "-1");
cvar_t show_fps_y = SCVAR("show_fps_y", "-1"); cvar_t show_fps_y = CVAR("show_fps_y", "-1");
cvar_t show_clock = SCVAR("cl_clock", "0"); cvar_t show_clock = CVAR("cl_clock", "0");
cvar_t show_clock_x = SCVAR("cl_clock_x", "0"); cvar_t show_clock_x = CVAR("cl_clock_x", "0");
cvar_t show_clock_y = SCVAR("cl_clock_y", "-1"); cvar_t show_clock_y = CVAR("cl_clock_y", "-1");
cvar_t show_gameclock = SCVAR("cl_gameclock", "0"); cvar_t show_gameclock = CVAR("cl_gameclock", "0");
cvar_t show_gameclock_x = SCVAR("cl_gameclock_x", "0"); cvar_t show_gameclock_x = CVAR("cl_gameclock_x", "0");
cvar_t show_gameclock_y = SCVAR("cl_gameclock_y", "-1"); cvar_t show_gameclock_y = CVAR("cl_gameclock_y", "-1");
cvar_t show_speed = SCVAR("show_speed", "0"); cvar_t show_speed = CVAR("show_speed", "0");
cvar_t show_speed_x = SCVAR("show_speed_x", "-1"); cvar_t show_speed_x = CVAR("show_speed_x", "-1");
cvar_t show_speed_y = SCVAR("show_speed_y", "-9"); cvar_t show_speed_y = CVAR("show_speed_y", "-9");
cvar_t scr_loadingrefresh = SCVAR("scr_loadingrefresh", "0"); cvar_t scr_loadingrefresh = CVAR("scr_loadingrefresh", "0");
cvar_t scr_showloading = CVAR("scr_showloading", "1"); cvar_t scr_showloading = CVAR("scr_showloading", "1");
cvar_t scr_showobituaries = CVAR("scr_showobituaries", "0"); cvar_t scr_showobituaries = CVAR("scr_showobituaries", "0");

View file

@ -58,14 +58,14 @@ qterm_t *activeqterm;
float con_cursorspeed = 4; float con_cursorspeed = 4;
cvar_t con_numnotifylines = SCVAR("con_notifylines","4"); //max lines to show cvar_t con_numnotifylines = CVAR("con_notifylines","4"); //max lines to show
cvar_t con_notifytime = SCVAR("con_notifytime","3"); //seconds cvar_t con_notifytime = CVAR("con_notifytime","3"); //seconds
cvar_t con_notify_x = SCVAR("con_notify_x","0"); cvar_t con_notify_x = CVAR("con_notify_x","0");
cvar_t con_notify_y = SCVAR("con_notify_y","0"); cvar_t con_notify_y = CVAR("con_notify_y","0");
cvar_t con_notify_w = SCVAR("con_notify_w","1"); cvar_t con_notify_w = CVAR("con_notify_w","1");
cvar_t con_centernotify = SCVAR("con_centernotify", "0"); cvar_t con_centernotify = CVAR("con_centernotify", "0");
cvar_t con_displaypossibilities = SCVAR("con_displaypossibilities", "1"); cvar_t con_displaypossibilities = CVAR("con_displaypossibilities", "1");
cvar_t con_maxlines = SCVAR("con_maxlines", "1024"); 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 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_numnotifylines_chat = CVAR("con_numnotifylines_chat", "8");
cvar_t con_notifytime_chat = CVAR("con_notifytime_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++) for (i = 0; i < countof(p->mirror); i++)
Z_Free(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->qhash);
Z_Free(p->arch); Z_Free(p->arch);
Z_Free(p); Z_Free(p);

View file

@ -407,6 +407,7 @@ static void SL_PreDraw (menu_t *menu)
info->numslots = Master_NumSorted(); info->numslots = Master_NumSorted();
snprintf(info->refreshtext, sizeof(info->refreshtext), "Refresh - %u/%u/%u\n", info->numslots, Master_NumAlive(), Master_TotalCount()); 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 void SL_PostDraw (menu_t *menu)
{ {
static char *helpstrings[] = static char *helpstrings[] =
@ -436,6 +437,31 @@ static void SL_PostDraw (menu_t *menu)
{ {
selectedserver.refreshtime = realtime + 4; selectedserver.refreshtime = realtime + 4;
server->sends++; server->sends++;
#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); Master_QueryServer(server);
} }
R2D_ImageColours(1,1,1,1); R2D_ImageColours(1,1,1,1);

View file

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

View file

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

View file

@ -209,7 +209,7 @@ qboolean m_recursiveDraw;
void M_ConfigureNetSubsystem(void); 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); 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", "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_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_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) {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. //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_cacheinfo = CVAR("slist_cacheinfo", "0"); //this proves dangerous, memory wise.
cvar_t slist_writeserverstxt = SCVAR("slist_writeservers", "0"); cvar_t slist_writeserverstxt = CVAR("slist_writeservers", "0");
void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad); void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad);
int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favorite); int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favorite);
@ -1904,6 +1904,7 @@ int Master_CheckPollSockets(void)
int users, maxusers; int users, maxusers;
int control; int control;
int ccrep;
MSG_BeginReading (msg_nullnetprim); MSG_BeginReading (msg_nullnetprim);
control = BigLong(*((int *)net_message.data)); control = BigLong(*((int *)net_message.data));
@ -1915,9 +1916,79 @@ int Master_CheckPollSockets(void)
if ((control & NETFLAG_LENGTH_MASK) != ret) if ((control & NETFLAG_LENGTH_MASK) != ret)
continue; continue;
if (MSG_ReadByte() != CCREP_SERVER_INFO) ccrep = MSG_ReadByte();
if (ccrep == CCREP_PLAYER_INFO)
{
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; continue;
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*/ /*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(); MSG_ReadString();
@ -1933,6 +2004,7 @@ int Master_CheckPollSockets(void)
CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i\\clients\\%i", name, map, maxusers, users), MP_NETQUAKE, false); CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i\\clients\\%i", name, map, maxusers, users), MP_NETQUAKE, false);
} }
}
#endif #endif
continue; continue;
} }
@ -1994,6 +2066,29 @@ void SListOptionChanged(serverinfo_t *newserver)
selectedserver.refreshtime = realtime+4; selectedserver.refreshtime = realtime+4;
newserver->sends++; newserver->sends++;
Master_QueryServer(newserver); 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,6 +2570,9 @@ void Master_QueryServer(serverinfo_t *server)
Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255); Q_snprintfz(data, sizeof(data), "%c%c%c%cgetstatus", 255, 255, 255, 255);
break; break;
case SS_DARKPLACES: case SS_DARKPLACES:
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); Q_snprintfz(data, sizeof(data), "%c%c%c%cgetinfo", 255, 255, 255, 255);
break; break;
#ifdef NQPROT #ifdef NQPROT
@ -2841,8 +2939,6 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
} }
} }
MasterInfo_RemovePlayers(&info->adr);
name = Info_ValueForKey(msg, "hostname"); name = Info_ValueForKey(msg, "hostname");
if (!*name) if (!*name)
name = Info_ValueForKey(msg, "sv_hostname"); name = Info_ValueForKey(msg, "sv_hostname");
@ -2939,6 +3035,16 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
strcpy(details.info, msg); strcpy(details.info, msg);
msg = msg+strlen(msg)+1; msg = msg+strlen(msg)+1;
//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
{
MasterInfo_RemovePlayers(&info->adr);
info->players=details.numplayers = 0; info->players=details.numplayers = 0;
if (!strchr(msg, '\n')) if (!strchr(msg, '\n'))
info->numhumans = info->players = atoi(Info_ValueForKey(details.info, "clients")); info->numhumans = info->players = atoi(Info_ValueForKey(details.info, "clients"));
@ -3111,6 +3217,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
if (info->moreinfo) if (info->moreinfo)
memcpy(info->moreinfo, &details, sizeof(serverdetailedinfo_t)); memcpy(info->moreinfo, &details, sizeof(serverdetailedinfo_t));
}
return true; return true;
} }

View file

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

View file

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

View file

@ -95,6 +95,8 @@ cvar_t r_bouncysparks = CVARFD ("r_bouncysparks", "1",
cvar_t r_drawentities = CVAR ("r_drawentities", "1"); cvar_t r_drawentities = CVAR ("r_drawentities", "1");
cvar_t r_drawflat = CVARAF ("r_drawflat", "0", "gl_textureless", 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_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_wireframe_smooth = CVAR ("r_wireframe_smooth", "0");
@ -114,7 +116,7 @@ cvar_t r_fb_bmodels = CVARAF("r_fb_bmodels", "1",
"gl_fb_bmodels", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); "gl_fb_bmodels", CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_fb_models = CVARAFD ("r_fb_models", "1", 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."); "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_t r_skin_overlays = CVARF ("r_skin_overlays", "1",
CVAR_SEMICHEAT|CVAR_RENDERERLATCH); 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_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_globalskin_count = CVARFD ("r_globalskin_count", "10", CVAR_RENDERERLATCH, "Specifies how many globalskins there are.");
@ -123,9 +125,9 @@ cvar_t r_coronas_occlusion = CVARFD ("r_coronas_occlusion", "", CVAR_ARCHIVE
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_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_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_t r_flashblend = CVARF ("gl_flashblend", "0",
CVAR_ARCHIVE); CVAR_ARCHIVE);
cvar_t r_flashblendscale = SCVARF ("gl_flashblendscale", "0.35", cvar_t r_flashblendscale = CVARF ("gl_flashblendscale", "0.35",
CVAR_ARCHIVE); CVAR_ARCHIVE);
cvar_t r_floorcolour = CVARAF ("r_floorcolour", "64 64 128", cvar_t r_floorcolour = CVARAF ("r_floorcolour", "64 64 128",
"r_floorcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); "r_floorcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);
@ -135,11 +137,11 @@ cvar_t r_fullbright = CVARFD ("r_fullbright", "0",
CVAR_CHEAT|CVAR_SHADERSYSTEM, "Ignore world lightmaps, drawing everything fully lit."); 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_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_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 = CVARF ("r_lightstylesmooth", "0", CVAR_ARCHIVE);
cvar_t r_lightstylesmooth_limit = SCVAR ("r_lightstylesmooth_limit", "2"); cvar_t r_lightstylesmooth_limit = CVAR ("r_lightstylesmooth_limit", "2");
cvar_t r_lightstylespeed = SCVAR ("r_lightstylespeed", "10"); cvar_t r_lightstylespeed = CVAR ("r_lightstylespeed", "10");
cvar_t r_lightstylescale = SCVAR ("r_lightstylescale", "1"); 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 = CVARF ("r_hdr_irisadaptation", "0", CVAR_ARCHIVE);
cvar_t r_hdr_irisadaptation_multiplier = CVAR ("r_hdr_irisadaptation_multiplier", "2"); 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"); 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_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)."); 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; qboolean r_softwarebanding;
cvar_t r_speeds = SCVAR ("r_speeds", "0"); cvar_t r_speeds = CVAR ("r_speeds", "0");
cvar_t r_stainfadeammount = SCVAR ("r_stainfadeammount", "1"); cvar_t r_stainfadeammount = CVAR ("r_stainfadeammount", "1");
cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1"); cvar_t r_stainfadetime = CVAR ("r_stainfadetime", "1");
cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"), cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"),
CVAR_ARCHIVE, CVAR_ARCHIVE,
Cvar_Limiter_ZeroToOne_Callback); Cvar_Limiter_ZeroToOne_Callback);
@ -207,13 +209,13 @@ cvar_t scr_conspeed = CVAR ("scr_conspeed", "2000");
cvar_t scr_fov = CVARFDC("fov", "90", cvar_t scr_fov = CVARFDC("fov", "90",
CVAR_ARCHIVE, "field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108.", CVAR_ARCHIVE, "field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108.",
SCR_Fov_Callback); SCR_Fov_Callback);
cvar_t scr_printspeed = SCVAR ("scr_printspeed", "16"); cvar_t scr_printspeed = CVAR ("scr_printspeed", "16");
cvar_t scr_showpause = SCVAR ("showpause", "1"); cvar_t scr_showpause = CVAR ("showpause", "1");
cvar_t scr_showturtle = SCVAR ("showturtle", "0"); cvar_t scr_showturtle = CVAR ("showturtle", "0");
cvar_t scr_turtlefps = SCVAR ("scr_turtlefps", "10"); cvar_t scr_turtlefps = CVAR ("scr_turtlefps", "10");
cvar_t scr_sshot_compression = SCVAR ("scr_sshot_compression", "75"); cvar_t scr_sshot_compression = CVAR ("scr_sshot_compression", "75");
cvar_t scr_sshot_type = SCVAR ("scr_sshot_type", "png"); cvar_t scr_sshot_type = CVAR ("scr_sshot_type", "png");
cvar_t scr_sshot_prefix = SCVAR ("scr_sshot_prefix", "screenshots/fte-"); cvar_t scr_sshot_prefix = CVAR ("scr_sshot_prefix", "screenshots/fte-");
cvar_t scr_viewsize = CVARFC("viewsize", "100", cvar_t scr_viewsize = CVARFC("viewsize", "100",
CVAR_ARCHIVE, CVAR_ARCHIVE,
SCR_Viewsize_Callback); SCR_Viewsize_Callback);
@ -278,7 +280,7 @@ extern cvar_t r_drawworld;
extern cvar_t r_fullbright; 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."); 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; 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_novis;
extern cvar_t r_speeds; extern cvar_t r_speeds;
extern cvar_t r_waterwarp; 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_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_t gl_lightmapmode = SCVARF("gl_lightmapmode", "",
// CVAR_ARCHIVE); // CVAR_ARCHIVE);
cvar_t gl_load24bit = SCVARF ("gl_load24bit", "1", cvar_t gl_load24bit = CVARF ("gl_load24bit", "1",
CVAR_ARCHIVE); CVAR_ARCHIVE);
cvar_t r_clear = CVARAF("r_clear","0", 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", 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..."); "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_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_t gl_overbright = CVARFC ("gl_overbright", "1",
CVAR_ARCHIVE, CVAR_ARCHIVE,
Surf_RebuildLightmap_Callback); 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_ARCHIVE);
cvar_t gl_picmip = CVARFD ("gl_picmip", "0", CVAR_ARCHIVE, "Reduce world/model texture sizes by some exponential factor."); 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."); 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_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_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_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."); 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 #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_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_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 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 dpcompat_psa_ungroup = CVAR ("dpcompat_psa_ungroup", "0");
cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE); 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_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_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."); 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."); 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; extern cvar_t gl_dither;
cvar_t gl_screenangle = SCVAR("gl_screenangle", "0"); cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
#endif #endif
#ifdef VKQUAKE #ifdef VKQUAKE
@ -885,6 +887,7 @@ void Renderer_Init(void)
Cvar_Register (&gl_mipcap, GLRENDEREROPTIONS); Cvar_Register (&gl_mipcap, GLRENDEREROPTIONS);
Cvar_Register (&gl_texture_anisotropic_filtering, GLRENDEREROPTIONS); Cvar_Register (&gl_texture_anisotropic_filtering, GLRENDEREROPTIONS);
Cvar_Register (&r_drawflat, GRAPHICALNICETIES); Cvar_Register (&r_drawflat, GRAPHICALNICETIES);
Cvar_Register (&r_lightmap, GRAPHICALNICETIES);
Cvar_Register (&r_menutint, GRAPHICALNICETIES); Cvar_Register (&r_menutint, GRAPHICALNICETIES);
Cvar_Register (&r_fb_bmodels, 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_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_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_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."); 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; 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 ALLCOLUMNS
#undef COLUMN #undef COLUMN

View file

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

View file

@ -928,8 +928,8 @@ int *debug;
HHOOK llkeyboardhook; HHOOK llkeyboardhook;
cvar_t sys_disableWinKeys = SCVAR("sys_disableWinKeys", "0"); cvar_t sys_disableWinKeys = CVAR("sys_disableWinKeys", "0");
cvar_t sys_disableTaskSwitch = SCVARF("sys_disableTaskSwitch", "0", CVAR_NOTFROMSERVER); // please don't encourage people to use this... 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) 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(); Validation_Apply_Ruleset();
} }
cvar_t allow_f_version = SCVAR("allow_f_version", "1"); cvar_t allow_f_version = CVAR("allow_f_version", "1");
cvar_t allow_f_server = SCVAR("allow_f_server", "1"); cvar_t allow_f_server = CVAR("allow_f_server", "1");
cvar_t allow_f_modified = SCVAR("allow_f_modified", "1"); cvar_t allow_f_modified = CVAR("allow_f_modified", "1");
cvar_t allow_f_skins = SCVAR("allow_f_skins", "1"); cvar_t allow_f_skins = CVAR("allow_f_skins", "1");
cvar_t allow_f_ruleset = SCVAR("allow_f_ruleset", "1"); cvar_t allow_f_ruleset = CVAR("allow_f_ruleset", "1");
cvar_t allow_f_scripts = SCVAR("allow_f_scripts", "1"); cvar_t allow_f_scripts = CVAR("allow_f_scripts", "1");
cvar_t allow_f_fakeshaft = SCVAR("allow_f_fakeshaft", "1"); cvar_t allow_f_fakeshaft = CVAR("allow_f_fakeshaft", "1");
cvar_t allow_f_system = SCVAR("allow_f_system", "0"); cvar_t allow_f_system = CVAR("allow_f_system", "0");
cvar_t allow_f_cmdline = SCVAR("allow_f_cmdline", "0"); cvar_t allow_f_cmdline = CVAR("allow_f_cmdline", "0");
cvar_t auth_validateclients = SCVAR("auth_validateclients", "1"); cvar_t auth_validateclients = CVAR("auth_validateclients", "1");
cvar_t ruleset = CVARC("ruleset", "none", rulesetcallback); cvar_t ruleset = CVARC("ruleset", "none", rulesetcallback);
@ -82,7 +82,7 @@ static void Validation_Version(void)
else if (r_shadow_realtime_dlight.ival) else if (r_shadow_realtime_dlight.ival)
*s++ = 'S'; *s++ = 'S';
#endif #endif
if (r_drawflat.ival) if (r_drawflat.ival || r_lightmap.ival)
*s++ = 'F'; *s++ = 'F';
if (gl_load24bit.ival) if (gl_load24bit.ival)
*s++ = 'H'; *s++ = 'H';

View file

@ -44,60 +44,60 @@ when crossing a water boudnary.
*/ */
#ifdef SIDEVIEWS #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_enabled[SIDEVIEWS] = {CVAR("v2_enabled", "2"), CVAR("v3_enabled", "0"), CVAR("v4_enabled", "0"), CVAR("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_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] = {SCVAR("v2_y", "0"), SCVAR("v3_y", "0"), SCVAR("v4_y", "0"), SCVAR("v5_y", "0")}; 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] = {SCVAR("v2_scalex", "0.25"), SCVAR("v3_scalex", "0.25"), SCVAR("v4_scalex", "0.25"), SCVAR("v5_scalex", "0.25")}; 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] = {SCVAR("v2_scaley", "0.25"), SCVAR("v3_scaley", "0.25"), SCVAR("v4_scaley", "0.25"), SCVAR("v5_scaley", "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] = {SCVAR("v2_yaw", "180"), SCVAR("v3_yaw", "90"), SCVAR("v4_yaw", "270"), SCVAR("v5_yaw", "0")}; cvar_t vsec_yaw[SIDEVIEWS] = {CVAR("v2_yaw", "180"), CVAR("v3_yaw", "90"), CVAR("v4_yaw", "270"), CVAR("v5_yaw", "0")};
#endif #endif
cvar_t cl_rollspeed = SCVAR("cl_rollspeed", "200"); cvar_t cl_rollspeed = CVAR("cl_rollspeed", "200");
cvar_t cl_rollangle = SCVAR("cl_rollangle", "2.0"); cvar_t cl_rollangle = CVAR("cl_rollangle", "2.0");
cvar_t v_deathtilt = SCVAR("v_deathtilt", "1"); cvar_t v_deathtilt = CVAR("v_deathtilt", "1");
cvar_t cl_bob = SCVAR("cl_bob","0.02"); cvar_t cl_bob = CVAR("cl_bob","0.02");
cvar_t cl_bobcycle = SCVAR("cl_bobcycle","0.6"); cvar_t cl_bobcycle = CVAR("cl_bobcycle","0.6");
cvar_t cl_bobup = SCVAR("cl_bobup","0.5"); cvar_t cl_bobup = CVAR("cl_bobup","0.5");
cvar_t v_kicktime = SCVAR("v_kicktime", "0.5"); cvar_t v_kicktime = CVAR("v_kicktime", "0.5");
cvar_t v_kickroll = SCVAR("v_kickroll", "0.6"); cvar_t v_kickroll = CVAR("v_kickroll", "0.6");
cvar_t v_kickpitch = SCVAR("v_kickpitch", "0.6"); cvar_t v_kickpitch = CVAR("v_kickpitch", "0.6");
cvar_t v_iyaw_cycle = SCVAR("v_iyaw_cycle", "2"); cvar_t v_iyaw_cycle = CVAR("v_iyaw_cycle", "2");
cvar_t v_iroll_cycle = SCVAR("v_iroll_cycle", "0.5"); cvar_t v_iroll_cycle = CVAR("v_iroll_cycle", "0.5");
cvar_t v_ipitch_cycle = SCVAR("v_ipitch_cycle", "1"); cvar_t v_ipitch_cycle = CVAR("v_ipitch_cycle", "1");
cvar_t v_iyaw_level = SCVAR("v_iyaw_level", "0.3"); cvar_t v_iyaw_level = CVAR("v_iyaw_level", "0.3");
cvar_t v_iroll_level = SCVAR("v_iroll_level", "0.1"); cvar_t v_iroll_level = CVAR("v_iroll_level", "0.1");
cvar_t v_ipitch_level = SCVAR("v_ipitch_level", "0.3"); cvar_t v_ipitch_level = CVAR("v_ipitch_level", "0.3");
cvar_t v_idlescale = SCVAR("v_idlescale", "0"); cvar_t v_idlescale = CVAR("v_idlescale", "0");
cvar_t crosshair = SCVARF("crosshair", "1", CVAR_ARCHIVE); cvar_t crosshair = CVARF("crosshair", "1", CVAR_ARCHIVE);
cvar_t crosshaircolor = SCVARF("crosshaircolor", "255 255 255", CVAR_ARCHIVE); cvar_t crosshaircolor = CVARF("crosshaircolor", "255 255 255", CVAR_ARCHIVE);
cvar_t crosshairsize = SCVARF("crosshairsize", "8", CVAR_ARCHIVE); cvar_t crosshairsize = CVARF("crosshairsize", "8", CVAR_ARCHIVE);
cvar_t cl_crossx = SCVARF("cl_crossx", "0", CVAR_ARCHIVE); cvar_t cl_crossx = CVARF("cl_crossx", "0", CVAR_ARCHIVE);
cvar_t cl_crossy = SCVARF("cl_crossy", "0", CVAR_ARCHIVE); cvar_t cl_crossy = CVARF("cl_crossy", "0", CVAR_ARCHIVE);
cvar_t crosshaircorrect = SCVARF("crosshaircorrect", "0", CVAR_SEMICHEAT); cvar_t crosshaircorrect = CVARF("crosshaircorrect", "0", CVAR_SEMICHEAT);
cvar_t crosshairimage = SCVAR("crosshairimage", ""); cvar_t crosshairimage = CVAR("crosshairimage", "");
cvar_t crosshairalpha = SCVAR("crosshairalpha", "1"); cvar_t crosshairalpha = CVAR("crosshairalpha", "1");
cvar_t gl_cshiftpercent = SCVAR("gl_cshiftpercent", "100"); cvar_t gl_cshiftpercent = CVAR("gl_cshiftpercent", "100");
cvar_t gl_cshiftenabled = CVARF("gl_polyblend", "1", CVAR_ARCHIVE); 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_contentblend = CVARF("v_contentblend", "1", CVAR_ARCHIVE);
cvar_t v_damagecshift = SCVAR("v_damagecshift", "1"); cvar_t v_damagecshift = CVAR("v_damagecshift", "1");
cvar_t v_quadcshift = SCVAR("v_quadcshift", "1"); cvar_t v_quadcshift = CVAR("v_quadcshift", "1");
cvar_t v_suitcshift = SCVAR("v_suitcshift", "1"); cvar_t v_suitcshift = CVAR("v_suitcshift", "1");
cvar_t v_ringcshift = SCVAR("v_ringcshift", "1"); cvar_t v_ringcshift = CVAR("v_ringcshift", "1");
cvar_t v_pentcshift = SCVAR("v_pentcshift", "1"); cvar_t v_pentcshift = CVAR("v_pentcshift", "1");
cvar_t v_gunkick = SCVAR("v_gunkick", "0"); cvar_t v_gunkick = CVAR("v_gunkick", "0");
cvar_t v_gunkick_q2 = SCVAR("v_gunkick_q2", "1"); cvar_t v_gunkick_q2 = CVAR("v_gunkick_q2", "1");
cvar_t v_viewheight = SCVAR("v_viewheight", "0"); cvar_t v_viewheight = CVAR("v_viewheight", "0");
cvar_t v_projectionmode = SCVAR("v_projectionmode", "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.");
@ -197,8 +197,8 @@ float V_CalcBob (playerview_t *pv, qboolean queryold)
//============================================================================= //=============================================================================
cvar_t v_centermove = SCVAR("v_centermove", "0.15"); cvar_t v_centermove = CVAR("v_centermove", "0.15");
cvar_t v_centerspeed = SCVAR("v_centerspeed","500"); cvar_t v_centerspeed = CVAR("v_centerspeed","500");
void V_StartPitchDrift (playerview_t *pv) 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 "quakedef.h"
#include "fs.h" #include "fs.h"
cvar_t ruleset_allow_in = SCVAR("ruleset_allow_in", "1"); cvar_t ruleset_allow_in = CVAR("ruleset_allow_in", "1");
cvar_t rcon_level = SCVAR("rcon_level", "20"); cvar_t rcon_level = CVAR("rcon_level", "20");
cvar_t cmd_maxbuffersize = SCVAR("cmd_maxbuffersize", "65536"); cvar_t cmd_maxbuffersize = CVAR("cmd_maxbuffersize", "65536");
cvar_t dpcompat_set = SCVAR("dpcompat_set", "0"); cvar_t dpcompat_set = CVAR("dpcompat_set", "0");
int Cmd_ExecLevel; int Cmd_ExecLevel;
qboolean cmd_didwait; qboolean cmd_didwait;
qboolean cmd_blockwait; qboolean cmd_blockwait;
@ -2614,28 +2614,33 @@ static const char *If_Token_Term(const char *func, const char **end)
} }
else if (*com_token == '!') else if (*com_token == '!')
{ {
func = If_Token(s, end, 0); func = If_Token(s, &s, 0);
s2 = retbool(!is_true(func)); s2 = retbool(!is_true(func));
} }
else if (*com_token == '~') else if (*com_token == '~')
{ {
func = If_Token(s, end, 0); func = If_Token(s, &s, 0);
s2 = retbool(~atoi(func)); s2 = retbool(~atoi(func));
} }
else if (*com_token == '-')
{
func = If_Token(s, &s, 0);
s2 = retfloat(-atof(func));
}
else if (!strcmp(com_token, "int")) else if (!strcmp(com_token, "int"))
{ {
func = If_Token(s, end, 0); func = If_Token(s, &s, 0);
s2 = retint(atoi(func)); s2 = retint(atoi(func));
} }
else if (!strcmp(com_token, "strlen")) else if (!strcmp(com_token, "strlen"))
{ {
func = If_Token(s, end, 0); func = If_Token(s, &s, 0);
s2 = retfloat(strlen(func)); s2 = retfloat(strlen(func));
} }
else if (!strcmp(com_token, "eval")) else if (!strcmp(com_token, "eval"))
{ {
//read the stuff to the right //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 //and evaluate it
s2 = If_Token(func, &func, IF_PRI_MAX); s2 = If_Token(func, &func, IF_PRI_MAX);
} }
@ -2824,6 +2829,8 @@ static const char *If_Token(const char *func, const char **end, int pri)
s2 = If_Token_Term(func, &s); s2 = If_Token_Term(func, &s);
*end = s; *end = s;
if (s)
{
while (*s == ' ' || *s == '\t') while (*s == ' ' || *s == '\t')
s++; s++;
@ -2839,6 +2846,7 @@ static const char *If_Token(const char *func, const char **end, int pri)
break; break;
} }
} }
}
return s2; return s2;
} }

View file

@ -25,6 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <ctype.h> #include <ctype.h>
#include <errno.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 // These 4 libraries required for the version command
#if defined(MINGW) #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 CVARD(ConsoleName,Value,Description) CVARAFDC(ConsoleName, Value, NULL, 0, Description, NULL)
#define CVAR(ConsoleName,Value) CVARD(ConsoleName, Value, 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) #define CVARDP4(Flags,ConsoleName,Value,Description) CVARFD(ConsoleName, Value, Flags,Description)
typedef struct cvar_group_s typedef struct cvar_group_s

View file

@ -386,10 +386,10 @@ typedef struct cminfo_s
static q2mapsurface_t nullsurface; static q2mapsurface_t nullsurface;
cvar_t map_noareas = SCVAR("map_noareas", "0"); //1 for lack of mod support. cvar_t map_noareas = CVAR("map_noareas", "0"); //1 for lack of mod support.
cvar_t map_noCurves = SCVARF("map_noCurves", "0", CVAR_CHEAT); 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 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 int CM_NumInlineModels (model_t *model);
static cmodel_t *CM_InlineModel (model_t *model, char *name); 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; int net_drop;
cvar_t showpackets = SCVAR("showpackets", "0"); cvar_t showpackets = CVAR("showpackets", "0");
cvar_t showdrop = SCVAR("showdrop", "0"); cvar_t showdrop = CVAR("showdrop", "0");
cvar_t qport = CVARF("qport_", "0", CVAR_NOSAVE); 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_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."); 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) if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(neterrno())); 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 // determine my name & address if we don't already know it

View file

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

View file

@ -13,7 +13,7 @@
#ifdef PLUGINS #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_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_Bullet_Init(qintptr_t *args);
qintptr_t Plug_ODE_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]; char shadertext[8192*2];
extern cvar_t r_drawflat; 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); Shader_DefaultScript(shortname, s, shadertext);
} }

View file

@ -31,10 +31,6 @@ struct font_s *font_tiny;
static int font_be_flags; static int font_be_flags;
extern unsigned int r2d_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 #ifdef AVAIL_FREETYPE
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_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_bloom;
extern cvar_t r_wireframe_smooth; extern cvar_t r_wireframe_smooth;
cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0"); cvar_t gl_affinemodels = CVAR("gl_affinemodels","0");
cvar_t gl_finish = SCVAR("gl_finish","0"); cvar_t gl_finish = CVAR("gl_finish","0");
cvar_t gl_dither = SCVAR("gl_dither", "1"); cvar_t gl_dither = CVAR("gl_dither", "1");
extern cvar_t r_stereo_separation; extern cvar_t r_stereo_separation;
extern cvar_t r_stereo_convergence; extern cvar_t r_stereo_convergence;
extern cvar_t r_stereo_method; extern cvar_t r_stereo_method;
@ -80,7 +80,7 @@ extern cvar_t r_portaldrawplanes;
extern cvar_t r_portalonly; extern cvar_t r_portalonly;
#ifdef R_XFLIP #ifdef R_XFLIP
cvar_t r_xflip = SCVAR("leftisright", "0"); cvar_t r_xflip = CVAR("leftisright", "0");
#endif #endif
extern cvar_t scr_fov; 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; char *builtin = NULL;
if (Shader_ParseShader("defaultwall", s)) if (Shader_ParseShader("defaultwall", s))
return; 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) if (!builtin && r_drawflat.ival)
builtin = ( builtin = (
"{\n" "{\n"

View file

@ -786,17 +786,18 @@ static void GL_DrawSkyBox (texid_t *texnums, batch_t *s)
============= =============
R_InitSky 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) void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int width, unsigned int height)
{ {
int i, j, p; int i, j, p;
unsigned trans[128*128]; unsigned *temp;
unsigned transpix, alphamask; unsigned transpix, alphamask;
int r, g, b; int r, g, b;
unsigned *rgba; unsigned *rgba;
char name[MAX_QPATH]; char name[MAX_QPATH*2];
unsigned int stride = width; unsigned int stride = width;
width /= 2; width /= 2;
@ -804,14 +805,63 @@ void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int
if (width < 1 || height < 1 || stride != width*2 || !src) if (width < 1 || height < 1 || stride != width*2 || !src)
return; 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}; size_t filesize = 0;
shader->defaulttextures->base = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA); qbyte *filedata = NULL;
shader->defaulttextures->base = R_LoadReplacementTexture(skyname, NULL, 0, src, stride, height, TF_SOLID8); if (!filedata)
shader->defaulttextures->fullbright = shader->defaulttextures->base; {
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; return;
} }
}
BZ_Free(imagedata);
}
}
temp = BZ_Malloc(width*height*sizeof(*temp));
// make an average value for the back to avoid // make an average value for the back to avoid
// a fringe on the top level // 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]; p = src[i*stride + j + width];
rgba = &d_8to24rgbtable[p]; rgba = &d_8to24rgbtable[p];
trans[(i*width) + j] = *rgba; temp[(i*width) + j] = *rgba;
r += ((qbyte *)rgba)[0]; r += ((qbyte *)rgba)[0];
g += ((qbyte *)rgba)[1]; g += ((qbyte *)rgba)[1];
b += ((qbyte *)rgba)[2]; 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_snprintfz(name, sizeof(name), "%s_solid", skyname);
Q_strlwr(name); 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) if (!shader->defaulttextures->fullbright)
{ {
//fixme: use premultiplied alpha here.
((qbyte *)&transpix)[0] = r/(width*height); ((qbyte *)&transpix)[0] = r/(width*height);
((qbyte *)&transpix)[1] = g/(width*height); ((qbyte *)&transpix)[1] = g/(width*height);
((qbyte *)&transpix)[2] = b/(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]; p = src[i*stride + j];
if (p == 0) if (p == 0)
trans[(i*width) + j] = transpix; temp[(i*width) + j] = transpix;
else else
trans[(i*width) + j] = d_8to24rgbtable[p] & alphamask; temp[(i*width) + j] = d_8to24rgbtable[p] & alphamask;
} }
//FIXME: support _trans //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); 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 #endif

View file

@ -373,13 +373,13 @@ IWEBFILE *IWebFOpenRead(char *name) //fread(name, "rb");
#else #else
#ifndef CLIENTONLY #ifndef CLIENTONLY
cvar_t ftpserver = SCVAR("sv_ftp", "0"); cvar_t ftpserver = CVAR("sv_ftp", "0");
cvar_t ftpserver_port = SCVAR("sv_ftp_port", "21"); cvar_t ftpserver_port = CVAR("sv_ftp_port", "21");
cvar_t httpserver = SCVAR("sv_http", "0"); cvar_t httpserver = CVAR("sv_http", "0");
cvar_t httpserver_port = SCVAR("sv_http_port", "80"); cvar_t httpserver_port = CVAR("sv_http_port", "80");
cvar_t sv_readlevel = SCVAR("sv_readlevel", "0"); //default to allow anyone cvar_t sv_readlevel = CVAR("sv_readlevel", "0"); //default to allow anyone
cvar_t sv_writelevel = SCVAR("sv_writelevel", "35"); //allowed to write to uploads/uname cvar_t sv_writelevel = CVAR("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 sv_fulllevel = CVAR("sv_fulllevel", "51"); //allowed to write anywhere, replace any file...
#endif #endif
//this file contains functions called from each side. //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 SafeOpenWrite (char *filename, int maxsize);
int SafeOpenRead (char *filename); int SafeOpenRead (char *filename);
void SafeRead (int handle, void *buffer, long count); 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); pbool SafeClose(int hand);
int SafeSeek(int hand, int ofs, int mode); int SafeSeek(int hand, int ofs, int mode);
void *SafeMalloc (long size); void *SafeMalloc (long size);

View file

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

View file

@ -1,6 +1,6 @@
void GoToDefinition(char *name); void GoToDefinition(char *name);
int Grep(char *filename, char *string); 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); void GUI_SetDefaultOpts(void);
int GUI_BuildParms(char *args, char **argv, pbool quick); int GUI_BuildParms(char *args, char **argv, pbool quick);

View file

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

View file

@ -1,3 +1,6 @@
#ifndef PROGSINT_H_INCLUDED
#define PROGSINT_H_INCLUDED
#ifdef _WIN32 #ifdef _WIN32
#ifndef _CRT_SECURE_NO_WARNINGS #ifndef _CRT_SECURE_NO_WARNINGS
#define _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 qcc_token[1024];
extern char *basictypenames[]; extern char *basictypenames[];
#endif #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_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 *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; 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 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. 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 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 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 timescalled; //part of the opt_stripfunctions optimisation.
int s_file; const char *filen;
int s_filed;
int s_line; int s_line;
int arraysize; 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 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 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 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. int fromstatement; //statement that it is valid from.
temp_t *temp; temp_t *temp;
@ -462,8 +465,9 @@ struct QCC_function_s
{ {
int builtin; // the builtin number. >= 0 int builtin; // the builtin number. >= 0
int code; // first statement. if -1, is a builtin. int code; // first statement. if -1, is a builtin.
string_t s_file; // source file with definition dfunction_t *merged; // this function was merged. this is the index to use to ensure that the parms are sized correctly..
const char *file; string_t s_filed; // source file with definition
const char *filen;
int line; int line;
char *name; //internal name of function char *name; //internal name of function
struct QCC_function_s *parentscope; //for nested functions 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_inline; //don't write the def to the output.
extern pbool keyword_strip; //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_union; //you surly know what a union is!
extern pbool keyword_wrap;
extern pbool keyword_weak;
extern pbool keyword_unused; extern pbool keyword_unused;
extern pbool keyword_used; extern pbool keyword_used;
@ -885,6 +891,8 @@ extern compiler_flag_t compiler_flag[];
extern unsigned char qccwarningaction[WARN_MAX]; extern unsigned char qccwarningaction[WARN_MAX];
extern jmp_buf pr_parse_abort; // longjump with this on parse error 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 int pr_source_line;
extern char *pr_file_p; extern char *pr_file_p;
@ -913,9 +921,11 @@ void QCC_PR_NewLine (pbool incomment);
#define GDF_SILENT 16 //used by the gui, to suppress ALL warnings associated with querying the def. #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_INLINE 32 //attempt to inline calls to this function
#define GDF_USED 64 //don't strip this, ever. #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_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); 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_FreeTemp(QCC_sref_t t);
void QCC_FreeDef(QCC_def_t *def);
char *QCC_PR_CheckCompConstTooltip(char *word, char *outstart, char *outend); char *QCC_PR_CheckCompConstTooltip(char *word, char *outstart, char *outend);
void QCC_PR_PrintDefs (void); void QCC_PR_PrintDefs (void);
@ -940,8 +950,6 @@ void QCC_PR_ResetErrorScope(void);
extern pbool pr_dumpasm; extern pbool pr_dumpasm;
extern QCC_string_t s_file; // filename for function definition
extern QCC_def_t def_ret, def_parms[MAX_PARMS]; extern QCC_def_t def_ret, def_parms[MAX_PARMS];
void QCC_PR_EmitArrayGetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char *arrayname); void QCC_PR_EmitArrayGetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char *arrayname);
@ -1006,7 +1014,7 @@ typedef struct
int block; int block;
int used; int used;
int fileline; int fileline;
char *filename; const char *filename;
} precache_t; } precache_t;
extern precache_t *precache_sound; extern precache_t *precache_sound;
extern int numsounds; extern int numsounds;
@ -1060,7 +1068,7 @@ static bool inline QCC_PR_CheckToken (char *string)
return true; return true;
} }
static void inline QCC_PR_Expect (char *string) static void inline QCC_PR_Expect (const char *string)
{ {
if (strcmp (string, pr_token)) if (strcmp (string, pr_token))
QCC_PR_ParseError ("expected %s, found %s",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 #endif
void editbadfile(char *fname, int line); void editbadfile(const char *fname, int line);
char *TypeName(QCC_type_t *type, char *buffer, int buffersize); char *TypeName(QCC_type_t *type, char *buffer, int buffersize);
void QCC_PR_AddIncludePath(const char *newinc); void QCC_PR_AddIncludePath(const char *newinc);
void QCC_PR_IncludeChunk (char *data, pbool duplicate, char *filename); 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_IncludeChunkEx(char *data, pbool duplicate, char *filename, CompilerConstant_t *cnst);
void QCC_PR_CloseProcessor(void); void QCC_PR_CloseProcessor(void);
void QCC_FindBestInclude(char *newfile, char *currentfile, pbool verbose);
pbool QCC_PR_UnInclude(void); pbool QCC_PR_UnInclude(void);
extern void *(*pHash_Get)(hashtable_t *table, const char *name); extern void *(*pHash_Get)(hashtable_t *table, const char *name);
extern void *(*pHash_GetNext)(hashtable_t *table, const char *name, void *old); 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); printf ("\n************ ERROR ************\n%s\n", msg);
editbadfile(strings+s_file, pr_source_line); editbadfile(s_filen, pr_source_line);
numsourcefiles = 0; numsourcefiles = 0;
@ -890,7 +890,7 @@ void ResizeBuf(int hand, int newsize)
qccfile[hand].buff = nb; qccfile[hand].buff = nb;
qccfile[hand].buffsize = newsize; 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) if (qccfile[hand].ofs +count >= qccfile[hand].buffsize)
ResizeBuf(hand, qccfile[hand].ofs + count+(64*1024)); ResizeBuf(hand, qccfile[hand].ofs + count+(64*1024));
@ -1242,6 +1242,7 @@ long QCC_LoadFile (char *filename, void **bufferptr)
mem += sizeof(qcc_cachedsourcefile_t); mem += sizeof(qcc_cachedsourcefile_t);
externs->ReadFile(filename, mem, len+2, NULL); externs->ReadFile(filename, mem, len+2, NULL);
mem[len] = 0;
mem = QCC_SanitizeCharSet(mem, &len, NULL, &orig); mem = QCC_SanitizeCharSet(mem, &len, NULL, &orig);

View file

@ -78,6 +78,8 @@ pbool keyword_inline;
pbool keyword_strip; pbool keyword_strip;
pbool keyword_ignore; pbool keyword_ignore;
pbool keyword_union; //you surly know what a union is! 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 #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); 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_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); 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_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); 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_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); 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); 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); 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); 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_IF(QCC_sref_t e, pbool preserve);
QCC_statement_t *QCC_Generate_OP_GOTO(void); QCC_statement_t *QCC_Generate_OP_GOTO(void);
QCC_sref_t QCC_PR_GenerateLogicalNot(QCC_sref_t e, const char *errormessage); 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. //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); 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; QCC_function_t *pr_assumetermscope;
unsigned int pr_assumetermflags; //GDF_ unsigned int pr_assumetermflags; //GDF_
pbool pr_dumpasm; 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. 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. //typically used for debugging. Also used to determine function names for intrinsics.
const char *QCC_GetSRefName(QCC_sref_t ref) 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) if (ref.sym->temp)
return ref.cast->name; return ref.cast->name;
@ -4259,7 +4262,7 @@ void QCC_PrecacheSound (const char *n, int ch)
// QCC_Error ("PrecacheSound: numsounds == MAX_SOUNDS"); // QCC_Error ("PrecacheSound: numsounds == MAX_SOUNDS");
strcpy (precache_sound[i].name, n); strcpy (precache_sound[i].name, n);
precache_sound[i].block = ch; 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; precache_sound[i].fileline = pr_source_line;
numsounds++; numsounds++;
} }
@ -4290,7 +4293,7 @@ void QCC_PrecacheModel (const char *n, int ch)
precache_model[i].block = ch - '0'; precache_model[i].block = ch - '0';
else else
precache_model[i].block = 1; 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; precache_model[i].fileline = pr_source_line;
nummodels++; nummodels++;
} }
@ -4313,7 +4316,7 @@ void QCC_SetModel (const char *n)
precache_model[i].block = 0; precache_model[i].block = 0;
precache_model[i].used=1; 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; precache_model[i].fileline = pr_source_line;
nummodels++; nummodels++;
} }
@ -4335,7 +4338,7 @@ void QCC_SoundUsed (const char *n)
precache_sound[i].block = 0; precache_sound[i].block = 0;
precache_sound[i].used=1; 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; precache_sound[i].fileline = pr_source_line;
numsounds++; 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_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 //reset the locals chain
pr.local_head.nextlocal = NULL; pr.local_head.nextlocal = NULL;
pr.local_tail = &pr.local_head; 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); QCC_PR_ParseWarning (ERR_UNKNOWNVALUE, "Class \"%s\" is not defined, cannot access memeber \"%s\"", assumeclass->name, name);
if (!autoprototype && !autoprototyped) 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 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)) else if (!implicit && !typecmp_lax(src.cast, cast))
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 else
{ {
char typea[256]; char typea[256];
@ -7704,7 +7709,7 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
e = nullsref; e = nullsref;
e.cast = type_float; e.cast = type_float;
patch = QCC_Generate_OP_GOTO(); 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; e.cast = newtype;
patch->a.ofs = &statements[numstatements] - patch; 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); d = QCC_PR_GetDef (type, QCC_PR_ParseName(), pr_scope, true, 0, 0);
QCC_PR_Expect("="); QCC_PR_Expect("=");
QCC_PR_ParseInitializerDef(d); QCC_PR_ParseInitializerDef(d, 0);
QCC_FreeDef(d); QCC_FreeDef(d);
QCC_FreeDef(d); QCC_FreeDef(d);
} }
@ -11114,7 +11119,7 @@ void QCC_CheckForDeadAndMissingReturns(int first, int last, int rettype)
} }
if (st2 == last) 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; 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->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 i;
return -2; 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. return -1; //assume taking a pointer to it is an initialisation.
// this code catches gotos, but can cause issues with while statements. // 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 (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)) if (OpAssignsToA(st->op))
return -1; return -1;
@ -11320,7 +11325,7 @@ int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_def_t *
if (pr_opcodes[st->op].type_b) 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)) if (OpAssignsToB(st->op))
return -1; return -1;
@ -11356,7 +11361,7 @@ int QCC_CheckOneUninitialised(int firststatement, int laststatement, QCC_def_t *
continue; 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)) if (OpAssignsToC(st->op))
return -1; 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)); err = QCC_CheckOneUninitialised(firststatement, laststatement, local, local->ofs, local->ofs + local->type->size * (local->arraysize?local->arraysize:1));
if (err > 0) 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; result = true;
// break; // 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). //these matter when the function goes recursive (and locals marshalling counts as recursive every time).
if (local->symboldata[local->ofs]._int) 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; error = true;
} }
if (local->constant) 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; error = true;
} }
} }
@ -11551,9 +11556,9 @@ void QCC_WriteGUIAsmFunction(QCC_function_t *sc, unsigned int firststatement)
} }
} }
if (currentsourcefile) 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 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) if (numfunctions >= MAX_FUNCTIONS)
QCC_PR_ParseError(ERR_INTERNAL, "Too many functions - %i\nAdd \"MAX_FUNCTIONS\" \"%i\" to qcc.cfg", numfunctions, (numfunctions+4096)&~4095); QCC_PR_ParseError(ERR_INTERNAL, "Too many functions - %i\nAdd \"MAX_FUNCTIONS\" \"%i\" to qcc.cfg", numfunctions, (numfunctions+4096)&~4095);
func = &functions[numfunctions++]; func = &functions[numfunctions++];
func->s_file = s_file2; func->filen = s_filen;
func->file = strings+s_file; func->s_filed = s_filed;
func->line = def->s_line; //FIXME func->line = def->s_line; //FIXME
func->name = def->name; func->name = def->name;
func->builtin = builtinnum; func->builtin = builtinnum;
@ -11660,14 +11665,32 @@ QCC_function_t *QCC_PR_GenerateBuiltinFunction (QCC_def_t *def, int builtinnum)
func->def = def; func->def = def;
return func; 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; QCC_function_t *func;
if (numfunctions >= MAX_FUNCTIONS) if (numfunctions >= MAX_FUNCTIONS)
QCC_PR_ParseError(ERR_INTERNAL, "Too many functions - %i\nAdd \"MAX_FUNCTIONS\" \"%i\" to qcc.cfg", numfunctions, (numfunctions+4096)&~4095); QCC_PR_ParseError(ERR_INTERNAL, "Too many functions - %i\nAdd \"MAX_FUNCTIONS\" \"%i\" to qcc.cfg", numfunctions, (numfunctions+4096)&~4095);
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 = &functions[numfunctions++];
func->s_file = s_file2; func->filen = s_filen;
func->file = strings+s_file; func->s_filed = s_filed;
func->line = pr_source_line;//def?def->s_line:0; //FIXME func->line = pr_source_line;//def?def->s_line:0; //FIXME
func->name = def?def->name:""; func->name = def?def->name:"";
func->builtin = 0; 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. 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; unsigned int u, p;
QCC_function_t *f; QCC_function_t *f;
QCC_sref_t parm; QCC_sref_t parm;
pbool needsdone=false; pbool needsdone=false;
QCC_def_t *prior = NULL;
conditional = 0; conditional = 0;
expandedemptymacro = false; expandedemptymacro = false;
@ -11735,7 +11760,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
// if (type->vargs) // if (type->vargs)
// QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body"); // 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 //reset the locals chain
pr.local_head.nextlocal = NULL; 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); 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 (type->vargcount)
{ {
if (!pr_parm_argcount_name) 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(); 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; pr_token_line_last = pr_token_line;
// this is cheap // 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 = array.sym->arraysize*array.cast->size;
numslots = (numslots+2)/3; 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); 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. 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) if (numfunctions >= MAX_FUNCTIONS)
QCC_Error(ERR_INTERNAL, "Too many function defs"); 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_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; func->symboldata[func->ofs]._int = pr_scope - functions;
index = QCC_PR_GetSRef(type_float, "index___", pr_scope, true, 0, false); 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) // if (flag_fasttrackarrays && numslots > 6)
// fasttrackpossible = QCC_PR_GetSRef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false); // 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; vectortrick = nullsref;
// if (numslots >= 15 && thearray.cast->type != ev_vector) // 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; // 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_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); 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) if (numfunctions >= MAX_FUNCTIONS)
QCC_Error(ERR_INTERNAL, "Too many function defs"); QCC_Error(ERR_INTERNAL, "Too many function defs");
s_file = arraydef->s_file; s_filen = arraydef->filen;
pr_scope = QCC_PR_GenerateQCFunction(scope, scope->type); 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_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); index = QCC_PR_GetSRef(type_float, "indexs___", pr_scope, true, 0, false);
value = QCC_PR_GetSRef(thearray.cast, "value___", 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_line = pr_source_line;
def->s_file = s_file; def->filen = s_filen;
def->s_filed = s_filed;
if (a>=0) if (a>=0)
def->initialized = 1; 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->symbolheader = rootsymbol;
def->symboldata = rootsymbol->symboldata; def->symboldata = rootsymbol->symboldata + def->ofs;
def->symbolsize = (def->arraysize?def->arraysize:1) * type->size; def->symbolsize = (def->arraysize?def->arraysize:1) * type->size;
if (type->type == ev_struct && (!arraysize || a>=0)) 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. //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) if (!foundstatic)
foundstatic = def; //save it off purely as a warning. foundstatic = def; //save it off purely as a warning.
@ -12740,18 +12789,49 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
continue; // in a different function 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 (type && typecmp(def->type, type))
{ {
if (pr_scope || typecmp_lax(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("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. !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. //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. //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
{
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); QCC_PR_ParsePrintDef(WARN_COMPATIBILITYHACK, def);
} }
else else
@ -12760,6 +12840,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
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))); 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 else
{ {
if (type->type != ev_function || type->num_parms != def->type->num_parms || !(def->type->vargs && !type->vargs)) if (type->type != ev_function || type->num_parms != def->type->num_parms || !(def->type->vargs && !type->vargs))
@ -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); def = QCC_PR_GetDef(ftype, newname, scope, true, 0, saved);
if (parttype->type == ev_function) if (parttype->type == ev_function)
def->initialized = true; def->initialized = true;
def->symboldata->_int = *fieldofs; def->symboldata[def->ofs]._int = *fieldofs;
*fieldofs += parttype->size; *fieldofs += parttype->size;
} }
else 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); 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; QCC_sref_t tmp;
int i; 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++) for (i = 0; i < arraysize; i++)
{ {
QCC_PR_ParseInitializerType(0, basedef, def); QCC_PR_ParseInitializerType(0, basedef, def, flags);
def.ofs += def.cast->size; def.ofs += def.cast->size;
if (!QCC_PR_CheckToken(",")) if (!QCC_PR_CheckToken(","))
{ {
@ -13020,18 +13103,30 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
{ {
for (i = 1; i < numfunctions; i++) 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)
{
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); tmp = QCC_MakeIntConst(i);
break; break;
} }
} }
} }
}
else else
{ {
for (i = 1; i < numfunctions; i++) 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)
{
if (!*functions[i].name)
functions[i].name = (char*)defname;
if (!strcmp(functions[i].name, defname))
{ {
tmp = QCC_MakeIntConst(i); tmp = QCC_MakeIntConst(i);
break; break;
@ -13039,6 +13134,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
} }
} }
} }
}
if (!tmp.cast) if (!tmp.cast)
f = QCC_PR_GenerateBuiltinFunction(def.sym, binum); f = QCC_PR_GenerateBuiltinFunction(def.sym, binum);
@ -13047,14 +13143,19 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
} }
else 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. //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. //the qc function is the one that is used, but there is a warning so you know how to gain efficiency.
int bi = -1; int bi = -1;
if (def.cast->type == ev_function && !arraysize) 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; bi = def.sym->symboldata[def.ofs]._int;
} }
if (bi <= 0 || bi >= numfunctions) 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; bi = functions[bi].code;
if (bi < 0) 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); QCC_PR_ParsePrintSRef(WARN_NOTSTANDARDBEHAVIOUR, def);
basedef->initialized = 3; basedef->initialized = 3;
} }
else else
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "redeclaration of function body"); QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "redeclaration of function body");
} }
if (pr_scope) 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. //generate a goto statement around the nested function, so that nothing is hurt.
patch = QCC_Generate_OP_GOTO(); 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; patch->a.ofs = &statements[numstatements] - patch;
//make sure parent state is restored properly. //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; pr_scope = parent;
} }
else else
f = QCC_PR_ParseImmediateStatements (def.sym, type); f = QCC_PR_ParseImmediateStatements (def.sym, type, flags&PIF_WRAP);
//allow dupes if its a builtin //allow dupes if its a builtin
if (!f->code && basedef->initialized) 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.cast = (type)->params[partnum].type;
def.ofs = offset + (type)->params[partnum].ofs; 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(",")) if (isunion || !QCC_PR_CheckToken(","))
{ {
QCC_PR_Expect("}"); 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); 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++) for (i = 0; (unsigned)i < type->size; i++)
if (def.sym->symboldata[def.ofs+i]._int != tmp.sym->symboldata[tmp.ofs+i]._int) 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_ParseWarning (WARN_COMPATIBILITYHACK, "incompatible redeclaration. Please validate builtin numbers. parseentitydata is #613");
QCC_PR_ParsePrintSRef(WARN_COMPATIBILITYHACK, tmp); 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 else
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "incompatible redeclaration"); 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) if (!def->initialized || def->initialized == 3)
def->initialized = 1; def->initialized = 1;
} }
@ -13431,6 +13538,8 @@ void QCC_PR_ParseDefs (char *classname)
pbool inlinefunction = false; pbool inlinefunction = false;
pbool allowinline = false; pbool allowinline = false;
pbool dostrip = false; pbool dostrip = false;
pbool dowrap = false;
pbool doweak = false;
pbool forceused = false; pbool forceused = false;
int arraysize; int arraysize;
unsigned int gd_flags; unsigned int gd_flags;
@ -13666,6 +13775,10 @@ void QCC_PR_ParseDefs (char *classname)
allowinline = true; allowinline = true;
else if (QCC_PR_CheckKeyword(keyword_ignore, "ignore")) else if (QCC_PR_CheckKeyword(keyword_ignore, "ignore"))
dostrip = true; dostrip = true;
else if (QCC_PR_CheckKeyword(keyword_wrap, "wrap"))
dowrap = true;
else if (QCC_PR_CheckKeyword(keyword_weak, "weak"))
doweak = true;
else else
break; break;
} }
@ -13732,7 +13845,7 @@ void QCC_PR_ParseDefs (char *classname)
{ {
def->referenced = true; def->referenced = true;
f = QCC_PR_ParseImmediateStatements (def, type); f = QCC_PR_ParseImmediateStatements (def, type, false);
def->initialized = 1; def->initialized = 1;
def->isstatic = isstatic; def->isstatic = isstatic;
@ -13943,7 +14056,7 @@ void QCC_PR_ParseDefs (char *classname)
if (isstatic) if (isstatic)
{ {
if (!strcmp(strings+def->s_file, strings+s_file)) if (!strcmp(def->filen, s_filen))
def->isstatic = isstatic; def->isstatic = isstatic;
else //if (type->type != ev_function && defaultstatic) //functions don't quite consitiute a definition 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"); 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; QCC_type_t *parentclass;
if (def->shared) if (def->shared)
QCC_PR_ParseError (ERR_SHAREDINITIALISED, "shared values may not be assigned an initial value", name); 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 { //ignore the code and stuff
if (dostrip && !def->initialized) if ((dostrip || doweak && dowrap) && !def->initialized)
def->initialized = 3; def->initialized = 3;
if (dostrip) if (dostrip)
def->referenced = true; def->referenced = true;
@ -14045,7 +14148,11 @@ void QCC_PR_ParseDefs (char *classname)
parentclass = pr_classtype; parentclass = pr_classtype;
pr_classtype = defclass?defclass:pr_classtype; pr_classtype = defclass?defclass:pr_classtype;
def->constant = (isconstant || (!isvar && !pr_scope)); 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); QCC_FreeDef(def);
pr_classtype = parentclass; 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) pbool QCC_PR_CompileFile (char *string, char *filename)
{ {
char *tmp;
jmp_buf oldjb; jmp_buf oldjb;
if (!pr.memory) if (!pr.memory)
QCC_Error (ERR_INTERNAL, "PR_CompileFile: Didn't clear"); QCC_Error (ERR_INTERNAL, "PR_CompileFile: Didn't clear");
@ -14149,18 +14257,16 @@ pbool QCC_PR_CompileFile (char *string, char *filename)
compilingfile = filename; compilingfile = filename;
s_filen = tmp = qccHunkAlloc(strlen(filename)+1);
strcpy(tmp, filename);
if (opt_filenames) if (opt_filenames)
{ {
optres_filenames += strlen(filename); optres_filenames += strlen(filename);
pr_file_p = qccHunkAlloc(strlen(filename)+1); s_filed = 0;
strcpy(pr_file_p, filename);
s_file = pr_file_p - strings;
s_file2 = 0;
} }
else else
{ s_filed = QCC_CopyString (filename);
s_file = s_file2 = QCC_CopyString (filename);
}
pr_file_p = string; pr_file_p = string;
pr_assumetermtype = NULL; pr_assumetermtype = NULL;
@ -14257,14 +14363,15 @@ pbool QCC_Include(char *filename)
char *newfile; char *newfile;
char fname[512]; char fname[512];
char *opr_file_p; char *opr_file_p;
QCC_string_t os_file, os_file2; const char *os_filen;
QCC_string_t os_filed;
int opr_source_line; int opr_source_line;
char *ocompilingfile; char *ocompilingfile;
struct qcc_includechunk_s *oldcurrentchunk; struct qcc_includechunk_s *oldcurrentchunk;
ocompilingfile = compilingfile; ocompilingfile = compilingfile;
os_file = s_file; os_filen = s_filen;
os_file2 = s_file2; os_filed = s_filed;
opr_source_line = pr_source_line; opr_source_line = pr_source_line;
opr_file_p = pr_file_p; opr_file_p = pr_file_p;
oldcurrentchunk = currentchunk; oldcurrentchunk = currentchunk;
@ -14277,8 +14384,8 @@ pbool QCC_Include(char *filename)
currentchunk = oldcurrentchunk; currentchunk = oldcurrentchunk;
compilingfile = ocompilingfile; compilingfile = ocompilingfile;
s_file = os_file; s_filen = os_filen;
s_file2 = os_file2; s_filed = os_filed;
pr_source_line = opr_source_line; pr_source_line = opr_source_line;
pr_file_p = opr_file_p; pr_file_p = opr_file_p;

View file

@ -114,11 +114,20 @@ void QCC_PR_AddIncludePath(const char *newinc)
{ {
int i; int i;
if (!*newinc)
{
QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Invalid include path.");
return;
}
for (i = 0; i < MAXINCLUDEDIRS; i++) for (i = 0; i < MAXINCLUDEDIRS; i++)
{ {
if (!*qccincludedir[i]) if (!*qccincludedir[i])
{ {
const char *e = newinc + strlen(newinc)-1;
QC_strlcpy(qccincludedir[i], newinc, sizeof(qccincludedir)); QC_strlcpy(qccincludedir[i], newinc, sizeof(qccincludedir));
if (*e != '/' && *e != '\\')
QC_strlcat(qccincludedir[i], "/", sizeof(qccincludedir));
break; break;
} }
if (!strcmp(qccincludedir[i], newinc)) if (!strcmp(qccincludedir[i], newinc))
@ -126,13 +135,10 @@ void QCC_PR_AddIncludePath(const char *newinc)
} }
if (i == MAXINCLUDEDIRS) 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)); qcc_includechunk_t *chunk = qccHunkAlloc(sizeof(qcc_includechunk_t));
chunk->prev = currentchunk; chunk->prev = currentchunk;
@ -181,7 +187,7 @@ pbool QCC_PR_UnInclude(void)
PR_PrintNextLine PR_PrintNextLine
============== ==============
*/ */
void QCC_PR_PrintNextLine (void) static void QCC_PR_PrintNextLine (void)
{ {
char *t; char *t;
@ -191,7 +197,7 @@ void QCC_PR_PrintNextLine (void)
printf ("\n"); 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; int doubledots;
char *end = fullname; char *end = fullname;
@ -268,12 +274,22 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, pbool verbose)
} }
if (verbose) if (verbose)
{
if (verbose == 2)
{
if (autoprototype)
printf("prototyping %s\n", fullname);
else
printf("compiling %s\n", fullname);
}
else
{ {
if (autoprototype) if (autoprototype)
printf("prototyping include %s\n", fullname); printf("prototyping include %s\n", fullname);
else else
printf("including %s\n", fullname); printf("including %s\n", fullname);
} }
}
QCC_Include(fullname); QCC_Include(fullname);
} }
@ -285,6 +301,7 @@ int QCC_PR_LexInteger (void);
void QCC_AddFile (char *filename); void QCC_AddFile (char *filename);
void QCC_PR_LexString (void); void QCC_PR_LexString (void);
pbool QCC_PR_SimpleGetToken (void); pbool QCC_PR_SimpleGetToken (void);
pbool QCC_PR_SimpleGetString(void);
#define PPI_VALUE 0 #define PPI_VALUE 0
#define PPI_NOT 1 #define PPI_NOT 1
@ -800,9 +817,9 @@ pbool QCC_PR_Precompiler(void)
msg[a] = '\0'; msg[a] = '\0';
if (flag_msvcstyle) 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 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); QCC_PR_SkipToEndOfLine(false);
} }
else if (!strncmp(directive, "copyright", 9)) else if (!strncmp(directive, "copyright", 9))
@ -852,6 +869,25 @@ pbool QCC_PR_Precompiler(void)
QCC_PR_SkipToEndOfLine(true); 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)) else if (!strncmp(directive, "includelist", 11))
{ {
int defines=0; int defines=0;
@ -946,7 +982,7 @@ pbool QCC_PR_Precompiler(void)
while(qcc_iswhitesameline(*pr_file_p)) while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++; pr_file_p++;
QCC_PR_LexString(); QCC_PR_SimpleGetString();
printf("Including datafile: %s\n", pr_token); printf("Including datafile: %s\n", pr_token);
QCC_AddFile(pr_token); QCC_AddFile(pr_token);
@ -970,21 +1006,11 @@ pbool QCC_PR_Precompiler(void)
while(qcc_iswhitesameline(*pr_file_p)) while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++; pr_file_p++;
QCC_PR_LexString(); QCC_PR_SimpleGetString();
strcpy(destfile, pr_token); QCC_Canonicalize(destfile, sizeof(destfile), pr_token, compilingfile);
printf("Outputfile: %s\n", destfile); printf("Outputfile: %s\n", pr_token);
pr_file_p++; QCC_PR_SkipToEndOfLine(true);
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++;
}
} }
else if (!strncmp(directive, "pragma", 6)) else if (!strncmp(directive, "pragma", 6))
{ {
@ -2327,6 +2353,83 @@ void QCC_PR_ExpandMacro(void)
pr_immediate._float = (float)i; 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 // just parses text, returning false if an eol is reached
pbool QCC_PR_SimpleGetToken (void) pbool QCC_PR_SimpleGetToken (void)
{ {
@ -2872,7 +2975,7 @@ static char *QCC_PR_CheckBuiltinCompConst(char *constname, char *retbuf, size_t
} }
if (!strcmp(constname, "__FILE__")) if (!strcmp(constname, "__FILE__"))
{ {
QC_snprintfz(retbuf, retbufsize, "\"%s\"", strings + s_file); QC_snprintfz(retbuf, retbufsize, "\"%s\"", s_filen);
return retbuf; return retbuf;
} }
if (!strcmp(constname, "__LINE__")) if (!strcmp(constname, "__LINE__"))
@ -3165,9 +3268,9 @@ int QCC_PR_CheckCompConst(void)
if (flag_debugmacros) if (flag_debugmacros)
{ {
if (flag_msvcstyle) 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 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 else
@ -3399,14 +3502,14 @@ void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
{ {
if (!qccwarningaction[type]) if (!qccwarningaction[type])
return; return;
if (def->s_file) if (def->filen)
{ {
char tybuffer[512]; char tybuffer[512];
char tmbuffer[512]; char tmbuffer[512];
char *modifiers; char *modifiers;
if (QCC_Temp_Describe(def, tmbuffer, sizeof(tmbuffer))) 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 else
{ {
@ -3416,9 +3519,9 @@ void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
else if (def->isstatic) else if (def->isstatic)
modifiers = "static "; modifiers = "static ";
if (flag_msvcstyle) 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 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 #ifndef QCC
void editbadfile(char *file, int line); void editbadfile(const char *file, int line);
#endif #endif
//will abort. //will abort.
void VARGS QCC_PR_ParseError (int errortype, const char *error, ...) 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); va_end (argptr);
#ifndef QCC #ifndef QCC
editbadfile(strings+s_file, pr_source_line); editbadfile(s_filen, pr_source_line);
#endif #endif
QCC_PR_PrintScope(); QCC_PR_PrintScope();
if (flag_msvcstyle) 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 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); 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); va_end (argptr);
#ifndef QCC #ifndef QCC
editbadfile(strings+s_file, pr_source_line); editbadfile(s_filen, pr_source_line);
#endif #endif
QCC_PR_PrintScope(); QCC_PR_PrintScope();
if (flag_msvcstyle) 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 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); 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); va_end (argptr);
#ifndef QCC #ifndef QCC
editbadfile(strings+s_file, pr_source_line); editbadfile(s_filen, pr_source_line);
#endif #endif
QCC_PR_PrintScope(); QCC_PR_PrintScope();
if (flag_msvcstyle) 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 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); 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) if (!string)
; ;
else if (!file || !*file) else if (!file || !*file)
printf (": werror%s: %s\n", wnam, string); printf (":: werror%s: %s\n", wnam, string);
else if (flag_msvcstyle) else if (flag_msvcstyle)
printf ("%s(%i) : werror%s: %s\n", file, line, wnam, string); printf ("%s(%i) : werror%s: %s\n", file, line, wnam, string);
else else
@ -3564,7 +3667,7 @@ pbool VARGS QCC_PR_PrintWarning (int type, const char *file, int line, const cha
if (!string) if (!string)
; ;
else if (!file || !*file) else if (!file || !*file)
printf (": warning%s: %s\n", wnam, string); printf (":: warning%s: %s\n", wnam, string);
else if (flag_msvcstyle) else if (flag_msvcstyle)
printf ("%s(%i) : warning%s: %s\n", file, line, wnam, string); printf ("%s(%i) : warning%s: %s\n", file, line, wnam, string);
else else
@ -3604,7 +3707,7 @@ pbool VARGS QCC_PR_ParseWarning (int type, const char *error, ...)
QC_vsnprintf (string,sizeof(string)-1, error,argptr); QC_vsnprintf (string,sizeof(string)-1, error,argptr);
va_end (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, ...) 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) if (!qcc_typeinfo[i].typedefed)
continue; 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]; newt = &qcc_typeinfo[i];
break; 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 LoadFile
@ -330,6 +381,17 @@ unsigned char *PDECL QCC_ReadFile (const char *fname, void *buffer, int len, siz
{ {
long length; long length;
FILE *f; 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"); f = fopen(fname, "rb");
if (!f) if (!f)
return NULL; return NULL;
@ -347,6 +409,11 @@ int PDECL QCC_RawFileSize (const char *fname)
{ {
long length; long length;
FILE *f; FILE *f;
vfile_t *v = QCC_FindVFile(fname);
if (v)
return v->fsize;
f = fopen(fname, "rb"); f = fopen(fname, "rb");
if (!f) if (!f)
return -1; return -1;
@ -500,6 +567,9 @@ pbool PDECL QCC_WriteFile (const char *name, void *data, int len)
#endif #endif
} }
if (QCC_FindVFile(name))
return QCC_AddVFile(name, data, len);
f = fopen(name, "wb"); f = fopen(name, "wb");
if (!f) if (!f)
return false; return false;
@ -1241,7 +1311,7 @@ enum {
static void EditorReload(editor_t *editor); static void EditorReload(editor_t *editor);
int EditorSave(editor_t *edit); 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); pbool EditorModified(editor_t *e);
void QueryOpenFile(void) 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 (line > functions[fno].line && bestline < functions[fno].line)
{ {
if (!strcmp(editor->filename, functions[fno].file)) if (!strcmp(editor->filename, functions[fno].filen))
{ {
best = fno; best = fno;
bestline = functions[fno].line; bestline = functions[fno].line;
@ -2046,7 +2116,9 @@ static void UpdateEditorTitle(editor_t *editor)
encoding = "unknown"; encoding = "unknown";
break; 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); sprintf(title, "*%s:%i - %s", editor->filename, 1+editor->curline, encoding);
else else
sprintf(title, "%s:%i - %s", editor->filename, 1+editor->curline, encoding); 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 //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]; char title[1024];
editor_t *neweditor; 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. //our qcc itself is fine with utf-16, so long as it has a BOM.
if (e->scintilla) 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) else if (e->savefmt == UTF_ANSI)
{ {
@ -2738,10 +2810,12 @@ 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. SendMessage(e->editpane, SCI_SETSAVEPOINT, 0, 0); //tell the control that it was saved.
} }
else else
{
QCC_WriteFileW(e->filename, (wchar_t*)buffer+1, blen); QCC_WriteFileW(e->filename, (wchar_t*)buffer+1, blen);
} }
} }
} }
}
return buffer; return buffer;
} }
@ -5323,6 +5397,8 @@ void UpdateFileList(void)
int size; int size;
char *buffer; char *buffer;
AddSourceFile(NULL, progssrcname);
f = fopen (progssrcname, "rb"); f = fopen (progssrcname, "rb");
if (!f) if (!f)
return; return;
@ -5343,14 +5419,15 @@ void UpdateFileList(void)
if (*qcc_token == '#') if (*qcc_token == '#')
{ {
//aaaahhh! newstyle! //aaaahhh! newstyle!
AddSourceFile(NULL, progssrcname);
} }
else else
{ {
pr_file_p = QCC_COM_Parse(pr_file_p); //we dont care about the produced progs.dat pr_file_p = QCC_COM_Parse(pr_file_p); //we dont care about the produced progs.dat
AddSourceFile(NULL, progssrcname);
while(pr_file_p) while(pr_file_p)
{ {
if (*qcc_token == '#') //panic if there's preprocessor in there.
break;
AddSourceFile(progssrcname, qcc_token); AddSourceFile(progssrcname, qcc_token);
pr_file_p = QCC_COM_Parse(pr_file_p); //we dont care about the produced progs.dat 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); 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) if (fl_compileonstart)
{ {
CreateOutputWindow(false); CreateOutputWindow(false);

View file

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

View file

@ -80,7 +80,7 @@ int numstatements;
QCC_function_t *functions; QCC_function_t *functions;
dfunction_t *dfunctions; //dfunction_t *dfunctions;
int numfunctions; int numfunctions;
QCC_ddef_t *qcc_globals; QCC_ddef_t *qcc_globals;
@ -200,6 +200,8 @@ struct {
{" F312", WARN_OVERFLOW}, {" F312", WARN_OVERFLOW},
{" F313", WARN_DENORMAL}, {" F313", WARN_DENORMAL},
{" F314", WARN_LAXCAST}, {" F314", WARN_LAXCAST},
{" F315", WARN_DUPLICATEPRECOMPILER},
{" F316", WARN_IDENTICALPRECOMPILER},
{" F208", WARN_NOTREFERENCEDCONST}, {" F208", WARN_NOTREFERENCEDCONST},
{" F209", WARN_EXTRAPRECACHE}, {" 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_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_var, defaultkeyword, "var", "Keyword: var", "Disables the 'var' keyword."},
{&keyword_vector, defaultkeyword, "vector", "Keyword: vector", "Disables the 'vector' 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 //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."}, {&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 #ifdef AVAIL_ZLIB
idf[num].compmethod = 2; idf[num].compmethod = 2;
#else #else
idf[num].compmethod = 1; idf[num].compmethod = 0;
#endif #endif
idf[num].ofs = SafeSeek(h, 0, SEEK_CUR); idf[num].ofs = SafeSeek(h, 0, SEEK_CUR);
idf[num].compsize = QC_encode(progfuncs, f->size, idf[num].compmethod, f->file, h); 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; int ret=0;
for (d=pr.def_head.next ; d ; d=d->next) 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->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); SafeWrite(handle, d->name, strlen(d->name)+1);
ret++; 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 (verbose >= 3)
{ {
if (onum == numpr_globals) 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 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 (verbose >= 3)
{ {
if (onum == numpr_globals) 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 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) 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].first_statement = PRLittleLong (functions[i].code);
funcs[i].parm_start = 0;//PRLittleLong (functions[i].parm_start); funcs[i].parm_start = 0;//PRLittleLong (functions[i].parm_start);
funcs[i].s_name = PRLittleLong (QCC_CopyString(functions[i].name)); 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].numparms = 0;//PRLittleLong ((functions[i].numparms>MAX_PARMS)?MAX_PARMS:functions[i].numparms);
funcs[i].locals = 0;//PRLittleLong (functions[i].locals); funcs[i].locals = 0;//PRLittleLong (functions[i].locals);
for (j = 0; j < MAX_PARMS; j++) for (j = 0; j < MAX_PARMS; j++)
@ -1327,9 +1338,17 @@ pbool QCC_WriteData (int crc)
} }
else else
funcs[i].s_name = PRLittleLong (QCC_CopyString(functions[i].name)); 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].parm_start = 0;
funcs[i].locals = 0; funcs[i].locals = 0;
@ -1346,7 +1365,7 @@ pbool QCC_WriteData (int crc)
{ {
if (!local->used) if (!local->used)
{ //all params should have been assigned space. logically we could have safely omitted the last ones, but blurgh. { //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; continue;
} }
@ -1394,10 +1413,10 @@ pbool QCC_WriteData (int crc)
funcs[i].numparms = PRLittleLong(funcs[i].numparms); funcs[i].numparms = PRLittleLong(funcs[i].numparms);
if (funcs[i].locals && !funcs[i].parm_start) 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 #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 #endif
} }
funcdata = funcs; 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) else if (strcmp(def->name, "IMMEDIATE") && qccwarningaction[wt] && !(def->type->type == ev_function && def->symbolheader->timescalled) && !def->symbolheader->used)
{ {
char typestr[256]; 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 { //try to avoid annoying warnings from dpextensions.qc
extwarncount++; 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) 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 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; pr_scope = NULL;
@ -1470,7 +1489,7 @@ pbool QCC_WriteData (int crc)
{ {
optres_unreferenced++; optres_unreferenced++;
#ifdef DEBUG_DUMP #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 #endif
continue; 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) if ((def->type->type == ev_struct || def->type->type == ev_union || def->arraysize) && def->deftail)
{ {
#ifdef DEBUG_DUMP #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 #endif
//the head of an array/struct is never written. only, its member fields are. //the head of an array/struct is never written. only, its member fields are.
continue; continue;
@ -2157,7 +2176,7 @@ strofs = (strofs+3)&~3;
printf("unable to write value for 'entity progs'\n"); //would not work anyway printf("unable to write value for 'entity progs'\n"); //would not work anyway
else 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) if (def->initialized)
i = PRLittleLong(qcc_pr_globals[def->ofs]._int); i = PRLittleLong(qcc_pr_globals[def->ofs]._int);
@ -2264,6 +2283,289 @@ strofs = (strofs+3)&~3;
return true; 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; QCC_type_t *t;
int errors; int errors;
pbool externokay = false;
errors = 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 // check to make sure all functions prototyped have code
for (d=pr.def_head.next ; d ; d=d->next) for (d=pr.def_head.next ; d ; d=d->next)
{ {
@ -2652,15 +2959,23 @@ int QCC_PR_FinishCompilation (void)
continue; 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); QCC_PR_ParsePrintDef(ERR_NOFUNC, d);
bodylessfuncs = true; bodylessfuncs = true;
errors = true; errors = true;
} }
else if (d->initialized==2) 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; bodylessfuncs = true;
} }
} }
}
pr_scope = NULL; pr_scope = NULL;
return !errors; return !errors;
@ -2819,7 +3134,9 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
{ {
if (!strcmp (d->name, "end_sys_globals")) if (!strcmp (d->name, "end_sys_globals"))
break; break;
// if (d->ofs<RESERVED_OFS) if (!*d->name)
continue;
// if (d->symbolheader->ofs<RESERVED_OFS)
// continue; // continue;
switch (d->type->type) 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) void QCC_PR_CommandLinePrecompilerOptions (void)
{ {
@ -3400,6 +3722,47 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
for (i = 1;i<myargc;i++) 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 //compiler constant
if ( !strncmp(myargv[i], "-D", 2) ) if ( !strncmp(myargv[i], "-D", 2) )
{ {
@ -3427,7 +3790,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
} }
//optimisations. //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; qcc_nopragmaoptimise = true;
p = 0; p = 0;
@ -3462,7 +3825,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised optimisation parameter (%s)", myargv[i]); 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; p = 0;
if (!strnicmp(myargv[i]+2, "no-", 3)) if (!strnicmp(myargv[i]+2, "no-", 3))
@ -3487,7 +3850,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void)
if (!compiler_flag[p].enabled) if (!compiler_flag[p].enabled)
QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised keyword parameter (%s)", myargv[i]); 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; pbool state;
const char *arg; 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; p = 0;
if (!strcmp("parse", myargv[i]+2)) 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")) 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]); 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) if (werror)
@ -3661,6 +4026,9 @@ void QCC_SetDefaultProperties (void)
ForcedCRC = 0; ForcedCRC = 0;
defaultstatic = 0; defaultstatic = 0;
verbose = 0;
*qccmsourcedir = 0;
QCC_PR_CloseProcessor();
QCC_PR_DefineName("FTEQCC"); 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_UNINITIALIZED] = WA_IGNORE; //not sure about this being ignored by default.
qccwarningaction[WARN_SELFNOTTHIS] = WA_IGNORE; qccwarningaction[WARN_SELFNOTTHIS] = WA_IGNORE;
qccwarningaction[WARN_EVILPREPROCESSOR] = WA_WARN;//FIXME: make into WA_ERROR; qccwarningaction[WARN_EVILPREPROCESSOR] = WA_WARN;//FIXME: make into WA_ERROR;
qccwarningaction[WARN_IDENTICALPRECOMPILER] = WA_IGNORE;
if (qcc_targetformat == QCF_HEXEN2 || qcc_targetformat == QCF_FTEH2) if (qcc_targetformat == QCF_HEXEN2 || qcc_targetformat == QCF_FTEH2)
qccwarningaction[WARN_CASEINSENSITIVEFRAMEMACRO] = WA_IGNORE; //hexenc consides these fair game. 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; char *s;
s_filen = "cmdline";
s_filed = 0;
pr_source_line = 0;
if (numsourcefiles && currentsourcefile == numsourcefiles) if (numsourcefiles && currentsourcefile == numsourcefiles)
{ {
numsourcefiles = 0; numsourcefiles = 0;
return false; return false;
} }
else if (!numsourcefiles)
currentsourcefile = 0;
if (currentsourcefile && qccpersisthunk && numsourcefiles) if (currentsourcefile && qccpersisthunk && numsourcefiles)
QCC_PR_ResetErrorScope(); //don't clear the ram if we're retaining def info 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; tempsused = 0;
s_file = 0;
QCC_PurgeTemps(); QCC_PurgeTemps();
@ -4090,12 +4464,6 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
memset(&extra_parms, 0, sizeof(extra_parms)); memset(&extra_parms, 0, sizeof(extra_parms));
#endif #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")) if ( QCC_CheckParm ("/?") || QCC_CheckParm ("?") || QCC_CheckParm ("-?") || QCC_CheckParm ("-help") || QCC_CheckParm ("--help"))
{ {
printf ("qcc looks for progs.src in the current directory.\n"); 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; pHash_RemoveData = &Hash_RemoveDataInsensitive;
} }
p = QCC_CheckParm ("-src"); if (*qccmsourcedir)
if (p && p < argc-1 )
{
strcpy (qccmsourcedir, argv[p+1]);
strcat (qccmsourcedir, "/");
printf ("Source directory: %s\n", qccmsourcedir); printf ("Source directory: %s\n", qccmsourcedir);
}
else
*qccmsourcedir = '\0';
QCC_InitData (); QCC_InitData ();
@ -4177,8 +4538,6 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
if (!numsourcefiles) if (!numsourcefiles)
{ {
p = QCC_CheckParm ("-qc"); p = QCC_CheckParm ("-qc");
if (!p || p >= argc-1 || argv[p+1][0] == '-')
p = QCC_CheckParm ("-srcfile");
if (p && p < argc-1 ) if (p && p < argc-1 )
sprintf (qccmprogsdat, "%s", argv[p+1]); sprintf (qccmprogsdat, "%s", argv[p+1]);
else else
@ -4335,6 +4694,13 @@ void QCC_ContinueCompile(void)
return; 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); qccmsrc = QCC_COM_Parse(qccmsrc);
if (!qccmsrc) if (!qccmsrc)
{ {
@ -4371,18 +4737,51 @@ void QCC_ContinueCompile(void)
} }
return; 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) if (autoprototype)
printf ("prototyping %s\n", qccmfilename); printf ("prototyping %s\n", qccmfilename);
else else
{ {
printf ("compiling %s\n", qccmfilename); printf ("compiling %s\n", qccmfilename);
} }
QCC_LoadFile (qccmfilename, (void *)&qccmsrc2); QCC_LoadFile (qccmfilename, (void *)&qccmsrc2);
if (!QCC_PR_CompileFile (qccmsrc2, qccmfilename) ) if (!QCC_PR_CompileFile (qccmsrc2, qccmfilename) )
QCC_Error (ERR_PARSEERRORS, "Errors have occured\n"); QCC_Error (ERR_PARSEERRORS, "Errors have occured\n");
*/
} }
void QCC_FinishCompile(void) void QCC_FinishCompile(void)
{ {
@ -4394,7 +4793,8 @@ void QCC_FinishCompile(void)
if (setjmp(pr_parse_abort)) if (setjmp(pr_parse_abort))
QCC_Error(ERR_INTERNAL, ""); QCC_Error(ERR_INTERNAL, "");
s_file = 0; s_filen = "";
s_filed = 0;
pr_source_line = 0; pr_source_line = 0;
if (!QCC_PR_FinishCompilation ()) 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 char *pr_file_p;
extern int pr_source_line; extern int pr_source_line;
void QCC_PR_ParseDefs (char *classname); void QCC_PR_ParseDefs (char *classname);
@ -4521,6 +4920,7 @@ void QCC_PR_ParseDefs (char *classname);
void StartNewStyleCompile(void) void StartNewStyleCompile(void)
{ {
char *tmp;
if (setjmp(pr_parse_abort)) if (setjmp(pr_parse_abort))
{ {
if (++pr_error_count > MAX_ERRORS) if (++pr_error_count > MAX_ERRORS)
@ -4535,8 +4935,17 @@ void StartNewStyleCompile(void)
compilingfile = qccmprogsdat; 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; pr_file_p = qccmsrc;
s_file = s_file2 = QCC_CopyString (compilingfile);
pr_source_line = 0; pr_source_line = 0;
@ -4565,9 +4974,19 @@ void new_QCC_ContinueCompile(void)
if (autoprototype && !parseonly) if (autoprototype && !parseonly)
{ {
char *tmp;
qccmsrc = originalqccmsrc; 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; pr_file_p = qccmsrc;
s_file = s_file2 = QCC_CopyString (compilingfile);
autoprototyped = autoprototype; autoprototyped = autoprototype;
QCC_SetDefaultProperties(); QCC_SetDefaultProperties();

View file

@ -1,6 +1,7 @@
pbool QC_decodeMethodSupported(int method); pbool QC_decodeMethodSupported(int method);
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 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);
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); int QC_encodecrc(int len, char *in);
char *PDECL filefromprogs(pubprogfuncs_t *progfuncs, progsnum_t prnum, char *fname, size_t *size, char *buffer); 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 "progsint.h"
//#include "qcc.h" #include "qcc.h"
#ifndef NO_ZLIB #ifndef NO_ZLIB
#define AVAIL_ZLIB #define AVAIL_ZLIB
@ -35,7 +35,7 @@ pbool QC_decodeMethodSupported(int method)
return false; 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; int i;
if (method == 0) //copy 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++) for (i = 0; i < len; i++)
buffer[i] = info[i] ^ 0xA5; buffer[i] = info[i] ^ 0xA5;
} }
else if (method == 2) //compression (ZLIB)
{
#ifdef AVAIL_ZLIB #ifdef AVAIL_ZLIB
else if (method == 2 || method == 8) //compression (ZLIB)
{
z_stream strm = { z_stream strm = {
info, (char*)info,
complen, complen,
0, 0,
@ -73,12 +73,15 @@ char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char *
0 0
}; };
if (method == 8)
inflateInit2(&strm, -MAX_WBITS);
else
inflateInit(&strm); inflateInit(&strm);
if (Z_STREAM_END != inflate(&strm, Z_FINISH)) //decompress it in one go. if (Z_STREAM_END != inflate(&strm, Z_FINISH)) //decompress it in one go.
Sys_Error("Failed block decompression\n"); Sys_Error("Failed block decompression\n");
inflateEnd(&strm); inflateEnd(&strm);
#endif
} }
#endif
//add your decryption/decompression routine here. //add your decryption/decompression routine here.
else else
Sys_Error("Bad file encryption routine\n"); Sys_Error("Bad file encryption routine\n");
@ -96,10 +99,10 @@ int QC_encodecrc(int len, char *in)
return 0; return 0;
#endif #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); int SafeSeek(int hand, int ofs, int mode);
//we are allowed to trash our input here. //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; int i;
if (method == 0) //copy, allows a lame pass-through. 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); SafeWrite(handle, in, len);
return 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++) for (i = 0; i < len; i++)
in[i] = in[i] ^ 0xA5; in[i] = in[i] ^ 0xA5;
SafeWrite(handle, in, len); SafeWrite(handle, in, len);
return len; return len;
} }*/
else if (method == 2 || method == 8) //compression (ZLIB) else if (method == 2 || method == 8) //compression (ZLIB)
{ {
#ifdef AVAIL_ZLIB #ifdef AVAIL_ZLIB
char out[8192]; char out[8192];
z_stream strm = { z_stream strm = {
in, (char *)in,
len, len,
0, 0,
@ -169,6 +172,75 @@ int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle)
} }
#endif #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) char *PDECL filefromprogs(pubprogfuncs_t *ppf, progsnum_t prnum, char *fname, size_t *size, char *buffer)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;

View file

@ -1,5 +1,8 @@
#if !defined(MINIMAL) && !defined(OMIT_QCC) #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 "qcc.h"
#include "progsint.h" #include "progsint.h"
#include "setjmp.h" #include "setjmp.h"
@ -861,7 +864,7 @@ pbool PDECL QC_Decompile(pubprogfuncs_t *ppf, char *fname)
f=SafeOpenWrite("qcdtest/defs.qc", 1024*512); 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); 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_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. #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 = {"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) static void QCBUILTIN PF_aim (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
edict_t *ent, *check, *bestent; edict_t *ent, *check, *bestent;
@ -10951,6 +10929,26 @@ void PR_DumpPlatform_f(void)
#else #else
//eg: pr_dumpplatform -FFTE -TCS -O csplat //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 idx;
int i, j; int i, j;
int d = 0, nd, k; 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_MONSTERCLIP", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_MONSTERCLIP)},
{"CONTENTBIT_BODY", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_BODY)}, {"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_CORPSE", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_CORPSE)},
{"CONTENTBIT_Q2LADDER", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(Q2CONTENTS_LADDER)}, {"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)}, {"CONTENTBIT_SKY", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_SKY)"i"},
{"CONTENTBITS_POINTSOLID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(MASK_POINTSOLID)}, {"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, NULL, 0,STRINGIFY(MASK_BOXSOLID)}, {"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,STRINGIFY(FTECONTENTS_FLUID)}, {"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_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}, {"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, "#define %s\n", QSG_Extensions[i].name);
} }
VFS_PRINTF(f, "\n");
if (accessors) if (accessors)
{ VFS_PRINTF(f, "#define _ACCESSORS;\n");
VFS_PRINTF(f, "accessor strbuf : float;\n");
VFS_PRINTF(f, "accessor searchhandle : float;\n"); VFS_PRINTF(f,
VFS_PRINTF(f, "accessor hashtable : float;\n"); "#ifdef _ACCESSORS\n"
VFS_PRINTF(f, "accessor infostring : string;\n"); "accessor strbuf : float;\n"
VFS_PRINTF(f, "accessor filestream : float;\n"); "accessor searchhandle : float;\n"
} "accessor hashtable : float;\n"
else "accessor infostring : string;\n"
{ "accessor filestream : float;\n"
VFS_PRINTF(f, "#define strbuf float\n"); "accessor filestream : float;\n"
VFS_PRINTF(f, "#define searchhandle float\n"); "#else\n"
VFS_PRINTF(f, "#define hashtable float\n"); "#define strbuf float\n"
VFS_PRINTF(f, "#define infostring string\n"); "#define searchhandle float\n"
VFS_PRINTF(f, "#define filestream 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++) for (i = 0; knowndefs[i].name; i++)
@ -12238,6 +12242,7 @@ void PR_DumpPlatform_f(void)
if (accessors) if (accessors)
{ {
VFS_PRINTF(f, "#ifdef _ACCESSORS\n");
VFS_PRINTF(f, VFS_PRINTF(f,
"accessor strbuf : float\n{\n" "accessor strbuf : float\n{\n"
"\tinline get float asfloat[float idx] = {return stof(bufstr_get(this, idx));};\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" "\tget string = fgets;\n"
"\tinline set string = {fputs(this,value);};\n" "\tinline set string = {fputs(this,value);};\n"
"};\n"); "};\n");
VFS_PRINTF(f, "#endif\n");
} }
VFS_PRINTF(f, "#pragma noref 0\n"); VFS_PRINTF(f, "#pragma noref 0\n");

View file

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

View file

@ -37,7 +37,7 @@ qboolean SV_MayCheat(void)
} }
extern cvar_t cl_warncmd; 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 redirect_t sv_redirected;
extern cvar_t sv_public; extern cvar_t sv_public;

View file

@ -58,14 +58,14 @@ cvar_t sv_nopvs = CVARD("sv_nopvs", "0", "Set to 1 to ignore pvs on the server.
cvar_t fraglog_public = CVARD("fraglog_public", "1", "Enables support for connectionless fraglog requests"); 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 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 timeout = CVAR("timeout","65"); // seconds without any message
cvar_t zombietime = SCVAR("zombietime", "2"); // seconds to sink messages cvar_t zombietime = CVAR("zombietime", "2"); // seconds to sink messages
// after disconnect // after disconnect
#ifdef SERVERONLY #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 rcon_password = CVARF("rcon_password", "", CVAR_NOUNSAFEEXPAND); // password for remote server commands
cvar_t password = SCVARF("password", "", CVAR_NOUNSAFEEXPAND); // password for entering the game cvar_t password = CVARF("password", "", CVAR_NOUNSAFEEXPAND); // password for entering the game
#else #else
extern cvar_t developer; extern cvar_t developer;
extern cvar_t rcon_password; extern cvar_t rcon_password;
@ -4415,6 +4415,11 @@ static void SV_PauseChanged(void)
ClientReliableWrite_Byte (cl, sv.paused!=0); 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_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_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_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_password = CVAR( "qtv_password", "");
cvar_t qtv_streamport = CVARAF( "qtv_streamport", "0", 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) else if (d->desttype != DEST_STREAM)
{ {
char buf[512]; 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); Z_Free(d);
@ -134,8 +134,11 @@ void DestFlush(qboolean compleate)
int len; int len;
mvddest_t *d, *t; mvddest_t *d, *t;
if (compleate)
{
//make sure everything is flushed. //make sure everything is flushed.
MVDWrite_Begin(255, -1, 0); MVDWrite_Begin(255, -1, 0);
}
if (!demo.dest) if (!demo.dest)
return; return;
@ -380,7 +383,7 @@ void SV_MVD_RunPendingConnections(void)
start = start+1; start = start+1;
while(*start == ' ' || *start == '\t') while(*start == ' ' || *start == '\t')
start++; 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")) if (!strcmp(com_token, "VERSION"))
{ {
start = COM_ParseToken(start, NULL); start = COM_ParseToken(start, NULL);
@ -429,6 +432,14 @@ void SV_MVD_RunPendingConnections(void)
{ {
//compression not supported yet //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 else
{ {
//not recognised. //not recognised.
@ -865,77 +876,9 @@ void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
MSG_WriteString (msg, info); 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) 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); SV_WriteMVDMessage(&demomsg, demomsgtype, demomsgto, demo_prevtime);
demomsg.cursize = 0; demomsg.cursize = 0;
@ -945,51 +888,9 @@ sizebuf_t *MVDWrite_Begin(qbyte type, int to, int size)
demomsgto = to; demomsgto = to;
demomsg.maxsize = demomsg.cursize+size; demomsg.maxsize = demomsg.cursize+size;
demomsg.cursize = 0;
demomsg.data = demomsgbuf; demomsg.data = demomsgbuf;
demomsg.prim = demo.recorder.netchan.netprim; demomsg.prim = demo.recorder.netchan.netprim;
return &demomsg; 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) if (!sv.mvdrecording)
return; return;
if (msg->overflowed)
{
msg->overflowed = false;
Con_Printf("SV_WriteMVDMessage: message overflowed\n");
return;
}
msec = (time - demo_prevtime)*1000; msec = (time - demo_prevtime)*1000;
if (abs(msec) > 1000) if (abs(msec) > 1000)
{ {
//catastoptic slip. debugging? reset any sync //catastoptic slip. debugging? reset any sync
msec = 0; msec = 1;
demo_prevtime = time; demo_prevtime = time;
} }
else else if (msec > 0)
{ { //if there was any progress, make sure we write msecs >0
if (msec > 255) msec = 255; if (msec > 255)
if (msec < 2) msec = 0; msec = 255;
if (msec < 1)
msec = 1;
demo_prevtime += msec*0.001; demo_prevtime += msec*0.001;
} }
else
msec = 0;
c = msec; c = msec;
DemoWrite(&c, sizeof(c)); 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. //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; int i;
if (writebroadcasts)
{
//chuck in the broadcast reliables //chuck in the broadcast reliables
ClientReliableCheckBlock(&demo.recorder, sv.reliable_datagram.cursize); ClientReliableCheckBlock(&demo.recorder, sv.reliable_datagram.cursize);
ClientReliableWrite_SZ(&demo.recorder, sv.reliable_datagram.data, 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 //and the broadcast unreliables. everything is reliables when it comes to mvds
ClientReliableCheckBlock(&demo.recorder, sv.datagram.cursize); ClientReliableCheckBlock(&demo.recorder, sv.datagram.cursize);
ClientReliableWrite_SZ(&demo.recorder, sv.datagram.data, sv.datagram.cursize); ClientReliableWrite_SZ(&demo.recorder, sv.datagram.data, sv.datagram.cursize);
}
if (demo.recorder.netchan.message.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; demo.recorder.netchan.message.cursize = 0;
} }
for (i = 0; i < demo.recorder.num_backbuf; i++) 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.data = demo.recorder.backbuf_data[i];
demo.recorder.backbuf.cursize = demo.recorder.backbuf_size[i]; demo.recorder.backbuf.cursize = demo.recorder.backbuf_size[i];
if (demo.recorder.backbuf.cursize) 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.backbuf_size[i] = 0;
} }
demo.recorder.num_backbuf = 0; demo.recorder.num_backbuf = 0;
@ -1143,6 +1058,8 @@ qboolean SV_MVDWritePackets (int num)
//flush any intermediate data //flush any intermediate data
MVDWrite_Begin(255, -1, 0); MVDWrite_Begin(255, -1, 0);
msg.allowoverflow = true; //fixme
msg.overflowed = false;
msg.prim = svs.netprim; msg.prim = svs.netprim;
msg.data = msg_buf; msg.data = msg_buf;
msg.maxsize = sizeof(msg_buf); msg.maxsize = sizeof(msg_buf);
@ -1714,6 +1631,7 @@ qboolean SV_MVD_Record (mvddest_t *dest)
if (!dest) if (!dest)
return false; return false;
SV_MVD_WriteReliables(false);
DestFlush(true); DestFlush(true);
if (!sv.mvdrecording) if (!sv.mvdrecording)
@ -1726,7 +1644,7 @@ qboolean SV_MVD_Record (mvddest_t *dest)
demo.datagram.data = demo.datagram_data; demo.datagram.data = demo.datagram_data;
demo.datagram.prim = demo.recorder.netchan.netprim; 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*/ { /*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_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*/ // 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); SV_MVD_SendInitialGamestate(dest);
return true; return true;
} }
void SV_EnableClientsCSQC(void); void SV_EnableClientsCSQC(void);
void SV_MVD_SendInitialGamestate(mvddest_t *dest) void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{ {
@ -1788,7 +1707,10 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (!demo.dest) if (!demo.dest)
return; return;
SV_MVD_WriteReliables(false);
sv.mvdrecording = true; sv.mvdrecording = true;
demo.resetdeltas = true;
host_client = &demo.recorder; host_client = &demo.recorder;
if (host_client->fteprotocolextensions & PEXT_CSQC) if (host_client->fteprotocolextensions & PEXT_CSQC)
@ -1860,7 +1782,6 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
SV_WriteRecordMVDMessage (&buf); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
#if 1
demo.recorder.prespawn_stage = PRESPAWN_SERVERINFO; demo.recorder.prespawn_stage = PRESPAWN_SERVERINFO;
demo.recorder.prespawn_idx = 0; demo.recorder.prespawn_idx = 0;
demo.recorder.netchan.message = buf; 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. 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_SendClientPrespawnInfo(&demo.recorder);
SV_WriteRecordMVDMessage (&demo.recorder.netchan.message); SV_MVD_WriteReliables(false);
SZ_Clear (&demo.recorder.netchan.message);
} }
memset(&demo.recorder.netchan.message, 0, sizeof(demo.recorder.netchan.message)); 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 // send current status of all other players
for (i = 0; i < demo.recorder.max_net_clients && i < svs.allocated_client_slots; i++) 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) if (buf.cursize > MAX_QWMSGLEN/2)
{ {
//flush backbuffer
SV_WriteRecordMVDMessage (&buf); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
@ -2096,8 +1847,8 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{ {
for (j = 0; j < MAX_CL_STATS; j++) for (j = 0; j < MAX_CL_STATS; j++)
{ {
demo.statsi[i][j] ^= -1; demo.statsi[i][j] = 0x7fffffff;
demo.statsf[i][j] *= -0.41426712; //randomish value demo.statsf[i][j] = -0x7fffffff;
} }
demo.playerreset[i] = true; demo.playerreset[i] = true;
} }
@ -2108,7 +1859,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
MSG_WriteString (&buf, "skins\n"); MSG_WriteString (&buf, "skins\n");
SV_WriteRecordMVDMessage (&buf); SV_WriteRecordMVDMessage (&buf);
SV_MVD_WriteReliables(false);
SV_WriteSetMVDMessage(); SV_WriteSetMVDMessage();
singledest = NULL; 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_gravity = CVAR( "sv_gravity", "800");
cvar_t sv_stopspeed = SCVAR( "sv_stopspeed", "100"); cvar_t sv_stopspeed = CVAR( "sv_stopspeed", "100");
cvar_t sv_maxspeed = SCVAR( "sv_maxspeed", "320"); cvar_t sv_maxspeed = CVAR( "sv_maxspeed", "320");
cvar_t sv_spectatormaxspeed = SCVAR( "sv_spectatormaxspeed", "500"); cvar_t sv_spectatormaxspeed = CVAR( "sv_spectatormaxspeed", "500");
cvar_t sv_accelerate = SCVAR( "sv_accelerate", "10"); cvar_t sv_accelerate = CVAR( "sv_accelerate", "10");
cvar_t sv_airaccelerate = SCVAR( "sv_airaccelerate", "0.7"); cvar_t sv_airaccelerate = CVAR( "sv_airaccelerate", "0.7");
cvar_t sv_wateraccelerate = SCVAR( "sv_wateraccelerate", "10"); cvar_t sv_wateraccelerate = CVAR( "sv_wateraccelerate", "10");
cvar_t sv_friction = SCVAR( "sv_friction", "4"); cvar_t sv_friction = CVAR( "sv_friction", "4");
cvar_t sv_waterfriction = SCVAR( "sv_waterfriction", "4"); cvar_t sv_waterfriction = CVAR( "sv_waterfriction", "4");
cvar_t sv_gameplayfix_noairborncorpse = SCVAR( "sv_gameplayfix_noairborncorpse", "0"); 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_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."); 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) #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.reliable_datagram);
SZ_Clear (&sv.datagram); SZ_Clear (&sv.datagram);
@ -3322,8 +3322,6 @@ void SV_SendMVDMessage(void)
// possibly a nails update // possibly a nails update
msg.cursize = 0; msg.cursize = 0;
msg.prim = demo.recorder.netchan.netprim; msg.prim = demo.recorder.netchan.netprim;
if (!demo.recorder.delta_sequence)
demo.recorder.delta_sequence = -1;
// copy the accumulated multicast datagram // copy the accumulated multicast datagram
// for this client out to the message // for this client out to the message
@ -3339,6 +3337,12 @@ void SV_SendMVDMessage(void)
SV_MVDWritePackets(1); SV_MVDWritePackets(1);
} }
if (demo.resetdeltas)
{
demo.resetdeltas = false;
demo.recorder.delta_sequence = -1;
}
else
demo.recorder.delta_sequence = demo.recorder.netchan.incoming_sequence&255; demo.recorder.delta_sequence = demo.recorder.netchan.incoming_sequence&255;
demo.recorder.netchan.incoming_sequence++; demo.recorder.netchan.incoming_sequence++;
demo.frames[demo.parsecount&DEMO_FRAMES_MASK].time = demo.time = sv.time; 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; dllhandle_t *sqlitehandle;
#endif #endif
cvar_t sql_driver = SCVARF("sv_sql_driver", "", CVAR_NOUNSAFEEXPAND); cvar_t sql_driver = CVARF("sv_sql_driver", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_host = SCVARF("sv_sql_host", "127.0.0.1", CVAR_NOUNSAFEEXPAND); cvar_t sql_host = CVARF("sv_sql_host", "127.0.0.1", CVAR_NOUNSAFEEXPAND);
cvar_t sql_username = SCVARF("sv_sql_username", "", CVAR_NOUNSAFEEXPAND); cvar_t sql_username = CVARF("sv_sql_username", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_password = SCVARF("sv_sql_password", "", CVAR_NOUNSAFEEXPAND); cvar_t sql_password = CVARF("sv_sql_password", "", CVAR_NOUNSAFEEXPAND);
cvar_t sql_defaultdb = SCVARF("sv_sql_defaultdb", "", CVAR_NOUNSAFEEXPAND); cvar_t sql_defaultdb = CVARF("sv_sql_defaultdb", "", CVAR_NOUNSAFEEXPAND);
void SQL_PushResult(sqlserver_t *server, queryresult_t *qres) 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_rollspeed;
extern cvar_t cl_rollangle; extern cvar_t cl_rollangle;
#endif #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_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."); 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_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_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 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 = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server. 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 = SCVAR("cmd_gamecodelevel", STRINGIFY(RESTRICT_LOCAL)); //execution level which gamecode is told about (for unrecognised commands) 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_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."); 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_walljump;
extern cvar_t pm_watersinkspeed; extern cvar_t pm_watersinkspeed;
extern cvar_t pm_flyfriction; 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 //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_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_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_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 #ifdef VOICECHAT
cvar_t sv_voip = CVARD("sv_voip", "1", "Enable reception of voice packets."); 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) else if (client->prespawn_idx == 4)
{ {
ClientReliableWrite_Begin(client, svc_setpause, 2); ClientReliableWrite_Begin(client, svc_setpause, 2);
ClientReliableWrite_Byte (client, sv.paused); ClientReliableWrite_Byte (client, sv.paused!=0);
} }
else 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 //figure out which gpu we're going to use
{ {
uint32_t gpucount = 0, i; 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++) for (i = 0; i < gpucount; i++)
{ {
VkPhysicalDeviceProperties props; VkPhysicalDeviceProperties props;
uint32_t j, queue_count;
vkGetPhysicalDeviceProperties(devs[i], &props); 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) if (!vk.gpu)
vk.gpu = devs[i]; vk.gpu = devs[i];
switch(props.deviceType) 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 //figure out which of the device's queue's we're going to use
{ {
uint32_t queue_count, i; uint32_t queue_count, i;