qcc: Add unsigned int, long/__int64, unsigned long/__uint64, and double datatypes to qcc+qcvm.

qcc: Add '#pragma opcode enable|disable NAME' to override whether an individual opcode may be generated for the current target.
nq: Fix smartjump on nq servers.
nq: Fix enemyskin/teamskin stuff on nq servers.
Rework show_fps cvar to give a greater focus on the timings graph.
Update updates menu to allow enabling/disabling specific sources.
Add separate settings for ef_red+ef_green+ef_blue.



git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5768 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-09-29 07:09:01 +00:00
parent 24a9634ccc
commit e3fdbfcdbd
46 changed files with 3320 additions and 1071 deletions

View file

@ -74,8 +74,8 @@ int CDAudio_GetAudioDiskInfo(void)
if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 )
{
Con_DPrintf("ioctl cdromreadtochdr failed\n");
return -1;
Con_DPrintf("ioctl cdromreadtochdr failed\n");
return -1;
}
if (tochdr.cdth_trk0 < 1)
@ -196,7 +196,7 @@ qboolean CDAudio_Startup(void)
cd_dev[sizeof(cd_dev) - 1] = 0;
}
if ((cdfile = open(cd_dev, O_RDONLY)) == -1)
if ((cdfile = open(cd_dev, O_RDONLY|O_NONBLOCK)) == -1)
{
Con_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno);
cdfile = -1;

View file

@ -30,6 +30,7 @@ extern cvar_t cl_predict_players_latency;
extern cvar_t cl_predict_players_nudge;
extern cvar_t cl_lerp_players;
extern cvar_t cl_lerp_maxinterval;
extern cvar_t cl_lerp_maxdistance;
extern cvar_t cl_solid_players;
extern cvar_t cl_item_bobbing;
@ -37,6 +38,9 @@ extern cvar_t r_rocketlight;
extern cvar_t r_lightflicker;
extern cvar_t r_dimlight_colour;
extern cvar_t r_brightlight_colour;
extern cvar_t r_redlight_colour;
extern cvar_t r_greenlight_colour;
extern cvar_t r_bluelight_colour;
extern cvar_t cl_r2g;
extern cvar_t r_powerupglow;
extern cvar_t v_powerupshell;
@ -3449,6 +3453,7 @@ static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newp
vec3_t move;
float a1, a2;
float maxdist = cl_lerp_maxdistance.value*cl_lerp_maxdistance.value;
/*
seeing as how dropped packets cannot be filled in due to the reliable networking stuff,
@ -3576,7 +3581,7 @@ static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newp
}
VectorSubtract(snew__origin, sold__origin, move);
if (DotProduct(move, move) > 200*200 || cos_theta < 0.707 || snew->modelindex != sold->modelindex || ((sold->effects ^ snew->effects) & EF_TELEPORT_BIT))
if (DotProduct(move, move) > maxdist || cos_theta < 0.707 || snew->modelindex != sold->modelindex || ((sold->effects ^ snew->effects) & EF_TELEPORT_BIT))
{
isnew = true; //disable lerping (and indirectly trails)
// VectorClear(move);
@ -4005,8 +4010,8 @@ void CL_LinkPacketEntities (void)
if (state->effects & EF_BRIGHTLIGHT)
{
radius = max(radius,r_dimlight_colour.vec4[3]);
VectorAdd(colour, r_dimlight_colour.vec4, colour);
radius = max(radius,r_brightlight_colour.vec4[3]);
VectorAdd(colour, r_brightlight_colour.vec4, colour);
}
if (state->effects & EF_DIMLIGHT)
{
@ -4015,24 +4020,18 @@ void CL_LinkPacketEntities (void)
}
if (state->effects & EF_BLUE)
{
radius = max(radius,200);
colour[0] += 0.5;
colour[1] += 0.5;
colour[2] += 3.0;
radius = max(radius,r_bluelight_colour.vec4[3]);
VectorAdd(colour, r_bluelight_colour.vec4, colour);
}
if (state->effects & EF_RED)
{
radius = max(radius,200);
colour[0] += 3.0;
colour[1] += 0.5;
colour[2] += 0.5;
radius = max(radius,r_redlight_colour.vec4[3]);
VectorAdd(colour, r_redlight_colour.vec4, colour);
}
if (state->effects & EF_GREEN)
{
radius = max(radius,200);
colour[0] += 0.5;
colour[1] += 3.0;
colour[2] += 0.5;
radius = max(radius,r_greenlight_colour.vec4[3]);
VectorAdd(colour, r_greenlight_colour.vec4, colour);
}
if (radius)
@ -5235,7 +5234,7 @@ void CL_LinkPlayers (void)
// spawn light flashes, even ones coming from invisible objects
if (r_powerupglow.value && !(r_powerupglow.value == 2 && j == cl.playerview[0].playernum)
&& (state->effects & (EF_BLUE|EF_RED|EF_BRIGHTLIGHT|EF_DIMLIGHT)))
&& (state->effects & (EF_BLUE|EF_RED|EF_GREEN|EF_BRIGHTLIGHT|EF_DIMLIGHT)))
{
vec3_t colour;
float radius;
@ -5246,31 +5245,28 @@ void CL_LinkPlayers (void)
if (state->effects & EF_BRIGHTLIGHT)
{
radius = max(radius,400);
colour[0] += 0.2;
colour[1] += 0.1;
colour[2] += 0.05;
radius = max(radius,r_brightlight_colour.vec4[3]);
VectorAdd(colour, r_brightlight_colour.vec4, colour);
}
if (state->effects & EF_DIMLIGHT)
{
radius = max(radius,200);
colour[0] += 2.0;
colour[1] += 1.0;
colour[2] += 0.5;
radius = max(radius,r_dimlight_colour.vec4[3]);
VectorAdd(colour, r_dimlight_colour.vec4, colour);
}
if (state->effects & EF_BLUE)
{
radius = max(radius,200);
colour[0] += 0.5;
colour[1] += 0.5;
colour[2] += 3.0;
radius = max(radius,r_bluelight_colour.vec4[3]);
VectorAdd(colour, r_bluelight_colour.vec4, colour);
}
if (state->effects & EF_RED)
{
radius = max(radius,200);
colour[0] += 5.0;
colour[1] += 0.5;
colour[2] += 0.5;
radius = max(radius,r_redlight_colour.vec4[3]);
VectorAdd(colour, r_redlight_colour.vec4, colour);
}
if (state->effects & EF_GREEN)
{
radius = max(radius,r_greenlight_colour.vec4[3]);
VectorAdd(colour, r_greenlight_colour.vec4, colour);
}
if (radius)

View file

@ -105,6 +105,7 @@ cvar_t m_forward = CVARF("m_forward","1", CVAR_ARCHIVE);
cvar_t m_side = CVARF("m_side","0.8", CVAR_ARCHIVE);
cvar_t cl_lerp_maxinterval = CVARD("cl_lerp_maxinterval", "0.3", "Maximum interval between keyframes, in seconds. Larger values can result in entities drifting very slowly when they move sporadically.");
cvar_t cl_lerp_maxdistance = CVARD("cl_lerp_maxdistance", "200", "Maximum distance that an entity may move between snapshots without being considered as having teleported.");
cvar_t cl_lerp_players = CVARD("cl_lerp_players", "0", "Set this to make other players smoother, though it may increase effective latency. Affects only QuakeWorld.");
cvar_t cl_predict_players = CVARD("cl_predict_players", "1", "Clear this cvar to see ents exactly how they are on the server.");
cvar_t cl_predict_players_frac = CVARD("cl_predict_players_frac", "0.9", "How much of other players to predict. Values less than 1 will help minimize overruns.");
@ -4805,6 +4806,7 @@ void CL_Init (void)
Cvar_Register (&rcon_address, cl_controlgroup);
Cvar_Register (&cl_lerp_maxinterval, cl_controlgroup);
Cvar_Register (&cl_lerp_maxdistance, cl_controlgroup);
Cvar_Register (&cl_lerp_players, cl_controlgroup);
Cvar_Register (&cl_predict_players, cl_predictiongroup);
Cvar_Register (&cl_predict_players_frac, cl_predictiongroup);

View file

@ -3908,6 +3908,35 @@ static void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caut
strcpy (cl.model_name[nummodels], str);
if (*str != '*' && strcmp(str, "null")) //not inline models!
CL_CheckOrEnqueDownloadFile(str, NULL, ((nummodels==1)?DLLF_REQUIRED|DLLF_ALLOWWEB:0));
//qw has a special network protocol for spikes.
if (!strcmp(cl.model_name[nummodels],"progs/spike.mdl"))
cl_spikeindex = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/player.mdl"))
cl_playerindex = nummodels;
#ifdef HAVE_LEGACY
if (*cl.model_name_vwep[0] && !strcmp(cl.model_name[nummodels],cl.model_name_vwep[0]) && cl_playerindex == -1)
cl_playerindex = nummodels;
#endif
if (!strcmp(cl.model_name[nummodels],"progs/h_player.mdl"))
cl_h_playerindex = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/flag.mdl"))
cl_flagindex = nummodels;
//rocket to grenade
if (!strcmp(cl.model_name[nummodels],"progs/missile.mdl"))
cl_rocketindex = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/grenade.mdl"))
cl_grenadeindex = nummodels;
//cl_gibfilter
if (!strcmp(cl.model_name[nummodels],"progs/gib1.mdl"))
cl_gib1index = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/gib2.mdl"))
cl_gib2index = nummodels;
if (!strcmp(cl.model_name[nummodels],"progs/gib3.mdl"))
cl_gib3index = nummodels;
Mod_TouchModel (str);
}
@ -4099,7 +4128,10 @@ static void CLNQ_ParseClientdata (void)
CL_SetStatInt(0, STAT_ITEMS, MSG_ReadLong());
pl->onground = (bits & SU_ONGROUND) != 0;
// cl.inwater = (bits & SU_INWATER) != 0;
if (bits & SU_INWATER)
pl->flags |= PF_INWATER; //mostly just means smartjump should be used.
else
pl->flags &= ~PF_INWATER;
if (cls.protocol_nq == CPNQ_DP5)
{
@ -5246,7 +5278,7 @@ void CL_NewTranslation (int slot)
s = Skin_FindName (player);
COM_StripExtension(s, s, MAX_QPATH);
if (player->qwskin && !stricmp(s, player->qwskin->name))
if (player->qwskin && stricmp(s, player->qwskin->name))
player->qwskin = NULL;
player->skinid = 0;
player->model = NULL;
@ -8243,9 +8275,9 @@ void CLNQ_ParseServerMessage (void)
// cl.players[i].rbottomcolor = (a&0xf0)>>4;
// sprintf(cl.players[i].team, "%2d", cl.players[i].rbottomcolor);
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "topcolor", va("%i", a&0x0f));
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "bottomcolor", va("%i", (a&0xf0)>>4));
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "team", va("%i", (a&0xf0)>>4));
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "topcolor", va("%i", (a&0xf0)>>4));
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "bottomcolor", va("%i", (a&0x0f)));
InfoBuf_SetValueForKey(&cl.players[i].userinfo, "team", va("%i", (a&0x0f)+1));
CL_ProcessUserInfo (i, &cl.players[i]);
// CLNQ_CheckPlayerIsSpectator(i);

View file

@ -776,6 +776,7 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st
{
vec3_t a;
int pmtype;
unsigned int flags = plstate->flags;
qboolean onground = plstate->onground;
qboolean jumpheld = plstate->jump_held;
vec3_t vel;
@ -827,6 +828,7 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st
plstate->jump_held = !!(state->u.q1.pmovetype&64);
}
plstate->pm_type = pmtype;
plstate->flags = flags & PF_INWATER;
plstate->viewangles[0] = SHORT2ANGLE(state->u.q1.vangle[0]);
plstate->viewangles[1] = SHORT2ANGLE(state->u.q1.vangle[1]);
@ -1383,7 +1385,19 @@ void CL_PredictMovePNum (int seat)
}
}
if (cls.protocol == CP_NETQUAKE && nopred)
{
pv->onground = to.state->onground;
if (to.state->flags & PF_INWATER)
{
pmove.watertype = FTECONTENTS_WATER; //don't really know.
pmove.waterlevel = 3; //pick one at random.
}
else
{
pmove.watertype = FTECONTENTS_EMPTY;
pmove.waterlevel = 0;
}
}
else
CL_CatagorizePosition(pv, to.state->origin);

View file

@ -222,7 +222,7 @@ qboolean scr_drawloading;
float scr_disabled_time;
cvar_t con_stayhidden = CVARFD("con_stayhidden", "1", 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 = CVARFD("show_fps", "0", CVAR_ARCHIVE, "Displays the current framerate on-screen.\n1: framerate average over a second.\n2: Slowest frame over the last second (the game will play like shit if this is significantly lower than the average).\n3: Shows the rate of the fastest frame (not very useful).\n4: Shows the current frame's timings (this depends upon timer precision).\n5: Display a graph of how long it took to render each frame, large spikes are BAD BAD BAD.\n6: Displays the standard deviation of the frame times, if its greater than 3 then something is probably badly made, or you've a virus scanner running...\n7: Framegraph, for use with slower frames.");
cvar_t show_fps = CVARFD("show_fps", "0", CVAR_ARCHIVE, "Displays the current framerate on-screen.\n0: Off.\n1: framerate average over a second.\n2: Show a frametimes graph (with additional timing info).\n-1: Normalized graph that focuses on the variation ignoring base times.");
cvar_t show_fps_x = CVAR("show_fps_x", "-1");
cvar_t show_fps_y = CVAR("show_fps_y", "-1");
cvar_t show_clock = CVAR("cl_clock", "0");
@ -1720,11 +1720,7 @@ void SCR_DrawFPS (void)
double t;
extern int fps_count;
static float lastfps;
static double deviationtimes[64];
static int deviationframe;
char str[80];
int sfps, frame;
qboolean usemsecs = false;
float frametime;
@ -1741,76 +1737,11 @@ void SCR_DrawFPS (void)
frametime = t - lastsystemtime;
lastsystemtime = t;
sfps = show_fps.ival;
if (sfps < 0)
{
sfps = -sfps;
usemsecs = true;
}
switch (sfps)
{
case 1:
default:
break;
case 2: // lowest FPS, highest MS encountered
if (lastfps > 1/frametime)
{
lastfps = 1/frametime;
fps_count = 0;
lastupdatetime = t;
}
break;
case 3: // highest FPS, lowest MS encountered
if (lastfps < 1/frametime)
{
lastfps = 1/frametime;
fps_count = 0;
lastupdatetime = t;
}
break;
case 4: // immediate FPS/MS
lastfps = 1/frametime;
lastupdatetime = t;
break;
case 5:
R_FrameTimeGraph(1000.0*2*frametime);
break;
case 7:
R_FrameTimeGraph(1000.0*1*frametime);
break;
case 6:
{
float mean, deviation;
deviationtimes[deviationframe++&63] = frametime*1000;
mean = 0;
for (frame = 0; frame < 64; frame++)
{
mean += deviationtimes[frame];
}
mean /= 64;
deviation = 0;
for (frame = 0; frame < 64; frame++)
{
deviation += (deviationtimes[frame] - mean)*(deviationtimes[frame] - mean);
}
deviation /= 64;
deviation = sqrt(deviation);
SCR_StringXY(va("%f deviation", deviation), show_fps_x.value, show_fps_y.value-8);
}
break;
case 8:
if (cls.timedemo)
Con_Printf("%f\n", frametime);
break;
}
if (usemsecs)
sprintf(str, "%4.1f MS", 1000.0/lastfps);
else
sprintf(str, "%3.1f FPS", lastfps);
if (show_fps.value < 0)
R_FrameTimeGraph(frametime, 0);
else if (show_fps.value > 1)
R_FrameTimeGraph(frametime, show_fps.value-1);
sprintf(str, "%3.1f FPS", lastfps);
SCR_StringXY(str, show_fps_x.value, show_fps_y.value);
}

View file

@ -281,13 +281,16 @@ sfx_t *cl_sfx_r_exp3;
cvar_t cl_expsprite = CVARFD("cl_expsprite", "1", CVAR_ARCHIVE, "Display a central sprite in explosion effects. QuakeWorld typically does so, NQ mods should not (which is problematic when played with the qw protocol).");
cvar_t r_explosionlight = CVARFC("r_explosionlight", "1", CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback);
static cvar_t r_explosionlight_colour = CVARF("r_explosionlight_colour", "4.0 2.0 0.5", CVAR_ARCHIVE);
static cvar_t r_explosionlight_fade = CVARF("r_explosionlight_fade", "0.784 0.92 0.48", CVAR_ARCHIVE);
cvar_t r_dimlight_colour = CVARF("r_dimlight_colour", "2.0 1.0 0.5 200", CVAR_ARCHIVE);
cvar_t r_brightlight_colour = CVARF("r_brightlight_colour", "2.0 1.0 0.5 400", CVAR_ARCHIVE);
cvar_t r_rocketlight_colour = CVARF("r_rocketlight_colour", "2.0 1.0 0.25 200", CVAR_ARCHIVE);
cvar_t r_muzzleflash_colour = CVARF("r_muzzleflash_colour", "1.5 1.3 1.0 200", CVAR_ARCHIVE);
cvar_t r_muzzleflash_fade = CVARF("r_muzzleflash_fade", "1.5 0.75 0.375 1000", CVAR_ARCHIVE);
static cvar_t r_explosionlight_colour = CVARFD("r_explosionlight_colour", "4.0 2.0 0.5", CVAR_ARCHIVE, "This controls the initial RGB values of EF_EXPLOSION effects.");
static cvar_t r_explosionlight_fade = CVARFD("r_explosionlight_fade", "0.784 0.92 0.48", CVAR_ARCHIVE, "This controls the per-second RGB decay values of EF_EXPLOSION effects.");
cvar_t r_dimlight_colour = CVARFD("r_dimlight_colour", "2.0 1.0 0.5 200", CVAR_ARCHIVE, "The red, green, blue, radius values for EF_DIMLIGHT effects (used for quad+pent in vanilla quake).");
cvar_t r_brightlight_colour = CVARFD("r_brightlight_colour", "2.0 1.0 0.5 400", CVAR_ARCHIVE, "The red, green, blue, radius values for EF_BRIGHTLIGHT effects (unused in vanilla quake).");
cvar_t r_redlight_colour = CVARFD("r_redlight_colour", "3.0 0.5 0.5 200", CVAR_ARCHIVE, "The red, green, blue, radius values for EF_RED effects (typically used for pentagram in quakeworld).");
cvar_t r_greenlight_colour = CVARFD("r_greenlight_colour", "0.5 3.0 0.5 200", CVAR_ARCHIVE, "The red, green, blue, radius values for EF_GREEN effects (rarely used).");
cvar_t r_bluelight_colour = CVARFD("r_bluelight_colour", "0.5 0.5 3.0 200", CVAR_ARCHIVE, "The red, green, blue, radius values for EF_BLUE effects (typically used for quad-damage in quakeworld)");
cvar_t r_rocketlight_colour = CVARFD("r_rocketlight_colour", "2.0 1.0 0.25 200", CVAR_ARCHIVE, "This controls the RGB+radius values of MF_ROCKET effects.");
cvar_t r_muzzleflash_colour = CVARFD("r_muzzleflash_colour", "1.5 1.3 1.0 200", CVAR_ARCHIVE, "This controls the initial RGB+radius of EF_MUZZLEFLASH/svc_muzzleflash effects.");
cvar_t r_muzzleflash_fade = CVARFD("r_muzzleflash_fade", "1.5 0.75 0.375 1000", CVAR_ARCHIVE, "This controls the per-second RGB+radius decay of EF_MUZZLEFLASH/svc_muzzleflash effects.");
cvar_t cl_truelightning = CVARF("cl_truelightning", "0", CVAR_SEMICHEAT);
static cvar_t cl_beam_trace = CVAR("cl_beam_trace", "0");
static cvar_t cl_legacystains = CVARD("cl_legacystains", "1", "WARNING: this cvar will default to 0 and later removed at some point"); //FIXME: do as the description says!
@ -424,6 +427,9 @@ void CL_InitTEnts (void)
Cvar_Register (&r_muzzleflash_colour, "Temporary entity control");
Cvar_Register (&r_muzzleflash_fade, "Temporary entity control");
Cvar_Register (&r_dimlight_colour, "Temporary entity control");
Cvar_Register (&r_redlight_colour, "Temporary entity control");
Cvar_Register (&r_greenlight_colour, "Temporary entity control");
Cvar_Register (&r_bluelight_colour, "Temporary entity control");
Cvar_Register (&r_brightlight_colour, "Temporary entity control");
Cvar_Register (&r_rocketlight_colour, "Temporary entity control");
Cvar_Register (&cl_legacystains, "Temporary entity control");

View file

@ -2,6 +2,10 @@
#include "shader.h"
#include "glquake.h" //we need some of the gl format enums
#ifdef __GNUC__
#pragma
#endif
#ifndef HAVE_CLIENT
//#define Con_Printf(f, ...)
//hope you're on a littleendian machine
@ -2449,6 +2453,7 @@ qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression
int ic;
qboolean byteswap;
switch(fmt)
{
case PTI_RGB8: //yay! nothing to do.

View file

@ -216,8 +216,14 @@ static struct
{
char *url;
char *prefix;
qboolean trustworthy; //trusted
char received; //says if we got a response yet or not
enum
{
SRCSTAT_UNKNOWN, //we don't know whether the user wants to allow or block this source.
SRCSTAT_DISABLED, //do NOT query this source
SRCSTAT_FAILED, //tried but failed. FIXME: add some reasons.
SRCSTAT_PENDING, //waiting for response (or queued). don't show package list yet.
SRCSTAT_OBTAINED, //we got a response.
} status;
qboolean save; //written into our local file
struct dl_download *curdl; //the download context
} downloadablelist[32];
@ -832,7 +838,7 @@ static qboolean PM_CheckFile(const char *filename, enum fs_relative base)
return false;
}
static void PM_AddSubList(const char *url, const char *prefix, qboolean save, qboolean trustworthy)
static void PM_AddSubList(const char *url, const char *prefix, qboolean save, qboolean enabled)
{
int i;
if (!*url)
@ -849,10 +855,10 @@ static void PM_AddSubList(const char *url, const char *prefix, qboolean save, qb
}
if (i == numdownloadablelists && i < countof(downloadablelist))
{
if (!strncmp(url, "https:", 6))
downloadablelist[i].trustworthy = trustworthy;
if (enabled)
downloadablelist[i].status = SRCSTAT_PENDING;
else
downloadablelist[i].trustworthy = false; //if its not a secure url, never consider it as trustworthy
downloadablelist[i].status = SRCSTAT_DISABLED;
downloadablelist[i].save = save;
downloadablelist[i].url = BZ_Malloc(strlen(url)+1);
@ -974,6 +980,7 @@ static qboolean PM_ParsePackageList(const char *f, int parseflags, const char *u
{
char *subprefix;
char url[MAX_OSPATH];
char enablement[MAX_OSPATH];
tokstart = COM_StringParse (tokstart, url, sizeof(url), false, false);
tokstart = COM_StringParse (tokstart, com_token, sizeof(com_token), false, false);
if (*prefix)
@ -981,7 +988,11 @@ static qboolean PM_ParsePackageList(const char *f, int parseflags, const char *u
else
subprefix = com_token;
PM_AddSubList(url, subprefix, (parseflags & DPF_ENABLED)?true:false, (parseflags&DPF_TRUSTED));
tokstart = COM_StringParse (tokstart, enablement, sizeof(enablement), false, false);
if (!Q_strcasecmp(enablement, "enabled") && (parseflags & DPF_ENABLED))
PM_AddSubList(url, subprefix, (parseflags & DPF_ENABLED)?true:false, true);
else
PM_AddSubList(url, subprefix, (parseflags & DPF_ENABLED)?true:false, false);
continue;
}
if (!strcmp(com_token, "set"))
@ -1594,7 +1605,7 @@ void PM_Shutdown(qboolean soft)
downloadablelist[numdownloadablelists].curdl = NULL;
}
#endif
downloadablelist[numdownloadablelists].received = 0;
downloadablelist[numdownloadablelists].status = SRCSTAT_UNKNOWN;
Z_Free(downloadablelist[numdownloadablelists].url);
downloadablelist[numdownloadablelists].url = NULL;
Z_Free(downloadablelist[numdownloadablelists].prefix);
@ -2110,12 +2121,12 @@ static void PM_ListDownloaded(struct dl_download *dl)
if (f)
{
downloadablelist[listidx].received = 1;
downloadablelist[listidx].status = SRCSTAT_OBTAINED;
PM_ParsePackageList(f, 0, dl->url, downloadablelist[listidx].prefix);
BZ_Free(f);
}
else
downloadablelist[listidx].received = -1;
downloadablelist[listidx].status = SRCSTAT_FAILED;
if (!doautoupdate && !domanifestinstall)
return; //don't spam this.
@ -2123,7 +2134,7 @@ static void PM_ListDownloaded(struct dl_download *dl)
//check if we're still waiting
for (listidx = 0; listidx < numdownloadablelists; listidx++)
{
if (!downloadablelist[listidx].received)
if (downloadablelist[listidx].status == SRCSTAT_PENDING)
break;
}
/*
@ -2189,8 +2200,8 @@ static void PM_AllowPackageListQuery_Callback(void *ctx, promptbutton_t opt)
//something changed, let it download now.
for (i = 0; i < numdownloadablelists; i++)
{
if (downloadablelist[i].received == -2)
downloadablelist[i].received = 0;
if (downloadablelist[i].status == SRCSTAT_UNKNOWN)
downloadablelist[i].status = SRCSTAT_PENDING;
}
PM_UpdatePackageList(false, 0);
}
@ -2207,7 +2218,7 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
//make sure our sources are okay.
if (*pkg_downloads_url.string)
PM_AddSubList(pkg_downloads_url.string, "", false, true);
PM_AddSubList(pkg_downloads_url.string, "", false, pkg_autoupdate.ival>=0);
#ifndef WEBCLIENT
for (i = 0; i < numdownloadablelists; i++)
@ -2230,7 +2241,7 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
//kick off the initial tier of list-downloads.
for (i = 0; i < numdownloadablelists; i++)
{
if (downloadablelist[i].received && allowphonehome>=0)
if (downloadablelist[i].status != SRCSTAT_PENDING && allowphonehome>=0)
continue;
autoupdate = false;
if (downloadablelist[i].curdl)
@ -2238,7 +2249,7 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
if (allowphonehome<=0)
{
downloadablelist[i].received = -2;
downloadablelist[i].status = SRCSTAT_UNKNOWN;
continue;
}
downloadablelist[i].curdl = HTTP_CL_Get(va("%s%s"DOWNLOADABLESARGS, downloadablelist[i].url, strchr(downloadablelist[i].url,'?')?"&":"?"), NULL, PM_ListDownloaded);
@ -2253,7 +2264,7 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
else
{
Con_Printf("Could not contact updates server - %s\n", downloadablelist[i].url);
downloadablelist[i].received = -1;
downloadablelist[i].status = SRCSTAT_FAILED;
}
}
@ -2322,7 +2333,12 @@ static void PM_WriteInstalledPackages(void)
{
if (downloadablelist[i].save)
{
s = va("sublist \"%s\" \"%s\"\n", downloadablelist[i].url, downloadablelist[i].prefix);
if (downloadablelist[i].status == SRCSTAT_DISABLED)
s = va("sublist \"%s\" \"%s\" \"disabled\"\n", downloadablelist[i].url, downloadablelist[i].prefix);
else if (downloadablelist[i].status != SRCSTAT_UNKNOWN)
s = va("sublist \"%s\" \"%s\" \"enabled\"\n", downloadablelist[i].url, downloadablelist[i].prefix);
else
s = va("sublist \"%s\" \"%s\"\n", downloadablelist[i].url, downloadablelist[i].prefix);
VFS_WRITE(f, s, strlen(s));
}
}
@ -3835,7 +3851,7 @@ void PM_Command_f(void)
{ //flush package cache, make a new request even if we already got a response from the server.
int i;
for (i = 0; i < numdownloadablelists; i++)
downloadablelist[i].received = 0;
downloadablelist[i].status = SRCSTAT_PENDING;
if (!allowphonehome)
allowphonehome = -1; //trigger a prompt, instead of ignoring it.
PM_UpdatePackageList(false, 0);
@ -4506,6 +4522,50 @@ static qboolean MD_Key (struct menucustom_s *c, struct emenu_s *m, int key, unsi
}
#ifdef WEBCLIENT
static void MD_Source_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m)
{
char *text;
switch(downloadablelist[c->dint].status)
{
case SRCSTAT_OBTAINED:
case SRCSTAT_PENDING:
Draw_FunStringWidth (x, y, "^&02 ", 48, 2, false); //green
break;
case SRCSTAT_FAILED:
case SRCSTAT_UNKNOWN:
Draw_FunStringWidth (x, y, "^&0E ", 48, 2, false); //yellow
break;
case SRCSTAT_DISABLED:
Draw_FunStringWidth (x, y, "^&04 ", 48, 2, false); //red
break;
}
text = va("Source %s", downloadablelist[c->dint].url);
Draw_FunString (x+48, y, text);
}
static qboolean MD_Source_Key (struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode)
{
if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1)
{
switch(downloadablelist[c->dint].status)
{
case SRCSTAT_OBTAINED:
case SRCSTAT_PENDING:
case SRCSTAT_FAILED:
case SRCSTAT_UNKNOWN:
downloadablelist[c->dint].status = SRCSTAT_DISABLED;
break;
case SRCSTAT_DISABLED:
downloadablelist[c->dint].status = SRCSTAT_PENDING;
break;
}
downloadablelist[c->dint].save = true;
PM_WriteInstalledPackages();
PM_UpdatePackageList(true, 2);
}
return false;
}
static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m)
{
char *settings[] =
@ -4794,7 +4854,7 @@ static void MD_Download_UpdateStatus(struct emenu_s *m)
{
for (i = 0; i < numdownloadablelists; i++)
{
if (!downloadablelist[i].received)
if (downloadablelist[i].status == SRCSTAT_PENDING)
{
Draw_FunStringWidth(0, vid.height - 8, "Querying for package list", vid.width, 2, false);
return;
@ -4804,6 +4864,18 @@ static void MD_Download_UpdateStatus(struct emenu_s *m)
info->populated = true;
MC_AddFrameStart(m, 48);
y = 48;
#ifdef WEBCLIENT
for (i = 0; i < numdownloadablelists; i++)
{
c = MC_AddCustom(m, 0, y, p, i, NULL);
c->draw = MD_Source_Draw;
c->key = MD_Source_Key;
c->common.width = 320-48-16;
c->common.height = 8;
y += 8;
}
y+=4; //small gap
#endif
b = MC_AddCommand(m, 48, 320-16, y, info->applymessage, MD_ApplyDownloads);
b->rightalign = false;
b->common.tooltip = "Enable/Disable/Download/Delete packages to match any changes made (you will be prompted with a list of the changes that will be made).";

View file

@ -688,6 +688,9 @@ void CD_f (void)
if (Q_strcasecmp(command, "eject") == 0)
{
if (Cmd_IsInsecure())
return;
if (cdplayingtrack || cdpausedtrack)
CDAudio_Stop();
CDAudio_Eject();

View file

@ -1313,16 +1313,10 @@ void M_Menu_FPS_f (void)
{
"Disabled",
"Average FPS",
"Worst FPS",
"Best FPS",
"Immediate FPS",
"Average MSEC",
"Worst MSEC",
"Best MSEC",
"Immediate MSEC",
"Timing Graph",
NULL
};
static const char *fpsvalues[] = {"0", "1", "2", "3", "4", "-1", "-2", "-3", "-4", NULL};
static const char *fpsvalues[] = {"0", "1", "2", NULL};
static const char *entlerpopts[] =
{
"Enabled (always)",

View file

@ -3387,6 +3387,16 @@ static void QCBUILTIN PF_ReadFloat(pubprogfuncs_t *prinst, struct globalvars_s *
}
G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
}
static void QCBUILTIN PF_ReadDouble(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (!csqc_mayread)
{
CSQC_Abort("PF_ReadDouble is not valid at this time");
G_FLOAT(OFS_RETURN) = -1;
return;
}
G_DOUBLE(OFS_RETURN) = MSG_ReadDouble();
}
static void QCBUILTIN PF_ReadInt(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (!csqc_mayread)
@ -3397,6 +3407,16 @@ static void QCBUILTIN PF_ReadInt(pubprogfuncs_t *prinst, struct globalvars_s *pr
}
G_INT(OFS_RETURN) = MSG_ReadLong();
}
static void QCBUILTIN PF_ReadInt64(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (!csqc_mayread)
{
CSQC_Abort("PF_ReadInt is not valid at this time");
G_INT(OFS_RETURN) = -1;
return;
}
G_INT64(OFS_RETURN) = MSG_ReadInt64();
}
static void QCBUILTIN PF_ReadString(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -3681,11 +3701,31 @@ static void QCBUILTIN PF_cs_sendevent (pubprogfuncs_t *prinst, struct globalvars
MSG_WriteByte(&cls.netchan.message, ev_float);
MSG_WriteFloat(&cls.netchan.message, G_FLOAT(OFS_PARM2+i*3));
}
else if (argtypes[i] == 'F')
{
MSG_WriteByte(&cls.netchan.message, ev_double);
MSG_WriteDouble(&cls.netchan.message, G_DOUBLE(OFS_PARM2+i*3));
}
else if (argtypes[i] == 'i')
{
MSG_WriteByte(&cls.netchan.message, ev_integer);
MSG_WriteLong(&cls.netchan.message, G_INT(OFS_PARM2+i*3));
}
else if (argtypes[i] == 'u')
{
MSG_WriteByte(&cls.netchan.message, ev_uint);
MSG_WriteLong(&cls.netchan.message, G_UINT(OFS_PARM2+i*3));
}
else if (argtypes[i] == 'I')
{
MSG_WriteByte(&cls.netchan.message, ev_int64);
MSG_WriteInt64(&cls.netchan.message, G_INT64(OFS_PARM2+i*3));
}
else if (argtypes[i] == 'U')
{
MSG_WriteByte(&cls.netchan.message, ev_uint64);
MSG_WriteInt64(&cls.netchan.message, G_UINT64(OFS_PARM2+i*3));
}
else if (argtypes[i] == 'v')
{
MSG_WriteByte(&cls.netchan.message, ev_vector);
@ -6936,8 +6976,10 @@ static struct {
{"readangle", PF_ReadAngle, 365}, // #365 float() readangle (EXT_CSQC)
{"readstring", PF_ReadString, 366}, // #366 string() readstring (EXT_CSQC)
{"readfloat", PF_ReadFloat, 367}, // #367 string() readfloat (EXT_CSQC)
{"readint", PF_ReadInt, 0}, // #0 string() readint
{"readfloat", PF_ReadFloat, 367}, // #367 float() readfloat (EXT_CSQC)
{"readdouble", PF_ReadDouble, 0}, // #367 __double() readdouble (EXT_CSQC)
{"readint", PF_ReadInt, 0}, // #0 int() readint
{"readint64", PF_ReadInt64, 0}, // #0 __int64() readint64
{"readentitynum", PF_ReadEntityNum, 368}, // #368 float() readentitynum (EXT_CSQC)
// {"readserverentitystate", PF_ReadServerEntityState, 369}, // #369 void(float flags, float simtime) readserverentitystate (EXT_CSQC_1)

View file

@ -397,7 +397,7 @@ void COM_AssertMainThread(const char *msg);
#define COM_HasWork() false
#define COM_DoWork(t,l) false
#define COM_AssertMainThread(msg)
#define COM_MainThreadWork()
#define COM_MainThreadWork() while(0)
#define COM_MainThreadFlush()
#define COM_DestroyWorkerThread()
#define COM_WorkerAbort(m)

View file

@ -30,6 +30,7 @@ int r_regsequence;
int rspeeds[RSPEED_MAX];
int rquant[RQUANT_MAX];
static void R_RegisterBuiltinRenderers(void);
void R_InitParticleTexture (void);
void R_RestartRenderer (rendererstate_t *newr);
static void R_UpdateRendererOpts(void);
@ -1080,6 +1081,9 @@ void Renderer_Init(void)
P_InitParticleSystem();
R_InitTextures();
R_RegisterBuiltinRenderers();
}
qboolean Renderer_Started(void)
@ -1128,9 +1132,49 @@ qboolean (*SCR_UpdateScreen) (void);
r_qrenderer_t qrenderer;
char *q_renderername = "Non-Selected renderer";
static struct
{
void *module;
rendererinfo_t *ri;
} rendererinfo[16];
qboolean R_RegisterRenderer(void *module, rendererinfo_t *ri)
{
size_t i;
for (i = 0; i < countof(rendererinfo); i++)
{ //already registered
if (rendererinfo[i].ri == ri)
return true;
}
for (i = 0; i < countof(rendererinfo); i++)
{ //register it in the first empty slot
if (!rendererinfo[i].ri)
{
rendererinfo[i].module = module;
rendererinfo[i].ri = ri;
return true;
}
}
Sys_Printf("unable to register renderer %s\n", ri->description);
return false;
}
static plugvrfuncs_t *vrfuncs;
qboolean R_RegisterVRDriver(void *module, plugvrfuncs_t *vr)
{
if (!vrfuncs)
{
vrfuncs = vr;
return true;
}
Sys_Printf("unable to register renderer %s\n", vr->description);
return false;
}
rendererinfo_t dedicatedrendererinfo = {
static rendererinfo_t dedicatedrendererinfo = {
//ALL builds need a 'none' renderer, as 0.
"No renderer",
{
@ -1188,139 +1232,105 @@ rendererinfo_t dedicatedrendererinfo = {
""
};
#ifdef GLQUAKE
extern rendererinfo_t openglrendererinfo;
#ifdef USE_EGL
extern rendererinfo_t eglrendererinfo;
#endif
extern rendererinfo_t rpirendererinfo;
#ifdef WAYLANDQUAKE
extern rendererinfo_t rendererinfo_wayland_gl;
#endif
rendererinfo_t fbdevrendererinfo;
#endif
#ifdef D3D8QUAKE
extern rendererinfo_t d3d8rendererinfo;
#endif
#ifdef D3D9QUAKE
extern rendererinfo_t d3d9rendererinfo;
#endif
#ifdef D3D11QUAKE
extern rendererinfo_t d3d11rendererinfo;
#endif
#ifdef SWQUAKE
extern rendererinfo_t swrendererinfo;
#endif
#ifdef VKQUAKE
extern rendererinfo_t vkrendererinfo;
//rendererinfo_t headlessvkrendererinfo;
#if defined(_WIN32) && defined(GLQUAKE) && !defined(FTE_SDL)
extern rendererinfo_t nvvkrendererinfo;
#endif
#ifdef WAYLANDQUAKE
extern rendererinfo_t rendererinfo_wayland_vk;
#endif
#endif
#ifdef HEADLESSQUAKE
extern rendererinfo_t headlessrenderer;
#endif
#if defined(GLQUAKE) && defined(USE_EGL)
extern rendererinfo_t rendererinfo_headless_egl;
#endif
static struct
static void R_RegisterBuiltinRenderers(void)
{
void *module;
rendererinfo_t *ri;
} rendererinfo[16] =
{
#ifdef GLQUAKE
#ifdef FTE_RPI
{NULL, &rpirendererinfo},
#endif
{NULL, &openglrendererinfo},
#ifdef USE_EGL
{NULL, &eglrendererinfo},
#endif
#endif
#ifdef D3D9QUAKE
{NULL, &d3d9rendererinfo},
#endif
#ifdef VKQUAKE
{NULL, &vkrendererinfo},
#if defined(_WIN32) && defined(GLQUAKE) && !defined(FTE_SDL)
{NULL, &nvvkrendererinfo},
#endif
#endif
#ifdef D3D11QUAKE
{NULL, &d3d11rendererinfo},
#endif
#ifdef SWQUAKE
{NULL, &swrendererinfo},
#endif
#ifdef D3D8QUAKE
{NULL, &d3d8rendererinfo},
#endif
#ifdef WAYLANDQUAKE
#ifdef GLQUAKE
{NULL, &rendererinfo_wayland_gl},
#endif
#ifdef VKQUAKE
{NULL, &rendererinfo_wayland_vk},
#endif
#endif
#ifdef GLQUAKE
{NULL, &fbdevrendererinfo}, //direct stuff that doesn't interact well with the system should always be low priority
#endif
#ifndef NPQTV
{NULL, &dedicatedrendererinfo},
#endif
#ifdef HEADLESSQUAKE
{NULL, &headlessrenderer},
#ifdef VKQUAKE
//{NULL, &headlessvkrendererinfo},
#endif
#endif
#if defined(GLQUAKE) && defined(USE_EGL)
{NULL, &rendererinfo_headless_egl},
#endif
};
qboolean R_RegisterRenderer(void *module, rendererinfo_t *ri)
{
size_t i;
for (i = 0; i < countof(rendererinfo); i++)
{ //already registered
if (rendererinfo[i].ri == ri)
return true;
}
for (i = 0; i < countof(rendererinfo); i++)
{ //register it in the first empty slot
if (!rendererinfo[i].ri)
{
rendererinfo[i].module = module;
rendererinfo[i].ri = ri;
return true;
}
}
Sys_Printf("unable to register renderer %s\n", ri->description);
return false;
}
static plugvrfuncs_t *vrfuncs;
qboolean R_RegisterVRDriver(void *module, plugvrfuncs_t *vr)
{
if (!vrfuncs)
{
vrfuncs = vr;
return true;
extern rendererinfo_t openglrendererinfo;
#ifdef FTE_RPI
{
extern rendererinfo_t rpirendererinfo;
R_RegisterRenderer(NULL, &rpirendererinfo);
}
#endif
R_RegisterRenderer(NULL, &openglrendererinfo);
#ifdef USE_EGL
{
extern rendererinfo_t eglrendererinfo;
R_RegisterRenderer(NULL, &eglrendererinfo);
}
#endif
}
#endif
Sys_Printf("unable to register renderer %s\n", vr->description);
return false;
#ifdef D3D9QUAKE
{
extern rendererinfo_t d3d9rendererinfo;
R_RegisterRenderer(NULL, &d3d9rendererinfo);
}
#endif
#ifdef VKQUAKE
{
extern rendererinfo_t vkrendererinfo;
R_RegisterRenderer(NULL, &vkrendererinfo);
#if defined(_WIN32) && defined(GLQUAKE) && !defined(FTE_SDL)
{
extern rendererinfo_t nvvkrendererinfo;
R_RegisterRenderer(NULL, &nvvkrendererinfo);
}
#endif
}
#endif
#ifdef D3D11QUAKE
{
extern rendererinfo_t d3d11rendererinfo;
R_RegisterRenderer(NULL, &d3d11rendererinfo);
}
#endif
#ifdef SWQUAKE
{
extern rendererinfo_t swrendererinfo;
R_RegisterRenderer(NULL, &swrendererinfo);
}
#endif
#ifdef D3D8QUAKE
{
extern rendererinfo_t d3d8rendererinfo;
R_RegisterRenderer(NULL, &d3d8rendererinfo);
}
#endif
#ifdef WAYLANDQUAKE
#ifdef GLQUAKE
{
extern rendererinfo_t rendererinfo_wayland_gl;
R_RegisterRenderer(NULL, &rendererinfo_wayland_gl);
}
#endif
#ifdef VKQUAKE
{
extern rendererinfo_t rendererinfo_wayland_vk;
R_RegisterRenderer(NULL, &rendererinfo_wayland_vk);
}
#endif
#endif
#if defined(GLQUAKE) && defined(USE_FBDEV)
{
extern rendererinfo_t fbdevrendererinfo;
R_RegisterRenderer(NULL, &fbdevrendererinfo); //direct stuff that doesn't interact well with the system should always be low priority
}
#endif
#ifndef NPQTV
R_RegisterRenderer(NULL, &dedicatedrendererinfo);
#endif
#ifdef HEADLESSQUAKE
{
extern rendererinfo_t headlessrenderer;
R_RegisterRenderer(NULL, &headlessrenderer);
#ifdef VKQUAKE
//R_RegisterRenderer(NULL, &headlessvkrendererinfo);
#endif
}
#endif
#if defined(GLQUAKE) && defined(USE_EGL)
{
extern rendererinfo_t rendererinfo_headless_egl;
R_RegisterRenderer(NULL, &rendererinfo_headless_egl);
}
#endif
}
void R_SetRenderer(rendererinfo_t *ri)
{
currentrendererstate.renderer = ri;
@ -2282,7 +2292,7 @@ void R_RestartRenderer (rendererstate_t *newr)
//if we ended up resorting to our last choice (dedicated) then print some informative message about it
//fixme: on unixy systems, we should make sure we're actually printing to something (ie: that we're not running via some x11 shortcut with our stdout redirected to /dev/nul
if (!failed && newr->renderer == &dedicatedrendererinfo)
if (!failed && (!newr->renderer || newr->renderer->rtype == QR_NONE))
{
Con_Printf(CON_ERROR "Video mode switch failed. Console forced.\n\nPlease change the following vars to something useable, and then use the setrenderer command.\n");
Con_Printf("%s: %s\n", vid_width.name, vid_width.string);

View file

@ -3020,7 +3020,7 @@ void Sbar_IntermissionNumber (float x, float y, int num, int digits, int color,
else
frame = *ptr -'0';
R2D_ScalePicAtlas (x,y, 16, 24, sb_nums[color][frame]);
R2D_ScalePicAtlas (x,y, 24, 24, sb_nums[color][frame]);
x += 24;
ptr++;
}
@ -3800,17 +3800,17 @@ void Sbar_CoopIntermission (playerview_t *pv)
dig = cl.completed_time/60;
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 64, dig, 4, 0, false);
num = cl.completed_time - dig*60;
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_colon);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 254,(sbar_rect.height - 200)/2 + 64, 16, 26, sb_nums[0][num/10]);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 278,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 64, 24, 24, sb_colon);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 254,(sbar_rect.height - 200)/2 + 64, 24, 24, sb_nums[0][num/10]);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 278,(sbar_rect.height - 200)/2 + 64, 24, 24, sb_nums[0][num%10]);
//it is assumed that secrits/monsters are going to be constant for any player...
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 104, pv->stats[STAT_SECRETS], 4, 0, false);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230, (sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230, (sbar_rect.height - 200)/2 + 104, 24, 24, sb_slash);
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 104, pv->stats[STAT_TOTALSECRETS], 4, 0, true);
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 144, pv->stats[STAT_MONSTERS], 4, 0, false);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash);
R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 144, 24, 24, sb_slash);
Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 144, pv->stats[STAT_TOTALMONSTERS], 4, 0, true);
}
/*

View file

@ -387,4 +387,4 @@ fte_inline float M_LinearToSRGB(float x, float mag)
void R_NetgraphInit(void);
void R_NetGraph (void);
void R_FrameTimeGraph (float frametime);
void R_FrameTimeGraph (float frametime, float scale);

View file

@ -157,7 +157,7 @@ static cvar_t v_depthsortentities = CVARAD("v_depthsortentities", "0", "v_reord
#ifdef QUAKESTATS
static cvar_t scr_autoid = CVARD("scr_autoid", "1", "Display nametags above all players while spectating.");
static cvar_t scr_autoid_team = CVARD("scr_autoid_team", "2", "Display nametags above team members. 0: off. 1: display with half-alpha if occluded. 2: hide when occluded.");
static cvar_t scr_autoid_team = CVARD("scr_autoid_team", "0", "Display nametags above team members. 0: off. 1: display with half-alpha if occluded. 2: hide when occluded.");
static cvar_t scr_autoid_health = CVARD("scr_autoid_health", "1", "Display health as part of nametags (when known).");
static cvar_t scr_autoid_armour = CVARD("scr_autoid_armor", "1", "Display armour as part of nametags (when known).");
static cvar_t scr_autoid_weapon = CVARD("scr_autoid_weapon", "1", "Display the player's best weapon as part of their nametag (when known).");

View file

@ -746,6 +746,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define fte_alignof(type) sizeof(qintptr_t)
#endif
//safeswitch(foo){safedefault: break;}
//switch, but errors for any omitted enum values despite the presence of a default case.
//(gcc will generally give warnings without the default, but sometimes you don't have control over the source of your enumeration values)
#if (__GNUC__ >= 4)
#define safeswitch \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic error \"-Wswitch-enum\"") \
_Pragma("GCC diagnostic error \"-Wswitch-default\"") \
switch
#define safedefault _Pragma("GCC diagnostic pop") default
#else
#define safeswitch switch
#define safedefault default
#endif
//fte_inline must only be used in headers, and requires one and ONLY one fte_inlinebody elsewhere.
//fte_inlinebody must be used on a prototype OUTSIDE of a header.
//fte_inlinestatic must not be used inside any headers at all.

View file

@ -887,7 +887,7 @@ void MSG_WriteByte (sizebuf_t *sb, int c)
#endif
buf = (qbyte*)SZ_GetSpace (sb, 1);
buf[0] = c;
buf[0] = c&0xff;
}
void MSG_WriteShort (sizebuf_t *sb, int c)
@ -901,7 +901,7 @@ void MSG_WriteShort (sizebuf_t *sb, int c)
buf = (qbyte*)SZ_GetSpace (sb, 2);
buf[0] = c&0xff;
buf[1] = c>>8;
buf[1] = (c>>8)&0xff;
}
void MSG_WriteLong (sizebuf_t *sb, int c)
@ -912,7 +912,21 @@ void MSG_WriteLong (sizebuf_t *sb, int c)
buf[0] = c&0xff;
buf[1] = (c>>8)&0xff;
buf[2] = (c>>16)&0xff;
buf[3] = c>>24;
buf[3] = (c>>24)&0xff;
}
void MSG_WriteInt64 (sizebuf_t *sb, qint64_t c)
{
qbyte *buf;
buf = (qbyte*)SZ_GetSpace (sb, 8);
buf[0] = c&0xff;
buf[1] = (c>>8)&0xff;
buf[2] = (c>>16)&0xff;
buf[3] = (c>>24)&0xff;
buf[4] = (c>>32)&0xff;
buf[5] = (c>>40)&0xff;
buf[6] = (c>>48)&0xff;
buf[7] = (c>>52)&0xff;
}
void MSG_WriteFloat (sizebuf_t *sb, float f)
@ -929,6 +943,17 @@ void MSG_WriteFloat (sizebuf_t *sb, float f)
SZ_Write (sb, &dat.l, 4);
}
void MSG_WriteDouble (sizebuf_t *sb, double f)
{
union
{
double f;
qint64_t l;
} dat;
dat.f = f;
MSG_WriteInt64(sb, dat.l);
}
void MSG_WriteString (sizebuf_t *sb, const char *s)
{
@ -1586,6 +1611,36 @@ int MSG_ReadLong (void)
return c;
}
qint64_t MSG_ReadInt64 (void)
{
qint64_t c;
if (net_message.packing!=SZ_RAWBYTES)
{
c = (unsigned int)MSG_ReadBits(32)
| ((qint64_t)(unsigned int)MSG_ReadBits(32)<<32);
return c;
}
if (msg_readcount+4 > net_message.cursize)
{
msg_badread = true;
return -1;
}
c = (net_message.data[msg_readcount+0]<<0)
| (net_message.data[msg_readcount+1]<<8)
| (net_message.data[msg_readcount+2]<<16)
| (net_message.data[msg_readcount+3]<<24)
| ((qint64_t)net_message.data[msg_readcount+5]<<32)
| ((qint64_t)net_message.data[msg_readcount+6]<<40)
| ((qint64_t)net_message.data[msg_readcount+7]<<48)
| ((qint64_t)net_message.data[msg_readcount+8]<<52);
msg_readcount += 8;
return c;
}
float MSG_ReadFloat (void)
{
@ -1614,10 +1669,21 @@ float MSG_ReadFloat (void)
dat.b[3] = net_message.data[msg_readcount+3];
msg_readcount += 4;
dat.l = LittleLong (dat.l);
if (bigendian)
dat.l = LittleLong (dat.l);
return dat.f;
}
double MSG_ReadDouble (void)
{ //type-pun it as an int64 over the network for easier handling of endian.
union
{
double d;
qint64_t l;
} dat;
dat.l = MSG_ReadInt64();
return dat.d;
}
char *MSG_ReadStringBuffer (char *out, size_t outsize)
{
@ -5188,6 +5254,7 @@ static cvar_t worker_sleeptime = CVARFD("worker_sleeptime", "0", CVAR_NOTFROMSER
void *com_resourcemutex;
static int com_liveworkers[WG_COUNT];
static void *com_workercondition[WG_COUNT];
int com_hadwork[WG_COUNT];
static volatile int com_workeracksequence;
static struct com_worker_s
{
@ -5332,6 +5399,7 @@ qboolean COM_DoWork(int tg, qboolean leavelocked)
if (work)
{
com_hadwork[tg]++;
// Sys_Printf("%x: Doing work %p (%s)\n", thread, work->ctx, work->ctx?(char*)work->ctx:"?");
Sys_UnlockConditional(com_workercondition[tg]);

View file

@ -277,8 +277,10 @@ void MSG_WriteChar (sizebuf_t *sb, int c);
void MSG_WriteByte (sizebuf_t *sb, int c);
void MSG_WriteShort (sizebuf_t *sb, int c);
void MSG_WriteLong (sizebuf_t *sb, int c);
void MSG_WriteInt64 (sizebuf_t *sb, qint64_t c);
void MSG_WriteEntity (sizebuf_t *sb, unsigned int e);
void MSG_WriteFloat (sizebuf_t *sb, float f);
void MSG_WriteDouble (sizebuf_t *sb, double f);
void MSG_WriteString (sizebuf_t *sb, const char *s);
void MSG_WriteCoord (sizebuf_t *sb, float f);
void MSG_WriteBigCoord (sizebuf_t *sb, float f);
@ -300,10 +302,12 @@ int MSG_ReadBits(int bits);
int MSG_ReadByte (void);
int MSG_ReadShort (void);
int MSG_ReadLong (void);
qint64_t MSG_ReadInt64 (void);
struct client_s;
unsigned int MSGSV_ReadEntity (struct client_s *fromclient);
unsigned int MSGCL_ReadEntity (void);
float MSG_ReadFloat (void);
double MSG_ReadDouble (void);
char *MSG_ReadStringBuffer (char *out, size_t outsize);
char *MSG_ReadString (void);
char *MSG_ReadStringLine (void);

View file

@ -1154,6 +1154,8 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname)
// check to see if it has already been defined
old = Cvar_FindVar (variable->name);
if (old && variable->name2)
old = Cvar_FindVar (variable->name2);
if (old)
{
if ((old->flags & CVAR_POINTER) && !(variable->flags & CVAR_POINTER))

View file

@ -891,8 +891,9 @@ vfsfile_t *SSL_OpenPrivKey(char *nativename, size_t nativesize)
}
vfsfile_t *SSL_OpenPubKey(char *nativename, size_t nativesize)
{
#define fullchainname "fullchain.pem"
#define pubname "cert.pem"
vfsfile_t *pubf;
vfsfile_t *pubf = NULL;
const char *mode = nativename?"wb":"rb";
int i = COM_CheckParm("-pubkey");
if (i++)
@ -903,10 +904,10 @@ vfsfile_t *SSL_OpenPubKey(char *nativename, size_t nativesize)
}
else
{
if (nativename)
if (!FS_NativePath(pubname, FS_ROOT, nativename, nativesize))
return NULL;
pubf = FS_OpenVFS(pubname, mode, FS_ROOT);
if (!pubf && (!nativename || FS_NativePath(fullchainname, FS_ROOT, nativename, nativesize)))
pubf = FS_OpenVFS(fullchainname, mode, FS_ROOT);
if (!pubf && (!nativename || FS_NativePath(pubname, FS_ROOT, nativename, nativesize)))
pubf = FS_OpenVFS(pubname, mode, FS_ROOT);
}
return pubf;
#undef pubname

View file

@ -1230,7 +1230,8 @@ void QCBUILTIN PF_touchtriggers(pubprogfuncs_t *prinst, struct globalvars_s *pr_
//chained search for float reference fields
void QCBUILTIN PF_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, ff, cf;
int i;
unsigned int ff, cf;
int s;
wedict_t *ent, *chain;
@ -1242,6 +1243,11 @@ void QCBUILTIN PF_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *p
cf = G_INT(OFS_PARM2)+prinst->fieldadjust;
else
cf = &((comentvars_t*)NULL)->chain - (pint_t*)NULL;
if (ff >= prinst->activefieldslots || cf >= prinst->activefieldslots)
{
PR_BIError (prinst, "PF_FindChain: bad field reference");
return;
}
for (i = 1; i < *prinst->parms->num_edicts; i++)
{
@ -1262,7 +1268,8 @@ void QCBUILTIN PF_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *p
//chained search for float, int, and entity reference fields
void QCBUILTIN PF_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, ff, cf;
int i;
unsigned int ff, cf;
float s;
wedict_t *ent, *chain;
@ -1274,6 +1281,11 @@ void QCBUILTIN PF_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *p
cf = G_INT(OFS_PARM2)+prinst->fieldadjust;
else
cf = &((comentvars_t*)NULL)->chain - (pint_t*)NULL;
if (ff >= prinst->activefieldslots || cf >= prinst->activefieldslots)
{
PR_BIError (prinst, "PF_FindChain: bad field reference");
return;
}
for (i = 1; i < *prinst->parms->num_edicts; i++)
{
@ -1294,7 +1306,8 @@ void QCBUILTIN PF_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *p
//chained search for strings in entity fields
void QCBUILTIN PF_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i, ff, cf;
int i;
unsigned int ff, cf;
const char *s;
string_t t;
wedict_t *ent, *chain;
@ -1307,6 +1320,11 @@ void QCBUILTIN PF_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
cf = G_INT(OFS_PARM2)+prinst->fieldadjust;
else
cf = &((comentvars_t*)NULL)->chain - (int*)NULL;
if (ff >= prinst->activefieldslots || cf >= prinst->activefieldslots)
{
PR_BIError (prinst, "PF_FindChain: bad field reference");
return;
}
for (i = 1; i < *prinst->parms->num_edicts; i++)
{
@ -1330,12 +1348,18 @@ void QCBUILTIN PF_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
//entity(entity start, float fld, float match) findflags = #449
void QCBUILTIN PF_FindFlags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int e, f;
int e;
unsigned int f;
int s;
wedict_t *ed;
e = G_EDICTNUM(prinst, OFS_PARM0);
f = G_INT(OFS_PARM1)+prinst->fieldadjust;
if (f >= prinst->activefieldslots)
{
PR_BIError (prinst, "PF_FindFlags: bad field reference");
return;
}
s = G_FLOAT(OFS_PARM2);
for (e++; e < *prinst->parms->num_edicts; e++)
@ -1356,7 +1380,8 @@ void QCBUILTIN PF_FindFlags (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
//entity(entity start, float fld, float match) findfloat = #98
void QCBUILTIN PF_FindFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int e, f;
int e;
unsigned int f;
int s;
wedict_t *ed;
@ -1370,6 +1395,11 @@ void QCBUILTIN PF_FindFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
e = G_EDICTNUM(prinst, OFS_PARM0);
f = G_INT(OFS_PARM1)+prinst->fieldadjust;
if (f >= prinst->activefieldslots)
{
PR_BIError (prinst, "PF_FindFloat: bad field reference");
return;
}
s = G_INT(OFS_PARM2);
for (e++; e < *prinst->parms->num_edicts; e++)
@ -1391,13 +1421,18 @@ void QCBUILTIN PF_FindFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
void QCBUILTIN PF_FindString (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int e;
int f;
unsigned int f;
const char *s;
string_t t;
wedict_t *ed;
e = G_EDICTNUM(prinst, OFS_PARM0);
f = G_INT(OFS_PARM1)+prinst->fieldadjust;
if (f >= prinst->activefieldslots)
{
PR_BIError (prinst, "PF_FindString: bad field reference");
return;
}
s = PR_GetStringOfs(prinst, OFS_PARM2);
if (!s)
{
@ -1430,8 +1465,7 @@ void QCBUILTIN PF_FindList (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
{
world_t *w = prinst->parms->user;
int e;
int f = G_INT(OFS_PARM0)+prinst->fieldadjust;
string_t t;
unsigned int f = G_INT(OFS_PARM0)+prinst->fieldadjust;
wedict_t *ed;
etype_t type = G_INT(OFS_PARM2);
@ -1439,11 +1473,25 @@ void QCBUILTIN PF_FindList (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
int *retlist;
unsigned found = 0;
//FIXME: bound f
if (type <= ev_double)
{
extern const unsigned int type_size[];
if (f < 0 || f+type_size[type] > prinst->activefieldslots)
{ //invalid field.
G_INT(OFS_PARM3) = G_INT(OFS_RETURN) = 0;
return;
}
}
else
{ //unsupported field type.
G_INT(OFS_PARM3) = G_INT(OFS_RETURN) = 0;
return;
}
if (type == ev_string)
{
const char *s = PR_GetStringOfs(prinst, OFS_PARM1);
string_t t;
if (!s)
s = ""; /* o.O */
for (e=1 ; e < *prinst->parms->num_edicts ; e++)
@ -1460,39 +1508,63 @@ void QCBUILTIN PF_FindList (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
}
else if (type == ev_float)
{ //handling -0 properly requires care
float s = G_FLOAT(OFS_PARM1);
pvec_t s = G_FLOAT(OFS_PARM1);
for (e=1 ; e < *prinst->parms->num_edicts ; e++)
{
ed = WEDICT_NUM_PB(prinst, e);
if (ED_ISFREE(ed))
continue;
if (((float*)ed->v)[f] == s)
if (((pvec_t*)ed->v)[f] == s)
list[found++] = EDICT_TO_PROG(prinst, ed);
}
}
else if (type == ev_double)
{ //handling 64bit -0 properly requires care
double s = G_DOUBLE(OFS_PARM1);
for (e=1 ; e < *prinst->parms->num_edicts ; e++)
{
ed = WEDICT_NUM_PB(prinst, e);
if (ED_ISFREE(ed))
continue;
if (*(double*)((pvec_t*)ed->v+f) == s)
list[found++] = EDICT_TO_PROG(prinst, ed);
}
}
else if (type == ev_int64 || type == ev_uint64)
{ //handling -0 properly requires care
pint64_t s = G_INT64(OFS_PARM1);
for (e=1 ; e < *prinst->parms->num_edicts ; e++)
{
ed = WEDICT_NUM_PB(prinst, e);
if (ED_ISFREE(ed))
continue;
if (*(pint64_t*)((pint_t*)ed->v+f) == s)
list[found++] = EDICT_TO_PROG(prinst, ed);
}
}
else if (type == ev_vector)
{ //big types...
float *s = G_VECTOR(OFS_PARM1);
pvec_t *s = G_VECTOR(OFS_PARM1);
for (e=1 ; e < *prinst->parms->num_edicts ; e++)
{
ed = WEDICT_NUM_PB(prinst, e);
if (ED_ISFREE(ed))
continue;
if (((float*)ed->v)[f+0] == s[0]&&
((float*)ed->v)[f+1] == s[1]&&
((float*)ed->v)[f+2] == s[2])
if (((pvec_t*)ed->v)[f+0] == s[0]&&
((pvec_t*)ed->v)[f+1] == s[1]&&
((pvec_t*)ed->v)[f+2] == s[2])
list[found++] = EDICT_TO_PROG(prinst, ed);
}
}
else
{ //generic references and other stuff that can just be treated as ints
int s = G_INT(OFS_PARM1);
pint_t s = G_INT(OFS_PARM1);
for (e=1 ; e < *prinst->parms->num_edicts ; e++)
{
ed = WEDICT_NUM_PB(prinst, e);
if (ED_ISFREE(ed))
continue;
if (((int*)ed->v)[f] == s)
if (((pint_t*)ed->v)[f] == s)
list[found++] = EDICT_TO_PROG(prinst, ed);
}
}
@ -6497,7 +6569,7 @@ void QCBUILTIN PF_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
G_FLOAT(OFS_RETURN) = realtime;
break;
case 1: //actual time, ish. we round to milliseconds to reduce spectre exposure
G_FLOAT(OFS_RETURN) = (qint64_t)(Sys_DoubleTime()*1000) / 1000.0;
G_FLOAT(OFS_RETURN) = (qint64_t)Sys_Milliseconds();
break;
//case 2: //highres.. looks like time into the frame
//case 3: //uptime

View file

@ -539,6 +539,7 @@ enum {
#define PF_GIB (1<<10) // offset the view height differently
//ZQuake.
#define PF_PMC_SHIFT 11
#define PF_PMC_MASK ((1<<11) | \
(1<<12) | \
(1<<13))
@ -565,7 +566,8 @@ enum {
#define PF_SOLID (1<<23) //or 15, depending on extensions... messy.
#define PF_PMC_SHIFT 11
//not networked
#define PF_INWATER (1u<<31) //for network smartjump.

View file

@ -627,7 +627,7 @@ void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tan
Q1BSP_ClipDecalToNodes(mod, &dec, mod->rootnode);
#endif
#ifdef Q3BSPS
else if (cl.worldmodel->fromgame == fg_quake3)
else if (mod->fromgame == fg_quake3)
{
if (mod->submodelof)
{
@ -641,7 +641,7 @@ void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tan
#endif
#ifdef TERRAIN
if (cl.worldmodel && cl.worldmodel->terrain)
if (mod->terrain)
Terrain_ClipDecal(&dec, center, dec.radius, mod);
#endif
}

View file

@ -218,58 +218,118 @@ void R_NetGraph (void)
#endif
}
void R_FrameTimeGraph (float frametime)
void R_FrameTimeGraph (float frametime, float scale)
{
int a, x, i, y;
float bias = 0;
int a, x, i, y, h, col;
vec2_t p[4];
vec2_t tc[4];
vec4_t rgba[4];
extern shader_t *shader_draw_fill;
timehistory[findex++&NET_TIMINGSMASK] = frametime;
conchar_t line[128];
int textheight;
float minv=FLT_MAX, maxv=FLT_MIN, avg=0, dev=0;
static struct
{
float time;
int col;
} history[NET_TIMINGS];
static unsigned int findex;
extern int com_hadwork[WG_COUNT];
history[findex&NET_TIMINGSMASK].time = frametime;
history[findex&NET_TIMINGSMASK].col = 0xffffffff;
findex++;
#ifdef LOADERTHREAD
if (com_hadwork[WG_MAIN])
{ //recolour the graph red if the main thread processed something from a worker.
//show three, because its not so easy to see when its whizzing past.
com_hadwork[WG_MAIN] = 0;
history[(findex-1)&NET_TIMINGSMASK].col = 0xff0000ff;
history[(findex-2)&NET_TIMINGSMASK].col = 0xff0000ff;
history[(findex-3)&NET_TIMINGSMASK].col = 0xff0000ff;
}
#endif
x = 0;
for (a=0 ; a<NET_TIMINGS ; a++)
{
i = (findex-a) & NET_TIMINGSMASK;
R_LineGraph (NET_TIMINGS-1-a, timehistory[i]);
avg += history[a].time;
if (minv > history[a].time)
minv = history[a].time;
if (maxv < history[a].time)
maxv = history[a].time;
}
if (!scale)
{
bias = minv;
scale = NET_GRAPHHEIGHT/(maxv-minv);
}
else
scale *= 1000;
avg/=a;
for (a = 0; a < NET_TIMINGS; a++)
dev += 1000*1000*(history[a].time - avg)*(history[a].time - avg);
dev /= a;
dev = sqrt(dev);
x = ((vid.width - 320)>>1);
x=-x;
y = vid.height - sb_lines - 16 - NET_GRAPHHEIGHT;
M_DrawTextBox (x, y, NET_TIMINGS/8, NET_GRAPHHEIGHT/8);
textheight = 4;
textheight = ceil(textheight*Font_CharVHeight(font_console)/8)*8; //might have a small gap underneath
y = vid.height - sb_lines - 16 - NET_GRAPHHEIGHT - textheight;
M_DrawTextBox (x, y, NET_TIMINGS/8, (textheight + NET_GRAPHHEIGHT)/8);
x=8;
y += 8;
#ifdef GRAPHTEX
Image_Upload(netgraphtexture, TF_RGBA32, ngraph_texels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_UIPIC|IF_NOMIPMAP|IF_NOPICMIP);
x=8;
R2D_Image(x, y, NET_TIMINGS, NET_GRAPHHEIGHT, 0, 0, 1, 1, netgraphshader);
#else
COM_ParseFunString(CON_WHITEMASK, va("mean: %.3ffps (%.3fms)", 1/avg, 1000*avg), line, sizeof(line), false);
Draw_ExpandedString(font_console, x, y, line);
y += Font_CharVHeight(font_console);
COM_ParseFunString(CON_WHITEMASK, va("fastest: %.3ffps (%.3fms)", 1/minv, 1000*minv), line, sizeof(line), false);
Draw_ExpandedString(font_console, x, y, line);
y += Font_CharVHeight(font_console);
COM_ParseFunString(CON_WHITEMASK, va("slowest: %.3ffps (%.3fms)", 1/maxv, 1000*maxv), line, sizeof(line), false);
Draw_ExpandedString(font_console, x, y, line);
y += Font_CharVHeight(font_console);
COM_ParseFunString(CON_WHITEMASK, va("deviation: %.3fms (max %.3fms)", dev, (maxv-minv)*1000/2), line, sizeof(line), false);
Draw_ExpandedString(font_console, x, y, line);
y += Font_CharVHeight(font_console);
Vector2Set(p[2], 0,0);
Vector2Set(p[3], 0,0);
Vector4Set(rgba[2], 0,0,0,0);
Vector4Set(rgba[3], 0,0,0,0);
for (a=0 ; a<NET_TIMINGS ; a++)
{
i = (findex-NET_TIMINGS+a)&(NET_TIMINGS-1);
h = (history[i].time - bias) * scale;
col = history[i].col;
if (h > NET_GRAPHHEIGHT)
h = NET_GRAPHHEIGHT;
Vector2Copy(p[3], p[0]); Vector4Copy(rgba[3], rgba[0]);
Vector2Copy(p[2], p[1]); Vector4Copy(rgba[2], rgba[1]);
Vector2Set(p[2+0], x+a, y+(1-ngraph[a].height)*NET_GRAPHHEIGHT);
Vector2Set(p[2+0], x+a, y+(NET_GRAPHHEIGHT-h));
Vector2Set(p[2+1], x+a, y+NET_GRAPHHEIGHT);
Vector2Set(tc[2+0], x/(float)NET_TIMINGS, (1-ngraph[a].height));
Vector2Set(tc[2+0], x/(float)NET_TIMINGS, (NET_GRAPHHEIGHT-h)/NET_GRAPHHEIGHT);
Vector2Set(tc[2+1], x/(float)NET_TIMINGS, 1);
Vector4Set(rgba[2+0], ((ngraph[a].col>>0)&0xff)/255.0, ((ngraph[a].col>>8)&0xff)/255.0, ((ngraph[a].col>>16)&0xff)/255.0, ((ngraph[a].col>>24)&0xff)/255.0);
Vector4Set(rgba[2+0], ((col>>0)&0xff)/255.0, ((col>>8)&0xff)/255.0, ((col>>16)&0xff)/255.0, ((col>>24)&0xff)/255.0);
Vector4Copy(rgba[2+0], rgba[2+1]);
if (a)
R2D_Image2dQuad((const vec2_t*)p, (const vec2_t*)tc, (const vec4_t*)rgba, shader_draw_fill);
}
#endif
}
void R_NetgraphInit(void)

View file

@ -74,6 +74,23 @@ static void VARGS QC_snprintfz (char *dest, size_t size, const char *fmt, ...)
#define LIKEPRINTF(x)
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define FTE_DEPRECATED __attribute__((__deprecated__)) //no idea about the actual gcc version
#ifdef _WIN32
#define LIKEPRINTF(x) __attribute__((format(ms_printf,x,x+1)))
#else
#define LIKEPRINTF(x) __attribute__((format(printf,x,x+1)))
#endif
#endif
#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
#define NORETURN __attribute__((noreturn))
#endif
#ifndef NORETURN
#define NORETURN
#endif
double I_FloatTime (void);
void VARGS QCC_Error (int errortype, const char *error, ...) LIKEPRINTF(2);
@ -114,7 +131,6 @@ char *QCC_COM_Parse2 (char *data);
unsigned int utf8_check(const void *in, unsigned int *value);
extern char qcc_token[1024];
extern int qcc_eof;
#define qcc_iswhite(c) ((c) == ' ' || (c) == '\r' || (c) == '\n' || (c) == '\t' || (c) == '\v')

View file

@ -58,6 +58,14 @@ QCC_ddef_t *GetField(const char *name);
return p;
}*/
const char *GetString(dstring_t str)
{
if (str >= strofs)
return "INVALIDSTRING";
else
return strings+str;
}
extern QCC_opcode_t pr_opcodes [];
int endofsystemfields;
@ -137,7 +145,7 @@ const char *temp_type (int temp, dstatement_t *start, dfunction_t *df)
}
}
printf("warning: Could not determine return type for %s\n", df->s_name + strings);
printf("warning: Could not determine return type for %s\n", GetString(df->s_name));
return "float";
@ -172,13 +180,6 @@ pbool IsConstant(QCC_ddef_t *def)
return true;
}
const char *qcstring(int str)
{
if ((unsigned)str >= strofs)
return "";
return strings+str;
}
char *type_name (QCC_ddef_t *def)
{
QCC_ddef_t *j;
@ -187,7 +188,7 @@ char *type_name (QCC_ddef_t *def)
{
case ev_field:
case ev_pointer:
j = GetField(def->s_name + strings);
j = GetField(GetString(def->s_name));
if (j)
return qcva(".%s",type_names[j->type]);
else
@ -280,7 +281,7 @@ static char *PR_ValueString (etype_t type, void *val)
switch (type)
{
case ev_string:
QC_snprintfz(line, sizeof(line), "%s", PR_String(strings + *(int *)val));
QC_snprintfz(line, sizeof(line), "%s", PR_String(GetString(*(int *)val)));
break;
case ev_entity:
QC_snprintfz(line, sizeof(line), "entity %i", *(int *)val);
@ -290,7 +291,7 @@ static char *PR_ValueString (etype_t type, void *val)
if (!f)
QC_snprintfz(line, sizeof(line), "undefined function");
else
QC_snprintfz(line, sizeof(line), "%s()", strings + f->s_name);
QC_snprintfz(line, sizeof(line), "%s()", GetString(f->s_name));
break;
/*
case ev_field:
@ -822,7 +823,7 @@ int DecompileReadData(char *srcfilename, char *buf, size_t bufsize)
// fix up the functions
for (i = 1; i < numfunctions; i++)
{
if ((unsigned)functions[i].s_name >= (unsigned)strofs || strlen(functions[i].s_name + strings) <= 0)
if ((unsigned)functions[i].s_name >= (unsigned)strofs || strlen(GetString(functions[i].s_name)) <= 0)
{
fd = DecompileFunctionGlobal(i);
if (fd)
@ -853,7 +854,7 @@ DecompileGetFunctionIdxByName(const char *name)
int i;
for (i = 1; i < numfunctions; i++)
if (!strcmp(name, strings + functions[i].s_name))
if (!strcmp(name, GetString(functions[i].s_name)))
{
return i;
}
@ -868,7 +869,7 @@ const etype_t DecompileGetFieldTypeByDef(QCC_ddef_t *def)
for (i = 1; i < numfielddefs; i++)
if (fields[i].ofs == ofs)
{
if (!strcmp(strings+def->s_name, strings+fields[i].s_name))
if (!strcmp(GetString(def->s_name), GetString(fields[i].s_name)))
return fields[i].type;
}
return ev_void;
@ -880,7 +881,7 @@ const char *DecompileGetFieldNameIdxByFinalOffset(int ofs)
for (i = 1; i < numfielddefs; i++)
if (fields[i].ofs == ofs)
{
return fields[i].s_name+strings;
return GetString(fields[i].s_name);
}
return "UNKNOWN FIELD";
}
@ -892,17 +893,17 @@ void DecompileGetFieldNameIdxByFinalOffset2(char *out, size_t outsize, int ofs)
{
if (fields[i].ofs == ofs)
{
QC_snprintfz(out, outsize, "%s", fields[i].s_name+strings);
QC_snprintfz(out, outsize, "%s", GetString(fields[i].s_name));
return;
}
else if (fields[i].type == ev_vector && fields[i].ofs+1 == ofs)
{
QC_snprintfz(out, outsize, "%s_y", fields[i].s_name+strings);
QC_snprintfz(out, outsize, "%s_y", GetString(fields[i].s_name));
return;
}
else if (fields[i].type == ev_vector && fields[i].ofs+2 == ofs)
{
QC_snprintfz(out, outsize, "%s_z", fields[i].s_name+strings);
QC_snprintfz(out, outsize, "%s_z", GetString(fields[i].s_name));
return;
}
}
@ -975,9 +976,9 @@ static unsigned int DecompileBuiltin(dfunction_t *df)
bi = -df->first_statement;
//okay, so this is kinda screwy, different mods have different sets of builtins, and a load of fte's are #0 too
//so just try to match by name first... lots of scanning. :(
if (df->s_name>0)
if (df->s_name>0 && df->s_name < strofs)
{
char *biname = strings + df->s_name;
const char *biname = GetString(df->s_name);
for (i = 0; i < (sizeof(builtins)/sizeof(builtins[0])); i++)
{
if (!builtins[i].name)
@ -1100,11 +1101,11 @@ void DecompileCalcProfiles(void)
{
unsigned int bi = DecompileBuiltin(df);
if (bi && builtins[bi].text)
QC_snprintfz(fname, sizeof(fname), "%s %s", builtins[bi].text, strings + functions[i].s_name);
QC_snprintfz(fname, sizeof(fname), "%s %s", builtins[bi].text, GetString(functions[i].s_name));
else
{
QC_snprintfz(fname, sizeof(fname), "__variant(...) %s", strings + functions[i].s_name);
printf("warning: unknown builtin %s\n", strings + functions[i].s_name);
QC_snprintfz(fname, sizeof(fname), "__variant(...) %s", GetString(functions[i].s_name));
printf("warning: unknown builtin %s\n", GetString(functions[i].s_name));
}
}
else
@ -1178,7 +1179,7 @@ void DecompileCalcProfiles(void)
}
strcat(fname, ") ");
line[0] = '\0';
QC_snprintfz(line, sizeof(line), "%s", strings + functions[i].s_name);
QC_snprintfz(line, sizeof(line), "%s", GetString(functions[i].s_name));
strcat(fname, line);
}
@ -1206,7 +1207,7 @@ QCC_ddef_t *GlobalAtOffset(dfunction_t *df, gofs_t ofs)
if (def->ofs == ofs)
{
/*if (!strings[def->s_name])
/*if (!GetString(def->s_name))
{
char line[16];
char *buf;
@ -1241,7 +1242,7 @@ QCC_ddef_t *GlobalAtOffset(dfunction_t *df, gofs_t ofs)
if (def->ofs == ofs)
{
char line[256], *buf;
sprintf(line, "%s_%c", strings+def->s_name, 'x'+parmofs); //globals, which are defined after the locals of the function they are first used in...
sprintf(line, "%s_%c", GetString(def->s_name), 'x'+parmofs); //globals, which are defined after the locals of the function they are first used in...
def = malloc(sizeof(*def)+strlen(line)+1); //must be static variables, but we can't handle them very well
buf = (char*)(def+1);
strcpy(buf, line);
@ -1290,7 +1291,7 @@ char *DecompileGlobal(dfunction_t *df, gofs_t ofs, QCC_type_t * req_t)
if (def)
{
const char *defname = qcstring(def->s_name);
const char *defname = GetString(def->s_name);
if (!strcmp(defname, "IMMEDIATE") || !strcmp(defname, ".imm") || !def->s_name)
{
@ -1316,14 +1317,14 @@ char *DecompileGlobal(dfunction_t *df, gofs_t ofs, QCC_type_t * req_t)
goto lookslikealocal;
else if ((parent = GlobalAtOffset(df, ofs-1)) && parent->type == ev_vector)
{ // _y
QC_snprintfz(line, sizeof(line), "%s_y", strings+parent->s_name); //globals, which are defined after the locals of the function they are first used in...
QC_snprintfz(line, sizeof(line), "%s_y", GetString(parent->s_name)); //globals, which are defined after the locals of the function they are first used in...
buf = malloc(strlen(line)+1); //must be static variables, but we can't handle them very well
strcpy(buf, line);
def->s_name = buf - strings;
}
else if ((parent = GlobalAtOffset(df, ofs-2)) && parent->type == ev_vector)
{ // _z
QC_snprintfz(line, sizeof(line), "%s_z", strings+parent->s_name); //globals, which are defined after the locals of the function they are first used in...
QC_snprintfz(line, sizeof(line), "%s_z", GetString(parent->s_name)); //globals, which are defined after the locals of the function they are first used in...
buf = malloc(strlen(line)+1); //must be static variables, but we can't handle them very well
strcpy(buf, line);
def->s_name = buf - strings;
@ -1337,7 +1338,7 @@ char *DecompileGlobal(dfunction_t *df, gofs_t ofs, QCC_type_t * req_t)
}
}
QC_snprintfz(line, sizeof(line), "%s", strings + def->s_name);
QC_snprintfz(line, sizeof(line), "%s", GetString(def->s_name));
if (def->type == ev_field && req_t == type_field && req_t->aux_type == type_float && DecompileGetFieldTypeByDef(def) == ev_vector)
strcat(line, "_x");
else if (def->type == ev_vector && req_t == type_float)
@ -1442,7 +1443,7 @@ void DecompileImmediate_Insert(dfunction_t *df, gofs_t ofs, char *knew, QCC_type
d = GlobalAtOffset(df, ofs);
if (d && d->s_name)// && strcmp(strings+d->s_name, "IMMEDIATE"))
if (d && d->s_name)// && strcmp(GetString(d->s_name), "IMMEDIATE"))
{ //every operator has a src (or two) and a dest.
//many compilers optimise by using the dest of a maths/logic operator to store to a local/global
//they then skip off the storeopcode.
@ -1450,7 +1451,7 @@ void DecompileImmediate_Insert(dfunction_t *df, gofs_t ofs, char *knew, QCC_type
IMMEDIATES[nofs].text = NULL;
IMMEDIATES[nofs].type = NULL;
QCC_CatVFile(Decompileofile, "%s = %s;\n", strings + d->s_name, knew);
QCC_CatVFile(Decompileofile, "%s = %s;\n", GetString(d->s_name), knew);
}
else
{
@ -1538,11 +1539,11 @@ char *DecompileImmediate_Get(dfunction_t *df, gofs_t ofs, QCC_type_t *req_t)
char *out;
if (((int*)pr_globals)[ofs] < 0 || ((int*)pr_globals)[ofs] > strofs)
{
printf("Hey! That's not a string! error in %s\n", strings + df->s_name);
printf("Hey! That's not a string! error in %s\n", GetString(df->s_name));
QC_snprintfz(temp, sizeof(temp), "%f", pr_globals[ofs]);
break;
}
in = &strings[((int*)pr_globals)[ofs]];
in = GetString(((int*)pr_globals)[ofs]);
out = temp;
if (req_t->type != ev_string)
{
@ -1639,7 +1640,7 @@ char *DecompileImmediate_Get(dfunction_t *df, gofs_t ofs, QCC_type_t *req_t)
if (!((int*)pr_globals)[ofs])
QC_snprintfz(temp, sizeof(temp), "__NULL__/*func*/");
else if (((int*)pr_globals)[ofs] > 0 && ((int*)pr_globals)[ofs] < numfunctions && functions[((int*)pr_globals)[ofs]].s_name>0)
QC_snprintfz(temp, sizeof(temp), "%s/*immediate*/", strings+functions[((int*)pr_globals)[ofs]].s_name);
QC_snprintfz(temp, sizeof(temp), "%s/*immediate*/", GetString(functions[((int*)pr_globals)[ofs]].s_name));
else
QC_snprintfz(temp, sizeof(temp), "((__variant(...))%i)", ((int*)pr_globals)[ofs]);
break;
@ -2317,7 +2318,7 @@ void DecompileDecompileStatement(dfunction_t * df, dstatement_t * s, int *indent
if (s->c)
QCC_CatVFile(Decompileofile, ", %s", DecompileGet(df, s->c, typ1));
QCC_CatVFile(Decompileofile, "]\n");
printf("warning: Unknown opcode %i in %s\n", op, strings + df->s_name);
printf("warning: Unknown opcode %i in %s\n", op, GetString(df->s_name));
}
}
@ -2367,7 +2368,7 @@ pbool DecompileDecompileFunction(dfunction_t * df, dstatement_t *altdone)
if (indent != 1)
{
printf("warning: Indentation structure corrupt (in func %s)\n", strings+df->s_name);
printf("warning: Indentation structure corrupt (in func %s)\n", GetString(df->s_name));
return false;
}
return true;
@ -2378,7 +2379,7 @@ char *DecompileString(int qcstring)
static char buf[8192];
char *s;
int c = 1;
const char *string = strings+qcstring;
const char *string = GetString(qcstring);
if (qcstring < 0 || qcstring >= strofs)
return "Invalid String";
@ -2468,7 +2469,7 @@ char *DecompileValueString(etype_t type, void *val)
break;
case ev_function:
if (*(int *)val>0 && *(int *)val<numfunctions)
QC_snprintfz(line, sizeof(line), "(/*func 0x%x*/%s)", *(int *)val, strings+functions[*(int *)val].s_name);
QC_snprintfz(line, sizeof(line), "(/*func 0x%x*/%s)", *(int *)val, GetString(functions[*(int *)val].s_name));
else
QC_snprintfz(line, sizeof(line), "((void())0x%xi)", *(int *)val);
break;
@ -2498,13 +2499,13 @@ char *DecompilePrintParameter(QCC_ddef_t * def)
{
QC_snprintfz(line, sizeof(line), "%s _p_%i%s", type_name(def), def->ofs, debug);
}
else if (!strcmp(strings + def->s_name, "IMMEDIATE") || !strcmp(strings + def->s_name, ".imm"))
else if (!strcmp(GetString(def->s_name), "IMMEDIATE") || !strcmp(GetString(def->s_name), ".imm"))
{
QC_snprintfz(line, sizeof(line), "%s%s", DecompileValueString((etype_t)(def->type), &pr_globals[def->ofs]), debug);
}
else
{
QC_snprintfz(line, sizeof(line), "%s %s%s", type_name(def), strings + def->s_name, debug);
QC_snprintfz(line, sizeof(line), "%s %s%s", type_name(def), GetString(def->s_name), debug);
}
return line;
}
@ -2527,18 +2528,18 @@ const char *GetMatchingField(QCC_ddef_t *field)
{
if (((int*)pr_globals)[def->ofs] == field->ofs)
{
if (!strcmp(strings+def->s_name, strings+field->s_name))
if (!strcmp(GetString(def->s_name), GetString(field->s_name)))
return NULL; //found ourself, give up.
lf = strlen(strings + field->s_name);
ld = strlen(strings + def->s_name);
lf = strlen(GetString(field->s_name));
ld = strlen(GetString(def->s_name));
if (lf - 2 == ld)
{
if ((strings + field->s_name)[lf-2] == '_' && (strings + field->s_name)[lf-1] == 'x')
if (!strncmp(strings + field->s_name, strings + def->s_name, ld))
if ((GetString(field->s_name)[lf-2]) == '_' && (GetString(field->s_name)[lf-1]) == 'x')
if (!strncmp(GetString(field->s_name), GetString(def->s_name), ld))
return NULL; //vector found foo_x
}
if (!ret)
ret = def->s_name+strings;
ret = GetString(def->s_name);
}
}
}
@ -2560,7 +2561,7 @@ QCC_ddef_t *GetField(const char *name)
{
d = &fields[i];
if (!strcmp(strings + d->s_name, name))
if (!strcmp(GetString(d->s_name), name))
return d;
}
return NULL;
@ -2595,7 +2596,7 @@ QCC_ddef_t *DecompileFindGlobal(const char *findname)
for (i = 0; i < numglobaldefs; i++)
{
def = &globals[i];
defname = strings + def->s_name;
defname = GetString(def->s_name);
if (!strcmp(findname, defname))
{
@ -2651,19 +2652,19 @@ void DecompilePreceedingGlobals(int start, int end, const char *name)
if (par->type == ev_function)
{
if (strcmp(strings + par->s_name, "IMMEDIATE") && strcmp(strings + par->s_name, ".imm"))
if (strcmp(GetString(par->s_name), "IMMEDIATE") && strcmp(GetString(par->s_name), ".imm"))
{
if (strcmp(strings + par->s_name, name))
if (strcmp(GetString(par->s_name), name))
{
int f = ((int*)pr_globals)[par->ofs];
//DecompileGetFunctionIdxByName(strings + par->s_name);
if (f && strcmp(strings+functions[f].s_name, strings + par->s_name))
if (f && strcmp(GetString(functions[f].s_name), GetString(par->s_name)))
{
char *s = strrchr(DecompileProfiles[f], ' ');
//happens with void() func = otherfunc;
//such functions thus don't have their own type+body
*s = 0;
QCC_CatVFile(Decompileofile, "var %s %s = %s;\n", DecompileProfiles[f], strings + par->s_name, s+1);
QCC_CatVFile(Decompileofile, "var %s %s = %s;\n", DecompileProfiles[f], GetString(par->s_name), s+1);
*s = ' ';
}
else
@ -2673,18 +2674,18 @@ void DecompilePreceedingGlobals(int start, int end, const char *name)
}
else if (par->type != ev_pointer)
{
if (strcmp(strings + par->s_name, "IMMEDIATE") && strcmp(strings + par->s_name, ".imm") && par->s_name)
if (strcmp(GetString(par->s_name), "IMMEDIATE") && strcmp(GetString(par->s_name), ".imm") && par->s_name)
{
if (par->type == ev_field)
{
ef = GetField(strings + par->s_name);
ef = GetField(GetString(par->s_name));
if (!ef)
{
QCC_CatVFile(Decompileofile, "var .unknowntype %s;\n", strings + par->s_name);
printf("Fatal Error: Could not locate a field named \"%s\"\n", strings + par->s_name);
QCC_CatVFile(Decompileofile, "var .unknowntype %s;\n", GetString(par->s_name));
printf("Fatal Error: Could not locate a field named \"%s\"\n", GetString(par->s_name));
}
else
{
@ -2694,7 +2695,7 @@ void DecompilePreceedingGlobals(int start, int end, const char *name)
matchingfield = GetMatchingField(ef);
#ifndef DONT_USE_DIRTY_TRICKS //could try scanning for an op_address+op_storep_fnc pair
if ((ef->type == ev_function) && !strcmp(strings + ef->s_name, "th_pain"))
if ((ef->type == ev_function) && !strcmp(GetString(ef->s_name), "th_pain"))
{
QCC_CatVFile(Decompileofile, ".void(entity attacker, float damage) th_pain;\n");
}
@ -2702,9 +2703,9 @@ void DecompilePreceedingGlobals(int start, int end, const char *name)
#endif
{
if (matchingfield)
QCC_CatVFile(Decompileofile, "var .%s %s = %s;\n", type_name(ef), strings + ef->s_name, matchingfield);
QCC_CatVFile(Decompileofile, "var .%s %s = %s;\n", type_name(ef), GetString(ef->s_name), matchingfield);
else
QCC_CatVFile(Decompileofile, ".%s %s;\n", type_name(ef), strings + ef->s_name);
QCC_CatVFile(Decompileofile, ".%s %s;\n", type_name(ef), GetString(ef->s_name));
// fprintf(Decompileofile, "//%i %i %i %i\n", ef->ofs, ((int*)pr_globals)[ef->ofs], par->ofs, ((int*)pr_globals)[par->ofs]);
}
@ -2719,7 +2720,7 @@ void DecompilePreceedingGlobals(int start, int end, const char *name)
if (par->type == ev_entity || par->type == ev_void)
{
QCC_CatVFile(Decompileofile, "%s %s;\n", type_name(par), strings + par->s_name);
QCC_CatVFile(Decompileofile, "%s %s;\n", type_name(par), GetString(par->s_name));
}
else
@ -2730,14 +2731,14 @@ void DecompilePreceedingGlobals(int start, int end, const char *name)
if (IsConstant(par))
{
QCC_CatVFile(Decompileofile, "%s %s = %s;\n", type_name(par), strings + par->s_name, line);
QCC_CatVFile(Decompileofile, "%s %s = %s;\n", type_name(par), GetString(par->s_name), line);
}
else
{
if (pr_globals[par->ofs] != 0)
QCC_CatVFile(Decompileofile, "%s %s /* = %s */;\n", type_name(par), strings + par->s_name, line);
QCC_CatVFile(Decompileofile, "%s %s /* = %s */;\n", type_name(par), GetString(par->s_name), line);
else
QCC_CatVFile(Decompileofile, "%s %s;\n", type_name(par), strings + par->s_name, line);
QCC_CatVFile(Decompileofile, "%s %s;\n", type_name(par), GetString(par->s_name), line);
}
}
}
@ -2763,7 +2764,7 @@ void DecompileFunction(const char *name, int *lastglobal)
for (i = 1; i < numfunctions; i++)
if (!strcmp(name, strings + functions[i].s_name))
if (!strcmp(name, GetString(functions[i].s_name)))
break;
if (i == numfunctions)
{
@ -3032,10 +3033,10 @@ void DecompileFunction(const char *name, int *lastglobal)
}
else
{
if (!strcmp(strings + par->s_name, "IMMEDIATE") || !strcmp(strings + par->s_name, ".imm"))
if (!strcmp(GetString(par->s_name), "IMMEDIATE") || !strcmp(GetString(par->s_name), ".imm"))
continue; // immediates don't belong
if (!strings[par->s_name])
if (!GetString(par->s_name))
{
QC_snprintfz(line, sizeof(line), "_l_%i", par->ofs);
arg2 = malloc(strlen(line)+1);
@ -3069,7 +3070,7 @@ void DecompileFunction(const char *name, int *lastglobal)
if (!DecompileDecompileFunction(df, altdone))
{
QCC_InsertVFile(Decompileofile, startpos, "#error Corrupt Function: %s\n#if 0\n", strings+df->s_name);
QCC_InsertVFile(Decompileofile, startpos, "#error Corrupt Function: %s\n#if 0\n", GetString(df->s_name));
QCC_CatVFile(Decompileofile, "#endif\n");
}
@ -3157,7 +3158,7 @@ void DecompileDecompileFunctions(const char *origcopyright)
lastfileofs = d->s_file;
fname[0] = '\0';
if (d->s_file <= strofs && d->s_file >= 0)
sprintf(fname, "%s", strings + d->s_file);
sprintf(fname, "%s", GetString(d->s_file));
// FrikaC -- not sure if this is cool or what?
bogusname = false;
if (strlen(fname) <= 0)
@ -3187,7 +3188,7 @@ void DecompileDecompileFunctions(const char *origcopyright)
{
synth_name[0] = 0;
}
if(!TrySynthName(qcva("%s", strings + d->s_name)) && !synth_name[0])
if(!TrySynthName(qcva("%s", GetString(d->s_name))) && !synth_name[0])
QC_snprintfz(synth_name, sizeof(synth_name), "frik%i.qc", fake_name++);
QC_snprintfz(fname, sizeof(fname), "%s", synth_name);
@ -3210,7 +3211,7 @@ void DecompileDecompileFunctions(const char *origcopyright)
}
}
Decompileofile = f;
DecompileFunction(strings + d->s_name, &lastglob);
DecompileFunction(GetString(d->s_name), &lastglob);
}
}
@ -3266,7 +3267,7 @@ char *DecompileGlobalStringNoContents(gofs_t ofs)
if (def->ofs == ofs)
{
line[0] = '0';
QC_snprintfz(line, sizeof(line), "%i(%s)", def->ofs, strings + def->s_name);
QC_snprintfz(line, sizeof(line), "%i(%s)", def->ofs, GetString(def->s_name));
break;
}
}
@ -3297,13 +3298,13 @@ char *DecompileGlobalString(gofs_t ofs)
{
line[0] = '0';
if (!strcmp(strings + def->s_name, "IMMEDIATE") || !strcmp(strings + def->s_name, ".imm"))
if (!strcmp(GetString(def->s_name), "IMMEDIATE") || !strcmp(GetString(def->s_name), ".imm"))
{
s = PR_ValueString((etype_t)(def->type), &pr_globals[ofs]);
QC_snprintfz(line, sizeof(line), "%i(%s)", def->ofs, s);
}
else
QC_snprintfz(line, sizeof(line), "%i(%s)", def->ofs, strings + def->s_name);
QC_snprintfz(line, sizeof(line), "%i(%s)", def->ofs, GetString(def->s_name));
}
}
@ -3356,7 +3357,7 @@ void DecompilePrintFunction(char *name)
dfunction_t *df;
for (i = 0; i < numfunctions; i++)
if (!strcmp(name, strings + functions[i].s_name))
if (!strcmp(name, GetString(functions[i].s_name)))
break;
if (i == numfunctions)
{

View file

@ -411,6 +411,24 @@ reeval:
ptr = QCPOINTERM(i);
ptr->_int = OPA->_int;
break;
case OP_STOREP_I64: // 64bit
i = OPB->_int + OPC->_int*sizeof(ptr->_int);
errorif (QCPOINTERWRITEFAIL(i, sizeof(ptr->_int64)))
{
if (!(ptr=PR_GetWriteTempStringPtr(progfuncs, OPB->_int, OPC->_int*sizeof(ptr->_int), sizeof(ptr->_int64))))
{
if (i == -1)
break;
if (i == 0)
QCFAULT(&progfuncs->funcs, "bad pointer write in %s (null pointer)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name));
else
QCFAULT(&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, prinst.addressableused);
}
}
else
ptr = QCPOINTERM(i);
ptr->_int64 = OPA->_int64;
break;
case OP_STOREP_V:
i = OPB->_int + (OPC->_int*sizeof(ptr->_int));
errorif (QCPOINTERWRITEFAIL(i, sizeof(pvec3_t)))
@ -504,6 +522,48 @@ reeval:
ptr = (eval_t *)(((int *)edvars(ed)) + i);
ptr->_int = OPC->_int;
break;
case OP_STOREF_I64:
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_STOREF_? references invalid entity in %s\n", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
break;
}
ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict);
errorif (!ed || ed->readonly)
{ //boot it over to the debugger
#if INTSIZE == 16
ddef16_t *d = ED_GlobalAtOfs16(progfuncs, st->a);
#else
ddef32_t *d = ED_GlobalAtOfs32(progfuncs, st->a);
#endif
fdef_t *f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->funcs.fieldadjust);
if (PR_ExecRunWarning(&progfuncs->funcs, st-pr_statements, "assignment to read-only entity %i in %s (%s.%s)\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), d?PR_StringToNative(&progfuncs->funcs, d->s_name):"??", f?f->name:"??"))
return prinst.pr_xstatement;
break;
}
//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods.
#ifdef NOLEGACY
errorif (ed->ereftype == ER_FREE)
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "assignment to free entity in %s", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
break;
}
#endif
i = OPB->_int + progfuncs->funcs.fieldadjust;
errorif ((unsigned int)i*4 >= ed->fieldsize) //FIXME:lazy size check
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_STOREF_? references invalid field %i in %s\n", OPB->_int, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
break;
}
ptr = (eval_t *)(((int *)edvars(ed)) + i);
ptr->_int64 = OPC->_int64;
break;
case OP_STOREF_V:
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
{
@ -634,7 +694,7 @@ reeval:
#endif
{
i = OPB->_int + progfuncs->funcs.fieldadjust;
errorif ((unsigned int)i*4 >= ed->fieldsize) //FIXME:lazy size check
errorif ((unsigned int)(i+1)*4 > ed->fieldsize) //FIXME:lazy size check
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_LOAD references invalid field %i in %s\n", OPB->_int, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
@ -645,7 +705,44 @@ reeval:
OPC->_int = ptr->_int;
}
break;
case OP_LOAD_I64:
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_LOAD_V references invalid entity %i in %s\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
OPC->_vector[0] = 0;
OPC->_vector[1] = 0;
OPC->_vector[2] = 0;
break;
}
ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
#ifdef NOLEGACY
if (ed->ereftype == ER_FREE)
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_LOAD references free entity %i in %s\n", OPA->edict, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
OPC->_vector[0] = 0;
OPC->_vector[1] = 0;
OPC->_vector[2] = 0;
}
else
#endif
{
i = OPB->_int + progfuncs->funcs.fieldadjust;
errorif ((unsigned int)(i+2)*4 > ed->fieldsize) //FIXME:lazy size check
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_LOAD references invalid field %i in %s\n", OPB->_int, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
OPC->_int = 0;
break;
}
ptr = (eval_t *)(((int *)edvars(ed)) + i);
OPC->_int64 = ptr->_int64;
}
break;
case OP_LOAD_V:
errorif ((unsigned)OPA->edict >= (unsigned)num_edicts)
{
@ -673,7 +770,7 @@ reeval:
#endif
{
i = OPB->_int + progfuncs->funcs.fieldadjust;
errorif ((unsigned int)i*4 >= ed->fieldsize) //FIXME:lazy size check
errorif ((unsigned int)(i+3)*4 > ed->fieldsize) //FIXME:lazy size check
{
if (PR_ExecRunWarning (&progfuncs->funcs, st-pr_statements, "OP_LOAD references invalid field %i in %s\n", OPB->_int, PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name)))
return prinst.pr_xstatement;
@ -685,7 +782,7 @@ reeval:
OPC->_vector[1] = ptr->_vector[1];
OPC->_vector[2] = ptr->_vector[2];
}
break;
break;
//==================
@ -948,7 +1045,15 @@ reeval:
else
OPC->_int = ((eval_t *)&glob[i])->_int;
break;
case OP_LOADA_I64:
i = st->a + OPB->_int;
if ((size_t)i >= (size_t)(current_progstate->globals_bytes>>2))
{
QCFAULT(&progfuncs->funcs, "bad array read in %s (index %i)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int);
}
else
OPC->_int64 = ((eval_t *)&glob[i])->_int64;
break;
case OP_LOADA_V:
i = st->a + OPB->_int;
if ((size_t)(i) >= (size_t)(current_progstate->globals_bytes>>2)-2u)
@ -1480,6 +1585,48 @@ reeval:
}
break;
*/
//[u]int64+double opcodes
case OP_ADD_I64: OPC->_int64 = OPA->_int64 + OPB->_int64; break;
case OP_SUB_I64: OPC->_int64 = OPA->_int64 - OPB->_int64; break;
case OP_MUL_I64: OPC->_int64 = OPA->_int64 * OPB->_int64; break;
case OP_DIV_I64: OPC->_int64 = OPA->_int64 / OPB->_int64; break;
case OP_BITAND_I64: OPC->_int64 = OPA->_int64 & OPB->_int64; break;
case OP_BITOR_I64: OPC->_int64 = OPA->_int64 | OPB->_int64; break;
case OP_BITXOR_I64: OPC->_int64 = OPA->_int64 ^ OPB->_int64; break;
case OP_LSHIFT_I64I: OPC->_int64 = OPA->_int64 << OPB->_int; break;
case OP_RSHIFT_I64I: OPC->_int64 = OPA->_int64 >> OPB->_int; break;
case OP_LT_I64: OPC->_int = OPA->_int64 < OPB->_int64; break;
case OP_LE_I64: OPC->_int = OPA->_int64 <= OPB->_int64; break;
case OP_EQ_I64: OPC->_int = OPA->_int64 == OPB->_int64; break;
case OP_NE_I64: OPC->_int = OPA->_int64 != OPB->_int64; break;
case OP_LT_U64: OPC->_int = OPA->_uint64 < OPB->_uint64; break;
case OP_LE_U64: OPC->_int = OPA->_uint64 <= OPB->_uint64; break;
case OP_DIV_U64: OPC->_uint64 = OPA->_uint64 / OPB->_uint64; break;
case OP_RSHIFT_U64I: OPC->_uint64 = OPA->_uint64 >> OPB->_int; break;
case OP_STORE_I64: OPB->_int64 = OPA->_int64;
// case OP_LOADF_I64: OPC->_int64 = OPA->_int64 X OPB->_int64; break;
// case OP_LOADP_I64: OPC->_int64 = OPA->_int64 X OPB->_int64; break;
case OP_CONV_UI64: OPC->_int64 = OPA->_uint; break;
case OP_CONV_II64: OPC->_int64 = OPA->_int; break;
case OP_CONV_I64I: OPC->_int = OPA->_int64; break;
case OP_CONV_FD: OPC->_double = OPA->_float; break;
case OP_CONV_DF: OPC->_float = OPA->_double; break;
case OP_CONV_I64F: OPC->_float = OPA->_int64; break;
case OP_CONV_FI64: OPC->_int64 = OPA->_float; break;
case OP_CONV_I64D: OPC->_double = OPA->_int64; break;
case OP_CONV_DI64: OPC->_int64 = OPA->_double; break;
case OP_ADD_D: OPC->_double = OPA->_double + OPB->_double; break;
case OP_SUB_D: OPC->_double = OPA->_double - OPB->_double; break;
case OP_MUL_D: OPC->_double = OPA->_double * OPB->_double; break;
case OP_DIV_D: OPC->_double = OPA->_double / OPB->_double; break;
case OP_LT_D: OPC->_double = OPA->_double < OPB->_double; break;
case OP_LE_D: OPC->_double = OPA->_double <= OPB->_double; break;
case OP_EQ_D: OPC->_double = OPA->_double == OPB->_double; break;
case OP_NE_D: OPC->_double = OPA->_double != OPB->_double; break;
default:
if (op & OP_BIT_BREAKPOINT) //break point!
{

View file

@ -1574,6 +1574,7 @@ static pubprogfuncs_t deffuncs = {
0, //string table size
0, //max size
0, //field adjust(aditional field offset)
0, //field slots allocated (for builtins to clamp field reference args).
PR_ForkStack,
PR_ResumeThread,

View file

@ -342,6 +342,62 @@ enum qcop_e {
OP_STOREP_B,//((char*)b)[(int)c] = (int)a
OP_LOADP_B, //(int)c = *(char*)
//r5768+
//opcodes for 32bit uints
OP_LE_U, //aka GT
OP_LT_U, //aka GE
OP_DIV_U, //don't need mul+add+sub
OP_RSHIFT_U, //lshift is the same for signed+unsigned
//opcodes for 64bit ints
OP_ADD_I64,
OP_SUB_I64,
OP_MUL_I64,
OP_DIV_I64,
OP_BITAND_I64,
OP_BITOR_I64,
OP_BITXOR_I64,
OP_LSHIFT_I64I,
OP_RSHIFT_I64I,
OP_LE_I64, //aka GT
OP_LT_I64, //aka GE
OP_EQ_I64,
OP_NE_I64,
//extra opcodes for 64bit uints
OP_LE_U64, //aka GT
OP_LT_U64, //aka GE
OP_DIV_U64,
OP_RSHIFT_U64I,
//general 64bitness
OP_STORE_I64,
OP_STOREP_I64,
OP_STOREF_I64,
OP_LOAD_I64,
OP_LOADA_I64,
OP_LOADP_I64,
//various conversions for our 64bit types (yay type promotion)
OP_CONV_UI64, //zero extend
OP_CONV_II64, //sign extend
OP_CONV_I64I, //truncate
OP_CONV_FD, //extension
OP_CONV_DF, //truncation
OP_CONV_I64F, //logically a promotion (always signed)
OP_CONV_FI64, //demotion (always signed)
OP_CONV_I64D, //'promotion' (always signed)
OP_CONV_DI64, //demotion (always signed)
//opcodes for doubles.
OP_ADD_D,
OP_SUB_D,
OP_MUL_D,
OP_DIV_D,
OP_LE_D,
OP_LT_D,
OP_EQ_D,
OP_NE_D,
OP_NUMREALOPS,
/*
@ -453,13 +509,61 @@ enum qcop_e {
OP_SPACESHIP_F, //lame
OP_SPACESHIP_S, //basically strcmp.
//uint32 opcodes. they match the int32 ones so emulation is basically swapping them over.
OP_ADD_U,
OP_SUB_U,
OP_MUL_U,
OP_MOD_U, //complex
OP_BITAND_U,
OP_BITOR_U,
OP_BITXOR_U,
OP_BITNOT_U, //BITXOR ~0
OP_BITCLR_U,
OP_LSHIFT_U, //same as signed (unlike rshift)
OP_GE_U, //LT_U
OP_GT_U, //LE_U
// OP_AND_U,
// OP_OR_U,
OP_EQ_U,
OP_NE_U,
//uint64 opcodes. they match the int32 ones so emulation is basically swapping them over.
OP_BITNOT_I64, //BITXOR ~0
OP_BITCLR_I64,
OP_GE_I64, //LT_I64
OP_GT_I64, //LE_I64
OP_ADD_U64,
OP_SUB_U64,
OP_MUL_U64,
OP_MOD_U64, //complex
OP_BITAND_U64,
OP_BITOR_U64,
OP_BITXOR_U64,
OP_BITNOT_U64, //BITXOR ~0
OP_BITCLR_U64,
OP_LSHIFT_U64I,
OP_GE_U64, //LT_U64
OP_GT_U64, //LE_U64
OP_EQ_U64,
OP_NE_U64,
//generally implemented by forcing to int64.
OP_BITAND_D,
OP_BITOR_D,
OP_BITXOR_D,
OP_BITNOT_D,
OP_BITCLR_D,
OP_LSHIFT_DI,
OP_RSHIFT_DI,
//special/fake opcodes used by the decompiler.
OPD_GOTO_FORSTART,
OPD_GOTO_WHILE1,
OP_NUMOPS,
OP_BIT_BREAKPOINT = 0x8000,
OP_NUMOPS
};
#define MAX_PARMS 8

View file

@ -610,8 +610,20 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val, pbool v
case ev_float:
QC_snprintfz (line, sizeof(line), "%g", val->_float);
break;
case ev_double:
QC_snprintfz (line, sizeof(line), "%g", val->_double);
break;
case ev_integer:
QC_snprintfz (line, sizeof(line), "%i", val->_int);
QC_snprintfz (line, sizeof(line), "%"pPRIi, val->_int);
break;
case ev_uint:
QC_snprintfz (line, sizeof(line), "%"pPRIu, val->_uint);
break;
case ev_int64:
QC_snprintfz (line, sizeof(line), "%"pPRIi64, val->_int64);
break;
case ev_uint64:
QC_snprintfz (line, sizeof(line), "%"pPRIu64, val->_uint64);
break;
case ev_vector:
QC_snprintfz (line, sizeof(line), "'%g %g %g'", val->_vector[0], val->_vector[1], val->_vector[2]);
@ -749,8 +761,23 @@ char *PDECL PR_UglyValueString (pubprogfuncs_t *ppf, etype_t type, eval_t *val)
else
sprintf (line, "%f", val->_float);
break;
case ev_double:
if (val->_double == (pint64_t)val->_double)
sprintf (line, "%"pPRIi64, (pint64_t)val->_double); //an attempt to cut down on the number of .000000 vars..
else
sprintf (line, "%f", val->_double);
break;
case ev_integer:
sprintf (line, "%i", val->_int);
sprintf (line, "%"pPRIi, val->_int);
break;
case ev_uint:
sprintf (line, "%"pPRIu, val->_uint);
break;
case ev_int64:
sprintf (line, "%"pPRIi64, val->_int64);
break;
case ev_uint64:
sprintf (line, "%"pPRIu64, val->_int64);
break;
case ev_vector:
if (val->_vector[0] == (int)val->_vector[0] && val->_vector[1] == (int)val->_vector[1] && val->_vector[2] == (int)val->_vector[2])
@ -815,8 +842,23 @@ char *PR_UglyOldValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
else
QC_snprintfz (line, sizeof(line), "%f", val->_float);
break;
case ev_double:
if (val->_double == (int)val->_double)
QC_snprintfz (line, sizeof(line), "%i", (int)val->_double); //an attempt to cut down on the number of .000000 vars..
else
QC_snprintfz (line, sizeof(line), "%f", val->_double);
break;
case ev_integer:
QC_snprintfz (line, sizeof(line), "%i", val->_int);
QC_snprintfz (line, sizeof(line), "%"pPRIi, val->_int);
break;
case ev_uint:
QC_snprintfz (line, sizeof(line), "%"pPRIu, val->_uint);
break;
case ev_int64:
QC_snprintfz (line, sizeof(line), "%"pPRIi64, val->_int64);
break;
case ev_uint64:
QC_snprintfz (line, sizeof(line), "%"pPRIu64, val->_uint64);
break;
case ev_vector:
if (val->_vector[0] == (int)val->_vector[0] && val->_vector[1] == (int)val->_vector[1] && val->_vector[2] == (int)val->_vector[2])
@ -862,10 +904,18 @@ char *PR_TypeString(progfuncs_t *progfuncs, etype_t type)
return "void";
case ev_float:
return "float";
case ev_double:
return "double";
case ev_vector:
return "vector";
case ev_integer:
return "integer";
case ev_uint:
return "uint";
case ev_int64:
return "int64";
case ev_uint64:
return "uint64";
default:
return "BAD TYPE";
}
@ -1192,9 +1242,21 @@ pbool PDECL ED_ParseEval (pubprogfuncs_t *ppf, eval_t *eval, int type, const cha
case ev_float:
eval->_float = (float)atof (s);
break;
case ev_double:
eval->_double = atof (s);
break;
case ev_integer:
eval->_int = atoi (s);
eval->_int = strtol (s, NULL, 0);
break;
case ev_uint:
eval->_uint = strtoul (s, NULL, 0);
break;
case ev_int64:
eval->_int64 = strtoll (s, NULL, 0);
break;
case ev_uint64:
eval->_uint64 = strtoull (s, NULL, 0);
break;
case ev_vector:
@ -1259,14 +1321,15 @@ pbool PDECL ED_ParseEval (pubprogfuncs_t *ppf, eval_t *eval, int type, const cha
pbool ED_ParseEpair (progfuncs_t *progfuncs, size_t qcptr, unsigned int fldofs, int fldtype, char *s)
{
int i;
pint64_t i;
puint64_t u;
progsnum_t module;
fdef_t *def;
string_t st;
mfunction_t *func;
int type = fldtype & ~DEF_SAVEGLOBAL;
double d;
qcptr += fldofs*sizeof(int);
eval_t *eval = (eval_t *)(progfuncs->funcs.stringtable + qcptr + (fldofs*sizeof(int)));
switch (type)
{
@ -1276,7 +1339,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, size_t qcptr, unsigned int fldofs,
#else
st = PR_StringToProgs(&progfuncs->funcs, ED_NewString (&progfuncs->funcs, s, 0, true));
#endif
*(string_t *)(progfuncs->funcs.stringtable + qcptr) = st;
eval->string = st;
break;
case ev_float:
@ -1285,19 +1348,60 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, size_t qcptr, unsigned int fldofs,
d = strtod(s, &s);
while(*s == ' ' || *s == '\t')
s++;
*(float *)(progfuncs->funcs.stringtable + qcptr) = d;
eval->_float = d;
if (*s)
return false; //some kind of junk in there.
break;
case ev_double:
while(*s == ' ' || *s == '\t')
s++;
d = strtod(s, &s);
while(*s == ' ' || *s == '\t')
s++;
eval->_double = d;
if (*s)
return false; //some kind of junk in there.
break;
case ev_entity: //ent references are simple ints for us.
case ev_integer:
while(*s == ' ' || *s == '\t')
s++;
i = strtol(s, &s, 0);
while(*s == ' ' || *s == '\t')
s++;
*(int *)(progfuncs->funcs.stringtable + qcptr) = i;
eval->_int = i;
if (*s)
return false; //some kind of junk in there.
break;
case ev_entity: //ent references are simple ints for us.
case ev_uint:
while(*s == ' ' || *s == '\t')
s++;
u = strtoul(s, &s, 0);
while(*s == ' ' || *s == '\t')
s++;
eval->_uint = u;
if (*s)
return false; //some kind of junk in there.
break;
case ev_int64:
while(*s == ' ' || *s == '\t')
s++;
i = strtoll(s, &s, 0);
while(*s == ' ' || *s == '\t')
s++;
eval->_int64 = i;
if (*s)
return false; //some kind of junk in there.
break;
case ev_uint64:
while(*s == ' ' || *s == '\t')
s++;
u = strtoull(s, &s, 0);
while(*s == ' ' || *s == '\t')
s++;
eval->_uint64 = u;
if (*s)
return false; //some kind of junk in there.
break;
@ -1308,7 +1412,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, size_t qcptr, unsigned int fldofs,
while(*s == ' ' || *s == '\t')
s++;
d = strtod(s, &s);
((float *)(progfuncs->funcs.stringtable + qcptr))[i] = d;
eval->_vector[i] = d;
}
while(*s == ' ' || *s == '\t')
s++;
@ -1323,13 +1427,13 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, size_t qcptr, unsigned int fldofs,
externs->Printf ("Can't find field %s\n", s);
return false;
}
*(int *)(progfuncs->funcs.stringtable + qcptr) = def->ofs;
eval->_int = def->ofs;
break;
case ev_function:
if (s[0] && s[1]==':'&&s[2]=='\0') //this isn't right...
{
*(func_t *)(progfuncs->funcs.stringtable + qcptr) = 0;
eval->function = 0;
return true;
}
func = ED_FindFunction (progfuncs, s, &module, -1);
@ -1338,7 +1442,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, size_t qcptr, unsigned int fldofs,
externs->Printf ("Can't find function %s\n", s);
return false;
}
*(func_t *)(progfuncs->funcs.stringtable + qcptr) = (func - pr_progstate[module].functions) | (module<<24);
eval->function = (func - pr_progstate[module].functions) | (module<<24);
break;
default:
@ -1564,7 +1668,11 @@ char *ED_WriteGlobals(progfuncs_t *progfuncs, char *buf, size_t *bufofs, size_t
}
else if (type != ev_string //anything other than these is not saved
&& type != ev_float
&& type != ev_double
&& type != ev_integer
&& type != ev_uint
&& type != ev_int64
&& type != ev_uint64
&& type != ev_entity
&& type != ev_vector)
continue;
@ -1621,7 +1729,11 @@ char *ED_WriteGlobals(progfuncs_t *progfuncs, char *buf, size_t *bufofs, size_t
}
else if (type != ev_string //anything other than these is not saved
&& type != ev_float
&& type != ev_double
&& type != ev_integer
&& type != ev_uint
&& type != ev_int64
&& type != ev_uint64
&& type != ev_entity
&& type != ev_vector)
continue;
@ -3098,8 +3210,11 @@ retry:
nf->progsofs = fld16[i].ofs;
nf->ofs = fld16[i].ofs;
if (prinst.fields_size < (nf->ofs+type_size[nf->type])*4)
prinst.fields_size = (nf->ofs+type_size[nf->type])*4;
if (prinst.fields_size < (nf->ofs+type_size[nf->type])*sizeof(pvec_t))
{
prinst.fields_size = (nf->ofs+type_size[nf->type])*sizeof(pvec_t);
progfuncs->funcs.activefieldslots = nf->ofs+type_size[nf->type];
}
prinst.numfields++;
}

View file

@ -244,7 +244,7 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, const char
prinst.reorganisefields = 2;
else if (engineofs)
{
progfuncs->funcs.fieldadjust = prinst.fields_size/4;
progfuncs->funcs.fieldadjust = prinst.fields_size/sizeof(pvec_t);
#ifdef MAPPING_DEBUG
externs->Printf("FIELD ADJUST: %i %i %i\n", progfuncs->funcs.fieldadjust, prinst.fields_size, (int)prinst.fields_size/4);
#endif
@ -329,7 +329,7 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, const char
}
else
{ //we just found a new fieldname inside a progs
prinst.field[fnum].ofs = ofs = prinst.fields_size/4; //add on the end
prinst.field[fnum].ofs = ofs = prinst.fields_size/sizeof(pvec_t); //add on the end
//if the progs field offset matches annother offset in the same progs, make it match up with the earlier one.
if (progsofs>=0)
@ -368,8 +368,11 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, const char
}
}
// if (type != ev_vector)
if (prinst.fields_size < (ofs+type_size[type])*4)
prinst.fields_size = (ofs+type_size[type])*4;
if (prinst.fields_size < (ofs+type_size[type])*sizeof(pvec_t))
{
prinst.fields_size = (ofs+type_size[type])*sizeof(pvec_t);
progfuncs->funcs.activefieldslots = prinst.fields_size/sizeof(pvec_t);
}
if (prinst.max_fields_size && prinst.fields_size > prinst.max_fields_size)
externs->Sys_Error("Allocated too many additional fields after ents were inited.");

View file

@ -67,7 +67,30 @@ typedef struct {
int spare[2];
} evalc_t;
#define sizeofevalc sizeof(evalc_t)
typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer, ev_integer, ev_variant, ev_struct, ev_union, ev_accessor, ev_enum, ev_boolean} etype_t;
typedef enum {
//vanilla types
ev_void,
ev_string, //offset into the string table - but if the high bit is set then its probably some special thing.
ev_float, //can hold up to 24 bits... sucks, but this is our basic numeric type.
ev_vector, //3 floats.
ev_entity, //index into the edicts array (vanilla used byte offsets from world).
ev_field, //index into the per-entity field table.
ev_function,//all functions are called via reference.
ev_pointer, //exists in vanilla - *(&ent.fld) opcodes are valid there - how else would you store to a field?
//extended types
ev_integer, //our first extended type... probably won't help performance much but at least it doesn't have the imprecision issue of floats.
ev_uint, //mostly just reuses int opcodes.
ev_int64, //large int type, because we can. might be useful for system handles perhaps? dunno, probably not that useful.
ev_uint64, //mostly just reuses int64 opcodes.
ev_double, //useful for timers, for the extra precision.
//qc-only types
ev_variant, //used primarily for builtin args, or for type punning casts without using pointers. should never be used for a global.
ev_struct, //big complex type
ev_union, //not really sure why this is separate from struct
ev_accessor,//some weird type to provide class-like functions over a basic type.
ev_enum, //just a numeric type
ev_boolean //exists to optimise if(-0) workarounds.
} etype_t;
enum {
DEBUG_TRACE_OFF, //debugging should be off.
DEBUG_TRACE_INTO, //debug into functions
@ -154,6 +177,8 @@ struct pubprogfuncs_s
int stringtablesize;
int stringtablemaxsize;
int fieldadjust; //FrikQCC style arrays can cause problems due to field remapping. This causes us to leave gaps but offsets identical. except for system fields, qc-addressable variables use their old offsets, this is the bias so that the offset pokes the correct memory.
unsigned int activefieldslots; //f+=fieldadjust; invalidfield = (f<0)||(f+fldsize>=activefieldslots); note that this does NOT apply to 'object' entities which are variable sized, use ed->fieldsize for those.
struct qcthread_s *(PDECL *Fork) (pubprogfuncs_t *prinst); //returns a pointer to a thread which can be resumed via RunThread.
void (PDECL *RunThread) (pubprogfuncs_t *prinst, struct qcthread_s *thread);
@ -260,12 +285,16 @@ pubprogfuncs_t * PDECL InitProgs(progparms_t *ext);
typedef union eval_s
{
string_t string;
float _float;
float _vector[3];
func_t function;
int _int;
int edict;
float prog; //so it can easily be changed
pvec_t _float;
pvec_t _vector[3];
func_t function; //module=0xff000000, func=0x00ffffff
pint_t _int;
puint_t _uint;
pint64_t _int64;
puint64_t _uint64;
double _double;
pint_t edict;
pvec_t prog; //so it can easily be changed
} eval_t;
#define PR_CURRENT -1
@ -334,7 +363,11 @@ typedef union eval_s
//To use these outside of builtins, you will likly have to use the 'globals' method.
#define G_FLOAT(o) (((pvec_t *)pr_globals)[o])
#define G_FLOAT2(o) (((pvec_t *)pr_globals)[OFS_PARM0 + o*3])
#define G_DOUBLE(o) (*(double *)(((pvec_t *)pr_globals+(o))))
#define G_INT(o) (((pint_t *)pr_globals)[o])
#define G_UINT(o) (((puint_t *)pr_globals)[o])
#define G_INT64(o) (*(pint64_t *)((pint_t *)pr_globals+(o)))
#define G_UINT64(o) (*(puint64_t *)((puint_t *)pr_globals+(o)))
#define G_EDICT(pf, o) PROG_TO_EDICT(pf, G_INT(o)) //((edict_t *)((char *) sv.edicts+ *(int *)&((float *)pr_globals)[o]))
#define G_EDICTNUM(pf, o) NUM_FOR_EDICT(pf, G_EDICT(pf, o))
#define G_VECTOR(o) (&((pvec_t *)pr_globals)[o])

View file

@ -23,10 +23,30 @@ typedef uint64_t puint_t;
typedef float pvec_t;
typedef int pint_t;
typedef unsigned int puint_t;
#define pPRId "d"
#define pPRIi "i"
#define pPRIu "u"
#define pPRIx "x"
#ifdef _MSC_VER
typedef __int64 pint64_t;
typedef unsigned __int64 puint64_t;
#define pPRId "d"
#define pPRIi "i"
#define pPRIu "u"
#define pPRIx "x"
#define pPRIi64 "I64i"
#define pPRIu64 "I64u"
#define pPRIx64 "I64x"
#else
#include <inttypes.h>
typedef int64_t pint64_t;
typedef uint64_t puint64_t;
#define pPRId PRId32
#define pPRIi PRIi32
#define pPRIu PRIu32
#define pPRIx PRIx32
#define pPRIi64 PRIi64
#define pPRIu64 PRIu64
#define pPRIx64 PRIx64
#endif
#define QCVM_32
#endif

View file

@ -317,7 +317,7 @@ typedef struct QCC_function_s QCC_function_t;
#define MAX_PARMS 8
//keep this sizeof(float)
typedef union QCC_eval_s
typedef union QCC_eval_basic_s
{
QCC_string_t string;
pvec_t _float;
@ -328,19 +328,24 @@ typedef union QCC_eval_s
#endif
func_t function;
pint_t _int;
puint_t _uint;
// union QCC_eval_s *ptr;
} QCC_eval_t;
} QCC_eval_basic_t;
//must be the maximum size possible for a single basic type.
typedef union QCC_evalstorage_s
typedef union QCC_eval_s
{
QCC_string_t string;
pvec_t _float;
double _double;
pvec_t vector[3];
func_t function;
pint_t _int;
puint_t _uint;
pint64_t _int64;
puint64_t _uint64;
// union QCC_eval_s *ptr;
} QCC_evalstorage_t;
} QCC_eval_t;
struct QCC_typeparam_s
{
@ -349,7 +354,7 @@ struct QCC_typeparam_s
pbool optional:1; //argument may safely be omitted, for builtin functions. for qc functions use the defltvalue instead.
pbool isvirtual:1; //const, with implicit initialisation only. valid for structs
unsigned char out; //0=in,1==inout,2=out
unsigned int ofs;
unsigned int ofs; //FIXME: make byte offsets, for bytes/shorts.
unsigned int arraysize;
char *paramname;
};
@ -375,8 +380,8 @@ typedef struct QCC_type_s
struct QCC_typeparam_s *params; //[num_parms]
unsigned int num_parms;
unsigned int size;
pbool typedefed:1;
unsigned int size; //FIXME: make bytes, for bytes+shorts
pbool typedefed:1; //name is in the typenames list.
pbool vargs:1; //function has vargs
pbool vargcount:1; //function has special varg count param
const char *name;
@ -412,7 +417,7 @@ typedef struct QCC_def_s
struct QCC_def_s *reloc; //the symbol that we're a reloc for
struct QCC_def_s *gaddress; //a def that holds our offset.
struct QCC_def_s *symbolheader; //this is the original symbol within which the def is stored.
union QCC_eval_s *symboldata; //null if uninitialised. use sym->symboldata[sym->ofs] to index.
union QCC_eval_basic_s *symboldata; //null if uninitialised. use sym->symboldata[sym->ofs] to index.
unsigned int symbolsize; //total byte size of symbol
int refcount; //if 0, temp can be reused. tracked on globals too in order to catch bugs that would otherwise be a little too obscure.
@ -497,7 +502,7 @@ extern int QCC_packid;
extern const unsigned int type_size[];
//extern QCC_def_t *def_for_type[9];
extern QCC_type_t *type_void, *type_string, *type_float, *type_vector, *type_entity, *type_field, *type_function, *type_floatfunction, *type_pointer, *type_floatpointer, *type_intpointer, *type_integer, *type_variant, *type_floatfield;
extern QCC_type_t *type_void, *type_string, *type_float, *type_double, *type_vector, *type_entity, *type_field, *type_function, *type_floatfunction, *type_pointer, *type_floatpointer, *type_intpointer, *type_bint, *type_bfloat, *type_integer, *type_uint, *type_int64, *type_uint64, *type_variant, *type_floatfield;
extern char *basictypenames[];
struct QCC_function_s
@ -581,7 +586,7 @@ extern token_type_t pr_token_type;
extern int pr_token_line;
extern int pr_token_line_last;
extern QCC_type_t *pr_immediate_type;
extern QCC_evalstorage_t pr_immediate;
extern QCC_eval_t pr_immediate;
extern pbool keyword_asm;
extern pbool keyword_break;
@ -596,10 +601,17 @@ extern pbool keyword_default;
extern pbool keyword_do;
extern pbool keyword_entity;
extern pbool keyword_float;
extern pbool keyword_double;
extern pbool keyword_for;
extern pbool keyword_goto;
extern pbool keyword_char;
extern pbool keyword_byte;
extern pbool keyword_short;
extern pbool keyword_int;
extern pbool keyword_integer;
extern pbool keyword_long;
extern pbool keyword_signed;
extern pbool keyword_unsigned;
extern pbool keyword_state;
extern pbool keyword_string;
extern pbool keyword_struct;
@ -642,6 +654,7 @@ extern pbool flag_laxcasts;
extern pbool flag_hashonly;
extern pbool flag_fasttrackarrays;
extern pbool flag_assume_integer;
extern pbool flag_assume_double;
extern pbool flag_msvcstyle;
extern pbool flag_debugmacros;
extern pbool flag_filetimes;
@ -656,6 +669,7 @@ extern pbool flag_assumevar;
extern pbool flag_dblstarexp;
extern pbool flag_allowuninit;
extern pbool flag_cpriority;
extern pbool flag_qcfuncs;
extern pbool flag_embedsrc;
extern pbool flag_nopragmafileline;
extern pbool flag_utf8strings;
@ -740,14 +754,14 @@ void QCC_PR_Expect (const char *string);
pbool QCC_PR_CheckKeyword(int keywordenabled, const char *string);
#endif
pbool QCC_PR_CheckTokenComment(const char *string, char **comment);
void VARGS QCC_PR_ParseError (int errortype, const char *error, ...);
NORETURN void VARGS QCC_PR_ParseError (int errortype, const char *error, ...);
pbool VARGS QCC_PR_ParseWarning (int warningtype, const char *error, ...);
pbool VARGS QCC_PR_Warning (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, ...);
void QCC_PR_ParsePrintDef (int warningtype, QCC_def_t *def);
void QCC_PR_ParsePrintSRef (int warningtype, QCC_sref_t sref);
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char *error, ...);
void VARGS QCC_PR_ParseErrorPrintSRef (int errortype, QCC_sref_t sref, const char *error, ...);
NORETURN void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char *error, ...);
NORETURN void VARGS QCC_PR_ParseErrorPrintSRef (int errortype, QCC_sref_t sref, const char *error, ...);
QCC_type_t *QCC_PR_MakeThiscall(QCC_type_t *orig, QCC_type_t *thistype);
@ -845,6 +859,7 @@ enum {
WARN_REDECLARATIONMISMATCH,
WARN_PARAMWITHNONAME,
WARN_ARGUMENTCHECK,
WARN_IGNOREDKEYWORD, //use of a keyword that fteqcc does not support at this time.
ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called.
@ -1066,6 +1081,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *defscope, QCC_def_t *thearray, char
void QCC_PR_EmitClassFromFunction(QCC_def_t *defscope, QCC_type_t *basetype);
void QCC_PR_ParseDefs (char *classname, pbool fatal);
void QCC_PR_ParseTypedef(void);
QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, const char *name, QCC_function_t *scope, int arraysize, QCC_def_t *rootsymbol, unsigned int ofs, int referable, unsigned int flags);
void QCC_PR_ParseInitializerDef(QCC_def_t *def, unsigned int flags);
void QCC_PR_FinaliseFunctions(void);
@ -1084,7 +1100,7 @@ void QCC_Cleanup(void);
extern char pr_immediate_string[8192];
extern size_t pr_immediate_strlen;
extern QCC_eval_t *qcc_pr_globals;
extern QCC_eval_basic_t *qcc_pr_globals;
extern unsigned int numpr_globals;
extern char *strings;

View file

@ -19,7 +19,7 @@ const char **myargv;
char qcc_token[1024];
int qcc_eof;
const unsigned int type_size[12] = {1, //void
const unsigned int type_size[] = {1, //void
sizeof(string_t)/4, //string
1, //float
3, //vector
@ -28,12 +28,18 @@ const unsigned int type_size[12] = {1, //void
sizeof(func_t)/4,//function
1, //pointer (its an int index)
1, //integer
1, //uint
2, //long
2, //ulong
2, //double
3, //fixme: how big should a variant be?
0, //ev_struct. variable sized.
0 //ev_union. variable sized.
0, //ev_union. variable sized.
0, //ev_accessor...
0, //ev_enum...
1, //ev_bool...
};
char *basictypenames[] = {
"void",
"string",
@ -44,11 +50,16 @@ char *basictypenames[] = {
"function",
"pointer",
"integer",
"uint",
"long",
"ulong",
"double",
"variant",
"struct",
"union",
"accessor",
"enum"
"enum",
"bool"
};
/*
@ -291,10 +302,7 @@ skipwhite:
while ((c = *data) && qcc_iswhite(c))
data++;
if (!c)
{
qcc_eof = true;
return NULL;
}
// skip // comments
if (c=='/' && data[1] == '/')
@ -415,10 +423,7 @@ skipwhite:
while ((c = *data) && qcc_iswhite(c))
data++;
if (!c)
{
qcc_eof = true;
return NULL;
}
// skip // comments
if (c=='/' && data[1] == '/')

File diff suppressed because it is too large Load diff

View file

@ -41,7 +41,7 @@ token_type_t pr_token_type;
int pr_token_line;
int pr_token_line_last;
QCC_type_t *pr_immediate_type;
QCC_evalstorage_t pr_immediate;
QCC_eval_t pr_immediate;
char pr_immediate_string[8192];
size_t pr_immediate_strlen;
@ -84,16 +84,22 @@ char *pr_punctuationremap[] = //a nice bit of evilness.
QCC_type_t *type_void; //void
QCC_type_t *type_string; //string
QCC_type_t *type_float; //float
QCC_type_t *type_double; //double
QCC_type_t *type_vector; //vector
QCC_type_t *type_entity; //entity
QCC_type_t *type_field; //.void
QCC_type_t *type_function; //void()
QCC_type_t *type_floatfunction; //float()
QCC_type_t *type_pointer; //??? * - careful with this one
QCC_type_t *type_integer; //int
QCC_type_t *type_integer; //int32
QCC_type_t *type_uint; //uint32
QCC_type_t *type_int64; //int64
QCC_type_t *type_uint64; //uint64
QCC_type_t *type_variant; //__variant
QCC_type_t *type_floatpointer; //float *
QCC_type_t *type_intpointer; //int *
QCC_type_t *type_bint; //int (0 or 1)
QCC_type_t *type_bfloat; //float (0.0 or 1.0, and never -0.0)
QCC_type_t *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float};
@ -1306,8 +1312,9 @@ static pbool QCC_PR_Precompiler(void)
}
else if (!QC_strcasecmp(qcc_token, "sourcefile"))
{
QCC_COM_Parse(msg);
QCC_RegisterSourceFile(qcc_token);
char *s = msg;
while ((s = QCC_COM_Parse(s)))
QCC_RegisterSourceFile(qcc_token);
}
else if (!QC_strcasecmp(qcc_token, "TARGET"))
{
@ -1330,6 +1337,41 @@ static pbool QCC_PR_Precompiler(void)
if (strcmp(destfile, olddest))
externs->Printf("Outputfile: %s\n", destfile);
}
else if (!QC_strcasecmp(qcc_token, "opcode"))
{
int st;
char *s = QCC_COM_Parse(msg);
if (!QC_strcasecmp(qcc_token, "enable") || !QC_strcasecmp(qcc_token, "on"))
st = 1;
else if (!QC_strcasecmp(qcc_token, "disable") || !QC_strcasecmp(qcc_token, "off"))
st = 0;
else
{
QCC_PR_ParseWarning(WARN_BADPRAGMA, "opcode state not recognised");
st = -1;
}
if (st >= 0)
{
int f;
while ((s = QCC_COM_Parse(s)))
{
for (f = 0; pr_opcodes[f].opname; f++)
{
if (!QC_strcasecmp(pr_opcodes[f].opname, qcc_token))
{
if (st)
pr_opcodes[f].flags |= OPF_VALID;
else
pr_opcodes[f].flags &= ~OPF_VALID;
break;
}
}
if (!pr_opcodes[f].opname)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "opcode %s not recognised", qcc_token);
}
}
}
else if (!QC_strcasecmp(qcc_token, "keyword") || !QC_strcasecmp(qcc_token, "flag"))
{
char *s;
@ -1344,31 +1386,29 @@ static pbool QCC_PR_Precompiler(void)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "compiler flag state not recognised");
st = -1;
}
if (st < 0)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
else
if (st >= 0)
{
int f;
s = QCC_COM_Parse(s);
for (f = 0; compiler_flag[f].enabled; f++)
while ((s = QCC_COM_Parse(s)))
{
if (!QC_strcasecmp(compiler_flag[f].abbrev, qcc_token))
for (f = 0; compiler_flag[f].enabled; f++)
{
if (compiler_flag[f].flags & FLAG_MIDCOMPILE)
if (!QC_strcasecmp(compiler_flag[f].abbrev, qcc_token))
{
*compiler_flag[f].enabled = st;
if (compiler_flag[f].enabled == &flag_cpriority)
QCC_PrioritiseOpcodes();
if (compiler_flag[f].flags & FLAG_MIDCOMPILE)
{
*compiler_flag[f].enabled = st;
if (compiler_flag[f].enabled == &flag_cpriority)
QCC_PrioritiseOpcodes();
}
else
QCC_PR_ParseWarning(WARN_BADPRAGMA, "Cannot enable/disable keyword/flag via a pragma");
break;
}
else
QCC_PR_ParseWarning(WARN_BADPRAGMA, "Cannot enable/disable keyword/flag via a pragma");
break;
}
if (!compiler_flag[f].enabled)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "keyword/flag %s not recognised", qcc_token);
}
if (!compiler_flag[f].enabled)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "keyword/flag %s not recognised", qcc_token);
}
}
else if (!QC_strcasecmp(qcc_token, "warning"))
@ -1392,21 +1432,28 @@ static pbool QCC_PR_Precompiler(void)
if (st>=0)
{
int wn;
s = QCC_COM_Parse(s);
wn = QCC_WarningForName(qcc_token);
if (wn < 0)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
else
while ((s = QCC_COM_Parse(s)))
{
if (st == 3) //toggle
qccwarningaction[wn] = !!qccwarningaction[wn];
wn = QCC_WarningForName(qcc_token);
if (wn < 0)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "warning id not recognised");
else
qccwarningaction[wn] = st;
{
if (st == 3) //toggle
qccwarningaction[wn] = !!qccwarningaction[wn];
else
qccwarningaction[wn] = st;
}
}
}
}
else
{
QCC_PR_SkipToEndOfLine(false);
QCC_PR_ParseWarning(WARN_BADPRAGMA, "Unknown pragma \'%s\'", qcc_token);
}
QCC_PR_SkipToEndOfLine(true);
}
return true;
}
@ -1445,98 +1492,6 @@ PR_LexString
Parses a quoted string
==============
*/
#if 0
void QCC_PR_LexString (void)
{
int c;
int len;
char tmpbuf[2048];
char *text;
char *oldf;
int oldline;
bool fromfile = true;
len = 0;
text = pr_file_p;
do
{
QCC_COM_Parse(text);
// print("Next token is \"%s\"\n", com_token);
if (*text == '\"')
{
text++;
if (fromfile) pr_file_p++;
}
do
{
c = *text++;
if (fromfile) pr_file_p++;
if (!c)
QCC_PR_ParseError ("EOF inside quote");
if (c=='\n')
QCC_PR_ParseError ("newline inside quote");
if (c=='\\')
{ // escape char
c = *text++;
if (fromfile) pr_file_p++;
if (!c)
QCC_PR_ParseError ("EOF inside quote");
if (c == 'n')
c = '\n';
else if (c == '"')
c = '"';
else if (c == '\\')
c = '\\';
else
QCC_PR_ParseError ("Unknown escape char");
}
else if (c=='\"')
{
if (fromfile) pr_file_p++;
break;
}
tmpbuf[len] = c;
len++;
} while (1);
tmpbuf[len] = 0;
// if (fromfile) pr_file_p++;
pr_immediate_type=NULL;
oldline=pr_source_line;
oldf=pr_file_p;
QCC_PR_Lex();
if (pr_immediate_type == &type_string)
{
// print("Appending \"%s\" to \"%s\"\n", pr_immediate_string, tmpbuf);
strcat(tmpbuf, pr_immediate_string);
len+=strlen(pr_immediate_string);
}
else
{
pr_source_line = oldline;
pr_file_p = oldf-1;
QCC_PR_LexWhitespace();
if (*pr_file_p != '\"') //annother string
break;
}
QCC_PR_LexWhitespace();
text = pr_file_p;
} while (1);
strcpy(pr_token, tmpbuf);
pr_token_type = tt_immediate;
pr_immediate_type = &type_string;
strcpy (pr_immediate_string, pr_token);
pr_immediate_strlen = strlen(pr_immediate_string);
// print("Found \"%s\"\n", pr_immediate_string);
}
#else
int QCC_PR_LexEscapedCodepoint(void)
{ //for "\foo" or '\foo' handling.
//caller will have read the \ already.
@ -1759,7 +1714,7 @@ void QCC_PR_LexString (void)
}
else if ((*pr_file_p == 'U' || *pr_file_p == 'u' || *pr_file_p == 'L') && pr_file_p[1] == '\"')
{ //unicode string, char32_t, char16_t, wchar_t respectively. we spit out utf-8 regardless.
QCC_PR_ParseWarning(WARN_NOTUTF8, "interpretting char32_t/char16_t/wchar_t as utf-8");
QCC_PR_ParseWarning(WARN_NOTUTF8, "char32_t/char16_t/wchar_t strings are not supported, treating as u8 prefix (as utf-8)");
stringtype = 2;
pr_file_p+=2;
}
@ -1823,22 +1778,22 @@ void QCC_PR_LexString (void)
c = 0xe01c | texttype;
}
else if (c == 'u' || c == 'U')
{
{ //special hack, \u is a utf-8 code regardless of output encoding...
c = QCC_PR_LexEscapedCodepoint();
goto forceutf8;
}
else if (c == 'x' || c == 'X')
{
{ //special hack, \xXX in a string is an explicit byte regardless of encoding.
c = QCC_PR_LexEscapedCodepoint();
if (c > 0xff)
QCC_PR_ParseWarning(ERR_BADCHARACTERCODE, "Bad unicode character code - codepoint %u is above 0xFF", c);
// if (c > 0xff)
// QCC_PR_ParseWarning(ERR_BADCHARACTERCODE, "Bad unicode character code - codepoint %#x is above 0xFF", c);
goto forcebyte;
}
else
{
c = QCC_PR_LexEscapedCodepoint();
if (stringtype != 2 && c > 0xff)
QCC_PR_ParseWarning(ERR_BADCHARACTERCODE, "Bad legacy character code - codepoint %u is above 0xFF", c);
// if (stringtype != 2 && c > 0xff)
// QCC_PR_ParseWarning(ERR_BADCHARACTERCODE, "Bad legacy character code - codepoint %#x is above 0xFF", c);
}
}
else if (c=='\"')
@ -2019,7 +1974,6 @@ forcebyte:
}
}*/
}
#endif
/*
==============
@ -2120,7 +2074,7 @@ static void QCC_PR_LexNumber (void)
{
pr_token[tokenlen++] = c;
pr_file_p++;
pr_immediate_type = type_float;
pr_immediate_type = flag_assume_double?type_double:type_float;
while(1)
{
c = *pr_file_p;
@ -2128,11 +2082,17 @@ static void QCC_PR_LexNumber (void)
{
pr_token[tokenlen++] = c;
}
else if (c == 'f')
else if (c == 'f' || c == 'F')
{
pr_file_p++;
break;
}
else if (c == 'd' || c == 'D')
{
pr_immediate_type = type_double;
pr_file_p++;
break;
}
else
{
break;
@ -2140,10 +2100,13 @@ static void QCC_PR_LexNumber (void)
pr_file_p++;
}
pr_token[tokenlen++] = 0;
pr_immediate._float = (float)atof(pr_token);
return;
if (pr_immediate_type == type_double)
pr_immediate._double = atof(pr_token);
else
pr_immediate._float = (float)atof(pr_token);
goto checkjunk;
}
else if (c == 'f')
else if (c == 'f' || c == 'F')
{
pr_token[tokenlen++] = c;
pr_token[tokenlen++] = 0;
@ -2154,23 +2117,71 @@ static void QCC_PR_LexNumber (void)
num*=sign;
if ((longlong)pr_immediate._float != (longlong)num)
QCC_PR_ParseWarning(WARN_OVERFLOW, "numerical overflow");
return;
goto checkjunk;
}
else if (c == 'i' || c == 'u')
{
else if (c == 'd' || c == 'D')
{ //note: conflicts with hex. add a dot before it or something.
pr_token[tokenlen++] = c;
pr_token[tokenlen++] = 0;
pr_file_p++;
pr_immediate_type = type_integer;
pr_immediate._int = num*sign;
pr_immediate_type = type_double;
pr_immediate._double = num*sign;
num*=sign;
if ((longlong)pr_immediate._int != (longlong)num)
{
if (((longlong)pr_immediate._int & LL(0xffffffff80000000)) != LL(0xffffffff80000000))
QCC_PR_ParseWarning(WARN_OVERFLOW, "numerical overflow");
if ((longlong)pr_immediate._double != (longlong)num)
QCC_PR_ParseWarning(WARN_OVERFLOW, "numerical overflow");
goto checkjunk;
}
else if (c == 'i' || c == 'u' || c == 'l' || c == 'I' || c == 'U' || c == 'L')
{ //length and sign flags can be any order. LL suffix must have the same case (but not necessarily match the sign suffix)
int isunsigned;
int islong = (c == 'l')||(c == 'L');
pr_token[tokenlen++] = c;
pr_file_p++;
if (islong)
{ //length suffix was first.
//long-long?
if (*pr_file_p == c)
pr_token[tokenlen++] = *pr_file_p++;
//check for signed suffix...
c = *pr_file_p;
isunsigned = (c == 'u')||(c=='U');
if (c == 'i' || c == 'I' || isunsigned) //ignore an explicit redundant 'i' char, for not-a-float.
pr_token[tokenlen++] = *pr_file_p++;
}
return;
else
{
isunsigned = (c == 'u')||(c=='U');
//we already made sure it u or i, and its not an l
c = *pr_file_p;
if (c == 'l' || c == 'L')
{
pr_token[tokenlen++] = *pr_file_p++;
islong = true;
//long-long?
if (*pr_file_p == c)
pr_token[tokenlen++] = *pr_file_p++;
}
}
pr_token[tokenlen++] = 0;
num *= sign;
if (islong)
{
pr_immediate_type = (isunsigned)?type_uint64:type_int64;
pr_immediate._int64 = num;
}
else
{
pr_immediate_type = (isunsigned)?type_uint:type_integer;
pr_immediate._int = num;
if ((longlong)pr_immediate._int != (longlong)num)
{
if (((longlong)pr_immediate._int & LL(0xffffffff80000000)) != LL(0xffffffff80000000))
QCC_PR_ParseWarning(WARN_OVERFLOW, "numerical overflow");
}
}
goto checkjunk;
}
else
break;
@ -2217,6 +2228,11 @@ qccxhex:
if ((longlong)pr_immediate._float != (longlong)num && base == 16)
QCC_PR_ParseWarning(WARN_OVERFLOW, "numerical overflow %lld will be rounded to %f", num, pr_immediate._float);
}
checkjunk:
c = *pr_file_p;
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || (c & 0x80))
QCC_PR_ParseWarning(ERR_NOTANUMBER, "bad suffix on number %s", pr_token);
}
@ -3960,7 +3976,7 @@ Aborts the current file load
void editbadfile(const char *file, int line);
#endif
//will abort.
void VARGS QCC_PR_ParseError (int errortype, const char *error, ...)
NORETURN void VARGS QCC_PR_ParseError (int errortype, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -3982,7 +3998,7 @@ void VARGS QCC_PR_ParseError (int errortype, const char *error, ...)
longjmp (pr_parse_abort, 1);
}
//will abort.
void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char *error, ...)
NORETURN void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -4005,7 +4021,7 @@ void VARGS QCC_PR_ParseErrorPrintDef (int errortype, QCC_def_t *def, const char
longjmp (pr_parse_abort, 1);
}
void VARGS QCC_PR_ParseErrorPrintSRef (int errortype, QCC_sref_t def, const char *error, ...)
NORETURN void VARGS QCC_PR_ParseErrorPrintSRef (int errortype, QCC_sref_t def, const char *error, ...)
{
va_list argptr;
char string[1024];
@ -4632,6 +4648,35 @@ char *TypeName(QCC_type_t *type, char *buffer, int buffersize)
Q_strlcat(buffer, "void", buffersize);
return buffer;
}
if (type->type == ev_enum)
{
if (buffersize < 0)
return buffer;
*buffer = 0;
Q_strlcat(buffer, "enum ", buffersize);
Q_strlcat(buffer, type->name, buffersize);
Q_strlcat(buffer, ":", buffersize);
TypeName(type->aux_type, buffer+strlen(buffer), buffersize-strlen(buffer));
return buffer;
}
if (type->type == ev_struct)
{
if (buffersize < 0)
return buffer;
*buffer = 0;
Q_strlcat(buffer, "struct ", buffersize);
Q_strlcat(buffer, type->name, buffersize);
return buffer;
}
if (type->type == ev_union)
{
if (buffersize < 0)
return buffer;
*buffer = 0;
Q_strlcat(buffer, "union ", buffersize);
Q_strlcat(buffer, type->name, buffersize);
return buffer;
}
if (type->type == ev_pointer)
{
@ -4953,8 +4998,18 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
if (QCC_PR_CheckToken("["))
{
QCC_PR_ParseError(0, "Array arguments are not supported\n");
QCC_PR_Expect("]");
if (QCC_PR_CheckToken("]")) //length omitted. just treat it as a pointer...?
{
QCC_PR_ParseError(0, "unsized array argument\n");
paramlist[numparms].type = QCC_PointerTypeTo(paramlist[numparms].type);
}
else
{ //proper array
paramlist[numparms].arraysize = QCC_PR_IntConstExpr();
if (!paramlist[numparms].arraysize)
QCC_PR_ParseError(ERR_NOTANAME, "cannot cope with 0-sized arrays");
QCC_PR_Expect("]");
}
}
}
else if (definenames)
@ -5153,6 +5208,12 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
// int ofs;
if (QCC_PR_CheckKeyword(keyword_const, "const"))
{
QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "ignoring unsupported const keyword");
silentfail = false; //FIXME
}
if (QCC_PR_PeekToken ("...") ) //this is getting stupid
{
QCC_PR_LexWhitespace (false);
@ -5875,20 +5936,13 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
return NULL;
}
//FIXME: these should be moved into parsetype
if (QCC_PR_CheckKeyword(keyword_enum, "enum"))
{
newt = QCC_PR_ParseEnum(false);
if (QCC_PR_CheckToken(";"))
return NULL;
return newt;
return QCC_PR_ParseEnum(false);
}
if (QCC_PR_CheckKeyword(keyword_enumflags, "enumflags"))
{
newt = QCC_PR_ParseEnum(true);
if (QCC_PR_CheckToken(";"))
return NULL;
return newt;
return QCC_PR_ParseEnum(true);
}
structtype = ev_void;
@ -6039,6 +6093,15 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QCC_PR_ParseError(ERR_NOTANAME, "cannot cope with 0-sized arrays");
QCC_PR_Expect("]");
}
while (QCC_PR_CheckToken("["))
{
int nsize=QCC_PR_IntConstExpr();
if (!nsize)
QCC_PR_ParseError(ERR_NOTANAME, "cannot cope with 0-sized arrays");
QCC_PR_Expect("]");
arraysize *= nsize;
QCC_PR_ParseWarning(WARN_IGNOREDKEYWORD, "multi-dimensional arrays are not supported. flattening to single array.");
}
if (QCC_PR_CheckToken("("))
type = QCC_PR_ParseFunctionType(false, type);
@ -6050,6 +6113,12 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
continue;
}
if (QCC_PR_CheckToken(":"))
{
QCC_PR_IntConstExpr();
QCC_PR_ParseWarning(WARN_IGNOREDKEYWORD, "bitfields are not supported");
}
if ((isnonvirt || isvirt) && type->type != ev_function)
QCC_PR_ParseWarning(ERR_INTERNAL, "[non]virtual members must be functions", type->name);
@ -6175,6 +6244,78 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
type = type_function;
else
{
//try and handle C's types, which have weird and obtuse combinations (like long long, long int, short int).
pbool isokay = false;
pbool issigned = false;
pbool isunsigned = false;
pbool islong = false;
pbool isfloat = false;
int bits = 0;
while(true)
{
if (!isunsigned && !issigned && QCC_PR_CheckKeyword(keyword_signed, "signed"))
issigned = isokay = true;
else if (!issigned && !isunsigned && QCC_PR_CheckKeyword(keyword_unsigned, "unsigned"))
isunsigned = isokay = true;
else if (!bits && QCC_PR_CheckKeyword(keyword_long, "long"))
{
if (islong)
bits = 128;
islong = isokay = true;
}
else if ((!bits || bits==16) && (QCC_PR_CheckKeyword(keyword_int, "int") || QCC_PR_CheckKeyword(keyword_integer, "integer")))
{ //long int, short int, etc are allowed
if (!bits)
bits = 32;
isokay = true;
}
else if (!bits && QCC_PR_CheckKeyword(keyword_short, "short"))
bits = 16, isokay = true;
else if (!bits && QCC_PR_CheckKeyword(keyword_char, "char"))
bits = 8, isokay = true;
else if (!bits && QCC_PR_CheckKeyword(keyword_int, "_Bool")) //c99
bits = 1, isokay = true;
else if (!bits && !islong && QCC_PR_CheckKeyword(keyword_float, "float"))
bits = 32, isfloat = isokay = true;
else if ((!bits||islong) && QCC_PR_CheckKeyword(keyword_double, "double"))
bits = islong?128:64, islong=false, isfloat = isokay = true;
else
break;
}
if (isokay)
{
if (!bits)
bits = islong?64:32; //<signed|unsigned|long> [int]
if (isfloat)
{
if (isunsigned)
QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "ignoring unsupported unsigned keyword, type will be signed");
if (bits > 64)
type = type_double, QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "long doubles are not supported, using double"); //permitted
else if (bits == 64)
type = type_double;
else
type = type_float;
}
else
{
if (bits > 64)
type = (isunsigned?type_uint64:type_int64), QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "long longs are not supported, using long"); //permitted
else if (bits == 64)
type = (isunsigned?type_uint64:type_int64);
else if (bits == 16)
type = (isunsigned?type_uint:type_integer), QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "shorts are not supported, using int"); //permitted
else if (bits == 8)
type = (isunsigned?type_uint:type_integer), QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "chars are not supported, using int"); //permitted
else
type = (isunsigned?type_uint:type_integer);
}
goto wasctype;
}
if (silentfail)
return NULL;
@ -6183,11 +6324,16 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
}
}
QCC_PR_Lex ();
wasctype:
while (QCC_PR_CheckToken("*"))
{
if (QCC_PR_CheckKeyword(keyword_const, "const"))
QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "ignoring unsupported const keyword");
type = QCC_PointerTypeTo(type);
}
if (QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function.
if (flag_qcfuncs && QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function.
{
type_inlinefunction = true;
type = QCC_PR_ParseFunctionType(newtype, type);

View file

@ -1701,6 +1701,7 @@ private:
connect(fileopen, &QAction::triggered, [=]()
{
GUIprintf("Ctrl+O hit\n");
QMessageBox::critical(nullptr, "Error", QString::asprintf("Not yet implemented"));
});
auto filesave = new QAction(tr("Save"), this);
fileMenu->addAction(filesave);

View file

@ -77,7 +77,7 @@ pbool newstylesource;
char destfile[1024]; //the file we're going to output to
pbool destfile_explicit; //destfile was override on the commandline, don't let qc change it.
QCC_eval_t *qcc_pr_globals;
QCC_eval_basic_t *qcc_pr_globals;
unsigned int numpr_globals;
char *strings;
@ -235,6 +235,7 @@ struct {
{" F330", WARN_MUTEDEPRECATEDVARIABLE},
{" F331", WARN_SELFNOTTHIS},
{" F332", WARN_DIVISIONBY0},
{" F333", WARN_ARGUMENTCHECK},
{" F207", WARN_NOTREFERENCEDFIELD},
{" F208", WARN_NOTREFERENCEDCONST},
@ -342,6 +343,12 @@ compiler_flag_t compiler_flag[] = {
{&keyword_goto, defaultkeyword, "goto", "Keyword: goto", "Disables the 'goto' keyword."},
{&keyword_int, typekeyword, "int", "Keyword: int", "Disables the 'int' keyword."},
{&keyword_integer, typekeyword, "integer", "Keyword: integer", "Disables the 'integer' keyword."},
{&keyword_double, defaultkeyword, "double", "Keyword: double", "Disables the 'double' keyword."},
{&keyword_long, defaultkeyword, "long", "Keyword: long", "Disables the 'long' keyword."},
{&keyword_short, defaultkeyword, "short", "Keyword: short", "Disables the 'short' keyword."},
{&keyword_char, defaultkeyword, "char", "Keyword: char", "Disables the 'char' keyword."},
{&keyword_signed, defaultkeyword, "signed", "Keyword: signed", "Disables the 'signed' keyword."},
{&keyword_unsigned, defaultkeyword, "unsigned", "Keyword: unsigned", "Disables the 'unsigned' keyword."},
{&keyword_noref, defaultkeyword, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't warn about it.
{&keyword_unused, nondefaultkeyword, "unused", "Keyword: unused", "Disables the 'unused' keyword. 'unused' means that the variable is unused, you're aware that its unused, and you'd rather not know about all the warnings this results in."},
{&keyword_used, nondefaultkeyword, "used", "Keyword: used", "Disables the 'used' keyword. 'used' means that the variable is used even if the qcc can't see how - thus preventing it from ever being stripped."},
@ -374,7 +381,7 @@ compiler_flag_t compiler_flag[] = {
//options
{&flag_acc, 0, "acc", "Reacc support", "Reacc is a pascall like compiler. It was released before the Quake source was released. This flag has a few effects. It sorts all qc files in the current directory into alphabetical order to compile them. It also allows Reacc global/field distinctions, as well as allows | for linebreaks. Whilst case insensitivity and lax type checking are supported by reacc, they are seperate compiler flags in fteqcc."}, //reacc like behaviour of src files.
{&flag_qccx, FLAG_MIDCOMPILE,"qccx", "QCCX syntax", "WARNING: This syntax makes mods inherantly engine specific.\nDo NOT use unless you know what you're doing.This is provided for compatibility only\nAny entity hacks will be unsupported in FTEQW, DP, and others, resulting in engine crashes if the code in question is executed."},
{&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, defaultflag, "kce", "Keywords Coexist", "If you want keywords to NOT be disabled when they a variable by the same name is defined, check here."},
// {&flag_lno, defaultflag, "lno", "Write Line Numbers", "Writes line number information. This is required for any real kind of debugging. Will be ignored if filenames were stripped."},
{&output_parms, 0, "parms", "Define offset parms", "if PARM0 PARM1 etc should be defined by the compiler. These are useful if you make use of the asm keyword for function calls, or you wish to create your own variable arguments. This is an easy way to break decompilers."}, //controls weather to define PARMx for the parms (note - this can screw over some decompilers)
{&autoprototype, 0, "autoproto", "Automatic Prototyping","Causes compilation to take two passes instead of one. The first pass, only the definitions are read. The second pass actually compiles your code. This means you never have to remember to prototype functions again."}, //so you no longer need to prototype functions and things in advance.
@ -404,6 +411,8 @@ compiler_flag_t compiler_flag[] = {
{&flag_assumevar, hideflag, "assumevar", "explicit consts", "Initialised globals will be considered non-const by default."},
{&flag_dblstarexp, hideflag, "ssp", "** exponent", "Treat ** as an operator for exponents, instead of multiplying by a dereferenced pointer."},
{&flag_cpriority, hideflag, "cpriority", "C Operator Priority", "QC treats !a&&b as equivelent to !(a&&b). When this is set, behaviour will be (!a)&&b as in C. Other operators are also affected in similar ways."},
{&flag_assume_double, hideflag, "assumedouble", "Assume Doubles", "Floating point immediates will be treated as doubles, for C compat."},
{&flag_qcfuncs, hidedefaultflag,"qcfuncs", "Parse QC-style funcs", "Recognise void() as a function type. Required for QC compat."},
{&flag_allowuninit, hideflag, "allowuninit", "Uninitialised Locals", "Permit optimisations that may result in locals being uninitialised. This may allow for greater reductions in temps."},
{&flag_nopragmafileline,FLAG_MIDCOMPILE,"nofileline", "Ignore #pragma file", "Ignores #pragma file(foo) and #pragma line(foo), so that errors and symbols reflect the actual lines, instead of the original source."},
// {&flag_lno, hidedefaultflag,"lno", "Gen Debugging Info", "Writes debugging info."},
@ -711,7 +720,7 @@ static void QCC_DumpAutoCvars (const char *outputname)
if (!strncmp(n, "autocvar_", 9))
{
char *desc;
QCC_eval_t *val = &qcc_pr_globals[d->ofs];
const QCC_eval_t *val = (const QCC_eval_t*)&qcc_pr_globals[d->ofs];
QCC_def_t *def = QCC_PR_GetDef(NULL, n, NULL, false, 0, 0);
n += 9;
@ -725,17 +734,29 @@ static void QCC_DumpAutoCvars (const char *outputname)
case ev_float:
snprintf(line, sizeof(line), "set %s\t%g%s%s\n", n, val->_float, desc?"\t//":"", desc?desc:"");
break;
case ev_double:
snprintf(line, sizeof(line), "set %s\t%g%s%s\n", n, val->_double, desc?"\t//":"", desc?desc:"");
break;
case ev_vector:
snprintf(line, sizeof(line), "set %s\t\"%g %g %g\"%s%s\n", n, val->vector[0], val->vector[1], val->vector[2], desc?"\t//":"", desc?desc:"");
snprintf(line, sizeof(line), "set %s\t\"%g %g %g\"%s%s\n", n, val->vector[0], val->vector[1], val->vector[2], desc?"\t//":"", desc?desc:"");
break;
case ev_integer:
snprintf(line, sizeof(line), "set %s\t%"pPRIi"%s%s\n", n, val->_int, desc?"\t//":"", desc?desc:"");
snprintf(line, sizeof(line), "set %s\t%"pPRIi"%s%s\n", n, val->_int, desc?"\t//":"", desc?desc:"");
break;
case ev_uint:
snprintf(line, sizeof(line), "set %s\t%"pPRIu"%s%s\n", n, val->_uint, desc?"\t//":"", desc?desc:"");
break;
case ev_int64:
snprintf(line, sizeof(line), "set %s\t%"pPRIi64"%s%s\n", n, val->_int64, desc?"\t//":"", desc?desc:"");
break;
case ev_uint64:
snprintf(line, sizeof(line), "set %s\t%"pPRIu64"%s%s\n", n, val->_uint64, desc?"\t//":"", desc?desc:"");
break;
case ev_string:
snprintf(line, sizeof(line), "set %s\t\"%s\"%s%s\n", n, strings + val->_int, desc?"\t//":"", desc?desc:"");
break;
default:
snprintf(line, sizeof(line), "//set %s\t ?%s%s\n", n, desc?"\t//":"", desc?desc:"");
snprintf(line, sizeof(line), "//set %s\t ?%s%s\n", n, desc?"\t//":"", desc?desc:"");
break;
}
SafeWrite(h, line, strlen(line));
@ -2640,7 +2661,7 @@ strofs = (strofs+3)&~3;
externs->Printf("Compile finished: %s (uhexen2 format)\n", destfile);
break;
case QCF_DARKPLACES:
externs->Printf("Compile finished: %s (patched-dp format)\n", destfile);
externs->Printf("Compile finished: %s (fte+dp format)\n", destfile);
break;
case QCF_QSS:
externs->Printf("Compile finished: %s (fte+qss format)\n", destfile);
@ -3273,6 +3294,7 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
type_void = QCC_PR_NewType("void", ev_void, true);
type_string = QCC_PR_NewType("string", ev_string, true);
type_float = QCC_PR_NewType("float", ev_float, true);
type_double = QCC_PR_NewType("__double", ev_double, true);
type_vector = QCC_PR_NewType("vector", ev_vector, true);
type_entity = QCC_PR_NewType("entity", ev_entity, true);
type_field = QCC_PR_NewType("__field", ev_field, false);
@ -3280,6 +3302,9 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
type_function->aux_type = type_void;
type_pointer = QCC_PR_NewType("__pointer", ev_pointer, false);
type_integer = QCC_PR_NewType("__int", ev_integer, true);
type_uint = QCC_PR_NewType("__uint", ev_uint, true);
type_int64 = QCC_PR_NewType("__int64", ev_int64, true);
type_uint64 = QCC_PR_NewType("__uint64", ev_int64, true);
type_variant = QCC_PR_NewType("__variant", ev_variant, true);
type_floatfield = QCC_PR_NewType("__fieldfloat", ev_field, false);
@ -3293,6 +3318,11 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
type_floatfunction = QCC_PR_NewType("__floatfunction", ev_function, false);
type_floatfunction->aux_type = type_float;
type_bfloat = QCC_PR_NewType("__bfloat", ev_boolean, false);
type_bfloat->parentclass = type_float;
type_bint = QCC_PR_NewType("__bint", ev_boolean, false);
type_bint->parentclass = type_integer;
//type_field->aux_type = type_float;
// QCC_PR_NewType("_Bool", ev_boolean, true);
@ -3300,8 +3330,6 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
// QCC_PR_NewType("__int", ev_integer, keyword_integer?true:false);
QCC_PR_NewType("variant", ev_variant, true);
QCC_PR_NewType("integer", ev_integer, keyword_integer?true:false);
QCC_PR_NewType("int", ev_integer, keyword_int?true:false);
@ -4297,7 +4325,7 @@ static void QCC_PR_CommandLinePrecompilerOptions (void)
else
*compiler_flag[p].enabled = false;
}
if (!stricmp(myargv[i]+5, "C"))
if (!stricmp(myargv[i]+5, "C") || !stricmp(myargv[i]+5, "c89") || !stricmp(myargv[i]+5, "c90") || !stricmp(myargv[i]+5, "c99") || !stricmp(myargv[i]+5, "c11") || !stricmp(myargv[i]+5, "c17"))
{ //set up for greatest C compatibility... variations from C are bugs, not features.
keyword_asm = false;
keyword_break = keyword_continue = keyword_for = keyword_goto = keyword_const = keyword_extern = keyword_static = true;
@ -4315,13 +4343,32 @@ static void QCC_PR_CommandLinePrecompilerOptions (void)
flag_assumevar = true; //const only if explicitly const.
pr_subscopedlocals = true; //locals shadow other locals rather than being the same one.
flag_cpriority = true; //fiddle with operator precedence.
flag_assume_integer = true;
flag_assume_integer = true; //unqualified numeric constants are assumed to be ints, consistent with C.
flag_assume_double = true; //and any immediates with a decimal points are assumed to be doubles, consistent with C.
flag_qcfuncs = false;
qccwarningaction[WARN_UNINITIALIZED] = WA_WARN; //C doesn't like that, might as well warn here too.
qccwarningaction[WARN_TOOMANYPARAMS] = WA_ERROR; //too many args to function is weeeeird.
qccwarningaction[WARN_TOOFEWPARAMS] = WA_ERROR; //missing args should be fatal.
qccwarningaction[WARN_ASSIGNMENTTOCONSTANT] = WA_ERROR; //const is const. at least its not const by default.
qccwarningaction[WARN_SAMENAMEASGLOBAL] = WA_IGNORE; //shadowing of globals.
if (!stricmp(myargv[i]+5, "c89") || !stricmp(myargv[i]+5, "c90"))
val = "199409L"; //it was ammended, apparently.
else if (!stricmp(myargv[i]+5, "c99"))
val = "199901L";
else if (!stricmp(myargv[i]+5, "c11"))
val = "201112L";
else if (!stricmp(myargv[i]+5, "c17"))
val = "201710L";
else
val = NULL;
cnst = QCC_PR_DefineName("__STDC_VERSION__");
if (val)
{
cnst->value = qccHunkAlloc(strlen(val)+1);
memcpy(cnst->value, val, strlen(val)+1);
}
}
else if (!strcmp(myargv[i]+5, "qccx"))
{
@ -4647,6 +4694,7 @@ static void QCC_SetDefaultProperties (void)
QCC_PR_CloseProcessor();
QCC_PR_DefineName("FTEQCC");
QCC_PR_DefineName("__FTEQCC__");
if ((FWDSLASHARGS && QCC_CheckParm("/O0")) || QCC_CheckParm("-O0"))
level = 0;

View file

@ -5395,6 +5395,59 @@ void QCBUILTIN PF_WriteInt (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
}
}
void QCBUILTIN PF_WriteInt64 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int dest = G_FLOAT(OFS_PARM0);
pint64_t val = G_INT64(OFS_PARM1);
if (dest == MSG_CSQC)
{ //csqc buffers are always written.
MSG_WriteInt64(&csqcmsgbuffer, val);
return;
}
if (pr_nonetaccess.value)
return;
#ifdef SERVER_DEMO_PLAYBACK
if (sv.demofile)
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
{
NPP_NQWriteLong(dest, val&0xffffffff);
NPP_NQWriteLong(dest, (val>>32)&0xffffffff);
return;
}
#ifdef NQPROT
else
{
NPP_QWWriteLong(dest, val&0xffffffff);
NPP_QWWriteLong(dest, (val>>32)&0xffffffff);
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
if (!cl)
return;
ClientReliableCheckBlock(cl, 8);
ClientReliableWrite_Int64(cl, val);
}
else
{
if (progstype != PROG_QW)
MSG_WriteInt64 (NQWriteDest(dest), val);
else
MSG_WriteInt64 (QWWriteDest(dest), val);
}
}
void QCBUILTIN PF_WriteAngle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int dest = G_FLOAT(OFS_PARM0);
@ -5559,6 +5612,63 @@ void QCBUILTIN PF_WriteFloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
}
}
void QCBUILTIN PF_WriteDouble (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int dest = G_FLOAT(OFS_PARM0);
double val = G_DOUBLE(OFS_PARM1);
union {
double val;
quint64_t ival;
} u = {val};
if (dest == MSG_CSQC)
{ //csqc buffers are always written.
MSG_WriteDouble(&csqcmsgbuffer, val);
return;
}
if (pr_nonetaccess.value)
return;
#ifdef SERVER_DEMO_PLAYBACK
if (sv.demofile)
return;
#endif
#ifdef NETPREPARSE
if (dpcompat_nopreparse.ival)
;
else if (progstype != PROG_QW)
{
NPP_NQWriteLong(dest, u.ival&0xffffffff);
NPP_NQWriteLong(dest, (u.ival>>32)&0xffffffff);
return;
}
#ifdef NQPROT
else
{
NPP_QWWriteLong(dest, u.ival&0xffffffff);
NPP_QWWriteLong(dest, (u.ival>>32)&0xffffffff);
return;
}
#endif
#endif
if (dest == MSG_ONE)
{
client_t *cl = Write_GetClient();
if (!cl)
return;
ClientReliableCheckBlock(cl, 8);
ClientReliableWrite_Double(cl, val);
}
else
{
if (progstype != PROG_QW)
MSG_WriteDouble (NQWriteDest(dest), val);
else
MSG_WriteDouble (QWWriteDest(dest), val);
}
}
void PF_WriteString_Internal (int target, const char *str)
{
if (target == MSG_CSQC)
@ -11006,7 +11116,9 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"touchtriggers", PF_touchtriggers, 0, 0, 0, 279, D("void(optional entity ent, optional vector neworigin)", "Triggers a touch events between self and every SOLID_TRIGGER entity that it is in contact with. This should typically just be the triggers touch functions. Also optionally updates the origin of the moved entity.")},//
{"WriteFloat", PF_WriteFloat, 0, 0, 0, 280, D("void(float buf, float fl)", "Writes a full 32bit float without any data conversions at all, for full precision.")},//
{"WriteInt", PF_WriteInt, 0, 0, 0, 0, D("void(float buf, int fl)", "Equivelent to WriteLong, but doesn't truncate to a float first before converting back to an int.")},//
{"WriteDouble", PF_WriteDouble, 0, 0, 0, 0, D("void(float buf, __double dbl)", "Writes a full 64bit double-precision float without any data conversions at all, for excessive precision.")},//
{"WriteInt", PF_WriteInt, 0, 0, 0, 0, D("void(float buf, int fl)", "Writes all 4 bytes of a 32bit integer without truncating to a float first before converting back to an int (unlike WriteLong does, but otherwise equivelent).")},//
{"WriteInt64", PF_WriteInt64, 0, 0, 0, 0, D("void(float buf, __int64 fl)", "Writes all 8 bytes of a 64bit integer.")},//
{"skel_ragupdate", PF_skel_ragedit, 0, 0, 0, 281, D("float(entity skelent, string dollcmd, float animskel)", "Updates the skeletal object attached to the entity according to its origin and other properties.\nif animskel is non-zero, the ragdoll will animate towards the bone state in the animskel skeletal object, otherwise they will pick up the model's base pose which may not give nice results.\nIf dollcmd is not set, the ragdoll will update (this should be done each frame).\nIf the doll is updated without having a valid doll, the model's default .doll will be instanciated.\ncommands:\n doll foo.doll : sets up the entity to use the named doll file\n dollstring TEXT : uses the doll file directly embedded within qc, with that extra prefix.\n cleardoll : uninstanciates the doll without destroying the skeletal object.\n animate 0.5 : specifies the strength of the ragdoll as a whole \n animatebody somebody 0.5 : specifies the strength of the ragdoll on a specific body (0 will disable ragdoll animations on that body).\n enablejoint somejoint 1 : enables (or disables) a joint. Disabling joints will allow the doll to shatter.")}, // (FTE_CSQC_RAGDOLL)
{"skel_mmap", PF_skel_mmap, 0, 0, 0, 282, D("float*(float skel)", "Map the bones in VM memory. They can then be accessed via pointers. Each bone is 12 floats, the four vectors interleaved (sadly).")},// (FTE_QC_RAGDOLL)
{"skel_set_bone_world",PF_skel_set_bone_world,0,0, 0, 283, D("void(entity ent, float bonenum, vector org, optional vector angorfwd, optional vector right, optional vector up)", "Sets the world position of a bone within the given entity's attached skeletal object. The world position is dependant upon the owning entity's position. If no orientation argument is specified, v_forward+v_right+v_up are used for the orientation instead. If 1 is specified, it is understood as angles. If 3 are specified, they are the forawrd/right/up vectors to use.")},
@ -11147,7 +11259,9 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"readangle", PF_Fixme, 0, 0, 0, 365, D("float()", "Reads a value matching the unspecified precision written ONLY by WriteAngle.")},// (EXT_CSQC)
{"readstring", PF_Fixme, 0, 0, 0, 366, D("string()", "Reads a null-terminated string.")},// (EXT_CSQC)
{"readfloat", PF_Fixme, 0, 0, 0, 367, D("float()", "Reads a float without any truncation nor conversions. Data MUST have originally been written with WriteFloat.")},// (EXT_CSQC)
{"readdouble", PF_Fixme, 0, 0, 0, 0, D("__double()", "Reads a double-precision float without any truncation nor conversions. Data MUST have originally been written with WriteDouble.")},// (EXT_CSQC)
{"readint", PF_Fixme, 0, 0, 0, 0, D("int()", "Reads a 32bit int without any conversions to float, otherwise interchangable with readlong.")},// (EXT_CSQC)
{"readint64", PF_Fixme, 0, 0, 0, 0, D("__int64()", "Reads a 64bit int. Paired with WriteInt64.")},// (EXT_CSQC)
{"readentitynum", PF_Fixme, 0, 0, 0, 368, D("float()", "Reads the serverside index of an entity, paired with WriteEntity. There may be nothing else known about the entity yet, so the result typically needs to be saved as-is and re-looked up each frame. This can be done via getentity(NUM, GE_*) for non-csqc ents, or findentity(world,entnum,NUM) - both of which can fail due to latency.")},// (EXT_CSQC)
// {"readserverentitystate",PF_Fixme,0, 0, 0, 369, "void(float flags, float simtime)"},// (EXT_CSQC_1)
@ -11330,7 +11444,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"strlennocol", PF_strlennocol, 0, 0, 0, 476, D("float(string s)", "Returns the number of characters in the string after any colour codes or other markup has been parsed.")},//DP_QC_STRINGCOLORFUNCTIONS
{"strdecolorize", PF_strdecolorize, 0, 0, 0, 477, D("string(string s)", "Flattens any markup/colours, removing them from the string.")},//DP_QC_STRINGCOLORFUNCTIONS
{"strftime", PF_strftime, 0, 0, 0, 478, "string(float uselocaltime, string format, ...)"}, //DP_QC_STRFTIME
{"tokenizebyseparator",PF_tokenizebyseparator,0,0, 0, 479, "float(string s, string separator1, ...)"}, //DP_QC_TOKENIZEBYSEPARATOR
{"tokenizebyseparator",PF_tokenizebyseparator,0,0, 0, 479, D("float(string s, string separator1, ...)", "Splits up the string using only the specified delimiters/separators. Multiple delimiters can be given, they are each considered equivelent (though should start with the longest if you want to do weird subseparator stuff).\nThe resulting tokens can be queried via argv (and argv_start|end_index builtins, if you want to determine which of the separators was present between two tokens).\nNote that while an input string containing JUST a separator will return 2, a string with no delimiter will return 1, while (in FTE) an empty string will ALWAYS return 0.")}, //DP_QC_TOKENIZEBYSEPARATOR
{"strtolower", PF_strtolower, 0, 0, 0, 480, "string(string s)"}, //DP_QC_STRING_CASE_FUNCTIONS
{"strtoupper", PF_strtoupper, 0, 0, 0, 481, "string(string s)"}, //DP_QC_STRING_CASE_FUNCTIONS
{"cvar_defstring", PF_cvar_defstring, 0, 0, 0, 482, "string(string s)"}, //DP_QC_CVAR_DEFSTRING
@ -12954,7 +13068,7 @@ void PR_DumpPlatform_f(void)
{"PFLAGS_FULLDYNAMIC", "const float", QW|NQ, D("When set in self.pflags, enables fully-customised dynamic lights. Custom rtlight information is not otherwise used."), PFLAGS_FULLDYNAMIC},
//including these for csqc stat types, hash tables, etc.
// {"EV_VOID", "const float", QW|NQ|CS, NULL, ev_void},
// {"EV_VOID", "const float", ALL, NULL, ev_void},
{"EV_STRING", "const float", ALL, NULL, ev_string},
{"EV_FLOAT", "const float", ALL, NULL, ev_float},
{"EV_VECTOR", "const float", ALL, NULL, ev_vector},
@ -12963,11 +13077,12 @@ void PR_DumpPlatform_f(void)
{"EV_FUNCTION", "const float", ALL, NULL, ev_function},
{"EV_POINTER", "const float", ALL, NULL, ev_pointer},
{"EV_INTEGER", "const float", ALL, NULL, ev_integer},
{"EV_VARIANT", "const float", ALL, NULL, ev_variant},
// {"EV_STRUCT", "const float", QW|NQ|CS, NULL, ev_struct},
// {"EV_UNION", "const float", QW|NQ|CS, NULL, ev_union},
{"EV_UINT", "const float", ALL, NULL, ev_uint},
{"EV_INT64", "const float", ALL, NULL, ev_int64},
{"EV_UINT64", "const float", ALL, NULL, ev_uint64},
{"EV_DOUBLE", "const float", ALL, NULL, ev_double},
{"gamestate", "hashtable", ALL, D("Special hash table index for hash_add and hash_get. Entries in this table will persist over map changes (and doesn't need to be created/deleted)."), 0},
{"gamestate", "hashtable", ALL, D("Special hash table index for hash_add and hash_get. Entries in this table will persist over map changes (and doesn't need to be created/deleted)."), 0},
{"HASH_REPLACE", "const float", ALL, D("Used with hash_add. Attempts to remove the old value instead of adding two values for a single key."), 256},
{"HASH_ADD", "const float", ALL, D("Used with hash_add. The new entry will be inserted in addition to the existing entry."), 512},

View file

@ -1432,7 +1432,9 @@ void ClientReliableWrite_Angle16(client_t *cl, float f);
void ClientReliableWrite_Byte(client_t *cl, int c);
void ClientReliableWrite_Char(client_t *cl, int c);
void ClientReliableWrite_Float(client_t *cl, float f);
void ClientReliableWrite_Double(client_t *cl, double f);
void ClientReliableWrite_Coord(client_t *cl, float f);
void ClientReliableWrite_Int64(client_t *cl, qint64_t c);
void ClientReliableWrite_Long(client_t *cl, int c);
void ClientReliableWrite_Short(client_t *cl, int c);
void ClientReliableWrite_Entity(client_t *cl, int c);

View file

@ -37,7 +37,7 @@ qboolean SV_MayCheat(void)
}
#ifdef SUBSERVERS
cvar_t sv_autooffload = CVARD("sv_autooffload", "0", "Automatically start the server in a separate process, so that sporadic or persistent gamecode slowdowns do not affect visual framerates. Note: Offloaded servers have separate cvar states which may complicate usage.");
cvar_t sv_autooffload = CVARD("sv_autooffload", "0", "Automatically start the server in a separate process, so that sporadic or persistent gamecode slowdowns do not affect visual framerates (equivelent to the mapcluster command). Note: Offloaded servers have separate cvar+command states which may complicate usage.");
#endif
extern cvar_t cl_warncmd;
cvar_t sv_cheats = CVARF("sv_cheats", "0", CVAR_LATCH);

View file

@ -187,6 +187,17 @@ void ClientReliableWrite_Char(client_t *cl, int c)
MSG_WriteChar(&cl->netchan.message, c);
}
void ClientReliableWrite_Double(client_t *cl, double f)
{
if (cl->num_backbuf)
{
MSG_WriteDouble(&cl->backbuf, f);
ClientReliable_FinishWrite(cl);
}
else
MSG_WriteDouble(&cl->netchan.message, f);
}
void ClientReliableWrite_Float(client_t *cl, float f)
{
if (cl->num_backbuf)
@ -209,6 +220,16 @@ void ClientReliableWrite_Coord(client_t *cl, float f)
MSG_WriteCoord(&cl->netchan.message, f);
}
void ClientReliableWrite_Int64(client_t *cl, qint64_t c)
{
if (cl->num_backbuf)
{
MSG_WriteInt64(&cl->backbuf, c);
ClientReliable_FinishWrite(cl);
}
else
MSG_WriteInt64(&cl->netchan.message, c);
}
void ClientReliableWrite_Long(client_t *cl, int c)
{
if (cl->num_backbuf)

View file

@ -7785,6 +7785,10 @@ void SV_ReadQCRequest(void)
args[i] = 'f';
G_FLOAT(OFS_PARM0+i*3) = MSG_ReadFloat();
break;
case ev_double:
args[i] = 'F';
G_FLOAT(OFS_PARM0+i*3) = MSG_ReadDouble();
break;
case ev_vector:
args[i] = 'v';
G_FLOAT(OFS_PARM0+i*3+0) = MSG_ReadFloat();
@ -7795,6 +7799,18 @@ void SV_ReadQCRequest(void)
args[i] = 'i';
G_INT(OFS_PARM0+i*3) = MSG_ReadLong();
break;
case ev_uint:
args[i] = 'u';
G_UINT(OFS_PARM0+i*3) = MSG_ReadLong();
break;
case ev_int64:
args[i] = 'I';
G_INT64(OFS_PARM0+i*3) = MSG_ReadInt64();
break;
case ev_uint64:
args[i] = 'U';
G_UINT64(OFS_PARM0+i*3) = MSG_ReadInt64();
break;
case ev_string:
args[i] = 's';
G_INT(OFS_PARM0+i*3) = PR_TempString(svprogfuncs, MSG_ReadString());