try to fix common-symbol conflicts in windows builds.

attempt to provide some better gettext support for engine strings (especially cvar/command descriptions). still no translations available though.
try to optimise hldml rendering a little.
fix issue with menuqc models rendering as black when fog is active.
use threads to try to reduce stalls from player-skin switches.
add sys_clocktype cvar to linux builds too, with CLOCK_MONOTONIC by default.
enable dtls certificate pinning log stuff.
fix r_viewmodel_fov being used instead of fov cvar.
fix possible segfault when egl driver fails.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5742 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-08-13 08:39:48 +00:00
parent f7d46b7878
commit 744b9a25db
57 changed files with 1680 additions and 1011 deletions

View File

@ -5696,7 +5696,7 @@ void CL_SetSolidEntities (void)
if (state->modelindex <= 0)
continue;
mod = cl.model_precache[state->modelindex];
if (!mod)
if (!mod || mod->loadstate != MLS_LOADED)
continue;
/*vanilla protocols have no 'solid' information. all entities get assigned ES_SOLID_BSP, even if its not actually solid.
so we need to make sure that item pickups are not erroneously considered solid, but doors etc are.
@ -5709,8 +5709,6 @@ void CL_SetSolidEntities (void)
pent = &pmove.physents[pmove.numphysent];
memset(pent, 0, sizeof(physent_t));
pent->model = mod;
if (pent->model->loadstate != MLS_LOADED)
continue;
VectorCopy (state->angles, pent->angles);
pent->angles[0]*=r_meshpitch.value;
}

View File

@ -2365,6 +2365,7 @@ void CL_CheckServerInfo(void)
// Initialize cl.maxpitch & cl.minpitch
if (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_NETQUAKE)
{
#ifdef NQPROT
s = InfoBuf_ValueForKey(&cl.serverinfo, "maxpitch");
cl.maxpitch = *s ? Q_atof(s) : ((cl_fullpitch_nq.ival && !cl.haveserverinfo)?90.0f:80.0f);
s = InfoBuf_ValueForKey(&cl.serverinfo, "minpitch");
@ -2375,6 +2376,12 @@ void CL_CheckServerInfo(void)
//should be about 0.5/65536, but there's some precision issues with such small numbers around 80, so we need to bias it more than we ought
cl.maxpitch -= 1.0/2048;
}
#else
s = InfoBuf_ValueForKey(&cl.serverinfo, "maxpitch");
cl.maxpitch = *s ? Q_atof(s) : 80.0f;
s = InfoBuf_ValueForKey(&cl.serverinfo, "minpitch");
cl.minpitch = *s ? Q_atof(s) : -70.0f;
#endif
}
else
{

View File

@ -154,7 +154,7 @@ typedef struct serverinfo_s
char gamedir[8+1];
char map[16];
unsigned short gameversion;
// unsigned short gameversion;
unsigned short ping;
short tl;

View File

@ -1597,7 +1597,7 @@ qbyte *ReadPCXData(qbyte *buf, int length, int width, int height, qbyte *result)
qwskin_t *Skin_Lookup (char *fullname);
char *Skin_FindName (player_info_t *sc);
void Skin_Find (player_info_t *sc);
qbyte *Skin_Cache8 (qwskin_t *skin);
qbyte *Skin_TryCache8 (qwskin_t *skin);
void Skin_Skins_f (void);
void Skin_FlushSkin(char *name);
void Skin_AllSkins_f (void);

View File

@ -103,8 +103,8 @@ static cvar_t in_builtinkeymap = CVARF("in_builtinkeymap", "0", CVAR_ARCHIVE);
static cvar_t in_simulatemultitouch = CVAR("in_simulatemultitouch", "0");
static cvar_t in_nonstandarddeadkeys = CVARD("in_nonstandarddeadkeys", "1", "Discard input events that result in multiple keys. Only the last key will be used. This results in behaviour that differs from eg notepad. To use a dead key, press it twice instead of the dead key followed by space.");
static cvar_t xinput_leftvibrator = CVARFD("xinput_leftvibrator","0", CVAR_ARCHIVE, "");
static cvar_t xinput_rightvibrator = CVARFD("xinput_rightvibrator","0", CVAR_ARCHIVE, "");
static cvar_t xinput_leftvibrator = CVARF("xinput_leftvibrator","0", CVAR_ARCHIVE);
static cvar_t xinput_rightvibrator = CVARF("xinput_rightvibrator","0", CVAR_ARCHIVE);
static cvar_t m_accel_noforce = CVAR("m_accel_noforce", "0");
static cvar_t m_threshold_noforce = CVAR("m_threshold_noforce", "0");
@ -116,6 +116,12 @@ extern qboolean multicursor_active[8];
POINT current_mouse_pos;
HWND mainwindow;
int window_center_x, window_center_y;
RECT window_rect;
typedef struct {
union {
HANDLE rawinputhandle;
@ -1569,10 +1575,9 @@ void INS_Accumulate (void)
if (!mouseactive)
{
extern int window_x, window_y;
GetCursorPos (&current_mouse_pos);
IN_MouseMove(sysmouse.qdeviceid, true, current_mouse_pos.x-window_x, current_mouse_pos.y-window_y, 0, 0);
IN_MouseMove(sysmouse.qdeviceid, true, current_mouse_pos.x-window_rect.left, current_mouse_pos.y-window_rect.top, 0, 0);
return;
}
}

View File

@ -432,14 +432,14 @@ void Key_UpdateCompletionDesc(void)
if (var)
{
if (desc)
Con_Footerf(NULL, false, "%s %s\n%s", cmd, var->string, desc);
Con_Footerf(NULL, false, "%s %s\n%s", cmd, var->string, localtext(desc));
else
Con_Footerf(NULL, false, "%s %s", cmd, var->string);
}
else
{
if (desc)
Con_Footerf(NULL, false, "%s: %s", cmd, desc);
Con_Footerf(NULL, false, "%s: %s", cmd, localtext(desc));
else
Con_Footerf(NULL, false, "");
}
@ -508,7 +508,7 @@ void CompleteCommand (qboolean force, int direction)
con_commandmatch = 1;
if (desc)
Con_Footerf(NULL, false, "%s: %s", cmd, desc);
Con_Footerf(NULL, false, "%s: %s", cmd, localtext(desc));
else
Con_Footerf(NULL, false, "");
return;

View File

@ -175,6 +175,7 @@ typedef struct package_s {
// DEP_MIRROR,
// DEP_FAILEDMIRROR,
DEP_SOURCE, //which source url we found this package from
DEP_EXTRACTNAME, //a file that will be installed
DEP_FILE //a file that will be installed
} dtype;
@ -286,6 +287,37 @@ static void PM_FreePackage(package_t *p)
Z_Free(p);
}
static void PM_AddDep(package_t *p, int deptype, const char *depname)
{
struct packagedep_s *nd, **link;
//no dupes.
for (link = &p->deps; (nd=*link) ; link = &nd->next)
{
if (nd->dtype == deptype && !strcmp(nd->name, depname))
return;
}
//add it on the end, preserving order.
nd = Z_Malloc(sizeof(*nd) + strlen(depname));
nd->dtype = deptype;
strcpy(nd->name, depname);
nd->next = *link;
*link = nd;
}
static qboolean PM_HasDep(package_t *p, int deptype, const char *depname)
{
struct packagedep_s *d;
//no dupes.
for (d = p->deps; d ; d = d->next)
{
if (d->dtype == deptype && !strcmp(d->name, depname))
return true;
}
return false;
}
static qboolean PM_PurgeOnDisable(package_t *p)
{
//corrupt packages must be purged
@ -310,7 +342,7 @@ void PM_ValidateAuthenticity(package_t *p)
int r;
char authority[MAX_QPATH], *sig;
#if 1//ndef _DEBUG
#ifndef _DEBUG
#pragma message("Temporary code.")
//this is temporary code and should be removed once everything else has been fixed.
//ignore the signature (flag as accepted) for any packages with all mirrors on our own update site.
@ -381,6 +413,7 @@ void PM_ValidateAuthenticity(package_t *p)
r = OSSL_VerifyHash(hashdata, hashsize, authority, signdata, signsize);
#endif
p->flags &= ~(DPF_SIGNATUREACCEPTED|DPF_SIGNATUREREJECTED|DPF_SIGNATUREUNKNOWN);
if (r == VH_CORRECT)
p->flags |= DPF_SIGNATUREACCEPTED;
else if (r == VH_INCORRECT)
@ -570,18 +603,15 @@ static qboolean PM_MergePackage(package_t *oldp, package_t *newp)
{
//if its a zip then the 'remote' file list will be blank while the local list is not (we can just keep the local list).
//if the file list DOES change, then bump the version.
if (ignorefiles)
if ((od->dtype == DEP_FILE && ignorefiles) || od->dtype == DEP_SOURCE)
{
if (od->dtype == DEP_FILE)
{
od = od->next;
continue;
}
if (nd->dtype == DEP_FILE)
{
nd = nd->next;
continue;
}
od = od->next;
continue;
}
if ((nd->dtype == DEP_FILE && ignorefiles) || nd->dtype == DEP_SOURCE)
{
nd = nd->next;
continue;
}
if (od->dtype != nd->dtype)
@ -600,6 +630,12 @@ static qboolean PM_MergePackage(package_t *oldp, package_t *newp)
if (newp->author){Z_Free(oldp->author); oldp->author = Z_StrDup(newp->author);}
if (newp->website){Z_Free(oldp->website); oldp->website = Z_StrDup(newp->website);}
if (newp->previewimage){Z_Free(oldp->previewimage); oldp->previewimage = Z_StrDup(newp->previewimage);}
if (newp->signature){Z_Free(oldp->signature); oldp->signature = Z_StrDup(newp->signature);}
if (newp->filesha1){Z_Free(oldp->filesha1); oldp->previewimage = Z_StrDup(newp->filesha1);}
if (newp->filesha512){Z_Free(oldp->filesha512); oldp->filesha512 = Z_StrDup(newp->filesha512);}
if (newp->filesize){oldp->filesize = newp->filesize;}
oldp->priority = newp->priority;
if (nm)
@ -625,6 +661,15 @@ static qboolean PM_MergePackage(package_t *oldp, package_t *newp)
//these flags should only remain set if set in both.
oldp->flags &= ~(DPF_FORGETONUNINSTALL|DPF_TESTING|DPF_MANIFEST) | (newp->flags & (DPF_FORGETONUNINSTALL|DPF_TESTING|DPF_MANIFEST));
for (nd = newp->deps; nd ; nd = nd->next)
{
if (nd->dtype == DEP_SOURCE)
{
if (!PM_HasDep(oldp, DEP_SOURCE, nd->name))
PM_AddDep(oldp, DEP_SOURCE, nd->name);
}
}
PM_FreePackage(newp);
return true;
}
@ -786,24 +831,6 @@ static qboolean PM_CheckFile(const char *filename, enum fs_relative base)
}
return false;
}
static void PM_AddDep(package_t *p, int deptype, const char *depname)
{
struct packagedep_s *nd, **link;
//no dupes.
for (link = &p->deps; (nd=*link) ; link = &nd->next)
{
if (nd->dtype == deptype && !strcmp(nd->name, depname))
return;
}
//add it on the end, preserving order.
nd = Z_Malloc(sizeof(*nd) + strlen(depname));
nd->dtype = deptype;
strcpy(nd->name, depname);
nd->next = *link;
*link = nd;
}
static void PM_AddSubList(const char *url, const char *prefix, qboolean save, qboolean trustworthy)
{
@ -845,6 +872,8 @@ static void PM_RemSubList(const char *url)
{
if (!strcmp(downloadablelist[i].url, url))
{
//FIXME: forget all packages which have only this url as a source. remove this source from other packages.
if (downloadablelist[i].curdl)
DL_Close(downloadablelist[i].curdl);
Z_Free(downloadablelist[i].url);
@ -1318,6 +1347,9 @@ static qboolean PM_ParsePackageList(const char *f, int parseflags, const char *u
p->flags |= DPF_USERMARKED; //FIXME: we don't know if this was manual or auto
}
if (url)
PM_AddDep(p, DEP_SOURCE, url);
PM_InsertPackage(p);
}
}
@ -3450,7 +3482,7 @@ static void PM_PromptApplyChanges(void)
pkg_updating = true;
#endif
strcpy(text, "Really decline the following\nrecommendedpackages?\n\n");
strcpy(text, "Really decline the following\nrecommended packages?\n\n");
if (PM_DeclinedPackages(text+strlen(text), sizeof(text)-strlen(text)))
Menu_Prompt(PM_PromptApplyDecline_Callback, NULL, text, NULL, "Confirm", "Cancel");
else
@ -3585,6 +3617,7 @@ void PM_Command_f(void)
int i, count;
package_t **sorted;
const char *category = "", *newcat;
struct packagedep_s *dep;
for (count = 0, p = availablepackages; p; p=p->next)
count++;
sorted = Z_Malloc(sizeof(*sorted)*count);
@ -3659,6 +3692,12 @@ void PM_Command_f(void)
//show the package details.
Con_Printf("\t^["S_COLOR_GRAY"%s%s%s%s^] %s"S_COLOR_GRAY" %s (%s%s)", markup, p->name, p->arch?":":"", p->arch?p->arch:"", status, strcmp(p->name, p->title)?p->title:"", p->version, (p->flags&DPF_TESTING)?"-testing":"");
for (dep = p->deps; dep; dep = dep->next)
{
if (dep->dtype == DEP_SOURCE)
Con_Printf(S_COLOR_MAGENTA" %s", dep->name);
}
if (!(p->flags&DPF_MARKED) && p == PM_FindPackage(p->name))
Con_Printf(" ^[[Add]\\type\\pkg add %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
if ((p->flags&DPF_MARKED) && p == PM_MarkedPackage(p->name, DPF_MARKED))
@ -3670,22 +3709,31 @@ void PM_Command_f(void)
}
else if (!strcmp(act, "show"))
{
struct packagedep_s *dep;
int found = 0;
key = Cmd_Argv(2);
p = PM_FindPackage(key);
if (p)
for (p = availablepackages; p; p=p->next)
{
if (Q_strcasecmp(p->name, key))
continue;
if (p->previewimage)
Con_Printf("^[%s (%s)\\tipimg\\%s\\tip\\%s^]\n", p->name, p->version, p->previewimage, "");
else
Con_Printf("%s (%s)\n", p->name, p->version);
if (p->title)
Con_Printf(" title: %s\n", p->title);
Con_Printf(" ^mtitle: ^m%s\n", p->title);
if (p->license)
Con_Printf(" license: %s\n", p->license);
Con_Printf(" ^mlicense: ^m%s\n", p->license);
if (p->author)
Con_Printf(" author: %s\n", p->author);
Con_Printf(" ^mauthor: ^m%s\n", p->author);
if (p->website)
Con_Printf(" website: %s\n", p->website);
Con_Printf(" ^mwebsite: ^m%s\n", p->website);
for (dep = p->deps; dep; dep = dep->next)
{
if (dep->dtype == DEP_SOURCE)
Con_Printf(" ^msource: ^m%s\n", dep->name);
}
if (p->description)
Con_Printf("%s\n", p->description);
@ -3728,10 +3776,22 @@ void PM_Command_f(void)
if (p->flags & DPF_ENGINE)
Con_Printf(" package is an engine update\n");
if (p->flags & DPF_TESTING)
Con_Printf(" package is untested\n");
return;
Con_Printf(S_COLOR_YELLOW" package is untested\n");
if (!PM_SignatureOkay(p))
{
if (!p->signature)
Con_Printf(CON_ERROR" Signature missing"CON_DEFAULT"\n"); //some idiot forgot to include a signature
else if (p->flags & DPF_SIGNATUREREJECTED)
Con_Printf(CON_ERROR" Signature invalid"CON_DEFAULT"\n"); //some idiot got the wrong auth/sig/hash
else if (p->flags & DPF_SIGNATUREUNKNOWN)
Con_Printf(S_COLOR_RED" Signature is not trusted"CON_DEFAULT"\n"); //clientside permission.
else
Con_Printf(CON_ERROR" Unable to verify signature"CON_DEFAULT"\n"); //clientside problem.
}
found++;
}
Con_Printf("<package not found>\n");
if (!found)
Con_Printf("<package not found>\n");
}
else if (!strcmp(act, "search") || !strcmp(act, "find"))
{

View File

@ -3590,7 +3590,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu
{
case MV_NONE:
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y,
va("arrows: pitch/rotate\n"
va("Help:\narrows: pitch/rotate\n"
"w: zoom in\n"
"s: zoom out\n"
"m: mode\n"
@ -3644,7 +3644,8 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu
if (!*contents)
Q_strncatz(contents, "non-solid", sizeof(contents));
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y,
va( "mins: %g %g %g, maxs: %g %g %g\n"
va( "Collision:\n"
"mins: %g %g %g, maxs: %g %g %g\n"
"contents: %s\n"
"surfflags: %#x\n"
"body: %i\n"
@ -3675,11 +3676,13 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu
else
{
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y,
va("mins: %g %g %g, maxs: %g %g %g\n", ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2])
va( "Collision info not available\n"
"mins: %g %g %g, maxs: %g %g %g\n", ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2])
, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);
}
break;
case MV_NORMALS:
Draw_FunString(0, y, va("Normals"));
break;
case MV_BONES:
#ifdef SKELETALMODELS
@ -3717,7 +3720,10 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu
{
char *body = Shader_GetShaderBody(Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup), mods->shaderfile, sizeof(mods->shaderfile));
if (!body)
{
Draw_FunString(0, y, "Shader info not available");
break;
}
if (*mods->shaderfile)
mods->shadertext = Z_StrDup(va("\n\nPress space to view+edit the shader\n\n%s", body));
else
@ -3790,8 +3796,13 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu
else
Draw_FunString(0, y, va("%s: <NO TEXTURE>", t));
}
else
Draw_FunString(0, y, "Texture info not available");
}
break;
default:
Draw_FunString(0, y, "Unknown display mode");
break;
}
}
static qboolean M_ModelViewerKey(struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode)

View File

@ -572,7 +572,7 @@ static void Prompt_Release(struct menu_s *gm)
callback(ctx, PROMPT_CANCEL);
Z_Free(m);
}
void Menu_Prompt (void (*callback)(void *, promptbutton_t), void *ctx, const char *messages, char *optionyes, char *optionno, char *optioncancel)
void Menu_Prompt (void (*callback)(void *, promptbutton_t), void *ctx, const char *messages, const char *optionyes, const char *optionno, const char *optioncancel)
{
promptmenu_t *m;
char *t;

View File

@ -127,7 +127,7 @@ typedef enum
PROMPT_NO = 1,
PROMPT_CANCEL = -1,
} promptbutton_t;
void Menu_Prompt (void (*callback)(void *, promptbutton_t), void *ctx, const char *messages, char *optionyes, char *optionno, char *optioncancel);
void Menu_Prompt (void (*callback)(void *, promptbutton_t), void *ctx, const char *messages, const char *optionyes, const char *optionno, const char *optioncancel);
#ifndef NOBUILTINMENUS

View File

@ -3236,7 +3236,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
Q_strncpyz(info->qcstatus, Info_ValueForKey(msg, "qcstatus"), sizeof(info->qcstatus));
Q_strncpyz(info->modname, Info_ValueForKey(msg, "modname"), sizeof(info->modname));
info->gameversion = atoi(Info_ValueForKey(msg, "gameversion"));
// info->gameversion = atoi(Info_ValueForKey(msg, "gameversion"));
info->numbots = 0;//atoi(Info_ValueForKey(msg, "bots"));
info->numhumans = info->players - info->numbots;

View File

@ -1381,6 +1381,8 @@ void P_ParticleEffect_f(void)
ptype->count = 1/atof(value);
if (Cmd_Argc()>2)
ptype->countrand = 1/atof(Cmd_Argv(2));
if (Cmd_Argc()>3)
ptype->countextra = atof(Cmd_Argv(3));
}
else if (!strcmp(var, "count"))
{

View File

@ -2797,6 +2797,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
if (csqc_worldchanged)
{
csqc_worldchanged = false;
cl.worldmodel = r_worldentity.model = csqc_world.worldmodel;
Surf_NewMap();
CL_UpdateWindowTitle();
@ -3144,7 +3145,7 @@ static void QCBUILTIN PF_cs_pointcontents(pubprogfuncs_t *prinst, struct globalv
v = G_VECTOR(OFS_PARM0);
cont = cl.worldmodel?World_PointContentsWorldOnly(w, v):FTECONTENTS_EMPTY;
cont = w->worldmodel?World_PointContentsWorldOnly(w, v):FTECONTENTS_EMPTY;
if (cont & FTECONTENTS_SOLID)
G_FLOAT(OFS_RETURN) = Q1CONTENTS_SOLID;
else if (cont & FTECONTENTS_SKY)
@ -3197,12 +3198,16 @@ static model_t *csqc_setmodel(pubprogfuncs_t *prinst, csqcedict_t *ent, int mode
VectorSubtract (model->maxs, model->mins, ent->v->size);
if (!ent->entnum)
{
cl.worldmodel = r_worldentity.model = csqc_world.worldmodel = model;
{ //setmodel(world, "maps/foo.bsp"); may be used to switch the csqc's worldmodel.
csqc_world.worldmodel = model;
csqc_worldchanged = true;
VectorAdd(ent->v->origin, ent->v->mins, ent->v->absmin);
VectorAdd(ent->v->origin, ent->v->maxs, ent->v->absmax);
World_ClearWorld (&csqc_world, true); //make sure any pvs stuff is rebuilt.
cl.num_statics = 0; //has pvs indexes that can cause crashes.
return model;
}
}
else
@ -4028,7 +4033,7 @@ static void QCBUILTIN PF_cs_runplayerphysics (pubprogfuncs_t *prinst, struct glo
return;
}
if (!cl.worldmodel)
if (!csqc_world.worldmodel)
return; //urm..
VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove));
@ -4122,11 +4127,11 @@ static void QCBUILTIN PF_cs_getentitytoken (pubprogfuncs_t *prinst, struct globa
if (prinst->callargc)
{
const char *s = PR_GetStringOfs(prinst, OFS_PARM0);
if (*s == 0 && cl.worldmodel)
if (*s == 0 && csqc_world.worldmodel)
{
if (cl.worldmodel->loadstate == MLS_LOADING)
COM_WorkerPartialSync(cl.worldmodel, &cl.worldmodel->loadstate, MLS_LOADING);
s = Mod_GetEntitiesString(cl.worldmodel);
if (csqc_world.worldmodel->loadstate == MLS_LOADING)
COM_WorkerPartialSync(csqc_world.worldmodel, &csqc_world.worldmodel->loadstate, MLS_LOADING);
s = Mod_GetEntitiesString(csqc_world.worldmodel);
}
csqcmapentitydata = s;
G_INT(OFS_RETURN) = 0;
@ -4796,11 +4801,6 @@ static void QCBUILTIN PF_cs_lightstyle (pubprogfuncs_t *prinst, struct globalvar
if (prinst->callargc >= 3) //fte is a quakeworld engine
VectorCopy(G_VECTOR(OFS_PARM2), rgb);
if ((unsigned)stnum >= cl_max_lightstyles)
{
Con_Printf ("PF_cs_lightstyle: stnum > MAX_LIGHTSTYLES");
return;
}
R_UpdateLightStyle(stnum, str, rgb[0],rgb[1],rgb[2]);
}
@ -5268,7 +5268,7 @@ static void QCBUILTIN PF_cs_OpenPortal (pubprogfuncs_t *prinst, struct globalvar
{
/*
#ifdef Q2BSPS
if (cl.worldmodel->fromgame == fg_quake2)
if (csqc_world.worldmodel->fromgame == fg_quake2)
{
int portal;
int state = G_FLOAT(OFS_PARM1)!=0;
@ -5276,19 +5276,19 @@ static void QCBUILTIN PF_cs_OpenPortal (pubprogfuncs_t *prinst, struct globalvar
portal = G_FLOAT(OFS_PARM0); //old legacy crap.
else
portal = G_WEDICT(prinst, OFS_PARM0)->xv->style; //read the func_areaportal's style field.
CMQ2_SetAreaPortalState(cl.worldmodel, portal, state);
CMQ2_SetAreaPortalState(csqc_world.worldmodel, portal, state);
}
#endif
*/
#ifdef Q3BSPS
if (cl.worldmodel->fromgame == fg_quake3)
if (csqc_world.worldmodel->fromgame == fg_quake3)
{
int state = G_FLOAT(OFS_PARM1)!=0;
wedict_t *portal = G_WEDICT(prinst, OFS_PARM0);
int area1 = portal->pvsinfo.areanum, area2 = portal->pvsinfo.areanum2;
if (area1 == area2 || area1<0 || area2<0)
return;
CMQ3_SetAreaPortalState(cl.worldmodel, portal->pvsinfo.areanum, portal->pvsinfo.areanum2, state);
CMQ3_SetAreaPortalState(csqc_world.worldmodel, portal->pvsinfo.areanum, portal->pvsinfo.areanum2, state);
}
#endif
}
@ -5323,11 +5323,11 @@ static void QCBUILTIN PF_cs_droptofloor (pubprogfuncs_t *prinst, struct globalva
static void QCBUILTIN PF_cl_getlight (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
vec3_t ambient, diffuse, dir;
if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED || !cl.worldmodel->funcs.LightPointValues)
if (!csqc_world.worldmodel || csqc_world.worldmodel->loadstate != MLS_LOADED || !csqc_world.worldmodel->funcs.LightPointValues)
VectorSet(G_VECTOR(OFS_RETURN), 0, 0, 0);
else
{
cl.worldmodel->funcs.LightPointValues(cl.worldmodel, G_VECTOR(OFS_PARM0), ambient, diffuse, dir);
csqc_world.worldmodel->funcs.LightPointValues(csqc_world.worldmodel, G_VECTOR(OFS_PARM0), ambient, diffuse, dir);
VectorMA(ambient, 0.5, diffuse, G_VECTOR(OFS_RETURN));
}
}
@ -8291,15 +8291,16 @@ void CSQC_WorldLoaded(void)
if (csqc_isdarkplaces)
CSQC_FindGlobals(false);
csqcmapentitydataloaded = true;
csqcmapentitydata = Mod_GetEntitiesString(cl.worldmodel);
csqc_world.worldmodel = cl.worldmodel;
csqcmapentitydataloaded = true;
csqcmapentitydata = Mod_GetEntitiesString(csqc_world.worldmodel);
World_RBE_Start(&csqc_world);
worldent = (csqcedict_t *)EDICT_NUM_PB(csqcprogs, 0);
worldent->v->solid = SOLID_BSP;
wmodelindex = CS_FindModel(cl.worldmodel?cl.worldmodel->name:"", &tmp);
wmodelindex = CS_FindModel(csqc_world.worldmodel?csqc_world.worldmodel->name:"", &tmp);
tmp = csqc_worldchanged;
csqc_setmodel(csqcprogs, worldent, wmodelindex);
csqc_worldchanged = tmp;

View File

@ -1359,6 +1359,8 @@ static struct
evalc_t frame2time;
evalc_t renderflags;
evalc_t skinobject;
evalc_t colourmod;
evalc_t alpha;
} menuc_eval;
static playerview_t menuview;
@ -2117,6 +2119,8 @@ static qboolean CopyMenuEdictToEntity(pubprogfuncs_t *prinst, menuedict_t *in, e
eval_t *colormapval = prinst->GetEdictFieldValue(prinst, (void*)in, "colormap", ev_float, &menuc_eval.colormap);
eval_t *renderflagsval = prinst->GetEdictFieldValue(prinst, (void*)in, "renderflags", ev_float, &menuc_eval.renderflags);
eval_t *skinobjectval = prinst->GetEdictFieldValue(prinst, (void*)in, "skinobject", ev_float, &menuc_eval.skinobject);
eval_t *colourmodval = prinst->GetEdictFieldValue(prinst, (void*)in, "colormod", ev_vector, &menuc_eval.colourmod);
eval_t *alphaval = prinst->GetEdictFieldValue(prinst, (void*)in, "alpha", ev_float, &menuc_eval.alpha);
int ival;
int rflags;
@ -2163,6 +2167,22 @@ static qboolean CopyMenuEdictToEntity(pubprogfuncs_t *prinst, menuedict_t *in, e
out->bottomcolour = BOTTOM_DEFAULT;
}
VectorSet(out->glowmod, 1,1,1);
if (!colourmodval || (!colourmodval->_vector[0] && !colourmodval->_vector[1] && !colourmodval->_vector[2]))
VectorSet(out->shaderRGBAf, 1, 1, 1);
else
{
out->flags |= RF_FORCECOLOURMOD;
VectorCopy(colourmodval->_vector, out->shaderRGBAf);
}
if (!alphaval || !alphaval->_float || alphaval->_float == 1)
out->shaderRGBAf[3] = 1.0f;
else
{
out->flags |= RF_TRANSLUCENT;
out->shaderRGBAf[3] = alphaval->_float;
}
if (rflags & CSQCRF_ADDITIVE)
out->flags |= RF_ADDITIVE;
if (rflags & CSQCRF_DEPTHHACK)

View File

@ -2958,12 +2958,12 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent)
*b = *ob;
if (b->vbo && b->maxmeshes)
{
b->meshbuf = *b->mesh[0];
b->meshbuf.numindexes = b->mesh[b->maxmeshes-1]->indexes+b->mesh[b->maxmeshes-1]->numindexes-b->mesh[0]->indexes;
b->meshbuf.numvertexes = b->mesh[b->maxmeshes-1]->xyz_array+b->mesh[b->maxmeshes-1]->numvertexes-b->mesh[0]->xyz_array;
b->user.meshbuf = *b->mesh[0];
b->user.meshbuf.numindexes = b->mesh[b->maxmeshes-1]->indexes+b->mesh[b->maxmeshes-1]->numindexes-b->mesh[0]->indexes;
b->user.meshbuf.numvertexes = b->mesh[b->maxmeshes-1]->xyz_array+b->mesh[b->maxmeshes-1]->numvertexes-b->mesh[0]->xyz_array;
b->mesh = &b->meshptr;
b->meshptr = &b->meshbuf;
b->mesh = &b->user.meshptr;
b->user.meshptr = &b->user.meshbuf;
b->meshes = b->maxmeshes = 1;
}
else
@ -3182,7 +3182,7 @@ static void Surf_SimpleWorld_Q1BSP(struct webostate_s *es, qbyte *pvs)
Surf_RenderDynamicLightmaps_Worker (wmodel, surf, es->lightstylevalues);
mesh = surf->mesh;
eb = &es->batches[surf->sbatch->ebobatch];
eb = &es->batches[surf->sbatch->user.bmodel.ebobatch];
if (eb->maxidx < eb->numidx + mesh->numindexes)
{
//FIXME: pre-allocate
@ -3253,7 +3253,7 @@ static void Surf_SimpleWorld_Q3BSP(struct webostate_s *es, qbyte *pvs)
surf->visframe = fc;
mesh = surf->mesh;
eb = &es->batches[surf->sbatch->ebobatch];
eb = &es->batches[surf->sbatch->user.bmodel.ebobatch];
if (eb->maxidx < eb->numidx + mesh->numindexes)
{
//FIXME: pre-allocate
@ -3431,7 +3431,7 @@ void Surf_DrawWorld (void)
for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++)
for (batch = currentmodel->batches[sortid]; batch != NULL; batch = batch->next)
{
batch->ebobatch = currentmodel->numbatches;
batch->user.bmodel.ebobatch = currentmodel->numbatches;
currentmodel->numbatches++;
}
/*TODO submodels too*/
@ -3469,7 +3469,7 @@ void Surf_DrawWorld (void)
for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++)
for (batch = currentmodel->batches[sortid]; batch != NULL; batch = batch->next)
{
batch->ebobatch = currentmodel->numbatches;
batch->user.bmodel.ebobatch = currentmodel->numbatches;
currentmodel->numbatches++;
}
}

View File

@ -411,6 +411,19 @@ void GLVID_Console_Resize(void);
int R_LightPoint (vec3_t p);
void R_RenderDlights (void);
typedef struct
{
int allocated[LMBLOCK_SIZE_MAX];
int firstlm;
int lmnum;
unsigned int width;
unsigned int height;
qboolean deluxe;
} lmalloc_t;
void Mod_LightmapAllocInit(lmalloc_t *lmallocator, qboolean hasdeluxe, unsigned int width, unsigned int height, int firstlm); //firstlm is for debugging stray lightmap indexes
//void Mod_LightmapAllocDone(lmalloc_t *lmallocator, model_t *mod);
void Mod_LightmapAllocBlock(lmalloc_t *lmallocator, int w, int h, unsigned short *x, unsigned short *y, int *tnum);
enum imageflags
{
/*warning: many of these flags only apply the first time it is requested*/
@ -449,7 +462,7 @@ enum imageflags
IF_NOPURGE = 1<<22, //texture is not flushed when no more shaders refer to it (for C code that holds a permanant reference to it - still purged on vid_reloads though)
IF_HIGHPRIORITY = 1<<23, //pushed to start of worker queue instead of end...
IF_LOWPRIORITY = 1<<24, //
IF_LOADNOW = 1<<25, /*hit the disk now, and delay the gl load until its actually needed. this is used only so that the width+height are known in advance*/
IF_LOADNOW = 1<<25, /*hit the disk now, and delay the gl load until its actually needed. this is used only so that the width+height are known in advance. valid on worker threads.*/
IF_NOPCX = 1<<26, /*block pcx format. meaning qw skins can use team colours and cropping*/
IF_TRYBUMP = 1<<27, /*attempt to load _bump if the specified _norm texture wasn't found*/
IF_RENDERTARGET = 1<<28, /*never loaded from disk, loading can't fail*/

View File

@ -408,15 +408,15 @@ cvar_t gl_conback = CVARFCD ("gl_conback", "",
// CVAR_ARCHIVE);
//cvar_t gl_detailscale = CVAR ("gl_detailscale", "5");
cvar_t gl_font = CVARFD ("gl_font", "",
CVAR_RENDERERCALLBACK|CVAR_ARCHIVE, ("Specifies the font file to use. a value such as FONT:ALTFONT specifies an alternative font to be used when ^^a is used.\n"
CVAR_RENDERERCALLBACK|CVAR_ARCHIVE, "Specifies the font file to use. a value such as FONT:ALTFONT specifies an alternative font to be used when ^^a is used.\n"
"When using TTF fonts, you will likely need to scale text to at least 150% - vid_conautoscale 1.5 will do this.\n"
"TTF fonts may be loaded from your windows directory. \'gl_font cour?col=1,1,1:couri?col=0,1,0\' loads eg: c:\\windows\\fonts\\cour.ttf, and uses the italic version of courier for alternative text, with specific colour tints."
));
);
cvar_t con_textfont = CVARAFD ("con_textfont", "", "gl_consolefont",
CVAR_RENDERERCALLBACK|CVAR_ARCHIVE, ("Specifies the font file to use. a value such as FONT:ALTFONT specifies an alternative font to be used when ^^a is used.\n"
CVAR_RENDERERCALLBACK|CVAR_ARCHIVE, "Specifies the font file to use. a value such as FONT:ALTFONT specifies an alternative font to be used when ^^a is used.\n"
"When using TTF fonts, you will likely need to scale text to at least 150% - vid_conautoscale 1.5 will do this.\n"
"TTF fonts may be loaded from your windows directory. \'gl_font cour?col=1,1,1:couri?col=0,1,0\' loads eg: c:\\windows\\fonts\\cour.ttf, and uses the italic version of courier for alternative text, with specific colour tints."
));
);
cvar_t gl_lateswap = CVAR ("gl_lateswap", "0");
cvar_t gl_lerpimages = CVARFD ("gl_lerpimages", "1", CVAR_ARCHIVE, "Enables smoother resampling for images which are not power-of-two, when the drivers do not support non-power-of-two textures.");
//cvar_t gl_lightmapmode = SCVARF("gl_lightmapmode", "",

View File

@ -120,7 +120,7 @@ qwskin_t *Skin_Lookup (char *fullname)
if (!strcmp (cleanname, skins[i].name))
{
skin = &skins[i];
Skin_Cache8 (skin);
Skin_TryCache8 (skin);
return skin;
}
}
@ -136,7 +136,7 @@ qwskin_t *Skin_Lookup (char *fullname)
memset (skin, 0, sizeof(*skin));
Q_strncpyz(skin->name, cleanname, sizeof(skin->name));
Skin_Cache8 (skin);
Skin_TryCache8 (skin);
return skin;
}
/*
@ -187,6 +187,126 @@ void Skin_Find (player_info_t *sc)
Q_strncpyz(skin->name, name, sizeof(skin->name));
}
qbyte *Skin_ParsePCX(const char *name, const pcx_t *pcx, size_t pcxsize, int *pcxheight, int *pcxwidth)
{
const qbyte *raw;
qbyte *out, *pix;
int x, y, srcw, srch;
int dataByte;
int runLength;
int fbremap[256];
unsigned short xmax, ymax, xmin, ymin;
*pcxheight = *pcxwidth = 0;
//
// parse the PCX file
//
raw = (const qbyte *)(pcx+1);
//check format (sizes are checked later)
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8)
{
Con_Printf ("Bad skin %s (unsupported format)\n", name);
return NULL;
}
xmax = (unsigned short)LittleShort(pcx->xmax);
ymax = (unsigned short)LittleShort(pcx->ymax);
xmin = (unsigned short)LittleShort(pcx->xmin);
ymin = (unsigned short)LittleShort(pcx->ymin);
srcw = xmax-xmin+1;
srch = ymax-ymin+1;
if (srcw < 1 || srch < 1 || srcw > 320 || srch > 200)
{
Con_Printf ("Bad skin %s (unsupported size)\n", name);
return NULL;
}
*pcxheight = srcw;
*pcxwidth = srch;
out = BZ_Malloc(srcw*srch);
if (!out)
Sys_Error ("Skin_Cache: couldn't allocate");
// TODO: we build a fullbright remap.. can we get rid of this?
for (x = 0; x < vid.fullbright; x++)
fbremap[x] = x + (256-vid.fullbright); //fullbrights don't exist, so don't loose palette info.
pix = out;
// memset (out, 0, skin->width*skin->height);
dataByte = 0; //typically black (this is in case a 0*0 file is loaded... which won't happen anyway)
for (y=0 ; y < srch ; y++, pix += srcw)
{
for (x=0 ; x < srcw ; )
{
if (raw - (const qbyte*)pcx > pcxsize)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
return NULL;
}
dataByte = *raw++;
if((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
if (raw - (const qbyte*)pcx > pcxsize)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
return NULL;
}
dataByte = *raw++;
}
else
runLength = 1;
// skin sanity check
if (runLength + x > xmax + 2)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
return NULL;
}
if (dataByte >= 256-vid.fullbright) //kill the fb componant
if (!r_fb_models.ival)
dataByte = fbremap[dataByte + vid.fullbright-256];
while(runLength-- > 0)
pix[x++] = dataByte;
}
//pad the end of the scan line with the trailing pixel
for ( ; x < srcw ; )
pix[x++] = dataByte;
}
//pad the bottom of the skin with that final pixel
for ( ; y < srch; y++, pix += srcw)
for (x = 0; x < srcw; )
pix[x++] = dataByte;
if ( raw - (const qbyte *)pcx > pcxsize)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
return NULL;
}
return out;
}
void Skin_WorkerDone(void *skinptr, void *skindata, size_t width, size_t height)
{
qwskin_t *skin = skinptr;
@ -202,18 +322,15 @@ void Skin_WorkerLoad(void *skinptr, void *data, size_t a, size_t b)
{
qwskin_t *skin = skinptr;
char name[MAX_QPATH];
qbyte *raw;
qbyte *out, *pix;
pcx_t *pcx;
int x, y, srcw, srch;
int dataByte;
int runLength;
int fbremap[256];
qbyte *out;
int srcw, srch;
size_t pcxsize;
void *pcxfiledata;
Q_snprintfz (name, sizeof(name), "skins/%s.pcx", skin->name);
raw = COM_LoadTempFile (name, FSLF_IGNOREPURE, &pcxsize);
if (!raw)
pcxfiledata = FS_LoadMallocFileFlags (name, FSLF_IGNOREPURE, &pcxsize);
if (!pcxfiledata)
{
//use 24bit skins even if gl_load24bit is failed
if (strcmp(skin->name, baseskin.string))
@ -223,126 +340,30 @@ void Skin_WorkerLoad(void *skinptr, void *data, size_t a, size_t b)
if (*baseskin.string)
{
Q_snprintfz (name, sizeof(name), "skins/%s.pcx", baseskin.string);
raw = COM_LoadTempFile (name, FSLF_IGNOREPURE, &pcxsize);
pcxfiledata = FS_LoadMallocFileFlags (name, FSLF_IGNOREPURE, &pcxsize);
}
}
if (!raw)
if (!pcxfiledata)
{
Skin_WorkerDone(skin, NULL, 0, 0);
return;
}
}
//
// parse the PCX file
//
pcx = (pcx_t *)raw;
raw = (qbyte *)(pcx+1);
//check format (sizes are checked later)
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8)
if (pcxfiledata)
{
Con_Printf ("Bad skin %s (unsupported format)\n", name);
Skin_WorkerDone(skin, NULL, 0, 0);
return;
out = Skin_ParsePCX(name, pcxfiledata, pcxsize, &srcw, &srch);
FS_FreeFile(pcxfiledata);
}
pcx->xmax = (unsigned short)LittleShort(pcx->xmax);
pcx->ymax = (unsigned short)LittleShort(pcx->ymax);
pcx->xmin = (unsigned short)LittleShort(pcx->xmin);
pcx->ymin = (unsigned short)LittleShort(pcx->ymin);
srcw = pcx->xmax-pcx->xmin+1;
srch = pcx->ymax-pcx->ymin+1;
if (srcw < 1 || srch < 1 || srcw > 320 || srch > 200)
else
{
Con_Printf ("Bad skin %s (unsupported size)\n", name);
Skin_WorkerDone(skin, NULL, 0, 0);
return;
out = NULL;
srcw = srch = 0;
}
skin->width = srcw;
skin->height = srch;
out = BZ_Malloc(skin->width*skin->height);
if (!out)
Sys_Error ("Skin_Cache: couldn't allocate");
// TODO: we build a fullbright remap.. can we get rid of this?
for (x = 0; x < vid.fullbright; x++)
fbremap[x] = x + (256-vid.fullbright); //fullbrights don't exist, so don't loose palette info.
pix = out;
// memset (out, 0, skin->width*skin->height);
dataByte = 0; //typically black (this is in case a 0*0 file is loaded... which won't happen anyway)
for (y=0 ; y < srch ; y++, pix += skin->width)
{
for (x=0 ; x < srcw ; )
{
if (raw - (qbyte*)pcx > pcxsize)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
Skin_WorkerDone(skin, NULL, 0, 0);
return;
}
dataByte = *raw++;
if((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
if (raw - (qbyte*)pcx > pcxsize)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
Skin_WorkerDone(skin, NULL, 0, 0);
return;
}
dataByte = *raw++;
}
else
runLength = 1;
// skin sanity check
if (runLength + x > pcx->xmax + 2)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
Skin_WorkerDone(skin, NULL, 0, 0);
return;
}
if (dataByte >= 256-vid.fullbright) //kill the fb componant
if (!r_fb_models.ival)
dataByte = fbremap[dataByte + vid.fullbright-256];
while(runLength-- > 0)
pix[x++] = dataByte;
}
//pad the end of the scan line with the trailing pixel
for ( ; x < skin->width ; )
pix[x++] = dataByte;
}
//pad the bottom of the skin with that final pixel
for ( ; y < skin->height; y++, pix += skin->width)
for (x = 0; x < skin->width; )
pix[x++] = dataByte;
if ( raw - (qbyte *)pcx > pcxsize)
{
BZ_Free(out);
Con_Printf ("Skin %s was malformed. You should delete it.\n", name);
Skin_WorkerDone(skin, NULL, 0, 0);
return;
}
Skin_WorkerDone(skin, out, srcw, srch);
COM_AddWork(WG_MAIN, Skin_WorkerDone, skin, NULL, 0, 0);
else
COM_AddWork(WG_MAIN, Skin_WorkerDone, skin, out, srcw, srch);
}
/*
@ -352,7 +373,7 @@ Skin_Cache
Returns a pointer to the skin bitmap, or NULL to use the default
==========
*/
qbyte *Skin_Cache8 (qwskin_t *skin)
qbyte *Skin_TryCache8 (qwskin_t *skin)
{
char name[1024];
char *skinpath;
@ -436,10 +457,8 @@ qbyte *Skin_Cache8 (qwskin_t *skin)
if (skin->loadstate == SKIN_FAILED)
return NULL;
skin->loadstate = SKIN_LOADING;
Skin_WorkerLoad(skin, NULL, 0, 0);
return skin->skindata;
COM_AddWork(WG_LOADER, Skin_WorkerLoad, skin, NULL,0,0);
return NULL;
}
/*
@ -512,7 +531,7 @@ void Skin_NextDownload (void)
sc = &cl.players[i];
if (!sc->name[0] || !sc->qwskin)
continue;
Skin_Cache8 (sc->qwskin);
Skin_TryCache8 (sc->qwskin);
//sc->qwskin = NULL;
}
}
@ -561,7 +580,7 @@ void Skin_Skins_f (void)
if (cls.state == ca_disconnected)
{
Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
Con_TPrintf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
return;
}
@ -627,7 +646,7 @@ void Skin_Skins_f (void)
{
if (cls.state == ca_disconnected)
{
Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
Con_TPrintf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
return;
}

View File

@ -1180,7 +1180,7 @@ static qboolean OpenAL_Init(soundcardinfo_t *sc, const char *devname)
devname = palcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
}
Q_snprintfz(sc->name, sizeof(sc->name), "%s", devname);
Con_Printf("Initiating "SDRVNAME": %s.\n", devname);
Con_TPrintf("Initiating "SDRVNAME": %s.\n", devname);
oali = Z_Malloc(sizeof(oalinfo_t));
sc->handle = oali;
@ -1489,11 +1489,11 @@ static qboolean QDECL OpenAL_InitCard(soundcardinfo_t *sc, const char *devname)
return false;
oali = sc->handle;
Con_Printf( SDRVNAME" AL_VERSION: %s\n",palGetString(AL_VERSION));
Con_Printf( SDRVNAME" AL_RENDERER: %s\n",palGetString(AL_RENDERER));
Con_Printf( SDRVNAME" AL_VENDOR: %s\n",palGetString(AL_VENDOR));
Con_DPrintf(SDRVNAME" AL_EXTENSIONS: %s\n",palGetString(AL_EXTENSIONS));
Con_DPrintf(SDRVNAME" ALC_EXTENSIONS: %s\n",palcGetString(oali->OpenAL_Device,ALC_EXTENSIONS));
Con_Printf( "AL_VERSION: %s\n",palGetString(AL_VERSION));
Con_Printf( "AL_RENDERER: %s\n",palGetString(AL_RENDERER));
Con_Printf( "AL_VENDOR: %s\n",palGetString(AL_VENDOR));
Con_DPrintf("AL_EXTENSIONS: %s\n",palGetString(AL_EXTENSIONS));
Con_DPrintf("ALC_EXTENSIONS: %s\n",palcGetString(oali->OpenAL_Device,ALC_EXTENSIONS));
sc->Shutdown = OpenAL_Shutdown;
#ifdef USEEFX

View File

@ -78,6 +78,7 @@ long sys_parentwindow;
qboolean sys_gracefulexit;
qboolean X11_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate);
static void Sys_InitClock(void);
qboolean Sys_InitTerminal (void) //we either have one or we don't.
{
@ -424,6 +425,7 @@ static void Sys_Register_File_Associations_f(void)
void Sys_Init(void)
{
Sys_InitClock();
Cmd_AddCommandD("sys_register_file_associations", Sys_Register_File_Associations_f, "Register FTE as the default handler for various file+protocol types, using FreeDesktop standards.\n");
}
void Sys_Shutdown(void)
@ -682,29 +684,111 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
return Sys_EnumerateFiles2(truepath, suboffset, match, func, parm, spath);
}
int secbase;
static quint64_t timer_basetime; //used by all clocks to bias them to starting at 0
static void Sys_ClockType_Changed(cvar_t *var, char *oldval);
static cvar_t sys_clocktype = CVARFCD("sys_clocktype", "", CVAR_NOTFROMSERVER, Sys_ClockType_Changed, "Controls which system clock to base timings from.\n0: auto\n"
"1: gettimeofday (may be discontinuous).\n"
"2: monotonic.");
static enum
{
QCLOCK_AUTO = 0,
QCLOCK_GTOD,
QCLOCK_MONOTONIC,
QCLOCK_REALTIME,
QCLOCK_INVALID
} timer_clocktype;
static quint64_t Sys_GetClock(quint64_t *freq)
{
quint64_t t;
if (timer_clocktype == QCLOCK_MONOTONIC)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
*freq = 1000000000;
t = (ts.tv_sec*(quint64_t)1000000000) + ts.tv_nsec;
}
else if (timer_clocktype == QCLOCK_REALTIME)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
*freq = 1000000000;
t = (ts.tv_sec*(quint64_t)1000000000) + ts.tv_nsec;
//WARNING t can go backwards
}
else //if (timer_clocktype == QCLOCK_GTOD)
{
struct timeval tp;
gettimeofday(&tp, NULL);
*freq = 1000000;
t = tp.tv_sec*(quint64_t)1000000 + tp.tv_usec;
//WARNING t can go backwards
}
return t - timer_basetime;
}
static void Sys_ClockType_Changed(cvar_t *var, char *oldval)
{
int newtype = var?var->ival:0;
if (newtype >= QCLOCK_INVALID)
newtype = QCLOCK_AUTO;
if (newtype <= QCLOCK_AUTO)
newtype = QCLOCK_MONOTONIC;
if (newtype != timer_clocktype)
{
quint64_t oldtime, oldfreq;
quint64_t newtime, newfreq;
oldtime = Sys_GetClock(&oldfreq);
timer_clocktype = newtype;
timer_basetime = 0;
newtime = Sys_GetClock(&newfreq);
timer_basetime = newtime - (newfreq * (oldtime) / oldfreq);
/*if (host_initialized)
{
const char *clockname = "unknown";
switch(timer_clocktype)
{
case QCLOCK_GTOD: clockname = "gettimeofday"; break;
case QCLOCK_MONOTONIC: clockname = "monotonic"; break;
case QCLOCK_REALTIME: clockname = "realtime"; break;
case QCLOCK_AUTO:
case QCLOCK_INVALID: break;
}
Con_Printf("Clock %s, wraps after %"PRIu64" days, %"PRIu64" years\n", clockname, (((quint64_t)-1)/newfreq)/(24*60*60), (((quint64_t)-1)/newfreq)/(24*60*60*365));
}*/
}
}
static void Sys_InitClock(void)
{
quint64_t freq;
Cvar_Register(&sys_clocktype, "System vars");
//calibrate it, and apply.
Sys_ClockType_Changed(NULL, NULL);
timer_basetime = 0;
timer_basetime = Sys_GetClock(&freq);
}
double Sys_DoubleTime (void)
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
quint64_t denum, num = Sys_GetClock(&denum);
return num / (long double)denum;
}
unsigned int Sys_Milliseconds (void)
{
return Sys_DoubleTime() * 1000;
quint64_t denum, num = Sys_GetClock(&denum);
num *= 1000;
return num / denum;
}
#ifdef USE_LIBTOOL
void Sys_CloseLibrary(dllhandle_t *lib)
{

View File

@ -3798,7 +3798,7 @@ void CL_Say (qboolean team, char *extra)
if (cls.state == ca_disconnected)
{
Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
Con_TPrintf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
return;
}

View File

@ -2521,15 +2521,17 @@ static void Cmd_Apropos_f (void)
char escapedvalue[1024];
char latchedvalue[1024];
char *query = Cmd_Argv(1);
const char *d;
for (grp=cvar_groups ; grp ; grp=grp->next)
for (var=grp->cvars ; var ; var=var->next)
{
d = var->description?localtext(var->description):NULL;
if (var->name && Q_strcasestr(var->name, query))
name = var->name;
else if (var->name2 && Q_strcasestr(var->name2, query))
name = var->name2;
else if (var->description && Q_strcasestr(var->description, query))
else if (d && Q_strcasestr(d, query))
name = var->name;
else
continue;
@ -2539,21 +2541,34 @@ static void Cmd_Apropos_f (void)
if (var->latched_string)
{
COM_QuotedString(var->latched_string, latchedvalue, sizeof(latchedvalue), false);
Con_Printf("cvar ^2%s^7: %s (effective %s): %s\n", name, latchedvalue, escapedvalue, var->description?var->description:"no description");
if (d)
Con_TPrintf("cvar ^2%s^7: %s (effective %s): ^3%s\n", name, latchedvalue, escapedvalue, d);
else
Con_TPrintf("cvar ^2%s^7: %s (effective %s): ^3no description\n", name, latchedvalue, escapedvalue);
}
else
Con_Printf("cvar ^2%s^7: %s : %s\n", name, escapedvalue, var->description?var->description:"no description");
{
if (d)
Con_TPrintf("cvar ^2%s^7: %s : ^3%s\n", name, escapedvalue, d);
else
Con_TPrintf("cvar ^2%s^7: %s : ^3no description\n", name, escapedvalue);
}
}
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
d = cmd->description?localtext(cmd->description):NULL;
if (cmd->name && Q_strcasestr(cmd->name, query))
;
else if (cmd->description && strstr(cmd->description, query))
else if (d && strstr(d, query))
;
else
continue;
Con_Printf("command ^2%s^7: %s\n", cmd->name, cmd->description?cmd->description:"no description");
if (d)
Con_TPrintf("command ^2%s^7: ^3%s\n", cmd->name, d);
else
Con_TPrintf("command ^2%s^7: ^3no description\n", cmd->name);
}
//FIXME: add aliases.
}

View File

@ -1427,22 +1427,6 @@ static void Alias_BuildSkeletalMesh(mesh_t *mesh, framestate_t *framestate, gali
);
}
#if !defined(SERVERONLY)
static void Alias_BuildSkeletalVerts(float *xyzout, float *normout, framestate_t *framestate, galiasinfo_t *inf)
{
float buffer[MAX_BONES*12];
float bufferalt[MAX_BONES*12];
boneidx_t *fte_restrict bidx = inf->ofs_skel_idx[0];
float *fte_restrict weight = inf->ofs_skel_weight[0];
const float *bonepose = Alias_GetBoneInformation(inf, framestate, SKEL_INVERSE_ABSOLUTE, buffer, bufferalt, MAX_BONES);
if (normout)
Alias_TransformVerticies_VN(bonepose, inf->numverts, bidx, weight, inf->ofs_skel_xyz[0], xyzout, inf->ofs_skel_norm[0], normout);
else
Alias_TransformVerticies_V(bonepose, inf->numverts, bidx, weight, inf->ofs_skel_xyz[0], xyzout);
}
#endif
#if defined(MD5MODELS) || defined(ZYMOTICMODELS) || defined(DPMMODELS)
static int QDECL sortweights(const void *v1, const void *v2) //helper for Alias_BuildGPUWeights
{
@ -1941,7 +1925,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
//float fg2time;
static float printtimer;
#if FRAME_BLENDS != 2
#if defined(_DEBUG) && FRAME_BLENDS != 2
if (e->framestate.g[FS_REG].lerpweight[2] || e->framestate.g[FS_REG].lerpweight[3])
Con_ThrottlePrintf(&printtimer, 1, "Alias_GAliasBuildMesh(%s): non-skeletal animation only supports two animations\n", e->model->name);
#endif
@ -2128,174 +2112,190 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
//used by the modelviewer.
void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qboolean normals)
{
galiasinfo_t *mod;
scenetris_t *t;
vecV_t *posedata = NULL;
vec3_t *normdata = NULL, tmp;
int surfnum = 0, i;
#ifdef SKELETALMODELS
int cursurfnum = -1;
#endif
int i, j;
if (!ent->model || ent->model->loadstate != MLS_LOADED || ent->model->type != mod_alias)
batch_t *batches[SHADER_SORT_COUNT], *b;
int s;
mesh_t *m;
unsigned int meshidx;
if (!ent->model || ent->model->loadstate != MLS_LOADED)
return;
mod = Mod_Extradata(ent->model);
for(; mod; mod = mod->nextsurf, surfnum++)
memset(batches, 0, sizeof(batches));
r_refdef.frustum_numplanes = 0;
switch(ent->model->type)
{
if (surfaceidx < 0)
{
if (!mod->contents)
continue;
}
else if (surfnum != surfaceidx)
case mod_alias:
R_GAlias_GenerateBatches(ent, batches);
break;
#ifdef HALFLIFEMODELS
case mod_halflife:
R_HalfLife_GenerateBatches(ent, batches);
break;
#endif
default:
return;
}
for (s = 0; s < countof(batches); s++)
{
if (!batches[s])
continue;
normdata = NULL;
#ifdef SKELETALMODELS
if (mod->numbones)
for (b = batches[s]; b; b = b->next)
{
if (!mod->ofs_skel_idx)
posedata = mod->ofs_skel_xyz; //if there's no weights, don't try animating anything.
else if (mod->shares_verts != cursurfnum || !posedata)
if (b->buildmeshes)
b->buildmeshes(b);
for (meshidx = b->firstmesh; meshidx < b->meshes; meshidx++)
{
cursurfnum = mod->shares_verts;
if (surfaceidx < 0)
{ //only draw meshes that have an actual contents value (collision data)
//FIXME: implement.
}
else
{ //only draw the mesh that's actually selected.
if (b->user.alias.surfrefs[meshidx] != surfaceidx)
continue;
}
posedata = alloca(mod->numverts*sizeof(vecV_t));
normdata = normals?alloca(mod->numverts*sizeof(vec3_t)):NULL;
Alias_BuildSkeletalVerts((float*)posedata, (float*)normdata, &ent->framestate, mod);
}
//else posedata = posedata;
}
else
#endif
#ifndef NONSKELETALMODELS
continue;
#else
if (!mod->numanimations)
{
#ifdef SKELETALMODELS
normdata = mod->ofs_skel_norm;
if (mod->ofs_skel_xyz)
posedata = mod->ofs_skel_xyz;
else
#endif
continue;
}
else
{
galiaspose_t *pose;
galiasanimation_t *group = mod->ofsanimations;
group += ent->framestate.g[FS_REG].frame[0] % mod->numanimations;
//FIXME: no support for frame blending.
if (!group->numposes || !group->poseofs)
continue;
pose = group->poseofs;
pose += (int)(ent->framestate.g[FS_REG].frametime[0] * group->rate)%group->numposes;
posedata = pose->ofsverts;
normdata = pose->ofsnormals;
}
#endif
m = b->mesh[meshidx];
if (normals && normdata)
{ //pegs, one on each vertex.
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = shader;
t->flags = BEF_LINES;
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
t->numidx = t->numvert = mod->numverts*2;
if (cl_numstrisidx+t->numidx > cl_maxstrisidx)
{
cl_maxstrisidx=cl_numstrisidx+t->numidx;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
if (cl_numstrisvert+t->numvert > cl_maxstrisvert)
cl_stris_ExpandVerts(cl_numstrisvert+t->numvert);
for (i = 0; i < mod->numverts; i++)
{
VectorMA(vec3_origin, posedata[i][0], ent->axis[0], tmp);
VectorMA(tmp, posedata[i][1], ent->axis[1], tmp);
VectorMA(tmp, posedata[i][2], ent->axis[2], tmp);
VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i*2+0]);
VectorMA(tmp, normdata[i][0], ent->axis[0], tmp);
VectorMA(tmp, normdata[i][1], ent->axis[1], tmp);
VectorMA(tmp, normdata[i][2], ent->axis[2], tmp);
VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i*2+1]);
Vector2Set(cl_strisvertt[t->firstvert+i*2+0], 0.0, 0.0);
Vector2Set(cl_strisvertt[t->firstvert+i*2+1], 1.0, 1.0);
Vector4Set(cl_strisvertc[t->firstvert+i*2+0], 0, 0, 1, 1);
Vector4Set(cl_strisvertc[t->firstvert+i*2+1], 0, 0, 1, 1);
cl_strisidx[cl_numstrisidx+i*2+0] = i*2+0;
cl_strisidx[cl_numstrisidx+i*2+1] = i*2+1;
}
cl_numstrisidx += i*2;
cl_numstrisvert += i*2;
}
else
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = shader;
t->flags = 0;//BEF_LINES;
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
if (t->flags&BEF_LINES)
t->numidx = mod->numindexes*2;
else
t->numidx = mod->numindexes;
t->numvert = mod->numverts;
if (cl_numstrisidx+t->numidx > cl_maxstrisidx)
{
cl_maxstrisidx=cl_numstrisidx+t->numidx;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
if (cl_numstrisvert+mod->numverts > cl_maxstrisvert)
cl_stris_ExpandVerts(cl_numstrisvert+mod->numverts);
for (i = 0; i < mod->numverts; i++)
{
VectorMA(vec3_origin, posedata[i][0], ent->axis[0], tmp);
VectorMA(tmp, posedata[i][1], ent->axis[1], tmp);
VectorMA(tmp, posedata[i][2], ent->axis[2], tmp);
VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i]);
Vector2Set(cl_strisvertt[t->firstvert+i], 0.5, 0.5);
Vector4Set(cl_strisvertc[t->firstvert+i], (mod->contents?1:0), 1, 1, 0.1);
}
if (t->flags&BEF_LINES)
{
for (i = 0; i < mod->numindexes; i+=3)
posedata = m->xyz_array;
normdata = normals?m->normals_array:NULL;
if (m->numbones)
{ //intended shader might have caused it to use skeletal stuff.
//we're too lame for that though.
posedata = alloca(m->numvertexes*sizeof(vecV_t));
if (normdata)
{
normdata = alloca(m->numvertexes*sizeof(vec3_t));
Alias_TransformVerticies_VN(m->bones, m->numvertexes, m->bonenums[0], m->boneweights[0], m->xyz_array[0], posedata[0], m->normals_array[0], normdata[0]);
}
else
Alias_TransformVerticies_V(m->bones, m->numvertexes, m->bonenums[0], m->boneweights[0], m->xyz_array[0], posedata[0]);
}
else
{
cl_strisidx[cl_numstrisidx++] = mod->ofs_indexes[i+0];
cl_strisidx[cl_numstrisidx++] = mod->ofs_indexes[i+1];
cl_strisidx[cl_numstrisidx++] = mod->ofs_indexes[i+1];
cl_strisidx[cl_numstrisidx++] = mod->ofs_indexes[i+2];
cl_strisidx[cl_numstrisidx++] = mod->ofs_indexes[i+2];
cl_strisidx[cl_numstrisidx++] = mod->ofs_indexes[i+0];
if (m->xyz_blendw[1] == 1 && m->xyz2_array)
posedata = m->xyz2_array;
else if (m->xyz_blendw[0] != 1 && m->xyz2_array)
{
posedata = alloca(m->numvertexes*sizeof(vecV_t));
for (i = 0; i < m->numvertexes; i++)
{
for (j = 0; j < 3; j++)
posedata[i][j] = m->xyz_array[i][j] * m->xyz_blendw[0] +
m->xyz2_array[i][j] * m->xyz_blendw[1];
}
}
else
posedata = m->xyz_array;
}
if (normdata)
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = shader;
t->flags = BEF_LINES;
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
t->numidx = t->numvert = m->numvertexes*2;
if (cl_numstrisidx+t->numidx > cl_maxstrisidx)
{
cl_maxstrisidx=cl_numstrisidx+t->numidx;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
if (cl_numstrisvert+t->numvert > cl_maxstrisvert)
cl_stris_ExpandVerts(cl_numstrisvert+t->numvert);
for (i = 0; i < m->numvertexes; i++)
{
VectorMA(vec3_origin, posedata[i][0], ent->axis[0], tmp);
VectorMA(tmp, posedata[i][1], ent->axis[1], tmp);
VectorMA(tmp, posedata[i][2], ent->axis[2], tmp);
VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i*2+0]);
VectorMA(tmp, normdata[i][0], ent->axis[0], tmp);
VectorMA(tmp, normdata[i][1], ent->axis[1], tmp);
VectorMA(tmp, normdata[i][2], ent->axis[2], tmp);
VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i*2+1]);
Vector2Set(cl_strisvertt[t->firstvert+i*2+0], 0.0, 0.0);
Vector2Set(cl_strisvertt[t->firstvert+i*2+1], 1.0, 1.0);
Vector4Set(cl_strisvertc[t->firstvert+i*2+0], 0, 0, 1, 1);
Vector4Set(cl_strisvertc[t->firstvert+i*2+1], 0, 0, 1, 1);
cl_strisidx[cl_numstrisidx+i*2+0] = i*2+0;
cl_strisidx[cl_numstrisidx+i*2+1] = i*2+1;
}
cl_numstrisidx += i*2;
cl_numstrisvert += i*2;
}
if (!normals)
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = shader;
t->flags = 0;//BEF_LINES;
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
if (t->flags&BEF_LINES)
t->numidx = m->numindexes*2;
else
t->numidx = m->numindexes;
t->numvert = m->numvertexes;
if (cl_numstrisidx+t->numidx > cl_maxstrisidx)
{
cl_maxstrisidx=cl_numstrisidx+t->numidx;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
if (cl_numstrisvert+m->numvertexes > cl_maxstrisvert)
cl_stris_ExpandVerts(cl_numstrisvert+m->numvertexes);
for (i = 0; i < m->numvertexes; i++)
{
VectorMA(vec3_origin, posedata[i][0], ent->axis[0], tmp);
VectorMA(tmp, posedata[i][1], ent->axis[1], tmp);
VectorMA(tmp, posedata[i][2], ent->axis[2], tmp);
VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i]);
Vector2Set(cl_strisvertt[t->firstvert+i], 0.5, 0.5);
Vector4Set(cl_strisvertc[t->firstvert+i], 1, 1, 1, 0.1);
}
if (t->flags&BEF_LINES)
{
for (i = 0; i < m->numindexes; i+=3)
{
cl_strisidx[cl_numstrisidx++] = m->indexes[i+0];
cl_strisidx[cl_numstrisidx++] = m->indexes[i+1];
cl_strisidx[cl_numstrisidx++] = m->indexes[i+1];
cl_strisidx[cl_numstrisidx++] = m->indexes[i+2];
cl_strisidx[cl_numstrisidx++] = m->indexes[i+2];
cl_strisidx[cl_numstrisidx++] = m->indexes[i+0];
}
}
else
{
for (i = 0; i < m->numindexes; i++)
cl_strisidx[cl_numstrisidx+i] = m->indexes[i];
cl_numstrisidx += m->numindexes;
}
cl_numstrisvert += m->numvertexes;
}
}
else
{
for (i = 0; i < mod->numindexes; i++)
cl_strisidx[cl_numstrisidx+i] = mod->ofs_indexes[i];
cl_numstrisidx += mod->numindexes;
}
cl_numstrisvert += mod->numverts;
}
}
}
@ -5487,8 +5487,14 @@ shader_t *Mod_ShaderForSkin(model_t *model, int surfaceidx, int num)
return NULL;
}
if (model->type == mod_alias)
switch(model->type)
{
case mod_brush:
if (surfaceidx < model->numtextures && !num)
return model->textures[surfaceidx]->shader;
return NULL;
case mod_alias:
inf = Mod_Extradata(model);
while(surfaceidx-->0 && inf)
@ -5498,11 +5504,9 @@ shader_t *Mod_ShaderForSkin(model_t *model, int surfaceidx, int num)
return NULL;
skin = inf->ofsskins;
return skin[num].frame[0].shader;
}
else if (model->type == mod_brush && surfaceidx < model->numtextures && !num)
return model->textures[surfaceidx]->shader;
else
default:
return NULL;
}
}
#endif
const char *Mod_SkinNameForNum(model_t *model, int surfaceidx, int num)
@ -5523,23 +5527,27 @@ const char *Mod_SkinNameForNum(model_t *model, int surfaceidx, int num)
return NULL;
}
if (!model || model->type != mod_alias)
switch(model->type)
{
if (model->type == mod_brush && surfaceidx < model->numtextures && !num)
case mod_brush:
if (surfaceidx < model->numtextures && !num)
return "";
return NULL;
}
inf = Mod_Extradata(model);
case mod_alias:
inf = Mod_Extradata(model);
while(surfaceidx-->0 && inf)
inf = inf->nextsurf;
if (!inf || num >= inf->numskins)
while(surfaceidx-->0 && inf)
inf = inf->nextsurf;
if (!inf || num >= inf->numskins)
return NULL;
skin = inf->ofsskins;
// if (!*skin[num].name)
// return skin[num].frame[0].shadername;
// else
return skin[num].name;
default:
return NULL;
skin = inf->ofsskins;
// if (!*skin[num].name)
// return skin[num].frame[0].shadername;
// else
return skin[num].name;
}
#endif
}
@ -5550,20 +5558,39 @@ const char *Mod_SurfaceNameForNum(model_t *model, int num)
#else
galiasinfo_t *inf;
if (!model || model->type != mod_alias)
if (!model || model->loadstate != MLS_LOADED)
{
if (model && model->loadstate == MLS_NOTLOADED)
Mod_LoadModel(model, MLV_SILENT);
if (model && model->loadstate == MLS_LOADING)
COM_WorkerPartialSync(model, &model->loadstate, MLS_LOADING);
if (!model || model->loadstate != MLS_LOADED)
return NULL;
}
switch(model->type)
{
case mod_brush:
if (model->type == mod_brush && num < model->numtextures)
return model->textures[num]->name;
return NULL;
}
inf = Mod_Extradata(model);
while(num-->0 && inf)
inf = inf->nextsurf;
if (inf)
return inf->surfacename;
else
case mod_halflife:
return NULL;
case mod_alias:
inf = Mod_Extradata(model);
while(num-->0 && inf)
inf = inf->nextsurf;
if (inf)
return inf->surfacename;
else
return NULL;
case mod_sprite:
case mod_dummy:
case mod_heightmap:
default:
return NULL;
}
#endif
}

View File

@ -1022,7 +1022,7 @@ coorddata MSG_ToAngle(float f, int bytes) //return value is NOT byteswapped.
void MSG_WriteCoord (sizebuf_t *sb, float f)
{
coorddata i = MSG_ToCoord(f, sb->prim.coordtype);
SZ_Write (sb, (void*)&i, sb->prim.coordtype&0xf);
SZ_Write (sb, (void*)&i, sb->prim.coordtype&COORDTYPE_SIZE_MASK);
}
void MSG_WriteAngle16 (sizebuf_t *sb, float f)
@ -1684,13 +1684,13 @@ float MSG_ReadCoord (void)
coorddata c = {{0}};
if (net_message.prim.coordtype == COORDTYPE_UNDEFINED)
net_message.prim.coordtype = COORDTYPE_FIXED_13_3;
MSG_ReadData(&c, net_message.prim.coordtype&0xf);
MSG_ReadData(c.b, net_message.prim.coordtype&COORDTYPE_SIZE_MASK);
return MSG_FromCoord(c, net_message.prim.coordtype);
}
float MSG_ReadCoordFloat (void)
{
coorddata c = {{0}};
MSG_ReadData(&c, COORDTYPE_FLOAT_32&0xf);
MSG_ReadData(c.b, COORDTYPE_FLOAT_32&COORDTYPE_SIZE_MASK);
return MSG_FromCoord(c, COORDTYPE_FLOAT_32);
}
@ -7775,7 +7775,7 @@ void Con_TPrintf (translation_t stringnum, ...)
if (!Sys_IsMainThread())
{ //shouldn't be redirected anyway...
fmt = langtext(stringnum,com_language);
fmt = localtext(stringnum);
va_start (argptr,stringnum);
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
va_end (argptr);
@ -7799,7 +7799,7 @@ void Con_TPrintf (translation_t stringnum, ...)
}
#endif
fmt = langtext(stringnum,com_language);
fmt = localtext(stringnum);
va_start (argptr,stringnum);
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);

View File

@ -160,6 +160,7 @@ struct netprim_s
#define COORDTYPE_FIXED_16_8 3 //rmq
#define COORDTYPE_FIXED_28_4 4 //rmq, pointless
#define COORDTYPE_FLOAT_32 (4|0x80) //fte/dp/rmq
#define COORDTYPE_SIZE_MASK 0xf //coordtype&mask == number of bytes.
qbyte anglesize;
qbyte flags;
#define NPQ2_ANG16 (1u<<0)
@ -756,6 +757,7 @@ int FS_GetManifestArgv(char **argv, int maxargs);
struct zonegroup_s;
void *FS_LoadMallocGroupFile(struct zonegroup_s *ctx, char *path, size_t *fsize, qboolean filters);
qbyte *FS_LoadMallocFile (const char *path, size_t *fsize);
qbyte *FS_LoadMallocFileFlags (const char *path, unsigned int locateflags, size_t *fsize);
qofs_t FS_LoadFile(const char *name, void **file);
void FS_FreeFile(void *file);
@ -918,7 +920,15 @@ void Log_ShutDown(void);
void IPLog_Add(const char *ip, const char *name); //for associating player ip addresses with names.
qboolean IPLog_Merge_File(const char *fname);
#endif
qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize);
enum certlog_problem_e
{
CERTLOG_WRONGHOST,
CERTLOG_EXPIRED,
CERTLOG_MISSINGCA,
CERTLOG_UNKNOWN,
};
qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize, unsigned int certlogproblems);
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
qboolean Log_CheckMapCompletion(const char *packagename, const char *mapname, float *besttime, float *fulltime, float *bestkills, float *bestsecrets);

View File

@ -1239,8 +1239,8 @@ cvar_t *Cvar_Get2(const char *name, const char *defaultvalue, int flags, const c
if (var)
return var;
if (!description)
description = "";
if (!description || !*description)
description = NULL;
//don't allow cvars with certain funny chars in their name. ever. such things get really messy when saved in configs or whatever.
if (!*name || strchr(name, '\"') || strchr(name, '^') || strchr(name, '$') || strchr(name, ' ') || strchr(name, '\t') || strchr(name, '\r') || strchr(name, '\n') || strchr(name, ';'))
@ -1313,13 +1313,13 @@ qboolean Cvar_Command (int level)
if (!level || (v->restriction?v->restriction:rcon_level.ival) > level)
{
Con_Printf ("You do not have the priveledges for %s\n", v->name);
Con_TPrintf ("You do not have the priveledges for %s\n", v->name);
return true;
}
if (v->flags & CVAR_NOTFROMSERVER && Cmd_IsInsecure())
{
Con_Printf ("Server tried setting %s cvar\n", v->name);
Con_TPrintf ("Server tried setting %s cvar\n", v->name);
return true;
}
@ -1330,36 +1330,36 @@ qboolean Cvar_Command (int level)
{
if (v->flags & CVAR_LATCH)
{
Con_Printf ("\"%s\" is currently \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_Printf ("Will be changed to \"%s\" on the next map\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
Con_TPrintf ("\"%s\" is currently \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_TPrintf ("Will be changed to \"%s\" on the next map\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
}
else if (v->flags & CVAR_VIDEOLATCH)
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_Printf ("Will be changed to \"%s\" on vid_restart\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
Con_TPrintf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_TPrintf ("Will be changed to \"%s\" on vid_restart\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
}
else if (v->flags & CVAR_RENDERERLATCH)
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_Printf ("Will be changed to \"%s\" on vid_reload\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
Con_TPrintf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_TPrintf ("Will be changed to \"%s\" on vid_reload\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
}
else
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
Con_Printf ("Effective value is \"%s\"\n", COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_TPrintf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->latched_string, buffer, sizeof(buffer), true));
Con_TPrintf ("Effective value is \"%s\"\n", COM_QuotedString(v->string, buffer, sizeof(buffer), true));
}
if (v->defaultstr)
Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), true));
Con_TPrintf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), true));
}
else
{
if (v->defaultstr && !strcmp(v->string, v->defaultstr))
Con_Printf ("\"%s\" is \"%s\" (default)\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_TPrintf ("\"%s\" is \"%s\" (default)\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
else
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
Con_TPrintf ("\"%s\" is \"%s\"\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer), true));
if (v->defaultstr)
Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), true));
Con_TPrintf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer), true));
}
}
return true;
@ -1373,7 +1373,7 @@ qboolean Cvar_Command (int level)
if (v->flags & CVAR_NOSET)
{
if (cl_warncmd.value || developer.value)
Con_Printf ("Cvar %s may not be set via the console\n", v->name);
Con_TPrintf ("Cvar %s may not be set via the console\n", v->name);
return true;
}

View File

@ -103,8 +103,6 @@ typedef struct cvar_s
#define CVARD(ConsoleName,Value,Description) CVARAFCD(ConsoleName, Value, NULL, 0, NULL, Description)
#define CVAR(ConsoleName,Value) CVARD(ConsoleName, Value, NULL)
#define CVARDP4(Flags,ConsoleName,Value,Description) CVARFD(ConsoleName, Value, Flags,Description)
typedef struct cvar_group_s
{
const char *name;

View File

@ -2601,6 +2601,10 @@ qbyte *FS_LoadMallocFile (const char *path, size_t *fsize)
{
return COM_LoadFile (path, 0, 5, fsize);
}
qbyte *FS_LoadMallocFileFlags (const char *path, unsigned int locateflags, size_t *fsize)
{
return COM_LoadFile (path, locateflags, 5, fsize);
}
void *FS_LoadMallocGroupFile(zonegroup_t *ctx, char *path, size_t *fsize, qboolean filters)
{
@ -5206,7 +5210,7 @@ static ftemanifest_t *FS_GenerateLegacyManifest(int game, const char *basedir)
{
man = FS_Manifest_Create(NULL, basedir);
for (cexec = gamemode_info[game].customexec; cexec[0] == '/' && cexec[1] == '/'; )
for (cexec = gamemode_info[game].customexec; cexec && cexec[0] == '/' && cexec[1] == '/'; )
{
char line[256];
char *e = strchr(cexec, '\n');

View File

@ -1670,6 +1670,19 @@ static qboolean FSZIP_ReadCentralEntry(zipfile_t *zip, qbyte *data, struct zipce
//access and creation do NOT exist in the central header.
extra += extrachunk_len;
break;
case 0x7075: //unicode (utf-8) filename replacements.
if (extra[0] == 1) //version
{
//if (LittleU4FromPtr(extra+1) == qcrc32(?,entry->fname, entry->fnane_len))
{
entry->fname = extra+5;
entry->fnane_len = extrachunk_len-5;
extra += extrachunk_len;
entry->gflags |= (1u<<11); //just set that flag. we don't support comments anyway.
}
}
break;
default:
/* Con_Printf("Unknown chunk %x\n", extrachunk_tag);
case 0x5455: //extended timestamp

View File

@ -640,7 +640,10 @@ struct certlog_s
size_t certsize;
qbyte cert[1];
};
#define CERTLOG_FILENAME "knowncerts.txt"
static link_t certlog;
static qboolean certlog_inited = false;
static void CertLog_Import(const char *filename);
static struct certlog_s *CertLog_Find(const char *hostname)
{
struct certlog_s *l;
@ -669,7 +672,7 @@ static void CertLog_Update(const char *hostname, const void *cert, size_t certsi
static void CertLog_Write(void)
{
struct certlog_s *l;
vfsfile_t *f = NULL;//FS_OpenVFS("knowncerts.txt", "wb", FS_ROOT);
vfsfile_t *f = FS_OpenVFS(CERTLOG_FILENAME, "wb", FS_ROOT);
if (f)
{
VFS_PRINTF(f, "version 1.0\n");
@ -685,7 +688,9 @@ static void CertLog_Write(void)
certhex[i*2+1] = hex[l->cert[i]&0xf];
}
certhex[i*2] = 0;
VFS_PRINTF(f, "%s \"%s\"\n", l->hostname, certhex);
VFS_PRINTF(f, "%s \"", l->hostname);
VFS_PUTS(f, certhex);
VFS_PRINTF(f, "\"\n");
}
}
}
@ -697,6 +702,8 @@ static void CertLog_Purge(void)
RemoveLink(&l->l);
Z_Free(l);
}
certlog_inited = false;
}
static int hexdecode(char c)
{
@ -715,7 +722,13 @@ static void CertLog_Import(const char *filename)
char certdata[16384];
char line[65536], *l;
size_t i, certsize;
vfsfile_t *f = FS_OpenVFS(filename, "rb", FS_ROOT);
vfsfile_t *f;
if (!certlog_inited && filename)
CertLog_Import(NULL);
certlog_inited |= !filename;
f = FS_OpenVFS(filename?filename:CERTLOG_FILENAME, "rb", FS_ROOT);
if (!f)
return;
//CertLog_Purge();
VFS_GETS(f, line, sizeof(line));
if (strncmp(line, "version 1.", 10))
@ -743,8 +756,10 @@ static void CertLog_UntrustAll_f(void)
static void CertLog_Import_f(void)
{
const char *fname = Cmd_Argv(1);
if (Cmd_IsInsecure())
return;
if (!*fname)
fname = "knowncerts.txt";
fname = NULL;
CertLog_Import(fname);
}
struct certprompt_s
@ -762,34 +777,64 @@ static void CertLog_Add_Prompted(void *vctx, promptbutton_t button)
{
CertLog_Update(ctx->hostname, ctx->cert, ctx->certsize);
CertLog_Write();
CL_BeginServerReconnect();
}
else
CL_Disconnect("Server certificate rejected");
certlog_curprompt = NULL;
}
qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize)
qboolean CertLog_ConnectOkay(const char *hostname, void *cert, size_t certsize, unsigned int certlogproblems)
{
struct certlog_s *l = CertLog_Find(hostname);
struct certlog_s *l;
if (certlog_curprompt)
return false;
if (!certlog_inited)
CertLog_Import(NULL);
l = CertLog_Find(hostname);
if (!l || l->certsize != certsize || memcmp(l->cert, cert, certsize))
{
{ //new or different
if (qrenderer)
{
unsigned int i;
size_t len;
char *text;
const char *accepttext;
const char *lines[] = {
va(localtext("Certificate for %s\n"), hostname),
(certlogproblems&CERTLOG_WRONGHOST)?localtext("^1Certificate does not match host\n"):"",
((certlogproblems&(CERTLOG_MISSINGCA|CERTLOG_WRONGHOST))==CERTLOG_MISSINGCA)?localtext("^1Certificate authority is untrusted.\n"):"",
(certlogproblems&CERTLOG_EXPIRED)?localtext("^1Expired Certificate\n"):"",
l?localtext("\n^1WARNING: Certificate has changed since previously trusted."):""};
struct certprompt_s *ctx = certlog_curprompt = Z_Malloc(sizeof(*ctx)+certsize + strlen(hostname));
ctx->hostname = ctx->cert + certsize;
ctx->certsize = certsize;
memcpy(ctx->cert, cert, certsize);
strcpy(ctx->hostname, hostname);
//FIXME: display some sort of fingerprint
if (!l)
Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\nServer certificate is\nself-signed", hostname), "Trust", NULL, "Disconnect");
if (l) //FIXME: show expiry info for the old cert, warn if more than a month?
accepttext = localtext("Replace Trust");
else if (!certlogproblems)
accepttext = localtext("Pin Trust");
else
Menu_Prompt(CertLog_Add_Prompted, ctx, va("%s\n^1Server certificate HAS CHANGED\nZomg\n^bFlee in Terror", hostname), "ReTrust", NULL, "Disconnect");
accepttext = localtext("Trust Anyway");
for (i = 0, len = 0; i < countof(lines); i++)
len += strlen(lines[i]);
text = alloca(len+1);
for (i = 0, len = 0; i < countof(lines); i++)
{
strcpy(text+len, lines[i]);
len += strlen(lines[i]);
}
text[len] = 0;
//FIXME: display some sort of fingerprint
Menu_Prompt(CertLog_Add_Prompted, ctx, text, accepttext, NULL, localtext("Disconnect"));
}
return false; //can't connect yet...
}

View File

@ -469,9 +469,11 @@ static qboolean QDECL SSL_CloseFile(vfsfile_t *vfs)
return true;
}
static qboolean SSL_CheckUserTrust(gnutls_session_t session, gnutlsfile_t *file, int *errorcode)
static int SSL_CheckUserTrust(gnutls_session_t session, gnutlsfile_t *file, int gcertcode)
{
int ret = gcertcode?GNUTLS_E_CERTIFICATE_ERROR:GNUTLS_E_SUCCESS;
#ifdef HAVE_CLIENT
unsigned int ferrcode;
//when using dtls, we expect self-signed certs and persistent trust.
if (file->datagram)
{
@ -487,16 +489,27 @@ static qboolean SSL_CheckUserTrust(gnutls_session_t session, gnutlsfile_t *file,
memcpy(certdata+certsize, certlist[j].data, certlist[j].size);
certsize += certlist[j].size;
}
if (CertLog_ConnectOkay(file->certname, certdata, certsize))
*errorcode = 0; //user has previously authorised it.
//if gcertcode is 0 then we can still pin it.
ferrcode = 0;
if (gcertcode & GNUTLS_CERT_SIGNER_NOT_FOUND)
ferrcode |= CERTLOG_MISSINGCA;
if (gcertcode & GNUTLS_CERT_UNEXPECTED_OWNER)
ferrcode |= CERTLOG_WRONGHOST;
if (gcertcode & GNUTLS_CERT_EXPIRED)
ferrcode |= CERTLOG_EXPIRED;
if (gcertcode & ~(GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND|GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_EXPIRED))
ferrcode |= CERTLOG_UNKNOWN;
if (CertLog_ConnectOkay(file->certname, certdata, certsize, ferrcode))
ret = GNUTLS_E_SUCCESS; //user has previously authorised it.
else
*errorcode = GNUTLS_E_CERTIFICATE_ERROR; //user didn't trust it yet
ret = GNUTLS_E_CERTIFICATE_ERROR; //user didn't trust it yet
free(certdata);
return true;
}
#endif
return false;
return ret;
}
static int QDECL SSL_CheckCert(gnutls_session_t session)
@ -566,16 +579,13 @@ static int QDECL SSL_CheckCert(gnutls_session_t session)
{
gnutls_datum_t out;
gnutls_certificate_type_t type;
int ret;
if (preverified && (certstatus&~GNUTLS_CERT_EXPIRED) == (GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND))
return 0;
if (certstatus == 0)
return SSL_CheckUserTrust(session, file, 0);
if (certstatus == (GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND))
{
if (SSL_CheckUserTrust(session, file, &errcode))
return errcode;
}
ret = SSL_CheckUserTrust(session, file, certstatus);
if (!ret)
return ret;
type = qgnutls_certificate_type_get (session);
if (qgnutls_certificate_verification_status_print(certstatus, type, &out, 0) >= 0)
@ -592,6 +602,7 @@ static int QDECL SSL_CheckCert(gnutls_session_t session)
if (certlist && certslen)
{
//and make sure the hostname on it actually makes sense.
int ret;
gnutls_x509_crt_t cert;
qgnutls_x509_crt_init(&cert);
qgnutls_x509_crt_import(cert, certlist, GNUTLS_X509_FMT_DER);
@ -599,10 +610,10 @@ static int QDECL SSL_CheckCert(gnutls_session_t session)
{
if (preverified && (certstatus&~GNUTLS_CERT_EXPIRED) == (GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND))
return 0;
if (certstatus == 0)
return SSL_CheckUserTrust(session, file, 0);
if (certstatus == (GNUTLS_CERT_INVALID|GNUTLS_CERT_SIGNER_NOT_FOUND) && SSL_CheckUserTrust(session, file, GNUTLS_E_CERTIFICATE_ERROR))
return 0;
ret = SSL_CheckUserTrust(session, file, certstatus); //looks okay... pin it by default...
if (!ret)
return ret;
if (certstatus & GNUTLS_CERT_SIGNER_NOT_FOUND)
Con_Printf(CON_ERROR "%s: Certificate authority is not recognised\n", file->certname);
@ -1233,7 +1244,7 @@ int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
}
}
//generates a signed blob
//crypto: generates a signed blob
int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax)
{
gnutls_datum_t hash = {hashdata, hashsize};
@ -1264,7 +1275,7 @@ int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata,
return sign.size;
}
//windows equivelent https://docs.microsoft.com/en-us/windows/win32/seccrypto/example-c-program-signing-a-hash-and-verifying-the-hash-signature
//crypto: verifies a signed blob matches an authority's public cert. windows equivelent https://docs.microsoft.com/en-us/windows/win32/seccrypto/example-c-program-signing-a-hash-and-verifying-the-hash-signature
enum hashvalidation_e GNUTLS_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize)
{
gnutls_datum_t hash = {hashdata, hashsize};

View File

@ -7733,19 +7733,19 @@ int NET_EnumerateAddresses(ftenet_connections_t *collection, struct ftenet_gener
static enum addressscope_e NET_ClassifyAddressipv4(int ip, const char **outdesc)
{
int scope = ASCOPE_NET;
char *desc = NULL;
const char *desc = NULL;
if ((ip&BigLong(0xffff0000)) == BigLong(0xA9FE0000)) //169.254.x.x/16
scope = ASCOPE_LINK, desc = "link-local";
scope = ASCOPE_LINK, desc = localtext("link-local");
else if ((ip&BigLong(0xff000000)) == BigLong(0x0a000000)) //10.x.x.x/8
scope = ASCOPE_LAN, desc = "private";
scope = ASCOPE_LAN, desc = localtext("private");
else if ((ip&BigLong(0xff000000)) == BigLong(0x7f000000)) //127.x.x.x/8
scope = ASCOPE_HOST, desc = "localhost";
else if ((ip&BigLong(0xfff00000)) == BigLong(0xac100000)) //172.16.x.x/12
scope = ASCOPE_LAN, desc = "private";
scope = ASCOPE_LAN, desc = localtext("private");
else if ((ip&BigLong(0xffff0000)) == BigLong(0xc0a80000)) //192.168.x.x/16
scope = ASCOPE_LAN, desc = "private";
scope = ASCOPE_LAN, desc = localtext("private");
else if ((ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //100.64.x.x/10
scope = ASCOPE_LAN, desc = "CGNAT";
scope = ASCOPE_LAN, desc = localtext("CGNAT");
else if (ip == BigLong(0x00000000)) //0.0.0.0/32
scope = ASCOPE_LAN, desc = "any";
@ -7760,14 +7760,14 @@ enum addressscope_e NET_ClassifyAddress(netadr_t *adr, const char **outdesc)
if (adr->type == NA_LOOPBACK)
{
//we don't list 127.0.0.1 or ::1, so don't bother with this either. its not interesting.
scope = ASCOPE_PROCESS, desc = "internal";
scope = ASCOPE_PROCESS, desc = localtext("internal");
}
else if (adr->type == NA_IPV6)
{
if ((*(int*)adr->address.ip6&BigLong(0xffc00000)) == BigLong(0xfe800000)) //fe80::/10
scope = ASCOPE_LINK, desc = "link-local";
scope = ASCOPE_LINK, desc = localtext("link-local");
else if ((*(int*)adr->address.ip6&BigLong(0xfe000000)) == BigLong(0xfc00000)) //fc::/7
scope = ASCOPE_LAN, desc = "ULA/private";
scope = ASCOPE_LAN, desc = localtext("ULA/private");
else if (*(int*)adr->address.ip6 == BigLong(0x20010000)) //2001::/32
scope = ASCOPE_NET, desc = "toredo";
else if ((*(int*)adr->address.ip6&BigLong(0xffff0000)) == BigLong(0x20020000)) //2002::/16
@ -7780,7 +7780,7 @@ enum addressscope_e NET_ClassifyAddress(netadr_t *adr, const char **outdesc)
{
scope = NET_ClassifyAddressipv4(*(int*)(adr->address.ip6+12), &desc);
if (!desc)
desc = "vp-mapped";
desc = localtext("v4-mapped");
}
}
#ifdef UNIXSOCKETS
@ -7826,20 +7826,20 @@ void NET_PrintAddresses(ftenet_connections_t *collection)
if ((addr[i].prot == NP_RTC_TCP || addr[i].prot == NP_RTC_TLS) && params[i])
{
if (addr[i].type == NA_INVALID)
Con_Printf("%s address (%s): /%s\n", scopes[scope], con[i]->name, params[i]);
Con_TPrintf("%s address (%s): /%s\n", scopes[scope], con[i]->name, params[i]);
else
Con_Printf("%s address (%s): %s/%s\n", scopes[scope], con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]), params[i]);
Con_TPrintf("%s address (%s): %s/%s\n", scopes[scope], con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]), params[i]);
}
else if (desc)
Con_Printf("%s address (%s): %s (%s)\n", scopes[scope], con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]), desc);
Con_TPrintf("%s address (%s): %s (%s)\n", scopes[scope], con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]), desc);
else
Con_Printf("%s address (%s): %s\n", scopes[scope], con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
Con_TPrintf("%s address (%s): %s\n", scopes[scope], con[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &addr[i]));
}
}
}
if (warn)
Con_Printf("net address: no public addresses\n");
Con_TPrintf("net address: no public addresses\n");
}
void NET_PrintConnectionsStatus(ftenet_connections_t *collection)

View File

@ -344,6 +344,7 @@ enum hashvalidation_e
VH_INCORRECT, //signature is wrong for that authority (bad, probably maliciously so)
VH_CORRECT //all is well.
};
struct dtlsfuncs_s;
#ifdef HAVE_DTLS
typedef struct dtlsfuncs_s
{
@ -360,23 +361,23 @@ const dtlsfuncs_t *DTLS_InitClient(void);
#ifdef HAVE_WINSSPI
vfsfile_t *SSPI_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
int SSPI_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
const dtlsfuncs_t *SSPI_DTLS_InitServer(void); //returns NULL if there's no cert available.
const dtlsfuncs_t *SSPI_DTLS_InitClient(void); //should always return something, if implemented.
const struct dtlsfuncs_s *SSPI_DTLS_InitServer(void); //returns NULL if there's no cert available.
const struct dtlsfuncs_s *SSPI_DTLS_InitClient(void); //should always return something, if implemented.
enum hashvalidation_e SSPI_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
#endif
#ifdef HAVE_GNUTLS
vfsfile_t *GNUTLS_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
const dtlsfuncs_t *GNUDTLS_InitServer(void); //returns NULL if there's no cert available.
const dtlsfuncs_t *GNUDTLS_InitClient(void); //should always return something, if implemented.
const struct dtlsfuncs_s *GNUDTLS_InitServer(void); //returns NULL if there's no cert available.
const struct dtlsfuncs_s *GNUDTLS_InitClient(void); //should always return something, if implemented.
enum hashvalidation_e GNUTLS_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax);
#endif
#ifdef HAVE_OPENSSL
vfsfile_t *OSSL_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
int OSSL_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
const dtlsfuncs_t *OSSL_InitServer(void); //returns NULL if there's no cert available.
const dtlsfuncs_t *OSSL_InitClient(void); //should always return something, if implemented.
const struct dtlsfuncs_s *OSSL_InitServer(void); //returns NULL if there's no cert available.
const struct dtlsfuncs_s *OSSL_InitClient(void); //should always return something, if implemented.
enum hashvalidation_e OSSL_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
#endif

View File

@ -1572,7 +1572,12 @@ void QCBUILTIN PF_cvar_description (pubprogfuncs_t *prinst, struct globalvars_s
const char *str = PR_GetStringOfs(prinst, OFS_PARM0);
cvar_t *cv = PF_Cvar_FindOrGet(str);
if (cv && !(cv->flags & CVAR_NOUNSAFEEXPAND))
RETURN_CSTRING(cv->description);
{
if (cv->description)
RETURN_CSTRING(localtext(cv->description));
else
G_INT(OFS_RETURN) = 0;
}
else
G_INT(OFS_RETURN) = 0;
}

View File

@ -1,5 +1,8 @@
#include "quakedef.h"
//#define COLOURMISSINGSTRINGS //for english people to more easily see what's not translatable (text still white)
//#define COLOURUNTRANSLATEDSTRINGS //show empty translations as alt-text versions of the original string
//client may remap messages from the server to a regional bit of text.
//server may remap progs messages
@ -74,7 +77,9 @@ static int TL_LoadLanguage(char *lang)
languages[j].name = strdup(lang);
languages[j].po = NULL;
#ifndef COLOURUNTRANSLATEDSTRINGS
if (f)
#endif
{
languages[j].po = PO_Create();
PO_Merge(languages[j].po, f);
@ -299,17 +304,7 @@ struct po_s
struct poline_s *lines;
};
const char *PO_GetText(struct po_s *po, const char *msg)
{
struct poline_s *line;
if (!po)
return msg;
line = Hash_Get(&po->hash, msg);
if (line)
return line->translated;
return msg;
}
static void PO_AddText(struct po_s *po, const char *orig, const char *trans)
static struct poline_s *PO_AddText(struct po_s *po, const char *orig, const char *trans)
{
size_t olen = strlen(orig)+1;
size_t tlen = strlen(trans)+1;
@ -323,6 +318,7 @@ static void PO_AddText(struct po_s *po, const char *orig, const char *trans)
line->next = po->lines;
po->lines = line;
return line;
}
void PO_Merge(struct po_s *po, vfsfile_t *file)
{
@ -330,6 +326,15 @@ void PO_Merge(struct po_s *po, vfsfile_t *file)
int inlen;
char msgid[32768];
char msgstr[32768];
struct {
quint32_t magic;
quint32_t revision;
quint32_t numstrings;
quint32_t offset_orig;
quint32_t offset_trans;
// quint32_t hashsize;
// quint32_t offset_hash;
} *moheader;
qboolean allowblanks = !!COM_CheckParm("-translatetoblank");
if (!file)
@ -343,61 +348,95 @@ void PO_Merge(struct po_s *po, vfsfile_t *file)
if (file)
VFS_CLOSE(file);
end = in + inlen;
while(in < end)
moheader = (void*)in;
if (inlen >= sizeof(*moheader) && moheader->magic == 0x950412de)
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
if (*in == '#')
struct
{
while (*in && *in != '\n')
quint32_t length;
quint32_t offset;
} *src = (void*)(in+moheader->offset_orig), *dst = (void*)(in+moheader->offset_trans);
quint32_t i;
for (i = moheader->numstrings; i-- > 0; src++, dst++)
PO_AddText(po, in+src->offset, in+dst->offset);
}
else
{
end = in + inlen;
while(in < end)
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
}
else if (!strncmp(in, "msgid", 5) && (in[5] == ' ' || in[5] == '\t' || in[5] == '\r' || in[5] == '\n'))
{
size_t start = 0;
size_t ofs = 0;
in += 5;
while(1)
if (*in == '#')
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
while (*in && *in != '\n')
in++;
if (*in == '\"')
{
in = COM_ParseCString(in, msgid+start, sizeof(msgid) - start, &ofs);
start += ofs;
}
else
break;
}
}
else if (!strncmp(in, "msgstr", 6) && (in[6] == ' ' || in[6] == '\t' || in[6] == '\r' || in[6] == '\n'))
{
size_t start = 0;
size_t ofs = 0;
in += 6;
while(1)
else if (!strncmp(in, "msgid", 5) && (in[5] == ' ' || in[5] == '\t' || in[5] == '\r' || in[5] == '\n'))
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
if (*in == '\"')
size_t start = 0;
size_t ofs = 0;
in += 5;
while(1)
{
in = COM_ParseCString(in, msgstr+start, sizeof(msgstr) - start, &ofs);
start += ofs;
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
if (*in == '\"')
{
in = COM_ParseCString(in, msgid+start, sizeof(msgid) - start, &ofs);
start += ofs;
}
else
break;
}
else
break;
}
else if (!strncmp(in, "msgstr", 6) && (in[6] == ' ' || in[6] == '\t' || in[6] == '\r' || in[6] == '\n'))
{
size_t start = 0;
size_t ofs = 0;
in += 6;
while(1)
{
while(*in == ' ' || *in == '\n' || *in == '\r' || *in == '\t')
in++;
if (*in == '\"')
{
in = COM_ParseCString(in, msgstr+start, sizeof(msgstr) - start, &ofs);
start += ofs;
}
else
break;
}
if ((*msgid && start) || allowblanks)
PO_AddText(po, msgid, msgstr);
}
else
{
//some sort of junk?
in++;
while (*in && *in != '\n')
if ((*msgid && start) || allowblanks)
PO_AddText(po, msgid, msgstr);
#ifdef COLOURUNTRANSLATEDSTRINGS
else if (!start)
{
char temp[1024];
int i;
Q_snprintfz(temp, sizeof(temp), "%s", *msgstr?msgstr:msgid);
for (i = 0; temp[i]; i++)
{
if (temp[i] == '%')
{
while (temp[i] > ' ')
i++;
}
else if (temp[i] >= ' ')
temp[i] |= 0x80;
}
PO_AddText(po, msgid, temp);
}
#endif
}
else
{
//some sort of junk?
in++;
while (*in && *in != '\n')
in++;
}
}
}
@ -424,3 +463,35 @@ void PO_Close(struct po_s *po)
}
Z_Free(po);
}
const char *PO_GetText(struct po_s *po, const char *msg)
{
struct poline_s *line;
if (!po)
return msg;
line = Hash_Get(&po->hash, msg);
#ifdef COLOURMISSINGSTRINGS
if (!line)
{
char temp[1024];
int i;
Q_snprintfz(temp, sizeof(temp), "%s", msg);
for (i = 0; temp[i]; i++)
{
if (temp[i] == '%')
{
while (temp[i] > ' ')
i++;
}
else if (temp[i] >= ' ')
temp[i] |= 0x80;
}
line = PO_AddText(po, msg, temp);
}
#endif
if (line)
return line->translated;
return msg;
}

View File

@ -17,6 +17,7 @@ extern struct language_s languages[MAX_LANGUAGES];
extern int com_language;
extern cvar_t language;
#define langtext(t,l) PO_GetText(languages[l].po, t)
#define localtext(t) PO_GetText(languages[com_language].po, t)
int TL_FindLanguage(const char *lang);
#endif

View File

@ -62,7 +62,7 @@ static D3DPRESENT_PARAMETERS d3dpp;
float d3d_trueprojection_std[16];
float d3d_trueprojection_view[16];
qboolean vid_initializing;
static qboolean vid_initializing;
extern qboolean scr_initialized; // ready to draw
extern qboolean scr_drawloading;
@ -73,15 +73,6 @@ extern cvar_t vid_hardwaregamma;
extern cvar_t vid_srgb;
//sound/error code needs this
HWND mainwindow;
//input code needs these
int window_center_x, window_center_y;
RECT window_rect;
int window_x, window_y;
/*void BuildGammaTable (float g, float c);
static void D3D9_VID_GenPaletteTables (unsigned char *palette)
{
@ -161,6 +152,7 @@ static void D3DVID_UpdateWindowStatus (HWND hWnd)
{
POINT p;
RECT nr;
int window_x, window_y;
int window_width, window_height;
GetClientRect(hWnd, &nr);

View File

@ -78,22 +78,13 @@ static DXGI_FORMAT depthformat;
void *d3d11mod;
static unsigned int d3d11multisample_count, d3d11multisample_quality;
qboolean vid_initializing;
static qboolean vid_initializing;
extern qboolean scr_initialized; // ready to draw
extern qboolean scr_drawloading;
extern qboolean scr_con_forcedraw;
static qboolean d3d_resized;
//sound/error code needs this
HWND mainwindow;
//input code needs these
int window_center_x, window_center_y;
RECT window_rect;
int window_x, window_y;
static void released3dbackbuffer(void);
static qboolean resetd3dbackbuffer(int width, int height);
@ -218,6 +209,7 @@ static void D3DVID_UpdateWindowStatus (HWND hWnd)
{
POINT p;
RECT nr;
int window_x, window_y;
int window_width, window_height;
GetClientRect(hWnd, &nr);

View File

@ -63,7 +63,7 @@ LPDIRECT3DDEVICE8 pD3DDev8;
static D3DPRESENT_PARAMETERS d3dpp;
float d3d_trueprojection[16];
qboolean vid_initializing;
static qboolean vid_initializing;
extern qboolean scr_initialized; // ready to draw
extern qboolean scr_drawloading;
@ -72,16 +72,6 @@ static qboolean d3d_resized;
extern cvar_t vid_hardwaregamma;
//sound/error code needs this
HWND mainwindow;
//input code needs these
int window_center_x, window_center_y;
RECT window_rect;
int window_x, window_y;
/*void BuildGammaTable (float g, float c);
static void D3D8_VID_GenPaletteTables (unsigned char *palette)
{

View File

@ -693,7 +693,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
if (plskin && plskin->loadstate < SKIN_LOADED)
{
Skin_Cache8(plskin); //we're not going to use it, but make sure its status is updated when it is finally loaded..
Skin_TryCache8(plskin); //we're not going to use it, but make sure its status is updated when it is finally loaded..
plskin = cl.players[e->playerindex].lastskin;
}
else
@ -806,6 +806,21 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
}
}
if (plskin)
{
original = Skin_TryCache8(plskin); //will start it loading if not already loaded.
if (plskin->loadstate == SKIN_LOADING)
return shader;
inwidth = plskin->width;
inheight = plskin->height;
}
else
{
original = NULL;
inwidth = 0;
inheight = 0;
}
//colourmap isn't present yet.
cm = Z_Malloc(sizeof(*cm));
*forcedtex = &cm->texnum;
@ -823,13 +838,8 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
shader = R_RegisterSkin(skinname, NULL);
cm->texnum.bump = shader->defaulttextures->bump; //can't colour bumpmapping
if (plskin)
if (original)
{
/*q1 only reskins the player model, not gibbed heads (which have the same colourmap)*/
original = Skin_Cache8(plskin);
inwidth = plskin->width;
inheight = plskin->height;
if (!original && TEXLOADED(plskin->textures.base))
{
cm->texnum.loweroverlay = plskin->textures.loweroverlay;
@ -844,12 +854,6 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
return shader;
}
}
else
{
original = NULL;
inwidth = 0;
inheight = 0;
}
if (!original)
{
if (skins && skins->numframes && skins->frame[subframe].texels)
@ -1653,7 +1657,7 @@ void R_GAlias_DrawBatch(batch_t *batch)
galiasinfo_t *inf;
model_t *clmodel;
int surfnum;
unsigned int surfnum;
static mesh_t mesh;
static mesh_t *meshl = &mesh;
@ -1673,7 +1677,7 @@ void R_GAlias_DrawBatch(batch_t *batch)
memset(&mesh, 0, sizeof(mesh));
for(surfnum=0; inf; inf=inf->nextsurf, surfnum++)
{
if (batch->surf_first == surfnum)
if (batch->user.alias.surfrefs[0] == surfnum)
{
/*needrecolour =*/ Alias_GAliasBuildMesh(&mesh, &batch->vbo, inf, surfnum, e, batch->shader->prog && (batch->shader->prog->supportedpermutations & PERMUTATION_SKELETAL));
batch->mesh = &meshl;
@ -1806,8 +1810,11 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
b->texture = NULL;
b->shader = shader;
for (j = 0; j < MAXRLIGHTMAPS; j++)
{
b->lightmap[j] = -1;
b->surf_first = surfnum;
b->lmlightstyle[j] = INVALID_LIGHTSTYLE;
}
b->user.alias.surfrefs[0] = surfnum;
b->flags = 0;
sort = shader->sort;
if (e->flags & RF_FORCECOLOURMOD)
@ -2732,7 +2739,7 @@ static void R_DB_Poly(batch_t *batch)
{
static mesh_t mesh;
static mesh_t *meshptr = &mesh;
unsigned int i = batch->surf_first;
unsigned int i = batch->user.poly.surface;
batch->mesh = &meshptr;
@ -2776,7 +2783,7 @@ static void BE_GenPolyBatches(batch_t **batches)
b->shader = shader;
for (j = 0; j < MAXRLIGHTMAPS; j++)
b->lightmap[j] = -1;
b->surf_first = i;
b->user.poly.surface = i;
b->flags = cl_stris[i].flags;
b->vbo = 0;
@ -2792,7 +2799,6 @@ static void BE_GenPolyBatches(batch_t **batches)
batches[sort] = b;
}
}
void R_HalfLife_GenerateBatches(entity_t *e, batch_t **batches);
void PR_Route_Visualise(void);
void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemode, const qbyte *worldpvs, const int *worldareas)
{

View File

@ -4150,6 +4150,8 @@ void GLBE_SelectEntity(entity_t *ent)
nd = 1;
if (shaderstate.depthrange != nd)
{
shaderstate.depthrange = nd;
if (nd < 1)
memcpy(shaderstate.projectionmatrix, r_refdef.m_projection_view, sizeof(shaderstate.projectionmatrix));
else
@ -4160,12 +4162,6 @@ void GLBE_SelectEntity(entity_t *ent)
qglLoadMatrixf(shaderstate.projectionmatrix);
qglMatrixMode(GL_MODELVIEW);
}
shaderstate.depthrange = nd;
// if (qglDepthRange)
// qglDepthRange (gldepthmin, gldepthmin + shaderstate.depthrange*(gldepthmax-gldepthmin));
// else if (qglDepthRangef)
// qglDepthRangef (gldepthmin, gldepthmin + shaderstate.depthrange*(gldepthmax-gldepthmin));
}
shaderstate.lastuniform = 0;

View File

@ -78,10 +78,10 @@ struct hlvremaps
unsigned short scoord;
unsigned short tcoord;
};
static index_t HLMDL_DeDupe(unsigned short *order, struct hlvremaps *rem, size_t *count, size_t max)
static index_t HLMDL_DeDupe(unsigned short *order, struct hlvremaps *rem, size_t *count, size_t first, size_t max)
{
size_t i;
for (i = *count; i-- > 0;)
for (i = *count; i-- > first;)
{
if (rem[i].vertidx == order[0] && rem[i].normalidx == order[1] && rem[i].scoord == order[2] && rem[i].tcoord == order[3])
return i;
@ -99,133 +99,189 @@ static index_t HLMDL_DeDupe(unsigned short *order, struct hlvremaps *rem, size_t
}
//parse the vertex info, pull out what we can
static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel, struct hlalternative_s *submodel)
static void HLMDL_PrepareVerticies (model_t *mod, hlmodel_t *model)
{
struct hlvremaps *uvert;
size_t uvertcount, uvertstart;
size_t uvertcount=0, uvertstart;
unsigned short count;
int i;
size_t idx = 0, v, m, maxidx=65536*3;
size_t idx = 0, m, maxidx=65536*3;
size_t maxverts = 65536;
mesh_t *mesh = &submodel->mesh;
index_t *index;
mesh_t *mesh, *submesh;
vec3_t *verts = (vec3_t *) ((qbyte *) model->header + amodel->vertindex);
qbyte *bone = ((qbyte *) model->header + amodel->vertinfoindex);
vec3_t *norms = (vec3_t *) ((qbyte *) model->header + amodel->normindex);
int body;
uvertcount = 0;
uvert = malloc(sizeof(*uvert)*maxverts);
index = malloc(sizeof(*mesh->colors4b_array)*maxidx);
index = malloc(sizeof(byte_vec4_t)*maxidx);
for(m = 0; m < amodel->nummesh; m++)
model->numgeomsets = model->header->numbodyparts;
model->geomset = ZG_Malloc(&mod->memgroup, sizeof(*model->geomset) * model->numgeomsets);
for (body = 0; body < model->numgeomsets; body++)
{
hlmdl_mesh_t *inmesh = (hlmdl_mesh_t *) ((qbyte *) model->header + amodel->meshindex) + m;
unsigned short *order = (unsigned short *) ((qbyte *) model->header + inmesh->index);
uvertstart = uvertcount;
submodel->submesh[m].firstindex = mesh->numindexes;
submodel->submesh[m].numindexes = 0;
for(;;)
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model->header + model->header->bodypartindex) + body;
int bodyindex;
model->geomset[body].numalternatives = bodypart->nummodels;
model->geomset[body].alternatives = ZG_Malloc(&mod->memgroup, sizeof(*model->geomset[body].alternatives) * bodypart->nummodels);
for (bodyindex = 0; bodyindex < bodypart->nummodels; bodyindex++)
{
count = *order++; /* get the vertex count and primitive type */
if(!count) break; /* done */
hlmdl_submodel_t *amodel = (hlmdl_submodel_t *) ((qbyte *) model->header + bodypart->modelindex) + bodyindex;
struct hlalternative_s *submodel;
if(count & 0x8000)
{ //fan
int first = HLMDL_DeDupe(order+0*4, uvert, &uvertcount, maxverts);
int prev = HLMDL_DeDupe(order+1*4, uvert, &uvertcount, maxverts);
count = (unsigned short)-(short)count;
if (idx + (count-2)*3 > maxidx)
break; //would overflow. fixme: extend
for (i = min(2,count); i < count; i++)
{
index[idx++] = first;
index[idx++] = prev;
index[idx++] = prev = HLMDL_DeDupe(order+i*4, uvert, &uvertcount, maxverts);
}
}
else
model->geomset[body].alternatives[bodyindex].numsubmeshes = amodel->nummesh;
model->geomset[body].alternatives[bodyindex].submesh = ZG_Malloc(&mod->memgroup, sizeof(*model->geomset[body].alternatives[bodyindex].submesh) * amodel->nummesh);
submodel = &model->geomset[body].alternatives[bodyindex];
for(m = 0; m < amodel->nummesh; m++)
{
int v0 = HLMDL_DeDupe(order+0*4, uvert, &uvertcount, maxverts);
int v1 = HLMDL_DeDupe(order+1*4, uvert, &uvertcount, maxverts);
//emit (count-2)*3 indicies as a strip
//012 213, etc
if (idx + (count-2)*3 > maxidx)
break; //would overflow. fixme: extend
for (i = min(2,count); i < count; i++)
hlmdl_mesh_t *inmesh = (hlmdl_mesh_t *) ((qbyte *) model->header + amodel->meshindex) + m;
unsigned short *order = (unsigned short *) ((qbyte *) model->header + inmesh->index);
uvertstart = uvertcount;
submodel->submesh[m].vbofirstvert = uvertstart;
submodel->submesh[m].vbofirstelement = idx;
submodel->submesh[m].numvertexes = 0;
submodel->submesh[m].numindexes = 0;
for(;;)
{
if (i & 1)
{
index[idx++] = v1;
index[idx++] = v0;
count = *order++; /* get the vertex count and primitive type */
if(!count) break; /* done */
if(count & 0x8000)
{ //fan
int first = HLMDL_DeDupe(order+0*4, uvert, &uvertcount, uvertstart, maxverts);
int prev = HLMDL_DeDupe(order+1*4, uvert, &uvertcount, uvertstart, maxverts);
count = (unsigned short)-(short)count;
if (idx + (count-2)*3 > maxidx)
break; //would overflow. fixme: extend
for (i = min(2,count); i < count; i++)
{
index[idx++] = first;
index[idx++] = prev;
index[idx++] = prev = HLMDL_DeDupe(order+i*4, uvert, &uvertcount, uvertstart, maxverts);
}
}
else
{
index[idx++] = v0;
index[idx++] = v1;
int v0 = HLMDL_DeDupe(order+0*4, uvert, &uvertcount, uvertstart, maxverts);
int v1 = HLMDL_DeDupe(order+1*4, uvert, &uvertcount, uvertstart, maxverts);
//emit (count-2)*3 indicies as a strip
//012 213, etc
if (idx + (count-2)*3 > maxidx)
break; //would overflow. fixme: extend
for (i = min(2,count); i < count; i++)
{
if (i & 1)
{
index[idx++] = v1;
index[idx++] = v0;
}
else
{
index[idx++] = v0;
index[idx++] = v1;
}
v0 = v1;
index[idx++] = v1 = HLMDL_DeDupe(order+i*4, uvert, &uvertcount, uvertstart, maxverts);
}
}
v0 = v1;
index[idx++] = v1 = HLMDL_DeDupe(order+i*4, uvert, &uvertcount, maxverts);
order += i*4;
}
if (uvertcount >= maxverts)
{
//if we're overflowing our verts, rewind, as we cannot generate this mesh. we'll just end up with a 0-index mesh, with no extra verts either
uvertcount = uvertstart;
idx = submodel->submesh[m].vbofirstelement;
}
submodel->submesh[m].numindexes = idx - submodel->submesh[m].vbofirstelement;
submodel->submesh[m].numvertexes = uvertcount - uvertstart;
}
order += i*4;
}
if (uvertcount >= maxverts)
{
//if we're overflowing our verts, rewind, as we cannot generate this mesh. we'll just end up with a 0-index mesh, with no extra verts either
uvertcount = uvertstart;
idx = submodel->submesh[m].firstindex;
}
submodel->submesh[m].numindexes = idx - submodel->submesh[m].firstindex;
}
mesh->numindexes = idx;
mesh->numvertexes = uvertcount;
mesh = &model->mesh;
mesh->indexes = ZG_Malloc(model->memgroup, sizeof(*mesh->indexes)*idx);
memcpy(mesh->indexes, index, sizeof(*mesh->indexes)*idx);
memcpy(mesh->indexes, index, sizeof(*index)*idx);
mesh->colors4b_array = ZG_Malloc(model->memgroup, sizeof(*mesh->colors4b_array)*uvertcount);
mesh->st_array = ZG_Malloc(model->memgroup, sizeof(*mesh->st_array)*uvertcount);
mesh->lmst_array[0] = ZG_Malloc(model->memgroup, sizeof(*mesh->lmst_array[0])*uvertcount);
mesh->xyz_array = ZG_Malloc(model->memgroup, sizeof(*mesh->xyz_array)*uvertcount);
mesh->normals_array = ZG_Malloc(model->memgroup, sizeof(*mesh->normals_array)*uvertcount);
mesh->bonenums = ZG_Malloc(model->memgroup, sizeof(*mesh->bonenums)*uvertcount);
mesh->boneweights = ZG_Malloc(model->memgroup, sizeof(*mesh->boneweights)*uvertcount);
#if defined(RTLIGHTS)
mesh->snormals_array = ZG_Malloc(model->memgroup, sizeof(*mesh->snormals_array)*uvertcount);
mesh->tnormals_array = ZG_Malloc(model->memgroup, sizeof(*mesh->tnormals_array)*uvertcount);
#endif
mesh->bonenums = ZG_Malloc(model->memgroup, sizeof(*mesh->bonenums)*uvertcount);
mesh->boneweights = ZG_Malloc(model->memgroup, sizeof(*mesh->boneweights)*uvertcount);
//prepare the verticies now that we have the mappings
for(v = 0; v < uvertcount; v++)
mesh->numindexes = idx;
mesh->numvertexes = uvertcount;
for (body = 0; body < model->numgeomsets; body++)
{
mesh->bonenums[v][0] = mesh->bonenums[v][1] = mesh->bonenums[v][2] = mesh->bonenums[v][3] = bone[uvert[v].vertidx];
Vector4Set(mesh->boneweights[v], 1, 0, 0, 0);
Vector4Set(mesh->colors4b_array[v], 255, 255, 255, 255); //why bytes? why not?
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model->header + model->header->bodypartindex) + body;
int bodyindex;
for (bodyindex = 0; bodyindex < bodypart->nummodels; bodyindex++)
{
hlmdl_submodel_t *amodel = (hlmdl_submodel_t *) ((qbyte *) model->header + bodypart->modelindex) + bodyindex;
mesh->lmst_array[0][v][0] = uvert[v].scoord;
mesh->lmst_array[0][v][1] = uvert[v].tcoord;
VectorCopy(verts[uvert[v].vertidx], mesh->xyz_array[v]);
vec3_t *verts = (vec3_t *) ((qbyte *) model->header + amodel->vertindex);
qbyte *bone = ((qbyte *) model->header + amodel->vertinfoindex);
vec3_t *norms = (vec3_t *) ((qbyte *) model->header + amodel->normindex);
size_t iv, ov;
//Warning: these models use different tables for vertex and normals.
//this means they might be transformed by different bones. we ignore that and just assume that the normals will want the same bone.
VectorCopy(norms[uvert[v].normalidx], mesh->normals_array[v]);
struct hlalternative_s *submodel = &model->geomset[body].alternatives[bodyindex];
for(m = 0; m < amodel->nummesh; m++)
{
submesh = &submodel->submesh[m];
submesh->indexes = mesh->indexes + submesh->vbofirstelement;
submesh->colors4b_array = mesh->colors4b_array + submesh->vbofirstvert;
submesh->st_array = mesh->st_array + submesh->vbofirstvert;
submesh->lmst_array[0] = mesh->lmst_array[0] + submesh->vbofirstvert;
submesh->xyz_array = mesh->xyz_array + submesh->vbofirstvert;
submesh->normals_array = mesh->normals_array + submesh->vbofirstvert;
submesh->bonenums = mesh->bonenums + submesh->vbofirstvert;
submesh->boneweights = mesh->boneweights + submesh->vbofirstvert;
//prepare the verticies now that we have the mappings
for(ov = 0, iv = submesh->vbofirstvert; ov < submesh->numvertexes; ov++, iv++)
{
submesh->bonenums[ov][0] = submesh->bonenums[ov][1] = submesh->bonenums[ov][2] = submesh->bonenums[ov][3] = bone[uvert[iv].vertidx];
Vector4Set(submesh->boneweights[ov], 1, 0, 0, 0);
Vector4Set(submesh->colors4b_array[ov], 255, 255, 255, 255); //why bytes? why not?
submesh->lmst_array[0][ov][0] = uvert[iv].scoord;
submesh->lmst_array[0][ov][1] = uvert[iv].tcoord;
VectorCopy(verts[uvert[iv].vertidx], submesh->xyz_array[ov]);
//Warning: these models use different tables for vertex and normals.
//this means they might be transformed by different bones. we ignore that and just assume that the normals will want the same bone.
VectorCopy(norms[uvert[iv].normalidx], submesh->normals_array[ov]);
}
#if defined(RTLIGHTS)
//treat this as the base pose, and calculate the sdir+tdir for bumpmaps.
submesh->snormals_array = mesh->snormals_array + submesh->vbofirstvert;
submesh->tnormals_array = mesh->tnormals_array + submesh->vbofirstvert;
// R_Generate_Mesh_ST_Vectors(submesh);
#endif
}
}
}
//scratch space...
mesh->indexes = ZG_Malloc(model->memgroup, sizeof(*mesh->indexes)*idx);
//don't need that mapping any more
free(uvert);
free(index);
#if defined(RTLIGHTS)
//treat this as the base pose, and calculate the sdir+tdir for bumpmaps.
R_Generate_Mesh_ST_Vectors(mesh);
#endif
}
#endif
@ -237,10 +293,11 @@ static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel,
qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
{
#ifndef SERVERONLY
int i;
int body;
int i, j;
struct hlmodelshaders_s *shaders;
hlmdl_tex_t *tex;
lmalloc_t atlas;
#endif
hlmodel_t *model;
@ -317,6 +374,7 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
shaders = ZG_Malloc(&mod->memgroup, texheader->numtextures*sizeof(shader_t));
model->shaders = shaders;
for(i = 0; i < texheader->numtextures; i++)
{
Q_snprintfz(shaders[i].name, sizeof(shaders[i].name), "%s/%s", mod->name, COM_SkipPath(tex[i].name));
@ -328,23 +386,128 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
if (tex[i].flags & HLMDLFL_FULLBRIGHT)
{
if (tex[i].flags & HLMDLFL_CHROME)
{
shader = HLSHADER_FULLBRIGHTCHROME;
Q_snprintfz(shaders[i].name, sizeof(shaders[i].name), "common/hlmodel_fullbrightchrome");
}
else
{
shader = HLSHADER_FULLBRIGHT;
Q_snprintfz(shaders[i].name, sizeof(shaders[i].name), "common/hlmodel_fullbright");
}
}
else if (tex[i].flags & HLMDLFL_CHROME)
{
shader = HLSHADER_CHROME;
Q_snprintfz(shaders[i].name, sizeof(shaders[i].name), "common/hlmodel_chrome");
}
else
{
shader = "";
Q_snprintfz(shaders[i].name, sizeof(shaders[i].name), "common/hlmodel_other");
}
shaders[i].defaultshadertext = shader;
}
else
{
shaders[i].defaultshadertext = NULL;
Q_snprintfz(shaders[i].name, sizeof(shaders[i].name), "common/hlmodel");
}
memset(&shaders[i].defaulttex, 0, sizeof(shaders[i].defaulttex));
shaders[i].defaulttex.base = Image_GetTexture(shaders[i].name, "", IF_NOALPHA, (qbyte *) texheader + tex[i].offset, (qbyte *) texheader + tex[i].w * tex[i].h + tex[i].offset, tex[i].w, tex[i].h, TF_8PAL24);
}
//figure out the preferred atlas size. hopefully it'll fit well enough...
if (texheader->numtextures == 1)
Mod_LightmapAllocInit(&atlas, false, tex[0].w, tex[0].h, 0);
else
{
int sz = 1;
for(i = 0; i < texheader->numtextures; i++)
while (sz < tex[i].w || sz < tex[i].h)
sz <<= 1;
for (; sz < sh_config.texture2d_maxsize; sz<<=1)
{
unsigned short x,y;
int atlasid;
Mod_LightmapAllocInit(&atlas, false, sz, sz, 0);
for(i = 0; i < texheader->numtextures; i++)
{
if (tex[i].flags & HLMDLFL_CHROME)
continue;
Mod_LightmapAllocBlock(&atlas, tex[i].w, tex[i].h, &x, &y, &atlasid);
}
if (i == texheader->numtextures && atlas.lmnum <= 0)
break; //okay, just go with it.
}
Mod_LightmapAllocInit(&atlas, false, sz, sz, 0);
}
for(i = 0; i < texheader->numtextures; i++)
{
if (tex[i].flags & HLMDLFL_CHROME)
{
shaders[i].x =
shaders[i].y = 0;
shaders[i].w = tex[i].w;
shaders[i].h = tex[i].h;
shaders[i].atlasid = -1;
continue;
}
shaders[i].w = tex[i].w;
shaders[i].h = tex[i].h;
Mod_LightmapAllocBlock(&atlas, shaders[i].w, shaders[i].h, &shaders[i].x, &shaders[i].y, &shaders[i].atlasid);
}
if (atlas.allocated[0])
atlas.lmnum++;
//now we know where the various textures will be, generate the atlas images.
for (j = 0; j < atlas.lmnum; j++)
{
char texname[MAX_QPATH];
texid_t basetex;
int y, x;
unsigned int *basepix = Z_Malloc(atlas.width * atlas.height * sizeof(*basepix));
for(i = 0; i < texheader->numtextures; i++)
{
if (shaders[i].atlasid == j)
{
unsigned *out = basepix + atlas.width*shaders[i].y + shaders[i].x;
qbyte *in = (qbyte *) texheader + tex[i].offset;
qbyte *pal = (qbyte *) texheader + tex[i].w * tex[i].h + tex[i].offset;
qbyte *rgb;
for(y = 0; y < tex[i].h; y++, out += atlas.width-shaders[i].w)
for(x = 0; x < tex[i].w; x++, in++)
{
rgb = pal + *in*3;
*out++ = 0xff000000 | (rgb[0]<<0) | (rgb[1]<<8) | (rgb[2]<<16);
}
}
}
Q_snprintfz(texname, sizeof(texname), "%s*%i", mod->name, j);
basetex = Image_GetTexture(texname, "", IF_NOALPHA|IF_NOREPLACE, basepix, NULL, atlas.width, atlas.height, PTI_RGBX8);
Z_Free(basepix);
for(i = 0; i < texheader->numtextures; i++)
{
if (shaders[i].atlasid == j)
shaders[i].defaulttex.base = basetex;
}
}
//and chrome textures need to preserve their texture coords to avoid weirdness.
for(i = 0; i < texheader->numtextures; i++)
{
if (tex[i].flags & HLMDLFL_CHROME)
{
qbyte *in = (qbyte *) texheader + tex[i].offset;
qbyte *pal = (qbyte *) texheader + tex[i].w * tex[i].h + tex[i].offset;
char texname[MAX_QPATH];
shaders[i].atlasid = j++;
Q_snprintfz(texname, sizeof(texname), "%s*%i", mod->name, shaders[i].atlasid);
shaders[i].defaulttex.base = Image_GetTexture(texname, "", IF_NOALPHA|IF_NOREPLACE, in, pal, tex[i].w, tex[i].h, TF_8PAL24);
}
}
model->numskinrefs = texheader->skinrefs;
model->numskingroups = texheader->skingroups;
@ -364,20 +527,7 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
#ifndef SERVERONLY
model->numgeomsets = model->header->numbodyparts;
model->geomset = ZG_Malloc(&mod->memgroup, sizeof(*model->geomset) * model->numgeomsets);
for (body = 0; body < model->numgeomsets; body++)
{
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model->header + model->header->bodypartindex) + body;
int bodyindex;
model->geomset[body].numalternatives = bodypart->nummodels;
model->geomset[body].alternatives = ZG_Malloc(&mod->memgroup, sizeof(*model->geomset[body].alternatives) * bodypart->nummodels);
for (bodyindex = 0; bodyindex < bodypart->nummodels; bodyindex++)
{
hlmdl_submodel_t *amodel = (hlmdl_submodel_t *) ((qbyte *) model->header + bodypart->modelindex) + bodyindex;
model->geomset[body].alternatives[bodyindex].numsubmeshes = amodel->nummesh;
model->geomset[body].alternatives[bodyindex].submesh = ZG_Malloc(&mod->memgroup, sizeof(*model->geomset[body].alternatives[bodyindex].submesh) * amodel->nummesh);
HLMDL_PrepareVerticies(model, amodel, &model->geomset[body].alternatives[bodyindex]);
}
}
HLMDL_PrepareVerticies(mod, model);
//FIXME: No VBOs used.
#endif
return true;
@ -1149,63 +1299,127 @@ unsigned int HLMDL_Contents (model_t *model, int hulloverride, const framestate_
#ifndef SERVERONLY
void R_HL_BuildFrame(hlmodel_t *model, hlmdl_submodel_t *amodel, entity_t *curent, int bodypart, int bodyidx, int meshidx, float tex_s, float tex_t, mesh_t *mesh, qboolean gpubones)
void R_HL_BuildFrame(hlmodel_t *model, int bodypart, int bodyidx, int meshidx, struct hlmodelshaders_s *texinfo, mesh_t *outmesh)
{
int b;
int cbone;
// int bgroup;
// int lastbone;
int v;
int w = texinfo->defaulttex.base->width;
int h = texinfo->defaulttex.base->height;
vec2_t texbase = {texinfo->x/(float)w, texinfo->y/(float)h};
vec2_t texscale = {1.0/w, 1.0/h};
*mesh = model->geomset[bodypart].alternatives[bodyidx].mesh;
mesh_t *srcmesh = &model->geomset[bodypart].alternatives[bodyidx].submesh[meshidx];
//copy out the indexes into the final mesh.
memcpy(outmesh->indexes+outmesh->numindexes, srcmesh->indexes, sizeof(index_t)*srcmesh->numindexes);
outmesh->numindexes += srcmesh->numindexes;
if (outmesh == &model->mesh)
{ //get the backend to do the skeletal stuff (read: glsl)
for(v = 0; v < srcmesh->numvertexes; v++)
{ //should really come up with a better way to deal with this, like rect textures.
srcmesh->st_array[v][0] = texbase[0] + srcmesh->lmst_array[0][v][0] * texscale[0];
srcmesh->st_array[v][1] = texbase[1] + srcmesh->lmst_array[0][v][1] * texscale[1];
}
}
else
{ //backend can't handle it, apparently. do it in software.
int fvert = srcmesh->vbofirstvert;
vecV_t *nxyz = outmesh->xyz_array+fvert;
vec3_t *nnorm = outmesh->normals_array+fvert;
for(v = 0; v < srcmesh->numvertexes; v++)
{ //should really come up with a better way to deal with this, like rect textures.
srcmesh->st_array[v][0] = texbase[0] + srcmesh->lmst_array[0][v][0] * texscale[0];
srcmesh->st_array[v][1] = texbase[1] + srcmesh->lmst_array[0][v][1] * texscale[1];
//transform to nxyz (a separate buffer from the srcmesh data)
VectorTransform(srcmesh->xyz_array[v], (void *)transform_matrix[srcmesh->bonenums[v][0]], nxyz[v]);
//transform to nnorm (a separate buffer from the srcmesh data)
nnorm[v][0] = DotProduct(srcmesh->normals_array[v], transform_matrix[srcmesh->bonenums[v][0]][0]);
nnorm[v][1] = DotProduct(srcmesh->normals_array[v], transform_matrix[srcmesh->bonenums[v][0]][1]);
nnorm[v][2] = DotProduct(srcmesh->normals_array[v], transform_matrix[srcmesh->bonenums[v][0]][2]);
//FIXME: svector, tvector!
}
}
}
static void R_HL_BuildMeshes(batch_t *b)
{
entity_t *rent = b->ent;
hlmodel_t *model = Mod_Extradata(rent->model);
int body, m;
static mesh_t *mptr[1], softbonemesh;
skinfile_t *sk = rent->customskin?Mod_LookupSkin(rent->customskin):NULL;
const unsigned int entity_body = 0/*rent->body*/;
int surf;
float *bones;
int numbones;
if (b->shader->prog && (b->shader->prog->supportedpermutations & PERMUTATION_SKELETAL) && model->header->numbones < sh_config.max_gpu_bones)
{ //okay, we can use gpu gones. yay.
b->mesh = mptr;
*b->mesh = &model->mesh;
}
else
{
static vecV_t nxyz_buffer[65536];
static vec3_t nnorm_buffer[65536];
//no gpu bone support. :(
softbonemesh = model->mesh;
b->mesh = mptr;
*b->mesh = &softbonemesh;
//this stuff will get recalculated
softbonemesh.xyz_array = nxyz_buffer;
softbonemesh.normals_array = nnorm_buffer;
//don't get confused.
softbonemesh.bonenums = NULL;
softbonemesh.boneweights = NULL;
softbonemesh.bones = NULL;
softbonemesh.numbones = 0;
}
(*b->mesh)->numindexes = 0;
//FIXME: cache this!
if (curent->framestate.bonecount >= model->header->numbones)
{
if (curent->framestate.skeltype == SKEL_RELATIVE)
if (rent->framestate.bonecount >= model->header->numbones)
{ //skeletal object...
int b;
if (rent->framestate.skeltype == SKEL_RELATIVE)
{
mesh->numbones = model->header->numbones;
for (b = 0; b < mesh->numbones; b++)
numbones = model->header->numbones;
for (b = 0; b < numbones; b++)
{
/* If we have a parent, take the addition. Otherwise just copy the values */
if(model->bones[b].parent>=0)
{
R_ConcatTransforms((void*)transform_matrix[model->bones[b].parent], (void*)(curent->framestate.bonestate+b*12), transform_matrix[b]);
R_ConcatTransforms((void*)transform_matrix[model->bones[b].parent], (void*)(rent->framestate.bonestate+b*12), transform_matrix[b]);
}
else
{
memcpy(transform_matrix[b], curent->framestate.bonestate+b*12, 12 * sizeof(float));
memcpy(transform_matrix[b], rent->framestate.bonestate+b*12, 12 * sizeof(float));
}
}
mesh->bones = transform_matrix[0][0];
bones = transform_matrix[0][0];
}
else
{
mesh->bones = curent->framestate.bonestate;
mesh->numbones = curent->framestate.bonecount;
bones = rent->framestate.bonestate;
numbones = rent->framestate.bonecount;
}
}
else
{
{ //lerp the bone data ourselves.
float relatives[12*MAX_BONES];
mesh->bones = transform_matrix[0][0];
mesh->numbones = model->header->numbones;
int cbone, b;
bones = transform_matrix[0][0];
numbones = model->header->numbones;
/* //FIXME: needs caching.
for (b = 0; b < MAX_BONE_CONTROLLERS; b++)
model->controller[b] = curent->framestate.bonecontrols[b];
for (cbone = 0, bgroup = 0; bgroup < FS_COUNT; bgroup++)
{
lastbone = curent->framestate.g[bgroup].endbone;
if (bgroup == FS_COUNT-1)
lastbone = model->header->numbones;
if (cbone >= lastbone)
continue;
HL_SetupBones(model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, curent->framestate.g[bgroup].subblendfrac, curent->framestate.g[bgroup].frametime[0], relatives); // Setup the bones
cbone = lastbone;
}
*/
cbone = HLMDL_GetBoneData_Internal(model, 0, model->header->numbones, &curent->framestate, relatives);
cbone = HLMDL_GetBoneData_Internal(model, 0, model->header->numbones, &rent->framestate, relatives);
//convert relative to absolutes
for (b = 0; b < cbone; b++)
@ -1222,62 +1436,83 @@ void R_HL_BuildFrame(hlmodel_t *model, hlmdl_submodel_t *amodel, entity_t *curen
}
}
mesh->indexes += model->geomset[bodypart].alternatives[bodyidx].submesh[meshidx].firstindex;
mesh->numindexes = model->geomset[bodypart].alternatives[bodyidx].submesh[meshidx].numindexes;
model->mesh.bones = bones;
model->mesh.numbones = numbones;
if (gpubones && model->header->numbones < sh_config.max_gpu_bones)
{ //get the backend to do the skeletal stuff (read: glsl)
for(v = 0; v < mesh->numvertexes; v++)
{ //should really come up with a better way to deal with this, like rect textures.
mesh->st_array[v][0] = mesh->lmst_array[0][v][0] * tex_s;
mesh->st_array[v][1] = mesh->lmst_array[0][v][1] * tex_t;
for (surf = 0; surf < b->meshes; surf++)
{
body = b->user.alias.surfrefs[surf] >> 8;
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model->header + model->header->bodypartindex) + body;
int bodyindex = ((sk && body < MAX_GEOMSETS && sk->geomset[body] >= 1)?sk->geomset[body]-1:(entity_body / bodypart->base)) % bodypart->nummodels;
hlmdl_submodel_t *amodel = (hlmdl_submodel_t *) ((qbyte *) model->header + bodypart->modelindex) + bodyindex;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Draw each mesh */
m = b->user.alias.surfrefs[surf] & 0xff;
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_mesh_t *mesh = (hlmdl_mesh_t *) ((qbyte *) model->header + amodel->meshindex) + m;
struct hlmodelshaders_s *texinfo;
int skinidx = mesh->skinindex;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if (rent->skinnum < model->numskingroups)
skinidx += rent->skinnum * model->numskinrefs;
texinfo = &model->shaders[model->skinref[skinidx]];
R_HL_BuildFrame(model, body, bodyindex, m, texinfo, *b->mesh);
}
}
}
else
{ //backend can't handle it, apparently. do it in software.
static vecV_t nxyz[2048];
static vec3_t nnorm[2048];
for(v = 0; v < mesh->numvertexes; v++)
{ //should really come up with a better way to deal with this, like rect textures.
mesh->st_array[v][0] = mesh->lmst_array[0][v][0] * tex_s;
mesh->st_array[v][1] = mesh->lmst_array[0][v][1] * tex_t;
VectorTransform(mesh->xyz_array[v], (void *)transform_matrix[mesh->bonenums[v][0]], nxyz[v]);
nnorm[v][0] = DotProduct(mesh->normals_array[v], transform_matrix[mesh->bonenums[v][0]][0]);
nnorm[v][1] = DotProduct(mesh->normals_array[v], transform_matrix[mesh->bonenums[v][0]][1]);
nnorm[v][2] = DotProduct(mesh->normals_array[v], transform_matrix[mesh->bonenums[v][0]][2]);
//FIXME: svector, tvector!
}
mesh->xyz_array = nxyz;
mesh->normals_array = nnorm;
mesh->bonenums = NULL;
mesh->boneweights = NULL;
mesh->bones = NULL;
mesh->numbones = 0;
}
b->meshes = 1;
}
qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel);
static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches);
static void R_HL_BuildMesh(struct batch_s *b)
{
R_HalfLife_WalkMeshes(b->ent, b, NULL);
}
static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
void R_HalfLife_GenerateBatches(entity_t *rent, batch_t **batches)
{
hlmodel_t *model = Mod_Extradata(rent->model);
int body, m;
int batchid = 0;
static mesh_t bmesh, *mptr = &bmesh;
skinfile_t *sk = NULL;
skinfile_t *sk = rent->customskin?Mod_LookupSkin(rent->customskin):NULL;
unsigned int entity_body = 0;
const unsigned int entity_body = 0/*rent->body*/;
batch_t *b = NULL;
if (rent->customskin)
sk = Mod_LookupSkin(rent->customskin);
//entity_body = rent->body; //hey, if its there, lets use it.
unsigned int surfidx = 0;
R_CalcModelLighting(rent, rent->model); //make sure the ent's lighting is right.
/*if (!model->vbobuilt)
{
mesh_t *mesh = &model->mesh;
vbo_t *vbo = &model->vbo;
vbobctx_t ctx;
model->vbobuilt = true;
BE_VBO_Begin(&ctx, (sizeof(*mesh->xyz_array)+
sizeof(*mesh->colors4b_array)+
sizeof(*mesh->st_array)+
sizeof(*mesh->lmst_array[0])+
sizeof(*mesh->normals_array)+
sizeof(*mesh->bonenums)+
sizeof(*mesh->boneweights)+
sizeof(*mesh->snormals_array)+
sizeof(*mesh->tnormals_array))*mesh->numvertexes);
BE_VBO_Data(&ctx, mesh->xyz_array, sizeof(*mesh->xyz_array)*mesh->numvertexes, &vbo->coord);
BE_VBO_Data(&ctx, mesh->colors4b_array, sizeof(*mesh->colors4b_array)*mesh->numvertexes, &vbo->colours[0]);vbo->colours_bytes = true;
BE_VBO_Data(&ctx, mesh->st_array, sizeof(*mesh->st_array)*mesh->numvertexes, &vbo->texcoord);
BE_VBO_Data(&ctx, mesh->lmst_array[0], sizeof(*mesh->lmst_array[0])*mesh->numvertexes, &vbo->lmcoord[0]);
BE_VBO_Data(&ctx, mesh->normals_array, sizeof(*mesh->normals_array)*mesh->numvertexes, &vbo->normals);
BE_VBO_Data(&ctx, mesh->bonenums, sizeof(*mesh->bonenums)*mesh->numvertexes, &vbo->bonenums);
BE_VBO_Data(&ctx, mesh->boneweights, sizeof(*mesh->boneweights)*mesh->numvertexes, &vbo->boneweights);
#if defined(RTLIGHTS)
BE_VBO_Data(&ctx, mesh->snormals_array, sizeof(*mesh->snormals_array)*mesh->numvertexes, &vbo->tvector);
BE_VBO_Data(&ctx, mesh->tnormals_array, sizeof(*mesh->tnormals_array)*mesh->numvertexes, &vbo->svector);
#endif
BE_VBO_Finish(&ctx, mesh->indexes, mesh->numindexes, &vbo->indicies, &vbo->vbomem, &vbo->ebomem);
}*/
for (body = 0; body < model->numgeomsets; body++)
{
@ -1289,14 +1524,15 @@ static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
/* Draw each mesh */
for(m = 0; m < amodel->nummesh; m++)
for(m = 0; m < amodel->nummesh; m++, surfidx++)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_mesh_t *mesh = (hlmdl_mesh_t *) ((qbyte *) model->header + amodel->meshindex) + m;
float tex_w;
float tex_h;
struct hlmodelshaders_s *s;
int skinidx = mesh->skinindex;
texnums_t *skin;
shader_t *shader;
int sort, j;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if (skinidx >= model->numskinrefs)
@ -1305,54 +1541,59 @@ static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
skinidx += rent->skinnum * model->numskinrefs;
s = &model->shaders[model->skinref[skinidx]];
if (batches)
{
int sort, j;
if (!s->shader)
{
if (s->defaultshadertext)
s->shader = R_RegisterShader(s->name, SUF_NONE, s->defaultshadertext);
else
s->shader = R_RegisterSkin(s->name, rent->model->name);
// R_BuildDefaultTexnums(&s->defaulttex, s->shader, 0);
}
skin = &s->defaulttex;
shader = s->shader;
if (sk)
{
int i;
for (i = 0; i < sk->nummappings; i++)
{
if (!strcmp(sk->mappings[i].surface, s->name))
{
skin = &sk->mappings[i].texnums;
shader = sk->mappings[i].shader;
break;
}
}
}
if ( rent->forcedshader ) {
shader = rent->forcedshader;
}
if (b && b->skin->base == skin->base && b->shader == shader && b->meshes < countof(b->user.alias.surfrefs))
; //merging it.
else
{
b = BE_GetTempBatch();
if (!b)
return;
b->skin = skin;
b->shader = shader;
if (!s->shader)
{
if (s->defaultshadertext)
s->shader = R_RegisterShader(s->name, SUF_NONE, s->defaultshadertext);
else
s->shader = R_RegisterSkin(s->name, rent->model->name);
R_BuildDefaultTexnums(&s->defaulttex, s->shader, 0);
}
b->skin = NULL;
b->shader = s->shader;
if (sk)
{
int i;
for (i = 0; i < sk->nummappings; i++)
{
if (!strcmp(sk->mappings[i].surface, s->name))
{
b->skin = &sk->mappings[i].texnums;
b->shader = sk->mappings[i].shader;
break;
}
}
}
if ( rent->forcedshader ) {
b->shader = rent->forcedshader;
}
b->buildmeshes = R_HL_BuildMesh;
b->buildmeshes = R_HL_BuildMeshes;
b->ent = rent;
b->mesh = NULL;
b->firstmesh = 0;
b->meshes = 1;
b->meshes = 0;
b->texture = NULL;
for (j = 0; j < MAXRLIGHTMAPS; j++)
{
b->lightmap[j] = -1;
b->surf_first = batchid;
b->lmlightstyle[j] = INVALID_LIGHTSTYLE;
}
b->flags = 0;
sort = b->shader->sort;
sort = shader->sort;
//fixme: we probably need to force some blend modes based on the surface flags.
if (rent->flags & RF_FORCECOLOURMOD)
b->flags |= BEF_FORCECOLOURMOD;
@ -1376,36 +1617,16 @@ static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
}
if (rent->flags & RF_NOSHADOW)
b->flags |= BEF_NOSHADOWS;
b->vbo = NULL;
b->vbo = NULL;//&model->vbo;
b->next = batches[sort];
batches[sort] = b;
}
else
{
if (batchid == b->surf_first)
{
tex_w = 1.0f / s->w;
tex_h = 1.0f / s->h;
b->mesh = &mptr;
R_HL_BuildFrame(model, amodel, b->ent, body, bodyindex, m, tex_w, tex_h, b->mesh[0], b->shader->prog && (b->shader->prog->supportedpermutations & PERMUTATION_SKELETAL));
return;
}
}
batchid++;
b->user.alias.surfrefs[b->meshes++] = (body<<8)|(m&0xff);
}
}
}
qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel);
void R_HalfLife_GenerateBatches(entity_t *e, batch_t **batches)
{
R_CalcModelLighting(e, e->model);
R_HalfLife_WalkMeshes(e, NULL, batches);
}
void HLMDL_DrawHitBoxes(entity_t *rent)
{
hlmodel_t *model = Mod_Extradata(rent->model);

View File

@ -2730,7 +2730,7 @@ static int Mod_Batches_Generate(model_t *mod)
lbatch->texture == surf->texinfo->texture &&
lbatch->shader == shader &&
lbatch->lightmap[0] == lmmerge(surf->lightmaptexturenums[0]) &&
Vector4Compare(plane, lbatch->plane) &&
Vector4Compare(plane, lbatch->user.bmodel.plane) &&
lbatch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES &&
#if MAXRLIGHTMAPS > 1
lbatch->lightmap[1] == lmmerge(surf->lightmaptexturenums[1]) &&
@ -2748,7 +2748,7 @@ static int Mod_Batches_Generate(model_t *mod)
batch->texture == surf->texinfo->texture &&
batch->shader == shader &&
batch->lightmap[0] == lmmerge(surf->lightmaptexturenums[0]) &&
Vector4Compare(plane, batch->plane) &&
Vector4Compare(plane, batch->user.bmodel.plane) &&
batch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES &&
#if MAXRLIGHTMAPS > 1
batch->lightmap[1] == lmmerge(surf->lightmaptexturenums[1]) &&
@ -2794,7 +2794,7 @@ static int Mod_Batches_Generate(model_t *mod)
batch->ent = &r_worldentity;
batch->fog = surf->fog;
batch->envmap = envmap;
Vector4Copy(plane, batch->plane);
Vector4Copy(plane, batch->user.bmodel.plane);
mod->batches[sortid] = batch;
}

View File

@ -160,21 +160,36 @@ typedef struct batch_s
struct
{
unsigned int shadowbatch; //a unique index to accelerate shadowmesh generation (dlights, yay!)
unsigned int ebobatch; //
unsigned int webobatch; //su
};
struct
unsigned int ebobatch; //temporal scene cache stuff, basically just a simple index so we don't have to deal with shader sort values when generating new index lists.
// } bmodel;
// struct
// {
vec4_t plane; /*used only at load (for portal surfaces, so multiple planes are not part of the same batch)*/
} bmodel; //bmodel surfaces.
struct
{
unsigned int surf_first;
unsigned int surf_count;
};
vec4_t plane; /*used only at load (for portal surfaces, so multiple planes are not part of the same batch)*/
unsigned int lightidx;
unsigned int lightmode;
} dlight; //deferred light batches
struct
{
unsigned short surfrefs[sizeof(mesh_t)/sizeof(unsigned short)]; //for hlmdl batching...
} alias;
struct
{
unsigned int surface;
} poly;
/* struct
{
unsigned int first;
unsigned int count;
} surf;*/
struct
{
mesh_t meshbuf;
mesh_t *meshptr;
};
};
} user;
} batch_t;
/*

View File

@ -551,10 +551,10 @@ qboolean Sh_CullLight(dlight_t *dl, qbyte *vvis);
void R_GenDlightMesh(struct batch_s *batch)
{
static mesh_t *meshptr;
dlight_t *l = cl_dlights + batch->surf_first;
dlight_t *l = cl_dlights + batch->user.dlight.lightidx;
vec3_t colour;
int lightflags = batch->surf_count;
int lightflags = batch->user.dlight.lightmode;
VectorCopy(l->color, colour);
if (l->style>=0 && l->style < cl_max_lightstyles)
@ -698,8 +698,8 @@ void R_GenDlightBatches(batch_t *batches[])
b->texture = NULL;
for (j = 0; j < MAXRLIGHTMAPS; j++)
b->lightmap[j] = -1;
b->surf_first = i;
b->surf_count = lmode;
b->user.dlight.lightidx = i;
b->user.dlight.lightmode = lmode;
b->flags |= BEF_NOSHADOWS|BEF_NODLIGHT; //that would be weeird
b->vbo = NULL;
b->next = batches[sort];

View File

@ -270,12 +270,12 @@ void GL_SetupSceneProcessingTextures (void)
void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const model_t *mod)
{
if ((e->flags & RF_WEAPONMODEL) && r_refdef.playerview->viewentity > 0)
if (e->flags & RF_WEAPONMODEL)
{
float em[16];
float vm[16];
if (e->flags & RF_WEAPONMODELNOBOB)
if ((e->flags & RF_WEAPONMODELNOBOB) || r_refdef.playerview->viewentity <= 0)
{
vm[0] = vpn[0];
vm[1] = vpn[1];
@ -625,7 +625,7 @@ static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, float projmatr
}
else
{
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection_std, fovv_x, fovv_y, r_refdef.mindist, false);
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection_std, fov_x, fov_y, r_refdef.mindist, false);
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection_view, fovv_x, fovv_y, r_refdef.mindist, false);
}

View File

@ -355,7 +355,7 @@ static void SHM_Shadow_Cache_Surface(msurface_t *surf)
{
int i;
i = surf->sbatch->shadowbatch;
i = surf->sbatch->user.bmodel.shadowbatch;
if (i < 0)
return;
@ -451,11 +451,11 @@ static void SH_CalcShadowBatches(model_t *mod)
{
if (!l || l->vbo != b->vbo || l->texture != b->texture)
{
b->shadowbatch = mod->numshadowbatches++;
b->user.bmodel.shadowbatch = mod->numshadowbatches++;
l = b;
}
else
b->shadowbatch = l->shadowbatch;
b->user.bmodel.shadowbatch = l->user.bmodel.shadowbatch;
}
}

View File

@ -3387,7 +3387,6 @@ static void GLVID_Shutdown(void)
#ifdef USE_EGL
case PSL_EGL:
EGL_Shutdown();
EGL_UnloadLibrary();
GL_ForgetPointers();
break;
#endif
@ -3431,10 +3430,24 @@ static void GLVID_Shutdown(void)
vm.modes = NULL;
vm.num_modes = 0;
#endif
x11.pXCloseDisplay(vid_dpy);
}
x11.pXCloseDisplay(vid_dpy);
vid_dpy = NULL;
vid_window = (Window)NULL;
switch(currentpsl)
{
#ifdef GLQUAKE
#ifdef USE_EGL
case PSL_EGL:
EGL_UnloadLibrary();
break;
#endif
#endif
default:
break;
}
currentpsl = PSL_NONE;
}

View File

@ -141,21 +141,18 @@ extern qboolean vid_isfullscreen;
static unsigned short originalgammaramps[3][256];
qboolean vid_initializing;
static qboolean vid_initializing;
static int DIBWidth, DIBHeight;
static RECT WindowRect;
static DWORD WindowStyle, ExWindowStyle;
HWND mainwindow;
static HWND dibwindow;
static HDC maindc;
HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
viddef_t vid; // global video state
//unsigned short d_8to16rgbtable[256];
//unsigned d_8to24rgbtable[256];
//unsigned short d_8to16bgrtable[256];
@ -176,10 +173,8 @@ extern cvar_t vid_desktopgamma;
extern cvar_t gl_lateswap;
extern cvar_t vid_preservegamma;
int window_x, window_y;
static int window_x, window_y;
static int window_width, window_height;
int window_center_x, window_center_y;
RECT window_rect;
static LONG WINAPI GLMainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

View File

@ -39,22 +39,6 @@ struct builddata_s
};
void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b); //data === builddata_t
typedef struct
{
int allocated[LMBLOCK_SIZE_MAX];
int firstlm;
int lmnum;
unsigned int width;
unsigned int height;
qboolean deluxe;
} lmalloc_t;
void Mod_LightmapAllocInit(lmalloc_t *lmallocator, qboolean hasdeluxe, unsigned int width, unsigned int height, int firstlm); //firstlm is for debugging stray lightmap indexes
void Mod_LightmapAllocDone(lmalloc_t *lmallocator, model_t *mod);
void Mod_LightmapAllocBlock(lmalloc_t *lmallocator, int w, int h, unsigned short *x, unsigned short *y, int *tnum);
#ifdef GLQUAKE
#if defined(ANDROID) /*FIXME: actually just to use standard GLES headers instead of full GL*/
#ifndef GLSLONLY

View File

@ -295,6 +295,8 @@ typedef struct //this is stored as the cache. an hlmodel_t is generated when dra
texnums_t defaulttex;
shader_t *shader;
int w, h;
int atlasid;
unsigned short x,y;
} *shaders;
short *skinref;
int numskinrefs;
@ -306,15 +308,13 @@ typedef struct //this is stored as the cache. an hlmodel_t is generated when dra
int numalternatives;
struct hlalternative_s
{
mesh_t mesh;
int numsubmeshes;
struct
{
int firstindex;
int numindexes;
} *submesh;
mesh_t *submesh;
} *alternatives;
} *geomset;
mesh_t mesh;
vbo_t vbo;
qboolean vbobuilt;
} hlmodel_t;
/* HL mathlib prototypes: */
@ -343,4 +343,5 @@ int HLMDL_GetAttachment(model_t *model, int tagnum, float *resultmatrix);
//stuff only useful for clients that need to draw stuff
void R_DrawHLModel(entity_t *curent);
void HLMDL_DrawHitBoxes(entity_t *ent);
void R_HalfLife_GenerateBatches(entity_t *rent, batch_t **batches);
#endif

View File

@ -447,9 +447,6 @@ reeval:
break;
}
ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
errorif (!ed || ed->readonly)
{ //boot it over to the debugger
#if INTSIZE == 16
@ -492,9 +489,6 @@ reeval:
break;
}
ed = PROG_TO_EDICT_PB(progfuncs, OPA->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
errorif (!ed || ed->readonly)
{ //boot it over to the debugger
#if INTSIZE == 16
@ -790,7 +784,6 @@ reeval:
PR_SwitchProgsParms(progfuncs, 0);
}
i = -newf->first_statement;
// p = pr_typecurrent;
if (i < externs->numglobalbuiltins)
{
#ifndef QCGC
@ -802,26 +795,18 @@ reeval:
num_edicts = sv_num_edicts;
}
else
{
// if (newf->first_statement == -0x7fffffff)
// ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals);
// else
PR_RunError (&progfuncs->funcs, "Bad builtin call number - %i", -newf->first_statement);
}
// memcpy(&pr_progstate[p].globals[OFS_RETURN], &current_progstate->globals[OFS_RETURN], sizeof(vec3_t));
PR_RunError (&progfuncs->funcs, "Bad builtin call number - %i", -newf->first_statement);
PR_SwitchProgsParms(progfuncs, (progsnum_t)callerprogs);
//decide weather non debugger wants to start debugging.
return prinst.pr_xstatement;
}
// PR_SwitchProgsParms((OPA->function & 0xff000000)>>24);
s = PR_EnterFunction (progfuncs, newf, callerprogs);
st = &pr_statements[s];
}
//resume at the new statement, which might be in a different progs
return s;
// break;
case OP_DONE:
case OP_RETURN:
@ -831,13 +816,7 @@ reeval:
glob[OFS_RETURN] = glob[st->a];
glob[OFS_RETURN+1] = glob[st->a+1];
glob[OFS_RETURN+2] = glob[st->a+2];
/*
{
static char buffer[1024*1024*8];
int size = sizeof buffer;
progfuncs->save_ents(progfuncs, buffer, &size, 0);
}
*/
s = PR_LeaveFunction (progfuncs);
st = &pr_statements[s];
if (prinst.pr_depth == prinst.exitdepth)

View File

@ -3370,7 +3370,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
if (eval_b && eval_b->_int == 4)
{
if (opt_assignments && var_a.cast && var_a.sym == statements[numstatements-1].c.sym && var_a.ofs == statements[numstatements-1].c.ofs)
if (var_a.cast && var_a.sym == statements[numstatements-1].c.sym && var_a.ofs == statements[numstatements-1].c.ofs)
if (var_a.sym && var_b.sym && var_a.sym->temp && var_a.sym->refcount==1)
{
op = &pr_opcodes[OP_ADD_PIW];

View File

@ -12281,6 +12281,7 @@ void PR_DumpPlatform_f(void)
{"startspot", "string", QW|NQ, "Receives the value of the second argument to changelevel from the previous map."},
{"dimension_send", "var float", QW|NQ, "Used by multicast functionality. Multicasts (and related builtins that multicast internally) will only be sent to players where (player.dimension_see & dimension_send) is non-zero."},
{"dimension_default", "//var float", QW|NQ, "Default dimension bitmask", 255},
{"__fullspawndata", "__unused var string", QW|NQ|H2, "Set by the engine before calls to spawn functions, and is most easily parsed with the tokenize builtin. This allows you to handle halflife's multiple-fields-with-the-same-name (or target-specific fields)."},
{"physics_mode", "__used var float", QW|NQ|CS, "0: original csqc - physics are not run\n1: DP-compat. Thinks occur, but not true movetypes.\n2: movetypes occur just as they do in ssqc.", 2},
{"gamespeed", "float", CS, "Set by the engine, this is the value of the sv_gamespeed cvar"},
{"numclientseats", "float", CS, "This is the number of splitscreen clients currently running on this client."},

View File

@ -2010,7 +2010,7 @@ static void SV_Status_f (void)
if (!sv.state)
{
Con_Printf("Server is not running\n");
Con_TPrintf("Server is not running\n");
return;
}
@ -2021,30 +2021,30 @@ static void SV_Status_f (void)
if (cpu)
cpu = 100*svs.stats.latched_active/cpu;
Con_Printf("cpu utilization : %3i%%\n",(int)cpu);
Con_Printf("avg response time: %i ms (%i max)\n",(int)(1000*svs.stats.latched_active/svs.stats.latched_count), (int)(1000*svs.stats.latched_maxresponse));
Con_Printf("packets/frame : %5.2f (%i max)\n", (float)svs.stats.latched_packets/svs.stats.latched_count, svs.stats.latched_maxpackets); //not relevent as a limit.
Con_TPrintf("cpu utilization : %3i%%\n",(int)cpu);
Con_TPrintf("avg response time: %i ms (%i max)\n",(int)(1000*svs.stats.latched_active/svs.stats.latched_count), (int)(1000*svs.stats.latched_maxresponse));
Con_TPrintf("packets/frame : %5.2f (%i max)\n", (float)svs.stats.latched_packets/svs.stats.latched_count, svs.stats.latched_maxpackets); //not relevent as a limit.
if (NET_GetRates(svs.sockets, &pi, &po, &bi, &bo))
Con_Printf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit.
Con_Printf("server uptime : %s\n", ShowTime(realtime));
Con_Printf("public : %s\n", sv_public.value?"yes":"no");
Con_TPrintf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit.
Con_TPrintf("server uptime : %s\n", ShowTime(realtime));
Con_TPrintf("public : %s\n", sv_public.value?"yes":"no");
switch(svs.gametype)
{
#ifdef Q3SERVER
case GT_QUAKE3:
Con_Printf("client types :%s\n", sv_listen_qw.ival?" Q3":"");
Con_TPrintf("client types :%s\n", sv_listen_qw.ival?" Q3":"");
break;
#endif
#ifdef Q2SERVER
case GT_QUAKE2:
Con_Printf("client types :%s\n", sv_listen_qw.ival?" Q2":"");
Con_TPrintf("client types :%s\n", sv_listen_qw.ival?" Q2":"");
break;
#endif
default:
Con_Printf("client types :%s", sv_listen_qw.ival?" QW":"");
Con_TPrintf("client types :%s", sv_listen_qw.ival?" QW":"");
#ifdef NQPROT
Con_Printf("%s%s", (sv_listen_nq.ival==2)?" -NQ":(sv_listen_nq.ival?" NQ":""), sv_listen_dp.ival?" DP":"");
Con_TPrintf("%s%s", (sv_listen_nq.ival==2)?" -NQ":(sv_listen_nq.ival?" NQ":""), sv_listen_dp.ival?" DP":"");
#endif
#ifdef QWOVERQ3
if (sv_listen_q3.ival) Con_Printf(" Q3");
@ -2057,7 +2057,7 @@ static void SV_Status_f (void)
#endif
Con_Printf("\n");
#if defined(TCPCONNECT) && !defined(CLIENTONLY)
Con_Printf("tcp services :");
Con_TPrintf("tcp services :");
#if defined(HAVE_SSL)
if (net_enable_tls.ival)
Con_Printf(" TLS");
@ -2085,12 +2085,12 @@ static void SV_Status_f (void)
return;
}
#endif
Con_Printf("map uptime : %s\n", ShowTime(sv.world.physicstime));
Con_TPrintf("map uptime : %s\n", ShowTime(sv.world.physicstime));
//show the current map+name (but hide name if its too long or would be ugly)
if (columns >= 80 && *sv.mapname && strlen(sv.mapname) < 45 && !strchr(sv.mapname, '\n'))
Con_Printf ("current map : %s (%s)\n", svs.name, sv.mapname);
Con_TPrintf ("current map : %s (%s)\n", svs.name, sv.mapname);
else
Con_Printf ("current map : %s\n", svs.name);
Con_TPrintf ("current map : %s\n", svs.name);
if (svs.gametype == GT_PROGS)
{
@ -2103,25 +2103,25 @@ static void SV_Status_f (void)
continue; //free, and older than the zombie time
count++;
}
Con_Printf("entities : %i/%i/%i (mem: %.1f%%)\n", count, sv.world.num_edicts, sv.world.max_edicts, 100*(float)(sv.world.progs->stringtablesize/(double)sv.world.progs->stringtablemaxsize));
Con_TPrintf("entities : %i/%i/%i (mem: %.1f%%)\n", count, sv.world.num_edicts, sv.world.max_edicts, 100*(float)(sv.world.progs->stringtablesize/(double)sv.world.progs->stringtablemaxsize));
for (count = 1; count < MAX_PRECACHE_MODELS; count++)
if (!sv.strings.model_precache[count])
break;
Con_Printf("models : %i/%i\n", count, MAX_PRECACHE_MODELS);
Con_TPrintf("models : %i/%i\n", count, MAX_PRECACHE_MODELS);
for (count = 1; count < MAX_PRECACHE_SOUNDS; count++)
if (!sv.strings.sound_precache[count])
break;
Con_Printf("sounds : %i/%i\n", count, MAX_PRECACHE_SOUNDS);
Con_TPrintf("sounds : %i/%i\n", count, MAX_PRECACHE_SOUNDS);
for (count = 1; count < MAX_SSPARTICLESPRE; count++)
if (!sv.strings.particle_precache[count])
break;
if (count!=1)
Con_Printf("particles : %i/%i\n", count, MAX_SSPARTICLESPRE);
Con_TPrintf("particles : %i/%i\n", count, MAX_SSPARTICLESPRE);
}
Con_Printf("gamedir : %s\n", FS_GetGamedir(true));
Con_TPrintf("gamedir : %s\n", FS_GetGamedir(true));
if (sv.csqcdebug)
Con_Printf("csqc debug : true\n");
Con_TPrintf("csqc debug : true\n");
#ifdef MVD_RECORDING
SV_Demo_PrintOutputs();
#endif
@ -2133,9 +2133,9 @@ static void SV_Status_f (void)
{
// most remote clients are 40 columns
// 0123456789012345678901234567890123456789
Con_Printf ("name userid frags\n");
Con_Printf (" address rate ping drop\n");
Con_Printf (" ---------------- ---- ---- -----\n");
Con_Printf ( "name userid frags\n"
" address rate ping drop\n"
" ---------------- ---- ---- -----\n");
for (i=0,cl=svs.clients ; i<svs.allocated_client_slots ; i++,cl++)
{
if (!cl->state)

View File

@ -158,47 +158,108 @@ int Sys_DebugLog(char *file, char *fmt, ...)
return 1;
}
/*
================
Sys_Milliseconds
================
*/
unsigned int Sys_Milliseconds (void)
static quint64_t timer_basetime; //used by all clocks to bias them to starting at 0
static void Sys_ClockType_Changed(cvar_t *var, char *oldval);
static cvar_t sys_clocktype = CVARFCD("sys_clocktype", "", CVAR_NOTFROMSERVER, Sys_ClockType_Changed, "Controls which system clock to base timings from.\n0: auto\n"
"1: gettimeofday (may be discontinuous).\n"
"2: monotonic.");
static enum
{
struct timeval tp;
struct timezone tzp;
static int secbase;
QCLOCK_AUTO = 0,
gettimeofday(&tp, &tzp);
QCLOCK_GTOD,
QCLOCK_MONOTONIC,
QCLOCK_REALTIME,
if (!secbase)
QCLOCK_INVALID
} timer_clocktype;
static quint64_t Sys_GetClock(quint64_t *freq)
{
quint64_t t;
if (timer_clocktype == QCLOCK_MONOTONIC)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
*freq = 1000000000;
t = (ts.tv_sec*(quint64_t)1000000000) + ts.tv_nsec;
}
return (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000;
}
else if (timer_clocktype == QCLOCK_REALTIME)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
*freq = 1000000000;
t = (ts.tv_sec*(quint64_t)1000000000) + ts.tv_nsec;
/*
================
Sys_DoubleTime
================
*/
//WARNING t can go backwards
}
else //if (timer_clocktype == QCLOCK_GTOD)
{
struct timeval tp;
gettimeofday(&tp, NULL);
*freq = 1000000;
t = tp.tv_sec*(quint64_t)1000000 + tp.tv_usec;
//WARNING t can go backwards
}
return t - timer_basetime;
}
static void Sys_ClockType_Changed(cvar_t *var, char *oldval)
{
int newtype = var?var->ival:0;
if (newtype >= QCLOCK_INVALID)
newtype = QCLOCK_AUTO;
if (newtype <= QCLOCK_AUTO)
newtype = QCLOCK_MONOTONIC;
if (newtype != timer_clocktype)
{
quint64_t oldtime, oldfreq;
quint64_t newtime, newfreq;
oldtime = Sys_GetClock(&oldfreq);
timer_clocktype = newtype;
timer_basetime = 0;
newtime = Sys_GetClock(&newfreq);
timer_basetime = newtime - (newfreq * (oldtime) / oldfreq);
/*if (host_initialized)
{
const char *clockname = "unknown";
switch(timer_clocktype)
{
case QCLOCK_GTOD: clockname = "gettimeofday"; break;
case QCLOCK_MONOTONIC: clockname = "monotonic"; break;
case QCLOCK_REALTIME: clockname = "realtime"; break;
case QCLOCK_AUTO:
case QCLOCK_INVALID: break;
}
Con_Printf("Clock %s, wraps after %"PRIu64" days, %"PRIu64" years\n", clockname, (((quint64_t)-1)/newfreq)/(24*60*60), (((quint64_t)-1)/newfreq)/(24*60*60*365));
}*/
}
}
static void Sys_InitClock(void)
{
quint64_t freq;
Cvar_Register(&sys_clocktype, "System vars");
//calibrate it, and apply.
Sys_ClockType_Changed(NULL, NULL);
timer_basetime = 0;
timer_basetime = Sys_GetClock(&freq);
}
double Sys_DoubleTime (void)
{
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
quint64_t denum, num = Sys_GetClock(&denum);
return num / (long double)denum;
}
unsigned int Sys_Milliseconds (void)
{
quint64_t denum, num = Sys_GetClock(&denum);
num *= 1000;
return num / denum;
}
/*
@ -671,6 +732,8 @@ is marked
*/
void Sys_Init (void)
{
Sys_InitClock();
Cvar_Register (&sys_nostdout, "System configuration");
Cvar_Register (&sys_extrasleep, "System configuration");

View File

@ -4539,7 +4539,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
if (sysextnames && (!vk.khr_swapchain || !surfext))
{
Con_Printf(CON_ERROR"Vulkan instance lacks driver support for %s\n", sysextnames[0]);
Con_TPrintf(CON_ERROR"Vulkan instance lacks driver support for %s\n", sysextnames[0]);
return false;
}
}
@ -4796,7 +4796,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
case VK_PHYSICAL_DEVICE_TYPE_CPU: type = "software"; break;
}
Con_Printf("Vulkan %u.%u.%u: GPU%i %s %s %s (%u.%u.%u)\n", VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion), VK_VERSION_PATCH(props.apiVersion),
Con_TPrintf("Vulkan %u.%u.%u: GPU%i %s %s %s (%u.%u.%u)\n", VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion), VK_VERSION_PATCH(props.apiVersion),
gpuidx, type, vendor, props.deviceName,
VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion), VK_VERSION_PATCH(props.driverVersion)
);
@ -5017,7 +5017,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
switch(err)
{
case VK_ERROR_INCOMPATIBLE_DRIVER:
Con_Printf(CON_ERROR"VK_ERROR_INCOMPATIBLE_DRIVER: please install an appropriate vulkan driver\n");
Con_TPrintf(CON_ERROR"VK_ERROR_INCOMPATIBLE_DRIVER: please install an appropriate vulkan driver\n");
return false;
case VK_ERROR_EXTENSION_NOT_PRESENT:
case VK_ERROR_FEATURE_NOT_PRESENT: