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:
parent
f7d46b7878
commit
744b9a25db
57 changed files with 1680 additions and 1011 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 (¤t_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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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", "",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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...
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
/*
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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], ¤t_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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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."},
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue