couple of fixes for q2 + berkelium.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4122 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
c9d051b710
commit
4cc1341b22
16 changed files with 204 additions and 69 deletions
|
@ -3658,7 +3658,7 @@ double Host_Frame (double time)
|
|||
SV_Frame();
|
||||
RSpeedEnd(RSPEED_SERVER);
|
||||
host_frametime = ohft;
|
||||
if (cls.protocol != CP_QUAKE3)
|
||||
if (cls.protocol != CP_QUAKE3 && cls.protocol != CP_QUAKE2)
|
||||
CL_ReadPackets (); //q3's cgame cannot cope with input commands with the same time as the most recent snapshot value
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -683,7 +683,7 @@ typedef struct
|
|||
int teamplay;
|
||||
int deathmatch;
|
||||
|
||||
qboolean teamfortress; //*sigh*. This is used for teamplay stuff. This sucks.
|
||||
qboolean teamfortress; // *sigh*. This is used for teamplay stuff. This sucks.
|
||||
qboolean hexen2pickups;
|
||||
|
||||
qboolean sendprespawn;
|
||||
|
|
|
@ -1394,6 +1394,9 @@ qboolean Media_UnregisterDecoder(struct plugin_s *plug, media_decoder_funcs_t *f
|
|||
static qboolean Media_Plugin_DecodeFrame(cin_t *cin, qboolean nosound)
|
||||
{
|
||||
struct plugin_s *oldplug = currentplug;
|
||||
if (!cin->plugin.funcs->decodeframe)
|
||||
return false; //plugin closed or something
|
||||
|
||||
currentplug = cin->plugin.plug;
|
||||
cin->outdata = cin->plugin.funcs->decodeframe(cin->plugin.ctx, nosound, &cin->outtype, &cin->outwidth, &cin->outheight);
|
||||
currentplug = oldplug;
|
||||
|
|
|
@ -57,7 +57,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
//mt_custom - Just an option with callbacks. This is the basis of the top/bottom color seletion, and could be used for all sorts of things.
|
||||
|
||||
|
||||
//Sample menu creation, entirly within /* and */
|
||||
//Sample menu creation, entirly within / * and * /
|
||||
//Note that most of FTE's menus are more complicated, as FTE runs on Q1/Q2/H2 data, and it's choice of menu images reflects this.
|
||||
//Most of the normal menus also have more items too, of course.
|
||||
|
||||
|
|
|
@ -2206,9 +2206,11 @@ void Surf_DrawWorld (void)
|
|||
{
|
||||
int leafnum;
|
||||
int clientarea;
|
||||
#ifdef QUAKE2
|
||||
#ifdef Q2CLIENT
|
||||
if (cls.protocol == CP_QUAKE2) //we can get server sent info
|
||||
{
|
||||
memcpy(areabits, cl.q2frame.areabits, sizeof(areabits));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ //generate the info each frame.
|
||||
|
|
|
@ -85,7 +85,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define AVAIL_OGGVORBIS
|
||||
|
||||
// #define AVAIL_OPENAL /* Jogi's OpenAL support */
|
||||
/* Jogi's OpenAL support */
|
||||
// #define AVAIL_OPENAL
|
||||
#endif
|
||||
|
||||
#if defined(MINGW) || defined(MACOSX)
|
||||
|
@ -109,7 +110,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define D3D9QUAKE
|
||||
#endif
|
||||
|
||||
#if (defined(D3D9QUAKE) || defined(D3D11Quake)) && !defined(D3DQUAKE)
|
||||
#if (defined(D3D9QUAKE) || defined(D3D11QUAKE)) && !defined(D3DQUAKE)
|
||||
#define D3DQUAKE
|
||||
#endif
|
||||
|
||||
|
@ -270,6 +271,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(RTLIGHTS) && !defined(GLQUAKE) && !defined(D3D9QUAKE)
|
||||
#undef RTLIGHTS
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#undef QTERM //not supported - FIXME: move to native plugin
|
||||
#endif
|
||||
|
|
|
@ -331,7 +331,7 @@ static qbyte portalopen[MAX_Q2MAP_AREAPORTALS]; //memset will work if it's a qby
|
|||
|
||||
|
||||
static int mapisq3;
|
||||
cvar_t map_noareas = SCVAR("map_noareas", "1"); //1 for lack of mod support.
|
||||
cvar_t map_noareas = SCVAR("map_noareas", "0"); //1 for lack of mod support.
|
||||
cvar_t map_noCurves = SCVARF("map_noCurves", "0", CVAR_CHEAT);
|
||||
cvar_t map_autoopenportals = SCVAR("map_autoopenportals", "1"); //1 for lack of mod support.
|
||||
cvar_t r_subdivisions = SCVAR("r_subdivisions", "2");
|
||||
|
@ -2318,6 +2318,13 @@ qboolean CModQ3_LoadFogs (lump_t *l)
|
|||
{
|
||||
out->planes[j] = brushsides[j].plane;
|
||||
}
|
||||
|
||||
if (!out->shader->fog_dist)
|
||||
{
|
||||
//invalid fog shader, don't use.
|
||||
out->shader = NULL;
|
||||
out->numplanes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2858,7 +2865,7 @@ qboolean CModRBSP_LoadRFaces (lump_t *l)
|
|||
R_BuildDefaultTexnums(&out->texinfo->texture->shader->defaulttextures, out->texinfo->texture->shader);
|
||||
}
|
||||
|
||||
if (in->fognum < 0 || in->fognum >= map_numfogs)
|
||||
if (in->fognum < 0 || in->fognum >= map_numfogs || !map_fogs[in->fognum].shader)
|
||||
out->fog = NULL;
|
||||
else
|
||||
out->fog = map_fogs + in->fognum;
|
||||
|
@ -5840,6 +5847,17 @@ int CM_WriteAreaBits (model_t *mod, qbyte *buffer, int area)
|
|||
}
|
||||
|
||||
|
||||
void CM_InitPortalState(void)
|
||||
{
|
||||
int i;
|
||||
//if we're not running q2, force all q2 portals open.
|
||||
if (svs.gametype != GT_QUAKE2 && !mapisq3)
|
||||
{
|
||||
for (i = 0; i < numareas; i++)
|
||||
map_q2areas[i].floodnum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CM_WritePortalState
|
||||
|
|
|
@ -477,7 +477,7 @@ static qintptr_t VARGS Plug_ExportNative(void *offset, quintptr_t mask, const qi
|
|||
else if (!strcmp(name, "Media_VideoDecoder"))
|
||||
{
|
||||
Media_RegisterDecoder(currentplug, func);
|
||||
currentplug->blockcloses++;
|
||||
// currentplug->blockcloses++;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -285,11 +285,16 @@ void QCBUILTIN PF_getsurfacetexture(progfuncs_t *prinst, struct globalvars_s *pr
|
|||
// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
|
||||
void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
#define TriangleNormal(a,b,c,n) ( \
|
||||
(n)[0] = ((a)[1] - (b)[1]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[1] - (b)[1]), \
|
||||
(n)[1] = ((a)[2] - (b)[2]) * ((c)[0] - (b)[0]) - ((a)[0] - (b)[0]) * ((c)[2] - (b)[2]), \
|
||||
(n)[2] = ((a)[0] - (b)[0]) * ((c)[1] - (b)[1]) - ((a)[1] - (b)[1]) * ((c)[0] - (b)[0]) \
|
||||
)
|
||||
|
||||
model_t *model;
|
||||
wedict_t *ent;
|
||||
msurface_t *surf;
|
||||
int i;
|
||||
float planedist;
|
||||
float *point;
|
||||
|
||||
vec3_t edgedir;
|
||||
|
@ -312,20 +317,20 @@ void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *
|
|||
if (!model || model->type != mod_brush)
|
||||
return;
|
||||
|
||||
if (model->fromgame != fg_quake)
|
||||
return;
|
||||
|
||||
if (model->fromgame == fg_quake)
|
||||
{
|
||||
//all polies, we can skip parts. special case.
|
||||
|
||||
surf = model->surfaces + model->firstmodelsurface;
|
||||
for (i = 0; i < model->nummodelsurfaces; i++, surf++)
|
||||
{
|
||||
planedist = DotProduct(point, surf->plane->normal) - surf->plane->dist;
|
||||
dist = DotProduct(point, surf->plane->normal) - surf->plane->dist;
|
||||
//don't care about SURF_PLANEBACK, the maths works out the same.
|
||||
|
||||
if (planedist*planedist < bestdist)
|
||||
if (dist*dist < bestdist)
|
||||
{ //within a specific range
|
||||
//make sure it's within the poly
|
||||
VectorMA(point, planedist, surf->plane->normal, cpoint);
|
||||
VectorMA(point, dist, surf->plane->normal, cpoint);
|
||||
for (e = surf->firstedge+surf->numedges; e > surf->firstedge; edge++)
|
||||
{
|
||||
edge = model->surfedges[--e];
|
||||
|
@ -362,12 +367,90 @@ void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int j;
|
||||
float *v1, *v2;
|
||||
vec3_t trinorm;
|
||||
|
||||
//if performance is needed, I suppose we could try walking bsp nodes a bit
|
||||
surf = model->surfaces + model->firstmodelsurface;
|
||||
for (i = 0; i < model->nummodelsurfaces; i++, surf++)
|
||||
{
|
||||
mesh_t *mesh = surf->mesh;
|
||||
/* vec3_t mins, maxs;
|
||||
|
||||
//calc the surface bounds
|
||||
ClearBounds(mins, maxs);
|
||||
for (j = 0; j < mesh->numvertexes; j++)
|
||||
AddPointToBounds(mesh->xyz_array[j], mins, maxs);
|
||||
|
||||
//clip the point to within those bounds
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
if (cpoint[j] < mins[j])
|
||||
cpoint[j] = mins[j];
|
||||
else
|
||||
cpoint[j] = point[j];
|
||||
|
||||
if (cpoint[j] > maxs[j])
|
||||
cpoint[j] = maxs[j];
|
||||
}
|
||||
//if the point got clipped to too far away, we can't do much
|
||||
VectorSubtract(point, cpoint, temp);
|
||||
dist = DotProduct(temp, temp);
|
||||
if (dist*dist > bestdist)
|
||||
continue;
|
||||
*/
|
||||
for (j = 0; j < mesh->numindexes; j+=3)
|
||||
{
|
||||
//calculate the distance from the plane
|
||||
TriangleNormal(mesh->xyz_array[mesh->indexes[j+2]], mesh->xyz_array[mesh->indexes[j+1]], mesh->xyz_array[mesh->indexes[j+0]], trinorm);
|
||||
if (!trinorm[0] && !trinorm[1] && !trinorm[2])
|
||||
continue;
|
||||
VectorNormalize(trinorm);
|
||||
dist = DotProduct(point, trinorm) - DotProduct(mesh->xyz_array[mesh->indexes[j+0]], trinorm);
|
||||
if (dist*dist < bestdist)
|
||||
{
|
||||
//set cpoint to be the point on the plane
|
||||
VectorMA(point, -dist, trinorm, cpoint);
|
||||
|
||||
//clip to each edge of the triangle
|
||||
for (e = 0; e < 3; e++)
|
||||
{
|
||||
v1 = mesh->xyz_array[mesh->indexes[j+e]];
|
||||
v2 = mesh->xyz_array[mesh->indexes[j+((e+1)%3)]];
|
||||
|
||||
VectorSubtract(v1, v2, edgedir);
|
||||
CrossProduct(edgedir, trinorm, edgenormal);
|
||||
VectorNormalize(edgenormal);
|
||||
|
||||
dist = DotProduct(cpoint, edgenormal) - DotProduct(v1, edgenormal);
|
||||
if (dist < 0)
|
||||
VectorMA(cpoint, -dist, edgenormal, cpoint);
|
||||
}
|
||||
|
||||
//if the point is closer, we win.
|
||||
VectorSubtract(cpoint, point, temp);
|
||||
dist = DotProduct(temp, temp);
|
||||
if (dist < bestdist)
|
||||
{
|
||||
bestsurf = i;
|
||||
bestdist = dist;
|
||||
//can't break, one of the other tris might be closer.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
G_FLOAT(OFS_RETURN) = bestsurf;
|
||||
}
|
||||
|
||||
// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
|
||||
void QCBUILTIN PF_getsurfaceclippedpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
Con_Printf("PF_getsurfaceclippedpoint not implemented\n");
|
||||
}
|
||||
|
||||
// #628 float(entity e, float s) getsurfacenumtriangles
|
||||
|
|
|
@ -2019,6 +2019,7 @@ static void BE_DrawMeshChain_Internal(void)
|
|||
switch (shaderstate.mode)
|
||||
{
|
||||
case BEM_LIGHT:
|
||||
if (shaderstate.shader_rtlight->prog)
|
||||
BE_RenderMeshProgram(shaderstate.shader_rtlight, vertcount, idxfirst, idxcount);
|
||||
break;
|
||||
case BEM_DEPTHONLY:
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "glquake.h"
|
||||
|
||||
#ifdef D3DQUAKE
|
||||
#ifdef D3D9QUAKE
|
||||
#include "winquake.h"
|
||||
|
||||
#if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500)
|
||||
|
|
|
@ -1515,7 +1515,7 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
|
|||
else if (qrenderer == QR_DIRECT3D9)
|
||||
FS_LoadFile(va("hlsl/%s.hlsl", basicname), &file);
|
||||
else if (qrenderer == QR_DIRECT3D11)
|
||||
FS_LoadFile(va("hlsl/%s.hlsl", basicname), &file);
|
||||
FS_LoadFile(va("hlsl11/%s.hlsl", basicname), &file);
|
||||
else if (qrenderer == QR_OPENGL)
|
||||
{
|
||||
#ifdef GLQUAKE
|
||||
|
@ -1625,7 +1625,7 @@ void Shader_WriteOutGenerics_f(void)
|
|||
else if (sbuiltins[i].qrtype == QR_DIRECT3D9)
|
||||
name = va("hlsl/%s.hlsl", sbuiltins[i].name);
|
||||
else if (sbuiltins[i].qrtype == QR_DIRECT3D11)
|
||||
name = va("hlsl/%s.hlsl", sbuiltins[i].name);
|
||||
name = va("hlsl11/%s.hlsl", sbuiltins[i].name);
|
||||
|
||||
if (name)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,6 @@ model meshes are interpolated multiple times per frame
|
|||
//#define DBG_COLOURNOTDEPTH
|
||||
|
||||
|
||||
#if defined(GLQUAKE) || defined(D3D9QUAKE)
|
||||
#ifdef RTLIGHTS
|
||||
|
||||
#include "glquake.h"
|
||||
|
@ -3080,4 +3079,3 @@ void Sh_DrawLights(qbyte *vis)
|
|||
// memset(&bench, 0, sizeof(bench));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
//network interface
|
||||
//network interface+main module
|
||||
|
||||
//this code should work okay as a host server for Xepher.
|
||||
//issue these two commands and Xephyr will do all the stuff we don't support properly.
|
||||
//DISPLAY=127.0.0.1:0 Xephyr :1
|
||||
//wmaker -display :1 (or xterm or whatever)
|
||||
|
||||
#include "../plugin.h"
|
||||
#include "../engine.h"
|
||||
|
@ -13,6 +18,7 @@ static qhandle_t xlistensocket=NULL;
|
|||
xwindow_t *xfocusedwindow;
|
||||
|
||||
qboolean xrefreshed;
|
||||
qboolean xscreenmodified; //texture updated
|
||||
|
||||
xclient_t *xgrabbedclient; //clients can ask the server to ignore other clients
|
||||
extern xwindow_t *xpgrabbedwindow;
|
||||
|
@ -1355,10 +1361,9 @@ void X_EvalutateCursorOwner(int movemode)
|
|||
|
||||
if (mx != x_mousex || my != x_mousey)
|
||||
{
|
||||
mask |= PointerMotionMask;
|
||||
if (mousestate)
|
||||
mask |= ButtonMotionMask;
|
||||
else
|
||||
mask |= PointerMotionMask;
|
||||
}
|
||||
if ((mousestate^x_mousestate) & Button1Mask)
|
||||
mask |= Button1MotionMask;
|
||||
|
@ -1669,6 +1674,7 @@ void XWindows_Draw(void)
|
|||
{
|
||||
XWindows_RefreshWindow(rootwindow);
|
||||
xrefreshed = false;
|
||||
xscreenmodified = true;
|
||||
// Con_Printf("updated screen\n");
|
||||
}
|
||||
|
||||
|
@ -1915,7 +1921,7 @@ int Plug_MenuEvent(int *args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int Plug_ExecuteCommand(int *args)
|
||||
qintptr_t Plug_ExecuteCommand(qintptr_t *args)
|
||||
{
|
||||
char cmd[256];
|
||||
Cmd_Argv(0, cmd, sizeof(cmd));
|
||||
|
@ -1927,7 +1933,7 @@ int Plug_ExecuteCommand(int *args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int Plug_Tick(int *args)
|
||||
qintptr_t Plug_Tick(qintptr_t *args)
|
||||
{
|
||||
XWindows_TendToClients();
|
||||
return 0;
|
||||
|
@ -1950,6 +1956,10 @@ qbyte *XWindows_DisplayFrame(void *ctx, qboolean nosound, enum uploadfmt *fmt, i
|
|||
*fmt = TF_BGRX32;
|
||||
*width = xscreenwidth;
|
||||
*height = xscreenheight;
|
||||
|
||||
if (!xscreenmodified)
|
||||
return NULL;
|
||||
xscreenmodified = false;
|
||||
return xscreen;
|
||||
}
|
||||
|
||||
|
@ -1971,6 +1981,7 @@ static qboolean XWindows_SetSize (void *ctx, int width, int height)
|
|||
xscreen = ns;
|
||||
xscreenwidth = width;
|
||||
xscreenheight = height;
|
||||
xscreenmodified = true;
|
||||
|
||||
//FIXME: resize root window + send notify
|
||||
|
||||
|
@ -2015,7 +2026,7 @@ media_decoder_funcs_t decoderfuncs =
|
|||
};
|
||||
|
||||
|
||||
int Plug_Init(int *args)
|
||||
qintptr_t Plug_Init(qintptr_t *args)
|
||||
{
|
||||
if (!Plug_Export("ExecuteCommand", Plug_ExecuteCommand) ||
|
||||
// !Plug_Export("MenuEvent", Plug_MenuEvent) ||
|
||||
|
|
|
@ -1437,7 +1437,7 @@ void XR_GetKeyboardMapping (xclient_t *cl, xReq *request)
|
|||
|
||||
void XR_QueryPointer (xclient_t *cl, xReq *request)
|
||||
{
|
||||
extern int mousecursor_x, mousecursor_y;
|
||||
extern int x_mousex, x_mousey, x_mousestate;
|
||||
xQueryPointerReply rep;
|
||||
|
||||
rep.type = X_Reply;
|
||||
|
@ -1446,14 +1446,25 @@ void XR_QueryPointer (xclient_t *cl, xReq *request)
|
|||
rep.length = 0;
|
||||
rep.root = rootwindow->res.id;
|
||||
rep.child = rootwindow->res.id;
|
||||
rep.rootX = mousecursor_x;
|
||||
rep.rootY = mousecursor_y;
|
||||
rep.winX = mousecursor_x;
|
||||
rep.winY = mousecursor_y;
|
||||
rep.rootX = x_mousex;
|
||||
rep.rootY = x_mousey;
|
||||
rep.winX = x_mousex;
|
||||
rep.winY = x_mousey;
|
||||
rep.mask = 0;
|
||||
rep.pad1 = 0;
|
||||
rep.pad = 0;
|
||||
|
||||
if ((x_mousestate) & Button1Mask)
|
||||
rep.mask |= Button1MotionMask;
|
||||
if ((x_mousestate) & Button2Mask)
|
||||
rep.mask |= Button2MotionMask;
|
||||
if ((x_mousestate) & Button3Mask)
|
||||
rep.mask |= Button3MotionMask;
|
||||
if ((x_mousestate) & Button4Mask)
|
||||
rep.mask |= Button4MotionMask;
|
||||
if ((x_mousestate) & Button5Mask)
|
||||
rep.mask |= Button5MotionMask;
|
||||
|
||||
X_SendData(cl, &rep, sizeof(rep));
|
||||
}
|
||||
|
||||
|
@ -2127,7 +2138,6 @@ void XR_CreatePixmap(xclient_t *cl, xReq *request)
|
|||
// X_SendError(cl, BadValue, req->depth, X_CreatePixmap, 0);
|
||||
// return;
|
||||
}
|
||||
req->depth = 24;
|
||||
|
||||
if (XS_GetResource(req->pid, (void**)&newpix) != x_none)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@ xwindow_t *rootwindow;
|
|||
xresource_t *resources;
|
||||
|
||||
qbyte *xscreen;
|
||||
qboolean xscreenmodified;
|
||||
short xscreenwidth;
|
||||
short xscreenheight;
|
||||
|
||||
|
@ -392,6 +393,7 @@ xwindow_t *XS_CreateWindow(int wid, xclient_t *owner, xwindow_t *parent, short x
|
|||
neww->width = width;
|
||||
neww->height = height;
|
||||
neww->buffer = NULL;
|
||||
neww->depth = 24;
|
||||
|
||||
XS_SetParent(neww, parent);
|
||||
|
||||
|
@ -561,6 +563,7 @@ void XS_CreateInitialResources(void)
|
|||
xscreenwidth = 640;
|
||||
xscreenheight = 480;
|
||||
xscreen = realloc(xscreen, xscreenwidth*4 * xscreenheight);
|
||||
xscreenmodified = true;
|
||||
|
||||
XS_CheckResourceSentinals();
|
||||
|
||||
|
@ -643,6 +646,7 @@ void XS_CreateInitialResources(void)
|
|||
XS_CreateAtom(baseres++, "WM_TRANSIENT_FOR", NULL);
|
||||
|
||||
rootwindow = XS_CreateWindow(baseres++, NULL, NULL, 0, 0, xscreenwidth, xscreenheight);
|
||||
rootwindow->depth = 24;
|
||||
rootwindow->mapped = true;
|
||||
|
||||
XS_CheckResourceSentinals();
|
||||
|
|
Loading…
Reference in a new issue