added support for external capture plugins - and using avcodec as a plugin.c.

The ragdoll API is potentially usable now, but still really limited.
Enabled SQL requests by default using sqlite. Note that you'll need the sqlite dll to use this. MySQL should still be usable, but I didn't try. MySQL requires -DUSE_MYSQL to compile it, and a dll and -mysql argument to enable it.
Fixed nacl.
NPFTE plugin now invokes an exe to run the game rather than running the game within the browser.
externvalue builtin now accepts & prefix to return a pointer instead.
Fixed vector autocvars.
uri_get, bufstr_add, bufstr_free, now functional.
QC debugger can now show asm if line numbers are not available.
Added support for QC watchpoints. Use the watchpoint command.
gl_specular now give specular even without rtlights, thankfully not as blatently, but its there.
android will not crash due to supported audio formats, and gles2 can be selected via a cvar (requires full FTEDroidActivity/program restart).

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4152 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2012-11-27 03:23:19 +00:00
parent 705e1ab0e0
commit 53a7b3d47c
159 changed files with 17179 additions and 30191 deletions

View file

@ -28,6 +28,35 @@ Note that there is no way to install the package with a different name at this t
Browser versions of FTE:
The FTE browser plugin is available only in windows.
Compile with 'make npfte-rel FTE_TARGET=win32'.
This will yield an npfte.dll file.
You can 'register' this dll by running 'regsvr32 npfte.dll' at a command prompt (this is the standard way to register an activex control - any setup software should provide some mechanism to do this at install time). This will register both the netscape/firefox/chrome/opera version, and the activex/IE version of the plugin.
Note that the plugin will run the engine in a separate process and thus requires a valid fteqw.exe file in the same directory as the plugin.
If given an 'npfte.txt' file that contains the line 'relexe foo', the plugin will try to run foo.exe instead of fteqw, basedir "foo" can be used to invoke it with a different basedir. You can use this if you'd rather run the mingl or gl-only version, or if you'd like to retarget npfte to invoke a different quake engine intead. Note that different quake engines will need to support the -plugin argument and the stdin/stdout parsing for embedding - at the time of writing, no others do.
The following chunk of html can then be included on a web page to embed it. Yes. Two nested objects.
<object name="ieplug" type="text/x-quaketvident" classid="clsid:7d676c9f-fb84-40b6-b3ff-e10831557eeb" width=100% height=100% ><param name="splash" value="http://127.0.0.1:27599/qtvsplash.jpg"><param name="game" value="q1"><param name="dataDownload" value=''><object name="npplug" type="text/x-quaketvident" width=100% height=100% ><param name="splash" value="http://127.0.0.1:27599/qtvsplash.jpg"><param name="game" value="q1"><param name="dataDownload" value=''>Plugin failed to load</object></object>
Nacl version of FTE:
make gl-rel FTE_TARGET=nacl NACL_SDK_ROOT=SOMEVALIDPATHHERE BITS=32
make gl-rel FTE_TARGET=nacl NACL_SDK_ROOT=SOMEVALIDPATHHERE BITS=64
in windows compile with cygwin, not minsys.
This will give you two 'nexe' files.
You can then embed the 'fteqw.nmf' file (its entire contents can be found on the following line) with mime type 'application/x-nacl' on your page. Give it a sane width/height.
{
"program": {
"x86-64": {"url": "fteqw_x86_64.nexe"},
"x86-32": {"url": "fteqw_x86_32.nexe"}
}
}
You can object.postMessage("join foo") / qtvplay / map to tell it to switch server/map/stream.
You can read console prints via listener.addEventListener('message', handleMessage, true);
Your users will need to explicitly allow nacl use outside of google play (in about:config or whatever it is), or you will need to submit your port of fte to google play.
This stuff has separate directories
engine: FTEQW game engine itself. Both client and dedicated server.
engine/ftequake: location of old msvc6 project file. Might not work.

View file

@ -537,6 +537,7 @@ SERVER_OBJS = \
sv_ents.o \
sv_send.o \
sv_user.o \
sv_sql.o \
sv_mvd.o \
sv_ccmds.o \
sv_rankin.o \
@ -664,6 +665,8 @@ endif
#specific targets override those defaults as needed.
#google native client
ifeq ($(FTE_TARGET),nacl)
OGGVORBISLDFLAGS=
ifeq ($(shell uname -o 2>&1 | grep Cygwin),)
CC=$(NACL_SDK_ROOT)/toolchain/linux_x86_newlib/bin/i686-nacl-gcc -DNACL -m$(BITS)
STRIP=$(NACL_SDK_ROOT)/toolchain/linux_x86_newlib/bin/i686-nacl-strip

View file

@ -697,7 +697,7 @@ void Cam_TrackPlayer(int pnum, char *cmdname, char *plrarg)
c = plrarg;
while (*c)
{
if (!isdigit(*c))
if (*c < '0' || *c > '9')
{
Con_Printf("Couldn't find nick %s\n", plrarg);
return;

View file

@ -34,7 +34,7 @@ char lastdemoname[256];
extern cvar_t qtvcl_forceversion1;
extern cvar_t qtvcl_eztvextensions;
unsigned char demobuffer[1024*16];
unsigned char demobuffer[1024*66];
int demobuffersize;
int demopreparsedbytes;
qboolean disablepreparse;
@ -325,20 +325,19 @@ void CL_DemoJump_f(void)
if (!cls.demoplayback)
return;
if (*s == '+')
if (*s == '+' || *s == '-')
{
if (colon)
{
colon++;
demtime += atoi(colon);
demtime += atoi(s)*60;
newtime = demtime + atoi(colon) + atoi(s)*60;
}
else
demtime += atoi(s);
newtime = demtime + atoi(s);
}
else
{
//absolute seek time
if (colon)
{
colon++;
@ -347,6 +346,7 @@ void CL_DemoJump_f(void)
}
else
newtime = atoi(s);
}
if (newtime >= demtime)
demtime = newtime;
@ -355,10 +355,10 @@ void CL_DemoJump_f(void)
Con_Printf("Rewinding demo\n");
CL_PlayDemo(lastdemoname);
//now fastparse it.
demtime = newtime;
}
}
}
/*
====================

View file

@ -2242,9 +2242,9 @@ void CL_LinkStaticEntities(void *pvs)
if ((!r_drawflame.ival) && (clmodel->engineflags & MDLF_FLAME))
continue;
/*pvs test*/
if (pvs && !cl.worldmodel->funcs.EdictInFatPVS(cl.worldmodel, &cl_static_entities[i].pvscache, pvs))
continue;
/*pvs test*/
ent = &cl_visedicts[cl_numvisedicts++];
*ent = *stat;
@ -3255,11 +3255,13 @@ void CL_ParsePlayerinfo (void)
TP_ParsePlayerInfo(oldstate, state, info);
//can't CL_SetStatInt as we don't know if its actually us or not
cl.players[num].stats[STAT_WEAPONFRAME] = state->weaponframe;
cl.players[num].statsf[STAT_WEAPONFRAME] = state->weaponframe;
for (i = 0; i < cl.splitclients; i++)
{
if (cl.playernum[i] == num)
if (spec_track[i] == num)
{
cl.playerview[i].stats[STAT_WEAPONFRAME] = state->weaponframe;
cl.playerview[i].statsf[STAT_WEAPONFRAME] = state->weaponframe;
@ -3484,9 +3486,10 @@ guess_pm_type:
TP_ParsePlayerInfo(oldstate, state, info);
//can't CL_SetStatInt as we don't know if its actually us or not
for (i = 0; i < cl.splitclients; i++)
{
if (cl.playernum[i] == num)
if (spec_track[i] == num)
{
cl.playerview[i].stats[STAT_WEAPONFRAME] = state->weaponframe;
cl.playerview[i].statsf[STAT_WEAPONFRAME] = state->weaponframe;
@ -3729,6 +3732,7 @@ void CL_LinkPlayers (void)
{
vec3_t org;
VectorCopy(state->origin, org);
//make the light appear at the predicted position rather than anywhere else.
for (pnum = 0; pnum < cl.splitclients; pnum++)
if (cl.playernum[pnum] == j)
VectorCopy(cl.playerview[pnum].simorg, org);

View file

@ -102,7 +102,7 @@ extern int total_loading_size, current_loading_size, loading_stage;
//
// info mirrors
//
cvar_t password = CVARF("password", "", CVAR_USERINFO | CVAR_NOUNSAFEEXPAND); //this is parhaps slightly dodgy...
cvar_t password = CVARAF("password", "", "pq_password", CVAR_USERINFO | CVAR_NOUNSAFEEXPAND); //this is parhaps slightly dodgy... added pq_password alias because baker seems to be using this for user accounts.
cvar_t spectator = CVARF("spectator", "", CVAR_USERINFO);
cvar_t name = CVARFC("name", "unnamed", CVAR_ARCHIVE | CVAR_USERINFO, Name_Callback);
cvar_t team = CVARF("team", "", CVAR_ARCHIVE | CVAR_USERINFO);
@ -1089,6 +1089,7 @@ void CL_ClearState (void)
CL_ClearParseState();
CL_ClearTEnts();
CL_ClearCustomTEnts();
Surf_ClearLightmaps();
T_FreeInfoStrings();
SCR_ShowPic_Clear();
@ -1135,6 +1136,7 @@ void CL_ClearState (void)
cl.allocated_client_slots = QWMAX_CLIENTS;
#ifndef CLIENTONLY
//FIXME: we should just set it to 0 to make sure its set up properly elsewhere.
if (sv.state)
cl.allocated_client_slots = sv.allocated_client_slots;
#endif
@ -3406,6 +3408,8 @@ Writes key bindings and archived cvars to config.cfg
void Host_WriteConfiguration (void)
{
vfsfile_t *f;
char savename[MAX_OSPATH];
char sysname[MAX_OSPATH];
if (host_initialized && cfg_save_name.string && *cfg_save_name.string)
{
@ -3415,7 +3419,9 @@ void Host_WriteConfiguration (void)
return;
}
f = FS_OpenVFS(va("%s.cfg",cfg_save_name.string), "wb", FS_GAMEONLY);
Q_snprintfz(savename, sizeof(savename), "%s.cfg", cfg_save_name.string);
f = FS_OpenVFS(savename, "wb", FS_GAMEONLY);
if (!f)
{
Con_TPrintf (TLC_CONFIGCFG_WRITEFAILED);
@ -3426,6 +3432,9 @@ void Host_WriteConfiguration (void)
Cvar_WriteVariables (f, false);
VFS_CLOSE (f);
FS_NativePath(savename, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf("Wrote %s\n", savename);
}
}
@ -3477,7 +3486,7 @@ double Host_Frame (double time)
static double time3 = 0;
int pass1, pass2, pass3;
// float fps;
double realframetime;
double realframetime, newrealtime;
static double spare;
float maxfps;
qboolean maxfpsignoreserver;
@ -3490,7 +3499,13 @@ double Host_Frame (double time)
return 0; // something bad happened, or the server disconnected
}
realframetime = time = Media_TweekCaptureFrameTime(time);
newrealtime = Media_TweekCaptureFrameTime(realtime, time);
realframetime = time = newrealtime - realtime;
realtime = newrealtime;
if (oldrealtime > realtime)
oldrealtime = 0;
// if (cls.demoplayback && cl_demospeed.value>0)
// realframetime *= cl_demospeed.value; // this probably screws up other timings
@ -3508,11 +3523,6 @@ double Host_Frame (double time)
Plug_Tick();
#endif
// decide the simulation time
realtime += realframetime;
if (oldrealtime > realtime)
oldrealtime = 0;
if (cl.paused)
cl.gametimemark += time;
@ -3570,7 +3580,7 @@ double Host_Frame (double time)
maxfps = 4;
}
if (maxfps > 0)
if (maxfps > 0 && Media_Capturing() != 2)
{
realtime += spare/1000; //don't use it all!
spare = CL_FilterTime((realtime - oldrealtime)*1000, maxfps, maxfpsignoreserver);
@ -3779,6 +3789,130 @@ void CL_ReadCDKey(void)
//============================================================================
void CL_StartCinematicOrMenu(void)
{
//start up the ui now we have a renderer
#ifdef VM_UI
UI_Start();
#endif
Con_TPrintf (TLC_QUAKEWORLD_INITED, fs_gamename.string);
//there might be some console command or somesuch waiting for the renderer to begin (demos or map command or whatever all need model support).
realtime+=1;
Cbuf_Execute (); //server may have been waiting for the renderer
//and any startup cinematics
#ifndef NOMEDIA
if (!cls.demoinfile && !cls.state && !Media_PlayingFullScreen())
{
int ol_depth;
int idcin_depth;
int idroq_depth;
idcin_depth = COM_FDepthFile("video/idlog.cin", true); //q2
idroq_depth = COM_FDepthFile("video/idlogo.roq", true); //q2
ol_depth = COM_FDepthFile("video/openinglogos.roq", true); //jk2
if (ol_depth != 0x7fffffff && (ol_depth <= idroq_depth || ol_depth <= idcin_depth))
Media_PlayFilm("video/openinglogos.roq");
else if (idroq_depth != 0x7fffffff && idroq_depth <= idcin_depth)
Media_PlayFilm("video/idlogo.roq");
else if (idcin_depth != 0x7fffffff)
Media_PlayFilm("video/idlog.cin");
}
#endif
if (!cls.demoinfile && !*cls.servername && !Media_Playing())
{
#ifndef CLIENTONLY
if (!sv.state)
#endif
{
if (qrenderer > QR_NONE)
M_ToggleMenu_f();
//Con_ForceActiveNow();
}
}
}
//note that this does NOT include commandline.
void CL_ExecInitialConfigs(void)
{
int qrc, hrc, def, i;
Cbuf_AddText ("cl_warncmd 0\n", RESTRICT_LOCAL);
//who should we imitate?
qrc = COM_FDepthFile("quake.rc", true); //q1
hrc = COM_FDepthFile("hexen.rc", true); //h2
def = COM_FDepthFile("default.cfg", true); //q2/q3
if (qrc <= def && qrc <= hrc && qrc!=0x7fffffff)
Cbuf_AddText ("exec quake.rc\n", RESTRICT_LOCAL);
else if (hrc <= def && hrc!=0x7fffffff)
Cbuf_AddText ("exec hexen.rc\n", RESTRICT_LOCAL);
else
{ //they didn't give us an rc file!
Cbuf_AddText ("bind ~ toggleconsole\n", RESTRICT_LOCAL); //we expect default.cfg to not exist. :(
Cbuf_AddText ("exec default.cfg\n", RESTRICT_LOCAL);
if (COM_FCheckExists ("config.cfg"))
Cbuf_AddText ("exec config.cfg\n", RESTRICT_LOCAL);
if (COM_FCheckExists ("q3config.cfg"))
Cbuf_AddText ("exec q3config.cfg\n", RESTRICT_LOCAL);
Cbuf_AddText ("exec autoexec.cfg\n", RESTRICT_LOCAL);
}
Cbuf_AddText ("exec fte.cfg\n", RESTRICT_LOCAL);
if (COM_FCheckExists ("frontend.cfg"))
Cbuf_AddText ("exec frontend.cfg\n", RESTRICT_LOCAL);
Cbuf_AddText ("cl_warncmd 1\n", RESTRICT_LOCAL); //and then it's allowed to start moaning.
{
extern cvar_t com_parseutf8;
com_parseutf8.ival = com_parseutf8.value;
}
// Cbuf_Execute (); //if the server initialisation causes a problem, give it a place to abort to
//assuming they didn't use any waits in their config (fools)
//the configs should be fully loaded.
//so convert the backwards compable commandline parameters in cvar sets.
if (COM_CheckParm ("-window") || COM_CheckParm ("-startwindowed"))
Cvar_Set(Cvar_FindVar("vid_fullscreen"), "0");
if (COM_CheckParm ("-fullscreen"))
Cvar_Set(Cvar_FindVar("vid_fullscreen"), "1");
if ((i = COM_CheckParm ("-width"))) //width on it's own also sets height
{
Cvar_Set(Cvar_FindVar("vid_width"), com_argv[i+1]);
Cvar_SetValue(Cvar_FindVar("vid_height"), (atoi(com_argv[i+1])/4)*3);
}
if ((i = COM_CheckParm ("-height")))
Cvar_Set(Cvar_FindVar("vid_height"), com_argv[i+1]);
if ((i = COM_CheckParm ("-conwidth"))) //width on it's own also sets height
{
Cvar_Set(Cvar_FindVar("vid_conwidth"), com_argv[i+1]);
Cvar_SetValue(Cvar_FindVar("vid_conheight"), (atoi(com_argv[i+1])/4)*3);
}
if ((i = COM_CheckParm ("-conheight")))
Cvar_Set(Cvar_FindVar("vid_conheight"), com_argv[i+1]);
if ((i = COM_CheckParm ("-bpp")))
Cvar_Set(Cvar_FindVar("vid_bpp"), com_argv[i+1]);
if (COM_CheckParm ("-current"))
Cvar_Set(Cvar_FindVar("vid_desktopsettings"), "1");
Cbuf_Execute (); //if the server initialisation causes a problem, give it a place to abort to
}
/*
====================
Host_Init
@ -3786,12 +3920,8 @@ Host_Init
*/
void Host_Init (quakeparms_t *parms)
{
#ifndef NPFTE
int i;
int qrc, hrc, def;
#endif
extern cvar_t com_parseutf8;
com_parseutf8.ival = 1;
com_parseutf8.ival = 1; //enable utf8 parsing even before cvars are registered.
COM_InitArgv (parms->argc, parms->argv);
@ -3875,117 +4005,27 @@ void Host_Init (quakeparms_t *parms)
host_initialized = true;
#ifdef NPFTE
}
Sys_SendKeyEvents();
void Host_FinishInit(void)
//the engine is technically initialised at this point, except for the renderer. now we exec configs and bring up the renderer
//anything that needs models cannot be run yet, but it should be safe to allow console commands etc.
//if we get a map command, we'll just stick it on the end of the console command buffer.
Con_History_Load();
CL_ExecInitialConfigs();
if (CL_CheckBootDownloads())
{
int i;
int qrc, hrc, def;
#endif
Cbuf_AddText ("cl_warncmd 0\n", RESTRICT_LOCAL);
//who should we imitate?
qrc = COM_FDepthFile("quake.rc", true); //q1
hrc = COM_FDepthFile("hexen.rc", true); //h2
def = COM_FDepthFile("default.cfg", true); //q2/q3
if (qrc <= def && qrc <= hrc && qrc!=0x7fffffff)
Cbuf_AddText ("exec quake.rc\n", RESTRICT_LOCAL);
else if (hrc <= def && hrc!=0x7fffffff)
Cbuf_AddText ("exec hexen.rc\n", RESTRICT_LOCAL);
else
{ //they didn't give us an rc file!
Cbuf_AddText ("bind ~ toggleconsole\n", RESTRICT_LOCAL); //we expect default.cfg to not exist. :(
Cbuf_AddText ("exec default.cfg\n", RESTRICT_LOCAL);
if (COM_FCheckExists ("config.cfg"))
Cbuf_AddText ("exec config.cfg\n", RESTRICT_LOCAL);
if (COM_FCheckExists ("q3config.cfg"))
Cbuf_AddText ("exec q3config.cfg\n", RESTRICT_LOCAL);
Cbuf_AddText ("exec autoexec.cfg\n", RESTRICT_LOCAL);
}
Cbuf_AddText ("exec fte.cfg\n", RESTRICT_LOCAL);
if (COM_FCheckExists ("frontend.cfg"))
Cbuf_AddText ("exec frontend.cfg\n", RESTRICT_LOCAL);
Cbuf_AddText ("cl_warncmd 1\n", RESTRICT_LOCAL); //and then it's allowed to start moaning.
{
extern cvar_t com_parseutf8;
com_parseutf8.ival = com_parseutf8.value;
}
Cbuf_Execute (); //if the server initialisation causes a problem, give it a place to abort to
//assuming they didn't use any waits in their config (fools)
//the configs should be fully loaded.
//so convert the backwards compable commandline parameters in cvar sets.
if (COM_CheckParm ("-window") || COM_CheckParm ("-startwindowed"))
Cvar_Set(Cvar_FindVar("vid_fullscreen"), "0");
if (COM_CheckParm ("-fullscreen"))
Cvar_Set(Cvar_FindVar("vid_fullscreen"), "1");
if ((i = COM_CheckParm ("-width"))) //width on it's own also sets height
{
Cvar_Set(Cvar_FindVar("vid_width"), com_argv[i+1]);
Cvar_SetValue(Cvar_FindVar("vid_height"), (atoi(com_argv[i+1])/4)*3);
}
if ((i = COM_CheckParm ("-height")))
Cvar_Set(Cvar_FindVar("vid_height"), com_argv[i+1]);
if ((i = COM_CheckParm ("-conwidth"))) //width on it's own also sets height
{
Cvar_Set(Cvar_FindVar("vid_conwidth"), com_argv[i+1]);
Cvar_SetValue(Cvar_FindVar("vid_conheight"), (atoi(com_argv[i+1])/4)*3);
}
if ((i = COM_CheckParm ("-conheight")))
Cvar_Set(Cvar_FindVar("vid_conheight"), com_argv[i+1]);
if ((i = COM_CheckParm ("-bpp")))
Cvar_Set(Cvar_FindVar("vid_bpp"), com_argv[i+1]);
if (COM_CheckParm ("-current"))
Cvar_Set(Cvar_FindVar("vid_desktopsettings"), "1");
//now exec their commandline
Cmd_StuffCmds();
Cbuf_Execute (); //if the server initialisation causes a problem, give it a place to abort to
Renderer_Start();
#ifdef VM_UI
UI_Start();
#endif
#ifndef NOMEDIA
if (!cls.demoinfile && !cls.state && !Media_PlayingFullScreen())
{
int ol_depth;
int idcin_depth;
int idroq_depth;
idcin_depth = COM_FDepthFile("video/idlog.cin", true); //q2
idroq_depth = COM_FDepthFile("video/idlogo.roq", true); //q2
ol_depth = COM_FDepthFile("video/openinglogos.roq", true); //jk2
if (ol_depth != 0x7fffffff && (ol_depth <= idroq_depth || ol_depth <= idcin_depth))
Media_PlayFilm("video/openinglogos.roq");
else if (idroq_depth != 0x7fffffff && idroq_depth <= idcin_depth)
Media_PlayFilm("video/idlogo.roq");
else if (idcin_depth != 0x7fffffff)
Media_PlayFilm("video/idlog.cin");
Cbuf_Execute ();
}
#endif
Con_TPrintf (TL_NL);
Con_Printf ("%s", version_string());
Con_TPrintf (TL_NL);
Con_TPrintf (TLC_QUAKEWORLD_INITED, fs_gamename.string);
Con_DPrintf("This program is free software; you can redistribute it and/or "
"modify it under the terms of the GNU General Public License "
"as published by the Free Software Foundation; either version 2 "
@ -3997,20 +4037,9 @@ Con_TPrintf (TL_NL);
"\n"
"See the GNU General Public License for more details.\n");
realtime+=1;
Cbuf_Execute (); //server may have been waiting for the renderer
Renderer_Start();
if (!cls.demoinfile && !*cls.servername && !Media_Playing())
{
#ifndef CLIENTONLY
if (!sv.state)
#endif
{
if (qrenderer > QR_NONE)
M_ToggleMenu_f();
//Con_ForceActiveNow();
}
}
CL_StartCinematicOrMenu();
}
/*
@ -4045,6 +4074,9 @@ void Host_Shutdown(void)
S_Shutdown();
IN_Shutdown ();
R_ShutdownRenderer();
#ifdef CL_MASTER
MasterInfo_Shutdown();
#endif
CL_FreeDlights();
M_Shutdown();
#ifndef CLIENTONLY

View file

@ -128,7 +128,8 @@ typedef struct serverinfo_s {
typedef struct master_s{
struct master_s *next;
netadr_t adr;
char *address; //text based address (http servers
char *address; //text based address (http servers)
struct dl_download *dl;
int type;
int servertype; //filled in for http servers
int sends; /*needs to resend?*/
@ -163,6 +164,7 @@ extern player_t *mplayers;
void Master_SetupSockets(void);
void CL_QueryServers(void);
int Master_CheckPollSockets(void);
void MasterInfo_Shutdown(void);
void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles);
serverinfo_t *Master_InfoForServer (netadr_t addr);
serverinfo_t *Master_InfoForNum (int num);

View file

@ -233,7 +233,7 @@ char *svc_nqstrings[] =
"dpsvc_spawnbaseline2", //55
"dpsvc_spawnstatic2", //56 obsolete
"dpsvc_entities", //57
"NEW PROTOCOL", //58
"dpsvc_csqcentities", //58
"dpsvc_spawnstaticsound2", //59
"dpsvc_trailparticles", //60
"dpsvc_pointparticles", //61
@ -360,8 +360,11 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags)
char *ext;
downloadlist_t *dl;
qboolean webdl = false;
if (localname && !strncmp(filename, "http://", 7))
if (!strncmp(filename, "http://", 7))
{
if (!localname)
return false;
webdl = true;
}
else
@ -619,6 +622,7 @@ void CL_DownloadFinished(void)
CL_CheckModelResources(filename);
if (!cl.sendprespawn)
{
/*
for (i = 0; i < mod_numknown; i++) //go and load this model now.
{
if (!strcmp(mod_known[i].name, filename))
@ -627,6 +631,7 @@ void CL_DownloadFinished(void)
break;
}
}
*/
for (i = 0; i < MAX_MODELS; i++) //go and load this model now.
{
if (!strcmp(cl.model_name[i], filename))
@ -637,6 +642,14 @@ void CL_DownloadFinished(void)
break;
}
}
for (i = 0; i < MAX_CSQCMODELS; i++) //go and load this model now.
{
if (!strcmp(cl.model_csqcname[i], filename))
{
cl.model_csqcprecache[i] = Mod_ForName(cl.model_csqcname[i], false); //throw away result.
break;
}
}
for (i = 0; i < MAX_VWEP_MODELS; i++)
{
if (!strcmp(cl.model_name_vwep[i], filename))
@ -1589,12 +1602,10 @@ downloadlist_t *CL_DownloadFailed(char *name)
return failed;
}
float downloadstarttime;
#ifdef PEXT_CHUNKEDDOWNLOADS
#define MAXBLOCKS 512 //must be power of 2
#define DLBLOCKSIZE 1024
int downloadsize;
int receivedbytes;
struct
{
int chunkno;
@ -1605,7 +1616,7 @@ int download_file_number;
int CL_DownloadRate(void)
{
return receivedbytes/(Sys_DoubleTime() - downloadstarttime);
return cls.downloadedbytes/(Sys_DoubleTime() - cls.downloadstarttime);
}
void CL_ParseChunkedDownload(void)
@ -1664,7 +1675,7 @@ void CL_ParseChunkedDownload(void)
cls.downloadpercent = 0;
downloadsize = totalsize;
downloadstarttime = Sys_DoubleTime();
cls.downloadstarttime = Sys_DoubleTime();
/*
strcpy(cls.downloadname, svname);
@ -1696,7 +1707,7 @@ void CL_ParseChunkedDownload(void)
download_file_number++;
firstblock = 0;
receivedbytes = 0;
cls.downloadedbytes = 0;
blockcycle = -1; //so it requests 0 first. :)
for (chunknum = 0; chunknum < MAXBLOCKS; chunknum++)
dlblock[chunknum].chunkno = ~0u;
@ -1728,7 +1739,7 @@ void CL_ParseChunkedDownload(void)
dlblock[ridx].chunkno = ~0;
// Con_Printf("usable\n", chunknum);
receivedbytes+=DLBLOCKSIZE;
cls.downloadedbytes+=DLBLOCKSIZE;
VFS_SEEK(cls.downloadqw, chunknum*DLBLOCKSIZE);
if (downloadsize - chunknum*DLBLOCKSIZE < DLBLOCKSIZE) //final block is actually meant to be smaller than we recieve.
@ -1736,7 +1747,7 @@ void CL_ParseChunkedDownload(void)
else
VFS_WRITE(cls.downloadqw, data, DLBLOCKSIZE);
cls.downloadpercent = receivedbytes/(float)downloadsize*100;
cls.downloadpercent = cls.downloadedbytes/(float)downloadsize*100;
}
int CL_CountQueuedDownloads(void)
@ -1781,7 +1792,7 @@ int CL_RequestADownloadChunk(void)
CL_SendClientCommand(true, "stopdownload");
CL_DownloadFinished();
Con_DPrintf("Download took %i seconds (%i more)\n", (int)(Sys_DoubleTime() - downloadstarttime), CL_CountQueuedDownloads());
Con_DPrintf("Download took %i seconds (%i more)\n", (int)(Sys_DoubleTime() - cls.downloadstarttime), CL_CountQueuedDownloads());
*cls.downloadlocalname = '\0';
*cls.downloadremotename = '\0';
@ -1896,8 +1907,8 @@ void CL_ParseDownload (void)
return;
}
downloadstarttime = Sys_DoubleTime();
receivedbytes = 0;
cls.downloadstarttime = Sys_DoubleTime();
cls.downloadedbytes = 0;
SCR_EndLoadingPlaque();
}
#ifdef PEXT_ZLIBDL
@ -1918,9 +1929,9 @@ void CL_ParseDownload (void)
msg_readcount += size;
}
receivedbytes += size;
cls.downloadedbytes += size;
if (cls.downloadpercent != percent) //try and guess the size (its most acurate when the percent value changes)
downloadsize = ((float)receivedbytes*100)/percent;
downloadsize = ((float)cls.downloadedbytes*100)/percent;
if (cls.downloadmethod == DL_QWPENDING)
cls.downloadmethod = DL_QW;
@ -1949,7 +1960,7 @@ void CL_ParseDownload (void)
cls.downloadqw = NULL;
cls.downloadpercent = 0;
Con_DPrintf("Download took %i seconds\n", (int)(Sys_DoubleTime() - downloadstarttime));
Con_DPrintf("Download took %i seconds\n", (int)(Sys_DoubleTime() - cls.downloadstarttime));
// get another file if needed
@ -2002,6 +2013,12 @@ void CLDP_ParseDownloadBegin(char *s)
size = (unsigned int)atoi(Cmd_Argv(1));
fname = Cmd_Argv(2);
if (strcmp(fname, cls.downloadlocalname))
{
Con_Printf("Warning: server started sending a file we did not request. Ignoring.\n");
return;
}
COM_StripExtension (fname, cls.downloadtempname, sizeof(cls.downloadtempname)-5);
strcat (cls.downloadtempname, ".tmp");
@ -2017,6 +2034,10 @@ void CLDP_ParseDownloadBegin(char *s)
cls.downloadqw = FS_OpenVFS (cls.downloadtempname, "wb", FS_GAME);
cls.downloadmethod = DL_DARKPLACES;
Q_strncpyz(cls.downloadlocalname, fname, sizeof(cls.downloadlocalname));
cls.downloadstarttime = Sys_DoubleTime();
cls.downloadedbytes = 0;
if (cls.downloadqw)
{
//fill the file with 0 bytes
@ -2032,7 +2053,7 @@ void CLDP_ParseDownloadBegin(char *s)
else
CL_DownloadFailed(cls.downloadremotename);
downloadstarttime = Sys_DoubleTime();
cls.downloadstarttime = Sys_DoubleTime();
}
void CLDP_ParseDownloadFinished(char *s)
@ -2089,7 +2110,7 @@ void CLDP_ParseDownloadFinished(char *s)
cls.downloadqw = NULL;
cls.downloadpercent = 0;
Con_DPrintf("Download took %i seconds\n", (int)(Sys_DoubleTime() - downloadstarttime));
Con_DPrintf("Download took %i seconds\n", (int)(Sys_DoubleTime() - cls.downloadstarttime));
// get another file if needed
@ -2758,8 +2779,15 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
Q_strncpyz (cl.levelname, str, sizeof(cl.levelname));
// seperate the printfs so the server message can have a color
#if 1
Con_Printf ("\n\n");
Con_Printf ("^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f");
Con_Printf ("\n\n");
Con_Printf ("\1%s\n", str);
#else
Con_TPrintf (TLC_LINEBREAK_NEWLEVEL);
Con_TPrintf (TLC_PC_PS_NL, 2, str);
#endif
SCR_BeginLoadingPlaque();
@ -3545,6 +3573,7 @@ void CL_ParseStatic (int version)
ent = &cl_static_entities[i].ent;
memset(ent, 0, sizeof(*ent));
memset(&cl_static_entities[i].pvscache, 0, sizeof(cl_static_entities[i].pvscache));
ent->keynum = es.number;
@ -3591,8 +3620,13 @@ void CL_ParseStatic (int version)
/*FIXME: compensate for angle*/
VectorAdd(es.origin, ent->model->mins, mins);
VectorAdd(es.origin, ent->model->maxs, maxs);
cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].pvscache, mins, maxs);
}
else
{
VectorCopy(es.origin, mins);
VectorCopy(es.origin, maxs);
}
cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].pvscache, mins, maxs);
}
/*
@ -3600,7 +3634,7 @@ void CL_ParseStatic (int version)
CL_ParseStaticSound
===================
*/
void CL_ParseStaticSound (void)
void CL_ParseStaticSound (qboolean large)
{
extern cvar_t cl_staticsounds;
vec3_t org;
@ -3609,6 +3643,9 @@ void CL_ParseStaticSound (void)
for (i=0 ; i<3 ; i++)
org[i] = MSG_ReadCoord ();
if (large)
sound_num = (unsigned short)MSG_ReadShort();
else
sound_num = MSG_ReadByte ();
vol = MSG_ReadByte ();
atten = MSG_ReadByte ();
@ -5474,7 +5511,7 @@ void CLQW_ParseServerMessage (void)
break;
case svc_spawnstaticsound:
CL_ParseStaticSound ();
CL_ParseStaticSound (false);
break;
case svc_cdtrack:
@ -6157,7 +6194,7 @@ void CLNQ_ParseServerMessage (void)
break;
case svc_spawnstaticsound:
CL_ParseStaticSound ();
CL_ParseStaticSound (false);
break;
case svc_spawnstatic:
@ -6386,6 +6423,10 @@ void CLNQ_ParseServerMessage (void)
CLDP_ParseDarkPlaces5Entities();
break;
case svcdp_spawnstaticsound2:
CL_ParseStaticSound(true);
break;
#ifdef PEXT_CSQC
case svcdp_csqcentities:
CSQC_ParseEntities();

View file

@ -1872,91 +1872,87 @@ int MipColor(int r, int g, int b)
return best;
}
qboolean SCR_ScreenShot (char *filename)
qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height)
{
int truewidth, trueheight;
qbyte *buffer;
int i, c, temp;
#if defined(AVAIL_PNGLIB) || defined(AVAIL_JPEGLIB)
extern cvar_t scr_sshot_compression;
#endif
#define MAX_PREPAD 128
char *ext;
ext = COM_FileExtension(filename);
buffer = VID_GetRGBInfo(MAX_PREPAD, &truewidth, &trueheight);
#ifdef warningmsg
#pragma warningmsg("Need to ensure that the various image writing routines can cope with ((width|height)&3")
#endif
if (!buffer)
if (!rgb_buffer)
return false;
#ifdef AVAIL_PNGLIB
if (!strcmp(ext, "png"))
{
Image_WritePNG(filename, scr_sshot_compression.value, buffer+MAX_PREPAD, truewidth, trueheight);
Image_WritePNG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
}
else
#endif
#ifdef AVAIL_JPEGLIB
if (!strcmp(ext, "jpeg") || !strcmp(ext, "jpg"))
{
screenshotJPEG(filename, scr_sshot_compression.value, buffer+MAX_PREPAD, truewidth, trueheight);
screenshotJPEG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
}
else
#endif
/* if (!strcmp(ext, "bmp"))
{
WriteBMPFile(pcxname, buffer+MAX_PREPAD, truewidth, trueheight);
WriteBMPFile(pcxname, rgb_buffer, width, height);
}
else*/
if (!strcmp(ext, "pcx"))
{
int y, x;
qbyte *src, *dest;
qbyte *newbuf = buffer + MAX_PREPAD;
// convert to eight bit
for (y = 0; y < trueheight; y++) {
src = newbuf + (truewidth * 3 * y);
dest = newbuf + (truewidth * y);
qbyte *newbuf = rgb_buffer;
// convert in-place to eight bit
for (y = 0; y < height; y++)
{
src = newbuf + (width * 3 * y);
dest = newbuf + (width * y);
for (x = 0; x < truewidth; x++) {
for (x = 0; x < width; x++) {
*dest++ = MipColor(src[0], src[1], src[2]);
src += 3;
}
}
WritePCXfile (filename, newbuf, truewidth, trueheight, truewidth, host_basepal, false);
WritePCXfile (filename, newbuf, width, height, width, host_basepal, false);
}
else //tga
{
buffer+=MAX_PREPAD-18;
memset (buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = truewidth&255;
buffer[13] = truewidth>>8;
buffer[14] = trueheight&255;
buffer[15] = trueheight>>8;
buffer[16] = 24; // pixel size
vfsfile_t *vfs;
FS_CreatePath(filename, FS_GAMEONLY);
vfs = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
if (vfs)
{
unsigned char header[18];
memset (header, 0, 18);
header[2] = 2; // uncompressed type
header[12] = width&255;
header[13] = width>>8;
header[14] = height&255;
header[15] = height>>8;
header[16] = 24; // pixel size
VFS_WRITE(vfs, header, sizeof(header));
// swap rgb to bgr
c = 18+truewidth*trueheight*3;
for (i=18 ; i<c ; i+=3)
c = width*height*3;
for (i=0 ; i<c ; i+=3)
{
temp = buffer[i];
buffer[i] = buffer[i+2];
buffer[i+2] = temp;
temp = ((qbyte*)rgb_buffer)[i];
((qbyte*)rgb_buffer)[i] = ((qbyte*)rgb_buffer)[i+2];
((qbyte*)rgb_buffer)[i+2] = temp;
}
VFS_WRITE(vfs, rgb_buffer, c);
VFS_CLOSE(vfs);
}
COM_WriteFile (filename, buffer, truewidth*trueheight*3 + 18 );
buffer-=MAX_PREPAD-18;
}
BZ_Free (buffer);
return true;
}
@ -1971,6 +1967,8 @@ void SCR_ScreenShot_f (void)
char pcxname[80];
int i;
vfsfile_t *vfs;
void *rgbbuffer;
int width, height;
if (!VID_GetRGBInfo)
{
@ -2015,10 +2013,18 @@ void SCR_ScreenShot_f (void)
FS_NativePath(pcxname, FS_GAMEONLY, sysname, sizeof(sysname));
if (SCR_ScreenShot(pcxname))
rgbbuffer = VID_GetRGBInfo(0, &width, &height);
if (rgbbuffer)
{
if (SCR_ScreenShot(pcxname, rgbbuffer, width, height))
{
Con_Printf ("Wrote %s\n", sysname);
else
Con_Printf ("Screenshot failed\n");
BZ_Free(rgbbuffer);
return;
}
BZ_Free(rgbbuffer);
}
Con_Printf ("Couldn't write %s\n", sysname);
}

View file

@ -1165,8 +1165,8 @@ void CL_ParseTEnt (void)
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 150 + r_explosionlight.value*200;
dl->die = cl.time + 1;
dl->decay = 300;
dl->die = cl.time + 0.75;
dl->decay = dl->radius*2;
dl->color[0] = 4.0;
dl->color[1] = 2.0;
@ -2890,7 +2890,7 @@ void CL_UpdateBeams (void)
int i, j;
beam_t *b;
vec3_t dist, org;
float *vieworg;
float *vieworg, *viewang;
float d;
entity_t *ent;
entity_state_t *st;
@ -2937,11 +2937,20 @@ void CL_UpdateBeams (void)
float delta, f, len;
if (cl.spectator && autocam[j])
{
{ //if we're tracking someone, use their origin explicitly.
vieworg = pl->origin;
}
else
vieworg = cl.playerview[j].simorg;
viewang = cl.playerview[j].simangles;
if (cl_truelightning.ival >= 2 && cls.netchan.outgoing_sequence > cl_truelightning.ival)
{
frame_t *frame = &cl.frames[(cls.netchan.outgoing_sequence-cl_truelightning.ival)&UPDATE_MASK];
viewang = frame->playerstate[cl.playernum[j]].viewangles;
viewang[0] = (frame->playerstate[cl.playernum[j]].command.angles[0] * 360) / 65336.0;
viewang[1] = (frame->playerstate[cl.playernum[j]].command.angles[1] * 360) / 65336.0;
}
VectorCopy (vieworg, b->start);
b->start[2] += cl.crouch[j] + bound(-7, v_viewheight.value, 4);
@ -2960,10 +2969,10 @@ void CL_UpdateBeams (void)
ang[0] = -ang[0];
if (ang[0] < -180)
ang[0] += 360;
ang[0] += (cl.playerview[j].simangles[0] - ang[0]) * f;
ang[0] += (viewang[0] - ang[0]) * f;
// lerp yaw
delta = cl.playerview[j].simangles[1] - ang[1];
delta = viewang[1] - ang[1];
if (delta > 180)
delta -= 360;
if (delta < -180)
@ -2974,7 +2983,7 @@ void CL_UpdateBeams (void)
AngleVectors (ang, fwd, ang, ang);
VectorCopy(fwd, ang);
VectorScale (fwd, len, fwd);
VectorCopy (cl.playerview[j].simorg, org);
VectorCopy (vieworg, org);
org[2] += 16;
VectorAdd (org, fwd, b->end);

View file

@ -1166,7 +1166,7 @@ void CLHL_LoadClientGame(void)
memset(&CLHL_cgamefuncs, 0, sizeof(CLHL_cgamefuncs));
clg = Sys_LoadLibrary("C:/Incoming/d/Half-Life/sdks/hlsdk-2.3-p3/hlsdk-2.3-p3/multiplayer/cl_dll/Debug/client", funcs);
clg = NULL;//Sys_LoadLibrary("C:/Incoming/d/Half-Life/sdks/hlsdk-2.3-p3/hlsdk-2.3-p3/multiplayer/cl_dll/Debug/client", funcs);
if (!clg)
{
path = NULL;

View file

@ -378,11 +378,13 @@ typedef struct
enum {DL_NONE, DL_QW, DL_QWCHUNKS, DL_Q3, DL_DARKPLACES, DL_QWPENDING, DL_HTTP, DL_FTP} downloadmethod;
vfsfile_t *downloadqw; // file transfer from server
char downloadtempname[MAX_OSPATH];
char downloadlocalname[MAX_OSPATH];
char downloadremotename[MAX_OSPATH];
int downloadpercent;
int downloadchunknum;
char downloadtempname[MAX_OSPATH]; //file its currently writing to.
char downloadlocalname[MAX_OSPATH]; //file its going to be renamed to.
char downloadremotename[MAX_OSPATH]; //file its coming from.
float downloadpercent; //for progress indicator.
int downloadchunknum; //for QW downloads only.
float downloadstarttime; //for speed info
unsigned int downloadedbytes; //number of bytes downloaded, for progress/speed info
// demo loop control
int demonum; // -1 = don't play demos
@ -822,6 +824,9 @@ void CL_SetInfo (int pnum, char *key, char *value);
void CL_BeginServerConnect(int port);
char *CL_TryingToConnect(void);
void CL_ExecInitialConfigs(void);
qboolean CL_CheckBootDownloads(void);
#define MAX_VISEDICTS 2048
extern int cl_numvisedicts;
extern entity_t cl_visedicts[];
@ -1347,6 +1352,14 @@ typedef struct
void (VARGS *getsize) (void *ctx, int *width, int *height);
void (VARGS *changestream) (void *ctx, char *streamname);
} media_decoder_funcs_t;
typedef struct {
void *(VARGS *capture_begin) (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits);
void (VARGS *capture_video) (void *ctx, void *data, int frame, int width, int height);
void (VARGS *capture_audio) (void *ctx, void *data, int bytes);
void (VARGS *capture_end) (void *ctx);
} media_encoder_funcs_t;
extern struct plugin_s *currentplug;
qboolean Media_RegisterDecoder(struct plugin_s *plug, media_decoder_funcs_t *funcs);
qboolean Media_UnregisterDecoder(struct plugin_s *plug, media_decoder_funcs_t *funcs);
qboolean Media_RegisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs);
qboolean Media_UnregisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs);

View file

@ -24,10 +24,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
console_t con_main;
console_t *con_current; // points to whatever is the visible console
console_t *con_chat; // points to a chat console
conline_t *con_footerline; //temp text at the bottom of the console
#define Font_ScreenWidth() (vid.pixelwidth)
static int Con_DrawProgress(int left, int right, int y);
static int Con_DrawConsoleLines(conline_t *l, int sx, int ex, int y, int top, qboolean selactive, int selsx, int selex, int selsy, int seley);
#ifdef QTERM
#include <windows.h>
@ -66,11 +68,6 @@ cvar_t con_separatechat = CVAR("con_separatechat", "0");
#define NUM_CON_TIMES 24
#define MAXCMDLINE 256
extern unsigned char key_lines[32][MAXCMDLINE];
extern int edit_line;
extern int key_linepos;
static conline_t *selstartline, *selendline;
static unsigned int selstartoffset, selendoffset;
@ -163,6 +160,14 @@ console_t *Con_Create(char *name, unsigned int flags)
void Con_SetActive (console_t *con)
{
con_current = con;
if (con_footerline)
{
selstartline = NULL;
selendline = NULL;
Z_Free(con_footerline);
con_footerline = NULL;
}
}
/*for enumerating consoles*/
qboolean Con_NameForNum(int num, char *buffer, int buffersize)
@ -357,6 +362,55 @@ void Key_ClearTyping (void)
key_linepos = 1;
}
void Con_History_Load(void)
{
unsigned char *cr;
vfsfile_t *file = FS_OpenVFS("conhistory.txt", "rb", FS_ROOT);
for (edit_line=0 ; edit_line<=CON_EDIT_LINES_MASK ; edit_line++)
{
key_lines[edit_line][0] = ']';
key_lines[edit_line][1] = 0;
}
edit_line = 0;
key_linepos = 1;
if (file)
{
while (VFS_GETS(file, key_lines[edit_line]+1, sizeof(key_lines[edit_line])-1))
{
//strip a trailing \r if its from windows.
cr = key_lines[edit_line] + strlen(key_lines[edit_line]);
if (cr > key_lines[edit_line] && cr[-1] == '\r')
cr[-1] = '\0';
edit_line = (edit_line + 1) & CON_EDIT_LINES_MASK;
}
VFS_CLOSE(file);
}
history_line = edit_line;
}
void Con_History_Save(void)
{
vfsfile_t *file = FS_OpenVFS("conhistory.txt", "wb", FS_ROOT);
int line;
if (file)
{
line = edit_line - CON_EDIT_LINES_MASK;
if (line < 0)
line = 0;
for(; line < edit_line; line++)
{
VFS_PUTS(file, key_lines[line]+1);
#ifdef _WIN32 //use an \r\n for readability with notepad.
VFS_PUTS(file, "\r\n");
#else
VFS_PUTS(file, "\n");
#endif
}
VFS_CLOSE(file);
}
}
/*
================
Con_ToggleConsole_f
@ -539,12 +593,20 @@ void Con_Init (void)
void Con_Shutdown(void)
{
Con_History_Save();
while(con_main.next)
{
Con_Destroy(con_main.next);
}
con_initialized = false;
Con_Destroy(&con_main);
selstartline = NULL;
selendline = NULL;
if (con_footerline)
Z_Free(con_footerline);
con_footerline = NULL;
}
void TTS_SayConString(conchar_t *stringtosay);
@ -793,6 +855,47 @@ void VARGS Con_DPrintf (char *fmt, ...)
Con_PrintCon(&con_main, msg);
}
/*description text at the bottom of the console*/
void Con_Footerf(qboolean append, char *fmt, ...)
{
va_list argptr;
char msg[MAXPRINTMSG];
conchar_t marked[MAXPRINTMSG], *markedend;
int oldlen, newlen;
conline_t *newf;
va_start (argptr,fmt);
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
va_end (argptr);
markedend = COM_ParseFunString(COLOR_YELLOW << CON_FGSHIFT, msg, marked, sizeof(marked), false);
newlen = markedend - marked;
if (append)
oldlen = con_footerline->length;
else
oldlen = 0;
if (!newlen && !oldlen)
newf = NULL;
else
{
newf = Z_Malloc(sizeof(*newf) + (oldlen + newlen) * sizeof(conchar_t));
if (con_footerline)
memcpy(newf, con_footerline, sizeof(*con_footerline)+oldlen*sizeof(conchar_t));
markedend = (void*)(newf+1);
markedend += oldlen;
memcpy(markedend, marked, newlen*sizeof(conchar_t));
newf->length = oldlen + newlen;
}
if (selstartline == con_footerline)
selstartline = NULL;
if (selendline == con_footerline)
selendline = NULL;
Z_Free(con_footerline);
con_footerline = newf;
}
/*
==============================================================================
@ -811,7 +914,7 @@ y is the bottom of the input
return value is the top of the region
================
*/
int Con_DrawInput (int left, int right, int y)
int Con_DrawInput (int left, int right, int y, qboolean selactive, int selsx, int selex, int selsy, int seley)
{
#ifdef _WIN32
extern qboolean ActiveApp;
@ -869,7 +972,7 @@ int Con_DrawInput (int left, int right, int y)
{
int cmdstart;
cmdstart = text[1] == '/'?2:1;
fname = Cmd_CompleteCommand(text+cmdstart, true, true, con_commandmatch);
fname = Cmd_CompleteCommand(text+cmdstart, true, true, con_commandmatch, NULL);
if (fname) //we can compleate it to:
{
for (p = min(strlen(fname), key_linepos-cmdstart); fname[p]>' '; p++)
@ -931,43 +1034,9 @@ int Con_DrawInput (int left, int right, int y)
}
/*if its getting completed to something, show some help about the command that is going to be used*/
if (!text[1])
con_commandmatch = 0;
if (con_commandmatch && fname && Cmd_IsCommand(text+(text[1] == '/'?2:1)))
if (con_footerline)
{
cvar_t *var;
char *desc = NULL;
if (!desc)
{
var = Cvar_FindVar(fname);
if (var && var->description)
desc = var->description;
}
if (!desc)
{
desc = Cmd_Describe(fname);
}
if (desc)
{
int lines;
conchar_t *starts[8];
conchar_t *ends[8];
conchar_t *end;
end = maskedtext;
end = COM_ParseFunString((COLOR_YELLOW<<CON_FGSHIFT), va("%s: %s", fname, desc), end, (maskedtext+sizeof(maskedtext)/sizeof(maskedtext[0])-1-end)*sizeof(maskedtext[0]), true);
lines = Font_LineBreaks(maskedtext, end, right - left, 8, starts, ends);
while(lines-->0)
{
rhs = left;
y -= Font_CharHeight();
for (cchar = starts[lines]; cchar < ends[lines]; cchar++)
{
rhs = Font_DrawChar(rhs, y, *cchar);
}
}
}
y = Con_DrawConsoleLines(con_footerline, left, right, y, 0, selactive, selsx, selex, selsy, seley);
}
/*just above that, we have the tab completion list*/
@ -984,7 +1053,7 @@ int Con_DrawInput (int left, int right, int y)
for (i = 1; ; i++)
{
cmd = Cmd_CompleteCommand (text+cmdstart, true, true, i);
cmd = Cmd_CompleteCommand (text+cmdstart, true, true, i, NULL);
if (!cmd)
break;
@ -1188,20 +1257,13 @@ static int Con_DrawProgress(int left, int right, int y)
progresstext = cls.downloadlocalname;
progresspercent = cls.downloadpercent;
if ((int)(realtime/2)&1)
sprintf(progresspercenttext, " %02d%% (%ukbps)", (int)progresspercent, CL_DownloadRate()/1000);
else
{
CL_GetDownloadSizes(&count, &total, &extra);
if (total == 0)
{
//just show progress
sprintf(progresspercenttext, " %02f%%", progresspercent);
}
if ((int)(realtime/2)&1 || total == 0)
sprintf(progresspercenttext, " %5.1f%% (%ukbps)", progresspercent, CL_DownloadRate()/1000);
else
{
sprintf(progresspercenttext, " %02d%% (%u%skb)", (int)progresspercent, total/1024, extra?"+":"");
}
sprintf(progresspercenttext, " %5.1f%% (%u%skb)", progresspercent, total/1024, extra?"+":"");
}
}
#ifdef RUNTIMELIGHTING
@ -1342,72 +1404,40 @@ int Con_DrawAlternateConsoles(int lines)
return y;
}
/*
================
Con_DrawConsole
Draws the console with the solid background
================
*/
void Con_DrawConsole (int lines, qboolean noback)
//draws the conline_t list bottom-up within the width of the screen until the top of the screen is reached.
//if text is selected, the selstartline globals will be updated, so make sure the lines persist or check them.
static int Con_DrawConsoleLines(conline_t *l, int sx, int ex, int y, int top, qboolean selactive, int selsx, int selex, int selsy, int seley)
{
extern qboolean scr_con_forcedraw;
int x, y, sx, ex, linecount, linelength;
conline_t *l;
conchar_t *s;
int selsx, selsy, selex, seley, selactive;
int top;
int linecount;
int linelength;
conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])];
conchar_t *s;
int i;
qboolean haveprogress;
int hidelines;
int x;
if (lines <= 0)
return;
#ifdef QTERM
if (qterms)
QT_Update();
#endif
// draw the background
if (!noback)
R2D_ConsoleBackground (0, lines, scr_con_forcedraw);
con_current->unseentext = false;
con_current->vislines = lines;
top = Con_DrawAlternateConsoles(lines);
x = 8;
y = lines;
selactive = Key_GetConsoleSelectionBox(&selsx, &selsy, &selex, &seley);
Font_BeginString(font_conchar, x, y, &x, &y);
Font_BeginString(font_conchar, selsx, selsy, &selsx, &selsy);
Font_BeginString(font_conchar, selex, seley, &selex, &seley);
ex = Font_ScreenWidth();
sx = x;
ex -= sx;
y -= Font_CharHeight();
haveprogress = Con_DrawProgress(x, ex - x, y) != y;
y = Con_DrawInput (x, ex - x, y);
//deactivate the selection if the start and end is outside
if (
(selsx < sx && selex < sx) ||
(selsx > ex && selex > ex) ||
(selsy < top && seley < top) ||
(selsy > y && seley > y)
)
selactive = false;
if (selactive)
{
if (selsx < x)
selsx = x;
if (selex < x)
selex = x;
//clip it
if (selsx < sx)
selsx = sx;
if (selex < sx)
selex = sx;
if (selsy > y)
selsy = y;
if (seley > y)
seley = y;
//scale the y coord to be in lines instead of pixels
selsy -= y;
seley -= y;
selsy /= Font_CharHeight();
@ -1415,6 +1445,7 @@ void Con_DrawConsole (int lines, qboolean noback)
selsy--;
seley--;
//invert the selections to make sense, text-wise
if (selsy == seley)
{
//single line selected backwards
@ -1441,19 +1472,6 @@ void Con_DrawConsole (int lines, qboolean noback)
seley += y;
}
if (!con_current->display)
con_current->display = con_current->current;
l = con_current->display;
hidelines = con_current->subline;
if (l != con_current->current)
{
y -= 8;
// draw arrows to show the buffer is backscrolled
for (x = sx ; x<ex; )
x = (Font_DrawChar (x, y, '^'|CON_WHITEMASK)-x)*4+x;
}
if (l && l == con_current->current && l->length == 0)
l = l->older;
for (; l; l = l->older)
@ -1470,14 +1488,6 @@ void Con_DrawConsole (int lines, qboolean noback)
}
l->lines = linecount;
if (hidelines > 0)
{
linecount -= hidelines;
if (linecount < 0)
linecount = 0;
hidelines -= linecount;
}
while (linecount-- > 0)
{
s = starts[linecount];
@ -1554,6 +1564,74 @@ void Con_DrawConsole (int lines, qboolean noback)
if (y < top)
break;
}
return y;
}
/*
================
Con_DrawConsole
Draws the console with the solid background
================
*/
void Con_DrawConsole (int lines, qboolean noback)
{
extern qboolean scr_con_forcedraw;
int x, y, sx, ex;
conline_t *l;
int selsx, selsy, selex, seley, selactive;
int top;
qboolean haveprogress;
if (lines <= 0)
return;
#ifdef QTERM
if (qterms)
QT_Update();
#endif
// draw the background
if (!noback)
R2D_ConsoleBackground (0, lines, scr_con_forcedraw);
con_current->unseentext = false;
con_current->vislines = lines;
top = Con_DrawAlternateConsoles(lines);
x = 8;
y = lines;
selstartline = NULL;
selendline = NULL;
selactive = Key_GetConsoleSelectionBox(&selsx, &selsy, &selex, &seley);
Font_BeginString(font_conchar, x, y, &x, &y);
Font_BeginString(font_conchar, selsx, selsy, &selsx, &selsy);
Font_BeginString(font_conchar, selex, seley, &selex, &seley);
ex = Font_ScreenWidth();
sx = x;
ex -= sx;
y -= Font_CharHeight();
haveprogress = Con_DrawProgress(x, ex - x, y) != y;
y = Con_DrawInput (x, ex - x, y, selactive, selsx, selex, selsy, seley);
if (!con_current->display)
con_current->display = con_current->current;
l = con_current->display;
if (l != con_current->current)
{
y -= 8;
// draw arrows to show the buffer is backscrolled
for (x = sx ; x<ex; )
x = (Font_DrawChar (x, y, '^'|CON_WHITEMASK)-x)*4+x;
}
y = Con_DrawConsoleLines(l, sx, ex, y, top, selactive, selsx, selex, selsy, seley);
if (!haveprogress && lines == vid.height)
{

View file

@ -7,6 +7,12 @@
//#include "d3dquake.h"
#endif
#ifdef NPFTE
//#define Con_Printf(f, ...)
//hope you're on a littleendian machine
#define LittleShort(s) s
#define LittleLong(s) s
#else
cvar_t r_dodgytgafiles = SCVAR("r_dodgytgafiles", "0"); //Certain tgas are upside down.
//This is due to a bug in tenebrae.
//(normally) the textures are actually the right way around.
@ -16,6 +22,7 @@ cvar_t r_dodgytgafiles = SCVAR("r_dodgytgafiles", "0"); //Certain tgas are upsid
cvar_t r_dodgypcxfiles = SCVAR("r_dodgypcxfiles", "0"); //Quake 2's PCX loading isn't complete,
//and some Q2 mods include PCX files
//that only work with this assumption
#endif
#ifndef _WIN32
#include <unistd.h>
@ -66,9 +73,10 @@ char *ReadGreyTargaFile (qbyte *data, int flen, tgaheader_t *tgahead, int asgrey
numPixels = columns * rows;
flipped = !((tgahead->attribs & 0x20) >> 5);
#ifndef NPFTE
if (r_dodgytgafiles.value)
flipped = true;
#endif
if (tgahead->version == 1)
{
@ -173,8 +181,10 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *
tgaheader.attribs = buf[17];
flipped = !((tgaheader.attribs & 0x20) >> 5);
#ifndef NPFTE
if (r_dodgytgafiles.value)
flipped = true;
#endif
data=buf+18;
data += tgaheader.id_len;
@ -872,7 +882,7 @@ error:
#ifndef NPFTE
int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, int height)
{
char name[MAX_OSPATH];
@ -940,6 +950,7 @@ err:
fclose(fp);
return true;
}
#endif
#endif
@ -1340,6 +1351,7 @@ badjpeg:
}
/*end read*/
#ifndef NPFTE
/*begin write*/
#define OUTPUT_BUF_SIZE 4096
typedef struct {
@ -1503,8 +1515,9 @@ void screenshotJPEG(char *filename, int compression, qbyte *screendata, int scre
#endif
}
#endif
#endif
#ifndef NPFTE
/*
==============
WritePCXfile
@ -1575,7 +1588,7 @@ void WritePCXfile (const char *filename, qbyte *data, int width, int height,
else
COM_WriteFile (filename, pcx, length);
}
#endif
/*
@ -1622,9 +1635,11 @@ qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height)
*width = swidth;
*height = sheight;
#ifndef NPFTE
if (r_dodgypcxfiles.value)
palette = host_basepal;
else
#endif
palette = buf + length-768;
data = (char *)(pcx+1);
@ -2054,6 +2069,10 @@ qbyte *ReadBMPFile(qbyte *buf, int length, int *width, int *height)
return NULL;
}*/
#ifndef NPFTE
// saturate function, stolen from jitspoe
void SaturateR8G8B8(qbyte *data, int size, float sat)
{
@ -2214,14 +2233,14 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
divsize = 4;
blocksize = 8;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT3")
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT2" || *(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT3")
{
intfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
pad = 8;
divsize = 4;
blocksize = 16;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT5")
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT4" || *(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT5")
{
intfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
pad = 8;
@ -2458,6 +2477,20 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
return tex;
}
#ifdef DDS
snprintf(fname, sizeof(fname)-1, "dds/%s.dds", nicename); /*should be safe if its null*/
if ((buf = COM_LoadFile (fname, 5)))
{
tex = GL_LoadTextureDDS(name, buf, com_filesize);
if (TEXVALID(tex))
{
BZ_Free(buf);
return tex;
}
BZ_Free(buf);
}
#endif
if (strchr(name, '/')) //never look in a root dir for the pic
i = 0;
else
@ -2489,7 +2522,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
if ((buf = COM_LoadFile (fname, 5)))
{
#ifdef DDS
tex = GL_LoadTextureDDS(fname, buf, com_filesize);
tex = GL_LoadTextureDDS(name, buf, com_filesize);
if (TEXVALID(tex))
{
BZ_Free(buf);
@ -2746,3 +2779,4 @@ void AddOcranaLEDsIndexed (qbyte *image, int h, int w)
}
}
}
#endif

View file

@ -403,7 +403,6 @@ static void INS_ActivateMouse (void)
ClipCursor (&window_rect);
}
Con_Printf("Mouse grabbed\n");
mouseactive = true;
}
}
@ -465,7 +464,6 @@ static void INS_DeactivateMouse (void)
ReleaseCapture ();
}
Con_Printf("Mouse released\n");
mouseactive = false;
}
}
@ -1220,7 +1218,7 @@ void INS_MouseMove (float *movements, int pnum)
extern int window_x, window_y;
#ifdef AVAIL_DINPUT
if (dinput)
if (dinput && mouseactive)
{
DIDEVICEOBJECTDATA od;
DWORD dwElements;

View file

@ -30,7 +30,7 @@ void Editor_Key(int key, int unicode);
#define KEY_MODIFIERSTATES 8
#define MAXCMDLINE 256
unsigned char key_lines[32][MAXCMDLINE];
unsigned char key_lines[CON_EDIT_LINES_MASK+1][MAXCMDLINE];
int key_linepos;
int shift_down=false;
int key_lastpress;
@ -245,7 +245,7 @@ qboolean Cmd_IsCommand (char *line)
command[i] = s[i];
command[i] = 0;
cmd = Cmd_CompleteCommand (command, true, false, -1);
cmd = Cmd_CompleteCommand (command, true, false, -1, NULL);
if (!cmd || strcmp (cmd, command) )
return false; // just a chat message
return true;
@ -268,18 +268,19 @@ void CompleteCommand (qboolean force)
{
int i;
char *cmd, *s;
char *desc;
s = key_lines[edit_line]+1;
if (*s == '\\' || *s == '/')
s++;
cmd = Cmd_CompleteCommand (s, true, true, 2);
cmd = Cmd_CompleteCommand (s, true, true, 2, NULL);
if (!cmd || force)
{
if (!force)
cmd = Cmd_CompleteCommand (s, false, true, 1);
cmd = Cmd_CompleteCommand (s, false, true, 1, &desc);
else
cmd = Cmd_CompleteCommand (s, true, true, con_commandmatch);
cmd = Cmd_CompleteCommand (s, true, true, con_commandmatch, &desc);
if (cmd)
{
key_lines[edit_line][1] = '/';
@ -292,7 +293,7 @@ void CompleteCommand (qboolean force)
// if (strlen(cmd)>strlen(s))
{
cmd = Cmd_CompleteCommand (s, true, true, 0);
cmd = Cmd_CompleteCommand (s, true, true, 0, NULL);
if (cmd && !strcmp(s, cmd)) //also a compleate var
{
key_lines[edit_line][key_linepos] = ' ';
@ -302,10 +303,13 @@ void CompleteCommand (qboolean force)
key_lines[edit_line][key_linepos] = 0;
if (!con_commandmatch)
con_commandmatch = 1;
if (desc)
Con_Footerf(false, "%s: %s", cmd, desc);
return;
}
}
cmd = Cmd_CompleteCommand (s, false, true, 0);
cmd = Cmd_CompleteCommand (s, false, true, 0, &desc);
if (cmd)
{
i = key_lines[edit_line][1] == '/'?2:1;
@ -323,14 +327,26 @@ void CompleteCommand (qboolean force)
if (!con_commandmatch)
con_commandmatch = 1;
if (desc)
Con_Footerf(false, "%s: %s", cmd, desc);
return; //don't alter con_commandmatch if we compleated a tiny bit more
}
}
con_commandmatch++;
if (!Cmd_CompleteCommand(s, true, true, con_commandmatch))
if (Cmd_CompleteCommand(s, true, true, con_commandmatch, &desc))
{
if (desc)
Con_Footerf(false, "%s: %s", cmd, desc);
}
else
{
Con_Footerf(false, "");
con_commandmatch = 1;
}
}
//lines typed at the main console enter here
void Con_ExecuteLine(console_t *con, char *line)
@ -338,6 +354,8 @@ void Con_ExecuteLine(console_t *con, char *line)
qboolean waschat = false;
con_commandmatch=1;
Con_Footerf(false, "");
if (cls.state >= ca_connected && cl_chatmode.value == 2)
{
waschat = true;
@ -451,6 +469,192 @@ void Key_ConsoleInsert(char *instext)
}
}
void Key_DefaultLinkClicked(char *text, char *info)
{
char *c;
/*the engine supports specific default links*/
/*we don't support everything. a: there's no point. b: unbindall links are evil.*/
c = Info_ValueForKey(info, "player");
if (*c)
{
unsigned int player = atoi(c);
int i;
if (player >= MAX_CLIENTS || !*cl.players[player].name)
return;
c = Info_ValueForKey(info, "action");
if (*c)
{
if (!strcmp(c, "mute"))
{
if (!cl.players[player].vignored)
{
cl.players[player].vignored = true;
Con_Printf("^[%s\\player\\%i^] muted\n", cl.players[player].name, player);
}
else
{
cl.players[player].vignored = false;
Con_Printf("^[%s\\player\\%i^] unmuted\n", cl.players[player].name, player);
}
}
else if (!strcmp(c, "ignore"))
{
if (!cl.players[player].ignored)
{
cl.players[player].ignored = true;
cl.players[player].vignored = true;
Con_Printf("^[%s\\player\\%i^] ignored\n", cl.players[player].name, player);
}
else
{
cl.players[player].ignored = false;
cl.players[player].vignored = false;
Con_Printf("^[%s\\player\\%i^] unignored\n", cl.players[player].name, player);
}
}
else if (!strcmp(c, "spec"))
{
Cam_TrackPlayer(0, "spectate", cl.players[player].name);
}
else if (!strcmp(c, "kick"))
{
#ifndef CLIENTONLY
if (sv.active)
{
//use the q3 command, because we can.
Cbuf_AddText(va("\nclientkick %i\n", player), RESTRICT_LOCAL);
}
else
#endif
Cbuf_AddText(va("\nrcon kick %s\n", cl.players[player].name), RESTRICT_LOCAL);
}
else if (!strcmp(c, "ban"))
{
#ifndef CLIENTONLY
if (sv.active)
{
//use the q3 command, because we can.
Cbuf_AddText(va("\nbanname %s QuickBan\n", cl.players[player].name), RESTRICT_LOCAL);
}
else
#endif
Cbuf_AddText(va("\nrcon banname %s QuickBan\n", cl.players[player].name), RESTRICT_LOCAL);
}
return;
}
Con_Footerf(false, "^m#^m ^[%s\\player\\%i^]: %if %ims", cl.players[player].name, player, cl.players[player].frags, cl.players[player].ping);
for (i = 0; i < cl.splitclients; i++)
{
if (cl.playernum[i] == player)
break;
}
if (i == cl.splitclients)
{
extern cvar_t rcon_password;
if (cl.spectator || cls.demoplayback)
{
//we're spectating, or an mvd
Con_Footerf(true, " ^[Spectate\\player\\%i\\action\\spec^]", player);
}
else
{
//we're playing.
if (cls.protocol == CP_QUAKEWORLD && strcmp(cl.players[cl.playernum[0]].team, cl.players[player].team))
Con_Footerf(true, " ^[[Join Team %s]\\cmd\\setinfo team %s^]", cl.players[player].team, cl.players[player].team);
}
Con_Footerf(true, " ^[%sgnore\\player\\%i\\action\\ignore^]", cl.players[player].ignored?"Uni":"I", player);
// if (cl_voip_play.ival)
Con_Footerf(true, " ^[%sute\\player\\%i\\action\\mute^]", cl.players[player].vignored?"Unm":"M", player);
if (!cls.demoplayback && (*rcon_password.string
#ifndef CLIENTONLY
|| (sv.state && svs.clients[player].netchan.remote_address.type != NA_LOOPBACK)
#endif
))
{
Con_Footerf(true, " ^[Kick\\player\\%i\\action\\kick^]", player);
Con_Footerf(true, " ^[Ban\\player\\%i\\action\\ban^]", player);
}
}
else
{
char cmdprefix[6];
snprintf(cmdprefix, sizeof(cmdprefix), "%i ", i);
//hey look! its you!
if (cl.spectator || cls.demoplayback)
{
//need join option here or something
}
else
{
Con_Footerf(true, " ^[Suicide\\cmd\\kill^]");
#ifndef CLIENTONLY
if (!sv.state)
Con_Footerf(true, " ^[Disconnect\\cmd\\disconnect^]");
if (cls.allow_cheats || (sv.state && sv.allocated_client_slots == 1))
#else
Con_Footerf(true, " ^[Disconnect\\cmd\\disconnect^]");
if (cls.allow_cheats)
#endif
{
Con_Footerf(true, " ^[Noclip\\cmd\\noclip^]");
Con_Footerf(true, " ^[Fly\\cmd\\fly^]");
Con_Footerf(true, " ^[God\\cmd\\god^]");
Con_Footerf(true, " ^[Give\\impulse\\9^]");
}
}
}
return;
}
c = Info_ValueForKey(info, "desc");
if (*c)
{
Con_Footerf(false, "%s", c);
return;
}
c = Info_ValueForKey(info, "connect");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nconnect %s\n", c), RESTRICT_LOCAL);
return;
}
c = Info_ValueForKey(info, "qtv");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nqtvplay %s\n", c), RESTRICT_LOCAL);
return;
}
c = Info_ValueForKey(info, "demo");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nplaydemo %s\n", c), RESTRICT_LOCAL);
return;
}
c = Info_ValueForKey(info, "cmd");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\ncmd %s\n", c), RESTRICT_LOCAL);
return;
}
c = Info_ValueForKey(info, "impulse");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nimpulse %s\n", c), RESTRICT_LOCAL);
return;
}
if (!*info && *text == '/')
{
Q_strncpyz(key_lines[edit_line]+1, text, sizeof(key_lines[edit_line])-1);
key_linepos = strlen(key_lines[edit_line]);
return;
}
}
void Key_ConsoleRelease(int key, int unicode)
{
extern int mousecursor_x, mousecursor_y;
@ -461,6 +665,7 @@ void Key_ConsoleRelease(int key, int unicode)
if (abs(con_mousedown[0] - mousecursor_x) < 5 && abs(con_mousedown[1] - mousecursor_y) < 5)
{
buffer = Con_CopyConsole(false);
Con_Footerf(false, "");
if (!buffer)
return;
if (keydown[K_SHIFT])
@ -506,156 +711,13 @@ void Key_ConsoleRelease(int key, int unicode)
{
if (end[0] == '^' && end[1] == ']')
{
char *c;
//okay, its a valid link that they clicked
*end = 0;
#ifdef CSQC_DAT
if (!CSQC_ConsoleLink(buffer+2, info))
#endif
{
/*the engine supports specific default links*/
/*we don't support everything. a: there's no point. b: unbindall links are evil.*/
c = Info_ValueForKey(info, "player");
if (*c)
{
unsigned int player = atoi(c);
int i;
if (player >= MAX_CLIENTS)
break;
c = Info_ValueForKey(info, "action");
if (*c)
{
if (!strcmp(c, "mute"))
{
if (!cl.players[player].vignored)
{
cl.players[player].vignored = true;
Con_Printf("^[%s\\player\\%i^] muted\n", cl.players[player].name, player);
}
else
{
cl.players[player].vignored = false;
Con_Printf("^[%s\\player\\%i^] unmuted\n", cl.players[player].name, player);
}
}
else if (!strcmp(c, "ignore"))
{
if (!cl.players[player].ignored)
{
cl.players[player].ignored = true;
cl.players[player].vignored = true;
Con_Printf("^[%s\\player\\%i^] ignored\n", cl.players[player].name, player);
}
else
{
cl.players[player].ignored = false;
cl.players[player].vignored = false;
Con_Printf("^[%s\\player\\%i^] unignored\n", cl.players[player].name, player);
}
}
else if (!strcmp(c, "kick"))
{
#ifndef CLIENTONLY
if (sv.active)
{
//use the q3 command, because we can.
Cbuf_AddText(va("\nclientkick %i\n", player), RESTRICT_LOCAL);
}
else
#endif
Cbuf_AddText(va("\nrcon kick %s\n", cl.players[player].name), RESTRICT_LOCAL);
}
else if (!strcmp(c, "ban"))
{
#ifndef CLIENTONLY
if (sv.active)
{
//use the q3 command, because we can.
Cbuf_AddText(va("\nbanname %s QuickBan\n", cl.players[player].name), RESTRICT_LOCAL);
}
else
#endif
Cbuf_AddText(va("\nrcon banname %s QuickBan\n", cl.players[player].name), RESTRICT_LOCAL);
}
break;
}
Con_Printf("^m#^m ^[%s\\player\\%i^]: %if %ims", cl.players[player].name, player, cl.players[player].frags, cl.players[player].ping);
for (i = 0; i < cl.splitclients; i++)
{
if (cl.playernum[i] == player)
break;
}
if (i == cl.splitclients)
{
extern cvar_t rcon_password;
if (cls.protocol == CP_QUAKEWORLD && strcmp(cl.players[cl.playernum[0]].team, cl.players[player].team))
Con_Printf(" ^[[Join Team %s]\\cmd\\setinfo team %s^]", cl.players[player].team, cl.players[player].team);
Con_Printf(" ^[%sgnore\\player\\%i\\action\\ignore^]", cl.players[player].ignored?"Uni":"I", player);
// if (cl_voip_play.ival)
Con_Printf(" ^[%sute\\player\\%i\\action\\mute^]", cl.players[player].vignored?"Unm":"M", player);
if (*rcon_password.string
#ifndef CLIENTONLY
|| (sv.state && svs.clients[player].netchan.remote_address.type != NA_LOOPBACK)
#endif
)
{
Con_Printf(" ^[Kick\\player\\%i\\action\\kick^]", player);
Con_Printf(" ^[Ban\\player\\%i\\action\\ban^]", player);
}
}
else
{
char cmdprefix[6];
snprintf(cmdprefix, sizeof(cmdprefix), "%i ", i);
//hey look! its you!
Con_Printf(" ^[Suicide\\cmd\\kill^]");
#ifndef CLIENTONLY
if (!sv.state)
Con_Printf(" ^[Disconnect\\cmd\\disconnect^]");
if (cls.allow_cheats || (sv.state && sv.allocated_client_slots == 1))
#else
Con_Printf(" ^[Disconnect\\cmd\\disconnect^]");
if (cls.allow_cheats)
#endif
{
Con_Printf(" ^[Noclip\\cmd\\noclip^]");
Con_Printf(" ^[Fly\\cmd\\fly^]");
Con_Printf(" ^[God\\cmd\\god^]");
Con_Printf(" ^[Give\\impulse\\9^]");
}
}
Con_Printf("\r");
break;
}
c = Info_ValueForKey(info, "connect");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nconnect %s\n", c), RESTRICT_LOCAL);
break;
}
c = Info_ValueForKey(info, "qtv");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nqtvplay %s\n", c), RESTRICT_LOCAL);
break;
}
c = Info_ValueForKey(info, "cmd");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\ncmd %s\n", c), RESTRICT_LOCAL);
break;
}
c = Info_ValueForKey(info, "impulse");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nimpulse %s\n", c), RESTRICT_LOCAL);
break;
}
Key_DefaultLinkClicked(buffer+2, info);
}
break;
@ -669,6 +731,8 @@ void Key_ConsoleRelease(int key, int unicode)
}
Z_Free(buffer);
}
else
Con_Footerf(false, "");
}
if (key == K_MOUSE2 && con_mousedown[2] == 2)
{
@ -700,7 +764,7 @@ unsigned char *utf_left(unsigned char *start, unsigned char *cursor)
if (*cursor == ']' && cursor > start && cursor[-1] == '^')
{
//just stepped onto a link
char *linkstart;
unsigned char *linkstart;
linkstart = cursor-1;
while(linkstart >= start)
{
@ -834,7 +898,7 @@ void Key_Console (unsigned int unicode, int key)
if (key == K_ENTER)
{ // backslash text are commands, else chat
int oldl = edit_line;
edit_line = (edit_line + 1) & 31;
edit_line = (edit_line + 1) & (CON_EDIT_LINES_MASK);
history_line = edit_line;
key_lines[edit_line][0] = ']';
key_lines[edit_line][1] = '\0';
@ -846,9 +910,12 @@ void Key_Console (unsigned int unicode, int key)
return;
}
if (key == K_SPACE && con_current->commandcompletion)
if (key == K_SPACE && keydown[K_CTRL] && con_current->commandcompletion)
{
if (keydown[K_CTRL] && Cmd_CompleteCommand(key_lines[edit_line]+1, true, true, con_current->commandcompletion))
char *txt = key_lines[edit_line]+1;
if (*txt == '/')
txt++;
if (Cmd_CompleteCommand(txt, true, true, con_current->commandcompletion, NULL))
{
CompleteCommand (true);
return;
@ -867,7 +934,7 @@ void Key_Console (unsigned int unicode, int key)
CompleteCommand (false);
return;
}
if (key != K_SHIFT && con_commandmatch)
if (key != K_CTRL && key != K_SHIFT && con_commandmatch)
con_commandmatch=1;
if (key == K_LEFTARROW)
@ -913,11 +980,11 @@ void Key_Console (unsigned int unicode, int key)
{
do
{
history_line = (history_line - 1) & 31;
history_line = (history_line - 1) & CON_EDIT_LINES_MASK;
} while (history_line != edit_line
&& !key_lines[history_line][1]);
if (history_line == edit_line)
history_line = (edit_line+1)&31;
history_line = (edit_line+1)&CON_EDIT_LINES_MASK;
Q_strcpy(key_lines[edit_line], key_lines[history_line]);
key_linepos = Q_strlen(key_lines[edit_line]);
@ -936,7 +1003,7 @@ void Key_Console (unsigned int unicode, int key)
}
do
{
history_line = (history_line + 1) & 31;
history_line = (history_line + 1) & CON_EDIT_LINES_MASK;
}
while (history_line != edit_line
&& !key_lines[history_line][1]);
@ -1105,7 +1172,7 @@ void Key_Console (unsigned int unicode, int key)
}
}
if (keydown[K_ALT])
if (keydown[K_ALT] && key > 32 && key < 128)
key |= 128; // red char
}
@ -1524,7 +1591,7 @@ void Key_Init (void)
{
int i;
for (i=0 ; i<32 ; i++)
for (i=0 ; i<=CON_EDIT_LINES_MASK ; i++)
{
key_lines[i][0] = ']';
key_lines[i][1] = 0;
@ -1611,9 +1678,9 @@ qboolean Key_MouseShouldBeFree(void)
//if true, the input code is expected to return mouse cursor positions rather than deltas
extern cvar_t cl_prydoncursor;
// extern int mouseusedforgui;
// if (mouseusedforgui) //I don't like this
// return true;
extern int mouseusedforgui;
if (mouseusedforgui) //I don't like this
return true;
// if (!ActiveApp)
// return true;

View file

@ -803,3 +803,173 @@ void Menu_DownloadStuff_f (void)
#endif
#ifdef AVAIL_ZLIB
static int numbootdownloads;
#include "fs.h"
extern searchpathfuncs_t zipfilefuncs;
static int CL_BootDownload_Extract(const char *fname, int fsize, void *ptr)
{
char buffer[512*1024];
int read;
void *zip = ptr;
flocation_t loc;
int slashes;
const char *s;
vfsfile_t *compressedpak;
vfsfile_t *decompressedpak;
if (zipfilefuncs.FindFile(zip, &loc, fname, NULL))
{
compressedpak = zipfilefuncs.OpenVFS(zip, &loc, "rb");
if (compressedpak)
{
//this extra logic is so we can handle things like nexuiz/data/blah.pk3
//as well as just data/blah.pk3
slashes = 0;
for (s = strchr(fname, '/'); s; s = strchr(s+1, '/'))
slashes++;
for (; slashes > 1; slashes--)
fname = strchr(fname, '/')+1;
if (!slashes)
{
FS_CreatePath(fname, FS_GAMEONLY);
decompressedpak = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
}
else
{
FS_CreatePath(fname, FS_ROOT);
decompressedpak = FS_OpenVFS(fname, "wb", FS_ROOT);
}
if (decompressedpak)
{
for(;;)
{
read = VFS_READ(compressedpak, buffer, sizeof(buffer));
if (read <= 0)
break;
if (VFS_WRITE(decompressedpak, buffer, read) != read)
{
Con_Printf("write failed writing %s. disk full?\n", fname);
break;
}
}
VFS_CLOSE(decompressedpak);
}
VFS_CLOSE(compressedpak);
}
}
return true;
}
static void CL_BootDownload_Complete(struct dl_download *dl)
{
void *zip;
/*
int sz;
char *buf;
FILE *f;
sz = VFS_GETLEN(dl->file);
buf = malloc(sz);
VFS_READ(dl->file, buf, sz);
f = fopen("C:/Games/Quake/test/emptybasedir/test.zip", "wb");
fwrite(buf, 1, sz, f);
fclose(f);
free(buf);
*/
if (dl->status == DL_FINISHED)
zip = zipfilefuncs.OpenNew(dl->file, dl->url);
else
zip = NULL;
/*the zip code will have eaten the file handle*/
dl->file = NULL;
if (zip)
{
/*scan it to extract its contents*/
zipfilefuncs.EnumerateFiles(zip, "*/*.pk3", CL_BootDownload_Extract, zip);
zipfilefuncs.EnumerateFiles(zip, "*/*.pak", CL_BootDownload_Extract, zip);
zipfilefuncs.EnumerateFiles(zip, "*/*/*.pk3", CL_BootDownload_Extract, zip);
zipfilefuncs.EnumerateFiles(zip, "*/*/*.pak", CL_BootDownload_Extract, zip);
/*close it, delete the temp file from disk, etc*/
zipfilefuncs.ClosePath(zip);
/*restart the filesystem so those new files can be found*/
Cmd_ExecuteString("fs_restart\n", RESTRICT_LOCAL);
}
if (!--numbootdownloads)
{
CL_ExecInitialConfigs();
Cmd_StuffCmds();
Cbuf_Execute ();
Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL);
}
}
qboolean CL_CheckBootDownloads(void)
{
char *downloads = fs_gamedownload.string;
char token[2048];
char *c, *s;
vfsfile_t *f;
struct dl_download *dl;
int mirrors;
while ((downloads = COM_ParseOut(downloads, token, sizeof(token))))
{
//FIXME: do we want to add some sort of file size indicator?
c = token;
while(*c && *c != ':' && *c != '|')
c++;
if (!*c) //erp?
continue;
*c++ = 0;
f = FS_OpenVFS(token, "rb", FS_ROOT);
if (f)
{
Con_DPrintf("Already have %s\n", token);
VFS_CLOSE(f);
continue;
}
mirrors = 1;
for (s = c; *s; s++)
{
if (*s == '|')
mirrors++;
}
mirrors = rand() % mirrors;
while(mirrors)
{
mirrors--;
while(*c != '|')
c++;
c++;
}
for (s = c; *s; s++)
{
if (*s == '|')
*s = 0;
}
Con_Printf("Attempting to download %s\n", c);
dl = HTTP_CL_Get(c, token, CL_BootDownload_Complete);
if (dl)
{
#ifdef MULTITHREAD
DL_CreateThread(dl, FS_OpenTemp(), CL_BootDownload_Complete);
#endif
numbootdownloads++;
}
}
return !numbootdownloads;
}
#else
qboolean CL_CheckBootDownloads(void)
{
return true;
}
#endif

View file

@ -14,6 +14,9 @@
#ifdef _WIN32
#define WINAMP
#endif
#if defined(_WIN32)
#define WINAVI
#endif
#ifdef WINAMP
@ -229,11 +232,13 @@ qboolean Media_FakeTrack(int i, qboolean loop)
sprintf(trackname, "sound/cdtracks/track%03i.ogg", i);
found = COM_FCheckExists(trackname);
}
#ifdef WINAVI
if (!found)
{
sprintf(trackname, "sound/cdtracks/track%03i.mp3", i);
found = COM_FCheckExists(trackname);
}
#endif
if (!found)
{
sprintf(trackname, "sound/cdtracks/track%03i.wav", i);
@ -756,10 +761,6 @@ char *Media_NextTrack(int musicchannelnum)
//Avi files are specific to windows. Bit of a bummer really.
#if defined(_WIN32)
#define WINAVI
#endif
@ -1405,6 +1406,7 @@ static qboolean Media_Plugin_DecodeFrame(cin_t *cin, qboolean nosound)
if (cin->outtype != TF_INVALID)
return true;
cin->ended = true;
return false;
}
static void Media_Plugin_DoneFrame(cin_t *cin)
@ -2357,33 +2359,26 @@ void Media_PlayFilm_f (void)
#if defined(GLQUAKE)
#if defined(WINAVI)
#define WINAVIRECORDING
PAVIFILE recordavi_file;
#define recordavi_video_stream (recordavi_codec_fourcc?recordavi_compressed_video_stream:recordavi_uncompressed_video_stream)
PAVISTREAM recordavi_uncompressed_video_stream;
PAVISTREAM recordavi_compressed_video_stream;
PAVISTREAM recordavi_uncompressed_audio_stream;
WAVEFORMATEX recordavi_wave_format;
unsigned long recordavi_codec_fourcc;
#endif /* WINAVI */
soundcardinfo_t *capture_fakesounddevice;
/*
int recordavi_video_frame_counter;
int recordavi_audio_frame_counter;
float recordavi_frametime; //length of a frame in fractional seconds
float recordavi_videotime;
float recordavi_audiotime;
int capturesize;
int capturewidth;
char *capturevideomem;
vfsfile_t *captureaudiorawfile;
*/
//int capturesize;
//int capturewidth;
//char *capturevideomem;
//short *captureaudiomem;
int captureaudiosamples;
//int captureaudiosamples;
double captureframeinterval; //interval between video frames
double capturelastvideotime; //time of last video frame
int captureframe;
qboolean captureframeforce;
qboolean capturepaused;
cvar_t capturerate = SCVAR("capturerate", "15");
cvar_t capturerate = SCVAR("capturerate", "30");
#if defined(WINAVI)
cvar_t capturecodec = SCVAR("capturecodec", "divx");
#else
@ -2394,19 +2389,333 @@ cvar_t capturesoundchannels = SCVAR("capturesoundchannels", "1");
cvar_t capturesoundbits = SCVAR("capturesoundbits", "8");
cvar_t capturemessage = SCVAR("capturemessage", "");
qboolean recordingdemo;
enum {
CT_NONE,
CT_AVI,
CT_SCREENSHOT
} capturetype;
char capturefilenameprefix[MAX_QPATH];
media_encoder_funcs_t *capturedriver[8];
qboolean Media_Capturing (void)
media_encoder_funcs_t *currentcapture_funcs;
void *currentcapture_ctx;
#if 1
/*screenshot capture*/
struct capture_raw_ctx
{
if (!capturetype)
return false;
char videonameprefix[MAX_QPATH];
vfsfile_t *audio;
};
static void *QDECL capture_raw_begin (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits)
{
struct capture_raw_ctx *ctx = Z_Malloc(sizeof(*ctx));
Q_strncpyz(ctx->videonameprefix, streamname, sizeof(ctx->videonameprefix));
ctx->audio = NULL;
if (*sndkhz)
{
char filename[MAX_OSPATH];
if (*sndbits < 8)
*sndbits = 8;
if (*sndbits != 8)
*sndbits = 16;
if (*sndchannels > 6)
*sndchannels = 6;
if (*sndchannels < 1)
*sndchannels = 1;
Q_snprintfz(filename, sizeof(filename), "%s/audio_%ichan_%ikhz_%ib.raw", ctx->videonameprefix, *sndchannels, *sndkhz/1000, *sndbits);
ctx->audio = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
}
if (!ctx->audio)
{
*sndkhz = 0;
*sndchannels = 0;
*sndbits = 0;
}
return ctx;
}
static void QDECL capture_raw_video (void *vctx, void *data, int frame, int width, int height)
{
struct capture_raw_ctx *ctx = vctx;
char filename[MAX_OSPATH];
Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", ctx->videonameprefix, frame, capturecodec.string);
SCR_ScreenShot(filename, data, width, height);
}
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
{
struct capture_raw_ctx *ctx = vctx;
if (ctx->audio)
VFS_WRITE(ctx->audio, data, bytes);
}
static void QDECL capture_raw_end (void *vctx)
{
struct capture_raw_ctx *ctx = vctx;
Z_Free(ctx);
}
static media_encoder_funcs_t capture_raw =
{
capture_raw_begin,
capture_raw_video,
capture_raw_audio,
capture_raw_end
};
#endif
#if defined(WINAVI)
/*screenshot capture*/
struct capture_avi_ctx
{
PAVIFILE file;
#define avi_video_stream(ctx) (ctx->codec_fourcc?ctx->compressed_video_stream:ctx->uncompressed_video_stream)
PAVISTREAM uncompressed_video_stream;
PAVISTREAM compressed_video_stream;
PAVISTREAM uncompressed_audio_stream;
WAVEFORMATEX wave_format;
unsigned long codec_fourcc;
int audio_frame_counter;
};
static void QDECL capture_avi_end(void *vctx)
{
struct capture_avi_ctx *ctx = vctx;
if (ctx->uncompressed_video_stream) qAVIStreamRelease(ctx->uncompressed_video_stream);
if (ctx->compressed_video_stream) qAVIStreamRelease(ctx->compressed_video_stream);
if (ctx->uncompressed_audio_stream) qAVIStreamRelease(ctx->uncompressed_audio_stream);
if (ctx->file) qAVIFileRelease(ctx->file);
Z_Free(ctx);
}
static void *QDECL capture_avi_begin (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits)
{
struct capture_avi_ctx *ctx = Z_Malloc(sizeof(*ctx));
HRESULT hr;
BITMAPINFOHEADER bitmap_info_header;
AVISTREAMINFOA stream_header;
FILE *f;
char aviname[256];
char nativepath[256];
char *fourcc = capturecodec.string;
if (strlen(fourcc) == 4)
ctx->codec_fourcc = mmioFOURCC(*(fourcc+0), *(fourcc+1), *(fourcc+2), *(fourcc+3));
else
ctx->codec_fourcc = 0;
if (!qAVIStartup())
{
Con_Printf("vfw support not available.\n");
capture_avi_end(ctx);
return NULL;
}
/*convert to foo.avi*/
COM_StripExtension(streamname, aviname, sizeof(aviname));
COM_DefaultExtension (aviname, ".avi", sizeof(aviname));
/*find the system location of that*/
FS_NativePath(aviname, FS_GAMEONLY, nativepath, sizeof(nativepath));
//wipe it.
f = fopen(nativepath, "rb");
if (f)
{
fclose(f);
unlink(nativepath);
}
hr = qAVIFileOpenA(&ctx->file, nativepath, OF_WRITE | OF_CREATE, NULL);
if (FAILED(hr))
{
Con_Printf("Failed to open %s\n", nativepath);
capture_avi_end(ctx);
return NULL;
}
memset(&bitmap_info_header, 0, sizeof(BITMAPINFOHEADER));
bitmap_info_header.biSize = 40;
bitmap_info_header.biWidth = vid.pixelwidth;
bitmap_info_header.biHeight = vid.pixelheight;
bitmap_info_header.biPlanes = 1;
bitmap_info_header.biBitCount = 24;
bitmap_info_header.biCompression = BI_RGB;
bitmap_info_header.biSizeImage = vid.pixelwidth*vid.pixelheight * 3;
memset(&stream_header, 0, sizeof(stream_header));
stream_header.fccType = streamtypeVIDEO;
stream_header.fccHandler = ctx->codec_fourcc;
stream_header.dwScale = 100;
stream_header.dwRate = (unsigned long)(0.5 + 100.0/captureframeinterval);
SetRect(&stream_header.rcFrame, 0, 0, vid.pixelwidth, vid.pixelheight);
hr = qAVIFileCreateStreamA(ctx->file, &ctx->uncompressed_video_stream, &stream_header);
if (FAILED(hr))
{
Con_Printf("Couldn't initialise the stream, check codec\n");
capture_avi_end(ctx);
return NULL;
}
if (ctx->codec_fourcc)
{
AVICOMPRESSOPTIONS opts;
AVICOMPRESSOPTIONS* aopts[1] = { &opts };
memset(&opts, 0, sizeof(opts));
opts.fccType = stream_header.fccType;
opts.fccHandler = ctx->codec_fourcc;
// Make the stream according to compression
hr = qAVIMakeCompressedStream(&ctx->compressed_video_stream, ctx->uncompressed_video_stream, &opts, NULL);
if (FAILED(hr))
{
Con_Printf("Failed to init compressor\n");
capture_avi_end(ctx);
return NULL;
}
}
hr = qAVIStreamSetFormat(avi_video_stream(ctx), 0, &bitmap_info_header, sizeof(BITMAPINFOHEADER));
if (FAILED(hr))
{
Con_Printf("Failed to set format\n");
capture_avi_end(ctx);
return NULL;
}
if (*sndbits != 8 && *sndbits != 16)
*sndbits = 8;
if (*sndchannels < 1 && *sndchannels > 6)
*sndchannels = 1;
if (*sndkhz)
{
memset(&ctx->wave_format, 0, sizeof(WAVEFORMATEX));
ctx->wave_format.wFormatTag = WAVE_FORMAT_PCM;
ctx->wave_format.nChannels = *sndchannels;
ctx->wave_format.nSamplesPerSec = *sndkhz;
ctx->wave_format.wBitsPerSample = *sndbits;
ctx->wave_format.nBlockAlign = ctx->wave_format.wBitsPerSample/8 * ctx->wave_format.nChannels;
ctx->wave_format.nAvgBytesPerSec = ctx->wave_format.nSamplesPerSec * ctx->wave_format.nBlockAlign;
ctx->wave_format.cbSize = 0;
memset(&stream_header, 0, sizeof(stream_header));
stream_header.fccType = streamtypeAUDIO;
stream_header.dwScale = ctx->wave_format.nBlockAlign;
stream_header.dwRate = stream_header.dwScale * (unsigned long)ctx->wave_format.nSamplesPerSec;
stream_header.dwSampleSize = ctx->wave_format.nBlockAlign;
hr = qAVIFileCreateStreamA(ctx->file, &ctx->uncompressed_audio_stream, &stream_header);
if (FAILED(hr))
{
capture_avi_end(ctx);
return NULL;
}
hr = qAVIStreamSetFormat(ctx->uncompressed_audio_stream, 0, &ctx->wave_format, sizeof(WAVEFORMATEX));
if (FAILED(hr))
{
capture_avi_end(ctx);
return NULL;
}
}
return ctx;
}
static void QDECL capture_avi_video(void *vctx, void *vdata, int frame, int width, int height)
{
struct capture_avi_ctx *ctx = vctx;
qbyte *data = vdata;
int c, i;
qbyte temp;
// swap rgb to bgr
c = width*height*3;
for (i=0 ; i<c ; i+=3)
{
temp = data[i];
data[i] = data[i+2];
data[i+2] = temp;
}
//write it
Con_Printf("%i - %f\n", frame, realtime);
if (FAILED(qAVIStreamWrite(avi_video_stream(ctx), frame, 1, data, width*height * 3, ((frame%15) == 0)?AVIIF_KEYFRAME:0, NULL, NULL)))
Con_Printf("Recoring error\n");
}
static void QDECL capture_avi_audio(void *vctx, void *data, int bytes)
{
struct capture_avi_ctx *ctx = vctx;
if (ctx->uncompressed_audio_stream)
qAVIStreamWrite(ctx->uncompressed_audio_stream, ctx->audio_frame_counter++, 1, data, bytes, AVIIF_KEYFRAME, NULL, NULL);
}
static media_encoder_funcs_t capture_avi =
{
capture_avi_begin,
capture_avi_video,
capture_avi_audio,
capture_avi_end
};
#else
media_encoder_funcs_t capture_avi =
{
NULL,
NULL,
NULL,
NULL
};
#endif
static media_encoder_funcs_t *pluginencodersfunc[8];
static struct plugin_s *pluginencodersplugin[8];
qboolean Media_RegisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs)
{
int i;
for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
{
if (pluginencodersfunc[i] == NULL)
{
pluginencodersfunc[i] = funcs;
pluginencodersplugin[i] = plug;
return true;
}
}
return false;
}
void Media_StopRecordFilm_f(void);
/*funcs==null closes ALL decoders from this plugin*/
qboolean Media_UnregisterEncoder(struct plugin_s *plug, media_encoder_funcs_t *funcs)
{
qboolean success = true;
int i;
static media_decoder_funcs_t deadfuncs;
for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
{
if (pluginencodersfunc[i] == funcs || (!funcs && pluginencodersplugin[i] == plug))
{
if (currentcapture_funcs == funcs)
Media_StopRecordFilm_f();
plugindecodersfunc[i] = NULL;
plugindecodersplugin[i] = NULL;
if (funcs)
return success;
}
}
return success;
}
//returns 0 if not capturing. 1 if capturing live. 2 if capturing a demo (where frame timings are forced).
int Media_Capturing (void)
{
if (!currentcapture_funcs)
return 0;
return captureframeforce?2:1;
}
void Media_CapturePause_f (void)
{
@ -2424,20 +2733,42 @@ qboolean Media_PausedDemo (void)
return false;
}
double Media_TweekCaptureFrameTime(double time)
static qboolean Media_ForceTimeInterval(void)
{
if (cls.demoplayback && Media_Capturing() && recordavi_frametime)
{
return time = recordavi_frametime;
return (cls.demoplayback && Media_Capturing() && captureframeinterval>0);
}
return time;
double Media_TweekCaptureFrameTime(double oldtime, double time)
{
if (Media_ForceTimeInterval())
{
captureframeforce = true;
//if we're forcing time intervals, then we use fixed time increments and generate a new video frame for every single frame.
return capturelastvideotime;
}
return oldtime + time;
}
void Media_RecordFrame (void)
{
if (!capturetype)
char *buffer;
int truewidth, trueheight;
if (!currentcapture_funcs)
return;
/* if (*capturecutoff.string && captureframe * captureframeinterval > capturecutoff.value*60)
{
currentcapture_funcs->capture_end(currentcapture_ctx);
currentcapture_ctx = currentcapture_funcs->capture_begin(Cmd_Argv(1), capturerate.value, vid.pixelwidth, vid.pixelheight, &sndkhz, &sndchannels, &sndbits);
if (!currentcapture_ctx)
{
currentcapture_funcs = NULL;
return;
}
captureframe = 0;
}
*/
if (Media_PausedDemo())
{
int y = vid.height -32-16;
@ -2445,12 +2776,12 @@ void Media_RecordFrame (void)
if (y > vid.height-8)
y = vid.height-8;
Draw_FunString((strlen(capturemessage.string)+1)*8, y, S_COLOR_RED "PAUSED");
if (captureframeforce)
capturelastvideotime += captureframeinterval;
return;
}
if (cls.findtrack)
return; //skip until we're tracking the right player.
//overlay this on the screen, so it appears in the film
if (*capturemessage.string)
{
@ -2462,55 +2793,33 @@ void Media_RecordFrame (void)
}
//time for annother frame?
if (recordavi_videotime > realtime+1)
recordavi_videotime = realtime; //urm, wrapped?..
if (recordavi_videotime > realtime)
if (!captureframeforce)
{
if (capturelastvideotime > realtime+1)
capturelastvideotime = realtime; //urm, wrapped?..
if (capturelastvideotime > realtime)
goto skipframe;
recordavi_videotime += recordavi_frametime;
//audio is mixed to match the video times
}
switch (capturetype)
if (cls.findtrack)
{
case CT_AVI:
#if defined(WINAVI)
{
HRESULT hr;
char *framebuffer = capturevideomem;
qbyte temp;
int i, c;
capturelastvideotime += captureframeinterval;
return; //skip until we're tracking the right player.
}
if (!framebuffer)
//submit the current video frame. audio will be mixed to match.
buffer = VID_GetRGBInfo(0, &truewidth, &trueheight);
if (buffer)
{
Con_Printf("framebuffer = NULL with AVI capture type (this shouldn't happen)\n");
return;
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, captureframe, truewidth, trueheight);
capturelastvideotime += captureframeinterval;
captureframe++;
BZ_Free (buffer);
}
//ask gl for it
qglReadPixels (0, 0, vid.pixelwidth, vid.pixelheight, GL_RGB, GL_UNSIGNED_BYTE, framebuffer );
else
Con_DPrintf("Unable to grab video image\n");
// swap rgb to bgr
c = vid.pixelwidth*vid.pixelheight*3;
for (i=0 ; i<c ; i+=3)
{
temp = framebuffer[i];
framebuffer[i] = framebuffer[i+2];
framebuffer[i+2] = temp;
}
//write it
hr = qAVIStreamWrite(recordavi_video_stream, captureframe++, 1, framebuffer, vid.pixelwidth*vid.pixelheight * 3, ((captureframe%15) == 0)?AVIIF_KEYFRAME:0, NULL, NULL);
if (FAILED(hr)) Con_Printf("Recoring error\n");
}
#endif /* WINAVI */
break;
case CT_SCREENSHOT:
{
char filename[MAX_OSPATH];
Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", capturefilenameprefix, captureframe++, capturecodec.string);
SCR_ScreenShot(filename);
}
break;
case CT_NONE: //non issue.
;
}
captureframeforce = false;
//this is drawn to the screen and not the film
skipframe:
@ -2539,7 +2848,7 @@ static unsigned int MSD_GetDMAPos(soundcardinfo_t *sc)
{
int s;
s = captureframe*(snd_speed*recordavi_frametime);
s = captureframe*(snd_speed*captureframeinterval);
// s >>= (sc->sn.samplebits/8) - 1;
@ -2559,52 +2868,39 @@ static void MSD_Submit(soundcardinfo_t *sc, int start, int end)
int offset;
int bytespersample;
lastpos = sc->snd_completed;
newpos = sc->paintedtime;
while(1)
{
lastpos = sc->snd_completed;
samplestosubmit = newpos - lastpos;
if (samplestosubmit < (snd_speed*recordavi_frametime))
if (samplestosubmit < (snd_speed*captureframeinterval))
return;
if (samplestosubmit < 1152)
return;
if (samplestosubmit > 1152)
samplestosubmit = 1152;
bytespersample = sc->sn.numchannels*sc->sn.samplebits/8;
sc->snd_completed = newpos;
offset = (lastpos % (sc->sn.samples/sc->sn.numchannels));
//we could just use a buffer size equal to the number of samples in each frame
//but that isn't as robust when it comes to floating point imprecisions
//namly: that it would loose a sample each frame with most framerates.
switch (capturetype)
{
case CT_AVI:
#if defined(WINAVI)
if ((sc->snd_completed % (sc->sn.samples/sc->sn.numchannels)) < offset)
{
int partialsamplestosubmit;
//wraped, two chunks to send
partialsamplestosubmit = ((sc->sn.samples/sc->sn.numchannels)) - offset;
qAVIStreamWrite(recordavi_uncompressed_audio_stream, recordavi_audio_frame_counter++, 1, sc->sn.buffer+offset*bytespersample, partialsamplestosubmit*bytespersample, AVIIF_KEYFRAME, NULL, NULL);
currentcapture_funcs->capture_audio(currentcapture_ctx, sc->sn.buffer+offset*bytespersample, partialsamplestosubmit*bytespersample);
samplestosubmit -= partialsamplestosubmit;
sc->snd_completed += partialsamplestosubmit;
offset = 0;
}
qAVIStreamWrite(recordavi_uncompressed_audio_stream, recordavi_audio_frame_counter++, 1, sc->sn.buffer+offset*bytespersample, samplestosubmit*bytespersample, AVIIF_KEYFRAME, NULL, NULL);
#endif /* WINAVI */
break;
case CT_NONE:
break;
case CT_SCREENSHOT:
if ((sc->snd_completed % (sc->sn.samples/sc->sn.numchannels)) < offset)
{
int partialsamplestosubmit;
//wraped, two chunks to send
partialsamplestosubmit = ((sc->sn.samples/sc->sn.numchannels)) - offset;
VFS_WRITE(captureaudiorawfile, sc->sn.buffer+offset*bytespersample, partialsamplestosubmit*bytespersample);
samplestosubmit -= partialsamplestosubmit;
offset = 0;
}
VFS_WRITE(captureaudiorawfile, sc->sn.buffer+offset*bytespersample, samplestosubmit*bytespersample);
break;
currentcapture_funcs->capture_audio(currentcapture_ctx, sc->sn.buffer+offset*bytespersample, samplestosubmit*bytespersample);
sc->snd_completed += samplestosubmit;
}
}
@ -2614,25 +2910,30 @@ static void MSD_Shutdown (soundcardinfo_t *sc)
capture_fakesounddevice = NULL;
}
void Media_InitFakeSoundDevice (int channels, int samplebits)
void Media_InitFakeSoundDevice (int speed, int channels, int samplebits)
{
soundcardinfo_t *sc;
if (capture_fakesounddevice)
return;
if (!snd_speed)
snd_speed = speed;
sc = Z_Malloc(sizeof(soundcardinfo_t));
sc->snd_sent = 0;
sc->snd_completed = 0;
sc->sn.samples = snd_speed*0.5;
sc->sn.speed = snd_speed;
sc->sn.samples = speed*0.5;
sc->sn.speed = speed;
sc->sn.samplebits = samplebits;
sc->sn.samplepos = 0;
sc->sn.numchannels = channels;
sc->inactive_sound = true;
sc->sn.samples -= sc->sn.samples%1152;
sc->sn.buffer = (unsigned char *) BZ_Malloc(sc->sn.samples*sc->sn.numchannels*(sc->sn.samplebits/8));
@ -2655,40 +2956,22 @@ void Media_InitFakeSoundDevice (int channels, int samplebits)
void Media_StopRecordFilm_f (void)
{
#if defined(WINAVI)
if (recordavi_uncompressed_video_stream) qAVIStreamRelease(recordavi_uncompressed_video_stream);
if (recordavi_compressed_video_stream) qAVIStreamRelease(recordavi_compressed_video_stream);
if (recordavi_uncompressed_audio_stream) qAVIStreamRelease(recordavi_uncompressed_audio_stream);
if (recordavi_file) qAVIFileRelease(recordavi_file);
recordavi_uncompressed_video_stream=NULL;
recordavi_compressed_video_stream = NULL;
recordavi_uncompressed_audio_stream=NULL;
recordavi_file = NULL;
#endif /* WINAVI */
if (capturevideomem)
BZ_Free(capturevideomem);
capturevideomem = NULL;
if (capture_fakesounddevice)
S_ShutdownCard(capture_fakesounddevice);
capture_fakesounddevice = NULL;
if (captureaudiorawfile)
VFS_CLOSE(captureaudiorawfile);
captureaudiorawfile = NULL;
capturevideomem = NULL;
recordingdemo=false;
capturetype = CT_NONE;
if (currentcapture_funcs)
currentcapture_funcs->capture_end(currentcapture_ctx);
currentcapture_ctx = NULL;
currentcapture_funcs = NULL;
}
void Media_RecordFilm_f (void)
{
char *fourcc = capturecodec.string;
int sndkhz, sndchannels, sndbits;
int i;
if (Cmd_Argc() != 2)
{
@ -2702,18 +2985,16 @@ void Media_RecordFilm_f (void)
Media_StopRecordFilm_f();
recordavi_video_frame_counter = 0;
recordavi_audio_frame_counter = 0;
if (capturerate.value<=0)
{
Con_Printf("Invalid capturerate\n");
capturerate.value = 15;
}
recordavi_frametime = 1/capturerate.value;
if (recordavi_frametime < 0.001)
recordavi_frametime = 0.001; //no more than 1000 images per second.
captureframeinterval = 1/capturerate.value;
if (captureframeinterval < 0.001)
captureframeinterval = 0.001; //no more than 1000 images per second.
capturelastvideotime = realtime = 0;
captureframe = 0;
if (*fourcc)
@ -2723,209 +3004,70 @@ void Media_RecordFilm_f (void)
!strcmp(fourcc, "jpg") ||
!strcmp(fourcc, "pcx"))
{
capturetype = CT_SCREENSHOT;
Q_strncpyz(capturefilenameprefix, Cmd_Argv(1), sizeof(capturefilenameprefix));
currentcapture_funcs = &capture_raw;
}
else
{
capturetype = CT_AVI;
currentcapture_funcs = &capture_avi;
}
}
else
{
capturetype = CT_AVI; //uncompressed avi
currentcapture_funcs = &capture_avi;
}
if (capturetype == CT_NONE)
for (i = 0; i < 8; i++)
{
if (pluginencodersfunc[i])
currentcapture_funcs = pluginencodersfunc[i];
}
else if (capturetype == CT_SCREENSHOT)
if (capturesound.ival)
{
if (capturesound.value && capturesoundchannels.value >= 1)
{
char filename[MAX_OSPATH];
int chans = capturesoundchannels.value;
int sbits = capturesoundbits.value;
if (sbits < 8)
sbits = 8;
if (sbits != 8)
sbits = 16;
if (chans > 6)
chans = 6;
Q_snprintfz(filename, sizeof(filename), "%s/audio_%ichan_%ikhz_%ib.raw", capturefilenameprefix, chans, snd_speed/1000, sbits);
captureaudiorawfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
if (captureaudiorawfile)
Media_InitFakeSoundDevice(chans, sbits);
sndkhz = snd_speed?snd_speed:48000;
sndchannels = capturesoundchannels.ival;
sndbits = capturesoundbits.ival;
}
}
#if defined(WINAVI)
else if (capturetype == CT_AVI)
{
HRESULT hr;
BITMAPINFOHEADER bitmap_info_header;
AVISTREAMINFOA stream_header;
FILE *f;
char aviname[256];
char nativepath[256];
if (strlen(fourcc) == 4)
recordavi_codec_fourcc = mmioFOURCC(*(fourcc+0), *(fourcc+1), *(fourcc+2), *(fourcc+3));
else
recordavi_codec_fourcc = 0;
if (!qAVIStartup())
{
Con_Printf("vfw support not available.\n");
return;
}
/*convert to foo.avi*/
COM_StripExtension(Cmd_Argv(1), aviname, sizeof(aviname));
COM_DefaultExtension (aviname, ".avi", sizeof(aviname));
/*find the system location of that*/
FS_NativePath(aviname, FS_ROOT, nativepath, sizeof(nativepath));
//wipe it.
f = fopen(nativepath, "rb");
if (f)
{
fclose(f);
unlink(nativepath);
}
hr = qAVIFileOpenA(&recordavi_file, nativepath, OF_WRITE | OF_CREATE, NULL);
if (FAILED(hr))
{
Con_Printf("Failed to open %s\n", nativepath);
return;
}
memset(&bitmap_info_header, 0, sizeof(BITMAPINFOHEADER));
bitmap_info_header.biSize = 40;
bitmap_info_header.biWidth = vid.pixelwidth;
bitmap_info_header.biHeight = vid.pixelheight;
bitmap_info_header.biPlanes = 1;
bitmap_info_header.biBitCount = 24;
bitmap_info_header.biCompression = BI_RGB;
bitmap_info_header.biSizeImage = vid.pixelwidth*vid.pixelheight * 3;
memset(&stream_header, 0, sizeof(stream_header));
stream_header.fccType = streamtypeVIDEO;
stream_header.fccHandler = recordavi_codec_fourcc;
stream_header.dwScale = 100;
stream_header.dwRate = (unsigned long)(0.5 + 100.0/recordavi_frametime);
SetRect(&stream_header.rcFrame, 0, 0, vid.pixelwidth, vid.pixelheight);
hr = qAVIFileCreateStreamA(recordavi_file, &recordavi_uncompressed_video_stream, &stream_header);
if (FAILED(hr))
{
Con_Printf("Couldn't initialise the stream, check codec\n");
Media_StopRecordFilm_f();
return;
}
if (recordavi_codec_fourcc)
{
AVICOMPRESSOPTIONS opts;
AVICOMPRESSOPTIONS* aopts[1] = { &opts };
memset(&opts, 0, sizeof(opts));
opts.fccType = stream_header.fccType;
opts.fccHandler = recordavi_codec_fourcc;
// Make the stream according to compression
hr = qAVIMakeCompressedStream(&recordavi_compressed_video_stream, recordavi_uncompressed_video_stream, &opts, NULL);
if (FAILED(hr))
{
Con_Printf("Failed to init compressor\n");
Media_StopRecordFilm_f();
return;
}
}
hr = qAVIStreamSetFormat(recordavi_video_stream, 0, &bitmap_info_header, sizeof(BITMAPINFOHEADER));
if (FAILED(hr))
{
Con_Printf("Failed to set format\n");
Media_StopRecordFilm_f();
return;
}
if (capturesoundbits.value != 8 && capturesoundbits.value != 16)
Cvar_Set(&capturesoundbits, "8");
if (capturesoundchannels.value < 1 && capturesoundchannels.value > 6)
Cvar_Set(&capturesoundchannels, "1");
if (capturesound.value)
{
memset(&recordavi_wave_format, 0, sizeof(WAVEFORMATEX));
recordavi_wave_format.wFormatTag = WAVE_FORMAT_PCM;
recordavi_wave_format.nChannels = capturesoundchannels.value;
recordavi_wave_format.nSamplesPerSec = snd_speed;
recordavi_wave_format.wBitsPerSample = capturesoundbits.value;
recordavi_wave_format.nBlockAlign = recordavi_wave_format.wBitsPerSample/8 * recordavi_wave_format.nChannels;
recordavi_wave_format.nAvgBytesPerSec = recordavi_wave_format.nSamplesPerSec * recordavi_wave_format.nBlockAlign;
recordavi_wave_format.cbSize = 0;
memset(&stream_header, 0, sizeof(stream_header));
stream_header.fccType = streamtypeAUDIO;
stream_header.dwScale = recordavi_wave_format.nBlockAlign;
stream_header.dwRate = stream_header.dwScale * (unsigned long)recordavi_wave_format.nSamplesPerSec;
stream_header.dwSampleSize = recordavi_wave_format.nBlockAlign;
hr = qAVIFileCreateStreamA(recordavi_file, &recordavi_uncompressed_audio_stream, &stream_header);
if (FAILED(hr)) return;
hr = qAVIStreamSetFormat(recordavi_uncompressed_audio_stream, 0, &recordavi_wave_format, sizeof(WAVEFORMATEX));
if (FAILED(hr)) return;
Media_InitFakeSoundDevice(recordavi_wave_format.nChannels, recordavi_wave_format.wBitsPerSample);
}
recordavi_videotime = realtime;
recordavi_audiotime = realtime;
// if (recordavi_wave_format.nSamplesPerSec)
// captureaudiomem = BZ_Malloc(recordavi_wave_format.nSamplesPerSec*2);
capturevideomem = BZ_Malloc(vid.pixelwidth*vid.pixelheight*3);
}
#endif /* WINAVI */
else
{
Con_Printf("That sort of video capturing is not supported in this build\n");
capturetype = CT_NONE;
sndkhz = 0;
sndchannels = 0;
sndbits = 0;
}
if (!currentcapture_funcs->capture_begin)
currentcapture_ctx = NULL;
else
currentcapture_ctx = currentcapture_funcs->capture_begin(Cmd_Argv(1), capturerate.value, vid.pixelwidth, vid.pixelheight, &sndkhz, &sndchannels, &sndbits);
if (!currentcapture_ctx)
{
currentcapture_funcs = NULL;
Con_Printf("Unable to initialise capture driver\n");
}
else if (sndkhz)
Media_InitFakeSoundDevice(sndkhz, sndchannels, sndbits);
}
void Media_CaptureDemoEnd(void)
{
if (recordingdemo)
Media_StopRecordFilm_f();
}
void CL_PlayDemo(char *demoname);
void Media_RecordDemo_f(void)
{
CL_PlayDemo_f();
if (Cmd_Argc() < 2)
return;
CL_PlayDemo(Cmd_Argv(1));
if (Cmd_Argc() > 2)
Cmd_ShiftArgs(1, false);
Media_RecordFilm_f();
scr_con_current=0;
key_dest = key_game;
if (capturetype != CT_NONE)
if (currentcapture_funcs)
recordingdemo = true;
else
CL_Stopdemo_f(); //capturing failed for some reason
}
#else /* GLQUAKE */
void Media_CaptureDemoEnd(void){}
void Media_RecordAudioFrame (short *sample_buffer, int samples){}
double Media_TweekCaptureFrameTime(double time) { return time ; }
void Media_RecordFrame (void) {}
qboolean Media_PausedDemo (void) {return false;} //should not return a value
#endif /* GLQUAKE */
#ifdef _WIN32
typedef struct ISpNotifySink ISpNotifySink;
@ -3626,6 +3768,11 @@ void Media_Init(void)
Cvar_Register(&tts_mode, "Gimmicks");
#endif
#if defined(WINAVI)
Media_RegisterEncoder(NULL, &capture_avi);
#endif
Media_RegisterEncoder(NULL, &capture_raw);
Cmd_AddCommand("playfilm", Media_PlayFilm_f);
Cmd_AddCommand("cinematic", Media_PlayFilm_f);
Cmd_AddCommand("music_fforward", Media_FForward_f);
@ -3872,7 +4019,7 @@ void M_Media_Draw (void){}
void M_Media_Key (int key) {}
qboolean Media_ShowFilm(void){return false;}
double Media_TweekCaptureFrameTime(double time) { return time ; }
double Media_TweekCaptureFrameTime(double oldtime, double time) { return oldtime+time ; }
void Media_RecordFrame (void) {}
void Media_CaptureDemoEnd(void) {}
void Media_RecordDemo_f(void) {}

View file

@ -435,6 +435,8 @@ const char *presetexec[] =
"gl_specular 0;"
"r_loadlit 0;"
"r_fastsky 1;"
"r_waterstyle 0;"
"r_lavastyle 0;"
"r_shadow_realtime_dlight 0;"
"r_shadow_realtime_world 0;"
"r_glsl_offsetmapping 0;"
@ -444,6 +446,7 @@ const char *presetexec[] =
"r_waterwarp 0;"
"r_lightstylesmooth 0;"
"r_part_density 0.25;"
, // fast options
"gl_texturemode ln;"
"r_particlesystem classic;"
@ -452,7 +455,10 @@ const char *presetexec[] =
"gl_flashblend 1;"
"r_loadlit 1;"
"r_fastsky 0;"
"r_waterstyle 1;"
"r_lavastyle 1;"
"r_nolightdir 0;"
, // normal options
#ifdef MINIMAL
"r_particlesystem classic;"
@ -467,6 +473,7 @@ const char *presetexec[] =
"gl_load24bit 1;"
"r_replacemodels \"md3 md2\";"
"r_waterwarp 1;"
, // nice options
"r_stains 0.75;"
"gl_texturemode ll;"
@ -476,14 +483,17 @@ const char *presetexec[] =
#endif
"gl_specular 1;"
"r_loadlit 2;"
"r_waterstyle 2;"
// "r_fastsky -1;"
"r_shadow_realtime_dlight 1;"
"gl_detail 1;"
"r_lightstylesmooth 1;"
"gl_texture_anisotropic_filtering 4;"
, // realtime options
// "r_bloom 1;"
"r_particledesc \"spikeset high tsshaft\";"
"r_waterstyle 3;"
"r_glsl_offsetmapping 1;"
"r_shadow_realtime_world 1;"
"gl_texture_anisotropic_filtering 16;"

View file

@ -40,6 +40,7 @@ cvar_t slist_writeserverstxt = SCVAR("slist_writeservers", "0");
void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad);
void CL_QueryServers(void);
int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite);
void MasterInfo_RemoveAllPlayers(void);
master_t *master;
player_t *mplayers;
@ -495,7 +496,7 @@ float Master_ReadKeyFloat(serverinfo_t *server, int keynum)
char *Master_ReadKeyString(serverinfo_t *server, int keynum)
{
char adr[MAX_ADR_SIZE];
static char adr[MAX_ADR_SIZE];
if (keynum < SLKEY_CUSTOM)
{
@ -631,12 +632,26 @@ void Master_AddMaster (char *address, int type, char *description)
void MasterInfo_Shutdown(void)
{
master_t *mast;
serverinfo_t *sv;
MasterInfo_RemoveAllPlayers();
while(firstserver)
{
sv = firstserver;
firstserver = sv->next;
Z_Free(sv);
}
while(master)
{
mast = master;
master = mast->next;
if (mast->dl)
DL_Close(mast->dl);
Z_Free(mast);
}
maxvisibleservers = 0;
numvisibleservers = 0;
Z_Free(visibleservers);
}
void Master_AddMasterHTTP (char *address, int mastertype, char *description)
@ -1267,6 +1282,8 @@ void MasterInfo_ProcessHTTPJSON(struct dl_download *dl)
{
int len;
char *buf;
master_t *mast = dl->user_ctx;
mast->dl = NULL;
if (dl->file)
{
len = VFS_GETLEN(dl->file);
@ -1285,11 +1302,15 @@ void MasterInfo_ProcessHTTPJSON(struct dl_download *dl)
// wrapper functions for the different server types
void MasterInfo_ProcessHTTPNQ(struct dl_download *dl)
{
master_t *mast = dl->user_ctx;
mast->dl = NULL;
MasterInfo_ProcessHTTP(dl->file, SS_NETQUAKE);
}
void MasterInfo_ProcessHTTPQW(struct dl_download *dl)
{
master_t *mast = dl->user_ctx;
mast->dl = NULL;
MasterInfo_ProcessHTTP(dl->file, SS_GENERICQUAKEWORLD);
}
#endif
@ -1368,13 +1389,28 @@ void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles)
#endif
#ifdef WEBCLIENT
case MT_MASTERHTTPJSON:
HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPJSON);
if (!mast->dl)
{
mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPJSON);
if (mast->dl)
mast->dl->user_ctx = mast;
}
break;
case MT_MASTERHTTPNQ:
HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPNQ);
if (!mast->dl)
{
mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPNQ);
if (mast->dl)
mast->dl->user_ctx = mast;
}
break;
case MT_MASTERHTTPQW:
HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPQW);
if (!mast->dl)
{
mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPQW);
if (mast->dl)
mast->dl->user_ctx = mast;
}
break;
#endif
}
@ -1757,6 +1793,16 @@ serverinfo_t *Master_InfoForNum (int num)
return NULL;
}
void MasterInfo_RemoveAllPlayers(void)
{
player_t *p;
while(mplayers)
{
p = mplayers;
mplayers = p->next;
Z_Free(p);
}
}
void MasterInfo_RemovePlayers(netadr_t adr)
{
player_t *p, *prev;

View file

@ -1779,6 +1779,8 @@ static void P_ImportEffectInfo_f(void)
args--;
}
line = COM_StringParse(line, com_token, sizeof(com_token), false, false);
if (!line)
break;
Q_strncpyz(arg[args], com_token, sizeof(arg[args]));
args++;
if (*com_token == '\n')
@ -4655,8 +4657,13 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type)
c = b->next;
q = c->p;
if (!q)
continue;
p = b->p;
q->rgba[3] = 1;
p->rgba[3] = 1;
VectorSubtract(r_refdef.vieworg, q->org, v);
VectorNormalize(v);
CrossProduct(c->dir, v, cr);
@ -5108,7 +5115,11 @@ static void PScript_DrawParticleTypes (void)
{
while ((p=type->particles))
{
if (pdraw)
if (scenetri)
{
tdraw(scenetri, p, type->slooks);
}
else if (pdraw)
RQ_AddDistReorder(pdraw, p, type->slooks, p->org);
// make sure emitter runs at least once

View file

@ -611,6 +611,13 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
cs_getframestate(in, rflags, &out->framestate);
VectorCopy(in->v->origin, out->origin);
VectorCopy(in->v->oldorigin, out->oldorigin);
if (in->v->enemy)
{
csqcedict_t *ed = (csqcedict_t*)PROG_TO_EDICT(csqcprogs, in->v->enemy);
VectorSubtract(out->oldorigin, ed->v->oldorigin, out->oldorigin);
}
if (rflags & CSQCRF_USEAXIS)
{
VectorCopy(csqcg.forward, out->axis[0]);
@ -1394,6 +1401,7 @@ static void QCBUILTIN PF_R_SetViewFlag(progfuncs_t *prinst, struct globalvars_s
}
}
void R2D_PolyBlend (void);
static void QCBUILTIN PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (cl.worldmodel)
@ -1404,13 +1412,7 @@ static void QCBUILTIN PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s
V_CalcGunPositionAngle(csqc_lplayernum, V_CalcBob(csqc_lplayernum, true));
R_RenderView();
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
{
GL_Set2D (false);
}
#endif
R2D_PolyBlend ();
vid.recalc_refdef = 1;
@ -1686,7 +1688,7 @@ static void csqc_setmodel(progfuncs_t *prinst, csqcedict_t *ent, int modelindex)
ent->v->modelindex = modelindex;
if (modelindex < 0)
{
if (modelindex <= -MAX_MODELS)
if (modelindex <= -MAX_CSQCMODELS)
return;
ent->v->model = PR_SetString(prinst, cl.model_csqcname[-modelindex]);
if (!cl.model_csqcprecache[-modelindex])
@ -3257,7 +3259,7 @@ static void QCBUILTIN PF_cl_runningserver (progfuncs_t *prinst, struct globalvar
#ifdef CLIENTONLY
G_FLOAT(OFS_RETURN) = false;
#else
G_FLOAT(OFS_RETURN) = !!sv.active;
G_FLOAT(OFS_RETURN) = sv.state != ss_dead;
#endif
}
@ -4275,7 +4277,6 @@ static struct {
// {"bulleten", PF_bulleten, 243}, (removed builtin)
{"rotatevectorsbytag", PF_rotatevectorsbytag, 244},
#ifdef SQL
{"sqlconnect", PF_NoCSQC, 250}, // #250 float([string host], [string user], [string pass], [string defaultdb], [string driver]) sqlconnect (FTE_SQL)
{"sqldisconnect", PF_NoCSQC, 251}, // #251 void(float serveridx) sqldisconnect (FTE_SQL)
{"sqlopenquery", PF_NoCSQC, 252}, // #252 float(float serveridx, void(float serveridx, float queryidx, float rows, float columns, float eof) callback, float querytype, string query) sqlopenquery (FTE_SQL)
@ -4285,7 +4286,6 @@ static struct {
{"sqlescape", PF_NoCSQC, 256}, // #256 string(float serveridx, string data) sqlescape (FTE_SQL)
{"sqlversion", PF_NoCSQC, 257}, // #257 string(float serveridx) sqlversion (FTE_SQL)
{"sqlreadfloat", PF_NoCSQC, 258}, // #258 float(float serveridx, float queryidx, float row, float column) sqlreadfloat (FTE_SQL)
#endif
{"stoi", PF_stoi, 259},
{"itos", PF_itos, 260},
@ -4293,7 +4293,7 @@ static struct {
{"htos", PF_htos, 262},
{"skel_create", PF_skel_create, 263},//float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_build", PF_skel_build, 264},//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_build", PF_skel_build, 264},//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone, optional float addition) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_get_numbones", PF_skel_get_numbones, 265},//float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_get_bonename", PF_skel_get_bonename, 266},//string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) (returns tempstring)
{"skel_get_boneparent", PF_skel_get_boneparent, 267},//float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS)
@ -4623,6 +4623,8 @@ static struct {
{"isfunction", PF_isfunction, 607},
{"parseentitydata", PF_parseentitydata, 608},
{"findkeysforcommand", PF_cl_findkeysforcommand, 610},
{"sprintf", PF_sprintf, 627},
{"getsurfacenumtriangles",PF_getsurfacenumtriangles,628},
@ -4831,6 +4833,10 @@ void CSQC_Shutdown(void)
memset(&deltafunction, 0, sizeof(deltafunction));
memset(csqcdelta_playerents, 0, sizeof(csqcdelta_playerents));
Z_Free(csqcent);
csqcent = NULL;
maxcsqcentities = 0;
csqcmapentitydata = NULL;
csqcmapentitydataloaded = false;
@ -5084,10 +5090,16 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
if (csqc_singlecheats || anycsqc)
{
Con_DPrintf("loading csaddon.dat...\n");
if (PR_LoadProgs(csqcprogs, "csaddon.dat", 0, NULL, 0) >= 0)
{
Con_DPrintf("loaded csaddon.dat...\n");
loaded = true;
}
else
Con_DPrintf("unable to find csaddon.dat.\n");
}
else
Con_DPrintf("skipping csaddon.dat due to cheat restrictions\n");
if (!loaded)
{
@ -5188,9 +5200,8 @@ void CSQC_WorldLoaded(void)
#endif
worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0);
worldent->v->modelindex = 1;
worldent->v->model = PR_SetString(csqcprogs, cl.model_name[(int)worldent->v->modelindex]);
worldent->v->solid = SOLID_BSP;
csqc_setmodel(csqcprogs, worldent, 1);
if (csqcg.worldloaded)
PR_ExecuteProgram(csqcprogs, csqcg.worldloaded);
@ -5357,7 +5368,7 @@ void CSQC_RegisterCvarsAndThings(void)
{
Cmd_AddCommand("coredump_csqc", CSQC_CoreDump);
Cmd_AddCommand ("extensionlist_csqc", PR_CSExtensionList_f);
Cmd_AddCommand("cl_cmd", CSQC_GameCommand_f);
Cmd_AddCommandD("cl_cmd", CSQC_GameCommand_f, "Calls the csqc's GameCommand function");
Cmd_AddCommand("breakpoint_csqc", CSQC_Breakpoint_f);
Cvar_Register(&pr_csqc_memsize, CSQCPROGSGROUP);

View file

@ -393,7 +393,8 @@ void QCBUILTIN PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_
else if ((*str & CON_CHARMASK) == '\r')
px = ipx;
else
px = Font_DrawScaleChar(px, py, size[0], size[1], *str++);
px = Font_DrawScaleChar(px, py, size[0], size[1], *str);
str++;
}
Font_InvalidateColour();
Font_EndString(font_conchar);
@ -411,7 +412,7 @@ void QCBUILTIN PF_CL_stringwidth(progfuncs_t *prinst, struct globalvars_s *pr_gl
else
fontsize = 8;
if (mp_globs.drawfontscale)
if (mp_globs.drawfontscale && !prinst->parms->user)
fontsize *= mp_globs.drawfontscale[1];
end = COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), !usecolours);
@ -421,7 +422,7 @@ void QCBUILTIN PF_CL_stringwidth(progfuncs_t *prinst, struct globalvars_s *pr_gl
px = Font_LineWidth(buffer, end);
Font_EndString(font_conchar);
if (mp_globs.drawfontscale)
if (mp_globs.drawfontscale && !prinst->parms->user)
px *= mp_globs.drawfontscale[1];
G_FLOAT(OFS_RETURN) = px * fontsize;
@ -572,9 +573,13 @@ void QCBUILTIN PF_CL_drawcharacter (progfuncs_t *prinst, struct globalvars_s *pr
return;
}
//no control chars. use quake ones if so
if (chara < 32 && chara != '\t')
chara |= 0xe000;
Font_BeginScaledString(font_conchar, pos[0], pos[1], &x, &y);
Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha);
Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK | /*0xe000|*/(chara&0xff));
Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK | /*0xe000|*/chara);
Font_InvalidateColour();
Font_EndString(font_conchar);
@ -590,6 +595,7 @@ void QCBUILTIN PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr
float alpha = G_FLOAT(OFS_PARM4);
// float flag = G_FLOAT(OFS_PARM5);
float x, y;
unsigned int c;
if (!text)
{
@ -602,7 +608,7 @@ void QCBUILTIN PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr
y = pos[1];
Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha);
if (mp_globs.drawfontscale)
if (mp_globs.drawfontscale && !prinst->parms->user)
{
size[0] *= mp_globs.drawfontscale[0];
size[1] *= mp_globs.drawfontscale[1];
@ -611,7 +617,12 @@ void QCBUILTIN PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr
{
//FIXME: which charset is this meant to be using?
//quakes? 8859-1? utf8? some weird hacky mixture?
x = Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK|/*0xe000|*/(*text++&0xff));
c = *text++&0xff;
if ((c&0x7f) < 32)
c |= 0xe000; //if its a control char, just use the quake range instead.
else if (c & 0x80)
c |= 0xe000; //if its a high char, just use the quake range instead. we could colour it, but why bother
x = Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK|/*0xe000|*/c);
}
Font_InvalidateColour();
Font_EndString(font_conchar);
@ -704,6 +715,7 @@ void QCBUILTIN PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (b == 0)
{
Con_Printf("mod by zero\n");
*prinst->pr_trace = 1;
G_FLOAT(OFS_RETURN) = 0;
}
else
@ -741,17 +753,26 @@ static void QCBUILTIN PF_menu_cvar (progfuncs_t *prinst, struct globalvars_s *pr
char *str;
str = PR_GetStringOfs(prinst, OFS_PARM0);
if (!strcmp(str, "vid_conwidth"))
G_FLOAT(OFS_RETURN) = vid.width;
else if (!strcmp(str, "vid_conheight"))
G_FLOAT(OFS_RETURN) = vid.height;
else
{
str = RemapCvarNameFromDPToFTE(str);
var = Cvar_Get(str, "", 0, "menu cvars");
if (var)
{
if (var->latched_string)
G_FLOAT(OFS_RETURN) = atof(var->latched_string); else
G_FLOAT(OFS_RETURN) = atof(var->latched_string);
else
G_FLOAT(OFS_RETURN) = var->value;
}
else
G_FLOAT(OFS_RETURN) = 0;
}
}
static void QCBUILTIN PF_menu_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *var_name, *val;
@ -833,6 +854,10 @@ void QCBUILTIN PF_isserver (progfuncs_t *prinst, struct globalvars_s *pr_globals
G_FLOAT(OFS_RETURN) = sv.state != ss_dead;
#endif
}
void QCBUILTIN PF_isdemo (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
G_FLOAT(OFS_RETURN) = !!cls.demoplayback;
}
//float clientstate(void) = #62;
void QCBUILTIN PF_clientstate (progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -914,12 +939,12 @@ void QCBUILTIN PF_cl_setmousetarget (progfuncs_t *prinst, struct globalvars_s *p
extern int mouseusedforgui;
switch ((int)G_FLOAT(OFS_PARM0))
{
case 1:
mouseusedforgui = true;
break;
case 2:
case 1: //1 is delta-based.
mouseusedforgui = false;
break;
case 2: //2 is absolute.
mouseusedforgui = true;
break;
default:
PR_BIError(prinst, "PF_setmousetarget: not a valid destination\n");
}
@ -929,7 +954,7 @@ void QCBUILTIN PF_cl_setmousetarget (progfuncs_t *prinst, struct globalvars_s *p
void QCBUILTIN PF_cl_getmousetarget (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
extern int mouseusedforgui;
G_FLOAT(OFS_RETURN) = mouseusedforgui?1:2;
G_FLOAT(OFS_RETURN) = mouseusedforgui?2:1;
}
//vector getmousepos(void) = #66;
@ -1406,6 +1431,37 @@ void QCBUILTIN PF_altstr_set(progfuncs_t *prinst, struct globalvars_s *pr_global
}
//string(string serveraddress) crypto_getkeyfp
void QCBUILTIN PF_crypto_getkeyfp(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//not supported.
G_INT(OFS_RETURN) = 0;
}
//string(string serveraddress) crypto_getidfp
void QCBUILTIN PF_crypto_getidfp(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//not supported.
G_INT(OFS_RETURN) = 0;
}
//string(string serveraddress) crypto_getencryptlevel
void QCBUILTIN PF_crypto_getencryptlevel(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//not supported.
G_INT(OFS_RETURN) = 0;
}
//string(float i) crypto_getmykeyfp
void QCBUILTIN PF_crypto_getmykeyfp(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//not supported.
G_INT(OFS_RETURN) = 0;
}
//string(float i) crypto_getmyidfp
void QCBUILTIN PF_crypto_getmyidfp(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//not supported.
G_INT(OFS_RETURN) = 0;
}
builtin_t menu_builtins[] = {
//0
PF_Fixme,
@ -1527,7 +1583,7 @@ builtin_t menu_builtins[] = {
PF_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
PF_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS)
PF_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
PF_strncasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
PF_strcasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
//230
PF_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
skip1
@ -1543,7 +1599,21 @@ builtin_t menu_builtins[] = {
skip10
skip50
//300
skip100
skip10
skip10
skip10
skip10
skip1
skip1
skip1
skip1
skip1
skip1
skip1
skip1
skip1
PF_isdemo,
skip50
//400
skip10
skip10
@ -1677,7 +1747,7 @@ builtin_t menu_builtins[] = {
PF_M_sethostcachemasknumber,
PF_M_resorthostcache,
PF_M_sethostcachesort,
PF_M_refreshhostcache,
PF_M_refreshhostcache, //600
PF_M_gethostcachenumber,
PF_M_gethostcacheindexforkey,
PF_M_addwantedhostcachekey,
@ -1692,16 +1762,14 @@ builtin_t menu_builtins[] = {
PF_sprintf, /*sprintf*/
skip1 /*not listed in dp*/
skip1 /*not listed in dp*/
skip1 /*setkeybind*/
skip1 /*setkeybind*/ //630
skip1 /*getbindmaps*/
skip1 /*setbindmaps*/
skip1 /*crypto*/
skip1 /*crypto*/
skip1 /*crypto*/
skip1 /*crypto*/
skip1 /*crypto #637*/
PF_crypto_getkeyfp, /*crypto*/
PF_crypto_getidfp, /*crypto*/
PF_crypto_getencryptlevel, /*crypto*/
PF_crypto_getmykeyfp, /*crypto*/
PF_crypto_getmyidfp, /*crypto #637*/
};
int menu_numbuiltins = sizeof(menu_builtins)/sizeof(menu_builtins[0]);
@ -1752,6 +1820,10 @@ void MP_Shutdown (void)
PR_fclose_progs(menuprogs);
search_close_progs(menuprogs, true);
#ifdef CL_MASTER
Master_ClearMasks();
#endif
CloseProgs(menuprogs);
#ifdef TEXTEDITOR
Editor_ProgsKilled(menuprogs);
@ -1762,12 +1834,6 @@ void MP_Shutdown (void)
m_state = 0;
mouseusedforgui = false;
if (inmenuprogs) //something in the menu caused the problem, so...
{
inmenuprogs = 0;
longjmp(mp_abort, 1);
}
}
pbool QC_WriteFile(const char *name, void *data, int len);
@ -1797,6 +1863,12 @@ void VARGS Menu_Abort (char *format, ...)
}
MP_Shutdown();
if (inmenuprogs) //something in the menu caused the problem, so...
{
inmenuprogs = 0;
longjmp(mp_abort, 1);
}
}
void MP_CvarChanged(cvar_t *var)
@ -1858,13 +1930,14 @@ qboolean MP_Init (void)
menuprogparms.sv_num_edicts = &num_menu_edicts;
menuprogparms.useeditor = NULL;//sorry... QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
menuprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
menutime = Sys_DoubleTime();
if (!menuprogs)
{
Con_DPrintf("Initializing menu.dat\n");
menuprogs = InitProgs(&menuprogparms);
PR_Configure(menuprogs, -1, 1);
PR_Configure(menuprogs, 64*1024*1024, 1);
if (PR_LoadProgs(menuprogs, "menu.dat", 10020, NULL, 0) < 0) //no per-progs builtins.
{
//failed to load or something
@ -1886,11 +1959,8 @@ qboolean MP_Init (void)
if (mp_time)
*mp_time = Sys_DoubleTime();
#ifdef warningmsg
#pragma warningmsg("disabled until csqc gets forked or some such")
#endif
//mp_globs.drawfont = (float*)PR_FindGlobal(menuprogs, "drawfont", 0, NULL);
//mp_globs.drawfontscale = (float*)PR_FindGlobal(menuprogs, "drawfontscale", 0, NULL);
mp_globs.drawfont = (float*)PR_FindGlobal(menuprogs, "drawfont", 0, NULL);
mp_globs.drawfontscale = (float*)PR_FindGlobal(menuprogs, "drawfontscale", 0, NULL);
menuentsize = PR_InitEnts(menuprogs, 8192);
@ -1971,6 +2041,12 @@ void MP_Draw(void)
void MP_Keydown(int key, int unicode)
{
extern qboolean keydown[K_MAX];
#ifdef TEXTEDITOR
if (editormodal)
return;
#endif
if (setjmp(mp_abort))
return;
@ -2008,6 +2084,11 @@ void MP_Keydown(int key, int unicode)
void MP_Keyup(int key, int unicode)
{
#ifdef TEXTEDITOR
if (editormodal)
return;
#endif
if (setjmp(mp_abort))
return;
@ -2030,6 +2111,10 @@ qboolean MP_Toggle(void)
{
if (!menuprogs)
return false;
#ifdef TEXTEDITOR
if (editormodal)
return false;
#endif
if (setjmp(mp_abort))
return false;

View file

@ -21,6 +21,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
this file deals with qc builtins to apply custom skeletal blending (skeletal objects extension), as well as the logic required to perform realtime ragdoll, if I ever implement that.
*/
/*
skeletal objects are just a set of bone poses.
they are separate from the entity they are attached to, and must be created/destroyed separately.
typically the bones are all stored relative to their parent.
qc must use skel_build to copy animation data from the file format into the skeletal object for rendering, but can build different bones using different animations or can override explicit bones.
ragdoll file is a description of the joints in the ragdoll.
a skeletal object, built from a doll instead of a model, has a series of physics objects created at key points (ie: not face).
these objects are absolute
qc must build the skeletal object still, which fills the skeletal object from the physics objects instead of animation data, for bones that have solid objects.
*/
#include "quakedef.h"
#if defined(CSQC_DAT) || !defined(CLIENTONLY)
@ -36,21 +48,25 @@ this file deals with qc builtins to apply custom skeletal blending (skeletal obj
typedef struct doll_s
{
char *name;
int uses;
model_t *model;
struct doll_s *next;
int numbodies;
int numjoints;
int numbones;
struct
{
char name[32];
int bone;
char *name;
} body[32];
} *body;
odejointinfo_t *joint;
struct
{
int type;
int body[2];
} joint[32];
//easy lookup table for bone->body.
//most of these will be -1, which means 'import from animation object'
int bodyidx;
} *bone;
} doll_t;
enum
@ -60,6 +76,8 @@ enum
};
typedef struct
{
odebody_t odebody;
int ownerent; /*multiple of 12*/
int flags;
@ -77,8 +95,8 @@ typedef struct skelobject_s
world_t *world; /*be it ssqc or csqc*/
enum
{
SKOT_RELATIVE,
SKOT_ABSOLUTE
SKOT_RELATIVE, //relative to parent
SKOT_ABSOLUTE //relative to model
} type;
unsigned int numbones;
@ -88,6 +106,8 @@ typedef struct skelobject_s
struct skelobject_s *animsource;
unsigned int numbodies;
body_t *body;
int numjoints;
odejoint_t *joint;
doll_t *doll;
#endif
} skelobject_t;
@ -177,13 +197,37 @@ static void bonematident_toqcvectors(float vx[3], float vy[3], float vz[3], floa
static qboolean pendingkill; /*states that there is a skel waiting to be killed*/
#ifdef RAGDOLL
doll_t *rag_loaddoll(model_t *mod, char *fname)
void rag_uninstanciate(skelobject_t *sko);
int rag_finddollbody(doll_t *d, char *bodyname)
{
int i;
for (i = 0; i < d->numbodies; i++)
{
if (!strcmp(d->body[i].name, bodyname))
return i;
}
return -1;
}
int rag_finddolljoint(doll_t *d, char *name)
{
int i;
for (i = 0; i < d->numjoints; i++)
{
if (!strcmp(d->joint[i].name, name))
return i;
}
return -1;
}
doll_t *rag_loaddoll(model_t *mod, char *fname, int numbones)
{
doll_t *d;
void *fptr = NULL;
char *file;
int fsize;
int i, j;
int i;
char *cmd;
galiasbone_t *bones;
int errors = 0;
for (d = dolllist; d; d = d->next)
{
@ -192,49 +236,180 @@ doll_t *rag_loaddoll(model_t *mod, char *fname)
return d;
}
bones = Mod_GetBoneInfo(mod);
if (!bones)
{
//model not skeletal.
return NULL;
}
fsize = FS_LoadFile(fname, &fptr);
if (!fptr)
return NULL;
d = malloc(sizeof(*d));
d->next = dolllist;
dolllist = d;
d->name = strdup(fname);
d->model = mod;
d->numbodies = 0;
d->body = NULL;
d->numjoints = 0;
d->uses = 0;
d->joint = NULL;
d->numbones = numbones;
d->bone = malloc(sizeof(*d->bone) * d->numbones);
for (i = 0; i < d->numbones; i++)
d->bone[i].bodyidx = -1;
file = fptr;
while(file)
while(file && *file)
{
file = COM_Parse(file);
if (!strcmp(com_token, "body"))
file = Cmd_TokenizeString(file, false, false);
cmd = Cmd_Argv(0);
if (!stricmp(cmd, "body"))
{
file = COM_Parse(file);
d->body[d->numbodies].name = strdup(com_token);
file = COM_Parse(file);
d->body[d->numbodies].bone = Mod_TagNumForName(d->model, com_token);
int boneidx;
boneidx = Mod_TagNumForName(d->model, Cmd_Argv(2))-1;
if (boneidx >= 0)
{
d->body = realloc(d->body, sizeof(*d->body)*(d->numbodies+1));
Q_strncpyz(d->body[d->numbodies].name, Cmd_Argv(1), sizeof(d->body[d->numbodies].name));
d->bone[boneidx].bodyidx = d->numbodies;
d->body[d->numbodies].bone = boneidx;
d->numbodies++;
}
else if (!strcmp(com_token, "joint"))
{
for (i = 0; i < 2; i++)
{
file = COM_Parse(file);
d->joint[d->numjoints].body[i] = 0;
for (j = 0; j < d->numbodies; j++)
{
if (!strcmp(d->body[j].name, com_token))
{
d->joint[d->numjoints].body[i] = j;
break;
else if (!errors++)
Con_Printf("Unable to create body \"%s\" because bone \"%s\" does not exist in \"%s\"\n", Cmd_Argv(1), Cmd_Argv(2), mod->name);
}
else if (!stricmp(cmd, "joint"))
{
odejointinfo_t *joint;
char *name;
d->joint = realloc(d->joint, sizeof(*d->joint)*(d->numjoints+1));
joint = &d->joint[d->numjoints];
memset(joint, 0, sizeof(*joint));
Q_strncpyz(joint->name, Cmd_Argv(1), sizeof(joint->name));
name = Cmd_Argv(2);
joint->body1 = *name?rag_finddollbody(d, name):-1;
if (*name && joint->body1 < 0 && !errors++)
{
Con_Printf("Joint \"%s\" joints invalid body \"%s\" in \"%s\"\n", joint->name, name, fname);
continue;
}
name = Cmd_Argv(3);
joint->body2 = *name?rag_finddollbody(d, name):-1;
if (*name && (joint->body2 < 0 || joint->body2 == joint->body1) && !errors++)
{
if (joint->body2 == joint->body1)
Con_Printf("Joint \"%s\" joints body \"%s\" to itself in \"%s\"\n", joint->name, name, fname);
else
Con_Printf("Joint \"%s\" joints invalid body \"%s\" in \"%s\"\n", joint->name, name, fname);
continue;
}
joint->orgmatrix[0] = 1;
joint->orgmatrix[4] = 1;
joint->orgmatrix[8] = 1;
joint->bonepivot = d->body[(joint->body2 >= 0)?joint->body2:joint->body1].bone; //default the pivot object to the bone of the second object.
joint->ERP = 0.4;
joint->ERP2 = 0.4;
joint->CFM = 0.1;
joint->CFM2 = 0.1;
if (joint->body1 >= 0 || joint->body2 >= 0)
d->numjoints++;
else if (!errors++)
Con_Printf("Joint property \"%s\" not recognised in \"%s\"\n", joint->name, fname);
}
else if (!stricmp(cmd, "setjoint"))
{
int j = rag_finddolljoint(d, Cmd_Argv(1));
if (j >= 0)
{
odejointinfo_t *joint = &d->joint[j];
char *prop = Cmd_Argv(2);
char *val = Cmd_Argv(3);
if (!stricmp(prop, "type"))
{
if (!stricmp(val, "fixed"))
joint->type = JOINTTYPE_FIXED;
else if (!stricmp(val, "point"))
joint->type = JOINTTYPE_POINT;
else if (!stricmp(val, "hinge"))
joint->type = JOINTTYPE_HINGE;
else if (!stricmp(val, "slider"))
joint->type = JOINTTYPE_SLIDER;
else if (!stricmp(val, "universal"))
joint->type = JOINTTYPE_UNIVERSAL;
else if (!stricmp(val, "hinge2"))
joint->type = JOINTTYPE_HINGE2;
}
else if (!stricmp(prop, "ERP"))
joint->ERP = atof(val);
else if (!stricmp(prop, "ERP2"))
joint->ERP2 = atof(val);
else if (!stricmp(prop, "CFM"))
joint->CFM = atof(val);
else if (!stricmp(prop, "CFM2"))
joint->CFM2 = atof(val);
else if (!stricmp(prop, "FMax"))
joint->FMax = atof(val);
else if (!stricmp(prop, "FMax2"))
joint->FMax2 = atof(val);
else if (!stricmp(prop, "HiStop"))
joint->HiStop = atof(val);
else if (!stricmp(prop, "HiStop2"))
joint->HiStop2 = atof(val);
else if (!stricmp(prop, "LoStop"))
joint->LoStop = atof(val);
else if (!stricmp(prop, "LoStop2"))
joint->LoStop2 = atof(val);
else if (!stricmp(prop, "origin") || !stricmp(prop, "pivot"))
{
//the origin is specified in base-frame model space
//we need to make it relative to the joint's bodies
float omat[12] = { 1, 0, 0, atoi(Cmd_Argv(3)),
0, 1, 0, atoi(Cmd_Argv(4)),
0, 0, 1, atoi(Cmd_Argv(5))};
char *bone = Cmd_Argv(6);
i = Mod_TagNumForName(d->model, Cmd_Argv(2))-1;
joint->bonepivot = i;
Matrix3x4_Multiply(omat, bones[i].inverse, joint->orgmatrix);
}
else if (!errors++)
Con_Printf("Joint property \"%s\" not recognised in \"%s\"\n", prop, fname);
}
else if (!errors++)
Con_Printf("Joint \"%s\" not yet defined in \"%s\"\n", Cmd_Argv(1), fname);
}
}
FS_FreeFile(fptr);
return d;
}
void rag_freedoll(doll_t *doll)
{
free(doll->bone);
free(doll->body);
free(doll->joint);
free(doll);
}
void rag_flushdolls(void)
{
doll_t *d, **link;
for (link = &dolllist; *link; )
{
d = *link;
if (!d->uses)
{
*link = d->next;
rag_freedoll(d);
}
else
link = &(*link)->next;
}
}
void skel_integrate(progfuncs_t *prinst, skelobject_t *sko, skelobject_t *skelobjsrc, float ft, float mmat[12])
{
@ -364,6 +539,7 @@ void skel_reset(progfuncs_t *prinst)
{
if (skelobjects[i].world = prinst->parms->user)
{
rag_uninstanciate(&skelobjects[i]);
skelobjects[i].numbones = 0;
skelobjects[i].inuse = false;
skelobjects[i].bonematrix = NULL;
@ -372,6 +548,7 @@ void skel_reset(progfuncs_t *prinst)
while (numskelobjectsused && !skelobjects[numskelobjectsused-1].inuse)
numskelobjectsused--;
rag_flushdolls();
}
/*deletes any skeletons marked for deletion*/
@ -385,8 +562,11 @@ void skel_dodelete(progfuncs_t *prinst)
for (skelidx = 0; skelidx < numskelobjectsused; skelidx++)
{
if (skelobjects[skelidx].inuse == 2)
{
rag_uninstanciate(&skelobjects[skelidx]);
skelobjects[skelidx].inuse = 0;
}
}
while (numskelobjectsused && !skelobjects[numskelobjectsused-1].inuse)
numskelobjectsused--;
@ -418,7 +598,7 @@ skelobject_t *skel_get(progfuncs_t *prinst, int skelidx, int bonecount)
skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount);
}
skelobjects[skelidx].world = prinst->parms->user;
if (numskelobjectsused == skelidx)
if (numskelobjectsused <= skelidx)
numskelobjectsused = skelidx + 1;
skelobjects[skelidx].model = NULL;
skelobjects[skelidx].inuse = 1;
@ -459,59 +639,223 @@ void QCBUILTIN PF_skel_mmap(progfuncs_t *prinst, struct globalvars_s *pr_globals
if (!sko || sko->world != prinst->parms->user)
G_INT(OFS_RETURN) = 0;
else
G_INT(OFS_RETURN) = PR_SetString(prinst, (void*)sko->bonematrix);
G_INT(OFS_RETURN) = (char*)sko->bonematrix - prinst->stringtable;
}
//may not poke the skeletal object bone data.
void rag_uninstanciate(skelobject_t *sko)
{
int i;
if (!sko->doll)
return;
for (i = 0; i < sko->numbodies; i++)
{
World_ODE_RagDestroyBody(sko->world, &sko->body[i].odebody);
}
free(sko->body);
sko->body = NULL;
sko->numbodies = 0;
for (i = 0; i < sko->numjoints; i++)
{
World_ODE_RagDestroyJoint(sko->world, &sko->joint[i]);
}
free(sko->joint);
sko->joint = NULL;
sko->numjoints = 0;
sko->doll->uses--;
sko->doll = NULL;
}
qboolean rag_instanciate(skelobject_t *sko, doll_t *doll, float *emat, wedict_t *ent)
{
int i;
vec3_t org, porg;
float *bmat;
float bodymat[12], worldmat[12];
vec3_t aaa2[3];
galiasbone_t *bones = Mod_GetBoneInfo(sko->model);
int bone;
odebody_t *body1, *body2;
odejointinfo_t *j;
sko->numbodies = doll->numbodies;
sko->body = malloc(sizeof(*sko->body) * sko->numbodies);
sko->doll = doll;
doll->uses++;
for (i = 0; i < sko->numbodies; i++)
{
memset(&sko->body[i], 0, sizeof(sko->body[i]));
bone = doll->body[i].bone;
bmat = sko->bonematrix + bone*12;
R_ConcatTransforms((void*)emat, (void*)bmat, (void*)bodymat);
if (!World_ODE_RagCreateBody(sko->world, &sko->body[i].odebody, bodymat, ent))
return false;
}
sko->numjoints = doll->numjoints;
sko->joint = malloc(sizeof(*sko->joint) * sko->numjoints);
memset(sko->joint, 0, sizeof(*sko->joint) * sko->numjoints);
for(i = 0; i < sko->numjoints; i++)
{
j = &doll->joint[i];
body1 = j->body1>=0?&sko->body[j->body1].odebody:NULL;
body2 = j->body2>=0?&sko->body[j->body2].odebody:NULL;
bone = j->bonepivot;
bmat = sko->bonematrix + bone*12;
R_ConcatTransforms(bmat, j->orgmatrix, bodymat);
R_ConcatTransforms((void*)emat, (void*)bodymat, (void*)worldmat);
aaa2[0][0] = worldmat[3];
aaa2[0][1] = worldmat[3+4];
aaa2[0][2] = worldmat[3+8];
// P_RunParticleEffectTypeString(aaa2[0], vec3_origin, 1, "te_spike");
aaa2[1][0] = 1;
aaa2[1][1] = 0;
aaa2[1][2] = 0;
aaa2[2][0] = 0;
aaa2[2][1] = 1;
aaa2[2][2] = 0;
// VectorCopy(j->offset, aaa2[0]); //fixme: transform these vectors into world space, and transform to match the current positions of the bones.
// VectorCopy(j->axis, aaa2[1]);
// VectorCopy(j->axis2, aaa2[2]);
World_ODE_RagCreateJoint(sko->world, &sko->joint[i], j, body1, body2, aaa2);
}
return true;
}
void rag_derive(skelobject_t *sko, skelobject_t *asko, float *emat)
{
doll_t *doll = sko->doll;
float *bmat = sko->bonematrix;
float *amat = asko?asko->bonematrix:NULL;
galiasbone_t *bones = Mod_GetBoneInfo(sko->model);
int i;
float invemat[12];
float bodymat[12];
Matrix3x4_Invert(emat, invemat);
for (i = 0; i < doll->numbones; i++)
{
if (doll->bone[i].bodyidx >= 0)
{
World_ODE_RagMatrixFromBody(sko->world, &sko->body[doll->bone[i].bodyidx].odebody, bodymat);
//that body matrix is in world space, so transform to model space for our result
R_ConcatTransforms((void*)invemat, (void*)bodymat, (void*)((float*)bmat+i*12));
}
else if (amat)
{
//this bone has no joint object, use the anim sko's relative pose info instead
if (bones[i].parent >= 0)
R_ConcatTransforms((void*)(bmat + bones[i].parent*12), (void*)((float*)amat+i*12), (void*)((float*)bmat+i*12));
else
memcpy((void*)((float*)bmat+i*12), (void*)((float*)amat+i*12), sizeof(float)*12);
}
}
}
//update a skeletal object to track its ragdoll/apply a ragdoll to a skeletal object.
void QCBUILTIN PF_skel_ragedit(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//do we want to be able to generate a ragdoll object with this function too?
#ifdef RAGDOLL
int skelidx = G_FLOAT(OFS_PARM0);
char *skelname = PR_GetStringOfs(prinst, OFS_PARM1);
wedict_t *wed = (wedict_t*)G_EDICT(prinst, OFS_PARM0);
char *ragname = PR_GetStringOfs(prinst, OFS_PARM1);
int parentskel = G_FLOAT(OFS_PARM2);
float *entorg = G_VECTOR(OFS_PARM3);
float *forward = G_VECTOR(OFS_PARM4);
float *right = G_VECTOR(OFS_PARM5);
float *up = G_VECTOR(OFS_PARM6);
int skelidx = wed->xv->skeletonindex;
skelobject_t *sko, *psko;
doll_t *doll;
int i;
float emat[12];
extern cvar_t temp1;
bonemat_fromqcvectors(emat, forward, right, up, entorg);
{
vec3_t d[3], a;
//fixme: respond to renderflags&USEAXIS? scale?
a[0] = wed->v->angles[0] * -1; /*mod_alias bug*/
a[1] = wed->v->angles[1];
a[2] = wed->v->angles[2];
AngleVectors(a, d[0], d[1], d[2]);
bonemat_fromqcvectors(emat, d[0], d[1], d[2], wed->v->origin);
skelidx = wed->xv->skeletonindex;
}
G_FLOAT(OFS_RETURN) = 0;
sko = skel_get(prinst, skelidx, 0);
if (!sko)
//the parent skeletal object must be relative, if specified.
psko = skel_get(prinst, parentskel, 0);
if (psko && psko->type != SKOT_RELATIVE)
return;
if (*skelname)
sko = skel_get(prinst, skelidx, 0);
if (!sko)
{
doll = rag_loaddoll(sko->model, skelname);
if (!doll)
Con_DPrintf("PF_skel_ragedit: invalid skeletal object\n");
return;
}
if (!sko->world->ode.ode)
{
Con_DPrintf("PF_skel_ragedit: ODE not enabled\n");
return;
}
if (*ragname)
{
if (sko->doll && !strcmp(sko->doll->name, ragname))
doll = sko->doll;
else
doll = rag_loaddoll(sko->model, ragname, sko->numbones);
if (!doll)
{
Con_DPrintf("PF_skel_ragedit: invalid doll\n");
return;
}
}
else
{
/*no doll name makes it revert to a normal skeleton*/
sko->doll = NULL;
rag_uninstanciate(sko);
G_FLOAT(OFS_RETURN) = 1;
return;
}
if (sko->doll != doll)
if (sko->type != SKOT_ABSOLUTE)
{
sko->doll = doll;
free(sko->body);
sko->numbodies = doll->numbodies;
sko->body = malloc(sko->numbodies * sizeof(*sko->body));
memset(sko->body, 0, sko->numbodies * sizeof(*sko->body));
// for (i = 0; i < sko->numbodies; i++)
// sko->body[i].jointo = doll->body[i].bone * 12;
float tmp[12];
float *bmat = sko->bonematrix;
galiasbone_t *bones = Mod_GetBoneInfo(sko->model);
for (i = 0; i < sko->numbones; i++)
{
//bones without parents are technically already absolute
if (bones[i].parent >= 0)
{
//write to a tmp to avoid premature clobbering
R_ConcatTransforms((void*)(bmat + bones[i].parent*12), (void*)((float*)bmat+i*12), (void*)tmp);
memcpy((void*)(bmat+i*12), tmp, sizeof(tmp));
}
}
sko->type = SKOT_ABSOLUTE;
}
psko = skel_get(prinst, parentskel, 0);
skel_integrate(prinst, sko, psko, host_frametime, emat);
if (sko->doll != doll || temp1.ival)
{
rag_uninstanciate(sko);
if (!rag_instanciate(sko, doll, emat, wed))
{
rag_uninstanciate(sko);
Con_DPrintf("PF_skel_ragedit: unable to instanciate objects\n");
G_FLOAT(OFS_RETURN) = 0;
return;
}
}
rag_derive(sko, psko, emat);
// skel_integrate(prinst, sko, psko, host_frametime, emat);
G_FLOAT(OFS_RETURN) = 1;
#endif
@ -527,6 +871,7 @@ void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_glob
model_t *model;
int midx;
int type;
int i;
midx = G_FLOAT(OFS_PARM0);
type = (*prinst->callargc > 1)?G_FLOAT(OFS_PARM1):SKOT_RELATIVE;
@ -554,6 +899,15 @@ void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_glob
skelobj->model = model;
skelobj->type = type;
/*
for (i = 0; i < numbones; i++)
{
galiasbone_t *bones = Mod_GetBoneInfo(skelobj->model);
Matrix3x4_Invert_Simple(bones[i].inverse, skelobj->bonematrix + i*12);
}
skelobj->type = SKOT_ABSOLUTE;
*/
G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1;
}
@ -605,6 +959,16 @@ void QCBUILTIN PF_skel_build(progfuncs_t *prinst, struct globalvars_s *pr_global
if (firstbone < 0)
firstbone = 0;
if (skelobj->type != SKOT_RELATIVE)
{
if (firstbone > 0 || lastbone < skelobj->numbones || retainfrac)
{
Con_Printf("skel_build on non-relative skeleton\n");
return;
}
skelobj->type = SKOT_RELATIVE; //entire model will get replaced, convert it.
}
if (retainfrac == 0)
{
/*replace everything*/

View file

@ -218,7 +218,8 @@ int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_lis
typedef struct quakeparms_s
{
char *basedir;
char *basedir; //working directory
char *binarydir; //exe directory
int argc;
const char **argv;
void *membase;
@ -240,6 +241,7 @@ extern qboolean noclip_anglehack;
extern quakeparms_t host_parms;
extern cvar_t fs_gamename;
extern cvar_t fs_gamedownload;
extern cvar_t com_protocolname;
extern cvar_t com_modname;
extern cvar_t sys_ticrate;

View file

@ -4,6 +4,7 @@
#include "gl_draw.h"
texid_t missing_texture;
texid_t missing_texture_gloss;
texid_t translate_texture;
shader_t *translate_shader;
@ -17,7 +18,9 @@ static mpic_t *draw_backtile;
static shader_t *shader_draw_fill, *shader_draw_fill_trans;
mpic_t *draw_disc;
shader_t *shader_brighten;
shader_t *shader_contrastup;
shader_t *shader_contrastdown;
shader_t *shader_brightness;
shader_t *shader_polyblend;
shader_t *shader_menutint;
@ -31,7 +34,7 @@ unsigned int r2d_be_flags;
extern cvar_t scr_conalpha;
extern cvar_t gl_conback;
extern cvar_t gl_font;
extern cvar_t gl_contrast;
extern cvar_t gl_contrast, gl_brightness;
extern cvar_t gl_screenangle;
extern cvar_t vid_conautoscale;
extern cvar_t vid_conheight;
@ -124,6 +127,8 @@ Image loading code must be ready for use at this point.
*/
void R2D_Init(void)
{
unsigned int nogloss[4*4];
int i;
conback = NULL;
Shader_Init();
@ -144,7 +149,10 @@ void R2D_Init(void)
#pragma warningmsg("Fixme: move conwidth handling into here")
#endif
for (i = 0; i < 4*4; i++)
nogloss[i] = LittleLong(0xff101010);
missing_texture = R_LoadTexture8("no_texture", 16, 16, (unsigned char*)r_notexture_mip + r_notexture_mip->offsets[0], IF_NOALPHA|IF_NOGAMMA, 0);
missing_texture_gloss = R_LoadTexture("no_texture_gloss", 4, 4, TF_RGBA32, (unsigned char*)nogloss, IF_NOGAMMA);
translate_texture = r_nulltex;
ch_int_texture = r_nulltex;
@ -182,10 +190,11 @@ void R2D_Init(void)
"blendfunc blend\n"
"}\n"
"}\n");
shader_brighten = R_RegisterShader("constrastshader",
shader_contrastup = R_RegisterShader("constrastupshader",
"{\n"
"program defaultfill\n"
"{\n"
"nodepthtest\n"
"map $whiteimage\n"
"blendfunc gl_dst_color gl_one\n"
"rgbgen vertex\n"
@ -193,6 +202,30 @@ void R2D_Init(void)
"}\n"
"}\n"
);
shader_contrastdown = R_RegisterShader("constrastdownshader",
"{\n"
"program defaultfill\n"
"{\n"
"nodepthtest\n"
"map $whiteimage\n"
"blendfunc gl_dst_color gl_zero\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"}\n"
"}\n"
);
shader_brightness = R_RegisterShader("brightnessshader",
"{\n"
"program defaultfill\n"
"{\n"
"nodepthtest\n"
"map $whiteimage\n"
"blendfunc gl_one gl_one\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"}\n"
"}\n"
);
shader_polyblend = R_RegisterShader("polyblendshader",
"{\n"
"program defaultfill\n"
@ -520,7 +553,9 @@ void R2D_ConsoleBackground (int firstline, int lastline, qboolean forceopaque)
void R2D_EditorBackground (void)
{
R2D_ScalePic(0, 0, vid.width, vid.height, conback);
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(0, 0, vid.width, vid.height);
// R2D_ScalePic(0, 0, vid.width, vid.height, conback);
}
/*
@ -760,7 +795,7 @@ void R2D_BrightenScreen (void)
RSpeedMark();
if (gl_contrast.value <= 1.0)
if (gl_contrast.value != 1.0 && gl_brightness.value != 0)
return;
if (r_refdef.flags & Q2RDF_NOWORLDMODEL)
@ -772,12 +807,28 @@ void R2D_BrightenScreen (void)
while (f > 1)
{
if (f >= 2)
{
R2D_ImageColours (1, 1, 1, 1);
else
R2D_ImageColours (f - 1, f - 1, f - 1, 1);
R2D_ScalePic(0, 0, vid.width, vid.height, shader_brighten);
f *= 0.5;
}
else
{
R2D_ImageColours (f - 1, f - 1, f - 1, 1);
f = 1;
}
R2D_ScalePic(0, 0, vid.width, vid.height, shader_contrastup);
}
if (f < 1)
{
R2D_ImageColours (f, f, f, 1);
R2D_ScalePic(0, 0, vid.width, vid.height, shader_contrastdown);
}
if (gl_brightness.value)
{
R2D_ImageColours (gl_brightness.value, gl_brightness.value, gl_brightness.value, 1);
R2D_ScalePic(0, 0, vid.width, vid.height, shader_brightness);
}
R2D_ImageColours (1, 1, 1, 1);
/*make sure the hud is drawn if needed*/

View file

@ -1592,9 +1592,9 @@ char *particle_set_high =
"float f;\n"
"nst = scoord.xy / scoord.w;\n"
"nst = (1.0 + nst)/2.0;\n"
"f = 1 - length(tcoord);\n"
// f = 1 - tcoord*tcoord;
"if (f < 0) discard;\n"
"f = 1.0 - length(tcoord);\n"
// f = 1.0 - tcoord*tcoord;
"if (f < 0.0) discard;\n"
"f *= alph;\n"
"gl_FragColor = texture2D(s_t0, nst - tcoord*f);\n"
"}\n"

View file

@ -1418,6 +1418,14 @@ static qbyte *R_MarkLeafSurfaces_Q1 (void)
}
#endif
/*
static qbyte *Surf_MaskVis(qbyte *src, qbyte *dest)
{
int i;
if (cl.worldmodel->leafs[i].ma
}
*/
qbyte *frustumvis;
/*
================
R_RecursiveWorldNode
@ -1456,6 +1464,9 @@ start:
{
pleaf = (mleaf_t *)node;
c = pleaf - cl.worldmodel->leafs;
frustumvis[c>>3] |= 1<<(c&7);
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
@ -2019,6 +2030,9 @@ void Surf_SetupFrame(void)
case Q1CONTENTS_SKY:
r_viewcontents |= FTECONTENTS_SKY;
break;
case Q1CONTENTS_SOLID:
r_viewcontents |= FTECONTENTS_SOLID;
break;
}
}
}
@ -2176,7 +2190,9 @@ R_DrawWorld
void Surf_DrawWorld (void)
{
qbyte *vis;
//surfvis vs entvis - the key difference is that surfvis is surfaces while entvis is volume. though surfvis should be frustum culled also for lighting. entvis doesn't care.
qbyte *surfvis, *entvis;
qbyte frustumvis_[MAX_MAP_LEAFS/8];
RSpeedLocals();
if (r_refdef.flags & Q2RDF_NOWORLDMODEL)
@ -2221,14 +2237,14 @@ void Surf_DrawWorld (void)
#ifdef Q3BSPS
if (currententity->model->fromgame == fg_quake3)
{
vis = R_MarkLeaves_Q3 ();
entvis = surfvis = R_MarkLeaves_Q3 ();
Surf_RecursiveQ3WorldNode (cl.worldmodel->nodes, (1<<FRUSTUMPLANES)-1);
//Surf_LeafWorldNode ();
}
else
#endif
{
vis = R_MarkLeaves_Q2 ();
entvis = surfvis = R_MarkLeaves_Q2 ();
VectorCopy (r_refdef.vieworg, modelorg);
Surf_RecursiveQ2WorldNode (cl.worldmodel->nodes);
}
@ -2238,14 +2254,14 @@ void Surf_DrawWorld (void)
#ifdef MAP_PROC
if (cl.worldmodel->fromgame == fg_doom3)
{
vis = D3_CalcVis(cl.worldmodel, r_origin);
entvis = surfvis = D3_CalcVis(cl.worldmodel, r_origin);
}
else
#endif
#ifdef MAP_DOOM
if (currentmodel->fromgame == fg_doom)
{
vis = NULL;
entvis = surfvis = NULL;
GLR_DoomWorld();
}
else
@ -2253,37 +2269,42 @@ void Surf_DrawWorld (void)
#ifdef TERRAIN
if (currentmodel->type == mod_heightmap)
{
vis = NULL;
entvis = surfvis = NULL;
}
else
#endif
{
//extern cvar_t temp1;
// if (0)//temp1.value)
// vis = R_MarkLeafSurfaces_Q1();
// entvis = surfvis = R_MarkLeafSurfaces_Q1();
// else
{
vis = R_MarkLeaves_Q1 ();
entvis = R_MarkLeaves_Q1 ();
if (!(r_novis.ival & 2))
VectorCopy (r_origin, modelorg);
frustumvis = frustumvis_;
memset(frustumvis, 0, (cl.worldmodel->numleafs + 7)>>3);
if (r_refdef.useperspective)
Surf_RecursiveWorldNode (cl.worldmodel->nodes, 0x1f);
else
Surf_OrthoRecursiveWorldNode (cl.worldmodel->nodes, 0x1f);
surfvis = frustumvis;
}
}
if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
{
CL_LinkStaticEntities(vis);
// CL_LinkStaticEntities(entvis);
TRACE(("dbg: calling R_DrawParticles\n"));
if (!r_refdef.recurse)
P_DrawParticles ();
}
RSpeedEnd(RSPEED_WORLDNODE);
TRACE(("dbg: calling BE_DrawWorld\n"));
BE_DrawWorld(true, vis);
BE_DrawWorld(true, surfvis);
/*FIXME: move this away*/
if (cl.worldmodel->fromgame == fg_quake || cl.worldmodel->fromgame == fg_halflife)
@ -2486,19 +2507,9 @@ int Surf_NewExternalLightmaps(int count, char *filepattern, qboolean deluxe)
return first;
}
/*
==================
GL_BuildLightmaps
Builds the lightmap texture
with all the surfaces from all brush models
Groups surfaces into their respective batches (based on the lightmap number).
==================
*/
void Surf_BuildLightmaps (void)
void Surf_BuildModelLightmaps (model_t *m)
{
int i, j, t;
model_t *m;
int i, t;
int shift;
msurface_t *surf;
batch_t *batch;
@ -2506,33 +2517,8 @@ void Surf_BuildLightmaps (void)
int ptype;
int newfirst;
r_framecount = 1; // no dlightcache
for (i = 0; i < numlightmaps; i++)
{
if (!lightmap[i])
break;
BZ_Free(lightmap[i]);
lightmap[i] = NULL;
}
Surf_LightmapMode();
r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
if (cl.worldmodel->fromgame == fg_doom)
return; //no lightmaps.
numlightmaps = 0;
for (j=1 ; j<MAX_MODELS ; j++)
{
m = cl.model_precache[j];
if (!m)
break;
if (!lightmap_bytes)
return;
#ifdef TERRAIN
if (m->terrain)
@ -2540,12 +2526,12 @@ void Surf_BuildLightmaps (void)
#endif
if (m->type != mod_brush)
continue;
return;
if (!m->lightmaps.count)
continue;
return;
if (m->needload)
continue;
return;
currentmodel = m;
shift = Surf_LightmapShift(currentmodel);
@ -2554,7 +2540,7 @@ void Surf_BuildLightmaps (void)
newfirst = cl.model_precache[1]->lightmaps.first;
else
{
if (!m->lightdata && m->lightmaps.count)
if (!m->lightdata && m->lightmaps.count && m->fromgame == fg_quake3)
{
char pattern[MAX_QPATH];
COM_StripAllExtensions(m->name, pattern, sizeof(pattern));
@ -2672,6 +2658,61 @@ void Surf_BuildLightmaps (void)
}
m->lightmaps.first = newfirst;
}
void Surf_ClearLightmaps(void)
{
lightmap_bytes = 0;
}
/*
==================
GL_BuildLightmaps
Builds the lightmap texture
with all the surfaces from all brush models
Groups surfaces into their respective batches (based on the lightmap number).
==================
*/
void Surf_BuildLightmaps (void)
{
int i, j;
model_t *m;
r_framecount = 1; // no dlightcache
for (i = 0; i < numlightmaps; i++)
{
if (!lightmap[i])
break;
BZ_Free(lightmap[i]);
lightmap[i] = NULL;
}
Surf_LightmapMode();
r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
numlightmaps = 0;
if (cl.worldmodel->fromgame == fg_doom)
return; //no lightmaps.
for (j=1 ; j<MAX_MODELS ; j++)
{
m = cl.model_precache[j];
if (!m)
break;
Surf_BuildModelLightmaps(m);
}
for (j=1 ; j<MAX_CSQCMODELS ; j++)
{
m = cl.model_csqcprecache[j];
if (!m)
break;
Surf_BuildModelLightmaps(m);
}
BE_UploadAllLightmaps();
}
#endif

View file

@ -200,7 +200,9 @@ void Surf_LessenStains(void);
void Surf_WipeStains(void);
void Surf_DeInit(void);
void Surf_Clear(struct model_s *mod);
void Surf_BuildLightmaps(void);
void Surf_BuildLightmaps(void); //enables Surf_BuildModelLightmaps, calls it for each bsp.
void Surf_ClearLightmaps(void); //stops Surf_BuildModelLightmaps from working.
void Surf_BuildModelLightmaps (struct model_s *m); //rebuild lightmaps for a single bsp. beware of submodels.
void Surf_RenderDynamicLightmaps (struct msurface_s *fa);
void Surf_RenderAmbientLightmaps (struct msurface_s *fa, int ambient);
int Surf_LightmapShift (struct model_s *model);
@ -360,7 +362,8 @@ qboolean Media_ShowFilm(void);
void Media_CaptureDemoEnd(void);
void Media_RecordFrame (void);
qboolean Media_PausedDemo (void);
double Media_TweekCaptureFrameTime(double time);
int Media_Capturing (void);
double Media_TweekCaptureFrameTime(double oldtime, double time);
void MYgluPerspective(double fovx, double fovy, double zNear, double zFar);
@ -424,6 +427,7 @@ extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_shadows;
extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha;
extern cvar_t r_waterstyle;
extern cvar_t r_lavastyle;
extern cvar_t r_dynamic;
extern cvar_t r_novis;
extern cvar_t r_netgraph;

View file

@ -41,7 +41,7 @@ void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue);
void GL_Texture_Anisotropic_Filtering_Callback (struct cvar_s *var, char *oldvalue);
#endif
cvar_t _vid_wait_override = CVARAF ("vid_wait", "",
cvar_t _vid_wait_override = CVARAF ("vid_wait", "1",
"_vid_wait_override", CVAR_ARCHIVE);
cvar_t _windowed_mouse = CVARF ("_windowed_mouse","1",
@ -169,8 +169,8 @@ cvar_t scr_viewsize = CVARFC("viewsize", "100",
cvar_t vid_conautoscale = CVARF ("vid_conautoscale", "2",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK);
#else
cvar_t vid_conautoscale = CVARF ("vid_conautoscale", "0",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK);
cvar_t vid_conautoscale = CVARFD ("vid_conautoscale", "0",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, "Changes the 2d scale, including hud, console, and fonts. To specify an explicit font size, divide the desired 'point' size by 8 to get the scale. High values will be clamped to maintain at least a 320*200 virtual size.");
#endif
cvar_t vid_conheight = CVARF ("vid_conheight", "0",
CVAR_ARCHIVE);
@ -256,13 +256,14 @@ cvar_t gl_compress = CVARF ("gl_compress", "0",
cvar_t gl_conback = CVARFC ("gl_conback", "",
CVAR_RENDERERCALLBACK, R2D_Conback_Callback);
cvar_t gl_contrast = CVAR ("gl_contrast", "1");
cvar_t gl_brightness = CVAR ("gl_brightness", "0");
cvar_t gl_detail = CVARF ("gl_detail", "0",
CVAR_ARCHIVE);
cvar_t gl_detailscale = CVAR ("gl_detailscale", "5");
cvar_t gl_font = CVARFD ("gl_font", "",
CVAR_RENDERERCALLBACK, ("Specifies the font file to use. a value such as FONT:ALTFONT specifies an alternative font to be used when ^^a is used."
"When using TTF fonts, you will likely need to scale text to at least 150% - vid_conautoscale 1.5 will do this."
"TTF fonts may be loaded from your windows directory. \'gl_font cour\' loads eg: c:\\windows\\fonts\\cour.ttf."
CVAR_RENDERERCALLBACK, ("Specifies the font file to use. a value such as FONT:ALTFONT specifies an alternative font to be used when ^^a is used.\n"
"When using TTF fonts, you will likely need to scale text to at least 150% - vid_conautoscale 1.5 will do this.\n"
"TTF fonts may be loaded from your windows directory. \'gl_font cour:couri\' loads eg: c:\\windows\\fonts\\cour.ttf, and uses the italic version of courier for alternative text."
));
cvar_t gl_lateswap = CVAR ("gl_lateswap", "0");
cvar_t gl_lerpimages = CVARF ("gl_lerpimages", "1", CVAR_ARCHIVE);
@ -337,6 +338,7 @@ cvar_t r_shadow_bumpscale_bumpmap = SCVAR ("r_shadow_bumpscale_bumpmap", "10"
cvar_t r_glsl_offsetmapping = CVARF ("r_glsl_offsetmapping", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM);
cvar_t r_glsl_offsetmapping_scale = CVAR ("r_glsl_offsetmapping_scale", "0.04");
cvar_t r_glsl_offsetmapping_reliefmapping = CVARF("r_glsl_offsetmapping_reliefmapping", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM);
cvar_t r_glsl_turbscale = CVARF ("r_glsl_turbscale", "1", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world = SCVARF ("r_shadow_realtime_world", "0", CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world_shadows = SCVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE);
@ -346,15 +348,16 @@ cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_ligh
cvar_t r_shadow_shadowmapping = SCVARF ("debug_r_shadow_shadowmapping", "0", 0);
cvar_t r_sun_dir = SCVAR ("r_sun_dir", "0.2 0.5 0.8");
cvar_t r_sun_colour = SCVARF ("r_sun_colour", "0 0 0", CVAR_ARCHIVE);
cvar_t r_waterstyle = CVARF ("r_waterstyle", "0", CVAR_ARCHIVE|CVAR_SHADERSYSTEM);
cvar_t r_waterstyle = CVARFD ("r_waterstyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Changes how water, slime, and teleporters are drawn. Possible values are:\n0: fastturb-style block colour.\n1: regular q1-style water.\n2: refraction(ripply and transparent)\n3: refraction with reflection at an angle\n4: ripplemapped without reflections (requires particle effects)\n5: ripples+reflections");
cvar_t r_lavastyle = CVARFD ("r_lavastyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only lava.");
cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "0");
cvar_t vid_preservegamma = SCVAR ("vid_preservegamma", "0");
cvar_t vid_hardwaregamma = SCVARF ("vid_hardwaregamma", "1",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t vid_desktopgamma = SCVARF ("vid_desktopgamma", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t vid_desktopgamma = CVARFD ("vid_desktopgamma", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Apply gamma ramps upon the desktop rather than the window.");
cvar_t r_fog_exp2 = CVARD ("r_fog_exp2", "1", "Expresses how fog fades with distance. 0 (matching DarkPlaces) is typically more realistic, while 1 (matching FitzQuake and others) is more common.");
@ -420,8 +423,9 @@ void GLRenderer_Init(void)
Cvar_Register (&r_glsl_offsetmapping, GRAPHICALNICETIES);
Cvar_Register (&r_glsl_offsetmapping_scale, GRAPHICALNICETIES);
Cvar_Register (&r_glsl_offsetmapping_reliefmapping, GRAPHICALNICETIES);
Cvar_Register (&r_glsl_turbscale, GRAPHICALNICETIES);
Cvar_Register (&gl_contrast, GLRENDEREROPTIONS);
#ifdef R_XFLIP
Cvar_Register (&r_xflip, GLRENDEREROPTIONS);
#endif
@ -601,6 +605,7 @@ void Renderer_Init(void)
Cvar_Register (&r_sun_dir, GRAPHICALNICETIES);
Cvar_Register (&r_sun_colour, GRAPHICALNICETIES);
Cvar_Register (&r_waterstyle, GRAPHICALNICETIES);
Cvar_Register (&r_lavastyle, GRAPHICALNICETIES);
Cvar_Register (&r_wireframe, GRAPHICALNICETIES);
Cvar_Register (&r_stereo_separation, GRAPHICALNICETIES);
Cvar_Register (&r_stereo_method, GRAPHICALNICETIES);
@ -635,6 +640,8 @@ void Renderer_Init(void)
Cvar_Register(&r_fullbrightSkins, GRAPHICALNICETIES);
Cvar_Register (&mod_md3flags, GRAPHICALNICETIES);
Cvar_Register (&gl_contrast, GLRENDEREROPTIONS);
Cvar_Register (&gl_brightness, GLRENDEREROPTIONS);
//renderer
@ -683,7 +690,6 @@ void Renderer_Init(void)
P_InitParticleSystem();
R_InitTextures();
RQ_Init();
}
qboolean Renderer_Started(void)
@ -976,6 +982,7 @@ void R_ShutdownRenderer(void)
if (host_basepal)
BZ_Free(host_basepal);
host_basepal = NULL;
Surf_ClearLightmaps();
RQ_Shutdown();
@ -1110,6 +1117,7 @@ TRACE(("dbg: R_ApplyRenderer: wad loaded\n"));
Draw_Init();
TRACE(("dbg: R_ApplyRenderer: draw inited\n"));
R_Init();
RQ_Init();
R_InitParticleTexture ();
TRACE(("dbg: R_ApplyRenderer: renderer inited\n"));
SCR_Init();
@ -1445,7 +1453,10 @@ TRACE(("dbg: R_RestartRenderer_f\n"));
if (!newr.renderer)
{
int i;
Con_Printf("vid_renderer unset or unsupported. Using default.\n");
if (*vid_renderer.string)
Con_Printf("vid_renderer unsupported. Using default.\n");
else
Con_DPrintf("vid_renderer unset. Using default.\n");
//gotta do this after main hunk is saved off.
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)

View file

@ -125,6 +125,39 @@ void RQ_RenderBatchClear(void)
rqmingrad = NUMGRADUATIONS-1;
}
//render without clearing
void RQ_RenderBatch(void)
{
#define SLOTS 512
void *slot[SLOTS];
void *typeptr = NULL;
int maxslot = SLOTS;
void (*lr) (int count, void **objects, void *objtype) = NULL;
int i;
renderque_t *rq;
for (i = rqmaxgrad; i>=rqmingrad; i--)
// for (i = rqmingrad; i<=rqmaxgrad; i++)
{
for (rq = distrque[i]; rq; rq=rq->next)
{
if (!maxslot || rq->render != lr || typeptr != rq->data2)
{
if (maxslot != SLOTS)
lr(SLOTS - maxslot, &slot[maxslot], typeptr);
maxslot = SLOTS;
}
slot[--maxslot] = rq->data1;
typeptr = rq->data2;
lr = rq->render;
}
}
if (maxslot != SLOTS)
lr(SLOTS - maxslot, &slot[maxslot], typeptr);
}
void RQ_Shutdown(void)
{
Z_Free(initialque);

View file

@ -5,6 +5,7 @@ void RQ_BeginFrame(void);
void RQ_AddDistReorder(void (*render) (int count, void **objects, void *objtype), void *object, void *objtype, float *pos);
void RQ_RenderBatchClear(void);
void RQ_RenderBatch(void);
typedef struct renderque_s
{

View file

@ -2554,6 +2554,19 @@ void Sbar_IntermissionNumber (int x, int y, int num, int digits, int color, qboo
}
}
#define COL_TEAM_LOWAVGHIGH COLUMN("low/avg/high", 12*8, {sprintf (num, "%3i/%3i/%3i", plow, pavg, phigh); Draw_FunString ( x, y, num); })
#define COL_TEAM_TEAM COLUMN("team", 4*8, {Draw_FunStringWidth ( x, y, tm->team, 4*8); \
if (!strncmp(cl.players[cl.playernum[0]].team, tm->team, 16))\
{\
Draw_FunString ( x - 1*8, y, "^Ue010");\
Draw_FunString ( x + 4*8, y, "^Ue011");\
}\
})
#define COL_TEAM_TOTAL COLUMN("total", 5*8, {Draw_FunString ( x, y, va("%5i", tm->frags)); })
#define COL_TEAM_PLAYERS COLUMN("players", 7*8, {Draw_FunString ( x, y, va("%5i", tm->players)); })
#define ALL_TEAM_COLUMNS COL_TEAM_LOWAVGHIGH COL_TEAM_TEAM COL_TEAM_TOTAL COL_TEAM_PLAYERS
/*
==================
Sbar_TeamOverlay
@ -2565,10 +2578,9 @@ added by Zoid
void Sbar_TeamOverlay (void)
{
mpic_t *pic;
int i, k, l;
int x, y;
int i, k;
int x, y, l;
char num[12];
char team[5];
team_t *tm;
int plow, phigh, pavg;
@ -2592,19 +2604,31 @@ void Sbar_TeamOverlay (void)
y += 24;
}
x = (vid.width - 320)/2 + 36;
Draw_FunString(x, y, "low/avg/high team total players");
x = l = (vid.width - 320)/2 + 36;
#define COLUMN(title, cwidth, code) Draw_FunString(x, y, title), x+=cwidth + 8;
ALL_TEAM_COLUMNS
// if (rank_width+(cwidth)+8 <= vid.width) {showcolumns |= (1<<COLUMN##title); rank_width += cwidth+8;}
// Draw_FunString(x, y, "low/avg/high");
// Draw_FunString(x+13*8, y, "team");
// Draw_FunString(x+18*8, y, "total");
// Draw_FunString(x+24*8, y, "players");
y += 8;
// Draw_String(x, y, "------------ ---- ----- -------");
Draw_FunString(x, y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1e\x1e\x1f");
x = l;
#undef COLUMN
#define COLUMN(title, cwidth, code) {char buf[64*6]; int t = (cwidth)/8; int c=0; while (t-->0) {buf[c++] = '^'; buf[c++] = 'U'; buf[c++] = 'e'; buf[c++] = '0'; buf[c++] = '1'; buf[c++] = (c==5?'d':(!t?'f':'e'));} buf[c] = 0; Draw_FunString(x, y, buf); x += cwidth + 8;}
ALL_TEAM_COLUMNS
// Draw_FunString(x, y, "^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01e^Ue01f ^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f");
y += 8;
#undef COLUMN
// sort the teams
Sbar_SortTeams();
// draw the text
l = scoreboardlines;
for (i=0 ; i < scoreboardteams && y <= vid.height-10 ; i++)
{
k = teamsort[i];
@ -2624,6 +2648,13 @@ void Sbar_TeamOverlay (void)
if (pavg < 0 || pavg > 999)
pavg = 999;
x = l;
#if 1
#define COLUMN(title, cwidth, code) code; x+=cwidth + 8;
ALL_TEAM_COLUMNS
#undef COLUMN
#else
sprintf (num, "%3i/%3i/%3i", plow, pavg, phigh);
Draw_FunString ( x, y, num);
@ -2641,10 +2672,10 @@ void Sbar_TeamOverlay (void)
if (!strncmp(cl.players[cl.playernum[0]].team, tm->team, 16))
{
Draw_FunString ( x + 104 - 8, y, "^Ue016");
Draw_FunString ( x + 104 + 32, y, "^Ue017");
Draw_FunString ( x + 104 - 8, y, "^Ue010");
Draw_FunString ( x + 104 + 32, y, "^Ue011");
}
#endif
y += 8;
}
y += 8;

View file

@ -81,7 +81,7 @@ void SCR_ShowPic_Clear(void);
//a header is better than none...
void Draw_TextBox (int x, int y, int width, int lines);
qboolean SCR_ScreenShot (char *filename);
qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height);
void SCR_DrawTwoDimensional(int uimenu, qboolean nohud);

View file

@ -50,7 +50,7 @@ vec3_t listener_up = {0, 0, 1};
vec3_t listener_velocity;
vec_t sound_nominal_clip_dist=1000.0;
#define MAX_SFX 512
#define MAX_SFX 2048
sfx_t *known_sfx; // hunk allocated [MAX_SFX]
int num_sfx;
@ -901,7 +901,7 @@ void S_Startup (void)
break;
}
sound_started = !!sndcardinfo;
sound_started = true;//!!sndcardinfo;
S_ClearRaw();

View file

@ -6,10 +6,10 @@ java code has a function or two which just periodically calls us to ask us to du
#include <jni.h>
#include <pthread.h>
//static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static soundcardinfo_t *sys_sc = NULL;
extern int sys_soundflags;
//called by the java code when it wants to know what sort of AudioTrack format to use.
JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_audioinfo(JNIEnv *env, jclass this, jint arg)
{
soundcardinfo_t *sc = sys_sc;
@ -33,8 +33,7 @@ JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_paintaudio(JNIEnv *env, jcl
int offset = 0;
soundcardinfo_t *sc = sys_sc;
int framesz;
// if (!pthread_mutex_lock(&mutex))
{
if (sc)
{
int buffersize = sc->sn.samples*sc->sn.samplebits/8;
@ -65,23 +64,19 @@ JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_paintaudio(JNIEnv *env, jcl
}
else
offset = len; /*so the playback thread ends up blocked properly*/
// pthread_mutex_unlock(&mutex);
}
return offset;
}
static void Droid_Shutdown(soundcardinfo_t *sc)
{
// pthread_mutex_lock(&mutex);
//fixme: what if we're currently inside Java_com_fteqw_FTEDroidEngine_paintaudio?
sys_sc = NULL;
free(sc->sn.buffer);
sys_soundflags = 0;
// pthread_mutex_unlock(&mutex);
}
//return the number of samples that have already been submitted to the device.
static unsigned int Droid_GetDMAPos(soundcardinfo_t *sc)
{
sc->sn.samplepos = sc->snd_sent / (sc->sn.samplebits/8);
@ -90,12 +85,10 @@ static unsigned int Droid_GetDMAPos(soundcardinfo_t *sc)
static void Droid_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{
// pthread_mutex_unlock(&mutex);
}
static void *Droid_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
{
// pthread_mutex_lock(&mutex);
return sc->sn.buffer;
}
@ -116,8 +109,6 @@ static int Droid_InitCard (soundcardinfo_t *sc, int cardnum)
if (sys_sc)
return 2;
// if (!pthread_mutex_lock(&mutex))
{
sc->selfpainting = true;
// sc->sn.speed = 11025;
// sc->sn.samplebits = 16;
@ -139,11 +130,7 @@ static int Droid_InitCard (soundcardinfo_t *sc, int cardnum)
sys_soundflags = 3;
// pthread_mutex_unlock(&mutex);
return 1;
}
return 0;
}
int (*pDroid_InitCard) (soundcardinfo_t *sc, int cardnum) = &Droid_InitCard;

View file

@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "winquake.h"
#include "fs.h"
int cache_full_cycle;
@ -779,7 +780,8 @@ qboolean S_LoadSound (sfx_t *s)
if (name[1] == ':' && name[2] == '\\')
{
FILE *f;
vfsfile_t *f;
int fsize;
#ifndef _WIN32 //convert from windows to a suitable alternative.
char unixname[128];
Q_snprintfz(unixname, sizeof(unixname), "/mnt/%c/%s", name[0]-'A'+'a', name+3);
@ -794,16 +796,16 @@ qboolean S_LoadSound (sfx_t *s)
#endif
if ((f = fopen(name, "rb")))
if ((f = VFSOS_Open(name, "rb")))
{
com_filesize = COM_filelength(f);
data = Hunk_TempAlloc (com_filesize);
result = fread(data, 1, com_filesize, f); //do something with result
fsize = VFS_GETLEN(f);
data = Hunk_TempAlloc (fsize);
result = VFS_READ(f, data, fsize);
if (result != com_filesize)
Con_SafePrintf("S_LoadSound() fread: Filename: %s, expected %i, result was %u\n",name,com_filesize,(unsigned int)result);
if (result != fsize)
Con_SafePrintf("S_LoadSound() fread: Filename: %s, expected %i, result was %u\n", name, fsize, (unsigned int)result);
fclose(f);
VFS_CLOSE(f);
}
else
{

View file

@ -64,6 +64,7 @@ public:
}
static void statuschanged(void *arg)
{
//potentially comes from another thread
//axfte *fte = (axfte*)arg;
InvalidateRect(NULL, NULL, FALSE);
}
@ -602,6 +603,7 @@ public:
ULONG_PTR dwContinue),
/* [in] */ ULONG_PTR dwContinue)
{
struct contextpublic *pub = (struct contextpublic*)plug;
int width, height;
HBITMAP bmp = (HBITMAP)funcs->GetSplashBack(plug, hdcDraw, &width, &height);
if (bmp)
@ -620,6 +622,11 @@ public:
DeleteDC(memDC);
funcs->ReleaseSplashBack(plug, bmp);
}
if (*pub->statusmessage)
{
SetBkMode(hdcDraw, TRANSPARENT);
TextOutA(hdcDraw, 0, 0, pub->statusmessage, strlen(pub->statusmessage));
}
return S_OK;
}
@ -785,10 +792,6 @@ struct
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\VersionIndependentProgID\\", "FTE.FTEPlug"},
{"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\ProgID\\", "FTE.FTEPlug.1.0"},
#ifdef warningmsg
#pragma warningmsg("Hey, moodles, do you want the plugin to register itself as a firefox plugin at the same time as it registers itself for support in IE?")
#endif
/*
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Description", ENGINEWEBSITE},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\GeckoVersion", "1.00"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Path", "***DLLNAME***"},
@ -800,7 +803,6 @@ struct
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-qtv\\Suffixes", "qtv"},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Suffixes\\qtv", ""},
{"Software\\MozillaPlugins\\@fteqw.com/FTE\\Suffixes\\mvd", ""},
*/
{NULL}
};
HRESULT WINAPI DllRegisterServer(void)
@ -826,8 +828,15 @@ HRESULT WINAPI DllRegisterServer(void)
RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)binaryname, strlen(binaryname));
else if (!strcmp(regkeys[i].value, "***VERSION***"))
{
char *ver = version_string();
RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)ver, strlen(ver));
char s[128];
#ifdef OFFICIAL_RELEASE
Q_snprintfz(s, sizeof(s), "%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
#elif defined(SVNREVISION)
Q_snprintfz(s, sizeof(s), "%s SVN %s", DISTRIBUTION, STRINGIFY(SVNREVISION));
#else
Q_snprintfz(s, sizeof(s), "%s build %s", DISTRIBUTION, __DATE__);
#endif
RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)s, strlen(s));
}
else
RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)regkeys[i].value, strlen(regkeys[i].value));

View file

@ -27,10 +27,11 @@ static unsigned int vibrateduration;
static char errormessage[256];
extern jmp_buf host_abort;
cvar_t sys_vibrate = CVAR("sys_vibrate", "1");
cvar_t sys_vibrate = CVARD("sys_vibrate", "1", "Enables the system vibrator for damage events and such things. The value provided is a duration scaler.");
cvar_t sys_osk = CVAR("sys_osk", "0"); //to be toggled
cvar_t sys_keepscreenon = CVAR("sys_keepscreenon", "1"); //to be toggled
cvar_t sys_orientation = CVAR("sys_orientation", "sensor");
cvar_t sys_keepscreenon = CVARD("sys_keepscreenon", "1", "If set, the screen will never darken. This might cost some extra battery power, but then so will running a 3d engine."); //to be toggled
cvar_t sys_orientation = CVARD("sys_orientation", "landscape", "Specifies what angle to render quake at.\nValid values are: sensor (autodetect), landscape, portrait, reverselandscape, reverseportrait");
cvar_t sys_glesversion_cvar = CVARD("sys_glesversion", "1", "Specifies which version of gles to use. 1 or 2 are valid values.");
extern cvar_t vid_conautoscale;
@ -56,9 +57,15 @@ JNIEXPORT jstring JNICALL Java_com_fteqw_FTEDroidEngine_geterrormessage(JNIEnv *
JNIEXPORT jstring JNICALL Java_com_fteqw_FTEDroidEngine_getpreferedorientation(JNIEnv *env, jobject obj)
{
sys_orientation.modified = false;
sys_glesversion_cvar.modified = false;
return (*env)->NewStringUTF(env, sys_orientation.string);
}
JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_getpreferedglesversion(JNIEnv *env, jobject obj)
{
return sys_glesversion_cvar.ival;
}
/*the java passes in all input directly via a 'UI' thread. we don't need to poll it at all*/
void INS_Move(float *movements, int pnum)
{
@ -96,8 +103,11 @@ JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject
static vec3_t oac;
//if we had an error, don't even run a frame any more.
if (*errormessage)
if (*errormessage || !sys_running)
{
Sys_Printf("Crashed or quit\n");
return 8;
}
#ifdef SERVERONLY
SV_Frame();
@ -127,7 +137,7 @@ JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject
ret |= 4;
if (*errormessage)
ret |= 8;
if (sys_orientation.modified)
if (sys_orientation.modified || sys_glesversion_cvar.modified)
ret |= 16;
if (sys_soundflags)
{
@ -190,6 +200,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o
Sys_Printf("reinit\n");
if (sys_memheap)
free(sys_memheap);
memset(&parms, 0, sizeof(parms));
parms.basedir = NULL; /*filled in later*/
parms.argc = 3;
parms.argv = args;
@ -239,6 +250,7 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o
#endif
sys_running = true;
sys_lastframe = Sys_Milliseconds();
sys_orientation.modified = true;
}
}
@ -407,6 +419,7 @@ void Sys_Init(void)
Cvar_Register(&sys_osk, "android stuff");
Cvar_Register(&sys_keepscreenon, "android stuff");
Cvar_Register(&sys_orientation, "android stuff");
Cvar_Register(&sys_glesversion_cvar, "android stuff");
}
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate)

View file

@ -398,6 +398,8 @@ int main(int argc, char **argv)
quakeparms_t parms;
int i;
memset(&parms, 0, sizeof(parms));
COM_InitArgv(argc, argv);
TL_InitLanguages();

View file

@ -67,7 +67,7 @@ qboolean NPFTE_BeginDownload(void *ctx, struct pipetype *ftype, char *url)
}
void NPFTE_StatusChanged(void *sysctx)
{
{ //potentially called from another thread
NPP instance = sysctx;
struct contextpublic *pub = instance->pdata;
InvalidateRgn(pub->oldwnd, NULL, FALSE);
@ -128,11 +128,28 @@ LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
case WM_ERASEBKGND:
return FALSE;
case WM_PAINT:
if (pub->downloading)
if (*pub->statusmessage)
{
HDC hdc;
PAINTSTRUCT paint;
char *s;
unsigned int progress;
unsigned int total;
progress = pub->dldone;
total = pub->dlsize;
hdc = BeginPaint(hWnd, &paint);
DrawWndBack(ctx, hWnd, hdc, &paint);
SetBkMode(hdc, TRANSPARENT);
TextOutA(hdc, 0, 0, pub->statusmessage, strlen(pub->statusmessage));
EndPaint(hWnd, &paint);
return TRUE;
}
else if (pub->downloading)
{
HDC hdc;
PAINTSTRUCT paint;
char s[32];
unsigned int progress;
unsigned int total;
@ -144,11 +161,11 @@ LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
SetBkMode(hdc, TRANSPARENT);
TextOutA(hdc, 0, 0, "Downloading Data, please wait", 16);
if (!progress && !total)
s = "connecting";
sprintf(s, "connecting");
else if (total)
s = va("%i bytes (%i%%)", progress, (int)((100.0f*progress)/total));
sprintf(s, "%i bytes (%i%%)", progress, (int)((100.0f*progress)/total));
else
s = va("%i bytes", progress);
sprintf(s, "%i bytes", progress);
TextOutA(hdc, 0, 32, s, strlen(s));
EndPaint(hWnd, &paint);
return TRUE;
@ -169,9 +186,9 @@ LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
if (pub->availver)
{
s = va("Your plugin may be incompatible");
s = "Your plugin may be incompatible";
TextOutA(hdc, 0, 32, s, strlen(s));
s = va("Version %3.2f was requested, you are using version %3.2f", pub->availver, (float)version_number());
s = "A newer version is available. Your version is dated " __DATE__ ".";
TextOutA(hdc, 0, 48, s, strlen(s));
}
}
@ -183,7 +200,7 @@ LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
case WM_LBUTTONDOWN:
SetActiveWindow(hWnd);
if (!Plug_StartContext(ctx))
Plug_StopContext(NULL);
Plug_StopContext(NULL, false);
break;
default:
break;

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,7 @@ struct contextpublic
unsigned int dlsize;
unsigned int dldone;
float availver; /*this is the version of the plugin that is available, if current is better, use 0*/
char statusmessage[256];
#if defined(_WIN32) && defined(__QUAKEDEF_H__)
/*the npapi stuff is lazy and uses this*/
@ -58,7 +59,7 @@ struct context *Plug_CreateContext(void *sysctx, const struct browserfuncs *func
void Plug_DestroyContext(struct context *ctx);
void Plug_LockPlugin(struct context *ctx, qboolean lockstate);
qboolean Plug_StartContext(struct context *ctx);
void Plug_StopContext(struct context *ctx);
void Plug_StopContext(struct context *ctx, qboolean wait);
qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int left, int top, int width, int height);
int Plug_FindProp(struct context *ctx, const char *field);
@ -81,7 +82,7 @@ struct plugfuncs
void (*DestroyContext)(struct context *ctx);
void (*LockPlugin)(struct context *ctx, qboolean lockstate);
qboolean (*StartContext)(struct context *ctx);
void (*StopContext)(struct context *ctx);
void (*StopContext)(struct context *ctx, qboolean wait);
qboolean (*ChangeWindow)(struct context *ctx, void *whnd, int left, int top, int width, int height);
int (*FindProp)(struct context *ctx, const char *field);

View file

@ -483,6 +483,8 @@ int QDECL main(int argc, char **argv)
int t;
int delay = 1;
memset(&parms, 0, sizeof(parms));
parms.argv = argv;
parms.basedir = ".";

View file

@ -49,6 +49,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#if !defined(CLIENTONLY) && !defined(SERVERONLY)
qboolean isDedicated = false;
#endif
qboolean isPlugin;
qboolean debugout;
HWND sys_parentwindow;
@ -87,7 +88,11 @@ qboolean Sys_RandomBytes(qbyte *string, int len)
return true;
}
/*
=================
Library loading
=================
*/
void Sys_CloseLibrary(dllhandle_t *lib)
{
FreeLibrary((HMODULE)lib);
@ -371,11 +376,14 @@ typedef BOOL (WINAPI *MINIDUMPWRITEDUMP) (
#ifdef PRINTGLARRAYS
#include "glquake.h"
#define GL_VERTEX_ARRAY_BINDING 0x85B5
#define GL_ARRAY_BUFFER 0x8892
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
@ -384,6 +392,167 @@ typedef BOOL (WINAPI *MINIDUMPWRITEDUMP) (
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
#define GL_CURRENT_PROGRAM 0x8B8D
char *DecodeGLEnum(GLenum num)
{
switch(num)
{
case GL_CW: return "GL_CW";
case GL_CCW: return "GL_CCW";
case GL_NEVER: return "GL_NEVER";
case GL_LESS: return "GL_LESS";
case GL_EQUAL: return "GL_EQUAL";
case GL_LEQUAL: return "GL_LEQUAL";
case GL_GREATER: return "GL_GREATER";
case GL_NOTEQUAL: return "GL_NOTEQUAL";
case GL_GEQUAL: return "GL_GEQUAL";
case GL_ALWAYS: return "GL_ALWAYS";
case GL_FRONT: return "GL_FRONT";
case GL_BACK: return "GL_BACK";
case GL_FRONT_AND_BACK: return "GL_FRONT_AND_BACK";
case GL_COMBINE_ARB: return "GL_COMBINE";
case GL_MODULATE: return "GL_MODULATE";
case GL_REPLACE: return "GL_REPLACE";
case GL_ZERO: return "GL_ZERO";
case GL_ONE: return "GL_ONE";
case GL_SRC_COLOR: return "GL_SRC_COLOR";
case GL_ONE_MINUS_SRC_COLOR: return "GL_ONE_MINUS_SRC_COLOR";
case GL_SRC_ALPHA: return "GL_SRC_ALPHA";
case GL_ONE_MINUS_SRC_ALPHA: return "GL_ONE_MINUS_SRC_ALPHA";
case GL_DST_ALPHA: return "GL_DST_ALPHA";
case GL_ONE_MINUS_DST_ALPHA: return "GL_ONE_MINUS_DST_ALPHA";
case GL_DST_COLOR: return "GL_DST_COLOR";
case GL_ONE_MINUS_DST_COLOR: return "GL_ONE_MINUS_DST_COLOR";
case GL_SRC_ALPHA_SATURATE: return "GL_SRC_ALPHA_SATURATE";
default: return va("0x%x", num);
}
}
void DumpGLState(void)
{
int rval;
void *ptr;
int i;
GLint glint;
GLint glint4[4];
void (APIENTRY *qglGetVertexAttribiv) (GLuint index, GLenum pname, GLint* params);
void (APIENTRY *qglGetVertexAttribPointerv) (GLuint index, GLenum pname, GLvoid** pointer);
qglGetVertexAttribiv = (void*)wglGetProcAddress("glGetVertexAttribiv");
qglGetVertexAttribPointerv = (void*)wglGetProcAddress("glGetVertexAttribPointerv");
#pragma comment(lib,"opengl32.lib")
if (qglGetVertexAttribiv)
{
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &rval);
Sys_Printf("VERTEX_ARRAY_BINDING: %i\n", rval);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &rval);
Sys_Printf("GL_ARRAY_BUFFER_BINDING: %i\n", rval);
if (glIsEnabled(GL_COLOR_ARRAY))
{
glGetIntegerv(GL_COLOR_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_COLOR_ARRAY_POINTER, &ptr);
Sys_Printf("GL_COLOR_ARRAY: %s %i:%p\n", glIsEnabled(GL_COLOR_ARRAY)?"en":"dis", rval, ptr);
}
// if (glIsEnabled(GL_FOG_COORDINATE_ARRAY_EXT))
// {
// glGetPointerv(GL_FOG_COORD_ARRAY_POINTER, &ptr);
// Sys_Printf("GL_FOG_COORDINATE_ARRAY_EXT: %i (%lx)\n", (int) glIsEnabled(GL_FOG_COORDINATE_ARRAY_EXT), (int) ptr);
// }
// if (glIsEnabled(GL_INDEX_ARRAY))
{
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_INDEX_ARRAY_POINTER, &ptr);
Sys_Printf("GL_INDEX_ARRAY: %s %i:%p\n", glIsEnabled(GL_INDEX_ARRAY)?"en":"dis", rval, ptr);
}
if (glIsEnabled(GL_NORMAL_ARRAY))
{
glGetIntegerv(GL_NORMAL_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_NORMAL_ARRAY_POINTER, &ptr);
Sys_Printf("GL_NORMAL_ARRAY: %s %i:%p\n", glIsEnabled(GL_NORMAL_ARRAY)?"en":"dis", rval, ptr);
}
// glGetPointerv(GL_SECONDARY_COLOR_ARRAY_POINTER, &ptr);
// Sys_Printf("GL_SECONDARY_COLOR_ARRAY: %i (%lx)\n", (int) glIsEnabled(GL_SECONDARY_COLOR_ARRAY), (int) ptr);
for (i = 0; i < 4; i++)
{
qglClientActiveTextureARB(mtexid0 + i);
if (glIsEnabled(GL_TEXTURE_COORD_ARRAY))
{
glGetIntegerv(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &ptr);
Sys_Printf("GL_TEXTURE_COORD_ARRAY %i: %s %i:%p\n", i, glIsEnabled(GL_TEXTURE_COORD_ARRAY)?"en":"dis", rval, ptr);
}
}
if (glIsEnabled(GL_VERTEX_ARRAY))
{
glGetIntegerv(GL_VERTEX_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_VERTEX_ARRAY_POINTER, &ptr);
Sys_Printf("GL_VERTEX_ARRAY: %s %i:%p\n", glIsEnabled(GL_VERTEX_ARRAY)?"en":"dis", rval, ptr);
}
for (i = 0; i < 16; i++)
{
int en, bo, as, st, ty, no;
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &en);
if (!en)
continue;
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &bo);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &as);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &st);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &ty);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &no);
qglGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr);
Sys_Printf("attrib%i: %s as:%i st:%i ty:%0x %s%i:%p\n", i, en?"en":"dis", as, st,ty,no?"norm ":"", bo, ptr);
}
glGetIntegerv(GL_CURRENT_PROGRAM, &glint);
Sys_Printf("GL_CURRENT_PROGRAM: %i\n", glint);
glGetIntegerv(GL_BLEND, &glint);
Sys_Printf("GL_BLEND: %i\n", glint);
glGetIntegerv(GL_BLEND_SRC, &glint);
Sys_Printf("GL_BLEND_SRC: %i\n", DecodeGLEnum(glint));
glGetIntegerv(GL_BLEND_DST, &glint);
Sys_Printf("GL_BLEND_DST: %i\n", DecodeGLEnum(glint));
glGetIntegerv(GL_DEPTH_WRITEMASK, &glint);
Sys_Printf("GL_DEPTH_WRITEMASK: %i\n", glint);
glGetIntegerv(GL_DEPTH_TEST, &glint);
Sys_Printf("GL_DEPTH_TEST: %i\n", glint);
glGetIntegerv(GL_DEPTH_FUNC, &glint);
Sys_Printf("GL_DEPTH_FUNC: %s\n", DecodeGLEnum(glint));
glGetIntegerv(GL_CULL_FACE, &glint);
Sys_Printf("GL_CULL_FACE: %i\n", glint);
glGetIntegerv(GL_CULL_FACE_MODE, &glint);
Sys_Printf("GL_CULL_FACE_MODE: %s\n", DecodeGLEnum(glint));
glGetIntegerv(GL_FRONT_FACE, &glint);
Sys_Printf("GL_FRONT_FACE: %s\n", DecodeGLEnum(glint));
glGetIntegerv(GL_SCISSOR_TEST, &glint);
Sys_Printf("GL_SCISSOR_TEST: %i\n", glint);
glGetIntegerv(GL_STENCIL_TEST, &glint);
Sys_Printf("GL_STENCIL_TEST: %i\n", glint);
glGetIntegerv(GL_COLOR_WRITEMASK, glint4);
Sys_Printf("GL_COLOR_WRITEMASK: %i %i %i %i\n", glint4[0], glint4[1], glint4[2], glint4[3]);
GL_SelectTexture(0);
glGetIntegerv(GL_TEXTURE_2D, &glint);
Sys_Printf("GL_TEXTURE_2D: %i\n", glint);
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &glint);
Sys_Printf("GL_TEXTURE_ENV_MODE: %s\n", DecodeGLEnum(glint));
GL_SelectTexture(1);
glGetIntegerv(GL_TEXTURE_2D, &glint);
Sys_Printf("GL_TEXTURE_2D: %i\n", glint);
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &glint);
Sys_Printf("GL_TEXTURE_ENV_MODE: %s\n", DecodeGLEnum(glint));
GL_SelectTexture(2);
glGetIntegerv(GL_TEXTURE_2D, &glint);
Sys_Printf("GL_TEXTURE_2D: %i\n", glint);
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &glint);
Sys_Printf("GL_TEXTURE_ENV_MODE: %s\n", DecodeGLEnum(glint));
}
}
#endif
DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exceptionInfo)
@ -398,56 +567,7 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception
BOOL (WINAPI *pIsDebuggerPresent)(void);
#ifdef PRINTGLARRAYS
int rval;
void *ptr;
int i;
void (APIENTRY *qglGetVertexAttribiv) (GLuint index, GLenum pname, GLint* params);
void (APIENTRY *qglGetVertexAttribPointerv) (GLuint index, GLenum pname, GLvoid** pointer);
qglGetVertexAttribiv = (void*)wglGetProcAddress("glGetVertexAttribiv");
qglGetVertexAttribPointerv = (void*)wglGetProcAddress("glGetVertexAttribPointerv");
#pragma comment(lib,"opengl32.lib")
if (qglGetVertexAttribiv)
{
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &rval);
Sys_Printf("GL_ARRAY_BUFFER_BINDING: %i\n", rval);
glGetPointerv(GL_COLOR_ARRAY_POINTER, &ptr);
Sys_Printf("GL_COLOR_ARRAY: %s (%lx)\n", glIsEnabled(GL_COLOR_ARRAY)?"en":"dis", (int) ptr);
// glGetPointerv(GL_FOG_COORD_ARRAY_POINTER, &ptr);
// Sys_Printf("GL_FOG_COORDINATE_ARRAY_EXT: %i (%lx)\n", (int) glIsEnabled(GL_FOG_COORDINATE_ARRAY_EXT), (int) ptr);
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_INDEX_ARRAY_POINTER, &ptr);
Sys_Printf("GL_INDEX_ARRAY: %s %i:%p\n", glIsEnabled(GL_INDEX_ARRAY)?"en":"dis", rval, ptr);
glGetPointerv(GL_NORMAL_ARRAY_POINTER, &ptr);
Sys_Printf("GL_NORMAL_ARRAY: %s (%lx)\n", glIsEnabled(GL_NORMAL_ARRAY)?"en":"dis", (int) ptr);
// glGetPointerv(GL_SECONDARY_COLOR_ARRAY_POINTER, &ptr);
// Sys_Printf("GL_SECONDARY_COLOR_ARRAY: %i (%lx)\n", (int) glIsEnabled(GL_SECONDARY_COLOR_ARRAY), (int) ptr);
for (i = 0; i < 4; i++)
{
qglClientActiveTextureARB(mtexid0 + i);
glGetIntegerv(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &ptr);
Sys_Printf("GL_TEXTURE_COORD_ARRAY %i: %s %i:%p\n", i, glIsEnabled(GL_TEXTURE_COORD_ARRAY)?"en":"dis", rval, ptr);
}
glGetIntegerv(GL_VERTEX_ARRAY_BUFFER_BINDING, &rval);
glGetPointerv(GL_VERTEX_ARRAY_POINTER, &ptr);
Sys_Printf("GL_VERTEX_ARRAY: %s %i:%p\n", glIsEnabled(GL_VERTEX_ARRAY)?"en":"dis", rval, ptr);
for (i = 0; i < 16; i++)
{
int en, bo, as, st, ty, no;
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &en);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &bo);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &as);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &st);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &ty);
qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &no);
qglGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr);
Sys_Printf("attrib%i: %s as:%i st:%i ty:%0x %s%i:%p\n", i, en?"en":"dis", as, st,ty,no?"norm ":"", bo, ptr);
}
}
DumpGLState();
#endif
hKernel = LoadLibrary ("kernel32");
@ -851,15 +971,7 @@ void VARGS Sys_Error (const char *error, ...)
SetHookState(false);
#endif
#ifdef NPFTE
{
extern jmp_buf host_abort;
/*jump to start of main loop (which exits the main loop)*/
longjmp (host_abort, 1);
}
#else
exit (1);
#endif
}
static wchar_t dequake(conchar_t chr)
@ -912,15 +1024,17 @@ void VARGS Sys_Printf (char *fmt, ...)
if (debugout)
{
//msvc debug output
conchar_t msg[1024], *end;
wchar_t wide[1024];
int i;
conchar_t msg[1024], *end, *in;
wchar_t wide[1024], *out;
end = COM_ParseFunString(CON_WHITEMASK, text, msg, sizeof(msg), false);
for (i = 0; msg+i < end; i++)
out = wide;
in = msg;
for (in = msg; in < end; in++)
{
wide[i] = dequake(msg[i] & CON_CHARMASK);
if (!(*in & CON_HIDDEN))
*out++ = dequake(*in & CON_CHARMASK);
}
wide[i] = 0;
*out = 0;
OutputDebugStringW(wide);
}
#endif
@ -946,21 +1060,12 @@ void Sys_Quit (void)
longjmp(restart_jmpbuf, 1);
#endif
#ifdef NPFTE
{
extern jmp_buf host_abort;
/*jump to start of main loop (which exits the main loop)*/
longjmp (host_abort, 1);
}
#else
#ifdef USE_MSVCRT_DEBUG
if (_CrtDumpMemoryLeaks())
OutputDebugStringA("Leaks detected\n");
#endif
exit(1);
#endif
}
@ -1262,7 +1367,52 @@ void Sys_SendKeyEvents (void)
{
MSG msg;
if (isDedicated)
if (isPlugin)
{
DWORD avail;
static char text[256], *nl;
static int textpos = 0;
HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
if (!PeekNamedPipe(input, NULL, 0, NULL, &avail, NULL))
{
Cmd_ExecuteString("quit force", RESTRICT_LOCAL);
}
else if (avail)
{
if (avail > sizeof(text)-1-avail)
avail = sizeof(text)-1-avail;
if (ReadFile(input, text+textpos, avail, &avail, NULL))
{
textpos += avail;
while(1)
{
text[textpos] = 0;
nl = strchr(text, '\n');
if (nl)
{
*nl++ = 0;
if (!qrenderer && !strncmp(text, "vid_recenter ", 13))
{
Cmd_TokenizeString(text, false, false);
sys_parentleft = strtoul(Cmd_Argv(1), NULL, 0);
sys_parenttop = strtoul(Cmd_Argv(2), NULL, 0);
sys_parentwidth = strtoul(Cmd_Argv(3), NULL, 0);
sys_parentheight = strtoul(Cmd_Argv(4), NULL, 0);
sys_parentwindow = (HWND)strtoul(Cmd_Argv(5), NULL, 16);
}
Cmd_ExecuteString(text, RESTRICT_LOCAL);
memmove(text, nl, textpos - (nl - text));
textpos -= (nl - text);
}
else
break;
}
}
}
}
else if (isDedicated)
{
#ifndef CLIENTONLY
SV_GetConsoleCommands ();
@ -1363,76 +1513,6 @@ qboolean Sys_Startup_CheckMem(quakeparms_t *parms)
return true;
}
#ifdef NPFTE
static quakeparms_t parms;
double lastlooptime;
qboolean NPQTV_Sys_Startup(int argc, char *argv[])
{
if (!host_initialized)
{
TL_InitLanguages();
parms.argc = argc;
parms.argv = argv;
parms.basedir = argv[0];
COM_InitArgv (parms.argc, parms.argv);
if (!Sys_Startup_CheckMem(&parms))
return false;
Host_Init (&parms);
}
lastlooptime = Sys_DoubleTime ();
return true;
}
void NPQTV_Sys_MainLoop(void)
{
double duratrion, newtime;
if (isDedicated)
{
#ifndef CLIENTONLY
NET_Sleep(50, false);
// find time passed since last cycle
newtime = Sys_DoubleTime ();
duratrion = newtime - lastlooptime;
lastlooptime = newtime;
SV_Frame ();
#else
Sys_Error("wut?");
#endif
}
else
{
#ifndef SERVERONLY
double sleeptime;
newtime = Sys_DoubleTime ();
duratrion = newtime - lastlooptime;
sleeptime = Host_Frame (duratrion);
lastlooptime = newtime;
SetHookState(sys_disableWinKeys.ival);
Sys_Sleep(sleeptime);
// Sleep(0);
#else
Sys_Error("wut?");
#endif
}
}
void Sys_RecentServer(char *command, char *target, char *title, char *desc)
{
}
#else
/*
==================
WinMain
@ -1833,7 +1913,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
// MSG msg;
quakeparms_t parms;
double time, oldtime, newtime;
char cwd[1024];
char cwd[1024], bindir[1024], *s;
const char *qtvfile = NULL;
int delay = 0;
@ -1841,6 +1921,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
if (hPrevInstance)
return 0;
memset(&parms, 0, sizeof(parms));
#ifndef MINGW
#if _MSC_VER > 1200
Win7_Init();
@ -1937,12 +2019,21 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
setjmp (restart_jmpbuf);
#endif
GetModuleFileName(NULL, cwd, sizeof(cwd)-1);
strcpy(exename, COM_SkipPath(cwd));
GetModuleFileName(NULL, bindir, sizeof(bindir)-1);
s = COM_SkipPath(exename);
strcpy(exename, s);
*s = 0;
parms.argv = (const char **)argv;
COM_InitArgv (parms.argc, parms.argv);
isPlugin = !!COM_CheckParm("-plugin");
if (isPlugin)
{
printf("status Starting up!\n");
fflush(stdout);
}
if (COM_CheckParm("--version") || COM_CheckParm("-v"))
{
printf("version " DISTRIBUTION " " __TIME__ " " __DATE__ "\n");
@ -1978,6 +2069,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
//tprints are now allowed
parms.basedir = cwd;
parms.binarydir = bindir;
parms.argc = com_argc;
parms.argv = com_argv;
@ -2050,6 +2142,12 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
#endif
#endif
if (isPlugin)
{
printf("status Running!\n");
fflush(stdout);
}
/* main window message loop */
while (1)
{
@ -2134,7 +2232,6 @@ int __cdecl main(void)
}
return WinMain(GetModuleHandle(NULL), NULL, cmdline, SW_NORMAL);
}
#endif
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate)
{

View file

@ -16,11 +16,22 @@ F11 will step through.
#include "quakedef.h"
#ifdef TEXTEDITOR
static cvar_t alloweditor = SCVAR("alloweditor", "1"); //disallow loading editor for stepbystep debugging.
static cvar_t editstripcr = SCVAR("edit_stripcr", "1"); //remove \r from eols (on load).
static cvar_t editaddcr = SCVAR("edit_addcr", "1"); //make sure that each line ends with a \r (on save).
static cvar_t edittabspacing = SCVAR("edit_tabsize", "4");
cvar_t debugger = SCVAR("debugger", "1");
#ifdef _WIN32
#define editaddcr_default "1"
#else
#define editaddcr_default "0"
#endif
#ifdef ANDROID
#define debugger_default "0"
#else
#define debugger_default "1"
#endif
static cvar_t editstripcr = CVARD("edit_stripcr", "1", "remove \\r from eols (on load)");
static cvar_t editaddcr = CVARD("edit_addcr", editaddcr_default, "make sure that each line ends with a \\r (on save)");
static cvar_t edittabspacing = CVARD("edit_tabsize", "4", "How wide tab alignment is");
cvar_t debugger = CVARD("debugger", debugger_default, "When enabled, QC errors and debug events will enable step-by-step tracing.");
#undef pr_trace
@ -53,6 +64,21 @@ static void E_Free(void *mem)
#define GETBLOCK(s, ret) ret = (void *)E_Malloc(sizeof(fileblock_t) + s);ret->allocatedlength = s;ret->data = (char *)ret + sizeof(fileblock_t)
void PR_GenerateStatementString (progfuncs_t *progfuncs, int statementnum, char *out, int outlen);
fileblock_t *GenAsm(int statement)
{
char linebuf[256];
fileblock_t *b;
int l;
PR_GenerateStatementString(editprogfuncs, statement, linebuf, sizeof(linebuf));
l = strlen(linebuf);
b = E_Malloc(sizeof(fileblock_t) + l);
b->allocatedlength = l;
b->datalength = l;
b->data = (char *)b + sizeof(fileblock_t);
memcpy(b->data, linebuf, l);
return b;
}
static char OpenEditorFile[256];
@ -61,8 +87,10 @@ qboolean editoractive; //(export)
qboolean editormodal; //doesn't return. (export)
static qboolean editorblocking;
static qboolean madechanges;
static qboolean editenabled;
static qboolean insertkeyhit=true;
static qboolean useeval;
static qboolean stepasm;
static char evalstring[256];
@ -161,7 +189,7 @@ static void CloseEditor(void)
{
fileblock_t *b;
key_dest = key_console;
key_dest = key_game;
editoractive = false;
editprogfuncs = NULL;
@ -169,11 +197,11 @@ static void CloseEditor(void)
return;
OpenEditorFile[0] = '\0';
for (b = firstblock; b;)
while(firstblock)
{
firstblock = b;
b=b->next;
E_Free(firstblock);
b = firstblock;
firstblock=firstblock->next;
E_Free(b);
}
madechanges = false;
@ -227,6 +255,7 @@ static qboolean EditorSaveFile(char *s) //returns true if succesful
fclose(F);
*/
madechanges = false;
editenabled = true;
executionlinenum = -1;
return true;
@ -236,6 +265,14 @@ static qboolean EditorSaveFile(char *s) //returns true if succesful
static void EditorNewFile(void)
{
fileblock_t *b;
while(firstblock)
{
b = firstblock;
firstblock=firstblock->next;
E_Free(b);
}
GETBLOCK(64, firstblock);
GETBLOCK(64, firstblock->next);
firstblock->next->prev = firstblock;
@ -250,9 +287,10 @@ static void EditorNewFile(void)
key_dest = key_editor;
editoractive = true;
editenabled = true;
}
static void EditorOpenFile(char *name)
static void EditorOpenFile(char *name, qboolean readonly)
{
int i;
char line[8192];
@ -347,14 +385,17 @@ static void EditorOpenFile(char *name)
madechanges = false;
executionlinenum = -1;
editenabled = !readonly;
key_dest = key_editor;
editoractive = true;
}
extern qboolean keydown[K_MAX];
void Editor_Key(int key, int unicode)
{
int i;
fileblock_t *nb;
if (keybindings[key][0])
if (!strcmp(keybindings[key][0], "toggleconsole"))
{
@ -400,7 +441,7 @@ void Editor_Key(int key, int unicode)
if (key == K_SHIFT)
return;
if (useeval && key != K_F11 && key != K_F5)
if (useeval)
{
switch(key)
{
@ -408,19 +449,19 @@ void Editor_Key(int key, int unicode)
if (editprogfuncs)
*editprogfuncs->pr_trace = 0;
useeval = false;
break;
return;
case K_F3:
useeval = false;
break;
return;
case K_DEL:
evalstring[0] = '\0';
break;
return;
case K_BACKSPACE:
i = strlen(evalstring);
if (i < 1)
break;
return;
evalstring[i-1] = '\0';
break;
return;
default:
if (unicode)
{
@ -428,9 +469,20 @@ void Editor_Key(int key, int unicode)
evalstring[i] = unicode;
evalstring[i+1] = '\0';
}
return;
case K_F5:
case K_F9:
case K_F11:
case K_MWHEELUP:
case K_UPARROW:
case K_PGUP:
case K_MWHEELDOWN:
case K_DOWNARROW:
case K_PGDN:
case K_LEFTARROW:
case K_RIGHTARROW:
break;
}
return;
}
/* if (ctrl_down && (key == 'c' || key == K_INS))
@ -466,6 +518,14 @@ void Editor_Key(int key, int unicode)
cursorblock = cursorblock->prev;
cursorlinenum--;
}
else if (cursorlinenum>1)
{
cursorlinenum--;
nb = GenAsm(cursorlinenum);
nb->next = cursorblock;
cursorblock->prev = nb;
firstblock = cursorblock = nb;
}
}
}
SetCursorpos();
@ -490,6 +550,14 @@ void Editor_Key(int key, int unicode)
cursorblock = cursorblock->next;
cursorlinenum++;
}
else
{
cursorlinenum++;
nb = GenAsm(cursorlinenum);
nb->prev = cursorblock;
cursorblock->next = nb;
cursorblock = nb;
}
}
}
SetCursorpos();
@ -516,7 +584,7 @@ void Editor_Key(int key, int unicode)
s++;
}
if (*file)
EditorOpenFile(file);
EditorOpenFile(file, false);
}
break;
case K_F3:
@ -593,14 +661,39 @@ void Editor_Key(int key, int unicode)
case K_LEFTARROW:
cursorx--;
if (keydown[K_CTRL])
{
//skip additional whitespace
while(cursorx > 0 && (cursorblock->data[cursorx-1] == ' ' || cursorblock->data[cursorx-1] <= '\t'))
cursorx--;
//skip over the word, to the start of it
while(cursorx > 0 && ((cursorblock->data[cursorx-1] >= 'a' && cursorblock->data[cursorx-1] <= 'z') ||
(cursorblock->data[cursorx-1] >= 'A' && cursorblock->data[cursorx-1] <= 'Z') ||
(cursorblock->data[cursorx-1] >= '0' && cursorblock->data[cursorx-1] <= '9')))
cursorx--;
}
if (cursorx < 0)
cursorx = 0;
break;
case K_RIGHTARROW:
if (keydown[K_CTRL])
{
while(cursorx+1 < cursorblock->datalength && ((cursorblock->data[cursorx] >= 'a' && cursorblock->data[cursorx] <= 'z') ||
(cursorblock->data[cursorx] >= 'A' && cursorblock->data[cursorx] <= 'Z') ||
(cursorblock->data[cursorx] >= '0' && cursorblock->data[cursorx] <= '9')))
cursorx++;
cursorx++;
while(cursorx+1 < cursorblock->datalength && (cursorblock->data[cursorx] == ' ' || cursorblock->data[cursorx] <= '\t'))
cursorx++;
}
else
{
cursorx++;
if (cursorx > cursorblock->datalength)
cursorx = cursorblock->datalength;
}
break;
case K_BACKSPACE:
@ -615,6 +708,8 @@ void Editor_Key(int key, int unicode)
break;
}
if (editenabled)
{
cursorlinenum-=1;
madechanges = true;
@ -634,10 +729,17 @@ void Editor_Key(int key, int unicode)
E_Free(b);
// cursorblock = b;
}
else
{
cursorblock = cursorblock->prev;
cursorx = cursorblock->datalength;
}
break;
}
case K_DEL: //bksp falls through.
if (editenabled)
{
int a;
fileblock_t *b;
@ -673,6 +775,7 @@ void Editor_Key(int key, int unicode)
break;
case K_ENTER:
if (editenabled)
{
fileblock_t *b = cursorblock;
@ -695,12 +798,20 @@ void Editor_Key(int key, int unicode)
cursorx = 0;
}
else if (cursorblock->next)
{
cursorblock = cursorblock->next;
cursorlinenum++;
cursorx = 0;
}
break;
case K_INS:
insertkeyhit = insertkeyhit?false:true;
break;
default:
if (!editenabled)
break;
if (unicode < ' ' && unicode != '\t') //we deem these as unprintable
break;
@ -735,58 +846,138 @@ void Editor_Key(int key, int unicode)
}
}
static void Draw_Line(int x, int y, fileblock_t *b, int cursorx)
static void Draw_Line(int vy, fileblock_t *b, int cursorx)
{
int nx = 0, nnx;
int nx = 0;
int y;
char *tooltip = NULL;
int nnx;
qbyte *d = b->data;
qbyte *c;
int i;
int colour=COLOR_WHITE;
extern int mousecursor_x, mousecursor_y;
int smx = (mousecursor_x * vid.pixelwidth) / vid.width, smy = (mousecursor_y * vid.pixelheight) / vid.height;
unsigned int colour;
int ts = edittabspacing.value;
char linebuf[128];
if (cursorx >= 0)
c = d + cursorx;
else
c = NULL;
Font_BeginString(font_conchar, x, y, &x, &y);
Font_BeginString(font_conchar, nx, vy, &nx, &y);
if (ts < 1)
ts = 4;
ts*=8;
//figure out the colour
if (b->flags & (FB_BREAK))
colour = COLOR_RED; //red
if (executionblock == b)
{
if (colour) //break point too
colour = COLOR_GREEN; //green
if (executionblock == b)
colour = COLOR_MAGENTA<<CON_FGSHIFT;
else
colour = COLOR_YELLOW; //yellow
colour = COLOR_RED<<CON_FGSHIFT;
}
else
{
if (executionblock == b)
colour = COLOR_YELLOW<<CON_FGSHIFT; //yellow
else
colour = COLOR_WHITE<<CON_FGSHIFT;
}
nx = x;
//if this line currently holds the mouse cursor, figure out the word that is highighted, and evaluate that word for debugging.
//self.ammo_shells is just 'self' if you highlight 'self', but if you highlight ammo_shells, it'll include the self, for easy debugging.
//use the f3 evaulator for more explicit debugging.
if (editprogfuncs && smy >= y && smy < y + Font_CharHeight())
{
int e, s;
nx = -viewportx;
for (i = 0; i < b->datalength; i++)
{
if (d[i] == '\t')
{
nnx=nx+ts;
nnx-=(nnx - -viewportx)%ts;
}
else
nnx = Font_CharEndCoord(font_conchar, nx, (int)d[i] | (colour));
if (smx >= nx && smx <= nnx)
{
for(s = i; s > 0; )
{
if ((d[s-1] >= 'a' && d[s-1] <= 'z') ||
(d[s-1] >= 'A' && d[s-1] <= 'Z') ||
(d[s-1] >= '0' && d[s-1] <= '9') ||
d[s-1] == '.' || d[s-1] == '_')
s--;
else
break;
}
for (e = i; e < b->datalength; )
{
if ((d[e] >= 'a' && d[e] <= 'z') ||
(d[e] >= 'A' && d[e] <= 'Z') ||
(d[e] >= '0' && d[e] <= '9') ||
/*d[e] == '.' ||*/ d[e] == '_')
e++;
else
break;
}
if (e >= s+sizeof(linebuf))
e = s+sizeof(linebuf) - 1;
memcpy(linebuf, d+s, e - s);
linebuf[e-s] = 0;
if (*linebuf)
tooltip = editprogfuncs->EvaluateDebugString(editprogfuncs, linebuf);
break;
}
nx = nnx;
}
}
nx = -viewportx;
for (i = 0; i < b->datalength; i++)
{
if (*d == '\t')
{
if (d == c)
Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK));
{
int e = Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK|CON_BLINKTEXT));
if (e >= vid.pixelwidth)
viewportx += e - vid.pixelwidth;
if (nx < 0)
{
viewportx -= -nx;
if (viewportx < 0)
viewportx = 0;
}
}
nx+=ts;
nx-=(nx - x)%ts;
nx-=(nx - -viewportx)%ts;
d++;
continue;
}
if (nx < (int)vid.pixelwidth)
nnx = Font_DrawChar(nx, y, (int)*d | (colour<<CON_FGSHIFT));
if (nx <= (int)vid.pixelwidth || cursorx>=0)
nnx = Font_DrawChar(nx, y, (int)*d | (colour));
else nnx = vid.pixelwidth;
if (d == c)
Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK));
{
int e = Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK|CON_BLINKTEXT));
if (e >= vid.pixelwidth)
viewportx += e - vid.pixelwidth;
if (nx < 0)
{
viewportx -= -nx;
if (viewportx < 0)
viewportx = 0;
}
}
nx = nnx;
d++;
@ -794,8 +985,32 @@ static void Draw_Line(int x, int y, fileblock_t *b, int cursorx)
/*we didn't do the cursor! stick it at the end*/
if (c && c >= d)
Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK));
{
int e = Font_DrawChar(nx, y, (int)11 | (CON_WHITEMASK|CON_BLINKTEXT));
if (e >= vid.pixelwidth)
viewportx += e - vid.pixelwidth;
if (nx < 0)
{
viewportx -= -nx;
if (viewportx < 0)
viewportx = 0;
}
}
if (tooltip)
{
while(*tooltip)
{
if (*tooltip == '\n')
{
smy += Font_CharHeight();
smx = (mousecursor_x * vid.pixelwidth) / vid.width;
tooltip++;
}
else
smx = Font_DrawChar(smx, smy, (COLOR_CYAN<<CON_FGSHIFT) | (COLOR_BLACK<<CON_BGSHIFT) | CON_NONCLEARBG | *tooltip++);
}
}
Font_EndString(font_conchar);
}
@ -821,7 +1036,6 @@ static fileblock_t *firstline(void)
void Editor_Draw(void)
{
int x;
int y;
int c;
fileblock_t *b;
@ -854,27 +1068,12 @@ void Editor_Draw(void)
}
}
x=0;
for (y = 0; y < cursorx; y++)
{
if (cursorblock->data[y] == '\0')
break;
else if (cursorblock->data[y] == '\t')
{
x+=32;
x&=~31;
}
else
x+=8;
}
x=-x + vid.width/2;
if (x > 0)
x = 0;
if (madechanges)
Draw_FunString (vid.width - 8, 0, "!");
if (!insertkeyhit)
Draw_FunString (vid.width - 16, 0, "O");
if (!editenabled)
Draw_FunString (vid.width - 24, 0, "R");
Draw_FunString(0, 0, va("%6i:%4i:%s", cursorlinenum, cursorx+1, OpenEditorFile));
if (useeval)
@ -915,9 +1114,8 @@ void Editor_Draw(void)
{
c = -1;
if (b == cursorblock)
if ((int)(Sys_DoubleTime()*4.0) & 1)
c = cursorx;
Draw_Line(x, y, b, c);
Draw_Line(y, b, c);
y+=8;
if (y > vid.height)
@ -947,10 +1145,10 @@ void Editor_Draw(void)
*/
}
int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int nump, char **parms)
int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int statement, int nump, char **parms)
{
char *f1, *f2;
if (editormodal || line < 0 || !debugger.ival)
if (editormodal || (line < 0 && !statement) || !debugger.ival)
return line; //whoops
if (qrenderer == QR_NONE)
@ -988,38 +1186,82 @@ int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int nump, char **
f1 += 4;
if (!strncmp(f2, "src/", 4))
f2 += 4;
stepasm = line < 0;
if (stepasm)
{
fileblock_t *nb, *lb;
int i;
EditorNewFile();
E_Free(firstblock->next);
E_Free(firstblock);
cursorlinenum = statement;
firstblock = GenAsm(cursorlinenum);
cursorblock = firstblock;
for (i = cursorlinenum; i > 0 && i > cursorlinenum - 20; i)
{
i--;
firstblock->prev = GenAsm(i);
firstblock->prev->next = firstblock;
firstblock = firstblock->prev;
}
lb = cursorblock;
for (i = cursorlinenum; i < cursorlinenum+20; )
{
i++;
nb = GenAsm(i);
lb->next = nb;
nb->prev = lb;
lb = nb;
}
}
else
{
if (!editoractive || strcmp(f1, f2))
{
if (editoractive)
if (editoractive && madechanges)
EditorSaveFile(OpenEditorFile);
EditorOpenFile(filename);
EditorOpenFile(filename, true);
}
for (cursorlinenum = 1, cursorblock = firstblock; cursorlinenum < line && cursorblock->next; cursorlinenum++)
cursorblock=cursorblock->next;
}
executionlinenum = cursorlinenum;
executionblock = cursorblock;
if (!parms)
{
double oldrealtime = realtime;
editormodal = true;
while(editormodal && editoractive && editprogfuncs)
{
realtime = Sys_DoubleTime();
// key_dest = key_editor;
scr_disabled_for_loading=false;
SCR_UpdateScreen();
Sys_SendKeyEvents();
IN_Commands ();
S_ExtraUpdate();
NET_Sleep(100, false); //any os.
NET_Sleep(20, false); //any os.
}
realtime = oldrealtime;
editormodal = false;
}
return line;
if (stepasm)
return -executionlinenum;
else
return executionlinenum;
}
void Editor_ProgsKilled(progfuncs_t *dead)
@ -1042,9 +1284,9 @@ static void Editor_f(void)
editprogfuncs = NULL;
useeval = false;
if (editoractive)
if (editoractive && madechanges)
EditorSaveFile(OpenEditorFile);
EditorOpenFile(Cmd_Argv(1));
EditorOpenFile(Cmd_Argv(1), false);
// EditorNewFile();
}
@ -1052,7 +1294,6 @@ void Editor_Init(void)
{
Cmd_AddCommand("edit", Editor_f);
Cvar_Register(&alloweditor, "Text editor");
Cvar_Register(&editstripcr, "Text editor");
Cvar_Register(&editaddcr, "Text editor");
Cvar_Register(&edittabspacing, "Text editor");

View file

@ -142,19 +142,21 @@ V_CalcBob
float V_CalcBob (int pnum, qboolean queryold)
{
static double bobtime[MAX_SPLITS];
static double cltime[MAX_SPLITS];
static float bob[MAX_SPLITS];
float cycle;
if (cl.spectator)
return 0;
if (!cl.onground[pnum] || cl.paused || queryold)
if (!cl.onground[pnum] || cl.paused)
return bob[pnum]; // just use old value
if (cl_bobcycle.value <= 0)
return 0;
bobtime[pnum] += host_frametime;
bobtime[pnum] += cl.time - cltime[pnum];
cltime[pnum] = cl.time;
cycle = bobtime[pnum] - (int)(bobtime[pnum]/cl_bobcycle.value)*cl_bobcycle.value;
cycle /= cl_bobcycle.value;
if (cycle < cl_bobup.value)
@ -568,7 +570,7 @@ void V_SetContentsColor (int contents)
cl.cshifts[CSHIFT_CONTENTS].percent *= v_contentblend.value;
if (cl.cshifts[CSHIFT_SERVER].percent)
if (cl.cshifts[CSHIFT_CONTENTS].percent)
{ //bound contents so it can't go negative
if (cl.cshifts[CSHIFT_CONTENTS].percent < 0)
cl.cshifts[CSHIFT_CONTENTS].percent = 0;
@ -1292,13 +1294,16 @@ void R_DrawNameTags(void)
continue;
if (i == cl.playernum[r_refdef.currentplayernum])
continue; // Don't draw tag for the local player
if (cl.players[i].spectator)
continue;
if (i == Cam_TrackNum(r_refdef.currentplayernum))
continue;
if (TP_IsPlayerVisible(nametagorg[i]))
{
VectorCopy(nametagorg[i], tagcenter);
tagcenter[2] += 32;
Matrix4x4_CM_Project(tagcenter, center, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y);
if (center[2] > 1)
if (!Matrix4x4_CM_Project(tagcenter, center, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
continue;
len = COM_ParseFunString(CON_WHITEMASK, cl.players[i].name, buffer, sizeof(buffer), false) - buffer;
@ -1307,6 +1312,7 @@ void R_DrawNameTags(void)
}
}
void R2D_PolyBlend (void);
void V_RenderPlayerViews(int plnum)
{
int oldnuments;
@ -1333,6 +1339,7 @@ void V_RenderPlayerViews(int plnum)
Cam_SelfTrack(plnum);
R_RenderView ();
R2D_PolyBlend ();
R_DrawNameTags();
cl_numvisedicts = oldnuments;

View file

@ -175,6 +175,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#endif
#else
#define USE_SQLITE
// #define USE_MYSQL
#define SIDEVIEWS 4 //enable secondary/reverse views.
#define SP2MODELS //quake2 sprite models
@ -260,6 +263,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef IRCCONNECT
#endif
#ifndef MULTITHREAD
#undef USE_SQLITE
#undef USE_MYSQL
#endif
#if defined(USE_SQLITE) || defined(USE_MYSQL)
#define SQL
#endif
//fix things a little...
#ifdef NPQTV

View file

@ -1336,10 +1336,10 @@ char *Cmd_ExpandStringArguments (char *data, char *dest, int destlen)
============
Cmd_TokenizeString
Parses the given string into command line tokens.
Parses the given string into command line tokens, stopping at the \n
============
*/
void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
char *Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
{
int i;
@ -1365,7 +1365,7 @@ void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
}
if (!*text)
return;
return text;
if (cmd_argc == 1)
{
@ -1374,7 +1374,9 @@ void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
text = COM_StringParse (text, com_token, sizeof(com_token), expandmacros, qctokenize);
if (!text)
return;
return text;
if (!strcmp(com_token, "\n"))
return text;
if (cmd_argc < MAX_ARGS)
{
@ -1383,6 +1385,7 @@ void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
cmd_argc++;
}
}
return text;
}
void Cmd_TokenizePunctation (char *text, char *punctuation)
@ -1438,7 +1441,7 @@ Cmd_AddCommand
============
*/
qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function)
qboolean Cmd_AddCommandD (char *cmd_name, xcommand_t function, char *desc)
{
cmd_function_t *cmd;
@ -1467,6 +1470,7 @@ qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function)
cmd = (cmd_function_t*)Z_Malloc (sizeof(cmd_function_t)+strlen(cmd_name)+1);
cmd->name = (char*)(cmd+1);
cmd->description = desc;
strcpy(cmd->name, cmd_name);
cmd->function = function;
cmd->next = cmd_functions;
@ -1476,6 +1480,11 @@ qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function)
return true;
}
qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function)
{
return Cmd_AddCommandD(cmd_name, function, NULL);
}
void Cmd_RemoveCommand (char *cmd_name)
{
cmd_function_t *cmd, **back;
@ -1660,8 +1669,9 @@ typedef struct {
qboolean allowcutdown;
qboolean cutdown;
char result[256];
char *desc;
} match_t;
void Cmd_CompleteCheck(char *check, match_t *match) //compare cumulative strings and join the result
void Cmd_CompleteCheck(char *check, match_t *match, char *desc) //compare cumulative strings and join the result
{
if (*match->result)
{
@ -1678,21 +1688,19 @@ void Cmd_CompleteCheck(char *check, match_t *match) //compare cumulative strings
else if (match->matchnum > 0)
{
strcpy(match->result, check);
match->desc = desc;
match->matchnum--;
}
}
else
{
if (match->matchnum > 0)
{
strcpy(match->result, check);
match->matchnum--;
}
else
strcpy(match->result, check);
match->desc = desc;
}
}
char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens, int matchnum)
char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens, int matchnum, char **descptr)
{
extern cvar_group_t *cvar_groups;
cmd_function_t *cmd;
@ -1711,6 +1719,9 @@ char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens
else
len = Q_strlen(partial);
if (descptr)
*descptr = NULL;
if (!len)
return NULL;
@ -1719,6 +1730,7 @@ char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens
match.allowcutdown = !fullonly?true:false;
match.cutdown = false;
match.desc = NULL;
if (matchnum)
match.matchnum = matchnum;
else
@ -1731,17 +1743,17 @@ char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens
{
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
if (!Q_strncasecmp (partial,cmd->name, len) && (matchnum == -1 || !partial[len] || strlen(cmd->name) == len))
Cmd_CompleteCheck(cmd->name, &match);
Cmd_CompleteCheck(cmd->name, &match, cmd->description);
for (a=cmd_alias ; a ; a=a->next)
if (!Q_strncasecmp (partial, a->name, len) && (matchnum == -1 || !partial[len] || strlen(a->name) == len))
Cmd_CompleteCheck(a->name, &match);
Cmd_CompleteCheck(a->name, &match, "");
for (grp=cvar_groups ; grp ; grp=grp->next)
for (cvar=grp->cvars ; cvar ; cvar=cvar->next)
{
if (!Q_strncasecmp (partial,cvar->name, len) && (matchnum == -1 || !partial[len] || strlen(cvar->name) == len))
Cmd_CompleteCheck(cvar->name, &match);
Cmd_CompleteCheck(cvar->name, &match, cvar->description);
if (cvar->name2 && !Q_strncasecmp (partial,cvar->name2, len) && (matchnum == -1 || !partial[len] || strlen(cvar->name2) == len))
Cmd_CompleteCheck(cvar->name2, &match);
Cmd_CompleteCheck(cvar->name2, &match, cvar->description);
}
}
@ -1749,23 +1761,26 @@ char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens
{
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
if (!Q_strncmp (partial,cmd->name, len) && (matchnum == -1 || !partial[len] || strlen(cmd->name) == len))
Cmd_CompleteCheck(cmd->name, &match);
Cmd_CompleteCheck(cmd->name, &match, cmd->description);
for (a=cmd_alias ; a ; a=a->next)
if (!Q_strncmp (partial, a->name, len) && (matchnum == -1 || !partial[len] || strlen(a->name) == len))
Cmd_CompleteCheck(a->name, &match);
Cmd_CompleteCheck(a->name, &match, "");
for (grp=cvar_groups ; grp ; grp=grp->next)
for (cvar=grp->cvars ; cvar ; cvar=cvar->next)
{
if (!Q_strncmp (partial,cvar->name, len) && (matchnum == -1 || !partial[len] || strlen(cvar->name) == len))
Cmd_CompleteCheck(cvar->name, &match);
Cmd_CompleteCheck(cvar->name, &match, cvar->description);
if (cvar->name2 && !Q_strncmp (partial,cvar->name2, len) && (matchnum == -1 || !partial[len] || strlen(cvar->name2) == len))
Cmd_CompleteCheck(cvar->name2, &match);
Cmd_CompleteCheck(cvar->name2, &match, cvar->description);
}
}
if (match.matchnum>0)
return NULL;
if (!*match.result)
return NULL;
if (descptr)
*descptr = match.desc;
return match.result;
}
@ -2735,6 +2750,7 @@ void Cmd_WriteConfig_f(void)
vfsfile_t *f;
char *filename;
char fname[MAX_OSPATH];
char sysname[MAX_OSPATH];
filename = Cmd_Argv(1);
if (!*filename)
@ -2779,6 +2795,9 @@ void Cmd_WriteConfig_f(void)
VFS_CLOSE(f);
Cvar_Saved();
FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname));
Con_Printf ("Wrote %s\n",sysname);
}
void Cmd_Reset_f(void)

View file

@ -78,6 +78,7 @@ void Cmd_StuffCmds (void);
void Cmd_RemoveCommand (char *cmd_name);
qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function);
qboolean Cmd_AddCommandD (char *cmd_name, xcommand_t function, char *description);
// called by the init functions of other parts of the program to
// register commands and functions to call for them.
// The cmd_name is referenced later, so it should not be in temp memory
@ -89,7 +90,7 @@ qboolean Cmd_Exists (char *cmd_name);
char *Cmd_Describe (char *cmd_name);
char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens, int matchnum);
char *Cmd_CompleteCommand (char *partial, qboolean fullonly, qboolean caseinsens, int matchnum, char **descptr);
qboolean Cmd_IsCommand (char *line);
// attempts to match a partial command for automatic command line completion
// returns NULL if nothing fits
@ -114,7 +115,7 @@ void Alias_WipeStuffedAliaes(void);
void Cmd_AddMacro(char *s, char *(*f)(void), int disputableintentions);
void Cmd_TokenizePunctation (char *text, char *punctuation);
void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize);
char *Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize);
// Takes a null terminated string. Does not need to be /n terminated.
// breaks the string up into arg tokens.

View file

@ -1534,8 +1534,9 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent
#ifdef SKELETALMODELS
meshcache.usebonepose = NULL;
if (inf->ofs_skel_xyz && 1)//!inf->ofs_skel_weight)
if (inf->ofs_skel_xyz && !inf->ofs_skel_weight)
{
//if we have skeletal xyz info, but no skeletal weights, then its a partial model that cannot possibly be animated.
meshcache.usebonepose = NULL;
mesh->xyz_array = (vecV_t*)((char*)inf + inf->ofs_skel_xyz);
mesh->xyz2_array = NULL;
@ -1548,8 +1549,10 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent
mesh->xyz2_array = NULL;
meshcache.usebonepose = Alias_GetBonePositions(inf, &e->framestate, meshcache.bonepose, MAX_BONES, true);
if (e->fatness || !inf->ofs_skel_idx || !usebones)
if (e->fatness || !inf->ofs_skel_idx || !usebones || inf->numswtransforms)
{
//software bone animation
//there are two ways to animate a skeleton, one is to transform
Alias_BuildSkeletalMesh(mesh, meshcache.usebonepose, inf);
#ifdef PEXT_FATNESS
@ -1575,6 +1578,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent
}
else
{
//hardware bone animation
mesh->xyz_array = (vecV_t*)((char*)inf + inf->ofs_skel_xyz);
mesh->normals_array = (vec3_t*)((char*)inf + inf->ofs_skel_norm);
mesh->snormals_array = (vec3_t*)((char*)inf + inf->ofs_skel_svect);
@ -5842,7 +5846,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(bones[i].name));
bones[i].parent = ijoint[i].parent;
GenMatrixPosQuat3Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]);
GenMatrixPosQuat3Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, mat);
if (ijoint[i].parent >= 0)
Matrix3x4_Multiply(mat, &basepose[ijoint[i].parent*12], &basepose[i*12]);
@ -5932,7 +5936,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
for (i = 0; i < h->num_anims; i++)
{
fgroup[i].isheirachical = true;
fgroup[i].loop = LittleLong(anim[i].flags) & IQM_LOOP;
fgroup[i].loop = !!(LittleLong(anim[i].flags) & IQM_LOOP);
Q_strncpyz(fgroup[i].name, strings+anim[i].name, sizeof(fgroup[i].name));
fgroup[i].numposes = LittleLong(anim[i].num_frames);
fgroup[i].poseofs = (char*)(opose+LittleLong(anim[i].first_frame)*12*h->num_poses) - (char*)&fgroup[i];

View file

@ -482,7 +482,7 @@ void (ODE_API *dJointSetUniversalParam)(dJointID, int parameter, dRea
//void (ODE_API *dJointSetPistonAnchorOffset)(dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz);
//void (ODE_API *dJointSetPistonParam)(dJointID, int parameter, dReal value);
//void (ODE_API *dJointAddPistonForce)(dJointID joint, dReal force);
//void (ODE_API *dJointSetFixed)(dJointID);
void (ODE_API *dJointSetFixed)(dJointID);
//void (ODE_API *dJointSetFixedParam)(dJointID, int parameter, dReal value);
//void (ODE_API *dJointSetAMotorNumAxes)(dJointID, int num);
//void (ODE_API *dJointSetAMotorAxis)(dJointID, int anum, int rel, dReal x, dReal y, dReal z);
@ -947,7 +947,7 @@ static dllfunction_t odefuncs[] =
// {"dJointSetPistonAnchorOffset", (void **) &dJointSetPistonAnchorOffset},
// {"dJointSetPistonParam", (void **) &dJointSetPistonParam},
// {"dJointAddPistonForce", (void **) &dJointAddPistonForce},
// {"dJointSetFixed", (void **) &dJointSetFixed},
{(void **) &dJointSetFixed, "dJointSetFixed"},
// {"dJointSetFixedParam", (void **) &dJointSetFixedParam},
// {"dJointSetAMotorNumAxes", (void **) &dJointSetAMotorNumAxes},
// {"dJointSetAMotorAxis", (void **) &dJointSetAMotorAxis},
@ -1177,7 +1177,7 @@ void World_ODE_Init(void)
const char* dllname =
{
# if defined(WIN64)
"libode1_64.dll"
"libode1_64"
# elif defined(WIN32)
"ode_double"
# elif defined(MACOSX)
@ -1664,7 +1664,6 @@ static void World_ODE_Frame_JointFromEntity(world_t *world, wedict_t *ed)
break;
case 0:
default:
Sys_Error("what? but above the joint was valid...\n");
break;
}
#undef SETPARAMS
@ -1771,11 +1770,169 @@ static qboolean GenerateCollisionMesh(world_t *world, model_t *mod, wedict_t *ed
ed->ode.ode_numtriangles = numindexes/3;
return true;
}
/*
static void World_ODE_BodyFromSkel(world_t *world)
qboolean World_ODE_RagCreateBody(world_t *world, odebody_t *bodyptr, float *mat, wedict_t *ent)
{
dVector3 r[3];
if (!world->ode.ode_space)
return false;
bodyptr->ode_geom = dCreateBox(world->ode.ode_space, 3, 3, 3);
bodyptr->ode_body = dBodyCreate(world->ode.ode_world);
dGeomSetBody(bodyptr->ode_geom, bodyptr->ode_body);
dGeomSetData(bodyptr->ode_geom, (void*)ent);
r[0][0] = mat[0];
r[0][1] = mat[1];
r[0][2] = mat[2];
r[1][0] = mat[4];
r[1][1] = mat[5];
r[1][2] = mat[6];
r[2][0] = mat[8];
r[2][1] = mat[9];
r[2][2] = mat[10];
dBodySetPosition(bodyptr->ode_body, mat[3], mat[7], mat[11]);
dBodySetRotation(bodyptr->ode_body, r[0]);
dBodySetLinearVel(bodyptr->ode_body, 0, 0, 0);
dBodySetAngularVel(bodyptr->ode_body, 0, 0, 0);
return true;
}
*/
void World_ODE_RagMatrixFromBody(world_t *world, odebody_t *bodyptr, float *mat)
{
const dReal *o = dBodyGetPosition(bodyptr->ode_body);
const dReal *r = dBodyGetRotation(bodyptr->ode_body);
mat[0] = r[0];
mat[1] = r[1];
mat[2] = r[2];
mat[3] = o[0];
mat[4] = r[4];
mat[5] = r[5];
mat[6] = r[6];
mat[7] = o[1];
mat[8] = r[8];
mat[9] = r[9];
mat[10] = r[10];
mat[11] = o[2];
}
void World_ODE_RagCreateJoint(world_t *world, odejoint_t *joint, odejointinfo_t *info, odebody_t *body1, odebody_t *body2, vec3_t aaa2[3])
{
switch(info->type)
{
case JOINTTYPE_POINT:
joint->ode_joint = dJointCreateBall(world->ode.ode_world, 0);
break;
case JOINTTYPE_HINGE:
joint->ode_joint = dJointCreateHinge(world->ode.ode_world, 0);
break;
case JOINTTYPE_SLIDER:
joint->ode_joint = dJointCreateSlider(world->ode.ode_world, 0);
break;
case JOINTTYPE_UNIVERSAL:
joint->ode_joint = dJointCreateUniversal(world->ode.ode_world, 0);
break;
case JOINTTYPE_HINGE2:
joint->ode_joint = dJointCreateHinge2(world->ode.ode_world, 0);
break;
case JOINTTYPE_FIXED:
joint->ode_joint = dJointCreateFixed(world->ode.ode_world, 0);
break;
default:
joint->ode_joint = NULL;
break;
}
if (joint->ode_joint)
{
//Con_Printf("made new joint %i\n", (int) (ed - prog->edicts));
// dJointSetData(joint->ode_joint, NULL);
dJointAttach(joint->ode_joint, body1?body1->ode_body:NULL, body2?body2->ode_body:NULL);
switch(info->type)
{
case JOINTTYPE_POINT:
dJointSetBallAnchor(joint->ode_joint, aaa2[0][0], aaa2[0][1], aaa2[0][2]);
break;
case JOINTTYPE_HINGE:
dJointSetHingeAnchor(joint->ode_joint, aaa2[0][0], aaa2[0][1], aaa2[0][2]);
dJointSetHingeAxis(joint->ode_joint, aaa2[1][0], aaa2[1][1], aaa2[1][2]);
dJointSetHingeParam(joint->ode_joint, dParamFMax, info->FMax);
dJointSetHingeParam(joint->ode_joint, dParamHiStop, info->HiStop);
dJointSetHingeParam(joint->ode_joint, dParamLoStop, info->LoStop);
dJointSetHingeParam(joint->ode_joint, dParamStopCFM, info->CFM);
dJointSetHingeParam(joint->ode_joint, dParamStopERP, info->ERP);
dJointSetHingeParam(joint->ode_joint, dParamVel, info->Vel);
break;
case JOINTTYPE_SLIDER:
dJointSetSliderAxis(joint->ode_joint, aaa2[1][0], aaa2[1][1], aaa2[1][2]);
dJointSetSliderParam(joint->ode_joint, dParamFMax, info->FMax);
dJointSetSliderParam(joint->ode_joint, dParamHiStop, info->HiStop);
dJointSetSliderParam(joint->ode_joint, dParamLoStop, info->LoStop);
dJointSetSliderParam(joint->ode_joint, dParamStopCFM, info->CFM);
dJointSetSliderParam(joint->ode_joint, dParamStopERP, info->ERP);
dJointSetSliderParam(joint->ode_joint, dParamVel, info->Vel);
break;
case JOINTTYPE_UNIVERSAL:
dJointSetUniversalAnchor(joint->ode_joint, aaa2[0][0], aaa2[0][1], aaa2[0][2]);
dJointSetUniversalAxis1(joint->ode_joint, aaa2[1][0], aaa2[1][1], aaa2[1][2]);
dJointSetUniversalAxis2(joint->ode_joint, aaa2[2][0], aaa2[2][1], aaa2[2][2]);
dJointSetUniversalParam(joint->ode_joint, dParamFMax, info->FMax);
dJointSetUniversalParam(joint->ode_joint, dParamHiStop, info->HiStop);
dJointSetUniversalParam(joint->ode_joint, dParamLoStop, info->LoStop);
dJointSetUniversalParam(joint->ode_joint, dParamStopCFM, info->CFM);
dJointSetUniversalParam(joint->ode_joint, dParamStopERP, info->ERP);
dJointSetUniversalParam(joint->ode_joint, dParamVel, info->Vel);
dJointSetUniversalParam(joint->ode_joint, dParamFMax2, info->FMax2);
dJointSetUniversalParam(joint->ode_joint, dParamHiStop2, info->HiStop2);
dJointSetUniversalParam(joint->ode_joint, dParamLoStop2, info->LoStop2);
dJointSetUniversalParam(joint->ode_joint, dParamStopCFM2, info->CFM2);
dJointSetUniversalParam(joint->ode_joint, dParamStopERP2, info->ERP2);
dJointSetUniversalParam(joint->ode_joint, dParamVel2, info->Vel2);
break;
case JOINTTYPE_HINGE2:
dJointSetHinge2Anchor(joint->ode_joint, aaa2[0][0], aaa2[0][1], aaa2[0][2]);
dJointSetHinge2Axis1(joint->ode_joint, aaa2[1][0], aaa2[1][1], aaa2[1][2]);
dJointSetHinge2Axis2(joint->ode_joint, aaa2[2][0], aaa2[2][1], aaa2[2][2]);
dJointSetHinge2Param(joint->ode_joint, dParamFMax, info->FMax);
dJointSetHinge2Param(joint->ode_joint, dParamHiStop, info->HiStop);
dJointSetHinge2Param(joint->ode_joint, dParamLoStop, info->LoStop);
dJointSetHinge2Param(joint->ode_joint, dParamStopCFM, info->CFM);
dJointSetHinge2Param(joint->ode_joint, dParamStopERP, info->ERP);
dJointSetHinge2Param(joint->ode_joint, dParamVel, info->Vel);
dJointSetHinge2Param(joint->ode_joint, dParamFMax2, info->FMax2);
dJointSetHinge2Param(joint->ode_joint, dParamHiStop2, info->HiStop2);
dJointSetHinge2Param(joint->ode_joint, dParamLoStop2, info->LoStop2);
dJointSetHinge2Param(joint->ode_joint, dParamStopCFM2, info->CFM2);
dJointSetHinge2Param(joint->ode_joint, dParamStopERP2, info->ERP2);
dJointSetHinge2Param(joint->ode_joint, dParamVel2, info->Vel2);
break;
case JOINTTYPE_FIXED:
dJointSetFixed(joint->ode_joint);
break;
}
}
}
void World_ODE_RagDestroyBody(world_t *world, odebody_t *bodyptr)
{
if (bodyptr->ode_geom)
dGeomDestroy(bodyptr->ode_geom);
bodyptr->ode_geom = NULL;
if (bodyptr->ode_body)
dBodyDestroy(bodyptr->ode_body);
bodyptr->ode_body = NULL;
}
void World_ODE_RagDestroyJoint(world_t *world, odejoint_t *joint)
{
if (joint->ode_joint)
dJointDestroy(joint->ode_joint);
joint->ode_joint = NULL;
}
static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
{
dBodyID body = (dBodyID)ed->ode.ode_body;
@ -1995,21 +2152,13 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
}
// get current data from entity
VectorClear(origin);
VectorClear(velocity);
//VectorClear(forward);
//VectorClear(left);
//VectorClear(up);
//VectorClear(spinvelocity);
VectorClear(angles);
VectorClear(avelocity);
gravity = true;
VectorCopy(ed->v->origin, origin);
VectorCopy(ed->v->velocity, velocity);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_forward);if (val) VectorCopy(val->vector, forward);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_left);if (val) VectorCopy(val->vector, left);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(val->vector, up);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(val->vector, spinvelocity);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_forward);if (val) VectorCopy(val->vector, forward); else VectorClear(forward);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_left);if (val) VectorCopy(val->vector, left); else VectorClear(left);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(val->vector, up); else VectorClear(up);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(val->vector, spinvelocity); else VectorClear(spinvelocity);
VectorCopy(ed->v->angles, angles);
VectorCopy(ed->v->avelocity, avelocity);
if (ed == world->edicts || (ed->xv->gravity && ed->xv->gravity <= 0.01))
@ -2231,11 +2380,11 @@ static void VARGS nearCallback (void *data, dGeomID o1, dGeomID o2)
return;
ed1 = (wedict_t *) dGeomGetData(o1);
if(ed1 && ed1->isfree)
ed1 = NULL;
if(!ed1 || ed1->isfree)
ed1 = world->edicts;
ed2 = (wedict_t *) dGeomGetData(o2);
if(ed2 && ed2->isfree)
ed2 = NULL;
if(!ed2 || ed2->isfree)
ed2 = world->edicts;
// generate contact points between the two non-space geoms
numcontacts = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(contact[0]));
@ -2317,7 +2466,7 @@ static void VARGS nearCallback (void *data, dGeomID o1, dGeomID o2)
void World_ODE_Frame(world_t *world, double frametime, double gravity)
{
if (world->ode.ode && (world->ode.hasodeents))// || world->ode.hasragdoll))
if (world->ode.ode && (world->ode.hasodeents || world->ode.hasextraobjs))
{
int i;
wedict_t *ed;

View file

@ -93,6 +93,7 @@ cvar_t gameversion = CVARFD("gameversion","", CVAR_SERVERINFO, "gamecode version
cvar_t gameversion_min = CVARD("gameversion_min","", "gamecode version for server browsers");
cvar_t gameversion_max = CVARD("gameversion_max","", "gamecode version for server browsers");
cvar_t fs_gamename = CVARFD("fs_gamename", "", CVAR_NOSET, "The filesystem is trying to run this game");
cvar_t fs_gamedownload = CVARFD("fs_gamedownload", "", CVAR_NOSET, "The place that the game can be downloaded from.");
cvar_t com_protocolname = CVARD("com_gamename", "", "The game name used for dpmaster queries");
cvar_t com_modname = CVARD("com_modname", "", "dpmaster information");
cvar_t com_parseutf8 = CVARD("com_parseutf8", "0", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts. -1=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
@ -188,7 +189,7 @@ void QDECL Q_strncpyz(char *d, const char *s, int n)
//windows/linux have inconsistant snprintf
//this is an attempt to get them consistant and safe
//size is the total size of the buffer
void VARGS Q_vsnprintfz (char *dest, size_t size, char *fmt, va_list argptr)
void VARGS Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr)
{
vsnprintf (dest, size, fmt, argptr);
dest[size-1] = 0;
@ -197,7 +198,7 @@ void VARGS Q_vsnprintfz (char *dest, size_t size, char *fmt, va_list argptr)
//windows/linux have inconsistant snprintf
//this is an attempt to get them consistant and safe
//size is the total size of the buffer
void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...)
void VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...)
{
va_list argptr;
@ -405,7 +406,7 @@ char *Q_strlwr(char *s)
int wildcmp(const char *wild, const char *string)
{
const char *cp=NULL, *mp=NULL;
/*
while ((*string) && (*wild != '*'))
{
if ((*wild != *string) && (*wild != '?'))
@ -415,30 +416,29 @@ int wildcmp(const char *wild, const char *string)
wild++;
string++;
}
*/
while (*string)
{
if (*wild == '*')
{
if (!*++wild) //a * at the end of the wild string matches anything the checked string has
if (wild[1] == *string || *string == '/' || *string == '\\')
{
string = strchr(string, '/');
if (string && string[1]) /*don't match it if there's a / with something after it*/
return 0;
return 1;
//* terminates if we get a match on the char following it, or if its a \ or / char
wild++;
continue;
}
mp = wild;
cp = string+1;
string++;
}
else if ((*wild == *string) || (*wild == '?'))
{
//this char matches
wild++;
string++;
}
else
{
wild = mp;
string = cp++;
//failure
return false;
}
}
@ -1629,7 +1629,7 @@ char *COM_SkipPath (const char *pathname)
last = pathname;
while (*pathname)
{
if (*pathname=='/')
if (*pathname=='/' || *pathname == '\\')
last = pathname+1;
pathname++;
}
@ -2455,77 +2455,25 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
messedup:
if (!--outsize)
break;
uc = (unsigned char)(*str++);
if (utf8)
*out++ = (unsigned char)(*str++) | ext;
*out++ = uc | ext;
else
{
if (strchr("\n\r\t ", *str))
*out++ = (unsigned char)(*str++) | (ext&~CON_HIGHCHARSMASK);
else if (*str >= 32 && *str < 127 && !(ext&CON_HIGHCHARSMASK))
*out++ = (unsigned char)(*str++) | ext;
if (uc == '\n' || uc == '\r' || uc == '\t' || uc == ' ')
*out++ = uc | (ext&~CON_HIGHCHARSMASK);
else if (uc >= 32 && uc < 127 && !(ext&CON_HIGHCHARSMASK))
*out++ = uc | ext;
else if (uc >= 0x80+32 && uc < 0x80+127)
*out++ = (uc&127) | ext ^ CON_2NDCHARSETTEXT;
else
*out++ = (unsigned char)(*str++) | ext | 0xe000;
*out++ = uc | ext | 0xe000;
}
}
*out = 0;
return out;
}
int COM_FunStringLength(unsigned char *str)
{
//FIXME:
int len = 0;
while(*str)
{
//fixme: utf8
if (*str == '^')
{
str++;
if (*str >= '0' && *str <= '9')
str++; //invisible
else if (*str == '&') // extended code
{
if (isextendedcode(str[1]) && isextendedcode(str[2]))
{
str++;// foreground char
str++; // background char
str++;
continue;
}
// else invalid code
goto messedup;
}
else if (*str == 'a' || *str == 'b' || *str == 'h' || *str == 's' || *str == 'r')
str++; //invisible
else if (*str == '^')
{
len++; //double-code single-output
str++;
}
else
{
len++; //not recognised
len++;
str++;
}
continue;
}
if (*str == '&' && str[1] == 'c' && ishexcode(str[2]) && ishexcode(str[3]) && ishexcode(str[4]))
{
//ezquake colour codes
str += 5;
continue;
}
messedup:
len++;
str++;
}
return len;
}
//============================================================================
#define TOKENSIZE sizeof(com_token)
@ -3472,6 +3420,12 @@ void COM_Version_f (void)
}
#endif
#ifdef MULTITHREAD
Con_Printf("multithreading: enabled\n");
#else
Con_Printf("multithreading: disabled\n");
#endif
//print out which libraries are disabled
#ifndef AVAIL_ZLIB
Con_Printf("zlib disabled\n");
@ -3493,6 +3447,37 @@ void COM_Version_f (void)
#else
Con_Printf("libjpeg: %i (%d series)\n", JPEG_LIB_VERSION, ( JPEG_LIB_VERSION / 10 ) );
#endif
#ifdef SPEEX_STATIC
Con_Printf("speex: static\n");
#elif defined(VOICECHAT)
Con_Printf("speex: dynamic\n");
#else
Con_Printf("speex: disabled\n");
#endif
#ifdef ODE_STATIC
Con_Printf("ODE: static\n");
#elif defined(USEODE)
Con_Printf("ODE: dynamic\n");
#else
Con_Printf("ODE: disabled\n");
#endif
#ifndef AVAIL_OGGVORBIS
Con_Printf("Ogg Vorbis: disabled\n");
#elif defined(LIBVORBISFILE_STATIC)
Con_Printf("Ogg Vorbis: static\n");
#else
Con_Printf("Ogg Vorbis: dynamic\n");
#endif
#ifdef USE_MYSQL
Con_Printf("mySQL: dynamic\n");
#else
Con_Printf("mySQL: disabled\n");
#endif
#ifdef USE_SQLITE
Con_Printf("sqlite: dynamic\n");
#else
Con_Printf("sqlite: disabled\n");
#endif
#ifndef AVAIL_OGGVORBIS
Con_Printf("libvorbis disabled\n");
#endif
@ -3734,7 +3719,7 @@ void COM_Effectinfo_Reload(void)
if (!f)
return;
buf = f;
while (*f)
while (f && *f)
{
f = COM_ParseToken(f, NULL);
if (strcmp(com_token, "\n"))
@ -3749,7 +3734,7 @@ void COM_Effectinfo_Reload(void)
do
{
f = COM_ParseToken(f, NULL);
} while(*f && strcmp(com_token, "\n"));
} while(f && *f && strcmp(com_token, "\n"));
}
}
FS_FreeFile(buf);

View file

@ -211,8 +211,8 @@ int wildcmp(const char *wild, const char *string); //1 if match
#define Q_strcmp(s1, s2) strcmp((s1), (s2))
#define Q_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...) LIKEPRINTF(3);
void VARGS Q_vsnprintfz (char *dest, size_t size, char *fmt, va_list args);
void VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...) LIKEPRINTF(3);
void VARGS Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list args);
int VARGS Com_sprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
#define Q_strncpyS(d, s, n) do{const char *____in=(s);char *____out=(d);int ____i; for (____i=0;*(____in); ____i++){if (____i == (n))break;*____out++ = *____in++;}if (____i < (n))*____out='\0';}while(0) //only use this when it should be used. If undiciided, use N
@ -277,7 +277,6 @@ void COM_ParsePlusSets (void);
typedef unsigned int conchar_t;
char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags);
conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, qboolean keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator
int COM_FunStringLength(unsigned char *str);
char *COM_SkipPath (const char *pathname);
void COM_StripExtension (const char *in, char *out, int outlen);
@ -391,7 +390,6 @@ void FS_ReloadPackFiles(void);
char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum);
FTE_DEPRECATED int COM_filelength (FILE *f);
qbyte *COM_LoadStackFile (const char *path, void *buffer, int bufsize);
qbyte *COM_LoadTempFile (const char *path);
qbyte *COM_LoadTempMoreFile (const char *path); //allocates a little bit more without freeing old temp

View file

@ -117,7 +117,6 @@ typedef struct console_s
int x; // offset in current line for next print
int cr;
conline_t *display; // bottom of console displays this line
int subline;
int vislines; // pixel lines
int linesprinted; // for notify times
qboolean unseentext;
@ -132,6 +131,15 @@ extern console_t con_main;
extern console_t *con_current; // point to either con_main or con_chat
extern console_t *con_chat;
//shared between console and keys.
//really the console input should be in console.c instead of keys.c I suppose.
#define MAXCMDLINE 256
#define CON_EDIT_LINES_MASK ((1<<6)-1)
extern unsigned char key_lines[CON_EDIT_LINES_MASK+1][MAXCMDLINE];
extern int edit_line;
extern int key_linepos;
extern int history_line;
extern int scr_chatmode;
//extern int con_totallines;
@ -144,6 +152,7 @@ void Con_CheckResize (void);
void Con_ForceActiveNow(void);
void Con_Init (void);
void Con_Shutdown (void);
void Con_History_Load(void);
void Con_DrawConsole (int lines, qboolean noback);
char *Con_CopyConsole(qboolean nomarkup);
void Con_Print (char *txt);
@ -151,6 +160,7 @@ void VARGS Con_Printf (const char *fmt, ...) LIKEPRINTF(1);
void VARGS Con_TPrintf (translation_t text, ...);
void VARGS Con_DPrintf (char *fmt, ...) LIKEPRINTF(1);
void VARGS Con_SafePrintf (char *fmt, ...) LIKEPRINTF(1);
void Con_Footerf(qboolean append, char *fmt, ...) LIKEPRINTF(2);
void Con_Clear_f (void);
void Con_DrawNotify (void);
void Con_ClearNotify (void);

View file

@ -176,40 +176,6 @@ searchpath_t *com_searchpaths;
searchpath_t *com_purepaths;
searchpath_t *com_base_searchpaths; // without gamedirs
/*
================
COM_filelength
================
*/
int COM_filelength (FILE *f)
{
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
/*
static int COM_FileOpenRead (char *path, FILE **hndl)
{
FILE *f;
f = fopen(path, "rb");
if (!f)
{
*hndl = NULL;
return -1;
}
*hndl = f;
return COM_filelength(f);
}
*/
int COM_FileSize(const char *path)
{
int len;
@ -1810,8 +1776,8 @@ void COM_Gamedir (const char *dir)
/*stuff that makes dp-only mods work a bit better*/
#define DPCOMPAT "set _cl_playermodel \"\"\n set dpcompat_set 1\n set dpcompat_trailparticles 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n"
/*nexuiz/xonotic has a few quirks...*/
#define NEXCFG DPCOMPAT "set r_particlesdesc effectinfo\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\n"
/*nexuiz/xonotic has a few quirks/annoyances...*/
#define NEXCFG DPCOMPAT "set r_particlesdesc effectinfo\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\npr_enable_uriget 0\n"
/*some modern non-compat settings*/
#define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n"
/*set some stuff so our regular qw client appears more like hexen2*/
@ -1830,6 +1796,7 @@ typedef struct {
const char *dir[4];
const char *poshname; //Full name for the game.
const char *downloadaddr;
} gamemode_info_t;
const gamemode_info_t gamemode_info[] = {
//note that there is no basic 'fte' gamemode, this is because we aim for network compatability. Darkplaces-Quake is the closest we get.
@ -1837,12 +1804,12 @@ const gamemode_info_t gamemode_info[] = {
//rogue/hipnotic have no special files - the detection conflicts and stops us from running regular quake
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
{"-quake", "q1", "DarkPlaces-Quake", {"id1/pak0.pak"
"id1/quake.rc"}, NULL, {"id1", "qw", "fte"}, "Quake"},
{"-quake", "q1", "DarkPlaces-Quake", {"id1/pak0.pak",
"id1/quake.rc"}, NULL, {"id1", "qw", "fte"}, "Quake"/*, "id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
{"-hipnotic", "hipnotic", "Darkplaces-Hipnotic", {NULL}, NULL, {"id1", "qw", "hipnotic", "fte"}, "Quake: Scourge of Armagon"},
{"-rogue", "rogue", "Darkplaces-Rogue", {NULL}, NULL, {"id1", "qw", "rogue", "fte"}, "Quake: Dissolution of Eternity"},
{"-nexuiz", "nexuiz", "Nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "ftedata"}, "Nexuiz"},
{"-xonotic", "xonotic", "Xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic"},
{"-xonotic", "xonotic", "Xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic", "data/xonotic-20120308-data.pk3|http://localhost/xonotic-0.6.0.zip"},
{"-spark", "spark", "Spark", {"base/src/progs.src",
"base/qwprogs.dat",
"base/pak0.pak"}, DMFCFG, {"base", }, "Spark"},
@ -2215,7 +2182,8 @@ static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir
FILE *f;
DWORD resultlen;
HKEY key = NULL;
if (!FAILED(RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key)))
if (RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\Valve\\Steam", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "SteamPath", NULL, NULL, basepath, &resultlen);
@ -2239,7 +2207,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
#endif
//first, try and find it in our game paths location
if (!FAILED(RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key)))
if (RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
if (!RegQueryValueEx(key, gamename, NULL, NULL, basepath, &resultlen))
@ -2284,7 +2252,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
HKEY key = NULL;
//look for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Quake2_exe\Path
if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Quake2_exe", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key)))
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Quake2_exe", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "Path", NULL, NULL, basepath, &resultlen);
@ -2306,7 +2274,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\Activision\Wolfenstein - Enemy Territory
if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Activision\\Wolfenstein - Enemy Territory", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key)))
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Activision\\Wolfenstein - Enemy Territory", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
@ -2328,7 +2296,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Quake III Arena\InstallPath
if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Quake III Arena", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key)))
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Quake III Arena", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
@ -2350,7 +2318,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\World Of Padman\Path
if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\World Of Padman", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key)))
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\World Of Padman", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "Path", NULL, NULL, basepath, &resultlen);
@ -2365,7 +2333,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
DWORD resultlen;
HKEY key = NULL;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Doom 3\InstallPath
if (!FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Doom 3", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key)))
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\id\\Doom 3", 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
resultlen = basepathlen;
RegQueryValueEx(key, "InstallPath", NULL, NULL, basepath, &resultlen);
@ -2416,13 +2384,13 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
Q_strncpyz(basepath, resultpath, basepathlen-1);
//and save it into the windows registry
if (!FAILED(RegCreateKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths",
if (RegCreateKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths",
0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&key,
NULL)))
NULL) == ERROR_SUCCESS)
{
RegSetValueEx(key, gamename, 0, REG_SZ, basepath, strlen(basepath));
@ -2439,6 +2407,9 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
#else
qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen)
{
#ifdef __linux__
// /usr/share/quake
#endif
return false;
}
#endif
@ -2518,6 +2489,7 @@ void FS_StartupWithGame(int gamenum)
Cvar_Set(&com_protocolname, gamemode_info[gamenum].protocolname);
Cvar_ForceSet(&fs_gamename, gamemode_info[gamenum].poshname);
Cvar_ForceSet(&fs_gamedownload, gamemode_info[gamenum].downloadaddr?gamemode_info[gamenum].downloadaddr:"");
i = COM_CheckParm ("-basepack");
while (i && i < com_argc-1)
@ -2596,7 +2568,7 @@ void FS_StartupWithGame(int gamenum)
COM_Gamedir(com_argv[i+1]);
}
#if 1//def ANDROID
#ifdef ANDROID
{
vfsfile_t *f;
//write a .nomedia file to avoid people from getting random explosion sounds etc intersperced with their music
@ -2679,6 +2651,7 @@ void COM_InitFilesystem (void)
Cvar_Register(&fs_gamename, "FS");
Cvar_Register(&fs_gamedownload, "FS");
Cvar_Register(&com_protocolname, "Server Info");
Cvar_Register(&com_modname, "Server Info");
//identify the game from a telling file
@ -2697,6 +2670,29 @@ void COM_InitFilesystem (void)
}
}
}
if (gamenum == -1 && host_parms.binarydir && *host_parms.binarydir && autobasedir)
{
for (i = 0; gamemode_info[i].argname && gamenum==-1; i++)
{
//look in the directory the exe exists in if we failed to find a valid installation in the working dir
for (j = 0; j < 4; j++)
{
if (gamemode_info[i].auniquefile[j])
{
f = VFSOS_Open(va("%s%s", host_parms.binarydir, gamemode_info[i].auniquefile[j]), "rb");
if (f)
{
//apply this as the new -basedir
Q_strncpyz(com_quakedir, host_parms.binarydir, sizeof(com_quakedir));
gamenum = i;
//we found it, its all okay
VFS_CLOSE(f);
break;
}
}
}
}
}
//use the game based on an exe name over the filesystem one (could easily have multiple fs path matches).
for (i = 0; gamemode_info[i].argname; i++)
{
@ -2711,6 +2707,9 @@ void COM_InitFilesystem (void)
{
gamenum = i;
if (autobasedir)
{
//try the working directory first
for (j = 0; j < 4; j++)
{
if (gamemode_info[gamenum].auniquefile[j])
@ -2722,11 +2721,33 @@ void COM_InitFilesystem (void)
VFS_CLOSE(f);
break;
}
if (autobasedir)
}
}
//try looking where the exe is
if (j == 4 && host_parms.binarydir && *host_parms.binarydir)
{
#ifdef _WIN32
if (Sys_FindGameData(gamemode_info[i].poshname, gamemode_info[i].exename, com_quakedir, sizeof(com_quakedir)))
for (j = 0; j < 4; j++)
{
if (gamemode_info[gamenum].auniquefile[j])
{
f = VFSOS_Open(va("%s%s", host_parms.binarydir, gamemode_info[i].auniquefile[j]), "rb");
if (f)
{
Q_strncpyz(com_quakedir, host_parms.binarydir, sizeof(com_quakedir));
//we found it, its all okay
VFS_CLOSE(f);
break;
}
}
}
}
//scan known locations/windows registry/etc to see if we can find an existing install
if (j == 4)
{
char realpath[MAX_OSPATH-1];
if (Sys_FindGameData(gamemode_info[i].poshname, gamemode_info[i].exename, realpath, sizeof(realpath)))
{
Q_strncpyz(com_quakedir, realpath, sizeof(com_quakedir));
if (com_quakedir[strlen(com_quakedir)-1] == '\\')
com_quakedir[strlen(com_quakedir)-1] = '/';
else if (com_quakedir[strlen(com_quakedir)-1] != '/')
@ -2736,13 +2757,10 @@ void COM_InitFilesystem (void)
}
}
else
#endif
{
Con_Printf("Couldn't find the gamedata for this game mode!\n");
}
}
break;
}
}
break;
}
@ -2760,8 +2778,10 @@ void COM_InitFilesystem (void)
if (autobasedir)
{
if (Sys_FindGameData(gamemode_info[i].poshname, gamemode_info[i].exename, com_quakedir, sizeof(com_quakedir)))
char realpath[MAX_OSPATH-1];
if (Sys_FindGameData(gamemode_info[i].poshname, gamemode_info[i].exename, realpath, sizeof(realpath)))
{
Q_strncpyz(com_quakedir, realpath, sizeof(com_quakedir));
if (com_quakedir[strlen(com_quakedir)-1] == '\\')
com_quakedir[strlen(com_quakedir)-1] = '/';
else if (com_quakedir[strlen(com_quakedir)-1] != '/')

View file

@ -121,7 +121,7 @@ vfsfile_t *FSSTDIO_OpenTemp(void)
vfsfile_t *Sys_OpenAsset(const char *fname);
#endif
static vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsflush)
vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsflush)
{
FILE *f;
vfsstdiofile_t *file;

View file

@ -524,6 +524,8 @@ int VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
VFS_SEEK(vfsz->parent->raw, vfsz->pos+vfsz->startpos);
vfsz->parent->currentfile = file;
}
if (vfsz->pos + bytestoread > vfsz->length)
bytestoread = max(0, vfsz->length - vfsz->pos);
read = VFS_READ(vfsz->parent->raw, buffer, bytestoread);
}

View file

@ -1969,7 +1969,8 @@ qboolean CModQ3_LoadSubmodels (lump_t *l)
bleaf->contents = 0;
leafbrush = &map_leafbrushes[numleafbrushes];
for ( j = 0; j < bleaf->numleafbrushes; j++, leafbrush++ ) {
for ( j = 0; j < bleaf->numleafbrushes; j++, leafbrush++ )
{
*leafbrush = LittleLong ( in->firstbrush ) + j;
bleaf->contents |= map_brushes[*leafbrush].contents;
}

View file

@ -1685,8 +1685,10 @@ void Matrix4x4_CM_UnProject(const vec3_t in, vec3_t out, const vec3_t viewangles
//returns fractions of screen.
//uses GL style rotations and translations and stuff.
//3d -> screen (fixme: offscreen return values needed)
void Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy)
//returns false if the 2d point is offscreen.
qboolean Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy)
{
qboolean result = true;
float modelview[16];
float proj[16];
@ -1705,12 +1707,17 @@ void Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles,
v[0] /= v[3];
v[1] /= v[3];
if (v[2] < 0)
result = false; //too close to the view
v[2] /= v[3];
out[0] = (1+v[0])/2;
out[1] = (1+v[1])/2;
out[2] = (1+v[2])/2;
if (out[2] > 1)
result = false; //beyond far clip plane
}
return result;
}

View file

@ -155,7 +155,7 @@ void Matrix4x4_CM_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, c
void Matrix4_CreateFromQuakeEntity (float *matrix, float x, float y, float z, float pitch, float yaw, float roll, float scale);
void Matrix4_Multiply (const float *a, const float *b, float *out);
void Matrix3x4_Multiply(const float *a, const float *b, float *out);
void Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy);
qboolean Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy);
void Matrix4x4_CM_Transform3 (const float *matrix, const float *vector, float *product);
void Matrix4x4_CM_Transform4 (const float *matrix, const float *vector, float *product);
void Matrix4x4_CM_Transform34(const float *matrix, const vec3_t vector, vec4_t product);

View file

@ -96,7 +96,7 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b);
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b);
char *NET_AdrToString (char *s, int len, netadr_t a);
char *NET_BaseAdrToString (char *s, int len, netadr_t a);
qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr);
qboolean NET_StringToSockaddr (const char *s, int defaultport, struct sockaddr_qstorage *sadr, int *addrfamily, int *addrsize);
qboolean NET_StringToAdr (const char *s, netadr_t *a);
qboolean NET_IsClientLegal(netadr_t *adr);

View file

@ -88,7 +88,7 @@ cvar_t net_mtu = CVARD("net_mtu", "1450", "Specifies a maximum udp payload size,
cvar_t pext_replacementdeltas = CVAR("debug_pext_replacementdeltas", "0"); /*rename once the extension is finalized*/
/*returns the bitmask of supported+enabled extensions*/
/*returns the entire bitmask of supported+enabled extensions*/
unsigned int Net_PextMask(int maskset)
{
unsigned int mask = 0;

View file

@ -662,13 +662,7 @@ idnewt:28000
any form of ipv6, including port number.
=============
*/
#define DO(src,dest) \
copy[0] = s[src]; \
copy[1] = s[src + 1]; \
sscanf (copy, "%x", &val); \
((struct sockaddr_ipx *)sadr)->dest = val
qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr)
qboolean NET_StringToSockaddr (const char *s, int defaultport, struct sockaddr_qstorage *sadr, int *addrfamily, int *addrsize)
{
struct hostent *h;
char *colon;
@ -685,6 +679,13 @@ qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr)
unsigned int val;
((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX;
#define DO(src,dest) \
copy[0] = s[src]; \
copy[1] = s[src + 1]; \
sscanf (copy, "%x", &val); \
((struct sockaddr_ipx *)sadr)->dest = val
copy[2] = 0;
DO(0, sa_netnum[0]);
DO(2, sa_netnum[1]);
@ -697,7 +698,14 @@ qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr)
DO(17, sa_nodenum[4]);
DO(19, sa_nodenum[5]);
sscanf (&s[22], "%u", &val);
#undef DO
((struct sockaddr_ipx *)sadr)->sa_socket = htons((unsigned short)val);
if (addrfamily)
*addrfamily = AF_IPX;
if (addrsize)
*addrsize = sizeof(struct sockaddr_ipx);
}
else
#endif
@ -719,7 +727,7 @@ qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr)
if (*s == '[')
{
port = strstr(s, "]:");
port = strstr(s, "]");
if (!port)
error = EAI_NONAME;
else
@ -729,7 +737,7 @@ qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr)
len = sizeof(dupbase)-1;
strncpy(dupbase, s+1, len);
dupbase[len] = '\0';
error = pgetaddrinfo(dupbase, port+2, &udp6hint, &addrinfo);
error = pgetaddrinfo(dupbase, (port[1] == ':')?port+2:NULL, &udp6hint, &addrinfo);
}
}
else
@ -779,6 +787,24 @@ dblbreak:
pfreeaddrinfo (addrinfo);
if (!((struct sockaddr*)sadr)->sa_family) //none suitablefound
return false;
if (addrfamily)
*addrfamily = ((struct sockaddr*)sadr)->sa_family;
if (((struct sockaddr*)sadr)->sa_family == AF_INET)
{
if (!((struct sockaddr_in *)sadr)->sin_port)
((struct sockaddr_in *)sadr)->sin_port = htons(defaultport);
if (addrsize)
*addrsize = sizeof(struct sockaddr_in);
}
else
{
if (!((struct sockaddr_in6 *)sadr)->sin6_port)
((struct sockaddr_in6 *)sadr)->sin6_port = htons(defaultport);
if (addrsize)
*addrsize = sizeof(struct sockaddr_in6);
}
}
else
#endif
@ -791,6 +817,8 @@ dblbreak:
if (strlen(s) >= sizeof(copy)-1)
return false;
((struct sockaddr_in *)sadr)->sin_port = htons(defaultport);
strcpy (copy, s);
// strip off a trailing :port if present
for (colon = copy ; *colon ; colon++)
@ -812,6 +840,10 @@ dblbreak:
return false;
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
}
if (addrfamily)
*addrfamily = AF_INET;
if (addrsize)
*addrsize = sizeof(struct sockaddr_in);
#else
return false;
#endif
@ -820,8 +852,6 @@ dblbreak:
return true;
}
#undef DO
/*
accepts anything that NET_StringToSockaddr accepts plus certain url schemes
including: tcp, irc
@ -868,7 +898,7 @@ qboolean NET_StringToAdr (const char *s, netadr_t *a)
{
//make sure that the rest of the address is a valid ip address (4 or 6)
if (!NET_StringToSockaddr (s+6, &sadr))
if (!NET_StringToSockaddr (s+6, 0, &sadr, NULL, NULL))
{
a->type = NA_INVALID;
return false;
@ -914,7 +944,7 @@ qboolean NET_StringToAdr (const char *s, netadr_t *a)
}
#endif
if (!NET_StringToSockaddr (s, &sadr))
if (!NET_StringToSockaddr (s, 0, &sadr, NULL, NULL))
{
a->type = NA_INVALID;
return false;
@ -4269,7 +4299,7 @@ void NET_GetLocalAddress (int socket, netadr_t *out)
if (getsockname (socket, (struct sockaddr *)&address, &namelen) == -1)
{
notvalid = true;
NET_StringToSockaddr("0.0.0.0", (struct sockaddr_qstorage *)&address);
NET_StringToSockaddr("0.0.0.0", 0, (struct sockaddr_qstorage *)&address, NULL, NULL);
// Sys_Error ("NET_Init: getsockname:", strerror(qerrno));
}

View file

@ -477,6 +477,11 @@ 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++;
}
else if (!strcmp(name, "Media_VideoEncoder"))
{
Media_RegisterEncoder(currentplug, func);
// currentplug->blockcloses++;
}
#endif
@ -1812,6 +1817,7 @@ void Plug_Close(plugin_t *plug)
Con_Printf("Closing plugin %s\n", plug->name);
#if defined(PLUGINS) && !defined(NOMEDIA) && !defined(SERVERONLY)
Media_UnregisterDecoder(plug, NULL);
Media_UnregisterEncoder(plug, NULL);
#endif
if (plug->shutdown)
VM_Call(plug->vm, plug->shutdown);
@ -1900,6 +1906,10 @@ void Plug_Shutdown(void)
BZ_Free(plugbuiltins);
plugbuiltins = NULL;
plugincvararraylen = 0;
BZ_Free(plugincvararray);
plugincvararray = NULL;
plugincommandarraylen = 0;
BZ_Free(plugincommandarray);
plugincommandarray = NULL;

View file

@ -6,16 +6,13 @@
#include <ctype.h>
//fixme
#define Z_QC_TAG 2
#define PRSTR 0xa6ffb3d7
static char *cvargroup_progs = "Progs variables";
cvar_t pr_brokenfloatconvert = SCVAR("pr_brokenfloatconvert", "0");
cvar_t pr_tempstringcount = SCVAR("pr_tempstringcount", "");//"16");
cvar_t pr_tempstringsize = SCVAR("pr_tempstringsize", "4096");
cvar_t dpcompat_stats = CVAR("dpcompat_stats", "0");
cvar_t pr_enable_uriget = SCVAR("pr_enable_uriget", "1");
int tokenizeqc(char *str, qboolean dpfuckage);
static char *strtoupper(char *s)
{
@ -50,7 +47,7 @@ void PF_Common_RegisterCvars(void)
Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs);
Cvar_Register (&pr_tempstringcount, cvargroup_progs);
Cvar_Register (&pr_tempstringsize, cvargroup_progs);
Cvar_Register (&dpcompat_stats, cvargroup_progs);
Cvar_Register (&pr_enable_uriget, cvargroup_progs);
WPhys_Init();
}
@ -823,9 +820,8 @@ void QCBUILTIN PF_cvar_type (progfuncs_t *prinst, struct globalvars_s *pr_global
ret |= 4; // CVAR_TYPE_PRIVATE
if(!(v->flags & CVAR_USERCREATED))
ret |= 8; // CVAR_TYPE_ENGINE
//fte cvars don't support this
// ret |= 16; // CVAR_TYPE_HASDESCRIPTION
if (v->description)
ret |= 16; // CVAR_TYPE_HASDESCRIPTION
}
G_FLOAT(OFS_RETURN) = ret;
}
@ -1204,19 +1200,19 @@ static void PF_fwrite (progfuncs_t *prinst, int fnum, char *msg, int len)
{
if (fnum < 0 || fnum >= MAX_QC_FILES)
{
Con_Printf("PF_fgets: File out of range\n");
Con_Printf("PF_fwrite: File out of range\n");
return; //out of range
}
if (!pf_fopen_files[fnum].data)
{
Con_Printf("PF_fgets: File is not open\n");
Con_Printf("PF_fwrite: File is not open\n");
return; //not open
}
if (pf_fopen_files[fnum].prinst != prinst)
{
Con_Printf("PF_fgets: File is from wrong instance\n");
Con_Printf("PF_fwrite: File is from wrong instance\n");
return; //this just isn't ours.
}
@ -1263,6 +1259,7 @@ void PF_fcloseall (progfuncs_t *prinst)
Con_Printf("qc file %s was still open\n", pf_fopen_files[i].name);
PF_fclose_i(i);
}
tokenizeqc("", false);
}
@ -2151,7 +2148,7 @@ void QCBUILTIN PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_global
slen = strlen(s);
if (start < 0)
start = slen-start;
start = slen+start;
if (length < 0)
length = slen-start+(length+1);
if (start < 0)
@ -2279,7 +2276,15 @@ void QCBUILTIN PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals)
void QCBUILTIN PF_strlennocol (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *in = PR_GetStringOfs(prinst, OFS_PARM0);
G_FLOAT(OFS_RETURN) = COM_FunStringLength(in);
char result[8192];
unsigned int flagged[8192];
unsigned int len = 0;
COM_ParseFunString(CON_WHITEMASK, in, flagged, sizeof(flagged), false);
COM_DeFunString(flagged, NULL, result, sizeof(result), true);
for (len = 0; result[len]; len++)
;
G_FLOAT(OFS_RETURN) = len;
}
//DP_QC_STRINGCOLORFUNCTIONS
@ -2351,7 +2356,7 @@ struct strbuf {
int allocated;
};
#define NUMSTRINGBUFS 16
#define NUMSTRINGBUFS 64
struct strbuf strbuflist[NUMSTRINGBUFS];
void PF_buf_shutdown(progfuncs_t *prinst)
@ -2531,30 +2536,67 @@ void QCBUILTIN PF_bufstr_set (progfuncs_t *prinst, struct globalvars_s *pr_glob
void QCBUILTIN PF_bufstr_add (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int bufno = G_FLOAT(OFS_PARM0)-1;
//char *string = PR_GetStringOfs(prinst, OFS_PARM1);
//int order = G_FLOAT(OFS_PARM2);
char *string = PR_GetStringOfs(prinst, OFS_PARM1);
int order = G_FLOAT(OFS_PARM2);
int index;
if ((unsigned int)bufno >= NUMSTRINGBUFS)
return;
if (strbuflist[bufno].prinst != prinst)
return;
Con_Printf("PF_bufstr_add: stub\n");
if (order)
{
//add on end
index = strbuflist[bufno].used;
}
else
{
//find a hole
for (index = 0; index < strbuflist[bufno].used; index++)
if (!strbuflist[bufno].strings[index])
break;
}
G_FLOAT(OFS_RETURN) = 0;
//expand it if needed
if (index >= strbuflist[bufno].allocated)
{
int oldcount;
oldcount = strbuflist[bufno].allocated;
strbuflist[bufno].allocated = (index + 256);
strbuflist[bufno].strings = BZ_Realloc(strbuflist[bufno].strings, strbuflist[bufno].allocated*sizeof(char*));
memset(strbuflist[bufno].strings+oldcount, 0, (strbuflist[bufno].allocated - oldcount) * sizeof(char*));
}
//add in the new string.
if (strbuflist[bufno].strings[index])
Z_Free(strbuflist[bufno].strings[index]);
strbuflist[bufno].strings[index] = Z_Malloc(strlen(string)+1);
strcpy(strbuflist[bufno].strings[index], string);
if (index >= strbuflist[bufno].used)
strbuflist[bufno].used = index+1;
G_FLOAT(OFS_RETURN) = index;
}
// #449 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
void QCBUILTIN PF_bufstr_free (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int bufno = G_FLOAT(OFS_PARM0)-1;
//int index = G_FLOAT(OFS_PARM1);
int index = G_FLOAT(OFS_PARM1);
if ((unsigned int)bufno >= NUMSTRINGBUFS)
return;
if (strbuflist[bufno].prinst != prinst)
return;
Con_Printf("PF_bufstr_free: stub\n");
if (index >= strbuflist[bufno].used)
return; //not valid anyway.
if (strbuflist[bufno].strings[index])
Z_Free(strbuflist[bufno].strings[index]);
strbuflist[bufno].strings[index] = NULL;
}
void QCBUILTIN PF_buf_cvarlist (progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -2659,13 +2701,73 @@ void QCBUILTIN PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_gl
RETURN_TSTRING(resultbuf);
}
#ifdef WEBCLIENT
static void PR_uri_get_callback(struct dl_download *dl)
{
extern progfuncs_t *menuprogs;
world_t *w = dl->user_ctx;
progfuncs_t *prinst = w?w->progs:menuprogs;
float id = dl->user_num;
func_t func;
if (!prinst)
return;
func = PR_FindFunction(prinst, "URI_Get_Callback", PR_ANY);
if (func)
{
int len;
char *buffer;
struct globalvars_s *pr_globals = PR_globals(prinst, PR_CURRENT);
G_FLOAT(OFS_PARM0) = id;
G_FLOAT(OFS_PARM1) = (dl->replycode!=200)?dl->replycode:0; //for compat with DP, we change any 200s to 0.
G_INT(OFS_PARM2) = 0;
if (dl->file)
{
len = VFS_GETLEN(dl->file);
buffer = malloc(len+1);
buffer[len] = 0;
VFS_READ(dl->file, buffer, len);
G_INT(OFS_PARM2) = PR_TempString(prinst, buffer);
free(buffer);
}
PR_ExecuteProgram(prinst, func);
}
}
#endif
// uri_get() gets content from an URL and calls a callback "uri_get_callback" with it set as string; an unique ID of the transfer is returned
// returns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string
//float(string uril, float id) uri_get = #513;
void QCBUILTIN PF_uri_get (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
Con_Printf("PF_uri_get: stub\n");
#ifdef WEBCLIENT
world_t *w = prinst->parms->user;
unsigned char *url = PR_GetStringOfs(prinst, OFS_PARM0);
float id = G_FLOAT(OFS_PARM1);
struct dl_download *dl;
if (!pr_enable_uriget.ival)
{
Con_Printf("PF_uri_get(\"%s\",%g): %s disabled\n", url, id, pr_enable_uriget.name);
G_FLOAT(OFS_RETURN) = 0;
return;
}
Con_DPrintf("PF_uri_get(%s,%g)\n", url, id);
dl = HTTP_CL_Get(url, NULL, PR_uri_get_callback);
if (dl)
{
dl->user_ctx = w;
dl->user_num = id;
G_FLOAT(OFS_RETURN) = 1;
}
else
#endif
G_FLOAT(OFS_RETURN) = 0;
}
@ -3170,6 +3272,17 @@ void QCBUILTIN PF_externvalue (progfuncs_t *prinst, struct globalvars_s *pr_glob
char *varname = PF_VarString(prinst, 1, pr_globals);
eval_t *var;
if (*varname == '&')
{
//return its address instead of its value, for pointer use.
var = prinst->FindGlobal(prinst, varname+1, n, NULL);
if (var)
G_INT(OFS_RETURN) = (char*)var - prinst->stringtable;
else
G_INT(OFS_RETURN) = 0;
}
else
{
var = prinst->FindGlobal(prinst, varname, n, NULL);
if (var)
@ -3184,6 +3297,7 @@ void QCBUILTIN PF_externvalue (progfuncs_t *prinst, struct globalvars_s *pr_glob
G_INT(OFS_RETURN) = n;
}
}
}
void QCBUILTIN PF_externcall (progfuncs_t *prinst, struct globalvars_s *pr_globals) //this func calls a function in annother progs (by name)
{
@ -3657,7 +3771,8 @@ nolength:
default:
verbatim:
if(o < end - 1)
*o++ = *s++;
*o++ = *s;
s++;
break;
}
}
@ -3667,6 +3782,77 @@ finished:
RETURN_TSTRING(outbuf);
}
fdef_t *ED_FieldInfo (progfuncs_t *progfuncs, unsigned int *count);
char *PR_UglyValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val);
pbool ED_ParseEval (progfuncs_t *progfuncs, eval_t *eval, int type, char *s);
//float()
void QCBUILTIN PF_numentityfields (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned int count = 0;
ED_FieldInfo(prinst, &count);
G_FLOAT(OFS_RETURN) = count;
}
//string(float fieldnum)
void QCBUILTIN PF_entityfieldname (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned int fidx = G_FLOAT(OFS_PARM0);
unsigned int count = 0;
fdef_t *fdef;
fdef = ED_FieldInfo(prinst, &count);
if (fidx < count)
{
RETURN_TSTRING(fdef[fidx].name);
}
else
G_INT(OFS_RETURN) = 0;
}
//float(float fieldnum)
void QCBUILTIN PF_entityfieldtype (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned int fidx = G_FLOAT(OFS_PARM0);
unsigned int count = 0;
fdef_t *fdef = ED_FieldInfo(prinst, &count);
if (fidx < count)
{
G_FLOAT(OFS_RETURN) = fdef[fidx].type;
}
else
G_FLOAT(OFS_RETURN) = 0;
}
//string(float fieldnum, entity ent)
void QCBUILTIN PF_getentityfieldstring (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned int fidx = G_FLOAT(OFS_PARM0);
wedict_t *ent = (wedict_t *)G_EDICT(prinst, OFS_PARM1);
eval_t *eval;
unsigned int count = 0;
fdef_t *fdef = ED_FieldInfo(prinst, &count);
if (fidx < count)
{
eval = (eval_t *)&((float *)ent->v)[fdef[fidx].ofs];
RETURN_TSTRING(PR_UglyValueString(prinst, fdef[fidx].type, eval));
}
else
G_INT(OFS_RETURN) = 0;
}
//float(float fieldnum, entity ent, string s)
void QCBUILTIN PF_putentityfieldstring (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned int fidx = G_FLOAT(OFS_PARM0);
wedict_t *ent = (wedict_t *)G_EDICT(prinst, OFS_PARM1);
char *str = PR_GetStringOfs(prinst, OFS_PARM2);
eval_t *eval;
unsigned int count = 0;
fdef_t *fdef = ED_FieldInfo(prinst, &count);
if (fidx < count)
{
eval = (eval_t *)&((float *)ent->v)[fdef[fidx].ofs];
G_FLOAT(OFS_RETURN) = ED_ParseEval(prinst, eval, fdef[fidx].type, str);
}
else
G_FLOAT(OFS_RETURN) = 0;
}
#define DEF_SAVEGLOBAL (1u<<15)
static void PR_AutoCvarApply(progfuncs_t *prinst, eval_t *val, etype_t type, cvar_t *var)
{
@ -3690,11 +3876,11 @@ static void PR_AutoCvarApply(progfuncs_t *prinst, eval_t *val, etype_t type, cva
char res[128];
char *vs = var->string;
vs = COM_ParseOut(vs, res, sizeof(res));
val->_vector[0] = atof(com_token);
val->_vector[0] = atof(res);
vs = COM_ParseOut(vs, res, sizeof(res));
val->_vector[1] = atof(com_token);
val->_vector[1] = atof(res);
vs = COM_ParseOut(vs, res, sizeof(res));
val->_vector[2] = atof(com_token);
val->_vector[2] = atof(res);
}
break;
}
@ -3726,11 +3912,17 @@ void PR_FoundPrefixedGlobals(progfuncs_t *progfuncs, char *name, eval_t *val, et
{
cvar_t *var;
char *vals;
int nlen;
name += 9; //autocvar_
switch(type & ~DEF_SAVEGLOBAL)
{
case ev_float:
//ignore individual vector componants. let the vector itself do all the work.
nlen = strlen(name);
if(nlen >= 2 && name[nlen-2] == '_' && (name[nlen-1] == 'x' || name[nlen-1] == 'y' || name[nlen-1] == 'z'))
return;
vals = va("%f", val->_float);
break;
case ev_integer:
@ -3786,7 +3978,7 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_PEXT_Q3BSP"}, //quake3 bsp support. dp probably has an equivelent, but this is queryable per client.
{"DP_ENT_COLORMOD"},
{NULL}, //splitscreen - not queryable.
{"FTE_HEXEN2"}, //client can use hexen2 maps. server can use hexen2 progs
{"FTE_HEXEN2", 3, NULL, {"particle2", "particle3", "particle4"}}, //client can use hexen2 maps. server can use hexen2 progs
{"FTE_PEXT_SPAWNSTATIC"}, //means that static entities can have alpha/scale and anything else the engine supports on normal ents. (Added for >256 models, while still being compatible - previous system failed with -1 skins)
{"FTE_PEXT_CUSTOMTENTS", 2, NULL, {"RegisterTempEnt", "CustomTempEnt"}},
{"FTE_PEXT_256PACKETENTITIES"}, //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity).
@ -3835,6 +4027,7 @@ lh_extension_t QSG_Extensions[] = {
//to an extend {"DP_HALFLIFE_SPRITE"},
{"DP_INPUTBUTTONS"},
{"DP_LITSUPPORT"},
{"DP_MD3_TAGSINFO", 2, NULL, {"gettagindex", "gettaginfo"}},
{"DP_MONSTERWALK"},
{"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support.
{"DP_MOVETYPEFOLLOW"},
@ -3854,6 +4047,7 @@ lh_extension_t QSG_Extensions[] = {
{"DP_QC_FINDCHAINFLAGS", 1, NULL, {"findchainflags"}},
{"DP_QC_FINDFLOAT", 1, NULL, {"findfloat"}},
{"DP_QC_FS_SEARCH", 4, NULL, {"search_begin", "search_end", "search_getsize", "search_getfilename"}},
{"DP_QC_GETSURFACE", 6, NULL, {"getsurfacenumpoints", "getsurfacepoint", "getsurfacenormal", "getsurfacetexture", "getsurfacenearpoint", "getsurfaceclippedpoint"}},
{"DP_QC_GETSURFACEPOINTATTRIBUTE", 1, NULL, {"getsurfacepointattribute"}},
{"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}},
{"DP_QC_MULTIPLETEMPSTRINGS"},
@ -3901,14 +4095,14 @@ lh_extension_t QSG_Extensions[] = {
{"DP_SV_WRITEUNTERMINATEDSTRING", 1, NULL, {"WriteUnterminatedString"}},
{"DP_TE_BLOOD", 1, NULL, {"te_blood"}},
{"DP_TE_BLOODSHOWER", 1, NULL, {"te_bloodshower"}},
{"DP_TE_CUSTOMFLASH", 1, NULL, {"te_customflash"}},
{"DP_TE_EXPLOSIONRGB"},
{"DP_TE_FLAMEJET", 1, NULL, {"te_flamejet"}},
{"_DP_TE_CUSTOMFLASH", 1, NULL, {"te_customflash"}},
{"DP_TE_EXPLOSIONRGB", 1, NULL, {"te_explosionrgb"}},
{"_DP_TE_FLAMEJET", 1, NULL, {"te_flamejet"}},
{"DP_TE_PARTICLECUBE", 1, NULL, {"te_particlecube"}},
//particlerain
//particlesnow
{"DP_TE_PLASMABURN", 1, NULL, {"te_plasmaburn"}},
{"DP_TE_QUADEFFECTS1"},
{"_DP_TE_PARTICLERAIN", 1, NULL, {"te_particlerain"}},
{"_DP_TE_PARTICLESNOW", 1, NULL, {"te_particlesnow"}},
{"_DP_TE_PLASMABURN", 1, NULL, {"te_plasmaburn"}},
{"_DP_TE_QUADEFFECTS1", 4, NULL, {"te_gunshotquad", "te_spikequad", "te_superspikequad", "te_explosionquad"}},
{"DP_TE_SMALLFLASH", 1, NULL, {"te_smallflash"}},
{"DP_TE_SPARK", 1, NULL, {"te_spark"}},
{"DP_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash", "te_teleport", "te_explosion2", "te_lightning1", "te_lightning2", "te_lightning3", "te_beam"}},
@ -3933,7 +4127,7 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files.
{"FTE_MEDIA_ROQ"}, //playfilm command supports q3 roq files
#endif
{"FTE_MULTIPROGS"}, //multiprogs functions are available.
{"FTE_MULTIPROGS", 5, NULL, {"externcall", "addprogs", "externvalue", "externset", "instr"}}, //multiprogs functions are available.
{"FTE_MULTITHREADED", 3, NULL, {"sleep", "fork", "abort"}},
#ifdef SERVER_DEMO_PLAYBACK
{"FTE_MVD_PLAYBACK"},
@ -3944,19 +4138,19 @@ lh_extension_t QSG_Extensions[] = {
{"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}},
{"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}},
{"FTE_QC_PAUSED"},
{"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}},
{"FTE_QC_INTCONV", 4, NULL, {"stoi", "itos", "stoh", "htos"}},
{"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}}, //includes the SV_ParseConnectionlessPacket event.
{"FTE_QC_TRACETRIGGER"},
{"FTE_SOLID_LADDER"}, //Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS
#ifdef SQL
// serverside SQL functions for managing an SQL database connection
{"FTE_SQL", 9, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion",
"sqlreadfloat"}},
#endif
//eperimental advanced strings functions.
//reuses the FRIK_FILE builtins (with substring extension)
{"FTE_STRINGS", 16, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone",
"strstrofs", "str2chr", "chr2str", "strconv", "infoadd", "infoget", "strncmp", "strcasecmp", "strncasecmp"}},
{"FTE_STRINGS", 17, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone",
"strstrofs", "str2chr", "chr2str", "strconv", "infoadd", "infoget", "strncmp", "strcasecmp", "strncasecmp", "strpad"}},
{"FTE_SV_REENTER"},
{"FTE_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash",
"te_teleport", "te_lightning1", "te_lightning2", "te_lightning3", "te_lightningblood", "te_bloodqw"}},

View file

@ -53,11 +53,6 @@ struct wedict_s
#define PF_pointsound PF_Fixme
#define PF_gecko_mousemove PF_Fixme
#define PF_numentityfields PF_Fixme
#define PF_entityfieldname PF_Fixme
#define PF_entityfieldtype PF_Fixme
#define PF_getentityfieldstring PF_Fixme
#define PF_putentityfieldstring PF_Fixme
#define PF_WritePicture PF_Fixme
#define PF_ReadPicture PF_Fixme
@ -179,6 +174,11 @@ void PR_fclose_progs (progfuncs_t *prinst);
char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals);
void PR_AutoCvarSetup(progfuncs_t *prinst);
void PR_AutoCvar(progfuncs_t *prinst, cvar_t *var);
void QCBUILTIN PF_numentityfields (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_entityfieldname (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_entityfieldtype (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_getentityfieldstring (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_putentityfieldstring (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_getsurfacenumpoints(progfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -315,7 +315,7 @@ void QCBUILTIN PF_calltimeofday (progfuncs_t *prinst, struct globalvars_s *pr_gl
void QCBUILTIN PF_whichpack (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_fclose_progs (progfuncs_t *prinst);
int QCEditor (progfuncs_t *prinst, char *filename, int line, int nump, char **parms);
int QCEditor (progfuncs_t *prinst, char *filename, int line, int statement, int nump, char **parms);
@ -489,6 +489,34 @@ enum csqc_input_event
CSIE_ACCELEROMETER = 4 /*x, y, z*/
};
enum terrainedit_e
{
ter_reload, //
ter_save, //
ter_sethole, //vector pos, float radius, floatbool hole
ter_height_set, //vector pos, float radius, float newheight
ter_height_smooth, //vector pos, float radius, float percent
ter_height_spread, //vector pos, float radius, float percent
ter_raise, //vector pos, float radius, float heightchange
ter_lower, //vector pos, float radius, float heightchange
ter_tex_kill, //vector pos, void junk, void junk, string texname
ter_tex_get, //vector pos, void junk, float imagenum
ter_mix_paint, //vector pos, float radius, float percent, string texname
ter_mix_concentrate, //vector pos, float radius, float percent
ter_mix_noise, //vector pos, float radius, float percent
ter_mix_blur, //vector pos, float radius, float percent
ter_water_set, //vector pos, float radius, float newwaterheight
ter_mesh_add, //entity ent
ter_mesh_kill, //vector pos, float radius
ter_tint, //vector pos, float radius, float percent, vector newcol, float newalph
ter_height_flatten, //vector pos, float radius, float percent
// ter_poly_add, //add a poly, woo
// ter_poly_remove, //remove polys
// ter_autopaint_h, //vector pos, float radius, float percent, string tex1, string tex2 (paint tex1/tex2
// ter_autopaint_n //vector pos, float radius, float percent, string tex1, string tex2
};
enum
{
GE_MAXENTS = -1,

View file

@ -52,10 +52,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT_SPAWNSTATIC2 0x00400000 //Sends an entity delta instead of a baseline.
#define PEXT_CUSTOMTEMPEFFECTS 0x00800000 //supports custom temp ents.
#define PEXT_256PACKETENTITIES 0x01000000 //Client can recieve 256 packet entities.
//#define PEXT_NEVERUSED 0x02000000
//#define PEXT_NEVERUSED 0x02000000 //reserved for a future multicastmask
#define PEXT_SHOWPIC 0x04000000
#define PEXT_SETATTACHMENT 0x08000000 //md3 tags (needs networking, they need to lerp).
//#define PEXT_NEVERUSED 0x10000000
//#define PEXT_NEVERUSED 0x10000000 //reserved for a future multicastmask
#define PEXT_CHUNKEDDOWNLOADS 0x20000000 //alternate file download method. Hopefully it'll give quadroupled download speed, especially on higher pings.
#ifdef CSQC_DAT
@ -773,8 +773,9 @@ enum {
==========================================================
*/
#define MAX_CLIENTS 32 /*max 255, min 32*/
#define QWMAX_CLIENTS 32 /*QW's standard max*/
#define MAX_CLIENTS 32//255 /*max 255, min 32*/
#define QWMAX_CLIENTS 32 /*QW's standard max. clients might have issues above this value*/
#define NQMAX_CLIENTS 16 /*NQ's standard max. clients might have issues above this value*/
#define UPDATE_BACKUP 64 // copies of entity_state_t to keep buffered
// must be power of two

View file

@ -33,10 +33,6 @@ Also, can efficiency be improved much?
*/
#ifdef __MORPHOS__
#include <proto/dynload.h>
#endif
#include "quakedef.h"
#ifdef VM_ANY
@ -70,10 +66,6 @@ struct vm_s {
qintptr_t (EXPORT_FN *vmMain)(qintptr_t command, qintptr_t arg0, qintptr_t arg1, qintptr_t arg2, qintptr_t arg3, qintptr_t arg4, qintptr_t arg5, qintptr_t arg6);
};
#if defined(__MORPHOS__) && I_AM_BIGFOOT
#include <proto/dynload.h>
#endif
dllhandle_t *QVM_LoadDLL(const char *name, void **vmMain, sys_calldll_t syscall)
{
void (EXPORT_FN *dllEntry)(sys_calldll_t syscall);
@ -88,11 +80,6 @@ dllhandle_t *QVM_LoadDLL(const char *name, void **vmMain, sys_calldll_t syscall)
{NULL, NULL},
};
#ifdef __MORPHOS__
if (DynLoadBase == 0)
return 0;
#endif
#ifdef _WIN32
snprintf(dllname_arch, sizeof(dllname_arch), "%sx86.dll", name);
snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s.dll", name);

View file

@ -92,6 +92,7 @@ qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refres
#ifdef MULTITHREAD
void *Sys_CreateThread(int (*func)(void *), void *args, int priority, int stacksize);
void Sys_WaitOnThread(void *thread);
void Sys_DetachThread(void *thread);
#define THREADP_IDLE -5
#define THREADP_NORMAL 0

View file

@ -207,6 +207,12 @@ void World_ODE_Init(void);
void World_ODE_Start(world_t *world);
void World_ODE_End(world_t *world);
void World_ODE_Shutdown(void);
qboolean World_ODE_RagCreateBody(world_t *world, odebody_t *bodyptr, float *mat, wedict_t *ed);
void World_ODE_RagDestroyBody(world_t *world, odebody_t *bodyptr);
void World_ODE_RagMatrixFromBody(world_t *world, odebody_t *bodyptr, float *mat);
void World_ODE_RagCreateJoint(world_t *world, odejoint_t *joint, odejointinfo_t *info, odebody_t *body1, odebody_t *body2, vec3_t aaa2[3]);
void World_ODE_RagDestroyJoint(world_t *world, odejoint_t *joint);
#endif
void World_ClearWorld (world_t *w);

View file

@ -13,7 +13,7 @@ extern ID3D11DeviceContext *d3ddevctx;
//#define d3dcheck(foo) foo
#define d3dcheck(foo) do{HRESULT err = foo; if (FAILED(err)) Sys_Error("D3D reported error on backend line %i - error 0x%x\n", __LINE__, (unsigned int)err);} while(0)
#define MAX_TMUS 8
#define MAX_TMUS 16
extern float d3d_trueprojection[16];
@ -1542,9 +1542,9 @@ static void BE_SubmitMeshChain(int idxfirst)
static void BE_ApplyUniforms(program_t *prog, int permu)
{
//FIXME: how many of these calls can we avoid?
ID3D11DeviceContext_IASetInputLayout(d3ddevctx, prog->handle[permu].hlsl.layout);
ID3D11DeviceContext_VSSetShader(d3ddevctx, prog->handle[permu].hlsl.vert, NULL, 0);
ID3D11DeviceContext_PSSetShader(d3ddevctx, prog->handle[permu].hlsl.frag, NULL, 0);
ID3D11DeviceContext_IASetInputLayout(d3ddevctx, prog->permu[permu].handle.hlsl.layout);
ID3D11DeviceContext_VSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.vert, NULL, 0);
ID3D11DeviceContext_PSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.frag, NULL, 0);
ID3D11DeviceContext_IASetPrimitiveTopology(d3ddevctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11DeviceContext_VSSetConstantBuffers(d3ddevctx, 0, sizeof(shaderstate.cbuffers)/sizeof(shaderstate.cbuffers[0]), shaderstate.cbuffers);
@ -1558,15 +1558,15 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i
program_t *p = s->prog;
if (TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_BUMPMAP].hlsl.vert)
if (TEXVALID(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.hlsl.vert)
perm |= PERMUTATION_BUMPMAP;
if (TEXVALID(shaderstate.curtexnums->specular) && p->handle[perm|PERMUTATION_SPECULAR].hlsl.vert)
if (TEXVALID(shaderstate.curtexnums->specular) && p->permu[perm|PERMUTATION_SPECULAR].handle.hlsl.vert)
perm |= PERMUTATION_SPECULAR;
if (TEXVALID(shaderstate.curtexnums->fullbright) && p->handle[perm|PERMUTATION_FULLBRIGHT].hlsl.vert)
if (TEXVALID(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.hlsl.vert)
perm |= PERMUTATION_FULLBRIGHT;
if (p->handle[perm|PERMUTATION_UPPERLOWER].hlsl.vert && (TEXVALID(shaderstate.curtexnums->upperoverlay) || TEXVALID(shaderstate.curtexnums->loweroverlay)))
if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXVALID(shaderstate.curtexnums->upperoverlay) || TEXVALID(shaderstate.curtexnums->loweroverlay)))
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.gfog_rgbd[3] && p->handle[perm|PERMUTATION_FOG].hlsl.vert)
if (r_refdef.gfog_rgbd[3] && p->permu[perm|PERMUTATION_FOG].handle.hlsl.vert)
perm |= PERMUTATION_FOG;
// if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert)
// perm |= PERMUTATION_OFFSET;
@ -2449,6 +2449,7 @@ static entity_t *R_NearestPortal(plane_t *plane)
int i;
entity_t *best = NULL;
float dist, bestd = 0;
//for q3-compat, portals on world scan for a visedict to use for their view.
for (i = 0; i < cl_numvisedicts; i++)
{
if (cl_visedicts[i].rtype == RT_PORTALSURFACE)

View file

@ -125,8 +125,11 @@ static void *D3D11_AllocNewTextureData(void *datargba, int width, int height, un
}
texid_t D3D11_AllocNewTexture(char *ident, int width, int height, unsigned int flags)
{
d3d11texture_t *t;
void *img = D3D11_AllocNewTextureData(NULL, width, height, flags);
d3d11texture_t *t = d3d_lookup_texture("");
if (!img)
return r_nulltex;
t = d3d_lookup_texture("");
t->tex2d = img;
return ToTexID(t);
@ -207,6 +210,8 @@ static void Upload_Texture_32(ID3D11Texture2D *tex, unsigned int *data, int widt
// D3D11_MAPPED_SUBRESOURCE lock;
D3D11_TEXTURE2D_DESC desc;
if (!tex)
return;
ID3D11Texture2D_GetDesc(tex, &desc);
if (width == desc.Width && height == desc.Height)

View file

@ -138,9 +138,9 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
ID3DBlob *vcode = NULL, *fcode = NULL, *errors = NULL;
qboolean success = false;
prog->handle[permu].hlsl.vert = NULL;
prog->handle[permu].hlsl.frag = NULL;
prog->handle[permu].hlsl.layout = NULL;
prog->permu[permu].handle.hlsl.vert = NULL;
prog->permu[permu].handle.hlsl.frag = NULL;
prog->permu[permu].handle.hlsl.layout = NULL;
if (pD3DCompile)
{
@ -176,7 +176,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
success = false;
else
{
if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), NULL, (ID3D11VertexShader**)&prog->handle[permu].hlsl.vert)))
if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), NULL, (ID3D11VertexShader**)&prog->permu[permu].handle.hlsl.vert)))
success = false;
}
if (errors)
@ -191,7 +191,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
success = false;
else
{
if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fcode->lpVtbl->GetBufferPointer(fcode), fcode->lpVtbl->GetBufferSize(fcode), NULL, (ID3D11PixelShader**)&prog->handle[permu].hlsl.frag)))
if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fcode->lpVtbl->GetBufferPointer(fcode), fcode->lpVtbl->GetBufferSize(fcode), NULL, (ID3D11PixelShader**)&prog->permu[permu].handle.hlsl.frag)))
success = false;
}
if (errors)
@ -291,7 +291,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, int permu
decl[elements].InstanceDataStepRate = 0;
elements++;
*/
if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), (ID3D11InputLayout**)&prog->handle[permu].hlsl.layout)))
if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vcode->lpVtbl->GetBufferPointer(vcode), vcode->lpVtbl->GetBufferSize(vcode), (ID3D11InputLayout**)&prog->permu[permu].handle.hlsl.layout)))
{
Con_Printf("HLSL Shader %s requires unsupported inputs\n", name);
success = false;

View file

@ -33,7 +33,11 @@ Things to improve:
#define FORCESTATE
#ifdef FORCESTATE
#pragma warningmsg("D3D9 FORCESTATE is active")
#endif
extern LPDIRECT3DDEVICE9 pD3DDev9;
@ -41,7 +45,9 @@ extern LPDIRECT3DDEVICE9 pD3DDev9;
//#define d3dcheck(foo) foo
#define d3dcheck(foo) do{HRESULT err = foo; if (FAILED(err)) Sys_Error("D3D reported error on backend line %i - error 0x%x\n", __LINE__, (unsigned int)err);} while(0)
#define MAX_TMUS 4
#define MAX_TMUS 16
#define MAX_TC_TMUS 4
extern float d3d_trueprojection[16];
@ -179,8 +185,8 @@ typedef struct
unsigned int dynxyz_offs;
unsigned int dynxyz_size;
IDirect3DVertexBuffer9 *dynst_buff[MAX_TMUS];
unsigned int dynst_offs[MAX_TMUS];
IDirect3DVertexBuffer9 *dynst_buff[MAX_TC_TMUS];
unsigned int dynst_offs[MAX_TC_TMUS];
unsigned int dynst_size;
IDirect3DVertexBuffer9 *dyncol_buff;
@ -304,7 +310,11 @@ static void BE_ApplyShaderBits(unsigned int bits)
}
}
#ifdef FORCESTATE
delta = ~0;
#else
delta = bits ^ shaderstate.shaderbits;
#endif
if (!delta)
return;
shaderstate.shaderbits = bits;
@ -433,7 +443,7 @@ void D3D9BE_Reset(qboolean before)
if (shaderstate.dynxyz_buff)
IDirect3DVertexBuffer9_Release(shaderstate.dynxyz_buff);
shaderstate.dynxyz_buff = NULL;
for (tmu = 0; tmu < MAX_TMUS; tmu++)
for (tmu = 0; tmu < MAX_TC_TMUS; tmu++)
{
if (shaderstate.dynst_buff[tmu])
IDirect3DVertexBuffer9_Release(shaderstate.dynst_buff[tmu]);
@ -507,7 +517,7 @@ void D3D9BE_Reset(qboolean before)
elements++;
}
for (tmu = 0; tmu < MAX_TMUS; tmu++)
for (tmu = 0; tmu < MAX_TC_TMUS; tmu++)
{
if (i & (D3D_VDEC_ST0<<tmu))
{
@ -547,7 +557,7 @@ void D3D9BE_Reset(qboolean before)
}
IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, shaderstate.dynxyz_size, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &shaderstate.dynxyz_buff, NULL);
for (tmu = 0; tmu < MAX_TMUS; tmu++)
for (tmu = 0; tmu < D3D_VDEC_ST0; tmu++)
IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, shaderstate.dynst_size, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &shaderstate.dynst_buff[tmu], NULL);
IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, shaderstate.dyncol_size, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &shaderstate.dyncol_buff, NULL);
IDirect3DDevice9_CreateIndexBuffer(pD3DDev9, shaderstate.dynidx_size, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFMT_QINDEX, D3DPOOL_DEFAULT, &shaderstate.dynidx_buff, NULL);
@ -1655,25 +1665,27 @@ static void BE_SubmitMeshChain(int idxfirst)
static void BE_ApplyUniforms(program_t *prog, int permu)
{
int h;
int i;
IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->handle[permu].hlsl.vert);
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->handle[permu].hlsl.frag);
IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[permu].handle.hlsl.vert);
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[permu].handle.hlsl.frag);
for (i = 0; i < prog->numparams; i++)
{
h = prog->permu[permu].parm[i];
switch (prog->parm[i].type)
{
case SP_M_PROJECTION:
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], d3d_trueprojection, 4);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, d3d_trueprojection, 4);
break;
case SP_M_VIEW:
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], r_refdef.m_view, 4);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, r_refdef.m_view, 4);
break;
// case SP_M_MODEL:
// IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], r_refdef.m_view, 4);
// IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, r_refdef.m_view, 4);
// break;
case SP_V_EYEPOS:
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], r_origin, 1);
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, r_origin, 1);
break;
case SP_E_EYEPOS:
{
@ -1681,13 +1693,13 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
float m16[16];
Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin);
Matrix4x4_CM_Transform3(m16, r_origin, t2);
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], t2, 1);
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, t2, 1);
}
break;
case SP_E_TIME:
{
vec4_t t1 = {shaderstate.curtime};
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], t1, 1);
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, t1, 1);
}
break;
case SP_M_MODELVIEWPROJECTION:
@ -1695,7 +1707,7 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
float mv[16], mvp[16];
Matrix4_Multiply(r_refdef.m_view, shaderstate.m_model, mv);
Matrix4_Multiply(d3d_trueprojection, mv, mvp);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], mvp, 4);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, mvp, 4);
}
break;
@ -1708,15 +1720,15 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
Matrix4_Invert(shaderstate.m_model, inv);
Matrix4x4_CM_Transform3(inv, shaderstate.curdlight->origin, t2);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], t2, 3);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, t2, 3);
break;
}
case SP_LIGHTRADIUS:
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], &shaderstate.curdlight->radius, 1);
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, &shaderstate.curdlight->radius, 1);
break;
case SP_LIGHTCOLOUR:
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], shaderstate.curdlight_colours, 3);
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, shaderstate.curdlight_colours, 3);
break;
case SP_E_COLOURS:
@ -1754,15 +1766,15 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i
program_t *p = s->prog;
if (TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_BUMPMAP].hlsl.vert)
if (TEXVALID(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.hlsl.vert)
perm |= PERMUTATION_BUMPMAP;
if (TEXVALID(shaderstate.curtexnums->specular) && p->handle[perm|PERMUTATION_SPECULAR].hlsl.vert)
if (TEXVALID(shaderstate.curtexnums->specular) && p->permu[perm|PERMUTATION_SPECULAR].handle.hlsl.vert)
perm |= PERMUTATION_SPECULAR;
if (TEXVALID(shaderstate.curtexnums->fullbright) && p->handle[perm|PERMUTATION_FULLBRIGHT].hlsl.vert)
if (TEXVALID(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.hlsl.vert)
perm |= PERMUTATION_FULLBRIGHT;
if (p->handle[perm|PERMUTATION_UPPERLOWER].hlsl.vert && (TEXVALID(shaderstate.curtexnums->upperoverlay) || TEXVALID(shaderstate.curtexnums->loweroverlay)))
if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXVALID(shaderstate.curtexnums->upperoverlay) || TEXVALID(shaderstate.curtexnums->loweroverlay)))
perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.gfog_rgbd[3] && p->handle[perm|PERMUTATION_FOG].hlsl.vert)
if (r_refdef.gfog_rgbd[3] && p->permu[perm|PERMUTATION_FOG].handle.hlsl.vert)
perm |= PERMUTATION_FOG;
// if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert)
// perm |= PERMUTATION_OFFSET;

View file

@ -155,14 +155,14 @@ void D3D9Shader_Init(void)
return;
}
qboolean D3D9Shader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag)
qboolean D3D9Shader_CreateProgram (program_t *prog, char *sname, int permu, char **precompilerconstants, char *vert, char *frag)
{
D3DXMACRO defines[64];
LPD3DXBUFFER code = NULL, errors = NULL;
qboolean success = false;
prog->handle[permu].hlsl.vert = NULL;
prog->handle[permu].hlsl.frag = NULL;
prog->permu[permu].handle.hlsl.vert = NULL;
prog->permu[permu].handle.hlsl.frag = NULL;
if (pD3DXCompileShader)
{
@ -194,32 +194,32 @@ qboolean D3D9Shader_CreateProgram (program_t *prog, int permu, char **precompile
success = true;
defines[0].Name = "VERTEX_SHADER";
if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, NULL, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->handle[permu].hlsl.ctabv)))
if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, NULL, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].handle.hlsl.ctabv)))
success = false;
else
{
IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&prog->handle[permu].hlsl.vert);
IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&prog->permu[permu].handle.hlsl.vert);
code->lpVtbl->Release(code);
}
if (errors)
{
char *messages = errors->lpVtbl->GetBufferPointer(errors);
Con_Printf("%s", messages);
Con_Printf("Error compiling vertex shader %s:\n%s", sname, messages);
errors->lpVtbl->Release(errors);
}
defines[0].Name = "FRAGMENT_SHADER";
if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, NULL, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->handle[permu].hlsl.ctabf)))
if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, NULL, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].handle.hlsl.ctabf)))
success = false;
else
{
IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&prog->handle[permu].hlsl.frag);
IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&prog->permu[permu].handle.hlsl.frag);
code->lpVtbl->Release(code);
}
if (errors)
{
char *messages = errors->lpVtbl->GetBufferPointer(errors);
Con_Printf("%s", messages);
Con_Printf("Error compiling pixel shader %s:\n%s", sname, messages);
errors->lpVtbl->Release(errors);
}
}

View file

@ -2,6 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}"
ProjectSection(ProjectDependencies) = postProject
{32B12987-DF8C-4E40-B07C-B18586A4CA65} = {32B12987-DF8C-4E40-B07C-B18586A4CA65}
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
@ -26,7 +27,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nacl", "..\nacl\nacl.vcproj
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xsv", "..\..\plugins\xsv\xsv.vcproj", "{873CCE24-3549-49D4-A4B4-653F91B1532A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "berkelium", "..\..\plugins\berkelium\berkelium.vcproj", "{4877586B-E85B-4DF8-BCCE-59D31514D240}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "berkplug", "..\..\plugins\berkelium\berkelium.vcproj", "{4877586B-E85B-4DF8-BCCE-59D31514D240}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avplug", "..\..\plugins\avplug\avplug.vcproj", "{32B12987-DF8C-4E40-B07C-B18586A4CA65}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -56,8 +59,8 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.ActiveCfg = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.Build.0 = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.ActiveCfg = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.Build.0 = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.ActiveCfg = D3DDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.Build.0 = D3DDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|Win32.ActiveCfg = D3DRelease|Win32
@ -76,6 +79,7 @@ Global
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.ActiveCfg = MDebug|Win32
@ -144,6 +148,7 @@ Global
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|x64.ActiveCfg = GLRelease|Win32
@ -349,7 +354,6 @@ Global
{873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug|Win32.Build.0 = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug|x64.ActiveCfg = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.GLDebug|Win32.ActiveCfg = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.GLDebug|Win32.Build.0 = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.GLDebug|x64.ActiveCfg = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.GLRelease|Win32.ActiveCfg = Release|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.GLRelease|x64.ActiveCfg = Release|Win32
@ -383,7 +387,6 @@ Global
{4877586B-E85B-4DF8-BCCE-59D31514D240}.Debug|Win32.Build.0 = Debug|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.Debug|x64.ActiveCfg = Debug|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.GLDebug|Win32.ActiveCfg = Debug|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.GLDebug|Win32.Build.0 = Debug|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.GLDebug|x64.ActiveCfg = Debug|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.GLRelease|Win32.ActiveCfg = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.GLRelease|x64.ActiveCfg = Release|Win32
@ -405,6 +408,41 @@ Global
{4877586B-E85B-4DF8-BCCE-59D31514D240}.Release|Win32.ActiveCfg = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.Release|Win32.Build.0 = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.Release|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DDebug|Win32.Build.0 = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DDebug|x64.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DRelease|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DRelease|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DRelease|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Debug|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Debug|Win32.Build.0 = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Debug|x64.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.GLDebug|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.GLDebug|x64.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.GLRelease|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.GLRelease|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.GLRelease|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MDebug|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MDebug|Win32.Build.0 = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MDebug|x64.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MinGLDebug|Win32.Build.0 = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MinGLDebug|x64.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MinGLRelease|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MinGLRelease|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MRelease|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MRelease|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.MRelease|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release Dedicated Server|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release Dedicated Server|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -249,7 +249,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../d3d9;../libs/dxsdk9/include;../libs/dxsdk7/include"
PreprocessorDefinitions="_DEBUG;D3D9QUAKE;WIN32;_WINDOWS"
PreprocessorDefinitions="_DEBUG;D3D9QUAKE;D3D11QUAKE;WIN32;_WINDOWS"
RuntimeLibrary="1"
FloatingPointModel="2"
UsePrecompiledHeader="2"
@ -4944,6 +4944,169 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\server\sv_sql.c"
>
<FileConfiguration
Name="MinGLDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\server\sv_user.c"
>
@ -9659,6 +9822,14 @@
<File
RelativePath="..\client\in_generic.c"
>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\client\in_win.c"
@ -20680,6 +20851,170 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\gl\gl_vidmacos.c"
>
<FileConfiguration
Name="MinGLDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MinGLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="MDebug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="GLRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="D3DRelease|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\client\in_macos.c"
>

File diff suppressed because it is too large Load diff

View file

@ -40,39 +40,149 @@ public class FTEDroidActivity extends Activity
private Sensor sensoracc;
private FTEView view;
float acc_x, acc_y, acc_z; /*might be some minor race condition on these*/
private String basedir, userdir;
private class FTEEGLConfig implements GLSurfaceView.EGLConfigChooser
{
int version;
public void setversion(FTEView view, int version)
{
this.version = version;
view.setEGLContextClientVersion(version);
}
public boolean CheckGLES2Support()
{
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
EGLConfig cfg;
int oldver = this.version;
int[] version = new int[2];
egl.eglInitialize(display, version);
this.version = 2;
cfg = chooseConfig(egl, display);
this.version = oldver;
int[] value = {0};
egl.eglGetConfigAttrib(display, cfg, EGL10.EGL_RENDERABLE_TYPE, value);
egl.eglTerminate(display);
return ((value[0] & 4) == 4);
}
@Override
public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display)
{
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
EGLConfig[] cfg = new EGLConfig[64];
int[] num_configs = {0};
int[] value = {0};
int i;
int[] attribs =
{
egl.EGL_RENDERABLE_TYPE, (version>=2?4:1)/*egl.EGL_OPENGL_ES2_BIT*/,
// egl.EGL_SURFACE_TYPE, egl.EGL_WINDOW_BIT,
egl.EGL_BLUE_SIZE, 5,
egl.EGL_GREEN_SIZE, 6,
egl.EGL_RED_SIZE, 5,
egl.EGL_DEPTH_SIZE, 16,
// egl.EGL_STENCIL_SIZE, 8,
egl.EGL_NONE, egl.EGL_NONE
};
if (!egl.eglChooseConfig(display, attribs, cfg, 64, num_configs))
throw new IllegalArgumentException("eglChooseConfig failed");
if (num_configs[0] == 0)
{
attribs[1] = 1; //egl.EGL_RENDERABLE_TYPE, 1/*egl.EGL_OPENGL_ES_BIT*/,
if (!egl.eglChooseConfig(display, attribs, cfg, 64, num_configs))
throw new IllegalArgumentException("eglChooseConfig failed");
if (num_configs[0] == 0)
{
throw new IllegalArgumentException("eglChooseConfig didn't report any valid configs");
}
}
android.util.Log.i("FTEDroid", "Found " + num_configs[0] + " EGL configs.");
//try to find a gles2 context instead.
for (i = 0; i < num_configs[0]; i++)
{
android.util.Log.i("FTEDroid", "Config " + i + ":");
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_RED_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_RED_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_GREEN_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_GREEN_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_BLUE_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_BLUE_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_DEPTH_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_DEPTH_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_STENCIL_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_STENCIL_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_RENDERABLE_TYPE, value);
android.util.Log.i("FTEDroid", "EGL_RENDERABLE_TYPE " + value[0]);
if ((value[0] & 4) == 4)
{
android.util.Log.i("FTEDroid", "Found a GLES2 context!");
return cfg[i];
}
}
return cfg[0];
}
}
private class FTERenderer implements GLSurfaceView.Renderer
{
private boolean inited;
public int glesversion;
private String basedir, userdir;
FTEDroidActivity act;
FTEView theview;
FTEEGLConfig cfgchooser;
int notifiedflags;
void updateGLESVersion()
{
if (FTEDroidEngine.getpreferedglesversion() < 2)
{
android.util.Log.i("FTEDroid", "Using GLES1");
this.glesversion = 1;
}
else if (android.os.Build.VERSION.SDK_INT >= 8) //could be 5 with setEGLContextFactory instead of setEGLContextClientVersion
{
if (cfgchooser.CheckGLES2Support())
{
android.util.Log.i("FTEDroid", "Support for GLES2 detected");
this.glesversion = 2;
cfgchooser.setversion(theview, this.glesversion);
}
else
{
android.util.Log.i("FTEDroid", "GLES2 not supported. Using GLES1.");
this.glesversion = 1;
}
}
else
{
android.util.Log.i("FTEDroid", "GLES2 requires android 2.2+");
this.glesversion = 1;
}
}
FTERenderer(FTEView view, FTEDroidActivity parent)
{
act = parent;
theview = view;
try
{
android.content.pm.PackageInfo info = parent.getPackageManager().getPackageInfo("com.fteqw", 0);
basedir = info.applicationInfo.sourceDir;
}
catch(android.content.pm.PackageManager.NameNotFoundException e)
{
/*oh well, can just use the homedir instead*/
}
// try
// {
userdir = Environment.getExternalStorageDirectory().getPath() + "/fte";
// }
// catch(foo)
// {
// }
android.util.Log.i("FTEDroid", "Base dir is \"" + basedir + "\".");
android.util.Log.i("FTEDroid", "User dir is \"" + userdir + "\".");
FTEDroidEngine.init(0, 0, 0, basedir, userdir);
inited = true;
cfgchooser = new FTEEGLConfig();
// theview.setEGLConfigChooser(cfgchooser);
updateGLESVersion();
}
@Override
@ -141,6 +251,16 @@ public class FTEDroidActivity extends Activity
}
if (((flags ^ notifiedflags) & 8) != 0)
{
final String errormsg = FTEDroidEngine.geterrormessage();
inited = false;
if (errormsg == "")
{
finish();
System.exit(0);
}
//8 means sys error
Runnable r = new Runnable()
{
@ -149,7 +269,7 @@ public class FTEDroidActivity extends Activity
theview.setVisibility(theview.GONE);
AlertDialog ad = new AlertDialog.Builder(act).create();
ad.setTitle("FTE ERROR");
ad.setMessage(FTEDroidEngine.geterrormessage());
ad.setMessage(errormsg);
ad.setCancelable(false);
ad.setButton("Ok", new DialogInterface.OnClickListener()
{
@ -167,6 +287,7 @@ public class FTEDroidActivity extends Activity
}
if (((flags ^ notifiedflags) & 16) != 0)
{
//16 means orientation cvar change
Runnable r = new Runnable()
{
public void run()
@ -231,93 +352,6 @@ public class FTEDroidActivity extends Activity
}
}
private class FTEEGLConfig implements GLSurfaceView.EGLConfigChooser
{
public void setversion(FTEView view, int version)
{
view.setEGLContextClientVersion(version);
}
public boolean CheckGLES2Support()
{
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
EGLConfig cfg;
int[] version = new int[2];
egl.eglInitialize(display, version);
cfg = chooseConfig(egl, display);
int[] value = {0};
egl.eglGetConfigAttrib(display, cfg, EGL10.EGL_RENDERABLE_TYPE, value);
egl.eglTerminate(display);
return ((value[0] & 4) == 4);
}
@Override
public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display)
{
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
EGLConfig[] cfg = new EGLConfig[64];
int[] num_configs = {0};
int[] value = {0};
int i;
int[] attribs =
{
egl.EGL_RENDERABLE_TYPE, 4/*egl.EGL_OPENGL_ES2_BIT*/,
// egl.EGL_SURFACE_TYPE, egl.EGL_WINDOW_BIT,
egl.EGL_BLUE_SIZE, 5,
egl.EGL_GREEN_SIZE, 6,
egl.EGL_RED_SIZE, 5,
egl.EGL_DEPTH_SIZE, 16,
// egl.EGL_STENCIL_SIZE, 8,
egl.EGL_NONE, egl.EGL_NONE
};
if (!egl.eglChooseConfig(display, attribs, cfg, 64, num_configs))
throw new IllegalArgumentException("eglChooseConfig failed");
if (num_configs[0] == 0)
{
attribs[1] = 1; //egl.EGL_RENDERABLE_TYPE, 1/*egl.EGL_OPENGL_ES_BIT*/,
if (!egl.eglChooseConfig(display, attribs, cfg, 64, num_configs))
throw new IllegalArgumentException("eglChooseConfig failed");
if (num_configs[0] == 0)
{
throw new IllegalArgumentException("eglChooseConfig didn't report any valid configs");
}
}
android.util.Log.i("FTEDroid", "Found " + num_configs[0] + " EGL configs.");
for (i = 0; i < num_configs[0]; i++)
{
android.util.Log.i("FTEDroid", "Config " + i + ":");
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_RED_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_RED_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_GREEN_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_GREEN_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_BLUE_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_BLUE_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_DEPTH_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_DEPTH_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_STENCIL_SIZE, value);
android.util.Log.i("FTEDroid", "EGL_STENCIL_SIZE " + value[0]);
egl.eglGetConfigAttrib(display, cfg[i], egl.EGL_RENDERABLE_TYPE, value);
android.util.Log.i("FTEDroid", "EGL_RENDERABLE_TYPE " + value[0]);
if ((value[0] & 4) == 4)
{
android.util.Log.i("FTEDroid", "Found a GLES2 context!");
return cfg[i];
}
}
return cfg[0];
}
}
private class FTEView extends GLSurfaceView implements SensorEventListener
{
private final FTERenderer rndr;
@ -334,8 +368,11 @@ public class FTEDroidActivity extends Activity
{
byte[] audbuf = new byte[2048];
int avail;
AudioTrack at;
int chans;
try
{
if (schannels >= 8) //the OUT enumeration allows specific speaker control. but also api level 5+
chans = AudioFormat.CHANNEL_OUT_7POINT1;
else if (schannels >= 6)
@ -353,7 +390,13 @@ public class FTEDroidActivity extends Activity
// if (sz < sspeed * 0.05)
// sz = sspeed * 0.05;
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, sspeed, chans, enc, sz, AudioTrack.MODE_STREAM);
at = new AudioTrack(AudioManager.STREAM_MUSIC, sspeed, chans, enc, sz, AudioTrack.MODE_STREAM);
}
catch(IllegalArgumentException e)
{
//fixme: tell the engine that its bad and that it should configure some different audio attributes, instead of simply muting.
return;
}
at.setStereoVolume(1, 1);
at.play();
@ -494,35 +537,6 @@ public class FTEDroidActivity extends Activity
inputevent = new FTELegacyInputEvent();
rndr = new FTERenderer(this, context);
if (USE_GLES_VERSION < 2)
{
android.util.Log.i("FTEDroid", "GLES2 disabled at game compile time");
rndr.glesversion = 1;
}
else if (android.os.Build.VERSION.SDK_INT >= 8) //could be 5 with setEGLContextFactory instead of setEGLContextClientVersion
{
FTEEGLConfig cfgchooser = new FTEEGLConfig();
setEGLConfigChooser(cfgchooser);
if (cfgchooser.CheckGLES2Support())
{
android.util.Log.i("FTEDroid", "Support for GLES2 detected");
rndr.glesversion = 2;
cfgchooser.setversion(this, rndr.glesversion);
}
else
{
android.util.Log.i("FTEDroid", "GLES2 not supported. Using GLES1.");
rndr.glesversion = 1;
}
}
else
{
android.util.Log.i("FTEDroid", "GLES2 requires android 2.2+");
rndr.glesversion = 1;
}
setRenderer(rndr);
setFocusable(true);
setFocusableInTouchMode(true);
@ -632,6 +646,28 @@ public class FTEDroidActivity extends Activity
public void onCreate(Bundle savedInstanceState)
{
android.util.Log.i("FTEDroid", "onCreate");
try
{
String packagename = this.getComponentName().getPackageName(); //"com.fteqw", but not hardcoded.
android.util.Log.i("FTEDroid", "Installed in package \"" + packagename + "\".");
android.content.pm.PackageInfo info = this.getPackageManager().getPackageInfo(packagename, 0);
basedir = info.applicationInfo.sourceDir;
}
catch(android.content.pm.PackageManager.NameNotFoundException e)
{
/*oh well, can just use the homedir instead*/
}
// try
// {
userdir = Environment.getExternalStorageDirectory().getPath() + "/fte";
// }
// catch(foo)
// {
// }
android.util.Log.i("FTEDroid", "Base dir is \"" + basedir + "\".");
android.util.Log.i("FTEDroid", "User dir is \"" + userdir + "\".");
//go full-screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);

View file

@ -11,6 +11,7 @@ public class FTEDroidEngine
public static native int audioinfo(int arg);
public static native String geterrormessage();
public static native String getpreferedorientation();
public static native int getpreferedglesversion();
public static native void newglcontext();
static

View file

@ -938,7 +938,7 @@ void R_GAlias_DrawBatch(batch_t *batch)
{
if (batch->surf_first == surfnum)
{
needrecolour = Alias_GAliasBuildMesh(&mesh, inf, surfnum, e, true);
needrecolour = Alias_GAliasBuildMesh(&mesh, inf, surfnum, e, batch->shader->prog && batch->shader->prog->permu[PERMUTATION_SKELETAL].handle.glsl);
batch->mesh = &meshl;
return;
}
@ -976,7 +976,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
clmodel = e->model;
if (!(e->flags & Q2RF_WEAPONMODEL))
if (!(e->flags & Q2RF_WEAPONMODEL) && !e->framestate.bonestate)
{
if (R_CullEntityBox (e, clmodel->mins, clmodel->maxs))
return;

File diff suppressed because it is too large Load diff

View file

@ -186,8 +186,6 @@ void R_BloomBlend (void)
if (!r_refdef.pxrect.width || !r_refdef.pxrect.height)
return;
GL_Set2D(false);
/*update textures if we need to resize them*/
R_SetupBloomTextures(r_refdef.pxrect.width, r_refdef.pxrect.height);

View file

@ -380,13 +380,15 @@ void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue)
void GLDraw_ImageList_f(void)
{
int count = 0;
unsigned int mem = 0;
gltexture_t *glt;
for (glt=gltextures ; glt ; glt=glt->next)
{
count++;
mem += glt->width * glt->height * 4;
Con_Printf("%s (%i*%i, seq=%i)\n", glt->identifier, glt->width, glt->height, glt->com.regsequence);
}
Con_Printf("%i images\n", count);
Con_Printf("%i images, %i bytes\n", count, mem);
}
void GLDraw_FlushOldTextures(void)
@ -493,7 +495,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n"));
TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n"));
GL_InitSceneProcessingShaders();
Cmd_AddCommand ("r_imagelist", GLDraw_ImageList_f);
Cmd_AddCommandD ("r_imagelist", GLDraw_ImageList_f, "Debug command. Reveals current list of loaded images.");
}
void GLDraw_DeInit (void)
@ -1393,15 +1395,9 @@ void GL_Upload24BGR (char *name, qbyte *framedata, int inwidth, int inheight, un
dest = uploadmemorybufferintermediate;
//change from bgr bottomup to rgba topdown
for (outwidth = 1; outwidth < inwidth; outwidth*=2)
;
for (outheight = 1; outheight < inheight; outheight*=2)
;
if (outwidth > 512)
outwidth = 512;
if (outheight > 512)
outheight = 512;
outwidth = inwidth;
outheight = inheight;
GL_RoundDimensions(&outwidth, &outheight, !(flags&IF_NOMIPMAP));
if (outwidth*outheight > sizeofuploadmemorybufferintermediate/4)
Sys_Error("GL_Upload24BGR: image too big (%i*%i)", inwidth, inheight);
@ -1466,15 +1462,9 @@ void GL_Upload24BGR_Flip (char *name, qbyte *framedata, int inwidth, int inheigh
dest = uploadmemorybufferintermediate;
//change from bgr bottomup to rgba topdown
for (outwidth = 1; outwidth < inwidth; outwidth*=2)
;
for (outheight = 1; outheight < inheight; outheight*=2)
;
if (outwidth > 512)
outwidth = 512;
if (outheight > 512)
outheight = 512;
outwidth = inwidth;
outheight = inheight;
GL_RoundDimensions(&outwidth, &outheight, !(flags&IF_NOMIPMAP));
if (outwidth*outheight > sizeofuploadmemorybufferintermediate/4)
Sys_Error("GL_Upload24BGR_Flip: image too big (%i*%i)", inwidth, inheight);

View file

@ -950,7 +950,7 @@ struct font_s *Font_LoadFont(int height, char *fontfilename)
for (i = '!'; i <= '_'; i++)
{
dp = NULL;
FS_LoadFile(va("wad/stcfn%.3d", i), &dp);
FS_LoadFile(va("wad/stcfn%.3d", i), (void**)&dp);
if (!dp)
break;
@ -1128,6 +1128,12 @@ struct font_s *Font_LoadFont(int height, char *fontfilename)
void Font_Free(struct font_s *f)
{
struct charcache_s **link;
if (f->alt)
{
Font_Free(f->alt);
f->alt = NULL;
}
for (link = &fontplanes.oldestchar; *link; )
{
if (*link >= f->chars && *link <= f->chars + FONTCHARS)
@ -1195,8 +1201,13 @@ int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode)
if ((charcode&CON_CHARMASK) == '\t')
return x + ((TABWIDTH - (x % TABWIDTH)) % TABWIDTH);
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
}
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
@ -1216,8 +1227,13 @@ int Font_CharWidth(unsigned int charcode)
struct font_s *font = curfont;
if (charcode&CON_HIDDEN)
return 0;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
}
c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
@ -1340,8 +1356,13 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
if (charcode & CON_HIDDEN)
return px;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
}
//crash if there is no current font.
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
@ -1464,8 +1485,13 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch
int col;
int v;
struct font_s *font = curfont;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
}
cw /= font->charheight;
ch /= font->charheight;

View file

@ -10,6 +10,17 @@
#define TERRAINTHICKNESS 16
#define TERRAINACTIVESECTIONS 1000
/*
a note on networking:
By default terrain is NOT networked. This means content is loaded without networking delays.
If you wish to edit the terrain collaboratively, you can enable the mod_terrain_networked cvar.
When set, changes on the server will notify clients that a section has changed, and the client will reload it as needed.
Changes on the client WILL NOT notify the server, and will get clobbered if the change is also made on the server.
This means for editing purposes, you MUST funnel it via ssqc with your own permission checks.
It also means for explosions and local stuff, the server will merely restate changes from impacts if you do them early. BUT DO NOT CALL THE EDIT FUNCTION IF THE SERVER HAS ALREADY APPLIED THE CHANGE.
*/
cvar_t mod_terrain_networked = CVARD("mod_terrain_networked", "0", "Terrain edits are networked. Clients will download sections on demand, and servers will notify clients of changes.");
//heightmaps work thusly:
//there is one raw heightmap file
//the file is split to 4*4 sections.
@ -258,6 +269,15 @@ static char *Terr_DiskSectionName(heightmap_t *hm, int sx, int sy)
sy &= CHUNKLIMIT-1;
return va("maps/%s/sect_%03x_%03x.hms", hm->path, sx, sy);
}
static char *Terr_TempDiskSectionName(heightmap_t *hm, int sx, int sy)
{
sx -= CHUNKBIAS;
sy -= CHUNKBIAS;
//wrap cleanly
sx &= CHUNKLIMIT-1;
sy &= CHUNKLIMIT-1;
return va("temp/%s/sect_%03x_%03x.hms", hm->path, sx, sy);
}
static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, int sy)
{
dsection_t *ds = NULL;
@ -269,6 +289,14 @@ static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, in
#endif
void *ptr;
if (mod_terrain_networked.ival)
{
#ifndef CLIENTONLY
if (hm != sv.world.worldmodel->terrain)
#endif
return NULL;
}
/*queue the file for download if we don't have it yet*/
if (FS_LoadFile(Terr_DiskSectionName(hm, sx, sy), (void**)&ds) < 0
#ifndef CLIENTONLY
@ -544,12 +572,12 @@ static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, in
return s;
}
static qboolean Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy)
//doesn't clear edited/dirty flags or anything
static qboolean Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy, char *fname)
{
#ifndef SERVERONLY
dsection_t ds;
dsmesh_t dm;
char *fname;
unsigned char *lm;
vfsfile_t *f;
int nothing = 0;
@ -608,7 +636,6 @@ static qboolean Terr_SaveSection(heightmap_t *hm, hmsection_t *s, int sx, int sy
ds.maxh = s->maxh;
ds.ents_num = s->numents;
fname = Terr_DiskSectionName(hm, sx, sy);
FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
@ -683,7 +710,7 @@ static hmsection_t *Terr_GetSection(heightmap_t *hm, int x, int y, qboolean dolo
}
/*save all currently loaded sections*/
int HeightMap_Save(heightmap_t *hm)
int Heightmap_Save(heightmap_t *hm)
{
hmsection_t *s;
int x, y;
@ -697,7 +724,7 @@ int HeightMap_Save(heightmap_t *hm)
continue;
if (s->flags & TSF_EDITED)
{
if (Terr_SaveSection(hm, s, x, y))
if (Terr_SaveSection(hm, s, x, y, Terr_DiskSectionName(hm, x, y)))
{
s->flags &= ~TSF_EDITED;
sectionssaved++;
@ -709,6 +736,68 @@ int HeightMap_Save(heightmap_t *hm)
return sectionssaved;
}
#ifndef CLIENTONLY
static int dehex(int i)
{
if (i >= '0' && i <= '9')
return (i-'0');
else if (i >= 'A' && i <= 'F')
return (i-'A'+10);
else
return (i-'a'+10);
}
//on servers, we can get requests to download current map sections. if so, give them it.
qboolean Terrain_LocateSection(char *name, flocation_t *loc)
{
heightmap_t *hm;
hmsection_t *s;
int x, y;
int nlen = strlen(name);
//reject if its not in maps
if (strncmp(name, "maps/", 5))
return false;
//or too short
if (nlen < 17+5)
return false;
//reject if its not a section...
if (strncmp(name+nlen - 17, "/sect_", 6) || strcmp(name+nlen - 4, ".hms"))
return false;
//FIXME: find the right map instead
hm = sv.world.worldmodel->terrain;
if (!hm) //its not terrain.
return false;
x = dehex(name[nlen-17+ 6])<<8;
x|= dehex(name[nlen-17+ 7])<<4;
x|= dehex(name[nlen-17+ 8])<<0;
y = dehex(name[nlen-17+10])<<8;
y|= dehex(name[nlen-17+11])<<4;
y|= dehex(name[nlen-17+12])<<0;
x += CHUNKBIAS;
y += CHUNKBIAS;
//verify that its valid
if (strcmp(name, Terr_DiskSectionName(hm, x, y)))
return false;
s = Terr_GetSection(hm, x, y, false);
if (!s || !(s->flags & TSF_EDITED))
return false; //its not been edited, might as well just use the regular file
name = Terr_TempDiskSectionName(hm, x, y);
if (!Terr_SaveSection(hm, s, x, y, name))
return false;
return FS_FLocateFile(name, FSLFRT_IFFOUND, loc);
}
#endif
void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusable)
{
RemoveLink(&s->recycle);
@ -729,7 +818,7 @@ void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusa
hm->relight = NULL;
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
if (qrenderer == QR_OPENGL && qglDeleteBuffersARB)
{
qglDeleteBuffersARB(1, &s->vbo.coord.gl.vbo);
qglDeleteBuffersARB(1, &s->vbo.indicies.gl.vbo);
@ -2491,35 +2580,6 @@ static void ted_itterate(heightmap_t *hm, int distribution, float *pos, float ra
}
}
//Heightmap_NativeBoxContents
enum
{
ter_reload, //
ter_save, //
ter_sethole, //vector pos, float radius, floatbool hole
ter_height_set, //vector pos, float radius, float newheight
ter_height_smooth, //vector pos, float radius, float percent
ter_height_spread, //vector pos, float radius, float percent
ter_raise, //vector pos, float radius, float heightchange
ter_lower, //vector pos, float radius, float heightchange
ter_tex_kill, //vector pos, void junk, void junk, string texname
ter_tex_get, //vector pos, void junk, float imagenum
ter_mixpaint, //vector pos, float radius, float percent, string texname
ter_mixconcentrate, //vector pos, float radius, float percent
ter_mixnoise, //vector pos, float radius, float percent
ter_mixblur, //vector pos, float radius, float percent
ter_water_set, //vector pos, float radius, float newwaterheight
ter_mesh_add, //entity ent
ter_mesh_kill, //vector pos, float radius
ter_tint, //vector pos, float radius, float percent, vector newcol, float newalph
ter_height_flatten, //vector pos, float radius, float percent
// ter_poly_add, //add a poly, woo
// ter_poly_remove, //remove polys
// ter_autopaint_h, //vector pos, float radius, float percent, string tex1, string tex2 (paint tex1/tex2
// ter_autopaint_n //vector pos, float radius, float percent, string tex1, string tex2
};
void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *vmw = prinst->parms->user;
@ -2548,7 +2608,7 @@ void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_glob
Terr_PurgeTerrainModel(mod, false, true);
break;
case ter_save:
Con_Printf("%i sections saved\n", HeightMap_Save(hm));
Con_Printf("%i sections saved\n", Heightmap_Save(hm));
break;
case ter_sethole:
/* {
@ -2623,16 +2683,16 @@ void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_glob
// case ter_mixset:
// ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixset, G_VECTOR(OFS_PARM4));
// break;
case ter_mixpaint:
case ter_mix_paint:
ted_itterate(hm, tid_exponential, pos, radius, quant/10, SECTTEXSIZE, ted_mixpaint, PR_GetStringOfs(prinst, OFS_PARM4));
break;
case ter_mixconcentrate:
case ter_mix_concentrate:
ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixconcentrate, NULL);
break;
case ter_mixnoise:
case ter_mix_noise:
ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixnoise, NULL);
break;
case ter_mixblur:
case ter_mix_blur:
Vector4Set(tally, 0, 0, 0, 0);
ted_itterate(hm, tid_exponential, pos, radius, 1, SECTTEXSIZE, ted_mixtally, &tally);
VectorScale(tally, 1/(tally[3]*255), tally);
@ -3007,4 +3067,9 @@ void *Mod_LoadTerrainInfo(model_t *mod, char *loadname)
return hm;
}
void Terr_Init(void)
{
Cvar_Register(&mod_terrain_networked, "Terrain");
}
#endif

View file

@ -556,176 +556,6 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
}
}
#if 0
/*
=======================================================================================================================
R_Draw_HL_AliasModel - main drawing function
=======================================================================================================================
*/
void R_DrawHLModel(entity_t *curent)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmodelcache_t *modelc = Mod_Extradata(curent->model);
hlmodel_t model;
int b, m, v;
short *skins;
int bgroup, cbone, lastbone;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//general model
model.header = (hlmdl_header_t *) ((char *)modelc + modelc->header);
model.texheader = (hlmdl_header_t *) ((char *)modelc + modelc->texheader);
model.textures = (hlmdl_tex_t *) ((char *)modelc + modelc->textures);
model.bones = (hlmdl_bone_t *) ((char *)modelc + modelc->bones);
model.bonectls = (hlmdl_bonecontroller_t *) ((char *)modelc + modelc->bonectls);
model.shaders = (shader_t **) ((char *)modelc + modelc->shaders);
skins = (short *) ((qbyte *) model.texheader + model.texheader->skins);
if (!model.texheader->numtextures)
{
Con_DPrintf("model with no textures: %s\n", curent->model->name);
return;
}
for (b = 0; b < MAX_BONE_CONTROLLERS; b++)
model.controller[b] = curent->framestate.bonecontrols[b];
// Con_Printf("%s %i\n", sequence->name, sequence->unknown1[0]);
cbone = 0;
for (bgroup = 0; bgroup < FS_COUNT; bgroup++)
{
lastbone = curent->framestate.g[bgroup].endbone;
if (bgroup == FS_COUNT-1)
lastbone = model.header->numbones;
if (cbone >= lastbone)
continue;
HL_SetupBones(&model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, (curent->framestate.g[bgroup].subblendfrac+1)*0.5, curent->framestate.g[bgroup].frametime[0]); /* Setup the bones */
cbone = lastbone;
}
/* Manipulate each mesh directly */
for(b = 0; b < model.header->numbodyparts; b++)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model.header + model.header->bodypartindex) +
b;
int bodyindex = (0 / bodypart->base) % bodypart->nummodels;
hlmdl_model_t *amodel = (hlmdl_model_t *) ((qbyte *) model.header + bodypart->modelindex) + bodyindex;
qbyte *bone = ((qbyte *) model.header + amodel->vertinfoindex);
vec3_t *verts = (vec3_t *) ((qbyte *) model.header + amodel->vertindex);
vec3_t transformed[2048];
// vec3_t *norms = (vec3_t *) ((qbyte *) model.header + amodel->unknown3[2]);
// vec3_t transformednorms[2048];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
for(v = 0; v < amodel->numverts; v++) // Transform per the matrix
{
VectorTransform(verts[v], (void *)transform_matrix[bone[v]], transformed[v]);
// glVertex3fv(verts[v]);
// glVertex3f( verts[v][0]+10*verts[v][0],
// verts[v][1]+10*verts[v][1],
// verts[v][2]+10*verts[v][2]);
}
//Need to work out what we have!
//raw data appears to be unit vectors
//transformed gives some points on the skeleton.
//what's also weird is that the meshes use these up!
/* glDisable(GL_TEXTURE_2D);
glBegin(GL_LINES);
for(v = 0; v < amodel->unknown3[0]; v++) // Transform per the matrix
{
VectorTransform(norms[v], transform_matrix[bone[v]], transformednorms[v]);
glVertex3fv(transformednorms[v]);
glVertex3f( transformednorms[v][0]+10*transformednorms[v][0],
transformednorms[v][1]+10*transformednorms[v][1],
transformednorms[v][2]+10*transformednorms[v][2]);
}
glEnd();
glEnable(GL_TEXTURE_2D);
*/
/* Draw each mesh */
for(m = 0; m < amodel->nummesh; m++)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_mesh_t *mesh = (hlmdl_mesh_t *) ((qbyte *) model.header + amodel->meshindex) + m;
float tex_w;
float tex_h;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
{
tex_w = 1.0f / model.textures[skins[mesh->skinindex]].w;
tex_h = 1.0f / model.textures[skins[mesh->skinindex]].h;
// GL_LazyBind(0, GL_TEXTURE_2D, model.shaders[skins[mesh->skinindex]]->defaulttextures.base);
}
GL_Draw_HL_AliasFrame((short *) ((qbyte *) model.header + mesh->index), transformed, tex_w, tex_h);
}
}
}
/*
=======================================================================================================================
GL_Draw_HL_AliasFrame - clip and draw all triangles
=======================================================================================================================
*/
void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float tex_h)
{
/*~~~~~~~~~~*/
int count = 0;
/*~~~~~~~~~~*/
// int c_tris=0;
// int c_verts=0;
// int c_chains=0;
for(;;)
{
count = *order++; /* get the vertex count and primitive type */
if(!count) break; /* done */
if(count < 0)
{
count = -count;
qglBegin(GL_TRIANGLE_FAN);
}
else
{
qglBegin(GL_TRIANGLE_STRIP);
}
// c_tris += count-2;
// c_chains++;
do
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
float *verts = transformed[order[0]];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//FIXME: what's order[1]?
/* texture coordinates come from the draw list */
qglTexCoord2f(order[2] * tex_w, order[3] * tex_h);
order += 4;
qglVertex3fv(verts);
// c_verts++;
} while(--count);
qglEnd();
}
}
#endif
void R_HL_BuildFrame(hlmodel_t *model, hlmdl_model_t *amodel, entity_t *curent, short *order, float tex_s, float tex_t, mesh_t *mesh)
{
static vecV_t xyz[2048];

View file

@ -314,7 +314,7 @@ void RMod_Think (void)
{
COM_StripExtension(lightmodel->name, filename, sizeof(filename));
COM_DefaultExtension(filename, ".lux", sizeof(filename));
f = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
f = FS_OpenVFS(filename, "wb", FS_GAME);
if (f)
{
VFS_WRITE(f, "QLIT\1\0\0\0", 8);
@ -329,7 +329,8 @@ void RMod_Think (void)
{
COM_StripExtension(lightmodel->name, filename, sizeof(filename));
COM_DefaultExtension(filename, ".lit", sizeof(filename));
f = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
f = FS_OpenVFS(filename, "wb", FS_GAME);
if (f)
{
VFS_WRITE(f, "QLIT\1\0\0\0", 8);
@ -429,6 +430,10 @@ void RMod_Init (void)
Cmd_AddCommand("mod_batchlist", RMod_BatchList_f);
Cmd_AddCommand("mod_texturelist", RMod_TextureList_f);
Cmd_AddCommand("mod_usetexture", RMod_BlockTextureColour_f);
#ifdef TERRAIN
Terr_Init();
#endif
}
void RMod_Shutdown (void)
@ -734,6 +739,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
TRACE(("RMod_LoadModel: md3\n"));
if (!Mod_LoadQ3Model (mod, buf))
continue;
Surf_BuildModelLightmaps(mod);
break;
#endif
@ -801,6 +807,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
TRACE(("RMod_LoadModel: q2/q3/raven/fusion bsp\n"));
if (!Mod_LoadQ2BrushModel (mod, buf))
continue;
Surf_BuildModelLightmaps(mod);
break;
#endif
#ifdef MAP_DOOM
@ -820,6 +827,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
TRACE(("RMod_LoadModel: hl/q1 bsp\n"));
if (!RMod_LoadBrushModel (mod, buf))
continue;
Surf_BuildModelLightmaps(mod);
break;
//Text based misc types.
@ -861,7 +869,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
}
#endif
Con_Printf(CON_WARNING "Unrecognised model format %i\n", LittleLong(*(unsigned *)buf));
Con_Printf(CON_WARNING "Unrecognised model format 0x%x (%c%c%c%c)\n", LittleLong(*(unsigned *)buf), ((char*)buf)[0], ((char*)buf)[1], ((char*)buf)[2], ((char*)buf)[3]);
continue;
}
@ -1236,7 +1244,7 @@ void RMod_LoadMiptex(texture_t *tx, miptex_t *mt, texnums_t *tn, int maps)
snprintf(altname, sizeof(altname)-1, "%s_bump", mt->name);
}
if (!TEXVALID(tn->bump) && loadmodel->fromgame != fg_halflife)// && gl_bump_fallbacks.ival)
if (!TEXVALID(tn->bump) && loadmodel->fromgame != fg_halflife && r_loadbumpmapping)// && gl_bump_fallbacks.ival)
{
//no mip levels here, would be absurd.
base = (qbyte *)(mt+1); //convert to greyscale.
@ -1794,9 +1802,9 @@ void RMod_LoadLighting (lump_t *l)
luxdata = Hunk_AllocName(samples*3, "lux data");
for (i = 0; i < samples; i++)
{
litdata[i*3+0] = 0.5f*255;
litdata[i*3+0] = 0.5f*255;
litdata[i*3+0] = 255;
luxdata[i*3+0] = 0.5f*255;
luxdata[i*3+1] = 0.5f*255;
luxdata[i*3+2] = 255;
}
}
#endif

View file

@ -305,6 +305,7 @@ typedef struct vbo_s
} vbo_t;
void GL_SelectVBO(int vbo);
void GL_SelectEBO(int vbo);
void GL_DeselectVAO(void);
typedef struct texture_s
{
@ -1019,10 +1020,12 @@ qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model);
// gl_heightmap.c
//
#ifdef TERRAIN
void Terr_Init(void);
void Terr_DrawTerrainModel (batch_t **batch, entity_t *e);
qboolean Terr_LoadTerrainModel (model_t *mod, void *buffer);
void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean lightmapreusable);
void *Mod_LoadTerrainInfo(model_t *mod, char *loadname); //call this after loading a bsp
qboolean Terrain_LocateSection(char *name, flocation_t *loc); //used on servers to generate sections for download.
qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, struct trace_s *trace);
unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org);
struct fragmentdecal_s;

View file

@ -102,6 +102,7 @@ texid_t scenepp_texture_warp;
texid_t scenepp_texture_edge;
texid_t scenepp_postproc_cube;
int scenepp_postproc_cube_size;
// KrimZon - init post processing - called in GL_CheckExtensions, when they're called
// I put it here so that only this file need be changed when messing with the post
@ -581,6 +582,9 @@ void R_RenderScene (void)
TRACE(("dbg: calling R_RenderDlights\n"));
R_RenderDlights ();
if (r_refdef.recurse)
RQ_RenderBatch();
else
RQ_RenderBatchClear();
cl_numvisedicts = tmpvisents;
@ -677,6 +681,7 @@ static entity_t *R_NearestPortal(plane_t *plane)
int i;
entity_t *best = NULL;
float dist, bestd = 0;
//for q3-compat, portals on world scan for a visedict to use for their view.
for (i = 0; i < cl_numvisedicts; i++)
{
if (cl_visedicts[i].rtype == RT_PORTALSURFACE)
@ -826,6 +831,15 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
// memset(newvis, 0xff, pvsbytes);
}
}
else if (batch->ent != &r_worldentity)
{
float d;
view = batch->ent;
d = DotProduct(r_refdef.vieworg, plane.normal) - plane.dist;
d-= 0.1; //nudge it past.
VectorAdd(r_refdef.vieworg, view->oldorigin, r_refdef.vieworg); //trivial offset for the warpzone.
VectorMA(r_refdef.vieworg, -d, plane.normal, r_refdef.pvsorigin); //clip the pvs origin to the plane.
}
else if (!(view = R_NearestPortal(&plane)) || VectorCompare(view->origin, view->oldorigin))
{
r_refdef.flipcull ^= true;
@ -1011,14 +1025,15 @@ void GLR_SetupFog (void)
}
#endif
void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth);
static void R_RenderMotionBlur(void)
{
int vwidth = 1, vheight = 1;
float vs, vt, cs, ct;
#ifdef warningmsg
#pragma warningmsg("backend fixme")
#endif
shader_t *shader;
#if !defined(ANDROID) && !defined(NACL)
//figure out the size of our texture.
if (gl_config.arb_texture_non_power_of_two)
{ //we can use any size, supposedly
vwidth = vid.pixelwidth;
@ -1032,21 +1047,6 @@ static void R_RenderMotionBlur(void)
vheight *= 2;
}
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
PPL_RevertToKnownState();
GL_LazyBind(0, GL_TEXTURE_2D, sceneblur_texture);
// go 2d
qglMatrixMode(GL_PROJECTION);
qglPushMatrix();
qglLoadIdentity ();
qglOrtho (0, vid.pixelwidth, 0, vid.pixelheight, -99999, 99999);
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
qglLoadIdentity ();
//blend the last frame onto the scene
//the maths is because our texture is over-sized (must be power of two)
cs = vs = (float)vid.pixelwidth / vwidth * 0.5;
@ -1054,34 +1054,28 @@ static void R_RenderMotionBlur(void)
vs *= gl_motionblurscale.value;
vt *= gl_motionblurscale.value;
qglDisable (GL_DEPTH_TEST);
GL_CullFace(0);
qglDisable (GL_ALPHA_TEST);
qglEnable(GL_BLEND);
qglColor4f(1, 1, 1, gl_motionblur.value);
qglBegin(GL_QUADS);
qglTexCoord2f(cs-vs, ct-vt);
qglVertex2f(0, 0);
qglTexCoord2f(cs+vs, ct-vt);
qglVertex2f(vid.pixelwidth, 0);
qglTexCoord2f(cs+vs, ct+vt);
qglVertex2f(vid.pixelwidth, vid.pixelheight);
qglTexCoord2f(cs-vs, ct+vt);
qglVertex2f(0, vid.pixelheight);
qglEnd();
qglMatrixMode(GL_PROJECTION);
qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
//render using our texture
shader = R_RegisterShader("postproc_motionblur",
"{\n"
"program default2d\n"
"{\n"
"map $sourcecolour\n"
"blendfunc blend\n"
"}\n"
"}\n"
);
GLBE_RenderToTexture(sceneblur_texture, r_nulltex, r_nulltex, false);
R2D_ImageColours(1, 1, 1, gl_motionblur.value);
R2D_Image(0, 0, vid.width, vid.height, cs-vs, ct+vt, cs+vs, ct-vt, shader);
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false);
//grab the current image so we can feed that back into the next frame.
GL_MTBind(0, GL_TEXTURE_2D, sceneblur_texture);
//copy the image into the texture so that we can play with it next frame too!
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#endif
PPL_RevertToKnownState();
}
/*FIXME: we could use geometry shaders to draw to all 6 faces at once*/
@ -1174,8 +1168,10 @@ qboolean R_RenderScene_Cubemap(void)
VectorCopy(r_refdef.viewangles, saveang);
saveang[2] = 0;
if (!TEXVALID(scenepp_postproc_cube))
if (!TEXVALID(scenepp_postproc_cube) || cmapsize != scenepp_postproc_cube_size)
{
if (TEXVALID(scenepp_postproc_cube))
GL_DestroyTexture(scenepp_postproc_cube);
scenepp_postproc_cube = GL_AllocNewTexture("***fish***", cmapsize, cmapsize, 0);
GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_postproc_cube);
@ -1185,10 +1181,14 @@ qboolean R_RenderScene_Cubemap(void)
qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
scenepp_postproc_cube_size = cmapsize;
}
r_refdef.vrect.width = cmapsize;
r_refdef.vrect.height = cmapsize;
vrect = r_refdef.vrect; //save off the old vrect
r_refdef.vrect.width = (cmapsize * vid.width) / vid.pixelwidth;
r_refdef.vrect.height = (cmapsize * vid.height) / vid.pixelheight;
r_refdef.vrect.x = 0;
r_refdef.vrect.y = prect.y;
@ -1223,6 +1223,8 @@ qboolean R_RenderScene_Cubemap(void)
qglCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, 0, 0, 0, vid.pixelheight - (prect.y + cmapsize), cmapsize, cmapsize);
}
r_refdef.vrect = vrect;
qglViewport (prect.x, vid.pixelheight - (prect.y+prect.height), prect.width, prect.height);
// go 2d
@ -1339,6 +1341,8 @@ void GLR_RenderView (void)
if (r_refdef.flags & Q2RDF_NOWORLDMODEL)
return;
GL_Set2D (false);
if (r_bloom.value)
R_BloomBlend();
@ -1348,7 +1352,6 @@ void GLR_RenderView (void)
{
if (scenepp_waterwarp)
{
GL_Set2D(false);
R2D_ScalePic(0, 0, vid.width, vid.height, scenepp_waterwarp);
}
}
@ -1363,7 +1366,6 @@ void GLR_RenderView (void)
shader_t *postproc = R_RegisterCustom(r_postprocshader.string, NULL, NULL);
if (postproc)
{
GL_Set2D(false);
R2D_ScalePic(0, 0, vid.width, vid.height, postproc);
}
}

View file

@ -178,12 +178,6 @@ void GLSCR_UpdateScreen (void)
GL_Set2D (false);
if (!noworld)
{
R2D_PolyBlend ();
R2D_BrightenScreen();
}
scr_con_forcedraw = false;
if (noworld)
{
@ -208,6 +202,8 @@ void GLSCR_UpdateScreen (void)
SCR_DrawCursor(0);
V_UpdatePalette (false);
R2D_BrightenScreen();
#if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame();
#endif

View file

@ -936,8 +936,6 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
break;
};
memset(prog->handle, 0, sizeof(*prog->handle)*PERMUTATIONS);
nummodifiers = 0;
for (end = strchr(name, '#'); end && *end; )
{
@ -965,6 +963,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
for (p = 0; p < PERMUTATIONS; p++)
{
memset(&prog->permu[p].handle, 0, sizeof(prog->permu[p].handle));
if (nopermutation & p)
{
continue;
@ -992,19 +991,19 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
#ifdef GLQUAKE
else if (qrenderer == QR_OPENGL)
{
if (prog->handle[p].glsl)
qglDeleteProgramObject_(prog->handle[p].glsl);
prog->handle[p].glsl = GLSlang_CreateProgram(name, (((p & PERMUTATION_SKELETAL) && ver < 120)?120:ver), permutationdefines, script, script, onefailed);
if (!prog->handle[p].glsl)
if (prog->permu[p].handle.glsl)
qglDeleteProgramObject_(prog->permu[p].handle.glsl);
prog->permu[p].handle.glsl = GLSlang_CreateProgram(name, (((p & PERMUTATION_SKELETAL) && ver < 120)?120:ver), permutationdefines, script, script, onefailed);
if (!prog->permu[p].handle.glsl)
onefailed = true;
if (!p && !prog->handle[p].glsl)
if (!p && !prog->permu[p].handle.glsl)
break;
}
#endif
#ifdef D3D9QUAKE
else if (qrenderer == QR_DIRECT3D9)
{
if (!D3D9Shader_CreateProgram(prog, p, permutationdefines, script, script))
if (!D3D9Shader_CreateProgram(prog, name, p, permutationdefines, script, script))
break;
}
#endif
@ -1041,7 +1040,7 @@ struct sbuiltin_s
char *body;
} sbuiltins[] =
{
#ifdef GLQUAKE
#if 0//def GLQUAKE
/*a quick note on glsl versions:
gl versioning started with 110
gles versioning started at 100 and only had a single one defined
@ -1293,162 +1292,6 @@ struct sbuiltin_s
"#endif\n"
},
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "rtlight",
/*
texture units:
s0=diffuse, s1=normal, s2=specular, s3=shadowmap
custom modifiers:
PCF(shadowmap)
CUBE(projected cubemap)
*/
"!!permu BUMP\n"
"!!permu SPECULAR\n"
"!!permu OFFSETMAPPING\n"
"!!permu SKELETAL\n"
"!!permu FOG\n"
"struct a2v {\n"
"float4 pos: POSITION;\n"
"float3 tc: TEXCOORD0;\n"
"float3 n: NORMAL0;\n"
"float3 s: TANGENT0;\n"
"float3 t: BINORMAL0;\n"
"};\n"
"struct v2f {\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float3 tc: TEXCOORD0;\n"
"float3 lpos: TEXCOORD1;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"float3 l_lightposition;\n"
"v2f main (a2v inp)\n"
"{\n"
" v2f outp;\n"
" outp.pos = mul(m_modelviewprojection, inp.pos);\n"
" outp.tc = inp.tc;\n"
"float3 lightminusvertex = l_lightposition - inp.pos.xyz;\n"
"outp.lpos.x = dot(lightminusvertex, inp.s.xyz);\n"
"outp.lpos.y = dot(lightminusvertex, inp.t.xyz);\n"
"outp.lpos.z = dot(lightminusvertex, inp.n.xyz);\n"
" return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"sampler s_t0;\n"
"sampler s_t1;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
" float3 col = l_lightcolour;\n"
" col *= max(1.0 - dot(inp.lpos, inp.lpos)/(l_lightradius*l_lightradius), 0.0);\n"
" float3 diff = tex2D(s_t0, inp.tc);\n"
" return float4(diff * col, 1);"
"}\n"
"#endif\n"
},
{QR_DIRECT3D9, 9, "defaultsky",
"struct a2v {\n"
"float4 pos: POSITION;\n"
"};\n"
"struct v2f {\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float3 vpos: TEXCOORD0;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"v2f main (a2v inp)\n"
"{\n"
" v2f outp;\n"
" outp.pos = mul(m_modelviewprojection, inp.pos);\n"
" outp.vpos = inp.pos;\n"
" return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float e_time;\n"
"float3 e_eyepos;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float3 l_lightposition;\n"
"sampler s_t0;\n" /*diffuse*/
"sampler s_t1;\n" /*normal*/
"sampler s_t2;\n" /*specular*/
"float4 main (v2f inp) : COLOR0\n"
"{\n"
" float2 tccoord;\n"
" float3 dir = inp.vpos - e_eyepos;\n"
" dir.z *= 3.0;\n"
" dir.xy /= 0.5*length(dir);\n"
" tccoord = (dir.xy + e_time*0.03125);\n"
" float4 solid = tex2D(s_t0, tccoord);\n"
" tccoord = (dir.xy + e_time*0.0625);\n"
" float4 clouds = tex2D(s_t1, tccoord);\n"
" return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n"
"}\n"
"#endif\n"
},
{QR_DIRECT3D9, 9, "defaultwarp",
"!!cvarf r_wateralpha\n"
"struct a2v {\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"struct v2f {\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"v2f main (a2v inp)\n"
"{\n"
" v2f outp;\n"
" outp.pos = mul(m_modelviewprojection, inp.pos);\n"
" outp.tc = inp.tc;\n"
" return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float cvar_r_wateralpha;\n"
"float e_time;\n"
"sampler s_t0;\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
" float2 ntc;\n"
" ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n"
" ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n"
" float3 ts = tex2D(s_t0, ntc).xyz;\n"
" return float4(ts, cvar_r_wateralpha);\n"
"}\n"
"#endif\n"
},
#endif
#include "r_bishaders.h"
{QR_NONE}
};
@ -1460,8 +1303,8 @@ void Shader_UnloadProg(program_t *prog)
int p;
for (p = 0; p < PERMUTATIONS; p++)
{
if (prog->handle[p].glsl)
qglDeleteProgramObject_(prog->handle[p].glsl);
if (prog->permu[p].handle.glsl)
qglDeleteProgramObject_(prog->permu[p].handle.glsl);
}
}
#endif
@ -1728,18 +1571,18 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
//figure out visible attributes
for (p = 0; p < PERMUTATIONS; p++)
{
if (!prog->handle[p].glsl)
if (!prog->permu[p].handle.glsl)
continue;
GLSlang_UseProgram(prog->handle[p].glsl);
GLSlang_UseProgram(prog->permu[p].handle.glsl);
for (i = 0; shader_attr_names[i].name; i++)
{
uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, shader_attr_names[i].name);
uniformloc = qglGetAttribLocationARB(prog->permu[p].handle.glsl, shader_attr_names[i].name);
if (uniformloc != -1)
{
if (shader_attr_names[i].ptype != uniformloc)
Con_Printf("Bad attribute\n");
else
prog->attrmask[p] |= 1u<<uniformloc;
prog->permu[p].attrmask |= 1u<<uniformloc;
}
}
}
@ -1750,11 +1593,11 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
found = false;
for (p = 0; p < PERMUTATIONS; p++)
{
if (!prog->handle[p].glsl)
if (!prog->permu[p].handle.glsl)
continue;
GLSlang_UseProgram(prog->handle[p].glsl);
GLSlang_UseProgram(prog->permu[p].handle.glsl);
uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, shader_unif_names[i].name);
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, shader_unif_names[i].name);
if (uniformloc != -1)
found = true;
@ -1764,7 +1607,7 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
break;
}
else
prog->parm[prog->numparams].handle[p] = uniformloc;
prog->permu[p].parm[prog->numparams] = uniformloc;
}
if (found)
{
@ -1797,16 +1640,16 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
found = false;
for (p = 0; p < PERMUTATIONS; p++)
{
if (!prog->handle[p].glsl)
if (!prog->permu[p].handle.glsl)
continue;
GL_SelectProgram(prog->handle[p].glsl);
uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, va("cvar_%s", tmpname));
GL_SelectProgram(prog->permu[p].handle.glsl);
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, va("cvar_%s", tmpname));
if (uniformloc != -1)
{
qglUniform1fARB(uniformloc, cvar->value);
found = true;
}
prog->parm[prog->numparams].handle[p] = uniformloc;
prog->permu[p].parm[prog->numparams] = uniformloc;
}
if (found)
prog->numparams++;
@ -1814,14 +1657,14 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
/*set texture uniforms*/
for (p = 0; p < PERMUTATIONS; p++)
{
if (!prog->handle[p].glsl)
if (!prog->permu[p].handle.glsl)
continue;
if (!(prog->attrmask[p] & (1u<<VATTR_VERTEX1))) //a shader kinda has to use one of these...
prog->attrmask[p] |= (1u<<VATTR_LEG_VERTEX);
GLSlang_UseProgram(prog->handle[p].glsl);
if (!(prog->permu[p].attrmask & (1u<<VATTR_VERTEX1))) //a shader kinda has to use one of these...
prog->permu[p].attrmask |= (1u<<VATTR_LEG_VERTEX);
GLSlang_UseProgram(prog->permu[p].handle.glsl);
for (i = 0; i < 8; i++)
{
uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, va("s_t%i", i));
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, va("s_t%i", i));
if (uniformloc != -1)
qglUniform1iARB(uniformloc, i);
}
@ -1846,20 +1689,20 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
cvar->flags |= CVAR_SHADERSYSTEM;
for (p = 0; p < PERMUTATIONS; p++)
{
if (!prog->handle[p].glsl)
if (!prog->permu[p].handle.hlsl.vert || !prog->permu[p].handle.hlsl.frag)
continue;
uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 1, va("cvar_%s", tmpname));
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 1, va("cvar_%s", tmpname));
if (uniformloc != -1)
{
vec4_t v = {cvar->value, 0, 0, 0};
IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->handle[0].hlsl.vert);
IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[p].handle.hlsl.vert);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, v, 1);
}
uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 2, va("cvar_%s", tmpname));
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 2, va("cvar_%s", tmpname));
if (uniformloc != -1)
{
vec4_t v = {cvar->value, 0, 0, 0};
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->handle[0].hlsl.vert);
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].handle.hlsl.frag);
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, v, 1);
}
}
@ -1869,10 +1712,10 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
found = false;
for (p = 0; p < PERMUTATIONS; p++)
{
uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 0, shader_unif_names[i].name);
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 0, shader_unif_names[i].name);
if (uniformloc != -1)
found = true;
prog->parm[prog->numparams].handle[p] = uniformloc;
prog->permu[p].parm[prog->numparams] = uniformloc;
}
if (found)
{
@ -1885,11 +1728,11 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
{
for (i = 0; i < 8; i++)
{
uniformloc = D3D9Shader_FindUniform(&prog->handle[p], 2, va("s_t%i", i));
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 2, va("s_t%i", i));
if (uniformloc != -1)
{
int v[4] = {i};
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->handle[0].hlsl.vert);
IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].handle.hlsl.frag);
IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1);
}
}
@ -2087,12 +1930,12 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p
prog->parm[prog->numparams].type = parmtype;
for (p = 0; p < PERMUTATIONS; p++)
{
if (!prog->handle[p].glsl)
if (!prog->permu[p].handle.glsl)
continue;
GLSlang_UseProgram(prog->handle[p].glsl);
GLSlang_UseProgram(prog->permu[p].handle.glsl);
uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, token);
prog->parm[prog->numparams].handle[p] = uniformloc;
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, token);
prog->permu[p].parm[prog->numparams] = uniformloc;
if (uniformloc != -1)
{
@ -2223,6 +2066,7 @@ static qboolean Shaderpass_MapGen (shader_t *shader, shaderpass_t *pass, char *t
{
pass->texgen = T_GEN_SPECULAR;
pass->tcgen = TC_GEN_BASE;
shader->flags |= SHADER_HASGLOSS;
}
else if (!Q_stricmp (tname, "$fullbright"))
{
@ -4010,7 +3854,15 @@ void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader)
}
if (!TEXVALID(shader->defaulttextures.specular))
{
extern cvar_t gl_specular;
if ((shader->flags & SHADER_HASGLOSS) && gl_specular.value && gl_load24bit.value)
{
if (!TEXVALID(tn->specular))
tn->specular = R_LoadHiResTexture(va("%s_gloss", shader->name), NULL, 0);
}
TEXASSIGN(shader->defaulttextures.specular, tn->specular);
}
if (!TEXVALID(shader->defaulttextures.fullbright))
TEXASSIGN(shader->defaulttextures.fullbright, tn->fullbright);
}
@ -4070,10 +3922,49 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args)
"{\n"
"map $fullbright\n"
"}\n"
"{\n"
"map $specular\n"
"}\n"
"}\n"
);
}
#endif
#if 0//def D3D9QUAKE
if (qrenderer == QR_DIRECT3D9)
{
if (!builtin)
builtin = (
"{\n"
"program defaultwall\n"
/*"param texture 0 tex_diffuse\n"
"param texture 1 tex_lightmap\n"
"param texture 2 tex_normalmap\n"
"param texture 3 tex_deluxmap\n"
"param texture 4 tex_fullbright\n"*/
"{\n"
"map $diffuse\n"
"}\n"
"{\n"
"map $lightmap\n"
"}\n"
"{\n"
"map $normalmap\n"
"}\n"
"{\n"
"map $deluxmap\n"
"}\n"
"{\n"
"map $fullbright\n"
"}\n"
"{\n"
"map $specular\n"
"}\n"
"}\n"
);
}
#endif
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
{
@ -4128,6 +4019,9 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args)
"{\n"
"map $fullbright\n"
"}\n"
"{\n"
"map $specular\n"
"}\n"
"}\n"
);
}
@ -4214,8 +4108,10 @@ char *Shader_DefaultBSPWater(char *shortname)
else if (r_fastturb.ival)
wstyle = 0;
#ifdef GLQUAKE
else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && r_waterstyle.ival>0 && !r_fastturb.ival && strncmp(shortname, "*lava", 5))
wstyle = r_waterstyle.ival; //r_waterstyle does not apply to lava, and requires glsl and stuff
else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && !strncmp(shortname, "*lava", 5))
wstyle = r_lavastyle.ival;
else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && strncmp(shortname, "*lava", 5))
wstyle = r_waterstyle.ival<1?1:r_waterstyle.ival;
#endif
else
wstyle = 1;
@ -4263,6 +4159,7 @@ char *Shader_DefaultBSPWater(char *shortname)
case 2: //refraction of the underwater surface, with a fresnel
return (
"{\n"
"sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/
"surfaceparm nodlight\n"
"{\n"
"map $refraction\n"
@ -4279,6 +4176,7 @@ char *Shader_DefaultBSPWater(char *shortname)
case 3: //reflections
return (
"{\n"
"sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/
"surfaceparm nodlight\n"
"{\n"
"map $refraction\n"
@ -4295,6 +4193,7 @@ char *Shader_DefaultBSPWater(char *shortname)
case 4: //ripples
return (
"{\n"
"sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/
"surfaceparm nodlight\n"
"{\n"
"map $refraction\n"
@ -4314,6 +4213,7 @@ char *Shader_DefaultBSPWater(char *shortname)
case 5: //ripples+reflections
return (
"{\n"
"sort blend\n" /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/
"surfaceparm nodlight\n"
"{\n"
"map $refraction\n"

View file

@ -429,6 +429,7 @@ static struct shadowmesh_s *SHM_FinishShadowMesh(dlight_t *dl)
case QR_OPENGL:
qglGenBuffersARB(2, sh_shmesh->vebo);
GL_DeselectVAO();
GL_SelectVBO(sh_shmesh->vebo[0]);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->verts) * sh_shmesh->numverts, sh_shmesh->verts, GL_STATIC_DRAW_ARB);
@ -1382,6 +1383,9 @@ static qboolean Sh_VisOverlaps(qbyte *v1, qbyte *v2)
return false;
}
#if 1
#define Sh_LeafInView Sh_VisOverlaps
#else
static qboolean Sh_LeafInView(qbyte *lightvis, qbyte *vvis)
{
int i;
@ -1409,6 +1413,7 @@ static qboolean Sh_LeafInView(qbyte *lightvis, qbyte *vvis)
return false;
}
#endif
typedef struct
{
@ -2181,7 +2186,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
else
lvis = NULL;
qglDisable(GL_SCISSOR_TEST);
Sh_ScissorOff();
Sh_GenShadowMap(l, lvis);
@ -2297,6 +2302,7 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e)
BE_SelectEntity(e);
GL_DeselectVAO();
GL_SelectVBO(0);
GL_SelectEBO(0);
qglEnableClientState(GL_VERTEX_ARRAY);
@ -2534,7 +2540,6 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
{
int sfrontfail;
int sbackfail;
qglEnable(GL_SCISSOR_TEST);
qglEnable(GL_STENCIL_TEST);
//FIXME: is it practical to test to see if scissors allow not clearing the stencil buffer?
@ -2650,7 +2655,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
//end stencil writing.
/*stencil writing probably changed the vertex pointer, and our backend caches it*/
PPL_RevertToKnownState();
// PPL_RevertToKnownState();
#if 0 //draw the stencil stuff to the red channel
qglMatrixMode(GL_PROJECTION);

View file

@ -319,6 +319,8 @@ extern cvar_t gl_workaround_ati_shadersource;
qboolean GL_CheckExtension(char *extname)
{
int i;
int len;
const char *foo;
cvar_t *v = Cvar_Get(va("gl_ext_%s", extname), "1", 0, "GL Extensions");
if (v && !v->ival)
{
@ -339,8 +341,18 @@ qboolean GL_CheckExtension(char *extname)
if (!gl_extensions)
return false;
//note that this is not actually correct...
return !!strstr(gl_extensions, extname);
//the list is space delimited. we cannot just strstr lest we find leading/trailing _FOO_.
len = strlen(extname);
for (foo = gl_extensions; *foo; )
{
if (!strncmp(foo, extname, len) && (foo[len] == ' ' || !foo[len]))
return true;
while(*foo && *foo != ' ')
foo++;
if (*foo == ' ')
foo++;
}
return false;
}
void APIENTRY GL_DrawRangeElementsEmul(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices)
@ -355,6 +367,10 @@ void APIENTRY GL_ClientStateStub(GLenum array)
{
}
void APIENTRY GL_ClientActiveTextureStub(GLenum texid)
{
}
#define getglcore getglfunction
#define getglext(name) getglfunction(name)
void GL_CheckExtensions (void *(*getglfunction) (char *name))
@ -388,7 +404,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
s++;
gl_minor_version = atoi(s);
}
gl_config.glversion = gl_major_version + (gl_minor_version/10.f);
//yes, I know, this can't cope with minor versions of 10+... I don't care yet.
gl_config.glversion += gl_major_version + (gl_minor_version/10.f);
/*gl3 adds glGetStringi instead, as core, with the old form require GL_ARB_compatibility*/
if (gl_major_version >= 3 && qglGetStringi) /*warning: wine fails to export qglGetStringi*/
@ -578,6 +595,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
}
}
/*
else if (GL_CheckExtension("GL_SGIS_multitexture") && !COM_CheckParm("-nomtex"))
{ //SGIS multitexture, limited in many ways but basic functionality is identical to ARB
Con_SafePrintf("Multitexture extensions found.\n");
@ -587,10 +605,17 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
mtexid0 = GL_TEXTURE0_SGIS;
}
*/
if (!qglClientActiveTextureARB)
{
qglClientActiveTextureARB = GL_ClientActiveTextureStub;
}
if ((gl_config.gles && gl_config.glversion >= 2) || GL_CheckExtension("GL_EXT_stencil_wrap"))
gl_config.ext_stencil_wrap = true;
qglStencilOpSeparateATI = NULL;
qglActiveStencilFaceEXT = NULL;
if (gl_config.gles && gl_config.glversion >= 2)
qglStencilOpSeparateATI = (void *) getglext("glStencilOpSeparate");
else if (GL_CheckExtension("GL_ATI_separate_stencil"))

View file

@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#include "glquake.h"
extern qboolean sys_glesversion;
extern int sys_glesversion;
static dllhandle_t *sys_gl_module = NULL;
@ -85,6 +85,9 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
Cons: GL_EndRendering call will not swap buffers. Buffers will be swapped on return to java.
*/
if (!sys_glesversion)
return false;
if (sys_glesversion >= 2)
Sys_Printf("Loading GLES2 driver\n");
else

View file

@ -1303,6 +1303,26 @@ void GLVID_Recenter_f(void)
//int nx = 0;
//int ny = 0;
#ifdef _MSC_VER
#define strtoull _strtoui64
#endif
if (Cmd_Argc() > 1)
sys_parentleft = atoi(Cmd_Argv(1));
if (Cmd_Argc() > 2)
sys_parenttop = atoi(Cmd_Argv(2));
if (Cmd_Argc() > 3)
sys_parentwidth = atoi(Cmd_Argv(3));
if (Cmd_Argc() > 4)
sys_parentheight = atoi(Cmd_Argv(4));
if (Cmd_Argc() > 5)
{
HWND newparent = (HWND)strtoull(Cmd_Argv(5), NULL, 16);
if (newparent != sys_parentwindow && mainwindow && modestate==MS_WINDOWED)
SetParent(mainwindow, sys_parentwindow);
sys_parentwindow = newparent;
}
if (sys_parentwindow && modestate==MS_WINDOWED)
{
WindowRect = centerrect(sys_parentleft, sys_parenttop, sys_parentwidth, sys_parentheight, vid_width.value, vid_height.value);
@ -1673,6 +1693,11 @@ BOOL bSetupPixelFormat(HDC hDC, rendererstate_t *info)
qDescribePixelFormat(hDC, pixelformat, sizeof(pfd), &pfd);
FixPaletteInDescriptor(hDC, &pfd);
gl_stencilbits = pfd.cStencilBits;
if ((pfd.dwFlags & PFD_GENERIC_FORMAT) && !(pfd.dwFlags & PFD_GENERIC_ACCELERATED))
{
Con_Printf(CON_WARNING "WARNING: software-rendered opengl context\nPlease install appropriate graphics drivers, or try d3d rendering instead\n");
}
return TRUE;
}
}
@ -1694,6 +1719,11 @@ BOOL bSetupPixelFormat(HDC hDC, rendererstate_t *info)
return FALSE;
}
if ((pfd.dwFlags & PFD_GENERIC_FORMAT) && !(pfd.dwFlags & PFD_GENERIC_ACCELERATED))
{
Con_Printf(CON_WARNING "WARNING: software-rendered opengl context\nPlease install appropriate graphics drivers, or try d3d rendering instead\n");
}
FixPaletteInDescriptor(hDC, &pfd);
return TRUE;
}
@ -1883,9 +1913,8 @@ LONG WINAPI GLMainWndProc (
if (wParam & MK_LBUTTON)
{
temp |= 1;
#ifdef NPFTE
if (sys_parentwindow && modestate == MS_WINDOWED)
SetFocus(hWnd);
#endif
}
if (wParam & MK_RBUTTON)

View file

@ -939,9 +939,11 @@ void LightFace (int surfnum)
temp[1] = DotProduct(wnorm, tvector);
temp[2] = DotProduct(wnorm, l.facenormal);
VectorNormalize(temp);
*dulout++ = -(temp[0]+1)*128 + 128;
*dulout++ = (temp[1]+1)*128 + 128;
*dulout++ = (temp[2]+1)*128 + 128;
temp[2] += 0.5;
VectorNormalize(temp);
*dulout++ = (-temp[0]+1)*128;
*dulout++ = (-temp[1]+1)*128;
*dulout++ = (-temp[2]+1)*128;
}
}
}

View file

@ -5,6 +5,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "altwater",
"!!cvarf r_glsl_turbscale\n"
//modifier: REFLECT (s_t2 is a reflection instead of diffusemap)
//modifier: STRENGTH (0.1 = fairly gentle, 0.2 = big waves)
//modifier: FRESNEL (5=water)
@ -12,6 +13,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//modifier: RIPPLEMAP (s_t3 contains a ripplemap
//modifier: TINT (some colour value)
"uniform float cvar_r_glsl_turbscale;\n"
"#ifndef FRESNEL\n"
"#define FRESNEL 5.0\n"
"#endif\n"
@ -74,9 +77,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//the fresnel term decides how transparent the water should be
"f = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL));\n"
"refr = texture2D(s_t0, stc + n.st*STRENGTH).rgb * TINT;\n"
"refr = texture2D(s_t0, stc + n.st*STRENGTH*cvar_r_glsl_turbscale).rgb * TINT;\n"
"#ifdef REFLECT\n"
"refl = texture2D(s_t2, stc - n.st*STRENGTH).rgb;\n"
"refl = texture2D(s_t2, stc - n.st*STRENGTH*cvar_r_glsl_turbscale).rgb;\n"
"#else\n"
"refl = texture2D(s_t2, ntc).xyz;\n"
"#endif\n"
@ -334,6 +337,44 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "default2d",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_projection, inp.pos);\n"
"outp.tc = inp.tc;\n"
"outp.vcol = inp.vcol;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture;\n"
"SamplerState SampleType;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return shaderTexture.Sample(SampleType, inp.tc) * inp.vcol;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultadditivesprite",
"!!permu FOG\n"
@ -431,6 +472,67 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultskin",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float3 normal: NORMAL;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float3 light: TEXCOORD1;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
//attribute vec2 v_texcoord;
//uniform vec3 e_light_dir;
//uniform vec3 e_light_mul;
//uniform vec3 e_light_ambient;
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.light = e_light_ambient + (dot(inp.normal,e_light_dir)*e_light_mul);\n"
"outp.tc = inp.tc.xy;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture[4]; //diffuse, lower, upper, fullbright\n"
"SamplerState SampleType;\n"
//uniform vec4 e_colourident;
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float4 col;\n"
"col = shaderTexture[0].Sample(SampleType, inp.tc);\n"
"#ifdef UPPER\n"
"float4 uc = shaderTexture[2].Sample(SampleType, inp.tc);\n"
"col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a);\n"
"#endif\n"
"#ifdef LOWER\n"
"float4 lc = shaderTexture[1].Sample(SampleType, inp.tc);\n"
"col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a);\n"
"#endif\n"
"col.rgb *= inp.light;\n"
"#ifdef FULLBRIGHT\n"
"float4 fb = shaderTexture[3].Sample(SampleType, inp.tc);\n"
"col.rgb = mix(col.rgb, fb.rgb, fb.a);\n"
"#endif\n"
"return col;\n"
// return fog4(col * e_colourident);
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultsky",
//regular sky shader for scrolling q1 skies
@ -465,6 +567,113 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultsky",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"};\n"
"struct v2f\n"
"{\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float3 vpos: TEXCOORD0;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
"outp.vpos = inp.pos;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float e_time;\n"
"float3 e_eyepos;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float3 l_lightposition;\n"
"sampler s_t0; /*diffuse*/\n"
"sampler s_t1; /*normal*/\n"
"sampler s_t2; /*specular*/\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
"float2 tccoord;\n"
"float3 dir = inp.vpos - e_eyepos;\n"
"dir.z *= 3.0;\n"
"dir.xy /= 0.5*length(dir);\n"
"tccoord = (dir.xy + e_time*0.03125);\n"
"float4 solid = tex2D(s_t0, tccoord);\n"
"tccoord = (dir.xy + e_time*0.0625);\n"
"float4 clouds = tex2D(s_t1, tccoord);\n"
"return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultsky",
//regular sky shader for scrolling q1 skies
//the sky surfaces are thrown through this as-is.
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float3 mpos: TEXCOORD1;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.mpos = outp.pos.xyz;\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture[2];\n"
"SamplerState SampleType;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float2 tccoord;\n"
"float3 dir = inp.mpos - v_eyepos;\n"
"dir.z *= 3.0;\n"
"dir.xy /= 0.5*length(dir);\n"
"tccoord = (dir.xy + e_time*0.03125);\n"
"float4 solid = shaderTexture[0].Sample(SampleType, tccoord);\n"
"tccoord = (dir.xy + e_time*0.0625);\n"
"float4 clouds = shaderTexture[1].Sample(SampleType, tccoord);\n"
"return (solid*(1.0-clouds.a)) + (clouds.a*clouds);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultsprite",
"!!permu FOG\n"
@ -496,6 +705,46 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultsprite",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.vcol = inp.vcol;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture;\n"
"SamplerState SampleType;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return shaderTexture.Sample(SampleType, inp.tc) * inp.vcol;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultwall",
"!!permu DELUXE\n"
@ -503,13 +752,15 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!permu FOG\n"
"!!permu LIGHTSTYLED\n"
"!!permu BUMP\n"
"!!permu SPECULAR\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvarf gl_specular\n"
//this is what normally draws all of your walls, even with rtlights disabled
//note that the '286' preset uses drawflat_walls instead.
"#include \"sys/fog.h\"\n"
"#if defined(OFFSETMAPPING)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR)\n"
"varying vec3 eyevector;\n"
"#endif\n"
@ -530,7 +781,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"attribute vec2 v_lmcoord3;\n"
"attribute vec2 v_lmcoord4;\n"
"#endif\n"
"#if defined(OFFSETMAPPING)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR)\n"
"uniform vec3 e_eyepos;\n"
"attribute vec3 v_normal;\n"
"attribute vec3 v_svector;\n"
@ -538,7 +789,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"void main ()\n"
"{\n"
"#if defined(OFFSETMAPPING)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR)\n"
"vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n"
"eyevector.x = -dot(eyeminusvertex, v_svector.xyz);\n"
"eyevector.y = dot(eyeminusvertex, v_tvector.xyz);\n"
@ -560,20 +811,23 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//samplers
"uniform sampler2D s_t0; //diffuse\n"
"uniform sampler2D s_t1; //lightmap0\n"
"#if defined(OFFSETMAPPING) || defined(DELUXE)\n"
"uniform sampler2D s_t2; //normal\n"
"#if defined(BUMP) && (defined(OFFSETMAPPING) || defined(DELUXE) || defined(SPECULAR))\n"
"uniform sampler2D s_t2; //normal.rgb+height.a\n"
"#endif\n"
"uniform sampler2D s_t3; //deluxe0\n"
"#ifdef FULLBRIGHT\n"
"uniform sampler2D s_t4; //fullbright\n"
"#endif\n"
"#ifdef SPECULAR\n"
"uniform sampler2D s_t5; //specular\n"
"#endif\n"
"#ifdef LIGHTSTYLED\n"
"uniform sampler2D s_t5; //lightmap1\n"
"uniform sampler2D s_t6; //lightmap2\n"
"uniform sampler2D s_t7; //lightmap3\n"
"uniform sampler2D s_t8; //deluxe1\n"
"uniform sampler2D s_t9; //deluxe2\n"
"uniform sampler2D s_t10; //deluxe3\n"
"uniform sampler2D s_t6; //lightmap1\n"
"uniform sampler2D s_t7; //lightmap2\n"
"uniform sampler2D s_t8; //lightmap3\n"
"uniform sampler2D s_t9; //deluxe1\n"
"uniform sampler2D s_t10; //deluxe2\n"
"uniform sampler2D s_t11; //deluxe3\n"
"#endif\n"
"#ifdef LIGHTSTYLED\n"
@ -582,6 +836,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"uniform vec4 e_lmscale;\n"
"#endif\n"
"uniform vec4 e_colourident;\n"
"#ifdef SPECULAR\n"
"uniform float cvar_gl_specular;\n"
"#endif\n"
"#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n"
"#endif\n"
@ -596,31 +853,53 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//yay, regular texture!
"gl_FragColor = texture2D(s_t0, tc);\n"
"#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR))\n"
"vec3 norm = normalize(texture2D(s_t2, tc).rgb - 0.5);\n"
"#elif defined(SPECULAR) || defined(DELUXE)\n"
"vec3 norm = vec3(0, 0, 1); //specular lighting expects this to exist.\n"
"#endif\n"
//modulate that by the lightmap(s) including deluxemap(s)
"#ifdef LIGHTSTYLED\n"
"vec4 lightmaps;\n"
"vec3 lightmaps;\n"
"#ifdef DELUXE\n"
"vec3 norm = texture2D(s_t2, tc).rgb;\n"
"lightmaps = texture2D(s_t1, lm ) * e_lmscale[0] * dot(norm, texture2D(s_t3, lm ).rgb);\n"
"lightmaps += texture2D(s_t5, lm2) * e_lmscale[1] * dot(norm, texture2D(s_t8, lm2).rgb);\n"
"lightmaps += texture2D(s_t6, lm3) * e_lmscale[2] * dot(norm, texture2D(s_t9, lm3).rgb);\n"
"lightmaps += texture2D(s_t7, lm4) * e_lmscale[3] * dot(norm, texture2D(s_t10,lm4).rgb);\n"
"lightmaps = texture2D(s_t1, lm ).rgb * e_lmscale[0].rgb * dot(norm, texture2D(s_t3, lm ).rgb);\n"
"lightmaps += texture2D(s_t6, lm2).rgb * e_lmscale[1].rgb * dot(norm, texture2D(s_t9, lm2).rgb);\n"
"lightmaps += texture2D(s_t7, lm3).rgb * e_lmscale[2].rgb * dot(norm, texture2D(s_t10, lm3).rgb);\n"
"lightmaps += texture2D(s_t8, lm4).rgb * e_lmscale[3].rgb * dot(norm, texture2D(s_t11,lm4).rgb);\n"
"#else\n"
"lightmaps = texture2D(s_t1, lm ) * e_lmscale[0];\n"
"lightmaps += texture2D(s_t5, lm2) * e_lmscale[1];\n"
"lightmaps += texture2D(s_t6, lm3) * e_lmscale[2];\n"
"lightmaps += texture2D(s_t7, lm4) * e_lmscale[3];\n"
"lightmaps = texture2D(s_t1, lm ).rgb * e_lmscale[0].rgb;\n"
"lightmaps += texture2D(s_t6, lm2).rgb * e_lmscale[1].rgb;\n"
"lightmaps += texture2D(s_t7, lm3).rgb * e_lmscale[2].rgb;\n"
"lightmaps += texture2D(s_t8, lm4).rgb * e_lmscale[3].rgb;\n"
"#endif\n"
"#else\n"
"vec3 lightmaps = (texture2D(s_t1, lm) * e_lmscale).rgb;\n"
//modulate by the bumpmap dot light
"#ifdef DELUXE\n"
"lightmaps *= dot(norm, 2.0*(texture2D(s_t3, lm).rgb-0.5));\n"
"#endif\n"
"#endif\n"
"#ifdef SPECULAR\n"
"vec4 specs = texture2D(s_t5, tc);\n"
"#ifdef DELUXE\n"
//not lightstyled...
"vec3 halfdir = normalize(normalize(eyevector) + 2.0*(texture2D(s_t3, lm).rgb-0.5)); //this norm should be the deluxemap info instead\n"
"#else\n"
"vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0)); //this norm should be the deluxemap info instead\n"
"#endif\n"
"float spec = pow(max(dot(halfdir, norm), 0.0), 32.0 * specs.a);\n"
"spec *= cvar_gl_specular;\n"
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
//As not all maps will have deluxemapping, and the double-cos from the light util makes everything far too dark anyway,
//we default to something that is not garish when the light value is directly infront of every single pixel.
//we can justify this difference due to the rtlight editor etc showing the *4.
"gl_FragColor.rgb += spec * specs.rgb;\n"
"#endif\n"
//now we have our diffuse+specular terms, modulate by lightmap values.
"gl_FragColor.rgb *= lightmaps.rgb;\n"
"#else\n"
"#ifdef DELUXE\n"
//gl_FragColor.rgb = dot(normalize(texture2D(s_t2, tc).rgb - 0.5), normalize(texture2D(s_t3, lm).rgb - 0.5));
//gl_FragColor.rgb = texture2D(s_t3, lm).rgb;
"gl_FragColor.rgb *= (texture2D(s_t1, lm) * e_lmscale).rgb * dot(normalize(texture2D(s_t2, tc).rgb-0.5), 2.0*(texture2D(s_t3, lm).rgb-0.5));\n"
"#else\n"
"gl_FragColor.rgb *= (texture2D(s_t1, lm) * e_lmscale).rgb;\n"
"#endif\n"
"#endif\n"
//add on the fullbright
"#ifdef FULLBRIGHT\n"
@ -638,6 +917,46 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultwall",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float2 lmtc: TEXCOORD1;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.lmtc = inp.tc.zw;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture[2];\n"
"SamplerState SampleType[2];\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return shaderTexture[0].Sample(SampleType[0], inp.tc) * shaderTexture[1].Sample(SampleType[1], inp.lmtc).bgra;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultwarp",
"!!cvarf r_wateralpha\n"
@ -671,6 +990,91 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultwarp",
"!!cvarf r_wateralpha\n"
"struct a2v {\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"struct v2f {\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
"outp.tc = inp.tc;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float cvar_r_wateralpha;\n"
"float e_time;\n"
"sampler s_t0;\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
"float2 ntc;\n"
"ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n"
"ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n"
"float3 ts = tex2D(s_t0, ntc).xyz;\n"
"return float4(ts, cvar_r_wateralpha);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultwarp",
"!!cvarf r_wateralpha\n"
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
// float cvar_r_wateralpha;
// float e_time;
// sampler s_t0;
"Texture2D shaderTexture;\n"
"SamplerState SampleType;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float2 ntc;\n"
"ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n"
"ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n"
"return shaderTexture.Sample(SampleType, ntc);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "drawflat_wall",
"!!cvarv r_floorcolor\n"
@ -705,6 +1109,49 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "drawflat_wall",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float3 norm: NORMAL;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float2 lmtc: TEXCOORD1;\n"
"float4 col: TEXCOORD2;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.lmtc = inp.tc.zw;\n"
"outp.col = ((inp.norm.z<0.73)?float4(0.5, 0.5, 0.5, 1):float4(0.25, 0.25, 0.5, 1));\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture;\n"
"SamplerState SampleType;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return inp.col * shaderTexture.Sample(SampleType, inp.lmtc);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "lpp_depthnorm",
"!!permu BUMP\n"
@ -1174,6 +1621,72 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "rtlight",
"!!permu BUMP\n"
"!!permu SPECULAR\n"
"!!permu OFFSETMAPPING\n"
"!!permu SKELETAL\n"
"!!permu FOG\n"
// texture units:
// s0=diffuse, s1=normal, s2=specular, s3=shadowmap
// custom modifiers:
// PCF(shadowmap)
// CUBE(projected cubemap)
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float3 tc: TEXCOORD0;\n"
"float3 n: NORMAL0;\n"
"float3 s: TANGENT0;\n"
"float3 t: BINORMAL0;\n"
"};\n"
"struct v2f\n"
"{\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float3 tc: TEXCOORD0;\n"
"float3 lpos: TEXCOORD1;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"float3 l_lightposition;\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
"outp.tc = inp.tc;\n"
"float3 lightminusvertex = l_lightposition - inp.pos.xyz;\n"
"outp.lpos.x = dot(lightminusvertex, inp.s.xyz);\n"
"outp.lpos.y = dot(lightminusvertex, inp.t.xyz);\n"
"outp.lpos.z = dot(lightminusvertex, inp.n.xyz);\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"sampler s_t0;\n"
"sampler s_t1;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
"float3 col = l_lightcolour;\n"
"col *= max(1.0 - dot(inp.lpos, inp.lpos)/(l_lightradius*l_lightradius), 0.0);\n"
"float3 diff = tex2D(s_t0, inp.tc);\n"
"return float4(diff * col, 1);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "underwaterwarp",
"!!cvarf r_waterwarp\n"
@ -1272,3 +1785,56 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "terrain",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float2 lmtc: TEXCOORD1;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.lmtc = inp.tc.zw;\n"
"outp.vcol = inp.vcol;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture[5];\n"
"SamplerState SampleType;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return float4(1,1,1,1);\n"
// float4 m = shaderTexture[4].Sample(SampleType, inp.tc) ;
// return inp.vcol*float4(m.aaa,1.0)*(
// shaderTexture[0].Sample(SampleType, inp.tc)*m.r
// + shaderTexture[1].Sample(SampleType, inp.tc)*m.g
// + shaderTexture[2].Sample(SampleType, inp.tc)*m.b
// + shaderTexture[3].Sample(SampleType, inp.tc)*1.0 - (m.r + m.g + m.b))
// ;
"}\n"
"#endif\n"
},
#endif

View file

@ -2,6 +2,7 @@
#define SHADER_H
typedef void (shader_gen_t)(char *name, shader_t*, const void *args);
#define SHADER_TMU_MAX 16
#define SHADER_PASS_MAX 8
#define SHADER_MAX_TC_MODS 8
#define SHADER_DEFORM_MAX 8
@ -347,7 +348,6 @@ typedef struct {
SP_CVAR3F,
SP_TEXTURE
} type;
unsigned int handle[PERMUTATIONS];
union
{
int ival;
@ -375,10 +375,13 @@ typedef struct programshared_s
{
int refs;
qboolean nofixedcompat;
union programhandle_u handle[PERMUTATIONS];
unsigned int attrmask[PERMUTATIONS];
int numparams;
shaderprogparm_t parm[SHADER_PROGPARMS_MAX];
struct {
union programhandle_u handle;
unsigned int attrmask;
unsigned int parm[SHADER_PROGPARMS_MAX];
} permu[PERMUTATIONS];
} program_t;
typedef struct {
@ -417,7 +420,7 @@ struct shader_s
SHADER_NOIMAGE = 1 << 8,
SHADER_ENTITY_MERGABLE = 1 << 9,
SHADER_VIDEOMAP = 1 << 10,
SHADER_DEPTHWRITE = 1 << 11,
SHADER_DEPTHWRITE = 1 << 11, //some pass already wrote depth. not used by the renderer.
SHADER_AGEN_PORTAL = 1 << 12,
SHADER_BLEND = 1 << 13, //blend or alphatest (not 100% opaque).
SHADER_NODRAW = 1 << 14, //parsed only to pee off developers when they forget it on no-pass shaders.
@ -430,6 +433,7 @@ struct shader_s
SHADER_HASREFRACT = 1 << 20, //says that we need to generate a refraction image first
SHADER_HASNORMALMAP = 1 << 21, //says that we need to load a normalmap texture
SHADER_HASRIPPLEMAP = 1 << 22, //water surface disturbances for water splashes
SHADER_HASGLOSS = 1 << 23, //
} flags;
program_t *prog;
@ -523,7 +527,7 @@ qboolean D3D9BE_LightCullModel(vec3_t org, model_t *model);
void D3D9BE_SelectEntity(entity_t *ent);
void D3D9BE_SelectDLight(dlight_t *dl, vec3_t colour);
qboolean D3D9Shader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag);
qboolean D3D9Shader_CreateProgram (program_t *prog, char *sname, int permu, char **precompilerconstants, char *vert, char *frag);
int D3D9Shader_FindUniform(union programhandle_u *h, int type, char *name);
void D3D9Shader_Init(void);
void D3D9BE_Reset(qboolean before);

Some files were not shown because too many files have changed in this diff Show more