2004-08-23 00:15:46 +00:00
|
|
|
#include "quakedef.h"
|
2005-09-09 23:40:55 +00:00
|
|
|
#ifdef VM_UI
|
2008-12-23 02:55:20 +00:00
|
|
|
#include "clq3defs.h"
|
2004-08-23 00:15:46 +00:00
|
|
|
#include "ui_public.h"
|
|
|
|
#include "cl_master.h"
|
2006-02-11 14:51:36 +00:00
|
|
|
#include "shader.h"
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2019-09-04 07:59:40 +00:00
|
|
|
static int keycatcher;
|
2005-09-08 22:52:46 +00:00
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
#define TT_STRING 1 // string
|
|
|
|
#define TT_LITERAL 2 // literal
|
|
|
|
#define TT_NUMBER 3 // number
|
|
|
|
#define TT_NAME 4 // name
|
|
|
|
#define TT_PUNCTUATION 5 // punctuation
|
|
|
|
|
|
|
|
#define SCRIPT_MAXDEPTH 64
|
|
|
|
#define SCRIPT_DEFINELENGTH 256
|
|
|
|
typedef struct {
|
|
|
|
char *filestack[SCRIPT_MAXDEPTH];
|
|
|
|
char *originalfilestack[SCRIPT_MAXDEPTH];
|
2006-03-12 05:21:15 +00:00
|
|
|
char *lastreadptr;
|
|
|
|
int lastreaddepth;
|
2005-08-26 22:56:51 +00:00
|
|
|
char filename[MAX_QPATH][SCRIPT_MAXDEPTH];
|
|
|
|
int stackdepth;
|
|
|
|
|
|
|
|
char *defines;
|
|
|
|
int numdefines;
|
|
|
|
} script_t;
|
2009-11-04 21:16:50 +00:00
|
|
|
static script_t *scripts;
|
|
|
|
static int maxscripts;
|
2019-01-29 07:18:07 +00:00
|
|
|
static unsigned int ui_width, ui_height; //to track when it needs to be restarted (the api has no video mode changed event)
|
2019-09-04 07:59:40 +00:00
|
|
|
static menu_t uimenu;
|
|
|
|
|
|
|
|
void Q3_SetKeyCatcher(int newcatcher)
|
|
|
|
{
|
|
|
|
int delta = newcatcher^keycatcher;
|
|
|
|
keycatcher = newcatcher;
|
|
|
|
if (delta & 2)
|
|
|
|
{
|
|
|
|
uimenu.isopaque = false; //no surprises.
|
|
|
|
if (newcatcher&2)
|
|
|
|
Menu_Push(&uimenu, false);
|
|
|
|
else
|
|
|
|
Menu_Unlink(&uimenu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int Q3_GetKeyCatcher(void)
|
|
|
|
{
|
|
|
|
return keycatcher;
|
|
|
|
}
|
2006-03-12 05:21:15 +00:00
|
|
|
#define Q3SCRIPTPUNCTUATION "(,{})(\':;=!><&|+-\""
|
|
|
|
void StripCSyntax (char *s)
|
|
|
|
{
|
|
|
|
while(*s)
|
|
|
|
{
|
|
|
|
if (*s == '\\')
|
|
|
|
{
|
|
|
|
memmove(s, s+1, strlen(s+1)+1);
|
|
|
|
switch (*s)
|
|
|
|
{
|
|
|
|
case 'r':
|
|
|
|
*s = '\r';
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
*s = '\n';
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
*s = '\\';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*s = '?';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
2006-02-12 00:01:42 +00:00
|
|
|
int Script_Read(int handle, struct pc_token_s *token)
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2006-03-12 05:21:15 +00:00
|
|
|
char *s;
|
|
|
|
char readstring[8192];
|
2005-08-26 22:56:51 +00:00
|
|
|
int i;
|
|
|
|
script_t *sc = scripts+handle-1;
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
if (!sc->stackdepth)
|
2006-03-12 05:21:15 +00:00
|
|
|
{
|
|
|
|
memset(token, 0, sizeof(*token));
|
2005-08-26 22:56:51 +00:00
|
|
|
return 0;
|
2006-03-12 05:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
s = sc->filestack[sc->stackdepth-1];
|
|
|
|
sc->lastreadptr = s;
|
|
|
|
sc->lastreaddepth = sc->stackdepth;
|
2005-08-26 22:56:51 +00:00
|
|
|
|
2006-03-12 05:21:15 +00:00
|
|
|
s = (char *)COM_ParseToken(s, Q3SCRIPTPUNCTUATION);
|
2007-08-30 02:15:25 +00:00
|
|
|
Q_strncpyz(readstring, com_token, sizeof(readstring));
|
2006-03-12 05:21:15 +00:00
|
|
|
if (com_tokentype == TTP_STRING)
|
|
|
|
{
|
|
|
|
while(s)
|
|
|
|
{
|
|
|
|
while (*s > '\0' && *s <= ' ')
|
|
|
|
s++;
|
|
|
|
if (*s == '/' && s[1] == '/')
|
|
|
|
{
|
|
|
|
while(*s && *s != '\n')
|
|
|
|
s++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
while (*s > '\0' && *s <= ' ')
|
|
|
|
s++;
|
|
|
|
if (*s == '\"')
|
|
|
|
{
|
|
|
|
s = (char*)COM_ParseToken(s, Q3SCRIPTPUNCTUATION);
|
2007-08-30 02:15:25 +00:00
|
|
|
Q_strncatz(readstring, com_token, sizeof(readstring));
|
2006-03-12 05:21:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sc->filestack[sc->stackdepth-1] = s;
|
2019-07-02 04:12:20 +00:00
|
|
|
if (com_tokentype == TTP_LINEENDING)
|
|
|
|
continue; //apparently we shouldn't stop on linebreaks
|
2005-08-26 22:56:51 +00:00
|
|
|
|
2006-03-12 05:21:15 +00:00
|
|
|
if (!strcmp(readstring, "#include"))
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2005-10-05 02:44:40 +00:00
|
|
|
sc->filestack[sc->stackdepth-1] = (char *)COM_ParseToken(sc->filestack[sc->stackdepth-1], Q3SCRIPTPUNCTUATION);
|
2005-08-26 22:56:51 +00:00
|
|
|
|
|
|
|
if (sc->stackdepth == SCRIPT_MAXDEPTH) //just don't enter it
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (sc->originalfilestack[sc->stackdepth])
|
|
|
|
BZ_Free(sc->originalfilestack[sc->stackdepth]);
|
2014-10-05 20:04:11 +00:00
|
|
|
sc->filestack[sc->stackdepth] = sc->originalfilestack[sc->stackdepth] = FS_LoadMallocFile(com_token, NULL);
|
2006-03-12 05:21:15 +00:00
|
|
|
Q_strncpyz(sc->filename[sc->stackdepth], com_token, MAX_QPATH);
|
2005-08-26 22:56:51 +00:00
|
|
|
sc->stackdepth++;
|
|
|
|
continue;
|
|
|
|
}
|
2006-03-12 05:21:15 +00:00
|
|
|
if (!strcmp(readstring, "#define"))
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
|
|
|
sc->numdefines++;
|
|
|
|
sc->defines = BZ_Realloc(sc->defines, sc->numdefines*SCRIPT_DEFINELENGTH*2);
|
2005-10-05 02:44:40 +00:00
|
|
|
sc->filestack[sc->stackdepth-1] = (char *)COM_ParseToken(sc->filestack[sc->stackdepth-1], Q3SCRIPTPUNCTUATION);
|
2005-08-26 22:56:51 +00:00
|
|
|
Q_strncpyz(sc->defines+SCRIPT_DEFINELENGTH*2*(sc->numdefines-1), com_token, SCRIPT_DEFINELENGTH);
|
2005-10-05 02:44:40 +00:00
|
|
|
sc->filestack[sc->stackdepth-1] = (char *)COM_ParseToken(sc->filestack[sc->stackdepth-1], Q3SCRIPTPUNCTUATION);
|
2005-08-26 22:56:51 +00:00
|
|
|
Q_strncpyz(sc->defines+SCRIPT_DEFINELENGTH*2*(sc->numdefines-1)+SCRIPT_DEFINELENGTH, com_token, SCRIPT_DEFINELENGTH);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2006-03-12 05:21:15 +00:00
|
|
|
if (!*readstring && com_tokentype != TTP_STRING)
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
|
|
|
if (sc->stackdepth==0)
|
2006-03-12 05:21:15 +00:00
|
|
|
{
|
|
|
|
memset(token, 0, sizeof(*token));
|
2005-08-26 22:56:51 +00:00
|
|
|
return 0;
|
2006-03-12 05:21:15 +00:00
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
|
|
|
|
sc->stackdepth--;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2006-03-12 05:21:15 +00:00
|
|
|
if (com_tokentype == TTP_STRING)
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2006-03-12 05:21:15 +00:00
|
|
|
i = sc->numdefines;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < sc->numdefines; i++)
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2006-03-12 05:21:15 +00:00
|
|
|
if (!strcmp(readstring, sc->defines+SCRIPT_DEFINELENGTH*2*i))
|
|
|
|
{
|
|
|
|
Q_strncpyz(token->string, sc->defines+SCRIPT_DEFINELENGTH*2*i+SCRIPT_DEFINELENGTH, sizeof(token->string));
|
|
|
|
break;
|
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
}
|
2006-03-12 05:21:15 +00:00
|
|
|
if (i == sc->numdefines) //otherwise
|
|
|
|
Q_strncpyz(token->string, readstring, sizeof(token->string));
|
|
|
|
|
|
|
|
StripCSyntax(token->string);
|
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
if (token->string[0] == '0' && (token->string[1] == 'x'||token->string[1] == 'X'))
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
token->intvalue = strtoul(token->string, NULL, 16);
|
|
|
|
token->floatvalue = token->intvalue;
|
2005-08-26 22:56:51 +00:00
|
|
|
token->type = TT_NUMBER;
|
2020-03-07 09:00:40 +00:00
|
|
|
token->subtype = 0x100;//TT_HEX;
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
token->intvalue = atoi(token->string);
|
|
|
|
token->floatvalue = atof(token->string);
|
|
|
|
if (token->floatvalue || *token->string == '0' || *token->string == '.')
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
token->type = TT_NUMBER;
|
|
|
|
token->subtype = 0;
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
2020-03-07 09:00:40 +00:00
|
|
|
else if (com_tokentype == TTP_STRING)
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
token->type = TT_STRING;
|
2005-08-26 22:56:51 +00:00
|
|
|
token->subtype = strlen(token->string);
|
|
|
|
}
|
2020-03-07 09:00:40 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (token->string[1] == '\0')
|
|
|
|
{
|
|
|
|
token->type = TT_PUNCTUATION;
|
|
|
|
token->subtype = token->string[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
token->type = TT_NAME;
|
|
|
|
token->subtype = strlen(token->string);
|
|
|
|
}
|
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Con_Printf("Found %s (%i, %i)\n", token->string, token->type, token->subtype);
|
2019-07-02 04:12:20 +00:00
|
|
|
return com_tokentype != TTP_EOF;
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Script_LoadFile(char *filename)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
script_t *sc;
|
|
|
|
for (i = 0; i < maxscripts; i++)
|
|
|
|
if (!scripts[i].stackdepth)
|
|
|
|
break;
|
|
|
|
if (i == maxscripts)
|
|
|
|
{
|
|
|
|
maxscripts++;
|
2008-05-09 14:22:37 +00:00
|
|
|
scripts = BZ_Realloc(scripts, sizeof(script_t)*maxscripts);
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sc = scripts+i;
|
|
|
|
memset(sc, 0, sizeof(*sc));
|
2014-10-05 20:04:11 +00:00
|
|
|
sc->filestack[0] = sc->originalfilestack[0] = FS_LoadMallocFile(filename, NULL);
|
2006-03-12 05:21:15 +00:00
|
|
|
Q_strncpyz(sc->filename[sc->stackdepth], filename, MAX_QPATH);
|
2005-08-26 22:56:51 +00:00
|
|
|
sc->stackdepth = 1;
|
|
|
|
|
|
|
|
return i+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Script_Free(int handle)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
script_t *sc = scripts+handle-1;
|
|
|
|
if (sc->defines)
|
|
|
|
BZ_Free(sc->defines);
|
|
|
|
|
|
|
|
for (i = 0; i < sc->stackdepth; i++)
|
|
|
|
BZ_Free(sc->originalfilestack[i]);
|
2006-03-12 05:21:15 +00:00
|
|
|
|
|
|
|
sc->stackdepth = 0;
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Script_Get_File_And_Line(int handle, char *filename, int *line)
|
|
|
|
{
|
|
|
|
script_t *sc = scripts+handle-1;
|
|
|
|
char *src;
|
|
|
|
char *start;
|
|
|
|
|
2006-03-12 05:21:15 +00:00
|
|
|
if (!sc->lastreaddepth)
|
|
|
|
{
|
|
|
|
*line = 0;
|
|
|
|
Q_strncpyz(filename, sc->filename[0], MAX_QPATH);
|
2005-08-26 22:56:51 +00:00
|
|
|
return;
|
2006-03-12 05:21:15 +00:00
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
*line = 1;
|
|
|
|
|
2006-03-12 05:21:15 +00:00
|
|
|
src = sc->lastreadptr;
|
|
|
|
start = sc->originalfilestack[sc->lastreaddepth-1];
|
2005-08-26 22:56:51 +00:00
|
|
|
|
|
|
|
while(start < src)
|
|
|
|
{
|
|
|
|
if (*start == '\n')
|
|
|
|
(*line)++;
|
|
|
|
start++;
|
|
|
|
}
|
|
|
|
|
2006-03-12 05:21:15 +00:00
|
|
|
Q_strncpyz(filename, sc->filename[sc->lastreaddepth-1], MAX_QPATH);
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
#ifdef GLQUAKE
|
2004-08-23 00:15:46 +00:00
|
|
|
#include "glquake.h"//hack
|
|
|
|
#else
|
|
|
|
typedef float m3by3_t[3][3];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static vm_t *uivm;
|
|
|
|
|
2014-12-23 15:26:42 +00:00
|
|
|
#define MAX_PINGREQUESTS 32
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2019-02-01 08:29:14 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
unsigned int startms;
|
|
|
|
netadr_t adr;
|
2020-02-11 18:06:10 +00:00
|
|
|
char brokername[64];
|
2019-02-01 08:29:14 +00:00
|
|
|
} ui_pings[MAX_PINGREQUESTS];
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2005-08-07 13:18:43 +00:00
|
|
|
#define UITAGNUM 2452
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2014-08-25 07:35:41 +00:00
|
|
|
extern model_t *mod_known;
|
2020-03-07 09:00:40 +00:00
|
|
|
extern int mod_numknown;
|
|
|
|
#define VM_FROMMHANDLE(a) (a>0&&a<=mod_numknown?mod_known+a-1:NULL)
|
2007-09-17 20:35:39 +00:00
|
|
|
#define VM_TOMHANDLE(a) (a?a-mod_known+1:0)
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
#define VM_FROMSHANDLE(a) (a>0&&a<=r_numshaders?r_shaders[a-1]:NULL)
|
2013-10-29 17:38:22 +00:00
|
|
|
#define VM_TOSHANDLE(a) (a?a->id+1:0)
|
2005-09-08 22:52:46 +00:00
|
|
|
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
struct q3refEntity_s {
|
2005-08-26 22:56:51 +00:00
|
|
|
refEntityType_t reType;
|
2004-08-23 00:15:46 +00:00
|
|
|
int renderfx;
|
|
|
|
|
2007-09-17 20:35:39 +00:00
|
|
|
int hModel; // opaque type outside refresh
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
// most recent data
|
|
|
|
vec3_t lightingOrigin; // so multi-part models can be lit identically (RF_LIGHTING_ORIGIN)
|
|
|
|
float shadowPlane; // projection shadows go here, stencils go slightly lower
|
|
|
|
|
|
|
|
vec3_t axis[3]; // rotation vectors
|
|
|
|
qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale
|
|
|
|
float origin[3]; // also used as MODEL_BEAM's "from"
|
|
|
|
int frame; // also used as MODEL_BEAM's diameter
|
|
|
|
|
|
|
|
// previous data for frame interpolation
|
|
|
|
float oldorigin[3]; // also used as MODEL_BEAM's "to"
|
|
|
|
int oldframe;
|
|
|
|
float backlerp; // 0.0 = current, 1.0 = old
|
|
|
|
|
|
|
|
// texturing
|
|
|
|
int skinNum; // inline skin index
|
2007-09-17 20:35:39 +00:00
|
|
|
int customSkin; // NULL for default skin
|
2004-08-23 00:15:46 +00:00
|
|
|
int customShader; // use one image for the entire thing
|
|
|
|
|
|
|
|
// misc
|
|
|
|
qbyte shaderRGBA[4]; // colors used by rgbgen entity shaders
|
|
|
|
float shaderTexCoord[2]; // texture coordinates used by tcMod entity modifiers
|
|
|
|
float shaderTime; // subtracted from refdef time to control effect start times
|
|
|
|
|
|
|
|
// extra sprite information
|
|
|
|
float radius;
|
|
|
|
float rotation;
|
2009-11-04 21:16:50 +00:00
|
|
|
};
|
2004-12-24 08:45:56 +00:00
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
struct q3polyvert_s
|
|
|
|
{
|
|
|
|
vec3_t org;
|
|
|
|
vec2_t tcoord;
|
|
|
|
qbyte colours[4];
|
|
|
|
};
|
2004-12-24 08:45:56 +00:00
|
|
|
|
2008-11-09 22:29:28 +00:00
|
|
|
#define Q3RF_MINLIGHT 1
|
2004-12-24 08:45:56 +00:00
|
|
|
#define Q3RF_THIRD_PERSON 2 // don't draw through eyes, only mirrors (player bodies, chat sprites)
|
|
|
|
#define Q3RF_FIRST_PERSON 4 // only draw through eyes (view weapon, damage blood blob)
|
|
|
|
#define Q3RF_DEPTHHACK 8 // for view weapon Z crunching
|
2008-11-09 22:29:28 +00:00
|
|
|
#define Q3RF_NOSHADOW 64
|
|
|
|
#define Q3RF_LIGHTING_ORIGIN 128
|
2007-09-17 20:35:39 +00:00
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
#define MAX_VMQ3_CACHED_STRINGS 2048
|
|
|
|
char *stringcache[MAX_VMQ3_CACHED_STRINGS];
|
2007-09-17 20:35:39 +00:00
|
|
|
|
2013-06-23 02:17:02 +00:00
|
|
|
void VMQ3_FlushStringHandles(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_VMQ3_CACHED_STRINGS; i++)
|
|
|
|
{
|
|
|
|
if (stringcache[i])
|
|
|
|
{
|
|
|
|
Z_Free(stringcache[i]);
|
|
|
|
stringcache[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-17 20:35:39 +00:00
|
|
|
char *VMQ3_StringFromHandle(int handle)
|
|
|
|
{
|
|
|
|
if (!handle)
|
|
|
|
return "";
|
|
|
|
handle--;
|
|
|
|
if ((unsigned) handle >= MAX_VMQ3_CACHED_STRINGS)
|
|
|
|
return "";
|
|
|
|
return stringcache[handle];
|
|
|
|
}
|
|
|
|
|
|
|
|
int VMQ3_StringToHandle(char *str)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_VMQ3_CACHED_STRINGS; i++)
|
|
|
|
{
|
|
|
|
if (!stringcache[i])
|
|
|
|
break;
|
|
|
|
if (!strcmp(str, stringcache[i]))
|
|
|
|
return i+1;
|
|
|
|
}
|
|
|
|
if (i == MAX_VMQ3_CACHED_STRINGS)
|
|
|
|
{
|
|
|
|
Con_Printf("Q3VM out of string handle space\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
stringcache[i] = Z_Malloc(strlen(str)+1);
|
|
|
|
strcpy(stringcache[i], str);
|
|
|
|
return i+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define VM_TOSTRCACHE(a) VMQ3_StringToHandle(VM_POINTER(a))
|
|
|
|
#define VM_FROMSTRCACHE(a) VMQ3_StringFromHandle(a)
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
void VQ3_AddEntity(const q3refEntity_t *q3)
|
|
|
|
{
|
|
|
|
entity_t ent;
|
|
|
|
memset(&ent, 0, sizeof(ent));
|
2007-09-17 20:35:39 +00:00
|
|
|
ent.model = VM_FROMMHANDLE(q3->hModel);
|
2008-12-23 02:55:20 +00:00
|
|
|
ent.framestate.g[FS_REG].frame[0] = q3->frame;
|
|
|
|
ent.framestate.g[FS_REG].frame[1] = q3->oldframe;
|
2004-12-21 04:29:14 +00:00
|
|
|
memcpy(ent.axis, q3->axis, sizeof(q3->axis));
|
2015-02-02 08:01:53 +00:00
|
|
|
ent.framestate.g[FS_REG].lerpweight[1] = q3->backlerp;
|
|
|
|
ent.framestate.g[FS_REG].lerpweight[0] = 1 - ent.framestate.g[FS_REG].lerpweight[1];
|
2014-02-11 17:51:29 +00:00
|
|
|
if (q3->reType == RT_SPRITE)
|
|
|
|
{
|
|
|
|
ent.scale = q3->radius;
|
|
|
|
ent.rotation = q3->rotation;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ent.scale = 1;
|
2005-08-26 22:56:51 +00:00
|
|
|
ent.rtype = q3->reType;
|
2005-08-07 13:18:43 +00:00
|
|
|
|
2014-03-30 08:55:06 +00:00
|
|
|
ent.customskin = q3->customSkin;
|
|
|
|
ent.skinnum = q3->skinNum;
|
2006-02-27 00:42:25 +00:00
|
|
|
|
|
|
|
ent.shaderRGBAf[0] = q3->shaderRGBA[0]/255.0f;
|
|
|
|
ent.shaderRGBAf[1] = q3->shaderRGBA[1]/255.0f;
|
|
|
|
ent.shaderRGBAf[2] = q3->shaderRGBA[2]/255.0f;
|
|
|
|
ent.shaderRGBAf[3] = q3->shaderRGBA[3]/255.0f;
|
2008-11-09 22:29:28 +00:00
|
|
|
|
2018-01-22 19:18:04 +00:00
|
|
|
/*don't set force-translucent etc, the shader is meant to already be correct*/
|
2008-11-09 22:29:28 +00:00
|
|
|
// if (ent.shaderRGBAf[3] <= 0)
|
|
|
|
// return;
|
|
|
|
|
2007-09-17 20:35:39 +00:00
|
|
|
ent.forcedshader = VM_FROMSHANDLE(q3->customShader);
|
2005-02-09 19:32:09 +00:00
|
|
|
ent.shaderTime = q3->shaderTime;
|
2005-08-07 13:18:43 +00:00
|
|
|
if (q3->renderfx & Q3RF_FIRST_PERSON)
|
2014-03-31 17:06:41 +00:00
|
|
|
ent.flags |= RF_WEAPONMODEL;
|
2004-12-24 08:45:56 +00:00
|
|
|
if (q3->renderfx & Q3RF_DEPTHHACK)
|
2014-03-31 17:06:41 +00:00
|
|
|
ent.flags |= RF_DEPTHHACK;
|
2004-12-24 08:45:56 +00:00
|
|
|
if (q3->renderfx & Q3RF_THIRD_PERSON)
|
2014-03-31 17:06:41 +00:00
|
|
|
ent.flags |= RF_EXTERNALMODEL;
|
2009-11-04 21:16:50 +00:00
|
|
|
if (q3->renderfx & Q3RF_NOSHADOW)
|
|
|
|
ent.flags |= RF_NOSHADOW;
|
|
|
|
|
2014-03-30 08:55:06 +00:00
|
|
|
ent.topcolour = TOP_DEFAULT;
|
|
|
|
ent.bottomcolour = BOTTOM_DEFAULT;
|
|
|
|
ent.playerindex = -1;
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
VectorCopy(q3->origin, ent.origin);
|
2005-08-26 22:56:51 +00:00
|
|
|
VectorCopy(q3->oldorigin, ent.oldorigin);
|
2005-08-07 13:18:43 +00:00
|
|
|
V_AddAxisEntity(&ent);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
void VQ3_AddPoly(shader_t *s, int num, q3polyvert_t *verts)
|
|
|
|
{
|
|
|
|
unsigned int v;
|
|
|
|
scenetris_t *t;
|
|
|
|
/*reuse the previous trigroup if its the same shader*/
|
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
|
|
|
if (cl_numstris && cl_stris[cl_numstris-1].shader == s && cl_stris[cl_numstris-1].flags == (BEF_NODLIGHT|BEF_NOSHADOWS))
|
2009-11-04 21:16:50 +00:00
|
|
|
t = &cl_stris[cl_numstris-1];
|
|
|
|
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 = s;
|
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
|
|
|
t->flags = BEF_NODLIGHT|BEF_NOSHADOWS;
|
2009-11-04 21:16:50 +00:00
|
|
|
t->numidx = 0;
|
|
|
|
t->numvert = 0;
|
|
|
|
t->firstidx = cl_numstrisidx;
|
|
|
|
t->firstvert = cl_numstrisvert;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cl_maxstrisvert < cl_numstrisvert+num)
|
2019-02-19 06:49:03 +00:00
|
|
|
cl_stris_ExpandVerts(cl_numstrisvert+num + 64);
|
2009-11-04 21:16:50 +00:00
|
|
|
if (cl_maxstrisidx < cl_numstrisidx+(num-2)*3)
|
|
|
|
{
|
|
|
|
cl_maxstrisidx = cl_numstrisidx+(num-2)*3 + 64;
|
|
|
|
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (v = 0; v < num; v++)
|
|
|
|
{
|
|
|
|
VectorCopy(verts[v].org, cl_strisvertv[cl_numstrisvert+v]);
|
|
|
|
Vector2Copy(verts[v].tcoord, cl_strisvertt[cl_numstrisvert+v]);
|
|
|
|
Vector4Scale(verts[v].colours, (1/255.0f), cl_strisvertc[cl_numstrisvert+v]);
|
|
|
|
}
|
|
|
|
for (v = 2; v < num; v++)
|
|
|
|
{
|
|
|
|
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert - t->firstvert;
|
|
|
|
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+(v-1) - t->firstvert;
|
|
|
|
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+v - t->firstvert;
|
|
|
|
}
|
|
|
|
|
|
|
|
t->numvert += num;
|
|
|
|
t->numidx += (num-2)*3;
|
|
|
|
cl_numstrisvert += num;
|
|
|
|
//we already increased idx
|
|
|
|
}
|
|
|
|
|
2004-12-24 08:45:56 +00:00
|
|
|
int VM_LerpTag(void *out, model_t *model, int f1, int f2, float l2, char *tagname)
|
|
|
|
{
|
|
|
|
int tagnum;
|
|
|
|
float *ang;
|
|
|
|
float *org;
|
|
|
|
|
2005-06-14 04:52:10 +00:00
|
|
|
float tr[12];
|
|
|
|
qboolean found;
|
2009-01-15 04:58:12 +00:00
|
|
|
framestate_t fstate;
|
2004-12-24 08:45:56 +00:00
|
|
|
|
|
|
|
org = (float*)out;
|
|
|
|
ang = ((float*)out+3);
|
|
|
|
|
2009-01-15 04:58:12 +00:00
|
|
|
memset(&fstate, 0, sizeof(fstate));
|
|
|
|
fstate.g[FS_REG].frame[0] = f1;
|
|
|
|
fstate.g[FS_REG].frame[1] = f2;
|
2015-02-02 08:01:53 +00:00
|
|
|
fstate.g[FS_REG].lerpweight[0] = 1 - l2;
|
|
|
|
fstate.g[FS_REG].lerpweight[1] = l2;
|
2009-01-15 04:58:12 +00:00
|
|
|
|
2007-08-06 21:13:15 +00:00
|
|
|
tagnum = Mod_TagNumForName(model, tagname);
|
2009-01-15 04:58:12 +00:00
|
|
|
found = Mod_GetTag(model, tagnum, &fstate, tr);
|
2004-12-24 08:45:56 +00:00
|
|
|
|
2013-06-23 02:17:02 +00:00
|
|
|
if (found && tagnum)
|
2005-06-14 04:52:10 +00:00
|
|
|
{
|
|
|
|
ang[0] = tr[0];
|
|
|
|
ang[1] = tr[1];
|
|
|
|
ang[2] = tr[2];
|
|
|
|
org[0] = tr[3];
|
2005-08-26 22:56:51 +00:00
|
|
|
|
2005-06-14 04:52:10 +00:00
|
|
|
ang[3] = tr[4];
|
|
|
|
ang[4] = tr[5];
|
|
|
|
ang[5] = tr[6];
|
|
|
|
org[1] = tr[7];
|
2005-08-26 22:56:51 +00:00
|
|
|
|
2005-06-14 04:52:10 +00:00
|
|
|
ang[6] = tr[8];
|
|
|
|
ang[7] = tr[9];
|
|
|
|
ang[8] = tr[10];
|
|
|
|
org[2] = tr[11];
|
2004-12-24 08:45:56 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
org[0] = 0;
|
|
|
|
org[1] = 0;
|
|
|
|
org[2] = 0;
|
|
|
|
|
|
|
|
ang[0] = 1;
|
|
|
|
ang[1] = 0;
|
|
|
|
ang[2] = 0;
|
|
|
|
|
|
|
|
ang[3] = 0;
|
|
|
|
ang[4] = 1;
|
|
|
|
ang[5] = 0;
|
|
|
|
|
|
|
|
ang[6] = 0;
|
|
|
|
ang[7] = 0;
|
|
|
|
ang[8] = 1;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
#define MAX_RENDER_STRINGS 8
|
|
|
|
#define MAX_RENDER_STRING_LENGTH 32
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
struct q3refdef_s {
|
2004-08-23 00:15:46 +00:00
|
|
|
int x, y, width, height;
|
|
|
|
float fov_x, fov_y;
|
|
|
|
vec3_t vieworg;
|
|
|
|
vec3_t viewaxis[3]; // transformation matrix
|
|
|
|
|
|
|
|
// time in milliseconds for shader effects and other time dependent rendering issues
|
|
|
|
int time;
|
|
|
|
|
|
|
|
int rdflags; // RDF_NOWORLDMODEL, etc
|
|
|
|
|
|
|
|
// 1 bits will prevent the associated area from rendering at all
|
|
|
|
qbyte areamask[MAX_MAP_AREA_BYTES];
|
|
|
|
|
|
|
|
// text messages for deform text shaders
|
|
|
|
char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
|
2009-11-04 21:16:50 +00:00
|
|
|
};
|
2017-08-14 16:38:44 +00:00
|
|
|
void R_DrawNameTags(void);
|
2004-08-23 00:15:46 +00:00
|
|
|
void VQ3_RenderView(const q3refdef_t *ref)
|
|
|
|
{
|
2014-06-02 16:50:40 +00:00
|
|
|
int i;
|
2009-11-04 21:16:50 +00:00
|
|
|
extern cvar_t r_torch;
|
2018-01-22 19:18:04 +00:00
|
|
|
|
|
|
|
if (R2D_Flush)
|
|
|
|
R2D_Flush();
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
VectorCopy(ref->vieworg, r_refdef.vieworg);
|
2004-12-24 08:45:56 +00:00
|
|
|
r_refdef.viewangles[0] = -(atan2(ref->viewaxis[0][2], sqrt(ref->viewaxis[0][1]*ref->viewaxis[0][1]+ref->viewaxis[0][0]*ref->viewaxis[0][0])) * 180 / M_PI);
|
2004-08-23 00:15:46 +00:00
|
|
|
r_refdef.viewangles[1] = (atan2(ref->viewaxis[0][1], ref->viewaxis[0][0]) * 180 / M_PI);
|
|
|
|
r_refdef.viewangles[2] = 0;
|
2010-11-13 17:22:46 +00:00
|
|
|
VectorCopy(ref->viewaxis[0], r_refdef.viewaxis[0]);
|
|
|
|
VectorCopy(ref->viewaxis[1], r_refdef.viewaxis[1]);
|
|
|
|
VectorCopy(ref->viewaxis[2], r_refdef.viewaxis[2]);
|
2005-08-07 13:18:43 +00:00
|
|
|
if (ref->rdflags & 1)
|
2014-03-31 17:06:41 +00:00
|
|
|
r_refdef.flags |= RDF_NOWORLDMODEL;
|
2006-03-06 01:41:09 +00:00
|
|
|
else
|
2014-03-31 17:06:41 +00:00
|
|
|
r_refdef.flags &= ~RDF_NOWORLDMODEL;
|
2018-01-22 19:18:04 +00:00
|
|
|
r_refdef.fovv_x = r_refdef.fov_x = ref->fov_x;
|
|
|
|
r_refdef.fovv_y = r_refdef.fov_y = ref->fov_y;
|
2004-08-23 00:15:46 +00:00
|
|
|
r_refdef.vrect.x = ref->x;
|
|
|
|
r_refdef.vrect.y = ref->y;
|
|
|
|
r_refdef.vrect.width = ref->width;
|
|
|
|
r_refdef.vrect.height = ref->height;
|
2005-02-09 19:32:09 +00:00
|
|
|
r_refdef.time = ref->time/1000.0f;
|
2005-08-07 13:18:43 +00:00
|
|
|
r_refdef.useperspective = true;
|
2016-10-22 07:06:51 +00:00
|
|
|
r_refdef.mindist = bound(0.1, gl_mindist.value, 4);
|
|
|
|
r_refdef.maxdist = gl_maxdist.value;
|
2013-06-23 02:17:02 +00:00
|
|
|
r_refdef.playerview = &cl.playerview[0];
|
2004-12-24 08:45:56 +00:00
|
|
|
|
2018-01-22 19:18:04 +00:00
|
|
|
if (ref->y < 0)
|
|
|
|
{ //evil hack to work around player model ui bug.
|
|
|
|
//if the y coord is off screen, reduce the height to keep things centred, and reduce the fov to compensate.
|
|
|
|
r_refdef.vrect.height += ref->y*2;
|
|
|
|
r_refdef.fovv_y = r_refdef.fov_y = ref->fov_y * r_refdef.vrect.height / ref->height;
|
|
|
|
r_refdef.vrect.y = 0;
|
|
|
|
}
|
|
|
|
|
2017-11-30 17:59:11 +00:00
|
|
|
memset(&r_refdef.globalfog, 0, sizeof(r_refdef.globalfog));
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
if (r_torch.ival)
|
|
|
|
{
|
|
|
|
dlight_t *dl;
|
2011-12-27 08:35:19 +00:00
|
|
|
dl = CL_NewDlight(0, ref->vieworg, 300, r_torch.ival, 0.5, 0.5, 0.2);
|
2011-07-30 14:14:56 +00:00
|
|
|
dl->flags |= LFLAG_SHADOWMAP|LFLAG_FLASHBLEND;
|
2009-11-04 21:16:50 +00:00
|
|
|
dl->fov = 60;
|
|
|
|
VectorCopy(ref->viewaxis[0], dl->axis[0]);
|
|
|
|
VectorCopy(ref->viewaxis[1], dl->axis[1]);
|
|
|
|
VectorCopy(ref->viewaxis[2], dl->axis[2]);
|
|
|
|
}
|
|
|
|
|
2014-06-02 16:50:40 +00:00
|
|
|
r_refdef.areabitsknown = true;
|
2015-09-01 04:45:15 +00:00
|
|
|
for (i = 0; i < MAX_MAP_AREA_BYTES/sizeof(int); i++)
|
2014-06-02 16:50:40 +00:00
|
|
|
((int*)r_refdef.areabits)[i] = ((int*)ref->areamask)[i] ^ ~0;
|
2004-08-23 00:15:46 +00:00
|
|
|
R_RenderView();
|
2017-08-14 16:38:44 +00:00
|
|
|
R_DrawNameTags();
|
2013-06-23 02:17:02 +00:00
|
|
|
r_refdef.playerview = NULL;
|
2009-11-04 21:16:50 +00:00
|
|
|
#ifdef GLQUAKE
|
2004-08-23 00:15:46 +00:00
|
|
|
if (qrenderer == QR_OPENGL)
|
|
|
|
{
|
2017-08-14 16:38:44 +00:00
|
|
|
// GL_Set2D (false);
|
2004-12-24 08:45:56 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-02-09 19:32:09 +00:00
|
|
|
r_refdef.time = 0;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
|
|
|
|
void UI_RegisterFont(char *fontName, int pointSize, fontInfo_t *font)
|
|
|
|
{
|
2005-12-17 16:52:22 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
char *c;
|
|
|
|
int *i;
|
|
|
|
float *f;
|
|
|
|
} in;
|
2005-08-26 22:56:51 +00:00
|
|
|
int i;
|
|
|
|
char name[MAX_QPATH];
|
2014-10-05 20:04:11 +00:00
|
|
|
size_t sz;
|
2020-03-07 09:00:40 +00:00
|
|
|
shader_t *shader;
|
2005-12-17 16:52:22 +00:00
|
|
|
#define readInt() LittleLong(*in.i++)
|
|
|
|
#define readFloat() LittleFloat(*in.f++)
|
2005-08-26 22:56:51 +00:00
|
|
|
|
2006-03-06 01:41:09 +00:00
|
|
|
snprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize);
|
2005-08-26 22:56:51 +00:00
|
|
|
|
2018-07-05 16:21:44 +00:00
|
|
|
in.c = COM_LoadTempFile(name, 0, &sz);
|
2014-10-05 20:04:11 +00:00
|
|
|
if (sz == sizeof(fontInfo_t))
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
|
|
|
for(i=0; i<GLYPHS_PER_FONT; i++)
|
|
|
|
{
|
|
|
|
font->glyphs[i].height = readInt();
|
|
|
|
font->glyphs[i].top = readInt();
|
|
|
|
font->glyphs[i].bottom = readInt();
|
|
|
|
font->glyphs[i].pitch = readInt();
|
|
|
|
font->glyphs[i].xSkip = readInt();
|
|
|
|
font->glyphs[i].imageWidth = readInt();
|
|
|
|
font->glyphs[i].imageHeight = readInt();
|
|
|
|
font->glyphs[i].s = readFloat();
|
|
|
|
font->glyphs[i].t = readFloat();
|
|
|
|
font->glyphs[i].s2 = readFloat();
|
|
|
|
font->glyphs[i].t2 = readFloat();
|
|
|
|
font->glyphs[i].glyph = readInt();
|
2005-12-17 16:52:22 +00:00
|
|
|
memcpy(font->glyphs[i].shaderName, in.i, 32);
|
|
|
|
in.c += 32;
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
font->glyphScale = readFloat();
|
2020-03-07 09:00:40 +00:00
|
|
|
memcpy(font->name, in.i, sizeof(font->name));
|
2005-08-26 22:56:51 +00:00
|
|
|
|
|
|
|
// Com_Memcpy(font, faceData, sizeof(fontInfo_t));
|
|
|
|
Q_strncpyz(font->name, name, sizeof(font->name));
|
|
|
|
for (i = GLYPH_START; i < GLYPH_END; i++)
|
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
shader = R_RegisterPic(font->glyphs[i].shaderName, NULL);
|
|
|
|
font->glyphs[i].glyph = VM_TOSHANDLE(shader);
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
static struct
|
|
|
|
{
|
|
|
|
int shaderhandle;
|
|
|
|
int x, y, w, h;
|
|
|
|
qboolean loop;
|
|
|
|
} uicinematics[16];
|
|
|
|
int UI_Cin_Play(const char *name, int x, int y, int w, int h, unsigned int flags)
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
shader_t *mediashader;
|
|
|
|
cin_t *cin;
|
|
|
|
for (idx = 0; ; idx++)
|
|
|
|
{
|
|
|
|
if (idx == countof(uicinematics))
|
|
|
|
return -1; //out of handles
|
|
|
|
if (uicinematics[idx].shaderhandle)
|
|
|
|
continue; //slot in use
|
|
|
|
break; //this slot is usable
|
|
|
|
}
|
|
|
|
|
|
|
|
mediashader = R_RegisterCustom(name, SUF_NONE, Shader_DefaultCinematic, va("video/%s", name));
|
|
|
|
if (!mediashader)
|
|
|
|
return -1; //wtf?
|
|
|
|
cin = R_ShaderGetCinematic(mediashader);
|
|
|
|
if (cin)
|
|
|
|
Media_SetState(cin, CINSTATE_PLAY);
|
|
|
|
else
|
|
|
|
return -1; //FAIL!
|
|
|
|
|
|
|
|
uicinematics[idx].x = x;
|
|
|
|
uicinematics[idx].y = y;
|
|
|
|
uicinematics[idx].w = w;
|
|
|
|
uicinematics[idx].h = h;
|
|
|
|
uicinematics[idx].loop = !!(flags&1);
|
|
|
|
uicinematics[idx].shaderhandle = VM_TOSHANDLE(mediashader);
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
int UI_Cin_Stop(int idx)
|
|
|
|
{
|
|
|
|
if (idx >= 0 && idx < countof(uicinematics))
|
|
|
|
{
|
|
|
|
shader_t *shader = VM_FROMSHANDLE(uicinematics[idx].shaderhandle);
|
|
|
|
R_UnloadShader(shader);
|
|
|
|
uicinematics[idx].shaderhandle = 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int UI_Cin_Run(int idx)
|
|
|
|
{
|
|
|
|
enum {
|
|
|
|
FMV_IDLE,
|
|
|
|
FMV_PLAY, // play
|
|
|
|
FMV_EOF, // all other conditions, i.e. stop/EOF/abort
|
|
|
|
FMV_ID_BLT,
|
|
|
|
FMV_ID_IDLE,
|
|
|
|
FMV_LOOPED,
|
|
|
|
FMV_ID_WAIT
|
|
|
|
};
|
|
|
|
int ret = FMV_IDLE;
|
|
|
|
|
|
|
|
|
|
|
|
if (idx >= 0 && idx < countof(uicinematics))
|
|
|
|
{
|
|
|
|
shader_t *shader = VM_FROMSHANDLE(uicinematics[idx].shaderhandle);
|
|
|
|
cin_t *cin = R_ShaderGetCinematic(shader);
|
|
|
|
if (cin)
|
|
|
|
{
|
|
|
|
switch(Media_GetState(cin))
|
|
|
|
{
|
|
|
|
case CINSTATE_INVALID: ret = FMV_IDLE; break;
|
|
|
|
case CINSTATE_PLAY: ret = FMV_PLAY; break;
|
|
|
|
case CINSTATE_LOOP: ret = FMV_PLAY; break;
|
|
|
|
case CINSTATE_PAUSE: ret = FMV_PLAY; break;
|
|
|
|
case CINSTATE_ENDED:
|
|
|
|
Media_SetState(cin, CINSTATE_FLUSHED);
|
|
|
|
ret = FMV_EOF;
|
|
|
|
break;
|
|
|
|
case CINSTATE_FLUSHED:
|
|
|
|
//FIXME: roq decoder has no reset method!
|
|
|
|
Media_Send_Reset(cin);
|
|
|
|
ret = FMV_LOOPED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
int UI_Cin_Draw(int idx)
|
|
|
|
{
|
|
|
|
if (idx >= 0 && idx < countof(uicinematics))
|
|
|
|
{
|
|
|
|
shader_t *shader = VM_FROMSHANDLE(uicinematics[idx].shaderhandle);
|
|
|
|
float x = uicinematics[idx].x;
|
|
|
|
float y = uicinematics[idx].y;
|
|
|
|
float w = uicinematics[idx].w;
|
|
|
|
float h = uicinematics[idx].h;
|
|
|
|
|
|
|
|
//gah! q3 compat sucks!
|
|
|
|
x *= vid.pixelwidth/640.0;
|
|
|
|
w *= vid.pixelwidth/640.0;
|
|
|
|
y *= vid.pixelheight/480.0;
|
|
|
|
h *= vid.pixelheight/480.0;
|
|
|
|
|
|
|
|
R2D_Image(x, y, w, h, 0, 0, 1, 1, shader);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int UI_Cin_SetExtents(int idx, int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
if (idx >= 0 && idx < countof(uicinematics))
|
|
|
|
{
|
|
|
|
uicinematics[idx].x = x;
|
|
|
|
uicinematics[idx].y = y;
|
|
|
|
uicinematics[idx].w = w;
|
|
|
|
uicinematics[idx].h = h;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-12 05:04:27 +00:00
|
|
|
static cvar_t *Cvar_Q3FindVar (const char *var_name)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
const char *q3;
|
|
|
|
const char *fte;
|
|
|
|
} cvarremaps[] =
|
|
|
|
{
|
|
|
|
{"s_musicvolume", "bgmvolume"},
|
|
|
|
{"r_gamma", "gamma"},
|
|
|
|
{"s_sdlSpeed", "s_khz"},
|
|
|
|
{"r_fullscreen", "vid_fullscreen"},
|
|
|
|
{"r_picmip", "gl_picmip"},
|
|
|
|
{"r_textureMode", "gl_texturemode"},
|
|
|
|
{"r_lodBias", "d_lodbias"},
|
|
|
|
{"r_colorbits", "vid_bpp"},
|
|
|
|
{"r_dynamiclight", "r_dynamic"},
|
|
|
|
{"r_finish", "gl_finish"},
|
|
|
|
// {"r_glDriver", NULL},
|
|
|
|
// {"r_depthbits", NULL},
|
|
|
|
// {"r_stencilbits", NULL},
|
|
|
|
// {"s_compression", NULL},
|
|
|
|
// {"r_texturebits", NULL},
|
|
|
|
// {"r_allowExtensions",NULL},
|
|
|
|
// {"s_useOpenAL", NULL},
|
|
|
|
// {"sv_running", NULL},
|
|
|
|
// {"sv_killserver", NULL},
|
|
|
|
// {"color1", NULL},
|
|
|
|
// {"in_joystick", NULL},
|
|
|
|
// {"joy_threshold", NULL},
|
|
|
|
// {"cl_freelook", NULL},
|
|
|
|
// {"color1", NULL},
|
|
|
|
// {"r_availableModes",NULL},
|
|
|
|
// {"r_mode", NULL},
|
|
|
|
};
|
|
|
|
cvar_t *v;
|
|
|
|
size_t i;
|
|
|
|
v = Cvar_FindVar(var_name);
|
|
|
|
if (v)
|
|
|
|
return v;
|
|
|
|
for (i = 0; i < countof(cvarremaps); i++)
|
|
|
|
{
|
|
|
|
if (!strcmp(cvarremaps[i].q3, var_name))
|
|
|
|
return Cvar_FindVar(cvarremaps[i].fte);
|
|
|
|
}
|
|
|
|
// Con_Printf("Q3 Cvar %s is not known\n", var_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
|
2020-07-14 00:48:56 +00:00
|
|
|
static void UI_SimulateTextEntry(void *cb, const char *utf8)
|
2020-03-07 09:00:40 +00:00
|
|
|
{
|
|
|
|
const char *line = utf8;
|
|
|
|
unsigned int unicode;
|
|
|
|
int err;
|
|
|
|
while(*line)
|
|
|
|
{
|
|
|
|
unicode = utf8_decode(&err, line, &line);
|
|
|
|
if (uivm)
|
|
|
|
VM_Call(uivm, UI_KEY_EVENT, unicode|1024, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-05 20:04:11 +00:00
|
|
|
#define VALIDATEPOINTER(o,l) if ((quintptr_t)o + l >= mask || VM_POINTER(o) < offset) Host_EndGame("Call to ui trap %i passes invalid pointer\n", (int)fn); //out of bounds.
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
static int overstrikemode;
|
2004-08-23 00:15:46 +00:00
|
|
|
int ret=0;
|
2008-06-08 14:37:57 +00:00
|
|
|
char adrbuf[MAX_ADR_SIZE];
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
//Remember to range check pointers.
|
|
|
|
//The QVM must not be allowed to write to anything outside it's memory.
|
|
|
|
//This includes getting the exe to copy it for it.
|
|
|
|
|
|
|
|
//don't bother with reading, as this isn't a virus risk.
|
|
|
|
//could be a cheat risk, but hey.
|
|
|
|
|
|
|
|
//make sure that any called functions are also range checked.
|
|
|
|
//like reading from files copies names into alternate buffers, allowing stack screwups.
|
|
|
|
|
2005-09-08 22:52:46 +00:00
|
|
|
switch((uiImport_t)fn)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
case UI_CVAR_CREATE:
|
|
|
|
case UI_CVAR_INFOSTRINGBUFFER:
|
|
|
|
case UI_R_ADDPOLYTOSCENE:
|
|
|
|
case UI_R_REMAP_SHADER:
|
|
|
|
case UI_UPDATESCREEN:
|
|
|
|
case UI_CM_LOADMODEL:
|
|
|
|
case UI_FS_SEEK:
|
|
|
|
Con_Printf("Q3UI: Not implemented system trap: %i\n", (int)fn);
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_ERROR:
|
2009-11-04 21:16:50 +00:00
|
|
|
Con_Printf("%s", (char*)VM_POINTER(arg[0]));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
case UI_PRINT:
|
2009-11-04 21:16:50 +00:00
|
|
|
Con_Printf("%s", (char*)VM_POINTER(arg[0]));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_MILLISECONDS:
|
|
|
|
VM_LONG(ret) = Sys_Milliseconds();
|
|
|
|
break;
|
|
|
|
|
2005-09-08 22:52:46 +00:00
|
|
|
case UI_ARGC:
|
|
|
|
VM_LONG(ret) = Cmd_Argc();
|
|
|
|
break;
|
|
|
|
case UI_ARGV:
|
|
|
|
// VALIDATEPOINTER(arg[1], arg[2]);
|
|
|
|
Q_strncpyz(VM_POINTER(arg[1]), Cmd_Argv(VM_LONG(arg[0])), VM_LONG(arg[2]));
|
|
|
|
break;
|
|
|
|
/* case UI_ARGS:
|
|
|
|
VALIDATEPOINTER(arg[0], arg[1]);
|
|
|
|
Q_strncpyz(VM_POINTER(arg[0]), Cmd_Args(), VM_LONG(arg[1]));
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
case UI_CVAR_SET:
|
|
|
|
{
|
|
|
|
cvar_t *var;
|
2011-01-29 21:01:40 +00:00
|
|
|
char *vname = VM_POINTER(arg[0]);
|
|
|
|
char *vval = VM_POINTER(arg[1]);
|
|
|
|
if (!strcmp(vname, "fs_game"))
|
2006-02-27 00:42:25 +00:00
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
char quoted[256];
|
|
|
|
Cbuf_AddText(va("gamedir %s\nui_restart\n", COM_QuotedString(vval, quoted, sizeof(quoted), false)), RESTRICT_SERVER);
|
2006-02-27 00:42:25 +00:00
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
else
|
2006-02-27 00:42:25 +00:00
|
|
|
{
|
2019-03-12 05:04:27 +00:00
|
|
|
var = Cvar_Q3FindVar(vname);
|
2006-02-27 00:42:25 +00:00
|
|
|
if (var)
|
2011-01-29 21:01:40 +00:00
|
|
|
Cvar_Set(var, vval); //set it
|
2006-02-27 00:42:25 +00:00
|
|
|
else
|
2011-01-29 21:01:40 +00:00
|
|
|
Cvar_Get(vname, vval, 0, "UI created"); //create one
|
2006-02-27 00:42:25 +00:00
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_CVAR_VARIABLEVALUE:
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
cvar_t *var;
|
2011-01-29 21:01:40 +00:00
|
|
|
char *vname = VM_POINTER(arg[0]);
|
2019-03-12 05:04:27 +00:00
|
|
|
var = Cvar_Q3FindVar(vname);
|
2004-08-23 00:15:46 +00:00
|
|
|
if (var)
|
|
|
|
VM_FLOAT(ret) = var->value;
|
|
|
|
else
|
|
|
|
VM_FLOAT(ret) = 0;
|
|
|
|
}
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_CVAR_VARIABLESTRINGBUFFER:
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
cvar_t *var;
|
2011-01-29 21:01:40 +00:00
|
|
|
char *vname = VM_POINTER(arg[0]);
|
2019-03-12 05:04:27 +00:00
|
|
|
var = Cvar_Q3FindVar(vname);
|
2004-08-23 00:15:46 +00:00
|
|
|
if (!VM_LONG(arg[2]))
|
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
else if (!var)
|
|
|
|
{
|
|
|
|
*(char *)VM_POINTER(arg[1]) = '\0';
|
|
|
|
VM_LONG(ret) = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (arg[1] + arg[2] >= mask || VM_POINTER(arg[1]) < offset)
|
|
|
|
VM_LONG(ret) = -2; //out of bounds.
|
|
|
|
else
|
|
|
|
Q_strncpyz(VM_POINTER(arg[1]), var->string, VM_LONG(arg[2]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_CVAR_SETVALUE:
|
2019-03-12 05:04:27 +00:00
|
|
|
Cvar_SetValue(Cvar_Q3FindVar(VM_POINTER(arg[0])), VM_FLOAT(arg[1]));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UI_CVAR_RESET: //cvar reset
|
2004-12-21 04:29:14 +00:00
|
|
|
{
|
|
|
|
cvar_t *var;
|
2011-01-29 21:01:40 +00:00
|
|
|
char *vname = VM_POINTER(arg[0]);
|
2019-03-12 05:04:27 +00:00
|
|
|
var = Cvar_Q3FindVar(vname);
|
2004-12-21 04:29:14 +00:00
|
|
|
if (var)
|
|
|
|
Cvar_Set(var, var->defaultstr);
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_CMD_EXECUTETEXT:
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2011-01-29 21:01:40 +00:00
|
|
|
char *cmdtext = VM_POINTER(arg[1]);
|
2012-04-09 19:12:12 +00:00
|
|
|
#ifdef CL_MASTER
|
2011-01-29 21:01:40 +00:00
|
|
|
if (!strncmp(cmdtext, "ping ", 5))
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_PINGREQUESTS; i++)
|
2019-02-01 08:29:14 +00:00
|
|
|
if (ui_pings[i].adr.type == NA_INVALID)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2011-01-29 21:01:40 +00:00
|
|
|
serverinfo_t *info;
|
2020-02-11 18:06:10 +00:00
|
|
|
const char *p = NULL;
|
2014-12-23 15:26:42 +00:00
|
|
|
COM_Parse(cmdtext + 5);
|
2019-02-01 08:29:14 +00:00
|
|
|
ui_pings[i].startms = Sys_Milliseconds();
|
2020-02-11 18:06:10 +00:00
|
|
|
if (NET_StringToAdr2(com_token, 0, &ui_pings[i].adr, 1, &p))
|
2011-01-29 21:01:40 +00:00
|
|
|
{
|
2020-02-11 18:06:10 +00:00
|
|
|
if (p && *p=='/')
|
|
|
|
p++;
|
|
|
|
info = Master_InfoForServer(&ui_pings[i].adr, p);
|
2016-02-15 06:01:17 +00:00
|
|
|
if (info)
|
|
|
|
{
|
|
|
|
info->special |= SS_KEEPINFO;
|
|
|
|
info->sends++;
|
|
|
|
Master_QueryServer(info);
|
|
|
|
}
|
2011-01-29 21:01:40 +00:00
|
|
|
}
|
2020-02-11 18:06:10 +00:00
|
|
|
Q_strncpyz(ui_pings[i].brokername, p?p:"", sizeof(ui_pings[i].brokername));
|
2011-01-29 21:01:40 +00:00
|
|
|
break;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
2011-01-29 21:01:40 +00:00
|
|
|
}
|
2012-04-09 19:12:12 +00:00
|
|
|
else
|
|
|
|
#endif
|
2011-01-29 21:01:40 +00:00
|
|
|
Cbuf_AddText(cmdtext, RESTRICT_SERVER);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_FS_FOPENFILE: //fopen
|
2004-08-23 00:15:46 +00:00
|
|
|
if ((int)arg[1] + 4 >= mask || VM_POINTER(arg[1]) < offset)
|
|
|
|
break; //out of bounds.
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_LONG(ret) = VM_fopen(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), 0);
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UI_FS_READ: //fread
|
|
|
|
if ((int)arg[0] + VM_LONG(arg[1]) >= mask || VM_POINTER(arg[0]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_LONG(ret) = VM_FRead(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), 0);
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
case UI_FS_WRITE: //fwrite
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_FS_FCLOSEFILE: //fclose
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_fclose(VM_LONG(arg[0]), 0);
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_FS_GETFILELIST: //fs listing
|
2004-08-23 00:15:46 +00:00
|
|
|
if ((int)arg[2] + arg[3] >= mask || VM_POINTER(arg[2]) < offset)
|
|
|
|
break; //out of bounds.
|
2007-09-02 19:55:17 +00:00
|
|
|
return VM_GetFileList(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3]));
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_REGISTERMODEL: //precache model
|
|
|
|
{
|
|
|
|
char *name = VM_POINTER(arg[0]);
|
2014-03-30 08:55:06 +00:00
|
|
|
model_t *mod;
|
|
|
|
mod = Mod_ForName(name, MLV_SILENT);
|
2014-10-05 20:04:11 +00:00
|
|
|
if (mod && mod->loadstate == MLS_LOADING)
|
|
|
|
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
|
|
|
|
if (!mod || mod->loadstate != MLS_LOADED || mod->type == mod_dummy)
|
2014-03-30 08:55:06 +00:00
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
else
|
|
|
|
VM_LONG(ret) = VM_TOMHANDLE(mod);
|
2006-03-12 05:21:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case UI_R_MODELBOUNDS:
|
|
|
|
{
|
|
|
|
VALIDATEPOINTER(arg[1], sizeof(vec3_t));
|
|
|
|
VALIDATEPOINTER(arg[2], sizeof(vec3_t));
|
|
|
|
{
|
2007-09-17 20:35:39 +00:00
|
|
|
model_t *mod = VM_FROMMHANDLE(arg[0]);
|
2006-03-12 05:21:15 +00:00
|
|
|
if (mod)
|
|
|
|
{
|
|
|
|
VectorCopy(mod->mins, ((float*)VM_POINTER(arg[1])));
|
|
|
|
VectorCopy(mod->maxs, ((float*)VM_POINTER(arg[2])));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VectorClear(((float*)VM_POINTER(arg[1])));
|
|
|
|
VectorClear(((float*)VM_POINTER(arg[2])));
|
|
|
|
}
|
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_REGISTERSKIN:
|
2014-03-30 08:55:06 +00:00
|
|
|
VM_LONG(ret) = Mod_RegisterSkinFile(VM_POINTER(arg[0]));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_REGISTERFONT: //register font
|
|
|
|
UI_RegisterFont(VM_POINTER(arg[0]), arg[1], VM_POINTER(arg[2]));
|
|
|
|
break;
|
|
|
|
case UI_R_REGISTERSHADERNOMIP:
|
2007-05-25 22:16:29 +00:00
|
|
|
if (!*(char*)VM_POINTER(arg[0]))
|
2004-08-23 00:15:46 +00:00
|
|
|
VM_LONG(ret) = 0;
|
2010-05-01 22:47:47 +00:00
|
|
|
else
|
2020-03-07 09:00:40 +00:00
|
|
|
{
|
|
|
|
shader_t *shader = R_RegisterPic(VM_POINTER(arg[0]), NULL);
|
|
|
|
VM_LONG(ret) = VM_TOSHANDLE(shader);
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_CLEARSCENE: //clear scene
|
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
|
|
|
CL_ClearEntityLists();
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_ADDREFENTITYTOSCENE: //add ent to scene
|
2004-08-23 00:15:46 +00:00
|
|
|
VQ3_AddEntity(VM_POINTER(arg[0]));
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_ADDLIGHTTOSCENE: //add light to scene.
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_RENDERSCENE: //render scene
|
2004-08-23 00:15:46 +00:00
|
|
|
VQ3_RenderView(VM_POINTER(arg[0]));
|
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_SETCOLOR: //setcolour float*
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2004-12-21 04:29:14 +00:00
|
|
|
float *fl =VM_POINTER(arg[0]);
|
|
|
|
if (!fl)
|
2011-03-31 01:14:01 +00:00
|
|
|
R2D_ImageColours(1, 1, 1, 1);
|
2004-08-23 00:15:46 +00:00
|
|
|
else
|
2011-03-31 01:14:01 +00:00
|
|
|
R2D_ImageColours(fl[0], fl[1], fl[2], fl[3]);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_R_DRAWSTRETCHPIC:
|
2011-03-31 01:14:01 +00:00
|
|
|
R2D_Image(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), VM_FLOAT(arg[4]), VM_FLOAT(arg[5]), VM_FLOAT(arg[6]), VM_FLOAT(arg[7]), VM_FROMSHANDLE(VM_LONG(arg[8])));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_CM_LERPTAG: //Lerp tag...
|
2004-12-21 04:29:14 +00:00
|
|
|
// tag, model, startFrame, endFrame, frac, tagName
|
2004-08-23 00:15:46 +00:00
|
|
|
if ((int)arg[0] + sizeof(float)*12 >= mask || VM_POINTER(arg[0]) < offset)
|
|
|
|
break; //out of bounds.
|
2007-09-17 20:35:39 +00:00
|
|
|
VM_LerpTag(VM_POINTER(arg[0]), VM_FROMMHANDLE(arg[1]), VM_LONG(arg[2]), VM_LONG(arg[3]), VM_FLOAT(arg[4]), VM_POINTER(arg[5]));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_S_REGISTERSOUND:
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
sfx_t *sfx;
|
2014-10-05 20:04:11 +00:00
|
|
|
sfx = S_PrecacheSound(va("%s", (char*)VM_POINTER(arg[0])));
|
2004-08-23 00:15:46 +00:00
|
|
|
if (sfx)
|
2007-09-17 20:35:39 +00:00
|
|
|
VM_LONG(ret) = VM_TOSTRCACHE(arg[0]); //return handle is the parameter they just gave
|
2004-08-23 00:15:46 +00:00
|
|
|
else
|
|
|
|
VM_LONG(ret) = -1;
|
|
|
|
}
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_S_STARTLOCALSOUND:
|
|
|
|
if (VM_LONG(arg[0]) != -1 && arg[0])
|
2007-09-17 20:35:39 +00:00
|
|
|
S_LocalSound(VM_FROMSTRCACHE(arg[0])); //now we can fix up the sound name
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
case UI_S_STARTBACKGROUNDTRACK:
|
|
|
|
Media_NamedTrack(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
|
|
|
|
break;
|
|
|
|
case UI_S_STOPBACKGROUNDTRACK:
|
|
|
|
Media_NamedTrack(NULL, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
//q3 shares insert mode between its ui and console. whereas fte doesn't support it (FIXME: add to Key_EntryInsert).
|
|
|
|
case UI_KEY_SETOVERSTRIKEMODE:
|
|
|
|
overstrikemode = arg[0];
|
|
|
|
return 0;
|
2005-09-08 22:52:46 +00:00
|
|
|
case UI_KEY_GETOVERSTRIKEMODE:
|
2020-03-07 09:00:40 +00:00
|
|
|
return overstrikemode;
|
|
|
|
|
|
|
|
case UI_GETCLIPBOARDDATA:
|
|
|
|
if (VM_OOB(arg[0], VM_LONG(arg[1])))
|
|
|
|
break; //out of bounds.
|
|
|
|
//our clipboard doesn't allow us to simply query without blocking (would result in stalls on x11/wayland)
|
|
|
|
//so just return nothing - we can send the text as if it were regular text entry for a similar result.
|
|
|
|
Q_strncpyz(VM_POINTER(arg[0]), "", VM_LONG(arg[1]));
|
|
|
|
|
|
|
|
//but do we really want to let mods read the system clipboard? I suppose it SHOULD be okay if the UI was manually installed by the user.
|
|
|
|
//side note: q3's text entry logic is kinda flawed.
|
|
|
|
Sys_Clipboard_PasteText(CBT_CLIPBOARD, UI_SimulateTextEntry, NULL);
|
|
|
|
break;
|
2005-09-08 22:52:46 +00:00
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_KEY_KEYNUMTOSTRINGBUF:
|
2004-08-23 00:15:46 +00:00
|
|
|
if (VM_LONG(arg[0]) < 0 || VM_LONG(arg[0]) > 255 || (int)arg[1] + VM_LONG(arg[2]) >= mask || VM_POINTER(arg[1]) < offset || VM_LONG(arg[2]) < 1)
|
|
|
|
break; //out of bounds.
|
|
|
|
|
Reworked client support for DPP5+. less code now, its much more graceful.
added waterfog command. waterfog overrides regular fog only when the view is in water.
fixed 64bit printf format specifiers. should work better on winxp64.
fixed some spec angle weirdness.
fixed viewsize 99.99 weirdness with ezhud.
fixed extra offset on the console (exhibited in 64bit builds, but not limited to).
fixed .avi playback, can now actually display frames again.
reimplemented line sparks.
fixed r_editlights_save flipping the light's pitch.
fixed issue with oggs failing to load.
fixed condump to cope with unicode properly.
made sv_bigcoords default except in quake. hexen2 kinda needs it for bsp angle precision.
fixed nq server to not stall weirdly on map changes.
fixed qwprogs svc_cdtrack not bugging out with nq clients on the server.
fixed restart command to load the last map run by the server, instead of start.bsp (when idle)
optimised d3d9 renderer a little. now uses less draw calls, especially with complex scenes. seems to get higher framerates than opengl now.
fixed d3d9 renderer to not bug out quite so much when run fullscreen (shader subsystem is now correctly initialised).
fixed a couple of bugs from font change. also now supports utf-8 in a few more places.
r_editlights_reload no longer generates rtlights inside the void. this resolves a few glitches (but should also help framerates a little).
fixed so corona-only lights won't generate shadowmaps and waste lots of time.
removed lots of #defines from qclib. I should never have made them in the first place, but I was lazy. obviously there's more left that I cba to remove yet.
fixed nested calls with variant-vectors. this fixes csaddon's light editor.
fixed qcc hc calling conventions using redundant stores.
disabled keywords can still be used by using __keyword instead.
fixed ftegccgui grep feature.
fixed motionless-dog qcc bug.
tweaked qcc warnings a little. -Wall is now a viable setting. you should be able to fix all those warnings.
fixed qw svc_intermission + dpp5+ clients bug.
fixed annoying spam about disconnecting in hexen2.
rewrote status command a little to cope with ipv6 addresses more gracefully
fixed significant stall when hibernating/debugging a server with a player sitting on it.
fixed truelightning.
fixed rocketlight overriding pflags.
fixed torches vanishing on vid_restart.
fixed issue with decal scaling.
fixed findentityfield builtin.
fixed fteqcc issue with ptr+1
fixed use of arrays inside class functions.
fixed/implemented fteqcc emulation of pointer opcodes.
added __inout keyword to fteqcc, so that it doesn't feel so horrendous.
fixed sizeof(*foo)
fixed *struct = struct;
fixed recursive structs.
fixed fteqcc warning report.
fixed sdl2 controller support, hopefully.
attempted to implement xinput, including per-player audio playback.
slightly fixed relaxed attitude to mouse focus when running fullscreen.
fixed weird warnings/errors with 'ent.arrayhead' terms. now generates sane errors.
implemented bindmaps (for csqc).
fixed crashing bug with eprint builtin.
implemented subset of music_playlist_* functionality. significant changes to music playback.
fixed some more dpcsqc compat.
fixed binds menu. now displays and accepts modifiers.
fixed issues with huge lightmaps.
fixed protocol determinism with dp clients connecting to fte servers. the initial getchallenge request now inhibits vanilla nq connection requests.
implemented support for 'dupe' userinfo key, allowing clients to request client->server packet duplication. should probably queue them tbh.
implemented sv_saveentfile command.
fixed resume after breaking inside a stepped-over function.
fixed erroneous footer after debugging.
(I wonder just how many things I broke with these fixes)
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4946 fc73d0e0-1445-4013-8a0c-d673dee63da5
2015-07-26 10:56:18 +00:00
|
|
|
Q_strncpyz(VM_POINTER(arg[1]), Key_KeynumToString(VM_LONG(arg[0]), 0), VM_LONG(arg[2]));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_KEY_GETBINDINGBUF:
|
2004-08-23 00:15:46 +00:00
|
|
|
if (VM_LONG(arg[0]) < 0 || VM_LONG(arg[0]) > 255 || (int)arg[1] + VM_LONG(arg[2]) >= mask || VM_POINTER(arg[1]) < offset || VM_LONG(arg[2]) < 1)
|
|
|
|
break; //out of bounds.
|
|
|
|
|
|
|
|
if (keybindings[VM_LONG(arg[0])][0])
|
|
|
|
Q_strncpyz(VM_POINTER(arg[1]), keybindings[VM_LONG(arg[0])][0], VM_LONG(arg[2]));
|
|
|
|
else
|
|
|
|
*(char *)VM_POINTER(arg[1]) = '\0';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UI_KEY_SETBINDING:
|
|
|
|
Key_SetBinding(VM_LONG(arg[0]), ~0, VM_POINTER(arg[1]), RESTRICT_LOCAL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UI_KEY_ISDOWN:
|
|
|
|
{
|
2017-06-21 01:24:25 +00:00
|
|
|
extern qboolean keydown[K_MAX];
|
|
|
|
unsigned int k = VM_LONG(arg[0]);
|
|
|
|
if (k < K_MAX && keydown[k])
|
2004-08-23 00:15:46 +00:00
|
|
|
VM_LONG(ret) = 1;
|
|
|
|
else
|
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_KEY_CLEARSTATES:
|
2004-08-23 00:15:46 +00:00
|
|
|
Key_ClearStates();
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_KEY_GETCATCHER:
|
2013-10-08 14:28:11 +00:00
|
|
|
if (Key_Dest_Has(kdm_console))
|
2005-08-26 22:56:51 +00:00
|
|
|
VM_LONG(ret) = keycatcher | 1;
|
|
|
|
else
|
|
|
|
VM_LONG(ret) = keycatcher;
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_KEY_SETCATCHER:
|
2019-09-04 07:59:40 +00:00
|
|
|
Q3_SetKeyCatcher(VM_LONG(arg[0]));
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_GETGLCONFIG: //get glconfig
|
2011-01-29 21:01:40 +00:00
|
|
|
{
|
|
|
|
char *cfg;
|
|
|
|
if ((int)arg[0] + 11332/*sizeof(glconfig_t)*/ >= mask || VM_POINTER(arg[0]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
cfg = VM_POINTER(arg[0]);
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
//do any needed work
|
2011-01-29 21:01:40 +00:00
|
|
|
memset(cfg, 0, 11304);
|
|
|
|
*(int *)(cfg+11304) = vid.width;
|
|
|
|
*(int *)(cfg+11308) = vid.height;
|
|
|
|
*(float *)(cfg+11312) = (float)vid.width/vid.height;
|
|
|
|
memset(cfg+11316, 0, 11332-11316);
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_GETCLIENTSTATE: //get client state
|
2004-12-21 04:29:14 +00:00
|
|
|
//fixme: we need to fill in a structure.
|
2014-10-05 20:04:11 +00:00
|
|
|
// Con_Printf("ui_getclientstate\n");
|
|
|
|
VALIDATEPOINTER(arg[0], sizeof(uiClientState_t));
|
|
|
|
{
|
2018-12-06 04:55:35 +00:00
|
|
|
extern cvar_t cl_disconnectreason;
|
2014-10-05 20:04:11 +00:00
|
|
|
uiClientState_t *state = VM_POINTER(arg[0]);
|
|
|
|
state->connectPacketCount = 0;//clc.connectPacketCount;
|
|
|
|
|
|
|
|
switch(cls.state)
|
|
|
|
{
|
|
|
|
case ca_disconnected:
|
|
|
|
if (CL_TryingToConnect())
|
|
|
|
state->connState = Q3CA_CONNECTING;
|
|
|
|
else
|
|
|
|
state->connState = Q3CA_DISCONNECTED;
|
|
|
|
break;
|
|
|
|
case ca_demostart:
|
|
|
|
state->connState = Q3CA_CONNECTING;
|
|
|
|
break;
|
|
|
|
case ca_connected:
|
|
|
|
state->connState = Q3CA_CONNECTED;
|
|
|
|
break;
|
|
|
|
case ca_onserver:
|
|
|
|
state->connState = Q3CA_PRIMED;
|
|
|
|
break;
|
|
|
|
case ca_active:
|
|
|
|
state->connState = Q3CA_ACTIVE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Q_strncpyz( state->servername, cls.servername, sizeof( state->servername ) );
|
|
|
|
Q_strncpyz( state->updateInfoString, "FTE!", sizeof( state->updateInfoString ) ); //warning/motd message from update server
|
2018-12-06 04:55:35 +00:00
|
|
|
Q_strncpyz( state->messageString, cl_disconnectreason.string, sizeof( state->messageString ) ); //error message from game server
|
2014-10-05 20:04:11 +00:00
|
|
|
state->clientNum = cl.playerview[0].playernum;
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_GETCONFIGSTRING:
|
2004-08-23 00:15:46 +00:00
|
|
|
if (arg[1] + VM_LONG(arg[2]) >= mask || VM_POINTER(arg[1]) < offset || VM_LONG(arg[2]) < 1)
|
|
|
|
{
|
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
break; //out of bounds.
|
|
|
|
}
|
2005-08-26 23:55:09 +00:00
|
|
|
#ifdef VM_CG
|
2005-08-26 22:56:51 +00:00
|
|
|
Q_strncpyz(VM_POINTER(arg[1]), CG_GetConfigString(VM_LONG(arg[0])), VM_LONG(arg[2]));
|
2005-08-26 23:55:09 +00:00
|
|
|
#endif
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
2012-04-09 19:12:12 +00:00
|
|
|
#ifdef CL_MASTER
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_GETPINGQUEUECOUNT: //these four are master server polling.
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_PINGREQUESTS; i++)
|
2019-02-01 08:29:14 +00:00
|
|
|
if (ui_pings[i].adr.type != NA_INVALID)
|
2004-08-23 00:15:46 +00:00
|
|
|
VM_LONG(ret)++;
|
|
|
|
}
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_CLEARPING: //clear ping
|
2004-08-23 00:15:46 +00:00
|
|
|
//void (int pingnum)
|
2014-12-23 15:26:42 +00:00
|
|
|
if (VM_LONG(arg[0])>= 0 && VM_LONG(arg[0]) < MAX_PINGREQUESTS)
|
2019-02-01 08:29:14 +00:00
|
|
|
ui_pings[VM_LONG(arg[0])].adr.type = NA_INVALID;
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_GETPING:
|
2004-08-23 00:15:46 +00:00
|
|
|
//void (int pingnum, char *buffer, int buflen, int *ping)
|
|
|
|
if ((int)arg[1] + VM_LONG(arg[2]) >= mask || VM_POINTER(arg[1]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
if ((int)arg[3] + sizeof(int) >= mask || VM_POINTER(arg[3]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
|
2012-04-09 19:12:12 +00:00
|
|
|
Master_CheckPollSockets();
|
2014-12-23 15:26:42 +00:00
|
|
|
if (VM_LONG(arg[0])>= 0 && VM_LONG(arg[0]) < MAX_PINGREQUESTS)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2019-02-01 08:29:14 +00:00
|
|
|
int i = VM_LONG(arg[0]);
|
2004-08-23 00:15:46 +00:00
|
|
|
char *buf = VM_POINTER(arg[1]);
|
2019-02-01 08:29:14 +00:00
|
|
|
size_t bufsize = VM_LONG(arg[2]);
|
|
|
|
int *ping = VM_POINTER(arg[3]);
|
2020-02-11 18:06:10 +00:00
|
|
|
serverinfo_t *info = Master_InfoForServer(&ui_pings[i].adr, ui_pings[i].brokername);
|
|
|
|
if (info)
|
|
|
|
Master_ServerToString(buf, bufsize, info);
|
|
|
|
else
|
|
|
|
NET_AdrToString(buf, bufsize, &ui_pings[i].adr);
|
2019-02-01 08:29:14 +00:00
|
|
|
|
2020-02-11 18:06:10 +00:00
|
|
|
if (info && /*(info->status & SRVSTATUS_ALIVE) &&*/ info->moreinfo)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2019-02-01 08:29:14 +00:00
|
|
|
VM_LONG(ret) = true;
|
2020-02-11 18:06:10 +00:00
|
|
|
*ping = (info->ping == PING_UNKNOWN)?1:info->ping;
|
2019-02-01 08:29:14 +00:00
|
|
|
break;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
2019-02-01 08:29:14 +00:00
|
|
|
i = Sys_Milliseconds()-ui_pings[i].startms;
|
|
|
|
if (i < 999)
|
|
|
|
i = 0; //don't time out yet.
|
|
|
|
*ping = i;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_GETPINGINFO:
|
2019-02-01 08:29:14 +00:00
|
|
|
//void (int pingnum, char *buffer, int buflen)
|
2004-08-23 00:15:46 +00:00
|
|
|
if ((int)arg[1] + VM_LONG(arg[2]) >= mask || VM_POINTER(arg[1]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
if ((int)arg[3] + sizeof(int) >= mask || VM_POINTER(arg[3]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
|
2012-04-09 19:12:12 +00:00
|
|
|
Master_CheckPollSockets();
|
2014-12-23 15:26:42 +00:00
|
|
|
if (VM_LONG(arg[0])>= 0 && VM_LONG(arg[0]) < MAX_PINGREQUESTS)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2019-02-01 08:29:14 +00:00
|
|
|
int i = VM_LONG(arg[0]);
|
2004-08-23 00:15:46 +00:00
|
|
|
char *buf = VM_POINTER(arg[1]);
|
2019-02-01 08:29:14 +00:00
|
|
|
size_t bufsize = VM_LONG(arg[2]);
|
2004-08-23 00:15:46 +00:00
|
|
|
char *adr;
|
2020-02-11 18:06:10 +00:00
|
|
|
serverinfo_t *info = Master_InfoForServer(&ui_pings[i].adr, ui_pings[i].brokername);
|
|
|
|
if (info && /*(info->status & SRVSTATUS_ALIVE) &&*/ info->moreinfo)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
adr = info->moreinfo->info;
|
|
|
|
if (!adr)
|
|
|
|
adr = "";
|
2019-02-01 08:29:14 +00:00
|
|
|
if (strlen(adr) < bufsize)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
strcpy(buf, adr);
|
2019-02-01 08:29:14 +00:00
|
|
|
Info_SetValueForKey(buf, "mapname", info->map, bufsize);
|
|
|
|
Info_SetValueForKey(buf, "hostname", info->name, bufsize);
|
|
|
|
Info_SetValueForKey(buf, "g_humanplayers", va("%i", info->numhumans), bufsize);
|
|
|
|
Info_SetValueForKey(buf, "sv_maxclients", va("%i", info->maxplayers), bufsize);
|
|
|
|
Info_SetValueForKey(buf, "clients", va("%i", info->players), bufsize);
|
|
|
|
if (info->adr.type == NA_IPV6 && info->adr.prot == NP_DGRAM)
|
|
|
|
Info_SetValueForKey(buf, "nettype", "2", bufsize);
|
|
|
|
else if (info->adr.type == NA_IP && info->adr.prot == NP_DGRAM)
|
|
|
|
Info_SetValueForKey(buf, "nettype", "1", bufsize);
|
|
|
|
else
|
|
|
|
Info_SetValueForKey(buf, "nettype", "", bufsize);
|
2004-08-23 00:15:46 +00:00
|
|
|
VM_LONG(ret) = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy(buf, "");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
case UI_LAN_UPDATEVISIBLEPINGS:
|
|
|
|
return CL_QueryServers(); //return true while we're still going.
|
|
|
|
case UI_LAN_RESETPINGS:
|
|
|
|
return 0;
|
|
|
|
case UI_LAN_ADDSERVER:
|
|
|
|
return 0;
|
|
|
|
case UI_LAN_REMOVESERVER:
|
|
|
|
return 0;
|
|
|
|
case UI_LAN_SERVERSTATUS:
|
|
|
|
//*address, *status, statuslen
|
|
|
|
return 0;
|
|
|
|
case UI_LAN_COMPARESERVERS:
|
2005-08-26 22:56:51 +00:00
|
|
|
{
|
2020-03-07 09:00:40 +00:00
|
|
|
hostcachekey_t q3tofte[] = {SLKEY_NAME, SLKEY_MAP, SLKEY_NUMHUMANS, SLKEY_GAMEDIR, SLKEY_PING, 0};
|
|
|
|
qboolean keyisstring[] = {true, true, false, true, false, false};
|
|
|
|
//int source = VM_LONG(arg[0]);
|
|
|
|
int key = bound(0, VM_LONG(arg[1]), countof(q3tofte));
|
|
|
|
int sortdir = VM_LONG(arg[2]);
|
|
|
|
serverinfo_t *s1 = Master_InfoForNum(VM_LONG(arg[3]));
|
|
|
|
serverinfo_t *s2 = Master_InfoForNum(VM_LONG(arg[4]));
|
|
|
|
if (keyisstring[key])
|
|
|
|
ret = strcasecmp(Master_ReadKeyString(s2, q3tofte[key]), Master_ReadKeyString(s1, q3tofte[key]));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = Master_ReadKeyFloat(s2, q3tofte[key]) - Master_ReadKeyFloat(s1, q3tofte[key]);
|
|
|
|
if (ret < 0)
|
|
|
|
ret = -1;
|
|
|
|
else if (ret > 0)
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
if (sortdir)
|
|
|
|
ret = -ret;
|
2005-08-26 22:56:51 +00:00
|
|
|
}
|
2020-03-07 09:00:40 +00:00
|
|
|
return ret;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_GETSERVERCOUNT: //LAN Get server count
|
2004-08-23 00:15:46 +00:00
|
|
|
//int (int source)
|
2020-03-07 09:00:40 +00:00
|
|
|
Master_CheckPollSockets();
|
2004-08-23 00:15:46 +00:00
|
|
|
VM_LONG(ret) = Master_TotalCount();
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_GETSERVERADDRESSSTRING: //LAN get server address
|
2004-08-23 00:15:46 +00:00
|
|
|
//void (int source, int svnum, char *buffer, int buflen)
|
|
|
|
if ((int)arg[2] + VM_LONG(arg[3]) >= mask || VM_POINTER(arg[2]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
{
|
|
|
|
char *buf = VM_POINTER(arg[2]);
|
|
|
|
char *adr;
|
|
|
|
serverinfo_t *info = Master_InfoForNum(VM_LONG(arg[1]));
|
|
|
|
if (info)
|
|
|
|
{
|
2020-02-11 18:06:10 +00:00
|
|
|
adr = Master_ServerToString(adrbuf, sizeof(adrbuf), info);
|
2004-08-23 00:15:46 +00:00
|
|
|
if (strlen(adr) < VM_LONG(arg[3]))
|
|
|
|
{
|
|
|
|
strcpy(buf, adr);
|
|
|
|
VM_LONG(ret) = true;
|
2020-03-07 09:00:40 +00:00
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy(buf, "");
|
|
|
|
}
|
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_LOADCACHEDSERVERS:
|
|
|
|
break;
|
|
|
|
case UI_LAN_SAVECACHEDSERVERS:
|
|
|
|
break;
|
|
|
|
case UI_LAN_GETSERVERPING:
|
|
|
|
return 50;
|
|
|
|
case UI_LAN_GETSERVERINFO:
|
2020-03-07 09:00:40 +00:00
|
|
|
if (VM_OOB(arg[2], arg[3]) || !arg[3])
|
|
|
|
break; //out of bounds.
|
|
|
|
{
|
|
|
|
//int source = VM_LONG(arg[0]);
|
|
|
|
int servernum = VM_LONG(arg[1]);
|
|
|
|
char *out = VM_POINTER(arg[2]);
|
|
|
|
int maxsize = VM_LONG(arg[3]);
|
|
|
|
char adr[MAX_ADR_SIZE];
|
|
|
|
serverinfo_t *info = Master_InfoForNum(servernum);
|
|
|
|
*out = 0;
|
|
|
|
if (info)
|
|
|
|
{
|
|
|
|
Info_SetValueForStarKey(out, "hostname", info->name, maxsize);
|
|
|
|
Info_SetValueForStarKey(out, "mapname", info->map, maxsize);
|
|
|
|
Info_SetValueForStarKey(out, "clients", va("%i", info->players), maxsize);
|
|
|
|
Info_SetValueForStarKey(out, "sv_maxclients", va("%i", info->maxplayers), maxsize);
|
|
|
|
Info_SetValueForStarKey(out, "ping", va("%i", info->ping), maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "minping", info->map, maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "maxping", info->map, maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "game", info->map, maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "gametype", info->map, maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "nettype", info->map, maxsize);
|
|
|
|
Info_SetValueForStarKey(out, "addr", NET_AdrToString(adr, sizeof(adr), &info->adr), maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "punkbuster", info->map, maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "g_needpass", info->map, maxsize);
|
|
|
|
// Info_SetValueForStarKey(out, "g_humanplayers", info->map, maxsize);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
break;
|
2020-03-07 09:00:40 +00:00
|
|
|
case UI_LAN_MARKSERVERVISIBLE:
|
|
|
|
/*not implemented*/
|
|
|
|
return 0;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_LAN_SERVERISVISIBLE:
|
|
|
|
return 1;
|
2012-04-09 19:12:12 +00:00
|
|
|
#endif
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
case UI_CVAR_REGISTER:
|
|
|
|
if (VM_OOB(arg[0], sizeof(q3vmcvar_t)))
|
|
|
|
break; //out of bounds.
|
|
|
|
return VMQ3_Cvar_Register(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3]));
|
|
|
|
|
|
|
|
case UI_CVAR_UPDATE:
|
|
|
|
if (VM_OOB(arg[0], sizeof(q3vmcvar_t)))
|
|
|
|
break; //out of bounds.
|
|
|
|
return VMQ3_Cvar_Update(VM_POINTER(arg[0]));
|
|
|
|
|
|
|
|
case UI_MEMORY_REMAINING:
|
|
|
|
VM_LONG(ret) = 1024*1024*8;//Hunk_LowMemAvailable();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UI_GET_CDKEY: //get cd key
|
|
|
|
{
|
|
|
|
char *keydest = VM_POINTER(arg[0]);
|
|
|
|
if ((int)arg[0] + VM_LONG(arg[1]) >= mask || VM_POINTER(arg[0]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
strncpy(keydest, Cvar_VariableString("cl_cdkey"), VM_LONG(arg[1]));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case UI_SET_CDKEY: //set cd key
|
|
|
|
{
|
|
|
|
char *keysrc = VM_POINTER(arg[0]);
|
|
|
|
cvar_t *cvar;
|
|
|
|
if ((int)arg[0] + strlen(keysrc) >= mask || VM_POINTER(arg[0]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
cvar = Cvar_Get("cl_cdkey", "", 0, "Quake3 auth");
|
|
|
|
Cvar_Set(cvar, keysrc);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UI_REAL_TIME:
|
|
|
|
VALIDATEPOINTER(arg[0], sizeof(q3time_t));
|
|
|
|
return Q3VM_GetRealtime(VM_POINTER(arg[0]));
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_VERIFY_CDKEY:
|
2004-08-23 00:15:46 +00:00
|
|
|
VM_LONG(ret) = true;
|
|
|
|
break;
|
|
|
|
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_SET_PBCLSTATUS:
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// standard Q3
|
|
|
|
case UI_MEMSET:
|
2011-01-29 21:01:40 +00:00
|
|
|
{
|
|
|
|
void *dest = VM_POINTER(arg[0]);
|
|
|
|
if ((int)arg[0] + arg[2] >= mask || dest < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
memset(dest, arg[1], arg[2]);
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
2005-08-26 22:56:51 +00:00
|
|
|
case UI_MEMCPY:
|
2011-01-29 21:01:40 +00:00
|
|
|
{
|
|
|
|
void *dest = VM_POINTER(arg[0]);
|
|
|
|
void *src = VM_POINTER(arg[1]);
|
|
|
|
if ((int)arg[0] + arg[2] >= mask || VM_POINTER(arg[0]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
memcpy(dest, src, arg[2]);
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
case UI_STRNCPY:
|
2011-01-29 21:01:40 +00:00
|
|
|
{
|
|
|
|
void *dest = VM_POINTER(arg[0]);
|
|
|
|
void *src = VM_POINTER(arg[1]);
|
|
|
|
if (arg[0] + arg[2] >= mask || VM_POINTER(arg[0]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
Q_strncpyS(dest, src, arg[2]);
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
case UI_SIN:
|
|
|
|
VM_FLOAT(ret)=(float)sin(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case UI_COS:
|
|
|
|
VM_FLOAT(ret)=(float)cos(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case UI_ATAN2:
|
|
|
|
VM_FLOAT(ret)=(float)atan2(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]));
|
|
|
|
break;
|
|
|
|
case UI_SQRT:
|
|
|
|
VM_FLOAT(ret)=(float)sqrt(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case UI_FLOOR:
|
|
|
|
VM_FLOAT(ret)=(float)floor(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case UI_CEIL:
|
|
|
|
VM_FLOAT(ret)=(float)ceil(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
2007-09-17 20:35:39 +00:00
|
|
|
/*
|
2004-08-23 00:15:46 +00:00
|
|
|
case UI_GETPLAYERINFO:
|
|
|
|
if (arg[1] + sizeof(vmuiclientinfo_t) >= mask || VM_POINTER(arg[1]) < offset)
|
|
|
|
break; //out of bounds.
|
|
|
|
if (VM_LONG(arg[0]) < -1 || VM_LONG(arg[0] ) >= MAX_CLIENTS)
|
|
|
|
break;
|
|
|
|
{
|
|
|
|
int i = VM_LONG(arg[0]);
|
|
|
|
vmuiclientinfo_t *vci = VM_POINTER(arg[1]);
|
|
|
|
if (i == -1)
|
|
|
|
{
|
|
|
|
i = cl.playernum[0];
|
|
|
|
if (i < 0)
|
|
|
|
{
|
|
|
|
memset(vci, 0, sizeof(*vci));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2007-07-23 18:52:11 +00:00
|
|
|
vci->bottomcolour = cl.players[i].rbottomcolor;
|
2004-08-23 00:15:46 +00:00
|
|
|
vci->frags = cl.players[i].frags;
|
2005-02-06 13:59:37 +00:00
|
|
|
Q_strncpyz(vci->name, cl.players[i].name, UIMAX_SCOREBOARDNAME);
|
2004-08-23 00:15:46 +00:00
|
|
|
vci->ping = cl.players[i].ping;
|
|
|
|
vci->pl = cl.players[i].pl;
|
|
|
|
vci->starttime = cl.players[i].entertime;
|
2007-07-23 18:52:11 +00:00
|
|
|
vci->topcolour = cl.players[i].rtopcolor;
|
2004-08-23 00:15:46 +00:00
|
|
|
vci->userid = cl.players[i].userid;
|
|
|
|
Q_strncpyz(vci->userinfo, cl.players[i].userinfo, sizeof(vci->userinfo));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case UI_GETSTAT:
|
|
|
|
if (VM_LONG(arg[0]) < 0 || VM_LONG(arg[0]) >= MAX_CL_STATS)
|
|
|
|
VM_LONG(ret) = 0; //invalid stat num.
|
|
|
|
else
|
|
|
|
VM_LONG(ret) = cl.stats[0][VM_LONG(arg[0])];
|
|
|
|
break;
|
|
|
|
case UI_GETVIDINFO:
|
|
|
|
{
|
|
|
|
vidinfo_t *vi;
|
|
|
|
if (arg[0] + VM_LONG(arg[1]) >= mask || VM_POINTER(arg[1]) < offset)
|
|
|
|
{
|
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
break; //out of bounds.
|
|
|
|
}
|
|
|
|
vi = VM_POINTER(arg[0]);
|
|
|
|
if (VM_LONG(arg[1]) < sizeof(vidinfo_t))
|
|
|
|
{
|
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
VM_LONG(ret) = sizeof(vidinfo_t);
|
|
|
|
vi->width = vid.width;
|
|
|
|
vi->height = vid.height;
|
|
|
|
vi->refreshrate = 60;
|
|
|
|
vi->fullscreen = 1;
|
|
|
|
Q_strncpyz(vi->renderername, q_renderername, sizeof(vi->renderername));
|
|
|
|
}
|
|
|
|
break;
|
2007-09-17 20:35:39 +00:00
|
|
|
*/
|
2005-08-26 22:56:51 +00:00
|
|
|
|
|
|
|
case UI_PC_ADD_GLOBAL_DEFINE:
|
|
|
|
Con_Printf("UI_PC_ADD_GLOBAL_DEFINE not supported\n");
|
|
|
|
break;
|
|
|
|
case UI_PC_SOURCE_FILE_AND_LINE:
|
|
|
|
Script_Get_File_And_Line(arg[0], VM_POINTER(arg[1]), VM_POINTER(arg[2]));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UI_PC_LOAD_SOURCE:
|
|
|
|
return Script_LoadFile(VM_POINTER(arg[0]));
|
|
|
|
case UI_PC_FREE_SOURCE:
|
|
|
|
Script_Free(arg[0]);
|
|
|
|
break;
|
|
|
|
case UI_PC_READ_TOKEN:
|
|
|
|
//fixme: memory protect.
|
|
|
|
return Script_Read(arg[0], VM_POINTER(arg[1]));
|
|
|
|
|
2006-03-06 01:41:09 +00:00
|
|
|
case UI_CIN_PLAYCINEMATIC:
|
2020-03-07 09:00:40 +00:00
|
|
|
return UI_Cin_Play(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), VM_LONG(arg[3]), VM_LONG(arg[4]), VM_LONG(arg[5]));
|
2006-03-06 01:41:09 +00:00
|
|
|
case UI_CIN_STOPCINEMATIC:
|
2020-03-07 09:00:40 +00:00
|
|
|
return UI_Cin_Stop(VM_LONG(arg[0]));
|
2006-03-06 01:41:09 +00:00
|
|
|
case UI_CIN_RUNCINEMATIC:
|
2020-03-07 09:00:40 +00:00
|
|
|
return UI_Cin_Run(VM_LONG(arg[0]));
|
2006-03-06 01:41:09 +00:00
|
|
|
case UI_CIN_DRAWCINEMATIC:
|
2020-03-07 09:00:40 +00:00
|
|
|
return UI_Cin_Draw(VM_LONG(arg[0]));
|
2006-03-06 01:41:09 +00:00
|
|
|
case UI_CIN_SETEXTENTS:
|
2020-03-07 09:00:40 +00:00
|
|
|
return UI_Cin_SetExtents(VM_LONG(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), VM_LONG(arg[3]), VM_LONG(arg[4]));
|
2006-03-06 01:41:09 +00:00
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
default:
|
2020-03-07 09:00:40 +00:00
|
|
|
Con_Printf("Q3UI: Unknown system trap: %i\n", (int)fn);
|
2005-08-26 22:56:51 +00:00
|
|
|
return 0;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
static int UI_SystemCallsVM(void *offset, quintptr_t mask, int fn, const int *arg)
|
2004-08-23 00:15:46 +00:00
|
|
|
{ //this is so we can use edit and continue properly (vc doesn't like function pointers for edit+continue)
|
2011-01-29 21:01:40 +00:00
|
|
|
#if __WORDSIZE == 32
|
|
|
|
return UI_SystemCalls(offset, mask, fn, (qintptr_t*)arg);
|
|
|
|
#else
|
|
|
|
qintptr_t args[9];
|
|
|
|
|
|
|
|
args[0]=arg[0];
|
|
|
|
args[1]=arg[1];
|
|
|
|
args[2]=arg[2];
|
|
|
|
args[3]=arg[3];
|
|
|
|
args[4]=arg[4];
|
|
|
|
args[5]=arg[5];
|
|
|
|
args[6]=arg[6];
|
|
|
|
args[7]=arg[7];
|
|
|
|
args[8]=arg[8];
|
|
|
|
|
|
|
|
return UI_SystemCalls(offset, mask, fn, args);
|
|
|
|
#endif
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//I'm not keen on this.
|
|
|
|
//but dlls call it without saying what sort of vm it comes from, so I've got to have them as specifics
|
2010-11-02 23:17:25 +00:00
|
|
|
static qintptr_t EXPORT_FN UI_SystemCallsNative(qintptr_t arg, ...)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2010-07-11 02:22:39 +00:00
|
|
|
qintptr_t args[9];
|
2004-08-23 00:15:46 +00:00
|
|
|
va_list argptr;
|
|
|
|
|
|
|
|
va_start(argptr, arg);
|
2010-07-11 02:22:39 +00:00
|
|
|
args[0]=va_arg(argptr, qintptr_t);
|
|
|
|
args[1]=va_arg(argptr, qintptr_t);
|
|
|
|
args[2]=va_arg(argptr, qintptr_t);
|
|
|
|
args[3]=va_arg(argptr, qintptr_t);
|
|
|
|
args[4]=va_arg(argptr, qintptr_t);
|
|
|
|
args[5]=va_arg(argptr, qintptr_t);
|
|
|
|
args[6]=va_arg(argptr, qintptr_t);
|
|
|
|
args[7]=va_arg(argptr, qintptr_t);
|
|
|
|
args[8]=va_arg(argptr, qintptr_t);
|
2004-08-23 00:15:46 +00:00
|
|
|
va_end(argptr);
|
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
return UI_SystemCalls(NULL, ~(quintptr_t)0, arg, args);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
2019-09-04 07:59:40 +00:00
|
|
|
static void UI_Release(menu_t *m)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2019-09-04 07:59:40 +00:00
|
|
|
keycatcher &= ~2;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
2019-09-04 07:59:40 +00:00
|
|
|
static void UI_DrawMenu(menu_t *m)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
if (uivm)
|
|
|
|
{
|
2019-01-29 07:18:07 +00:00
|
|
|
if (qrenderer != QR_NONE && (ui_width != vid.width || ui_height != vid.height))
|
|
|
|
{
|
|
|
|
ui_width = vid.width;
|
|
|
|
ui_height = vid.height;
|
|
|
|
VM_Call(uivm, UI_INIT);
|
|
|
|
}
|
2005-08-26 22:56:51 +00:00
|
|
|
VM_Call(uivm, UI_REFRESH, (int)(realtime * 1000));
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
|
2019-09-04 07:59:40 +00:00
|
|
|
uimenu.isopaque = VM_Call(uivm, UI_IS_FULLSCREEN);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-04 07:59:40 +00:00
|
|
|
qboolean UI_KeyPress(struct menu_s *m, qboolean isdown, unsigned int devid, int key, int unicode)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2004-12-21 04:29:14 +00:00
|
|
|
// qboolean result;
|
2004-08-23 00:15:46 +00:00
|
|
|
if (!uivm)
|
|
|
|
return false;
|
2005-08-26 22:56:51 +00:00
|
|
|
// if (key_dest == key_menu)
|
|
|
|
// return false;
|
2004-08-23 00:15:46 +00:00
|
|
|
if (!(keycatcher&2))
|
|
|
|
{
|
2019-09-04 07:59:40 +00:00
|
|
|
if (key == K_ESCAPE && isdown)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2009-11-04 21:16:50 +00:00
|
|
|
UI_OpenMenu();
|
2006-09-17 00:59:22 +00:00
|
|
|
return true;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
if (key && key < 1024)
|
|
|
|
/*result = */VM_Call(uivm, UI_KEY_EVENT, key, isdown);
|
|
|
|
if (unicode && unicode < 1024)
|
|
|
|
/*result = */VM_Call(uivm, UI_KEY_EVENT, unicode|1024, isdown);
|
2004-12-21 04:29:14 +00:00
|
|
|
return true;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
2019-09-04 07:59:40 +00:00
|
|
|
static qboolean UI_MousePosition(struct menu_s *m, qboolean abs, unsigned int devid, float x, float y)
|
|
|
|
{ //q3ui is a peice of poo and only accepts relative mouse movements.
|
|
|
|
//which it then clamps arbitrarily
|
|
|
|
//which means we can't use hardware cursors
|
|
|
|
//which results in clumsyness when switching between q3ui and everything else.
|
|
|
|
|
|
|
|
if (uivm && !abs)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2019-09-04 07:59:40 +00:00
|
|
|
int px = x, py = y;
|
2019-01-29 07:18:07 +00:00
|
|
|
VM_Call(uivm, UI_MOUSE_EVENT, px, py);
|
2009-11-04 21:16:50 +00:00
|
|
|
return true;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
2009-11-04 21:16:50 +00:00
|
|
|
return false;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
2019-09-04 07:59:40 +00:00
|
|
|
void UI_Reset(void)
|
|
|
|
{
|
|
|
|
Menu_Unlink(&uimenu);
|
|
|
|
|
|
|
|
if (qrenderer == QR_NONE) //no renderer loaded
|
|
|
|
UI_Stop();
|
|
|
|
else if (uivm)
|
|
|
|
VM_Call(uivm, UI_INIT);
|
|
|
|
}
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
void UI_Stop (void)
|
|
|
|
{
|
2019-09-04 07:59:40 +00:00
|
|
|
Menu_Unlink(&uimenu);
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
if (uivm)
|
|
|
|
{
|
|
|
|
VM_Call(uivm, UI_SHUTDOWN);
|
|
|
|
VM_Destroy(uivm);
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_fcloseall(0);
|
2004-08-23 00:15:46 +00:00
|
|
|
uivm = NULL;
|
2014-10-05 20:04:11 +00:00
|
|
|
|
|
|
|
//mimic Q3 and save the config if anything got changed.
|
|
|
|
//note that q3 checks every frame. we only check when the ui is closed.
|
|
|
|
if (Cvar_UnsavedArchive())
|
|
|
|
Cmd_ExecuteString("cfg_save", RESTRICT_LOCAL);
|
2019-08-03 01:58:03 +00:00
|
|
|
#if defined(CL_MASTER)
|
2017-12-09 21:22:46 +00:00
|
|
|
MasterInfo_WriteServers();
|
2019-08-03 01:58:03 +00:00
|
|
|
#endif
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UI_Start (void)
|
|
|
|
{
|
2014-12-23 15:26:42 +00:00
|
|
|
int i;
|
2004-08-23 00:15:46 +00:00
|
|
|
int apiversion;
|
2012-09-30 05:52:03 +00:00
|
|
|
if (qrenderer == QR_NONE)
|
2005-10-16 03:54:43 +00:00
|
|
|
return;
|
|
|
|
|
2013-03-12 23:03:04 +00:00
|
|
|
UI_Stop();
|
|
|
|
|
2014-12-23 15:26:42 +00:00
|
|
|
for (i = 0; i < MAX_PINGREQUESTS; i++)
|
2019-02-01 08:29:14 +00:00
|
|
|
ui_pings[i].adr.type = NA_INVALID;
|
2014-12-23 15:26:42 +00:00
|
|
|
|
2019-09-04 07:59:40 +00:00
|
|
|
uimenu.drawmenu = UI_DrawMenu;
|
|
|
|
uimenu.mousemove = UI_MousePosition;
|
|
|
|
uimenu.keyevent = UI_KeyPress;
|
|
|
|
uimenu.release = UI_Release;
|
|
|
|
|
2019-01-29 07:18:07 +00:00
|
|
|
ui_width = vid.width;
|
|
|
|
ui_height = vid.height;
|
2019-02-24 08:32:45 +00:00
|
|
|
uivm = VM_Create("ui", com_nogamedirnativecode.ival?NULL:UI_SystemCallsNative, "vm/ui", UI_SystemCallsVM);
|
2004-08-23 00:15:46 +00:00
|
|
|
if (uivm)
|
|
|
|
{
|
2007-09-17 20:35:39 +00:00
|
|
|
apiversion = VM_Call(uivm, UI_GETAPIVERSION, 6);
|
|
|
|
if (apiversion != 4 && apiversion != 6) //make sure we can run the thing
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2007-10-05 18:08:47 +00:00
|
|
|
Con_Printf("User-Interface VM uses incompatible API version (%i)\n", apiversion);
|
2004-08-23 00:15:46 +00:00
|
|
|
VM_Destroy(uivm);
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_fcloseall(0);
|
2004-08-23 00:15:46 +00:00
|
|
|
uivm = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
VM_Call(uivm, UI_INIT);
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
UI_OpenMenu();
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UI_Restart_f(void)
|
|
|
|
{
|
|
|
|
UI_Stop();
|
2018-01-22 19:18:04 +00:00
|
|
|
if (strcmp(Cmd_Argv(1), "off"))
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
2018-01-22 19:18:04 +00:00
|
|
|
UI_Start();
|
|
|
|
|
|
|
|
if (uivm)
|
|
|
|
{
|
|
|
|
if (cls.state)
|
|
|
|
VM_Call(uivm, UI_SET_ACTIVE_MENU, 2);
|
|
|
|
else
|
|
|
|
VM_Call(uivm, UI_SET_ACTIVE_MENU, 1);
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
qboolean UI_OpenMenu(void)
|
|
|
|
{
|
|
|
|
if (uivm)
|
|
|
|
{
|
|
|
|
if (cls.state)
|
|
|
|
VM_Call(uivm, UI_SET_ACTIVE_MENU, 2);
|
|
|
|
else
|
|
|
|
VM_Call(uivm, UI_SET_ACTIVE_MENU, 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-09-08 22:52:46 +00:00
|
|
|
qboolean UI_Command(void)
|
|
|
|
{
|
|
|
|
if (uivm)
|
2014-10-05 20:04:11 +00:00
|
|
|
return VM_Call(uivm, UI_CONSOLE_COMMAND, (int)(realtime * 1000));
|
2005-09-08 22:52:46 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-01 08:29:14 +00:00
|
|
|
qboolean UI_IsRunning(void)
|
|
|
|
{
|
|
|
|
if (uivm)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
void UI_Init (void)
|
|
|
|
{
|
2011-01-30 01:32:30 +00:00
|
|
|
Cmd_AddCommand("ui_restart", UI_Restart_f);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
#endif
|
2005-09-09 23:40:55 +00:00
|
|
|
|