From 25ef3f02dbec703baa8228320b907a3e2d56311e Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 24 Apr 2012 07:59:11 +0000 Subject: [PATCH] Couple of bugs fixed - other-player prediction, net_preparse crashes, q2 gamecode no longer crashes. Throttle getstatus requests (so we don't end up being used for udp escilation (d)dos attacks so usefully/expensively). Added cl_predict_players_frac. vanilla QW effectively had a hardcoded value of 0.5. Added simple fps preset menu, which keeps on appearing until they actually pick one. mwahaha. Quit menu offers to save settings if some CVAR_ARCHIVE cvar was changed. alias models do vertex blending on the gpu. GL renderer now uses vao when available. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4031 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 6 +- engine/client/cl_demo.c | 101 +++-- engine/client/cl_ents.c | 27 +- engine/client/cl_ignore.c | 2 +- engine/client/cl_input.c | 1 + engine/client/cl_main.c | 17 +- engine/client/cl_parse.c | 24 +- engine/client/cl_pred.c | 29 +- engine/client/client.h | 21 +- engine/client/in_generic.c | 7 +- engine/client/keys.c | 2 +- engine/client/m_download.c | 4 +- engine/client/m_items.c | 26 +- engine/client/m_mp3.c | 223 ++++++++-- engine/client/m_options.c | 62 ++- engine/client/m_script.c | 1 - engine/client/menu.c | 92 +++- engine/client/menu.h | 2 + engine/client/merged.h | 1 + engine/client/p_classic.c | 29 +- engine/client/p_script.c | 3 + engine/client/pr_csqc.c | 6 +- engine/client/r_part.c | 2 + engine/client/r_surf.c | 93 +++- engine/client/renderer.c | 14 +- engine/client/roq_read.c | 1 - engine/client/snd_dma.c | 4 +- engine/client/snd_mem.c | 4 +- engine/client/sys_droid.c | 4 + engine/client/sys_linux.c | 4 + engine/client/sys_morphos.c | 4 + engine/client/sys_sdl.c | 5 + engine/client/sys_win.c | 68 +++ engine/common/cmd.c | 2 + engine/common/com_mesh.c | 41 +- engine/common/common.c | 2 + engine/common/common.h | 16 +- engine/common/cvar.c | 22 +- engine/common/cvar.h | 3 + engine/common/fs.c | 15 +- engine/common/gl_q2bsp.c | 3 +- engine/common/log.c | 4 +- engine/common/mathlib.c | 2 +- engine/common/net_chan.c | 10 +- engine/common/net_wins.c | 259 +++++++++++- engine/common/plugin.c | 41 +- engine/common/qvm.c | 2 +- engine/common/sys.h | 1 + engine/common/translate.c | 3 +- engine/d3d/d3d_backend.c | 6 +- engine/dotnet2005/ftequake.sln | 38 ++ engine/dotnet2005/ftequake.vcproj | 172 +++++++- engine/gl/gl_backend.c | 678 ++++++++++++++++++------------ engine/gl/gl_bloom.c | 3 +- engine/gl/gl_draw.c | 6 +- engine/gl/gl_heightmap.c | 4 +- engine/gl/gl_hlmdl.c | 2 +- engine/gl/gl_model.c | 14 +- engine/gl/gl_model.h | 6 + engine/gl/gl_ngraph.c | 3 +- engine/gl/gl_rmain.c | 18 +- engine/gl/gl_rsurf.c | 29 +- engine/gl/gl_screen.c | 20 +- engine/gl/gl_shader.c | 127 +++--- engine/gl/gl_shadow.c | 22 +- engine/gl/gl_vidcommon.c | 166 +++++--- engine/gl/gl_vidnt.c | 172 +++++++- engine/gl/gl_warp.c | 4 +- engine/gl/glquake.h | 13 +- engine/gl/shader.h | 48 ++- engine/http/httpserver.c | 26 +- engine/nacl/gl_vidppapi.c | 30 +- engine/nacl/sys_ppapi.c | 39 +- engine/qclib/qccmain.c | 2 + engine/server/net_preparse.c | 25 +- engine/server/pr_cmds.c | 73 ++-- engine/server/sv_main.c | 51 ++- engine/server/sv_mvd.c | 8 +- engine/server/sv_rankin.c | 61 ++- engine/server/sv_sys_unix.c | 5 + engine/server/sv_sys_win.c | 4 + engine/server/sv_user.c | 16 +- engine/server/svq2_game.c | 1 + 83 files changed, 2430 insertions(+), 777 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index 51a6c199..fe7e7584 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -734,7 +734,7 @@ ifeq ($(shell echo $(FTE_TARGET)|grep -E -v "win(32|64)$$"),) GL_EXE_NAME=../fteglqw$(BITS).exe GLCL_EXE_NAME=../fteglqwcl$(BITS).exe GL_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 - GL_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) $(DX7SDK) + GL_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD GLB_DIR=gl_mgw$(BITS) GLCL_DIR=glcl_mgw$(BITS) @@ -750,7 +750,7 @@ ifeq ($(shell echo $(FTE_TARGET)|grep -E -v "win(32|64)$$"),) M_EXE_NAME=../fteqw$(BITS).exe MCL_EXE_NAME=../fteqwcl$(BITS).exe M_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 - M_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS) $(DX7SDK) + M_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS) $(DX7SDK) -DMULTITHREAD MB_DIR=m_mgw$(BITS) MCL_DIR=mcl_mgw$(BITS) @@ -758,7 +758,7 @@ ifeq ($(shell echo $(FTE_TARGET)|grep -E -v "win(32|64)$$"),) D3D_EXE_NAME=../fted3dqw$(BITS).exe D3DCL_EXE_NAME=../fted3dclqw$(BITS).exe D3D_LDFLAGS=$(IMAGELDFLAGS) -ldxguid -lws2_32 -lwinmm -lgdi32 -lole32 - D3D_CFLAGS=$(D3DCFLAGS) $(W32_CFLAGS) $(DX7SDK) + D3D_CFLAGS=$(D3DCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD D3DB_DIR=d3d_mgw$(BITS) D3DCL_DIR=d3dcl_mgw$(BITS) diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index e7fd26ea..dbff238b 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -253,8 +253,6 @@ int readdemobytes(int *readpos, void *data, int len) return 0; } - - if (*readpos+len > demobuffersize) { len = demobuffersize; @@ -1613,6 +1611,8 @@ void CL_Demo_ClientCommand(char *commandtext) char qtvhostname[1024]; char qtvrequestbuffer[4096]; int qtvrequestsize; +char qtvrequestcmdbuffer[4096]; +int qtvrequestcmdsize; vfsfile_t *qtvrequest; void CL_QTVPoll (void) @@ -1637,6 +1637,16 @@ void CL_QTVPoll (void) if (!qtvrequest) return; + if (qtvrequestcmdsize) + { + len = VFS_WRITE(qtvrequest, qtvrequestcmdbuffer, qtvrequestcmdsize); + if (len > 0) + { + memmove(qtvrequestcmdbuffer, qtvrequestcmdbuffer+len, qtvrequestcmdsize-len); + qtvrequestcmdsize -= len; + } + } + for(;;) { len = VFS_READ(qtvrequest, qtvrequestbuffer+qtvrequestsize, (sizeof(qtvrequestbuffer) - qtvrequestsize -1 > 0)?1:0); @@ -1645,7 +1655,13 @@ void CL_QTVPoll (void) qtvrequestsize += len; } qtvrequestbuffer[qtvrequestsize] = '\0'; - if (!qtvrequestsize) + + if (qtvrequestsize >= sizeof(qtvrequestbuffer) - 1) + { + Con_Printf("%i of %i...\n", qtvrequestsize, sizeof(qtvrequestbuffer)); + len = -1; + } + if (!qtvrequestsize && len == 0) return; //make sure it's a compleate chunk. @@ -1673,7 +1689,17 @@ void CL_QTVPoll (void) } } if (!tail) + { + if (len < 0) + { + Con_Printf("invalid QTV handshake\n"); + SCR_SetLoadingStage(LS_NONE); + VFS_CLOSE(qtvrequest); + qtvrequest = NULL; + qtvrequestsize = 0; + } return; + } s[1] = '\0'; //make sure its null terminated before the data payload s = qtvrequestbuffer; for (e = s; *e; ) @@ -1793,6 +1819,7 @@ void CL_QTVPoll (void) return; } + SCR_SetLoadingStage(LS_NONE); VFS_CLOSE(qtvrequest); qtvrequest = NULL; qtvrequestsize = 0; @@ -1979,6 +2006,8 @@ void CL_QTVPlay_f (void) char *connrequest; vfsfile_t *newf; char *host; + char msg[4096]; + int msglen=0; if (Cmd_Argc() < 2) { @@ -2022,54 +2051,62 @@ void CL_QTVPlay_f (void) if (qtvcl_forceversion1.ival) { - connrequest = "QTV\n" - "VERSION: 1.0\n"; + Q_snprintfz(msg+msglen, sizeof(msg)-msglen, + "QTV\n" + "VERSION: 1.0\n"); } else { - connrequest = "QTV\n" - "VERSION: 1.1\n"; + Q_snprintfz(msg+msglen, sizeof(msg)-msglen, + "QTV\n" + "VERSION: 1.1\n"); } - - VFS_WRITE(newf, connrequest, strlen(connrequest)); + msglen += strlen(msg+msglen); if (qtvcl_eztvextensions.ival) { - connrequest = "QTV_EZQUAKE_EXT: 3\n"; - VFS_WRITE(newf, connrequest, strlen(connrequest)); - connrequest = va("USERINFO: %s\n", cls.userinfo[0]); - VFS_WRITE(newf, connrequest, strlen(connrequest)); + raw = 0; + + Q_snprintfz(msg+msglen, sizeof(msg)-msglen, + "QTV_EZQUAKE_EXT: 3\n" + "USERINFO: %s\n", cls.userinfo[0]); + msglen += strlen(msg+msglen); } else if (raw) { - connrequest = "RAW: 1\n"; - VFS_WRITE(newf, connrequest, strlen(connrequest)); + Q_snprintfz(msg+msglen, sizeof(msg)-msglen, + "RAW: 1\n"); + msglen += strlen(msg+msglen); } if (host) { - connrequest = "SOURCE: "; - VFS_WRITE(newf, connrequest, strlen(connrequest)); - connrequest = host; - VFS_WRITE(newf, connrequest, strlen(connrequest)); - connrequest = "\n"; + Q_snprintfz(msg+msglen, sizeof(msg)-msglen, + "SOURCE: %s\n", host); + msglen += strlen(msg+msglen); } else { - connrequest = "SOURCELIST\n"; + Q_snprintfz(msg+msglen, sizeof(msg)-msglen, + "SOURCELIST\n"); + msglen += strlen(msg+msglen); } - VFS_WRITE(newf, connrequest, strlen(connrequest)); - connrequest = "\n"; - VFS_WRITE(newf, connrequest, strlen(connrequest)); + Q_snprintfz(msg+msglen, sizeof(msg)-msglen, + "\n"); + msglen += strlen(msg+msglen); if (raw) { + VFS_WRITE(newf, msg, msglen); CL_QTVPlay(newf, false); } else { if (qtvrequest) VFS_CLOSE(qtvrequest); + + memcpy(qtvrequestcmdbuffer, msg, msglen); + qtvrequestcmdsize = msglen; qtvrequest = newf; qtvrequestsize = 0; } @@ -2145,6 +2182,7 @@ void CL_FinishTimeDemo (void) { int frames; float time; + cvar_t *vw; cls.timedemo = false; @@ -2164,6 +2202,9 @@ void CL_FinishTimeDemo (void) cls.td_startframe = 0; TP_ExecTrigger ("f_timedemoend"); + + vw = Cvar_FindVar("vid_wait"); + Cvar_Set(vw, vw->string); } /* @@ -2175,6 +2216,7 @@ timedemo [demoname] */ void CL_TimeDemo_f (void) { + cvar_t *vw; if (Cmd_Argc() != 2) { Con_Printf ("timedemo : gets demo speeds\n"); @@ -2186,6 +2228,17 @@ void CL_TimeDemo_f (void) if (cls.state != ca_demostart) return; + vw = Cvar_FindVar("vid_wait"); + if (vw) + { + char *t = vw->string; + vw->string = "0"; + vw->value = 0; + Cvar_ForceCallback(vw); + vw->string = t; + } + +//read the initial frame so load times don't count as part of the time CL_ReadPackets(); // cls.td_starttime will be grabbed at the second frame of the demo, so diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index ddfe937b..c87f43dc 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "shader.h" extern cvar_t cl_predict_players; +extern cvar_t cl_predict_players_frac; extern cvar_t cl_lerp_players; extern cvar_t cl_solid_players; extern cvar_t cl_item_bobbing; @@ -3394,7 +3395,7 @@ guess_pm_type: CL_SetSolidEntities(); CL_SetSolidPlayers(); - CL_PredictUsercmd (0, state, &exact, &state->command); //uses player 0's maxspeed/grav... + CL_PredictUsercmd (0, num+1, state, &exact, &state->command); //uses player 0's maxspeed/grav... VectorCopy (exact.origin, state->predorigin); } else @@ -3529,6 +3530,7 @@ void CL_LinkPlayers (void) model_t *model; static int flickertime; static int flicker; + float predictmsmult = 1000*cl_predict_players_frac.value; if (!cl.worldmodel || cl.worldmodel->needload) return; @@ -3719,7 +3721,7 @@ void CL_LinkPlayers (void) VectorInverse(ent->axis[1]); // only predict half the move to minimize overruns - msec = 500*(playertime - state->state_time); + msec = predictmsmult*(playertime - state->state_time); if (pnum < cl.splitclients) { //this is a local player @@ -3742,14 +3744,14 @@ void CL_LinkPlayers (void) else { // predict players movement - if (msec > 255) - msec = 255; + if (msec > 250) + msec = 250; state->command.msec = msec; //Con_DPrintf ("predict: %i\n", msec); oldphysent = pmove.numphysent; CL_SetSolidPlayers (); - CL_PredictUsercmd (0, state, &exact, &state->command); //uses player 0's maxspeed/grav... + CL_PredictUsercmd (0, j+1, state, &exact, &state->command); //uses player 0's maxspeed/grav... pmove.numphysent = oldphysent; VectorCopy (exact.origin, ent->origin); } @@ -4021,6 +4023,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred) frame_t *frame; struct predicted_player *pplayer; extern cvar_t cl_nopred; + float predictmsmult = 1000*cl_predict_players_frac.value; int s; @@ -4028,7 +4031,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred) if (playertime > realtime) playertime = realtime; - if (cl_nopred.value || cls.demoplayback || cl.paused) + if (cl_nopred.value || /*cls.demoplayback ||*/ cl.paused) return; frame = &cl.frames[cl.parsecount&UPDATE_MASK]; @@ -4063,7 +4066,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred) if (s == cl.splitclients) { // only predict half the move to minimize overruns - msec = 500*(playertime - state->state_time); + msec = predictmsmult*(playertime - state->state_time); if (msec <= 0 || !cl_predict_players.ival || !dopred) @@ -4074,12 +4077,12 @@ void CL_SetUpPlayerPrediction(qboolean dopred) else { // predict players movement - if (msec > 255) - msec = 255; + if (msec > 250) + msec = 250; state->command.msec = msec; //Con_DPrintf ("predict: %i\n", msec); - CL_PredictUsercmd (0, state, &exact, &state->command); + CL_PredictUsercmd (0, j+1, state, &exact, &state->command); VectorCopy (exact.origin, pplayer->origin); } @@ -4119,8 +4122,8 @@ void CL_SetSolidPlayers (void) if (pmove.numphysent == MAX_PHYSENTS) //too many. return; - for (j=0, pplayer = predicted_players; j < MAX_CLIENTS; j++, pplayer++) { - + for (j=0, pplayer = predicted_players; j < MAX_CLIENTS; j++, pplayer++) + { if (!pplayer->active) continue; // not present this frame diff --git a/engine/client/cl_ignore.c b/engine/client/cl_ignore.c index d8cbd9ae..5922846d 100644 --- a/engine/client/cl_ignore.c +++ b/engine/client/cl_ignore.c @@ -648,7 +648,7 @@ void Ignore_Init(void) Cvar_Register (&ignore_mode, IGNOREGROUP); Cvar_Register (&ignore_opponents, IGNOREGROUP); - Cmd_AddCommand ("mute", VIgnore_f); + Cmd_AddCommand ("cl_voip_mute", VIgnore_f); Cmd_AddCommand ("ignore", Ignore_f); Cmd_AddCommand ("ignorelist", IgnoreList_f); Cmd_AddCommand ("unignore", Unignore_f); diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 38ff92d5..db3f8936 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1557,6 +1557,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) // CL_BaseMove (&independantphysics[plnum], plnum, (msecstouse - independantphysics[plnum].msec), wantfps); CL_AdjustAngles (plnum, frametime); IN_Move (mousemovements[plnum], plnum); + CL_ClampPitch(plnum); independantphysics[plnum].forwardmove += mousemovements[plnum][0]; independantphysics[plnum].sidemove += mousemovements[plnum][1]; independantphysics[plnum].upmove += mousemovements[plnum][2]; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 1143b0a4..ba842395 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -77,6 +77,7 @@ cvar_t m_side = CVARF("m_side","0.8", CVAR_ARCHIVE); cvar_t cl_lerp_players = CVARD("cl_lerp_players", "0", "Set this to make other players smoother, though it may increase effective latency. Affects only QuakeWorld."); cvar_t cl_predict_players = CVARD("cl_predict_players", "1", "Clear this cvar to see ents exactly how they are on the server."); +cvar_t cl_predict_players_frac = CVARD("cl_predict_players_frac", "0.9", "How much of other players to predict. Values less than 1 will help minimize overruns."); cvar_t cl_solid_players = CVAR("cl_solid_players", "1"); cvar_t cl_noblink = CVARD("cl_noblink", "0", "Disable the ^^b text blinking feature."); cvar_t cl_servername = CVAR("cl_servername", "none"); @@ -290,14 +291,14 @@ void CL_Quit_f (void) TP_ExecTrigger("f_quit"); Cbuf_Execute(); - +/* #ifndef CLIENTONLY if (!isDedicated) #endif { M_Menu_Quit_f (); return; - } + }*/ CL_Disconnect (); Sys_Quit (); } @@ -342,7 +343,7 @@ void CL_SupportedFTEExtensions(int *pext1, int *pext2) } #endif -char *CL_GUIDString(void) +char *CL_GUIDString(netadr_t adr) { static qbyte buf[2048]; static int buflen; @@ -381,7 +382,7 @@ char *CL_GUIDString(void) } } - NET_AdrToString(serveraddr, sizeof(serveraddr), cls.netchan.remote_address); + NET_AdrToString(serveraddr, sizeof(serveraddr), adr); blocks[0] = buf;lens[0] = buflen; blocks[1] = serveraddr;lens[1] = strlen(serveraddr); @@ -561,7 +562,7 @@ void CL_SendConnectPacket (int mtu, #endif cls.netchan.compress = false; - info = CL_GUIDString(); + info = CL_GUIDString(adr); if (info) Q_strncatz(data, va("0x%x \"%s\"\n", PROTOCOL_INFO_GUID, info), sizeof(data)); @@ -2027,7 +2028,7 @@ void CL_Startdemos_f (void) Con_Printf ("Max %i demos in demoloop\n", MAX_DEMOS); c = MAX_DEMOS; } - Con_Printf ("%i demo(s) in loop\n", c); + Con_DPrintf ("%i demo(s) in loop\n", c); for (i=1 ; i0; i--) - Con_Printf ("^Ue01e"); - Con_Printf ("^Ue01f"); - Con_Printf ("\n\n"); - } + 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); @@ -4541,7 +4535,7 @@ void CL_ParsePrint(char *msg, int level) int CL_PlayerColor(player_info_t *plr, qboolean *name_coloured) { char *t; - int c; + unsigned int c; *name_coloured = false; @@ -4711,7 +4705,7 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) if (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)) // for team chat don't highlight the name, just the brackets { // color is reset every printf so we're safe here - Q_strncatz(fullchatmessage, va("\1%s^%c(", name_coloured?"":"^m", c), sizeof(fullchatmessage)); + Q_strncatz(fullchatmessage, va("\1(%s^%c", name_coloured?"":"^m", c), sizeof(fullchatmessage)); Q_strncatz(fullchatmessage, va("%s%s^d", name_coloured?"^m":"", name), sizeof(fullchatmessage)); Q_strncatz(fullchatmessage, va("%s^%c)", name_coloured?"^m":"", c), sizeof(fullchatmessage)); } @@ -4859,7 +4853,7 @@ void CL_PrintStandardMessage(char *msg, int printlevel) c = '0' + CL_PlayerColor(p, &coloured); // print name - Q_strncatz(fullmessage, va("%s^%c%s^7", coloured?"\1":"", c, name), sizeof(fullmessage)); + Q_strncatz(fullmessage, va("%s^%c%s^7%s", coloured?"^m":"", c, name, coloured?"^m":""), sizeof(fullmessage)); break; } } diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 1eccd749..ca2f0ce0 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -357,7 +357,7 @@ void CL_NudgePosition (void) CL_PredictUsercmd ============== */ -void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, usercmd_t *u) +void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state_t *to, usercmd_t *u) { extern vec3_t player_mins; extern vec3_t player_maxs; @@ -370,8 +370,8 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user split = *u; split.msec /= 2; - CL_PredictUsercmd (pnum, from, &temp, &split); - CL_PredictUsercmd (pnum, &temp, to, &split); + CL_PredictUsercmd (pnum, entnum, from, &temp, &split); + CL_PredictUsercmd (pnum, entnum, &temp, to, &split); return; } @@ -393,7 +393,7 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user pmove.pm_type = from->pm_type; pmove.cmd = *u; - pmove.skipent = cl.playernum[pnum]+1; + pmove.skipent = entnum; movevars.entgravity = cl.entgravity[pnum]; movevars.maxspeed = cl.maxspeed[pnum]; @@ -641,7 +641,17 @@ void CL_CalcClientTime(void) float f; f = (demtime - olddemotime) / (nextdemotime - olddemotime); f = bound(0, f, 1); - cl.time = cl.servertime = cl.gametime*f + cl.oldgametime*(1-f); + cl.servertime = cl.gametime*f + cl.oldgametime*(1-f); + } + else if (0) + { + float f; + f = cl.gametime - cl.oldgametime; + if (f > 0.1) + f = 0.1; + f = (realtime - cl.gametimemark) / (f); + f = bound(0, f, 1); + cl.servertime = cl.gametime*f + cl.oldgametime*(1-f); } else { @@ -846,8 +856,7 @@ qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence) cmd.upmove = state->u.q1.movement[2]; oldphysent = pmove.numphysent; - pmove.skipent = state->number-1; - CL_PredictUsercmd (0, &start, &exact, &cmd); //uses player 0's maxspeed/grav... + CL_PredictUsercmd (0, state->number, &start, &exact, &cmd); //uses player 0's maxspeed/grav... pmove.numphysent = oldphysent; /*need to update the entity's angles and origin so the linkentities function puts it in the correct predicted place*/ @@ -1042,7 +1051,7 @@ fixedorg: VectorCopy (cl.simvel[pnum], from->playerstate[cl.playernum[pnum]].velocity); VectorCopy (cl.simorg[pnum], from->playerstate[cl.playernum[pnum]].origin); - CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]], &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); + CL_PredictUsercmd (pnum, cl.playernum[pnum]+1, &from->playerstate[cl.playernum[pnum]], &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); } else { @@ -1050,7 +1059,7 @@ fixedorg: cls.netchan.outgoing_sequence; i++) { to = &cl.frames[(cl.ackedinputsequence+i) & UPDATE_MASK]; - CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] + CL_PredictUsercmd (pnum, cl.playernum[pnum]+1, &from->playerstate[cl.playernum[pnum]] , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); if (to->senttime >= realtime) @@ -1065,7 +1074,7 @@ fixedorg: to = &ind; to->cmd[pnum] = independantphysics[pnum]; to->senttime = realtime; - CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] + CL_PredictUsercmd (pnum, cl.playernum[pnum]+1, &from->playerstate[cl.playernum[pnum]] , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); } cl.onground[pnum] = pmove.onground; diff --git a/engine/client/client.h b/engine/client/client.h index fcdab053..cc2ac050 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1088,7 +1088,7 @@ void CSQC_CvarChanged(cvar_t *var); // void CL_InitPrediction (void); void CL_PredictMove (void); -void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, usercmd_t *u); +void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state_t *to, usercmd_t *u); #ifdef Q2CLIENT void CLQ2_CheckPredictionError (void); #endif @@ -1295,3 +1295,22 @@ int qm_stricmp(char *s1, char *s2); void Stats_ParsePrintLine(char *line); void Stats_NewMap(void); +enum uploadfmt; +typedef struct +{ + void *(VARGS *createdecoder)(char *name); + void *(VARGS *decodeframe)(void *ctx, qboolean nosound, enum uploadfmt *fmt, int *width, int *height); + void (VARGS *doneframe)(void *ctx, void *img); + void (VARGS *shutdown)(void *ctx); + void (VARGS *rewind)(void *ctx); + + //these are any interactivity functions you might want... + void (VARGS *cursormove) (void *ctx, float posx, float posy); //pos is 0-1 + void (VARGS *key) (void *ctx, int code, int unicode, int event); + qboolean (VARGS *setsize) (void *ctx, int width, int height); + void (VARGS *getsize) (void *ctx, int *width, int *height); + void (VARGS *changestream) (void *ctx, char *streamname); +} media_decoder_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); diff --git a/engine/client/in_generic.c b/engine/client/in_generic.c index 8c94b776..63421435 100644 --- a/engine/client/in_generic.c +++ b/engine/client/in_generic.c @@ -82,13 +82,14 @@ void IN_Shutdown(void) void IN_ReInit() { - Cvar_Register (&m_simtouch, "input controls"); - Cvar_Register (&m_filter, "input controls"); - Cvar_Register (&m_strafeonright, "input controls"); } void IN_Init(void) { + Cvar_Register (&m_simtouch, "input controls"); + Cvar_Register (&m_filter, "input controls"); + Cvar_Register (&m_strafeonright, "input controls"); + IN_ReInit(); } diff --git a/engine/client/keys.c b/engine/client/keys.c index 5f5bc7f3..73d72878 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -1467,7 +1467,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down) if (key_dest == key_game) #endif { - if (Media_PlayingFullScreen()) + if (down && Media_PlayingFullScreen()) { Media_PlayFilm(""); return; diff --git a/engine/client/m_download.c b/engine/client/m_download.c index e5fff9f7..2a83f1a0 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -633,9 +633,9 @@ static void Menu_Download_Got(struct dl_download *dl) else destname = va("%s", p->dest); - if (!FS_Remove(destname, *p->gamedir?FS_ROOT:FS_GAME)) + if (FS_Remove(destname, *p->gamedir?FS_ROOT:FS_GAME)) Con_Printf("Deleted old %s\n", destname); - if (FS_Rename2(diskname, destname, FS_GAME, *p->gamedir?FS_ROOT:FS_GAME)) + if (!FS_Rename2(diskname, destname, FS_GAME, *p->gamedir?FS_ROOT:FS_GAME)) { Con_Printf("Couldn't rename %s to %s. Removed instead.\n", diskname, destname); FS_Remove (diskname, FS_GAME); diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 353ab73f..ac5fcec4 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -10,6 +10,7 @@ qboolean bindingactive; extern cvar_t cl_cursor; extern cvar_t cl_cursorsize; extern cvar_t cl_cursorbias; +extern cvar_t m_preset_chosen; menu_t *currentmenu; menu_t *firstmenu; @@ -1428,6 +1429,18 @@ menu_t *M_CreateMenu (int extrasize) return menu; } +menu_t *M_CreateMenuInfront (int extrasize) +{ + menu_t *menu; + menu = Z_Malloc(sizeof(menu_t)+extrasize); + menu->iszone=true; + menu->data = menu+1; + + M_AddMenuFront(menu); + menu->exclusive = false; + + return menu; +} void M_HideMenu (menu_t *menu) { if (menu == firstmenu) @@ -1470,7 +1483,10 @@ void M_RemoveMenu (menu_t *menu) menu->options=NULL; if (menu->tooltip) + { Z_Free(menu->tooltip); + menu->tooltip = NULL; + } if (menu->iszone) { @@ -1491,6 +1507,12 @@ void M_RemoveAllMenus (void) M_RemoveMenu(firstmenu); } +void M_MenuPop_f (void) +{ + if (!firstmenu) + return; + M_RemoveMenu(firstmenu); +} void DrawCursor(int prydoncursornum) @@ -1949,7 +1971,6 @@ void M_Menu_Main_f (void) mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 42, mainm->selecteditem->common.posy); } - return; } else if (mgt == MGT_HEXEN2) { @@ -2083,6 +2104,9 @@ void M_Menu_Main_f (void) mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 54, 32); } + + if (!m_preset_chosen.ival) + M_Menu_Preset_f(); } int MC_AddBulk(struct menu_s *menu, menubulk_t *bulk, int xstart, int xtextend, int y) diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index da5fb170..c7195590 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -956,29 +956,8 @@ static qboolean qAVIStartup(void) } #endif -#define MFT_CAPTURE 5 //fixme - -typedef enum { - MFT_NONE, - MFT_STATIC, //non-moving, PCX, no sound - MFT_ROQ, - MFT_AVI, - MFT_CIN, - MFT_OFSGECKO -} media_filmtype_t; - -struct cin_s { - - //these are the outputs (not always power of two!) - enum uploadfmt outtype; - int outwidth; - int outheight; - qbyte *outdata; - qbyte *outpalette; - int outunchanged; - qboolean ended; - - texid_t texture; +struct cin_s +{ qboolean (*decodeframe)(cin_t *cin, qboolean nosound); void (*doneframe)(cin_t *cin); @@ -992,9 +971,18 @@ struct cin_s { void (*changestream) (struct cin_s *cin, char *streamname); - // - media_filmtype_t filmtype; + //these are the outputs (not always power of two!) + enum uploadfmt outtype; + int outwidth; + int outheight; + qbyte *outdata; + qbyte *outpalette; + int outunchanged; + qboolean ended; + + texid_t texture; + #ifdef WINAVI struct { @@ -1027,6 +1015,14 @@ struct cin_s { } gecko; #endif +#ifdef PLUGINS + struct { + void *ctx; + struct plugin_s *plug; + media_decoder_funcs_t *funcs; /*fixme*/ + } plugin; +#endif + struct { qbyte *filmimage; //rgba int imagewidth; @@ -1191,7 +1187,6 @@ cin_t *Media_WinAvi_TryLoad(char *name) int filmheight; cin = Z_Malloc(sizeof(cin_t)); - cin->filmtype = MFT_AVI; cin->avi.pavi = pavi; if (qAVIFileGetStream(cin->avi.pavi, &cin->avi.pavivideo, streamtypeVIDEO, 0)) //retrieve video stream @@ -1289,7 +1284,6 @@ cin_t *Media_WinAvi_TryLoad(char *name) } } - cin->filmtype = MFT_AVI; cin->decodeframe = Media_WinAvi_DecodeFrame; cin->shutdown = Media_WINAVI_Shutdown; return cin; @@ -1306,6 +1300,165 @@ cin_t *Media_WinAvi_TryLoad(char *name) //AVI Support (windows) ////////////////////////////////////////////////////////////////////////////////// +//Plugin Support +#ifdef PLUGINS +media_decoder_funcs_t *plugindecodersfunc[8]; +struct plugin_s *plugindecodersplugin[8]; + +qboolean Media_RegisterDecoder(struct plugin_s *plug, media_decoder_funcs_t *funcs) +{ + int i; + for (i = 0; i < sizeof(plugindecodersfunc)/sizeof(plugindecodersfunc[0]); i++) + { + if (plugindecodersfunc[i] == NULL) + { + plugindecodersfunc[i] = funcs; + plugindecodersplugin[i] = plug; + return true; + } + } + return false; +} +qboolean Media_UnregisterDecoder(struct plugin_s *plug, media_decoder_funcs_t *funcs) +{ + int i; + for (i = 0; i < sizeof(plugindecodersfunc)/sizeof(plugindecodersfunc[0]); i++) + { + if (plugindecodersfunc[i] == funcs || (!funcs && plugindecodersplugin[i] == plug)) + { + plugindecodersfunc[i] = NULL; + plugindecodersplugin[i] = NULL; + return true; + } + } + return false; +} + +static qboolean Media_Plugin_DecodeFrame(cin_t *cin, qboolean nosound) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + cin->outdata = cin->plugin.funcs->decodeframe(cin->plugin.ctx, nosound, &cin->outtype, &cin->outwidth, &cin->outheight); + currentplug = oldplug; + + if (cin->outtype != TF_INVALID) + return true; + return false; +} +static void Media_Plugin_DoneFrame(cin_t *cin) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->doneframe) + cin->plugin.funcs->doneframe(cin->plugin.ctx, cin->outdata); + currentplug = oldplug; +} +static void Media_Plugin_Shutdown(cin_t *cin) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->shutdown) + cin->plugin.funcs->shutdown(cin->plugin.ctx); + currentplug = oldplug; +} +static void Media_Plugin_Rewind(cin_t *cin) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->rewind) + cin->plugin.funcs->rewind(cin->plugin.ctx); + currentplug = oldplug; +} + +void Media_Plugin_MoveCursor(cin_t *cin, float posx, float posy) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->cursormove) + cin->plugin.funcs->cursormove(cin->plugin.ctx, posx, posy); + currentplug = oldplug; +} +void Media_Plugin_KeyPress(cin_t *cin, int code, int unicode, int event) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->key) + cin->plugin.funcs->key(cin->plugin.ctx, code, unicode, event); + currentplug = oldplug; +} +qboolean Media_Plugin_SetSize(cin_t *cin, int width, int height) +{ + qboolean result = false; + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->setsize) + result = cin->plugin.funcs->setsize(cin->plugin.ctx, width, height); + currentplug = oldplug; + return result; +} +void Media_Plugin_GetSize(cin_t *cin, int *width, int *height) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->getsize) + cin->plugin.funcs->getsize(cin->plugin.ctx, width, height); + currentplug = oldplug; +} +void Media_Plugin_ChangeStream(cin_t *cin, char *streamname) +{ + struct plugin_s *oldplug = currentplug; + currentplug = cin->plugin.plug; + if (cin->plugin.funcs->changestream) + cin->plugin.funcs->changestream(cin->plugin.ctx, streamname); + currentplug = oldplug; +} + +cin_t *Media_Plugin_TryLoad(char *name) +{ + cin_t *cin; + int i; + media_decoder_funcs_t *funcs = NULL; + struct plugin_s *plug = NULL; + void *ctx = NULL; + struct plugin_s *oldplug = currentplug; + for (i = 0; i < sizeof(plugindecodersfunc)/sizeof(plugindecodersfunc[0]); i++) + { + funcs = plugindecodersfunc[i]; + if (funcs) + { + plug = plugindecodersplugin[i]; + currentplug = plug; + ctx = funcs->createdecoder(name); + if (ctx) + break; + } + } + currentplug = oldplug; + + if (ctx) + { + cin = Z_Malloc(sizeof(cin_t)); + cin->plugin.funcs = funcs; + cin->plugin.plug = plug; + cin->plugin.ctx = ctx; + cin->decodeframe = Media_Plugin_DecodeFrame; + cin->doneframe = Media_Plugin_DoneFrame; + cin->shutdown = Media_Plugin_Shutdown; + cin->rewind = Media_Plugin_Rewind; + + cin->cursormove = Media_Plugin_MoveCursor; + cin->key = Media_Plugin_KeyPress; + cin->setsize = Media_Plugin_SetSize; + cin->getsize = Media_Plugin_GetSize; + cin->changestream = Media_Plugin_ChangeStream; + + return cin; + } + return NULL; +} +#endif +//Plugin Support +////////////////////////////////////////////////////////////////////////////////// //Quake3 RoQ Support #ifdef Q3CLIENT @@ -1435,7 +1588,6 @@ cin_t *Media_RoQ_TryLoad(char *name) if ((roqfilm = roq_open(name))) { cin = Z_Malloc(sizeof(cin_t)); - cin->filmtype = MFT_ROQ; cin->decodeframe = Media_Roq_DecodeFrame; cin->shutdown = Media_Roq_Shutdown; @@ -1516,7 +1668,6 @@ cin_t *Media_Static_TryLoad(char *name) } cin = Z_Malloc(sizeof(cin_t)); - cin->filmtype = MFT_STATIC; cin->decodeframe = Media_Static_DecodeFrame; cin->shutdown = Media_Static_Shutdown; @@ -1570,7 +1721,6 @@ cin_t *Media_Cin_TryLoad(char *name) { cin = Z_Malloc(sizeof(cin_t)); cin->q2cin.cin = q2cin; - cin->filmtype = MFT_CIN; cin->decodeframe = Media_Cin_DecodeFrame; cin->shutdown = Media_Cin_Shutdown; @@ -1921,6 +2071,12 @@ cin_t *Media_StartCin(char *name) if (!cin) cin = Media_WinAvi_TryLoad(name); #endif +#ifdef PLUGINS + if (!cin) + cin = Media_Plugin_TryLoad(name); +#endif + if (!cin) + Con_Printf("Unable to decode \"%s\"\n", name); return cin; } @@ -2003,6 +2159,13 @@ qboolean Media_ShowFilm(void) Media_PlayFilm(""); else { + if (cin->cursormove) + { + extern int mousecursor_x, mousecursor_y; + cin->cursormove(cin, mousecursor_x/(float)vid.width, mousecursor_y/(float)vid.height); + } + +// GL_Set2D (false); R2D_ImageColours(1, 1, 1, 1); R2D_ScalePic(0, 0, vid.width, vid.height, videoshader); diff --git a/engine/client/m_options.c b/engine/client/m_options.c index bcb334d0..c06913f2 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -408,11 +408,11 @@ void M_Menu_Particles_f (void) const char *presetname[] = { - "286", - "Fast", - "Normal", - "Nice", - "Realtime", + "286", //everything turned off to make it as fast as possible, even if you're crippled without it + "Fast", //typical deathmatch settings. + "Normal", //some extra effects + "Nice", //potentially expensive, but not painful + "Realtime", //everything on NULL }; #define PRESET_NUM 5 @@ -422,6 +422,7 @@ const char *presetname[] = const char *presetexec[] = { // 286 options (also the first commands to be execed in the chain) + "m_preset_chosen 1;" "gl_texturemode nn;" "r_particlesystem null;" "r_stains 0;" @@ -429,41 +430,45 @@ const char *presetexec[] = "r_nolerp 1;" "r_nolightdir 1;" "r_dynamic 0;" + "gl_polyblend 0;" "gl_flashblend 0;" "gl_specular 0;" "r_loadlit 0;" "r_fastsky 1;" "r_shadow_realtime_dlight 0;" "r_shadow_realtime_world 0;" + "r_glsl_offsetmapping 0;" "gl_detail 0;" "gl_load24bit 0;" "r_replacemodels \"\";" "r_waterwarp 0;" "r_lightstylesmooth 0;" + "r_part_density 0.25;" , // fast options "gl_texturemode ln;" + "r_particlesystem classic;" + "r_drawflat 0;" + "r_nolerp 0;" + "gl_flashblend 1;" + "r_loadlit 1;" + "r_fastsky 0;" + "r_nolightdir 0;" + , // normal options #ifdef MINIMAL "r_particlesystem classic;" #else "r_particlesystem script;" "r_particledesc classic;" #endif - "r_drawflat 0;" - "r_nolerp 0;" - "gl_flashblend 1;" - "r_loadlit 1;" - "r_fastsky 0;" - "r_waterwarp -1;" - , // normal options - "r_particlesystem classic;" - "r_stains 0.75;" - "r_nolightdir 0;" + "r_part_density 1;" + "gl_polyblend 1;" "r_dynamic 1;" "gl_flashblend 0;" "gl_load24bit 1;" "r_replacemodels \"md3 md2\";" "r_waterwarp 1;" , // nice options + "r_stains 0.75;" "gl_texturemode ll;" #ifndef MINIMAL "r_particlesystem script;" @@ -478,6 +483,8 @@ const char *presetexec[] = "gl_texture_anisotropic_filtering 4;" , // realtime options // "r_bloom 1;" + "r_particledesc \"spikeset high tsshaft\";" + "r_glsl_offsetmapping 1;" "r_shadow_realtime_world 1;" "gl_texture_anisotropic_filtering 16;" }; @@ -499,11 +506,36 @@ static void ApplyPreset (int presetnum) } } +void M_Menu_Preset_f (void) +{ + menu_t *menu; + int y; + menubulk_t bulk[] = + { + MB_REDTEXT("Please Choose Preset", false), + MB_TEXT("\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", false), + MB_CONSOLECMD("286 untextured", "fps_preset 286;menupop\n", "Lacks textures, particles, pretty much everything."), + MB_CONSOLECMD("fast deathmatch", "fps_preset fast;menupop\n", "Fullscreen effects off to give consistant framerates"), + MB_CONSOLECMD("normal faithful", "fps_preset normal;menupop\n", "This is for Quake purists!"), + MB_CONSOLECMD("nice dynamic", "fps_preset nice;menupop\n", "For people who like nice things, but still want to actually play"), + MB_CONSOLECMD("realtime all on", "fps_preset realtime;menupop\n", "For people who value pretty over fast/smooth. Not viable for deathmatch."), + MB_END() + }; + menu = M_Options_Title(&y, 0); + MC_AddBulk(menu, bulk, 16, 216, y); +} + void FPS_Preset_f (void) { char *arg = Cmd_Argv(1); int i; + if (!*arg) + { + M_Menu_Preset_f(); + return; + } + for (i = 0; i < PRESET_NUM; i++) { if (!stricmp(presetname[i], arg)) diff --git a/engine/client/m_script.c b/engine/client/m_script.c index 79f011f8..7fe62d75 100644 --- a/engine/client/m_script.c +++ b/engine/client/m_script.c @@ -32,7 +32,6 @@ void M_MenuS_Clear_f (void) if (menu_script) { M_RemoveMenu(menu_script); - menu_script = NULL; } // Cvar_Set(menualias.name, ""); diff --git a/engine/client/menu.c b/engine/client/menu.c index 4a00e702..597f3f05 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -33,6 +33,7 @@ qboolean m_recursiveDraw; void M_ConfigureNetSubsystem(void); cvar_t m_helpismedia = SCVAR("m_helpismedia", "0"); +cvar_t m_preset_chosen = CVARF("m_preset_chosen", "0", CVAR_ARCHIVE); //============================================================================= /* Support Routines */ @@ -736,35 +737,93 @@ qboolean MC_Quit_Key (int key, menu_t *menu) return true; } -menu_t quitmenu; -void M_Menu_Quit_f (void) +void Cmd_WriteConfig_f(void); +qboolean MC_SaveQuit_Key (int key, menu_t *menu) { - int i; - - if (1) + switch (key) { + case K_ESCAPE: + M_RemoveMenu(menu); + break; + + case 'n': + case 'N': + M_RemoveMenu(menu); CL_Disconnect (); Sys_Quit (); + break; + + case 'Y': + case 'y': + M_RemoveMenu(menu); + Cmd_ExecuteString("cfg_save", RESTRICT_LOCAL); + CL_Disconnect (); + Sys_Quit (); + break; + + default: + break; } + + return true; +} + +void M_Menu_Quit_f (void) +{ + menu_t *quitmenu; + int i; + int mode; + + char *arg = Cmd_Argv(1); + if (!strcmp(arg, "force")) + mode = 0; + else if (!strcmp(arg, "save")) + mode = 2; + else if (!strcmp(arg, "prompt")) + mode = 1; else { + if (Cvar_UnsavedArchive()) + mode = 2; + else + mode = 0; + } + + switch(mode) + { + case 0: + CL_Disconnect (); + Sys_Quit (); + break; + case 2: key_dest = key_menu; m_state = m_complex; - M_RemoveMenu(&quitmenu); - memset(&quitmenu, 0, sizeof(quitmenu)); - M_AddMenuFront(&quitmenu); - quitmenu.exclusive = false; - quitmenu.key = MC_Quit_Key; + quitmenu = M_CreateMenuInfront(0); + quitmenu->key = MC_SaveQuit_Key; + + MC_AddWhiteText(quitmenu, 64, 84, "You have unsaved settings ", false); + MC_AddWhiteText(quitmenu, 64, 92, " Would you like to ", false); + MC_AddWhiteText(quitmenu, 64, 100, " save them now? ", false); + MC_AddWhiteText(quitmenu, 64, 108, " [Y/N/ESC] ", false); + MC_AddBox (quitmenu, 56, 76, 25, 4); + break; + case 1: + key_dest = key_menu; + m_state = m_complex; + + quitmenu = M_CreateMenuInfront(0); + quitmenu->key = MC_Quit_Key; i = rand()&7; - MC_AddWhiteText(&quitmenu, 64, 84, quitMessage[i*4+0], false); - MC_AddWhiteText(&quitmenu, 64, 92, quitMessage[i*4+1], false); - MC_AddWhiteText(&quitmenu, 64, 100, quitMessage[i*4+2], false); - MC_AddWhiteText(&quitmenu, 64, 108, quitMessage[i*4+3], false); - MC_AddBox (&quitmenu, 56, 76, 24, 4); + MC_AddWhiteText(quitmenu, 64, 84, quitMessage[i*4+0], false); + MC_AddWhiteText(quitmenu, 64, 92, quitMessage[i*4+1], false); + MC_AddWhiteText(quitmenu, 64, 100, quitMessage[i*4+2], false); + MC_AddWhiteText(quitmenu, 64, 108, quitMessage[i*4+3], false); + MC_AddBox (quitmenu, 56, 76, 24, 4); + break; } } @@ -942,6 +1001,7 @@ void M_Reinit(void) } void FPS_Preset_f(void); +void M_MenuPop_f(void); //menu.dat is loaded later... after the video and everything is up. void M_Init (void) @@ -950,7 +1010,9 @@ void M_Init (void) Cmd_AddCommand("togglemenu", M_ToggleMenu_f); Cmd_AddCommand("closemenu", M_CloseMenu_f); Cmd_AddCommand("fps_preset", FPS_Preset_f); + Cmd_AddCommand("menupop", M_MenuPop_f); + Cvar_Register(&m_preset_chosen, "Menu thingumiebobs"); Cvar_Register(&m_helpismedia, "Menu thingumiebobs"); Media_Init(); diff --git a/engine/client/menu.h b/engine/client/menu.h index 734011dd..99141eeb 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -355,6 +355,7 @@ int MC_AddBulk(struct menu_s *menu, menubulk_t *bulk, int xstart, int xtextend, menu_t *M_Options_Title(int *y, int infosize); /*Create a menu with the default options titlebar*/ menu_t *M_CreateMenu (int extrasize); +menu_t *M_CreateMenuInfront (int extrasize); void M_AddMenu (menu_t *menu); void M_AddMenuFront (menu_t *menu); void M_HideMenu (menu_t *menu); @@ -378,6 +379,7 @@ void M_Menu_Main_f (void); void M_Menu_Video_f (void); void M_Menu_Help_f (void); void M_Menu_Quit_f (void); + void M_Menu_Preset_f (void); void M_Menu_LanConfig_f (void); void M_Menu_GameOptions_f (void); void M_Menu_Search_f (void); diff --git a/engine/client/merged.h b/engine/client/merged.h index 7b5c79a0..cf89acf7 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -192,6 +192,7 @@ typedef enum uploadfmt TF_RGBA32, /*rgba byte order*/ TF_BGRA32, /*bgra byte order*/ TF_RGBX32, /*rgb byte order, with extra wasted byte after blue*/ + TF_BGRX32, /*rgb byte order, with extra wasted byte after blue*/ TF_RGB24, /*bgr byte order, no alpha channel nor pad, and top down*/ TF_BGR24_FLIP, /*bgr byte order, no alpha channel nor pad, and bottom up*/ TF_SOLID8, /*8bit quake-palette image*/ diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index 3315cb4d..a6033f41 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -77,6 +77,7 @@ typedef struct cparticle_s #define ABSOLUTE_MAX_PARTICLES 8192 static int r_numparticles; static cparticle_t *particles, *active_particles, *free_particles; +extern cvar_t r_part_density; extern qbyte default_quakepal[]; /*for ramps more than anything else*/ static int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; @@ -432,7 +433,7 @@ static void PClassic_DrawParticles(void) #ifdef POLYS if (cl_numstrisvert+3 > cl_maxstrisvert) { - cl_maxstrisvert+=64*3; + cl_maxstrisvert+=1024*3; cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert); cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert); cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert); @@ -456,7 +457,7 @@ static void PClassic_DrawParticles(void) if (cl_numstrisidx+3 > cl_maxstrisidx) { - cl_maxstrisidx += 64*3; + cl_maxstrisidx += 1024*3; cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx); } cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - scenetri->firstvert) + 0; @@ -559,8 +560,11 @@ static void Classic_ParticleExplosion (vec3_t org) { int i, j; cparticle_t *p; + int count; + + count = 1024 * r_part_density.value; - for (i = 0; i < 1024; i++) + for (i = 0; i < count; i++) { if (!free_particles) return; @@ -597,8 +601,11 @@ static void Classic_BlobExplosion (vec3_t org) { int i, j; cparticle_t *p; + int count; + + count = 1024 * r_part_density.value; - for (i = 0; i < 1024; i++) + for (i = 0; i < count; i++) { if (!free_particles) return; @@ -642,6 +649,8 @@ static void Classic_RunParticleEffect (vec3_t org, vec3_t dir, int color, int co scale = (count > 130) ? 3 : (count > 20) ? 2 : 1; + count *= r_part_density.value; + for (i = 0; i < count; i++) { if (!free_particles) @@ -709,11 +718,15 @@ static void Classic_TeleportSplash (vec3_t org) float vel; vec3_t dir; - for (i = -16; i < 16; i += 4) + int st = 4 / r_part_density.value; + if (st == 0) + st = 1; + + for (i = -16; i < 16; i += st) { - for (j = -16; j < 16; j += 4) + for (j = -16; j < 16; j += st) { - for (k = -24; k < 32; k += 4) + for (k = -24; k < 32; k += st) { if (!free_particles) return; @@ -770,6 +783,8 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef scale = 3; break; } + scale /= r_part_density.value; + VectorScale (dir, scale, dir); len /= scale; diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 5aa14ed1..b97dbd98 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -335,6 +335,7 @@ extern cvar_t r_part_sparks_trifan; extern cvar_t r_part_sparks_textured; extern cvar_t r_part_beams; extern cvar_t r_part_contentswitch; +extern cvar_t r_part_density; static float particletime; @@ -3072,6 +3073,8 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, if (ts) pcount += ts->state2.emittime; + pcount *= r_part_density.value; + switch (ptype->spawnmode) { case SM_UNICIRCLE: diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 818c0026..a50ccc1c 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3947,9 +3947,9 @@ static void QCBUILTIN PF_getentity(progfuncs_t *prinst, struct globalvars_s *pr_ #if 1 -static void QCBUILTIN PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ -} +//static void QCBUILTIN PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals) +//{ +//} #else packet_entities_t *CL_ProcessPacketEntities(float *servertime, qboolean nolerp); static void QCBUILTIN PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/client/r_part.c b/engine/client/r_part.c index 249a4d85..483ae9fd 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -137,6 +137,7 @@ cvar_t r_part_sparks_trifan = CVAR("r_part_sparks_trifan", "1"); cvar_t r_part_sparks_textured = CVAR("r_part_sparks_textured", "1"); cvar_t r_part_beams = CVAR("r_part_beams", "1"); cvar_t r_part_contentswitch = CVARFD("r_part_contentswitch", "1", CVAR_ARCHIVE, "Enable particle effects to change based on content (ex. water)."); +cvar_t r_part_density = CVAR("r_part_density", "1"); particleengine_t *pe; @@ -161,6 +162,7 @@ void P_InitParticleSystem(void) Cvar_Register(&r_part_sparks_textured, particlecvargroupname); Cvar_Register(&r_part_beams, particlecvargroupname); Cvar_Register(&r_part_contentswitch, particlecvargroupname); + Cvar_Register(&r_part_density, particlecvargroupname); Cvar_Register (&gl_part_flame, particlecvargroupname); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 8acfdfb2..0abb2085 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -1640,7 +1640,7 @@ static void Surf_LeafWorldNode (void) // if (!r_nocull->value) { - for (i=0,clipplane=frustum ; i<5 ; i++,clipplane++) + for (i=0,clipplane=frustum ; iminmaxs, pleaf->minmaxs+3, clipplane); if (clipped == 2) @@ -1653,7 +1653,7 @@ static void Surf_LeafWorldNode (void) } } - if (i != 4) + if (i != FRUSTUMPLANES) { continue; } @@ -1699,6 +1699,92 @@ static void Surf_LeafWorldNode (void) } } } + +static void Surf_RecursiveQ3WorldNode (mnode_t *node, unsigned int clipflags) +{ + int c, side, clipped; + mplane_t *plane, *clipplane; + msurface_t *surf, **mark; + mleaf_t *pleaf; + double dot; + +start: + + if (node->visframe != r_visframecount) + return; + + for (c = 0, clipplane = frustum; c < FRUSTUMPLANES; c++, clipplane++) + { + if (!(clipflags & (1 << c))) + continue; // don't need to clip against it + + clipped = BOX_ON_PLANE_SIDE (node->minmaxs, node->minmaxs + 3, clipplane); + if (clipped == 2) + return; + else if (clipped == 1) + clipflags -= (1<contents != -1) + { + pleaf = (mleaf_t *)node; + + if (! (areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) ) + return; // not visible + + mark = pleaf->firstmarksurface; + for (c = pleaf->nummarksurfaces; c; c--) + { + surf = *mark++; + if (surf->visframe == r_framecount) + continue; + surf->visframe = r_framecount; + +// if (((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK))) +// continue; // wrong side + + surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh; + } + return; + } + +// node is just a decision point, so go down the apropriate sides + +// find which side of the node we are on + plane = node->plane; + + switch (plane->type) + { + case PLANE_X: + dot = modelorg[0] - plane->dist; + break; + case PLANE_Y: + dot = modelorg[1] - plane->dist; + break; + case PLANE_Z: + dot = modelorg[2] - plane->dist; + break; + default: + dot = DotProduct (modelorg, plane->normal) - plane->dist; + break; + } + + if (dot >= 0) + side = 0; + else + side = 1; + +// recurse down the children, front side first + Surf_RecursiveQ3WorldNode (node->children[side], clipflags); + +// q3 nodes contain no drawables + +// recurse down the back side + //GLR_RecursiveWorldNode (node->children[!side], clipflags); + node = node->children[!side]; + goto start; +} #endif static void Surf_CleanChains(void) @@ -2076,7 +2162,8 @@ void Surf_DrawWorld (void) if (currententity->model->fromgame == fg_quake3) { vis = R_MarkLeaves_Q3 (); - Surf_LeafWorldNode (); + Surf_RecursiveQ3WorldNode (cl.worldmodel->nodes, (1<>3] & (1<<(cluster&7))) { +#if 1 + for (node = (mnode_t*)leaf; node; node = node->parent) + { + if (node->visframe == r_visframecount) + break; + node->visframe = r_visframecount; + } +#else leaf->visframe = r_visframecount; leaf->vischain = r_vischain; r_vischain = leaf; +#endif } } } diff --git a/engine/client/roq_read.c b/engine/client/roq_read.c index 884071b1..6a6c40e9 100644 --- a/engine/client/roq_read.c +++ b/engine/client/roq_read.c @@ -88,7 +88,6 @@ int max_frame; head3 = get_word(fp); if(head1 != 0x1084 && head2 != 0xffffffff && head3 != 0x1e) { - Con_Printf("Not an RoQ file.\n"); return 1; } diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 7b2a69c1..776cb49f 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -2016,7 +2016,6 @@ void S_ExtraUpdate (void) if (snd_noextraupdate.ival) return; // don't pollute timings - S_LockMixer(); for (sc = sndcardinfo; sc; sc = sc->next) { if (sc->selfpainting) @@ -2028,9 +2027,10 @@ void S_ExtraUpdate (void) continue; } + S_LockMixer(); S_Update_(sc); + S_UnlockMixer(); } - S_UnlockMixer(); } diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index 94153fa7..5c859cf5 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "winquake.h" -#include "errno.h" int cache_full_cycle; @@ -796,6 +795,7 @@ qboolean S_LoadSound (sfx_t *s) name = unixname; #endif + if ((f = fopen(name, "rb"))) { com_filesize = COM_filelength(f); @@ -803,7 +803,7 @@ qboolean S_LoadSound (sfx_t *s) result = fread(data, 1, com_filesize, f); //do something with result if (result != com_filesize) - Con_SafePrintf("S_LoadSound() fread: Filename: %s, expected %i, result was %u (%s)\n",name,com_filesize,(unsigned int)result,strerror(errno)); + Con_SafePrintf("S_LoadSound() fread: Filename: %s, expected %i, result was %u\n",name,com_filesize,(unsigned int)result); fclose(f); } diff --git a/engine/client/sys_droid.c b/engine/client/sys_droid.c index c3d5f870..10b98bed 100644 --- a/engine/client/sys_droid.c +++ b/engine/client/sys_droid.c @@ -225,6 +225,10 @@ qboolean Sys_remove (char *path) { return !unlink(path); } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return !rename(oldfname, newfname); +} void Sys_SendKeyEvents(void) { } diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index dde2438f..fda75b54 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -286,6 +286,10 @@ qboolean Sys_remove (char *path) { return system(va("rm \"%s\"", path)); } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return !rename(oldfname, newfname); +} int Sys_FileOpenRead (char *path, int *handle) { diff --git a/engine/client/sys_morphos.c b/engine/client/sys_morphos.c index 354a600b..590841f6 100755 --- a/engine/client/sys_morphos.c +++ b/engine/client/sys_morphos.c @@ -294,6 +294,10 @@ qboolean Sys_remove(char *path) return DeleteFile(path); } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return !rename(oldfname, newfname); +} /* Quake 2 stuff */ static void *gamefile; diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index c38c45e1..c3be63fa 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -126,6 +126,11 @@ qboolean Sys_remove (char *path) return true; } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return !rename(oldfname, newfname); +} + //someone used the 'quit' command void Sys_Quit (void) { diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 4001b5d3..03582adb 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -356,6 +356,23 @@ typedef BOOL (WINAPI *MINIDUMPWRITEDUMP) ( PMINIDUMP_CALLBACK_INFORMATION CallbackParam ); +#if 0 +#include "glquake.h" +#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_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#endif + DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exceptionInfo) { char dumpPath[1024]; @@ -367,6 +384,52 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception HMODULE hKernel; BOOL (WINAPI *pIsDebuggerPresent)(void); +#if 0 + 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") + + 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); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &rval); + glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &ptr); + Sys_Printf("GL_TEXTURE_COORD_ARRAY: %s %i:%p\n", 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); + } +#endif + hKernel = LoadLibrary ("kernel32"); pIsDebuggerPresent = (void*)GetProcAddress(hKernel, "IsDebuggerPresent"); @@ -535,6 +598,11 @@ qboolean Sys_remove (char *path) return true; } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return !rename(oldfname, newfname); +} + int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm) { HANDLE r; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 159feb0d..87022da2 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -2822,6 +2822,8 @@ void Cmd_WriteConfig_f(void) VFS_CLOSE(f); FS_FlushFSHash(); + + Cvar_Saved(); } void Cmd_Reset_f(void) diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 1537aece..a57e167b 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1119,7 +1119,8 @@ struct int bonecount; #endif - vecV_t *acoords; + vecV_t *acoords1; + vecV_t *acoords2; vec3_t *anorm; vec3_t *anorms; vec3_t *anormt; @@ -1437,6 +1438,7 @@ void Alias_FlushCache(void) qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, entity_t *e, qboolean usebones) { + extern cvar_t r_nolerp; galiasgroup_t *g1, *g2; int frame1; @@ -1484,7 +1486,8 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent if (meshcache.surfnum == inf->shares_verts && meshcache.ent == e) { - mesh->xyz_array = meshcache.acoords; + mesh->xyz_array = meshcache.acoords1; + mesh->xyz2_array = meshcache.acoords2; mesh->normals_array = meshcache.anorm; mesh->snormals_array = meshcache.anorms; mesh->tnormals_array = meshcache.anormt; @@ -1523,12 +1526,14 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent { meshcache.usebonepose = NULL; mesh->xyz_array = (vecV_t*)((char*)inf + inf->ofs_skel_xyz); + mesh->xyz2_array = NULL; mesh->normals_array = (vec3_t*)((char*)inf + inf->ofs_skel_norm); mesh->snormals_array = (vec3_t*)((char*)inf + inf->ofs_skel_svect); mesh->tnormals_array = (vec3_t*)((char*)inf + inf->ofs_skel_tvect); } else if (inf->numbones) { + mesh->xyz2_array = NULL; meshcache.usebonepose = Alias_GetBonePositions(inf, &e->framestate, meshcache.bonepose, MAX_BONES, true); if (e->fatness || !inf->ofs_skel_idx || !usebones) @@ -1626,12 +1631,40 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent frame2=0; } - R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), + + if (r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival) + { + mesh->xyz2_array = NULL; + R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2), 1-lerp, e->fatness); + } + else + { + galiaspose_t *p1 = (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1); + galiaspose_t *p2 = (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2); + + mesh->normals_array = (vec3_t *)((char *)p1 + p1->ofsnormals); + mesh->snormals_array = (vec3_t *)((char *)p1 + p1->ofssvector); + mesh->tnormals_array = (vec3_t *)((char *)p1 + p1->ofstvector); + + if (p1 == p2 || r_nolerp.ival) + { + mesh->xyz_array = (vecV_t *)((char *)p1 + p1->ofsverts); + mesh->xyz2_array = NULL; + } + else + { + mesh->xyz_blendw[0] = 1-lerp; + mesh->xyz_blendw[1] = lerp; + mesh->xyz_array = (vecV_t *)((char *)p1 + p1->ofsverts); + mesh->xyz2_array = (vecV_t *)((char *)p2 + p2->ofsverts); + } + } } - meshcache.acoords = mesh->xyz_array; + meshcache.acoords1 = mesh->xyz_array; + meshcache.acoords2 = mesh->xyz2_array; meshcache.anorm = mesh->normals_array; meshcache.anorms = mesh->snormals_array; meshcache.anormt = mesh->tnormals_array; diff --git a/engine/common/common.c b/engine/common/common.c index 95af1310..4bf39ca3 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -3056,6 +3056,7 @@ void COM_InitArgv (int argc, const char **argv) //not allowed to tprint int i; size_t result; +#ifndef NACL FILE *f; if (argv && argv[0]) @@ -3103,6 +3104,7 @@ void COM_InitArgv (int argc, const char **argv) //not allowed to tprint fclose(f); } +#endif safe = false; diff --git a/engine/common/common.h b/engine/common/common.h index 8c8d216f..c8088e25 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -302,7 +302,7 @@ extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in //extern char *com_basedir; void COM_WriteFile (const char *filename, const void *data, int len); -FILE *COM_WriteFileOpen (char *filename); +FTE_DEPRECATED FILE *COM_WriteFileOpen (char *filename); typedef struct { struct searchpath_s *search; @@ -325,14 +325,14 @@ char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly); char *FS_GetPackNames(char *buffer, int buffersize, int referencedonly, qboolean ext); void FS_ReferenceControl(unsigned int refflag, unsigned int resetflags); -int COM_FOpenFile (const char *filename, FILE **file); -int COM_FOpenWriteFile (const char *filename, FILE **file); +FTE_DEPRECATED int COM_FOpenFile (const char *filename, FILE **file); +FTE_DEPRECATED int COM_FOpenWriteFile (const char *filename, FILE **file); //#ifdef _MSC_VER //this is enough to annoy me, without conflicting with other (more bizzare) platforms. //#define fopen dont_use_fopen //#endif -void COM_CloseFile (FILE *h); +FTE_DEPRECATED void COM_CloseFile (FILE *h); #define COM_FDepthFile(filename,ignorepacks) FS_FLocateFile(filename,ignorepacks?FSLFRT_DEPTH_OSONLY:FSLFRT_DEPTH_ANYPATH, NULL) #define COM_FCheckExists(filename) FS_FLocateFile(filename,FSLFRT_IFFOUND, NULL) @@ -371,9 +371,9 @@ enum fs_relative{ void FS_FlushFSHash(void); void FS_CreatePath(const char *pname, enum fs_relative relativeto); -int FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto); //0 on success, non-0 on error -int FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto); -int FS_Remove(const char *fname, enum fs_relative relativeto); //0 on success, non-0 on error +qboolean FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto); //0 on success, non-0 on error +qboolean FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto); +qboolean FS_Remove(const char *fname, enum fs_relative relativeto); //0 on success, non-0 on error qboolean FS_Copy(const char *source, const char *dest, enum fs_relative relativesource, enum fs_relative relativedest); qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out, int outlen); //if you really need to fopen yourself qboolean FS_WriteFile (const char *filename, const void *data, int len, enum fs_relative relativeto); @@ -385,7 +385,7 @@ void FS_ReloadPackFiles(void); char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum); -int COM_filelength (FILE *f); +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 diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 486cb2bc..9fd7563d 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -590,6 +590,15 @@ char *Cvar_CompleteVariable (char *partial) } */ +static qboolean cvar_archivedvaluechanged; +qboolean Cvar_UnsavedArchive(void) +{ + return cvar_archivedvaluechanged; +} +void Cvar_Saved(void) +{ + cvar_archivedvaluechanged = false; +} /* ============ @@ -712,6 +721,9 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force) var->modified++; //only modified if it changed. if (var->callback) var->callback(var, latch); + + if ((var->flags & CVAR_ARCHIVE) && !(var->flags & CVAR_SERVEROVERRIDE) && cl_warncmd.ival) + cvar_archivedvaluechanged = true; } Z_Free (latch); // free the old value string @@ -1055,9 +1067,11 @@ void Cvar_LockFromServer(cvar_t *var, const char *str) { char *oldlatch; - Con_DPrintf("Server taking control of cvar %s (%s)\n", var->name, str); - - var->flags |= CVAR_SERVEROVERRIDE; + if (!(var->flags & CVAR_SERVEROVERRIDE)) + { + Con_DPrintf("Server taking control of cvar %s (%s)\n", var->name, str); + var->flags |= CVAR_SERVEROVERRIDE; + } oldlatch = var->latched_string; if (oldlatch) //maintaining control @@ -1180,7 +1194,7 @@ void Cvar_WriteVariables (vfsfile_t *f, qboolean all) { writtengroupheader = false; for (var = grp->cvars ; var ; var = var->next) - if (var->flags & CVAR_ARCHIVE || all) + if (var->flags & CVAR_ARCHIVE || (all && var != &cl_warncmd)) { if (!writtengroupheader) { diff --git a/engine/common/cvar.h b/engine/common/cvar.h index b7d82316..2b650c99 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -160,6 +160,9 @@ void Cvar_SetValue (cvar_t *var, float value); qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag); +qboolean Cvar_UnsavedArchive(void); +void Cvar_Saved(void); + int Cvar_ApplyLatches(int latchflag); //sets vars to their latched values diff --git a/engine/common/fs.c b/engine/common/fs.c index 648426a0..47648534 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -5,7 +5,6 @@ #include #include -#include #include "fs.h" #include "shader.h" @@ -989,29 +988,29 @@ vfsfile_t *FS_OpenReadLocation(flocation_t *location) return NULL; } -int FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto) +qboolean FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto) { char oldfullname[MAX_OSPATH]; char newfullname[MAX_OSPATH]; if (!FS_NativePath(oldf, oldrelativeto, oldfullname, sizeof(oldfullname))) - return EPERM; + return false; if (!FS_NativePath(newf, newrelativeto, newfullname, sizeof(newfullname))) - return EPERM; + return false; FS_CreatePath(newf, newrelativeto); - return rename(oldfullname, newfullname); + return Sys_Rename(oldfullname, newfullname); } -int FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto) +qboolean FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto) { return FS_Rename2(oldf, newf, relativeto, relativeto); } -int FS_Remove(const char *fname, enum fs_relative relativeto) +qboolean FS_Remove(const char *fname, enum fs_relative relativeto) { char fullname[MAX_OSPATH]; if (!FS_NativePath(fname, relativeto, fullname, sizeof(fullname))) - return EPERM; + return false; return Sys_remove (fullname); } diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index a01b3782..ff49b755 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -3,7 +3,6 @@ #include "glquake.h" #endif #include "com_mesh.h" -#include "errno.h" #define MAX_Q3MAP_INDICES 0x80000 #define MAX_Q3MAP_VERTEXES 0x80000 @@ -5650,7 +5649,7 @@ void CM_ReadPortalState (FILE *f) result = fread (portalopen, 1, sizeof(portalopen), f); // do something with result if (result != sizeof(portalopen)) - Con_Printf("CM_ReadPortalState() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(portalopen),(unsigned int)result,strerror(errno)); + Con_Printf("CM_ReadPortalState() fread: expected %lu, result was %u\n",(long unsigned int)sizeof(portalopen),(unsigned int)result); FloodAreaConnections (); } diff --git a/engine/common/log.c b/engine/common/log.c index 8375f83b..4355f84f 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -220,7 +220,7 @@ void Log_String (logtype_t lognum, char *s) else continue; // skip nonexistant files - if (FS_Rename(oldf, newf, FS_ROOT)) + if (!FS_Rename(oldf, newf, FS_ROOT)) { // rename failed, disable log and bug out Cvar_ForceSet(&log_enable[lognum], "0"); @@ -231,7 +231,7 @@ void Log_String (logtype_t lognum, char *s) // TODO: option to compress file somewhere in here? // rename our base file, which better exist... - if (FS_Rename(f, oldf, FS_ROOT)) + if (!FS_Rename(f, oldf, FS_ROOT)) { // rename failed, disable log and bug out Cvar_ForceSet(&log_enable[lognum], "0"); diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index f11185ab..7b387dc3 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -1240,7 +1240,7 @@ void Matrix4x4_CM_Projection_Inf(float *proj, float fovx, float fovy, float near proj[2] = 0; proj[6] = 0; - proj[10] = -1 * nudge; + proj[10] = -1 * ((float)(1<<21)/(1<<22)); proj[14] = -2*neard * nudge; proj[3] = 0; diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 4b38ed60..a09b80ff 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -84,7 +84,7 @@ int net_drop; cvar_t showpackets = SCVAR("showpackets", "0"); cvar_t showdrop = SCVAR("showdrop", "0"); cvar_t qport = SCVAR("qport", "0"); -cvar_t net_mtu = CVARD("mtu", "1450", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation."); +cvar_t net_mtu = CVARD("net_mtu", "1450", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation."); cvar_t pext_replacementdeltas = CVAR("debug_pext_replacementdeltas", "0"); /*rename once the extension is finalized*/ @@ -204,6 +204,8 @@ void Netchan_Init (void) // pick a port value that should be nice and random #ifdef _WIN32 port = (time(NULL)) & 0xffff; +#elif defined(NACL) + port = ((int)(getpid()) * time(NULL)) & 0xffff; #else port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff; #endif @@ -293,7 +295,7 @@ void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport) chan->message.data = chan->message_buf; chan->message.allowoverflow = true; - chan->message.maxsize = MAX_QWMSGLEN;//sizeof(chan->message_buf); + chan->message.maxsize = MAX_QWMSGLEN; chan->qport = qport; } @@ -681,12 +683,10 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) while(offset < send.cursize) { no = offset + chan->fragmentsize - hsz; + no &= ~7; if (no < send.cursize) { more = true; - no &= 7; - if (no == offset) - break; } else { diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index c56de639..d8f18aca 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -2420,7 +2420,7 @@ handshakeerror: net_message.cursize = BigShort(*(short*)st->inbuffer); if (net_message.cursize >= sizeof(net_message_buffer) ) { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); goto closesvstream; } if (net_message.cursize+2 > st->inlen) @@ -3886,6 +3886,7 @@ int TCP_OpenStream (netadr_t remoteaddr) if (connect(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET) { + Con_Printf ("TCP_OpenStream: connect: error %i\n", qerrno); closesocket(newsocket); return INVALID_SOCKET; } @@ -4659,6 +4660,262 @@ vfsfile_t *FS_OpenTCP(const char *name) else return NULL; } +#elif 0 //defined(HAVE_WEBSOCKCL) +This code is disabled. +I cannot provide a reliable mechanism over chrome/nacl's websockets at this time. +Some module within the ppapi/nacl/chrome stack refuses to forward the data when stressed. +All I can determine is that the connection has a gap. +Hopefully this should be fixed by pepper_19. + +As far as I'm aware, this and the relevent code in QTV should be functionally complete. + +typedef struct +{ + vfsfile_t funcs; + + PP_Resource sock; + + unsigned char readbuffer[65536]; + int readbuffered; + qboolean havepacket; + struct PP_Var incomingpacket; + qboolean failed; +} tcpfile_t; + +static void tcp_websocketgot(void *user_data, int32_t result) +{ + tcpfile_t *wsc = user_data; + if (result == PP_OK) + { + if (wsc->incomingpacket.type == PP_VARTYPE_UNDEFINED) + { + Con_Printf("ERROR: %s: var was not set by PPAPI. Data has been lost.\n", __func__); + wsc->failed = true; + } + wsc->havepacket = true; + } + else + { + Sys_Printf("%s: %i\n", __func__, result); + wsc->failed = true; + } +} +static void tcp_websocketconnected(void *user_data, int32_t result) +{ + tcpfile_t *wsc = user_data; + if (result == PP_OK) + { + int res; + //we got a successful connection, enable reception. + struct PP_CompletionCallback ccb = {tcp_websocketgot, wsc, PP_COMPLETIONCALLBACK_FLAG_NONE}; + res = ppb_websocket_interface->ReceiveMessage(wsc->sock, &wsc->incomingpacket, ccb); + if (res != PP_OK_COMPLETIONPENDING) + tcp_websocketgot(wsc, res); + } + else + { + Sys_Printf("%s: %i\n", __func__, result); + //some sort of error connecting, make it timeout now + wsc->failed = true; + } +} +static void tcp_websocketclosed(void *user_data, int32_t result) +{ + tcpfile_t *wsc = user_data; + wsc->failed = true; + if (wsc->havepacket) + { + wsc->havepacket = false; + ppb_var_interface->Release(wsc->incomingpacket); + } + ppb_core->ReleaseResource(wsc->sock); + wsc->sock = 0; +// Z_Free(wsc); +} + +void VFSTCP_Close (struct vfsfile_s *file) +{ + /*meant to free the memory too, in this case we get the callback to do it*/ + tcpfile_t *wsc = (void*)file; + + struct PP_CompletionCallback ccb = {tcp_websocketclosed, wsc, PP_COMPLETIONCALLBACK_FLAG_NONE}; + ppb_websocket_interface->Close(wsc->sock, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(), ccb); +} + +int VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +{ + tcpfile_t *wsc = (void*)file; + int res; + + if (wsc->havepacket && wsc->readbuffered < bytestoread + 1024) + { + if (wsc->incomingpacket.type == PP_VARTYPE_UNDEFINED) + Con_Printf("PPAPI bug: var is still undefined after being received\n"); + else + { + int len = 0; + unsigned char *utf8 = (unsigned char *)ppb_var_interface->VarToUtf8(wsc->incomingpacket, &len); + unsigned char *out = (unsigned char *)wsc->readbuffer + wsc->readbuffered; + + wsc->havepacket = false; + + Con_Printf("Len: %i\n", len); + while(len && out < wsc->readbuffer + sizeof(wsc->readbuffer)) + { + if ((*utf8 & 0xe0)==0xc0 && len > 1) + { + *out = ((utf8[0] & 0x1f)<<6) | ((utf8[1] & 0x3f)<<0); + utf8+=2; + len -= 2; + } + else if (*utf8 & 0x80) + { + *out = '?'; + utf8++; + len -= 1; + } + else + { + *out = utf8[0]; + utf8++; + len -= 1; + } + out++; + } + if (len) + { + Con_Printf("oh noes! buffer not big enough!\n"); + wsc->failed = true; + } + Con_Printf("Old: %i\n", wsc->readbuffered); + wsc->readbuffered = out - wsc->readbuffer; + Con_Printf("New: %i\n", wsc->readbuffered); + + ppb_var_interface->Release(wsc->incomingpacket); + wsc->incomingpacket = PP_MakeUndefined(); + } + if (!wsc->failed) + { + //get the next one + struct PP_CompletionCallback ccb = {tcp_websocketgot, wsc, PP_COMPLETIONCALLBACK_FLAG_NONE}; + res = ppb_websocket_interface->ReceiveMessage(wsc->sock, &wsc->incomingpacket, ccb); + if (res != PP_OK_COMPLETIONPENDING) + tcp_websocketgot(wsc, res); + } + } + + if (wsc->readbuffered) + { +// Con_Printf("Reading %i bytes of %i\n", bytestoread, wsc->readbuffered); + if (bytestoread > wsc->readbuffered) + bytestoread = wsc->readbuffered; + + memcpy(buffer, wsc->readbuffer, bytestoread); + memmove(wsc->readbuffer, wsc->readbuffer+bytestoread, wsc->readbuffered-bytestoread); + wsc->readbuffered -= bytestoread; + } + else if (wsc->failed) + bytestoread = -1; /*signal eof*/ + else + bytestoread = 0; + return bytestoread; +} +int VFSTCP_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite) +{ + tcpfile_t *wsc = (void*)file; + int res; + int outchars = 0; + unsigned char outdata[bytestowrite*2+1]; + unsigned char *out=outdata; + const unsigned char *in=buffer; + if (wsc->failed) + return 0; + + for(res = 0; res < bytestowrite; res++) + { + /*FIXME: do we need this code?*/ + if (!*in) + { + *out++ = 0xc0 | (0x100 >> 6); + *out++ = 0x80 | (0x100 & 0x3f); + } + else if (*in >= 0x80) + { + *out++ = 0xc0 | (*in >> 6); + *out++ = 0x80 | (*in & 0x3f); + } + else + *out++ = *in; + in++; + outchars++; + } + *out = 0; + struct PP_Var str = ppb_var_interface->VarFromUtf8(outdata, out - outdata); + res = ppb_websocket_interface->SendMessage(wsc->sock, str); +// Sys_Printf("FTENET_WebSocket_SendPacket: result %i\n", res); + ppb_var_interface->Release(str); + + if (res == PP_OK) + return bytestowrite; + return 0; +} + +qboolean VFSTCP_Seek (struct vfsfile_s *file, unsigned long pos) +{ + //no seeking allowed + tcpfile_t *wsc = (void*)file; + Con_Printf("tcp seek?\n"); + wsc->failed = true; + return false; +} +unsigned long VFSTCP_Tell (struct vfsfile_s *file) +{ + //no telling allowed + tcpfile_t *wsc = (void*)file; + Con_Printf("tcp tell?\n"); + wsc->failed = true; + return 0; +} +unsigned long VFSTCP_GetLen (struct vfsfile_s *file) +{ + return 0; +} + +/*nacl websockets implementation...*/ +vfsfile_t *FS_OpenTCP(const char *name) +{ + tcpfile_t *newf; + + netadr_t adr; + + if (!ppb_websocket_interface) + { + return NULL; + } + if (!NET_StringToAdr(name, &adr)) + return NULL; //couldn't resolve the name + newf = Z_Malloc(sizeof(*newf)); + if (newf) + { + struct PP_CompletionCallback ccb = {tcp_websocketconnected, newf, PP_COMPLETIONCALLBACK_FLAG_NONE}; + newf->sock = ppb_websocket_interface->Create(pp_instance); + struct PP_Var str = ppb_var_interface->VarFromUtf8(adr.address.websocketurl, strlen(adr.address.websocketurl)); + ppb_websocket_interface->Connect(newf->sock, str, NULL, 0, ccb); + ppb_var_interface->Release(str); + + newf->funcs.Close = VFSTCP_Close; + newf->funcs.Flush = NULL; + newf->funcs.GetLen = VFSTCP_GetLen; + newf->funcs.ReadBytes = VFSTCP_ReadBytes; + newf->funcs.Seek = VFSTCP_Seek; + newf->funcs.Tell = VFSTCP_Tell; + newf->funcs.WriteBytes = VFSTCP_WriteBytes; + newf->funcs.seekingisabadplan = true; + + return &newf->funcs; + } + return NULL; +} #else vfsfile_t *FS_OpenTCP(const char *name) { diff --git a/engine/common/plugin.c b/engine/common/plugin.c index e94d41a5..ff58385e 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -436,14 +436,13 @@ qintptr_t VARGS Plug_GetPluginName(void *offset, quintptr_t mask, const qintptr_ return false; } -typedef void (*funcptr_t) (); qintptr_t VARGS Plug_ExportNative(void *offset, quintptr_t mask, const qintptr_t *arg) { - funcptr_t func; + void *func; char *name = (char*)VM_POINTER(arg[0]); arg++; - func = *(funcptr_t*)arg; + func = ((void**)arg)[0]; if (!strcmp(name, "UnsafeClose")) { @@ -472,6 +471,13 @@ qintptr_t VARGS Plug_ExportNative(void *offset, quintptr_t mask, const qintptr_t currentplug->blockcloses++; } */ +#if defined(PLUGINS) && !defined(NOMEDIA) && !defined(SERVERONLY) + else if (!strcmp(name, "Media_VideoDecoder")) + { + Media_RegisterDecoder(currentplug, func); + currentplug->blockcloses++; + } +#endif #ifndef SERVERONLY else if (!strcmp(name, "S_LoadSound")) //a hook for loading extra types of sound (wav, mp3, ogg, midi, whatever you choose to support) @@ -757,14 +763,14 @@ int pluginstreamarraylen; int Plug_NewStreamHandle(plugstream_e type) { int i; - for (i = 0; i < pluginstreamarraylen; i++) + for (i = 1; i < pluginstreamarraylen; i++) { if (!pluginstreamarray[i].plugin) break; } - if (i == pluginstreamarraylen) + if (i >= pluginstreamarraylen) { - pluginstreamarraylen++; + pluginstreamarraylen=i+16; pluginstreamarray = BZ_Realloc(pluginstreamarray, pluginstreamarraylen*sizeof(pluginstream_t)); } @@ -787,6 +793,7 @@ qintptr_t VARGS Plug_Net_TCPListen(void *offset, quintptr_t mask, const qintptr_ int sock; struct sockaddr_qstorage address; int _true = 1; + int alen; char *localip = VM_POINTER(arg[0]); unsigned short localport = VM_LONG(arg[1]); @@ -812,6 +819,19 @@ qintptr_t VARGS Plug_Net_TCPListen(void *offset, quintptr_t mask, const qintptr_ ((struct sockaddr_in6*)&address)->sin6_port = htons(localport); #endif + switch(((struct sockaddr*)&address)->sa_family) + { + case AF_INET: + alen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + alen = sizeof(struct sockaddr_in6); + break; + default: + return -2; + } + + if ((sock = socket(((struct sockaddr*)&address)->sa_family, SOCK_STREAM, 0)) == -1) { Con_Printf("Failed to create socket\n"); @@ -822,13 +842,14 @@ qintptr_t VARGS Plug_Net_TCPListen(void *offset, quintptr_t mask, const qintptr_ closesocket(sock); return -2; } + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&_true, sizeof(_true)); - if( bind (sock, (void *)&address, sizeof(address)) == -1) + if (bind (sock, (void *)&address, alen) == -1) { closesocket(sock); return -2; } - if( listen (sock, maxcount) == -1) + if (listen (sock, maxcount) == -1) { closesocket(sock); return -2; @@ -853,9 +874,11 @@ qintptr_t VARGS Plug_Net_Accept(void *offset, quintptr_t mask, const qintptr_t * return -2; sock = pluginstreamarray[handle].socket; + if (sock < 0) + return -1; + addrlen = sizeof(address); sock = accept(sock, (struct sockaddr *)&address, &addrlen); - if (sock < 0) return -1; diff --git a/engine/common/qvm.c b/engine/common/qvm.c index e1178675..7ec3d908 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -382,7 +382,7 @@ qvm_t *QVM_LoadVM(const char *name, sys_callqvm_t syscall) if ((1<= qvm->ds_mask) //is this bit greater than our minimum? break; } - qvm->len_ss = (1<len_ds*sizeof(qbyte) - 4; //expand the stack space to fill it. + qvm->len_ss = (1<len_ds*(int)sizeof(qbyte) - 4; //expand the stack space to fill it. qvm->ds_mask = qvm->len_ds*sizeof(qbyte)+(qvm->len_ss+4)*sizeof(qbyte); qvm->len_ss -= qvm->len_ss&7; diff --git a/engine/common/sys.h b/engine/common/sys.h index a9ad338d..e4671291 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // void Sys_mkdir (char *path); //not all pre-unix systems have directories (including dos 1) qboolean Sys_remove (char *path); +qboolean Sys_Rename (char *oldfname, char *newfname); qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen); // diff --git a/engine/common/translate.c b/engine/common/translate.c index 7408b26a..f45eaa2e 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -1,5 +1,4 @@ #include "quakedef.h" -#include "errno.h" #undef malloc #undef free @@ -584,7 +583,7 @@ void TL_LoadLanguage (char *name, char *shortname, int num) //this is one of the result = fread(buffer, 1, size, f); // do something with result if (result != size) - Con_Printf("TL_LoadLanguage() fread: Filename: %s, expected %i, result was %u (%s)\n",va("%s.trl", shortname),size,(unsigned int)result,strerror(errno)); + Con_Printf("TL_LoadLanguage() fread: Filename: %s, expected %i, result was %u\n",va("%s.trl", shortname),size,(unsigned int)result); fclose(f); diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index c19a3086..9b996d3e 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -1718,10 +1718,8 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned i perm |= PERMUTATION_SPECULAR; if (TEXVALID(shaderstate.curtexnums->fullbright) && p->handle[perm|PERMUTATION_FULLBRIGHT].hlsl.vert) perm |= PERMUTATION_FULLBRIGHT; - if (TEXVALID(shaderstate.curtexnums->loweroverlay) && p->handle[perm|PERMUTATION_LOWER].hlsl.vert) - perm |= PERMUTATION_LOWER; - if (TEXVALID(shaderstate.curtexnums->upperoverlay) && p->handle[perm|PERMUTATION_UPPER].hlsl.vert) - perm |= PERMUTATION_UPPER; + if (p->handle[perm|PERMUTATION_UPPERLOWER].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) perm |= PERMUTATION_FOG; // if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert) diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index a4a5076c..cd1c7e5c 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -24,6 +24,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "droid", "droid\droid.vcproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nacl", "..\nacl\nacl.vcproj", "{4735677B-6D5A-4BE6-A945-CB32A7282F56}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xsv", "..\..\plugins\xsv\xsv.vcproj", "{873CCE24-3549-49D4-A4B4-653F91B1532A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution D3DDebug|Win32 = D3DDebug|Win32 @@ -359,6 +361,42 @@ Global {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release|Win32.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Release|x64.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|Win32.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|Win32.Build.0 = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|x64.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DRelease|Win32.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DRelease|Win32.Build.0 = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DRelease|x64.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Debug|Win32.ActiveCfg = Debug|Win32 + {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|Win32.Build.0 = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.GLRelease|x64.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MDebug|Win32.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MDebug|Win32.Build.0 = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MDebug|x64.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLDebug|Win32.Build.0 = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLDebug|x64.ActiveCfg = Debug|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|Win32.Build.0 = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MinGLRelease|x64.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MRelease|Win32.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MRelease|Win32.Build.0 = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.MRelease|x64.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Release Dedicated Server|Win32.Build.0 = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Release Dedicated Server|x64.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Release|Win32.ActiveCfg = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Release|Win32.Build.0 = Release|Win32 + {873CCE24-3549-49D4-A4B4-653F91B1532A}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index eeea29d4..c93506c9 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -766,6 +766,7 @@ Optimization="0" AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include,../d3d,../d3d9,../libs/dxsdk9/include" PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD" + BasicRuntimeChecks="3" RuntimeLibrary="1" EnableFunctionLevelLinking="true" FloatingPointModel="2" @@ -1273,7 +1274,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include" - PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;SERVERONLY" + PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;SERVERONLY;MULTITHREAD" MinimalRebuild="true" RuntimeLibrary="0" FloatingPointModel="2" @@ -1681,7 +1682,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include" - PreprocessorDefinitions="NDEBUG;GLQUAKE;WIN32;_WINDOWS;BOTLIB_STATIC" + PreprocessorDefinitions="NDEBUG;GLQUAKE;WIN32;_WINDOWS;BOTLIB_STATIC;MULTITHREAD" StringPooling="true" ExceptionHandling="0" BufferSecurityCheck="false" @@ -1784,11 +1785,15 @@ Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="2" + EnableIntrinsicFunctions="true" + FavorSizeOrSpeed="1" + OmitFramePointers="true" + WholeProgramOptimization="true" AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include,../d3d,../d3d9,../libs/dxsdk9/include" PreprocessorDefinitions="NDEBUG;GLQUAKE;WIN32;_WINDOWS" StringPooling="true" RuntimeLibrary="0" - EnableFunctionLevelLinking="true" + BufferSecurityCheck="false" FloatingPointModel="2" UsePrecompiledHeader="2" PrecompiledHeaderThrough="quakedef.h" @@ -1824,6 +1829,7 @@ GenerateMapFile="true" MapFileName=".\ftequake___Win32_GLRelease/fteglqw.map" SubSystem="2" + LinkTimeCodeGeneration="1" TargetMachine="17" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + >tmu) & 1) != 0) -#endif - { - qglClientActiveTextureARB(tmu + mtexid0); - if (0) - { - shaderstate.tmuarrayactive |= 1u<>tmu) & 1) != arrays) -#endif + //legacy colour attribute (including flat shaded) + if ((bitstochange) & (1u<= (1u<= (1u<coord2.gl.vbo && !shaderstate.sourcevbo->coord2.gl.addr) + { + GL_SelectVBO(shaderstate.pendingvertexvbo); + qglVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), shaderstate.pendingvertexpointer); + } + else + { + GL_SelectVBO(shaderstate.sourcevbo->coord2.gl.vbo); + qglVertexAttribPointer(VATTR_VERTEX2, 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), shaderstate.sourcevbo->coord2.gl.addr); + } + break; + case VATTR_COLOUR: + if (shaderstate.sourcevbo->colours.gl.addr) + { + GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); + qglVertexAttribPointer(VATTR_COLOUR, 4, shaderstate.colourarraytype, ((shaderstate.colourarraytype==GL_FLOAT)?GL_FALSE:GL_TRUE), 0, shaderstate.sourcevbo->colours.gl.addr); + break; + } + break; + case VATTR_TEXCOORD: + GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); + qglVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord.gl.addr); + break; + case VATTR_LMCOORD: + GL_SelectVBO(shaderstate.sourcevbo->lmcoord.gl.vbo); + qglVertexAttribPointer(VATTR_LMCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord.gl.addr); + break; + case VATTR_NORMALS: + if (!shaderstate.sourcevbo->normals.gl.addr) + break; + GL_SelectVBO(shaderstate.sourcevbo->normals.gl.vbo); + qglVertexAttribPointer(VATTR_NORMALS, 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->normals.gl.addr); + break; + case VATTR_SNORMALS: + if (!shaderstate.sourcevbo->svector.gl.addr) + break; + GL_SelectVBO(shaderstate.sourcevbo->svector.gl.vbo); + qglVertexAttribPointer(VATTR_SNORMALS, 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->svector.gl.addr); + break; + case VATTR_TNORMALS: + if (!shaderstate.sourcevbo->tvector.gl.addr) + break; + GL_SelectVBO(shaderstate.sourcevbo->tvector.gl.vbo); + qglVertexAttribPointer(VATTR_TNORMALS, 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector.gl.addr); + break; + case VATTR_BONENUMS: + GL_SelectVBO(shaderstate.sourcevbo->bonenums.gl.vbo); + qglVertexAttribPointer(VATTR_BONENUMS, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(byte_vec4_t), shaderstate.sourcevbo->bonenums.gl.addr); + break; + case VATTR_BONEWEIGHTS: + GL_SelectVBO(shaderstate.sourcevbo->boneweights.gl.vbo); + qglVertexAttribPointer(VATTR_BONEWEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->boneweights.gl.addr); + break; + } + if ((bitstoendisable) & (1u<vaodynamic&progattrmask; + bitstoendisable = 0; + + if (bitstochange & (1u<indicies.gl.vbo); } } - shaderstate.sha_attr = newm; + else + { + bitstochange = progattrmask; + bitstoendisable = progattrmask^shaderstate.sha_attr; + + shaderstate.sha_attr = progattrmask; + +#ifndef FORCESTATE + if (shaderstate.currentebo != shaderstate.sourcevbo->indicies.gl.vbo) +#endif + { + shaderstate.currentebo = shaderstate.sourcevbo->indicies.gl.vbo; + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, shaderstate.currentebo); + } + } + + if (bitstochange || bitstoendisable) + BE_ApplyAttributes(bitstochange, bitstoendisable); } + +void GLBE_SetupVAO(vbo_t *vbo, unsigned vaodynamic) +{ + if (qglGenVertexArrays) + { + unsigned int availbits; + qglGenVertexArrays(1, &vbo->vao); + + availbits = + (1u<coord.gl.vbo; + shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord.gl.addr; + + shaderstate.currentvao = vbo->vao; + qglBindVertexArray(vbo->vao); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, shaderstate.sourcevbo->indicies.gl.vbo); + BE_ApplyAttributes(availbits, availbits); + GL_SelectVBO(shaderstate.sourcevbo->coord.gl.vbo); + vbo->vaodynamic = vaodynamic; + + shaderstate.curvertexpointer = NULL; + shaderstate.curvertexvbo = 0; + } + else + { + /*always select the coord vbo and indicies ebo, for easy bufferdata*/ + GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); + GL_SelectVBO(shaderstate.sourcevbo->coord.gl.vbo); + } +} + void GL_SelectProgram(int program) { if (shaderstate.currentprogram != program) @@ -489,15 +687,40 @@ void GL_SelectProgram(int program) void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsigned numindicies, int ibo, index_t *indicies) { - GL_SelectVBO(vbo); - GL_SelectEBO(ibo); - qglEnableClientState(GL_VERTEX_ARRAY); - //draw cached world shadow mesh - qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), verts); - qglDrawRangeElements(GL_TRIANGLES, 0, numverts, numindicies, GL_INDEX_TYPE, indicies); + shaderstate.pendingvertexvbo = vbo; + shaderstate.pendingvertexpointer = verts; + + shaderstate.sourcevbo = &shaderstate.dummyvbo; + shaderstate.dummyvbo.indicies.gl.vbo = ibo; + + if (gl_config.nofixedfunc) + { + //shaderstate.sourcevbo = &shaderstate.dummyvbo; + GL_SelectProgram(shaderstate.allblackshader); + qglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), verts); + qglVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), verts); + BE_EnableShaderAttributes(gl_config.nofixedfunc?(1u<0) { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); } GL_SelectTexture(0); - qglEnableClientState(GL_VERTEX_ARRAY); - BE_SetPassBlendMode(0, PBM_REPLACE); - - if (qglColor3f) + if (!gl_config.nofixedfunc) + { + BE_SetPassBlendMode(0, PBM_REPLACE); qglColor3f(1,1,1); + GL_DeSelectProgram(); + } + shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY|SBITS_MASK_BITS); shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE; @@ -629,8 +851,6 @@ static void RevertToKnownState(void) qglDepthMask(GL_TRUE); qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - GL_DeSelectProgram(); } void PPL_RevertToKnownState(void) @@ -662,7 +882,7 @@ void BE_SetupForShadowMap(void) { while(shaderstate.lastpasstmus>0) { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); } qglShadeModel(GL_FLAT); @@ -707,7 +927,7 @@ static void T_Gen_CurrentRender(int tmu) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } -static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolean useclientarray) +static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) { extern texid_t missing_texture; extern texid_t scenepp_postproc_cube; @@ -753,20 +973,20 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea break; case T_GEN_LIGHTCUBEMAP: - GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, shaderstate.lightcubemap, useclientarray); + GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, shaderstate.lightcubemap); return; case T_GEN_CUBEMAP: t = pass->anim_frames[0]; - GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); + GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t); return; case T_GEN_SOURCECUBE: t = scenepp_postproc_cube; - GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); + GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t); return; case T_GEN_3DMAP: t = pass->anim_frames[0]; - GL_LazyBind(tmu, GL_TEXTURE_3D, t, useclientarray); + GL_LazyBind(tmu, GL_TEXTURE_3D, t); return; case T_GEN_VIDEOMAP: @@ -788,7 +1008,7 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea t = shaderstate.tex_sourcedepth; break; } - GL_LazyBind(tmu, GL_TEXTURE_2D, t, useclientarray); + GL_LazyBind(tmu, GL_TEXTURE_2D, t); } /*========================================== matrix functions =====================================*/ @@ -925,9 +1145,12 @@ void GLBE_Init(void) int i; double t; + memset(&shaderstate, 0, sizeof(shaderstate)); + shaderstate.curentity = &r_worldentity; be_maxpasses = gl_mtexarbable; - + gl_stencilbits = 0; + qglGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits); for (i = 0; i < FTABLE_SIZE; i++) { t = (double)i / (double)FTABLE_SIZE; @@ -968,13 +1191,8 @@ void GLBE_Init(void) /*lock the cvar down if the backend can't actually do it*/ if (!gl_config.tex_env_combine && !gl_config.nofixedfunc && gl_overbright.ival) Cvar_ApplyLatchFlag(&gl_overbright, "0", CVAR_RENDERERLATCH); - - shaderstate.shaderbits = ~0; + shaderstate.shaderbits = ~SBITS_ATEST_BITS; BE_SendPassBlendDepthMask(0); - - if (qglEnableClientState && !gl_config.nofixedfunc) - qglEnableClientState(GL_VERTEX_ARRAY); - currententity = &r_worldentity; @@ -1802,24 +2020,12 @@ static void GenerateColourMods(const shaderpass_t *pass) mesh_t *meshlist; meshlist = shaderstate.meshes[0]; - /*if (shaderstate.sourcevbo->colours4ub) - { - //hack... - GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); - qglEnableClientState(GL_COLOR_ARRAY); - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, shaderstate.sourcevbo->colours4ub.gl.addr); - qglShadeModel(GL_SMOOTH); - return; - }*/ if (pass->flags & SHADER_PASS_NOCOLORARRAY && qglColor4fv) { - avec4_t scol; - - colourgen(pass, 1, meshlist->colors4f_array, &scol, meshlist); - alphagen(pass, 1, meshlist->colors4f_array, &scol, meshlist); - qglDisableClientState(GL_COLOR_ARRAY); - qglColor4fv(scol); - qglShadeModel(GL_FLAT); + colourgen(pass, 1, meshlist->colors4f_array, &shaderstate.pendingcolourflat, meshlist); + alphagen(pass, 1, meshlist->colors4f_array, &shaderstate.pendingcolourflat, meshlist); + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; } else { @@ -1828,44 +2034,35 @@ static void GenerateColourMods(const shaderpass_t *pass) { if (shaderstate.mode == BEM_DEPTHDARK || shaderstate.mode == BEM_DEPTHONLY) { - avec4_t scol; - scol[0] = scol[1] = scol[2] = 0; - alphagen(pass, 1, meshlist->colors4f_array, &scol, meshlist); - qglDisableClientState(GL_COLOR_ARRAY); - qglColor4fv(scol); - qglShadeModel(GL_FLAT); + shaderstate.pendingcolourflat[0] = shaderstate.pendingcolourflat[1] = shaderstate.pendingcolourflat[2] = 0; + alphagen(pass, 1, meshlist->colors4f_array, &shaderstate.pendingcolourflat, meshlist); + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; return; } if (shaderstate.mode == BEM_LIGHT) { - avec4_t scol; - scol[0] = scol[1] = scol[2] = 1; - alphagen(pass, 1, meshlist->colors4f_array, &scol, meshlist); - qglDisableClientState(GL_COLOR_ARRAY); - qglColor4fv(scol); - qglShadeModel(GL_FLAT); + shaderstate.pendingcolourflat[0] = shaderstate.pendingcolourflat[1] = shaderstate.pendingcolourflat[2] = 1; + alphagen(pass, 1, meshlist->colors4f_array, &shaderstate.pendingcolourflat, meshlist); + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; return; } if (r_nolightdir.ival) { - qglDisableClientState(GL_COLOR_ARRAY); - qglColor4f( shaderstate.curentity->light_avg[0], - shaderstate.curentity->light_avg[1], - shaderstate.curentity->light_avg[2], - shaderstate.curentity->shaderRGBAf[3]); - qglShadeModel(GL_FLAT); + VectorCopy(shaderstate.curentity->light_avg, shaderstate.pendingcolourflat); + shaderstate.pendingcolourflat[3] = shaderstate.curentity->shaderRGBAf[3]; + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; return; } } - qglShadeModel(GL_SMOOTH); - //if its vetex lighting, just use the vbo if (((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING && shaderstate.identitylighting == 1) || pass->rgbgen == RGB_GEN_VERTEX_EXACT) && pass->alphagen == ALPHA_GEN_VERTEX) { - GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); - qglColorPointer(4, shaderstate.colourarraytype, 0, shaderstate.sourcevbo->colours.gl.addr); - qglEnableClientState(GL_COLOR_ARRAY); + shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours.gl.vbo; + shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours.gl.addr; return; } @@ -1876,9 +2073,9 @@ static void GenerateColourMods(const shaderpass_t *pass) colourgen(pass, meshlist->numvertexes, meshlist->colors4f_array, coloursarray + meshlist->vbofirstvert, meshlist); alphagen(pass, meshlist->numvertexes, meshlist->colors4f_array, coloursarray + meshlist->vbofirstvert, meshlist); } - GL_SelectVBO(0); - qglColorPointer(4, GL_FLOAT, 0, coloursarray); - qglEnableClientState(GL_COLOR_ARRAY); + + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = coloursarray; } } @@ -1979,7 +2176,6 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits) if (!delta) return; shaderstate.shaderbits = sbits; - if (delta & SBITS_BLEND_BITS) { if (sbits & SBITS_BLEND_BITS) @@ -2163,6 +2359,7 @@ static void BE_SubmitMeshChain(void) qglLockArraysEXT(startv, endv); } */ + for (m = 0, mesh = shaderstate.meshes[0]; m < shaderstate.meshcount; ) { startv = mesh->vbofirstvert; @@ -2200,6 +2397,7 @@ static void DrawPass(const shaderpass_t *pass) int i; int tmu; int lastpass = pass->numMergedPasses; + unsigned int attr = (1u<fullbright)) continue; - Shader_BindTextureForPass(tmu, pass+i, true); + Shader_BindTextureForPass(tmu, pass+i); + attr |= (1u<<(VATTR_LEG_TMU0+tmu)); BE_GeneratePassTC(pass, i); @@ -2234,91 +2433,33 @@ static void DrawPass(const shaderpass_t *pass) for (i = tmu; i < shaderstate.lastpasstmus; i++) { - GL_LazyBind(i, 0, r_nulltex, false); + GL_LazyBind(i, 0, r_nulltex); } shaderstate.lastpasstmus = tmu; - GL_ApplyVertexPointer(); + BE_EnableShaderAttributes(attr); BE_SubmitMeshChain(); } -static unsigned int BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, qboolean entunchanged) +static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, qboolean entunchanged) { vec3_t param3; int r, g, b; int i; - unsigned int attr = 0; const shaderprogparm_t *p; + /*don't bother setting it if the ent properties are unchanged (but do if the mesh changed)*/ + if (entunchanged) + return; + for (i = 0; i < prog->numparams; i++) { p = &prog->parm[i]; if (p->handle[perm] == -1) continue; /*not in this permutation*/ - /*don't bother setting it if the ent properties are unchanged (but do if the mesh changed)*/ - if (entunchanged && p->type >= SP_FIRSTUNIFORM) - break; - switch(p->type) { - case SP_ATTR_VERTEX: - /*we still do vertex transforms for billboards and shadows and such*/ - GL_SelectVBO(shaderstate.pendingvertexvbo); - qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), shaderstate.pendingvertexpointer); - attr |= 1u<handle[perm]; - break; - case SP_ATTR_COLOUR: - if (shaderstate.sourcevbo->colours.gl.addr) - { - GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 4, shaderstate.colourarraytype, ((shaderstate.colourarraytype==GL_FLOAT)?GL_FALSE:GL_TRUE), 0, shaderstate.sourcevbo->colours.gl.addr); - attr |= 1u<handle[perm]; - break; - } - break; - case SP_ATTR_TEXCOORD: - GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord.gl.addr); - attr |= 1u<handle[perm]; - break; - case SP_ATTR_LMCOORD: - GL_SelectVBO(shaderstate.sourcevbo->lmcoord.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord.gl.addr); - attr |= 1u<handle[perm]; - break; - case SP_ATTR_NORMALS: - if (!shaderstate.sourcevbo->normals.gl.addr) - break; - GL_SelectVBO(shaderstate.sourcevbo->normals.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->normals.gl.addr); - attr |= 1u<handle[perm]; - break; - case SP_ATTR_SNORMALS: - if (!shaderstate.sourcevbo->svector.gl.addr) - break; - GL_SelectVBO(shaderstate.sourcevbo->svector.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->svector.gl.addr); - attr |= 1u<handle[perm]; - break; - case SP_ATTR_TNORMALS: - if (!shaderstate.sourcevbo->tvector.gl.addr) - break; - GL_SelectVBO(shaderstate.sourcevbo->tvector.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector.gl.addr); - attr |= 1u<handle[perm]; - break; - case SP_ATTR_BONENUMS: - GL_SelectVBO(shaderstate.sourcevbo->bonenums.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(byte_vec4_t), shaderstate.sourcevbo->bonenums.gl.addr); - attr |= 1u<handle[perm]; - break; - case SP_ATTR_BONEWEIGHTS: - GL_SelectVBO(shaderstate.sourcevbo->boneweights.gl.vbo); - qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->boneweights.gl.addr); - attr |= 1u<handle[perm]; - break; - case SP_M_VIEW: qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.m_view); break; @@ -2360,22 +2501,26 @@ static unsigned int BE_Program_Set_Attributes(const program_t *prog, unsigned in } break; + case SP_E_VBLEND: + qglUniform2fvARB(p->handle[perm], 1, shaderstate.meshes[0]->xyz_blendw); + break; + case SP_E_LMSCALE: { vec4_t colscale; - if (shaderstate.mode == BEM_DEPTHDARK) + if (shaderstate.curentity->model && shaderstate.curentity->model->engineflags & MDLF_NEEDOVERBRIGHT) { - VectorClear(colscale); - } - else if (shaderstate.curentity->model && shaderstate.curentity->model->engineflags & MDLF_NEEDOVERBRIGHT) - { - float sc = 1<shaderRGBAf, sc, colscale); } - else + else if (shaderstate.identitylighting == 1) { VectorCopy(shaderstate.curentity->shaderRGBAf, colscale); } + else + { + VectorScale(shaderstate.curentity->shaderRGBAf, shaderstate.identitylighting, colscale); + } colscale[3] = shaderstate.curentity->shaderRGBAf[3]; qglUniform4fvARB(p->handle[perm], 1, (GLfloat*)colscale); @@ -2539,14 +2684,12 @@ static unsigned int BE_Program_Set_Attributes(const program_t *prog, unsigned in break; } } - return attr; } static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass) { program_t *p = shader->prog; int i; - unsigned int attr = 0; int perm; @@ -2558,21 +2701,26 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas else return; } + if (p->handle[perm|PERMUTATION_FRAMEBLEND].glsl && shaderstate.sourcevbo->coord2.gl.addr) + perm |= PERMUTATION_FRAMEBLEND; if (TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_BUMPMAP].glsl) perm |= PERMUTATION_BUMPMAP; if (TEXVALID(shaderstate.curtexnums->specular) && p->handle[perm|PERMUTATION_SPECULAR].glsl) perm |= PERMUTATION_SPECULAR; if (TEXVALID(shaderstate.curtexnums->fullbright) && p->handle[perm|PERMUTATION_FULLBRIGHT].glsl) perm |= PERMUTATION_FULLBRIGHT; - if (TEXVALID(shaderstate.curtexnums->loweroverlay) && p->handle[perm|PERMUTATION_LOWER].glsl) - perm |= PERMUTATION_LOWER; - if (TEXVALID(shaderstate.curtexnums->upperoverlay) && p->handle[perm|PERMUTATION_UPPER].glsl) - perm |= PERMUTATION_UPPER; + if ((TEXVALID(shaderstate.curtexnums->loweroverlay) || TEXVALID(shaderstate.curtexnums->upperoverlay)) && p->handle[perm|PERMUTATION_UPPERLOWER].glsl) + perm |= PERMUTATION_UPPERLOWER; if (r_refdef.gfog_rgbd[3] && p->handle[perm|PERMUTATION_FOG].glsl) perm |= PERMUTATION_FOG; if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET].glsl) perm |= PERMUTATION_OFFSET; + if (shaderstate.currentvao != shaderstate.sourcevbo->vao) + { + shaderstate.currentvao = shaderstate.sourcevbo->vao; + qglBindVertexArray(shaderstate.sourcevbo->vao); + } GL_SelectProgram(p->handle[perm].glsl); if (shaderstate.lastuniform == p->handle[perm].glsl) i = true; @@ -2581,47 +2729,36 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas i = false; shaderstate.lastuniform = p->handle[perm].glsl; } - attr = BE_Program_Set_Attributes(p, perm, i); + BE_Program_Set_Attributes(p, perm, i); BE_SendPassBlendDepthMask(pass->shaderbits); + BE_EnableShaderAttributes(p->attrmask[perm]); if (p->nofixedcompat) { - if (!gl_config.nofixedfunc) - qglDisableClientState(GL_COLOR_ARRAY); - BE_EnableShaderAttributes(attr); for (i = 0; i < pass->numMergedPasses; i++) { - Shader_BindTextureForPass(i, pass+i, false); + Shader_BindTextureForPass(i, pass+i); } //we need this loop to fix up fixed-function stuff for (; i < shaderstate.lastpasstmus; i++) { - GL_LazyBind(i, 0, r_nulltex, false); + GL_LazyBind(i, 0, r_nulltex); } shaderstate.lastpasstmus = pass->numMergedPasses; - - if (!gl_config.nofixedfunc) - { - qglEnableClientState(GL_VERTEX_ARRAY); - GL_ApplyVertexPointer(); - } } else { - BE_EnableShaderAttributes(attr); - qglEnableClientState(GL_VERTEX_ARRAY); GenerateColourMods(pass); for (i = 0; i < pass->numMergedPasses; i++) { - Shader_BindTextureForPass(i, pass+i, true); + Shader_BindTextureForPass(i, pass+i); BE_GeneratePassTC(pass, i); } for (; i < shaderstate.lastpasstmus; i++) { - GL_LazyBind(i, 0, r_nulltex, false); + GL_LazyBind(i, 0, r_nulltex); } shaderstate.lastpasstmus = pass->numMergedPasses; - GL_ApplyVertexPointer(); } BE_SubmitMeshChain(); } @@ -2671,13 +2808,10 @@ void GLBE_SelectMode(backendmode_t mode) case BEM_DEPTHONLY: GL_DeSelectProgram(); /*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/ - qglDisableClientState(GL_COLOR_ARRAY); while(shaderstate.lastpasstmus>0) { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); } - if (qglShadeModel) - qglShadeModel(GL_FLAT); //we don't write or blend anything (maybe alpha test... but mneh) BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS); @@ -2688,20 +2822,27 @@ void GLBE_SelectMode(backendmode_t mode) #ifdef RTLIGHTS case BEM_STENCIL: - GL_DeSelectProgram(); - + /*BEM_STENCIL doesn't support mesh writing*/ BE_PushOffsetShadow(false); - /*BEM_STENCIL doesn't support mesh writing*/ - qglDisableClientState(GL_COLOR_ARRAY); + if (!shaderstate.allblackshader) + { + char *defs[] = {NULL}; + shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config.gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false); + } + //disable all tmus while(shaderstate.lastpasstmus>0) { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); } - qglShadeModel(GL_FLAT); + if (!gl_config.nofixedfunc) + { + GL_DeSelectProgram(); + //replace mode please - BE_SetPassBlendMode(0, PBM_REPLACE); + BE_SetPassBlendMode(0, PBM_REPLACE); + } //we don't write or blend anything (maybe alpha test... but mneh) BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHCLOSERONLY | SBITS_MASK_BITS); @@ -2769,14 +2910,14 @@ void GLBE_SelectMode(backendmode_t mode) case BEM_FOG: while(shaderstate.lastpasstmus>0) { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); } - GL_LazyBind(0, GL_TEXTURE_2D, shaderstate.fogtexture, true); + GL_LazyBind(0, GL_TEXTURE_2D, shaderstate.fogtexture); shaderstate.lastpasstmus = 1; - qglDisableClientState(GL_COLOR_ARRAY); - qglColor4f(1, 1, 1, 1); - qglShadeModel(GL_FLAT); + Vector4Set(shaderstate.pendingcolourflat, 1, 1, 1, 1); + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; BE_SetPassBlendMode(0, PBM_MODULATE); BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY); break; @@ -2786,16 +2927,26 @@ void GLBE_SelectMode(backendmode_t mode) void GLBE_SelectEntity(entity_t *ent) { - if (shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange) - qglDepthRange (gldepthmin, gldepthmax); + if (shaderstate.curentity->flags & Q2RF_DEPTHHACK) + { + if (qglDepthRange) + qglDepthRange (gldepthmin, gldepthmax); + else if (qglDepthRangef) + qglDepthRangef (gldepthmin, gldepthmax); + } shaderstate.curentity = ent; currententity = ent; R_RotateForEntity(shaderstate.modelmatrix, shaderstate.modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model); Matrix4_Invert(shaderstate.modelmatrix, shaderstate.modelmatrixinv); if (qglLoadMatrixf) qglLoadMatrixf(shaderstate.modelviewmatrix); - if (shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange) - qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); + if (shaderstate.curentity->flags & Q2RF_DEPTHHACK) + { + if (qglDepthRange) + qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); + else if (qglDepthRangef) + qglDepthRangef (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); + } shaderstate.lastuniform = 0; } @@ -2912,7 +3063,6 @@ static void DrawMeshes(void) RQuantAdd(RQUANT_ENTBATCHES, 1); } - GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); if (shaderstate.curshader->numdeforms) GenerateVertexDeforms(shaderstate.curshader); else @@ -2976,31 +3126,36 @@ static void DrawMeshes(void) #ifdef warningmsg #pragma warningmsg("fixme: support alpha test") #endif - GL_ApplyVertexPointer(); + GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); + BE_EnableShaderAttributes((1u<indicies.gl.vbo); + BE_EnableShaderAttributes((1u<flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright)) + if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright) && !gl_config.nofixedfunc) { + //FIXME: do this with a shader instead? its not urgent as we can draw the shader normally anyway, just faster. + GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); GL_DeSelectProgram(); - qglColor3f(0,0,0); - qglDisableClientState(GL_COLOR_ARRAY); + shaderstate.pendingcolourvbo = 0; + shaderstate.pendingcolourpointer = NULL; + Vector4Set(shaderstate.pendingcolourflat, 0, 0, 0, 1); while(shaderstate.lastpasstmus>0) { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); } BE_SetPassBlendMode(0, PBM_REPLACE); BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits); - GL_ApplyVertexPointer(); + BE_EnableShaderAttributes((1u<indicies.gl.vbo); GL_DeSelectProgram(); while (passno < shaderstate.curshader->numpasses) { @@ -3052,6 +3208,7 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ m = *meshlist++; shaderstate.dummyvbo.coord.gl.addr = m->xyz_array; + shaderstate.dummyvbo.coord2.gl.addr = m->xyz2_array; shaderstate.dummyvbo.texcoord.gl.addr = m->st_array; shaderstate.dummyvbo.indicies.gl.addr = m->indexes; shaderstate.dummyvbo.normals.gl.addr = m->normals_array; @@ -3116,6 +3273,7 @@ void GLBE_SubmitBatch(batch_t *batch) else { shaderstate.dummyvbo.coord.gl.addr = batch->mesh[0]->xyz_array; + shaderstate.dummyvbo.coord2.gl.addr = batch->mesh[0]->xyz2_array; shaderstate.dummyvbo.texcoord.gl.addr = batch->mesh[0]->st_array; shaderstate.dummyvbo.lmcoord.gl.addr = batch->mesh[0]->lmst_array; shaderstate.dummyvbo.indicies.gl.addr = batch->mesh[0]->indexes; @@ -3561,7 +3719,7 @@ void GLBE_DrawWorld (qbyte *vis) } #ifdef RTLIGHTS - if (r_shadow_realtime_world.value && gl_config.arb_shader_objects) + if (r_shadow_realtime_world.ival && gl_config.arb_shader_objects) shaderstate.identitylighting = r_shadow_realtime_world_lightmaps.value; else #endif diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 5a4ad4e5..591bdc15 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -789,8 +789,7 @@ void R_BloomBlend (void) qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (qglGetError()) - Con_Printf("GL Error whilst rendering bloom\n"); + checkglerror(); PPL_RevertToKnownState(); } diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 2614cd61..3aa6d97e 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -52,6 +52,8 @@ void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, void GL_Upload32(name, data, width, height, flags); break; + case TF_BGRX32: + flags |= IF_NOALPHA; case TF_BGRA32: GL_Upload32_BGRA(name, data, width, height, flags); break; @@ -1468,7 +1470,7 @@ void GL_Upload24BGR_Flip (char *name, qbyte *framedata, int inwidth, int inheigh outheight = 512; if (outwidth*outheight > sizeofuploadmemorybufferintermediate/4) - Sys_Error("MediaGL_ShowFrameBGR_24_Flip: image too big (%i*%i)", inwidth, inheight); + Sys_Error("GL_Upload24BGR_Flip: image too big (%i*%i)", inwidth, inheight); for (y=1 ; y<=outheight ; y++) { @@ -1998,9 +2000,7 @@ void GL_Upload8 (char *name, qbyte *data, int width, int height, unsigned int fl } #endif #endif -checkglerror(); GL_Upload32 (name, trans, width, height, flags); -checkglerror(); } void GL_Upload8FB (qbyte *data, int width, int height, unsigned flags) diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index e27be258..bee41c31 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -1,9 +1,7 @@ #include "quakedef.h" #ifdef TERRAIN -#ifdef GLQUAKE #include "glquake.h" -#endif #include "shader.h" #include "pr_common.h" @@ -428,6 +426,7 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e) } } +#ifdef GLQUAKE if (qrenderer == QR_OPENGL) { if (!s->vbo.coord.gl.vbo) @@ -454,6 +453,7 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e) // Z_Free(mesh->indexes); // mesh->indexes = NULL; } +#endif } mins[2] = s->minh; diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 2b8c2f28..e05d9aba 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -684,7 +684,7 @@ void R_DrawHLModel(entity_t *curent) { 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.texnums[skins[mesh->skinindex]], false); + GL_LazyBind(0, GL_TEXTURE_2D, model.texnums[skins[mesh->skinindex]]); } GL_Draw_HL_AliasFrame((short *) ((qbyte *) model.header + mesh->index), transformed, tex_w, tex_h); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 71277dc2..320dfc4d 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -205,10 +205,6 @@ void RMod_Think (void) #ifdef RUNTIMELIGHTING if (lightmodel) { - if (relitsurface >= lightmodel->numsurfaces) - { - return; - } #ifdef MULTITHREAD if (!relightthreads) { @@ -237,6 +233,10 @@ void RMod_Think (void) for (i = 0; i < relightthreads; i++) relightthread[i] = Sys_CreateThread(RelightThread, lightmodel, THREADP_NORMAL, 0); } + if (relitsurface < lightmodel->numsurfaces) + { + return; + } #else LightFace(relitsurface); RMod_UpdateLightmap(relitsurface); @@ -250,7 +250,7 @@ void RMod_Think (void) Con_Printf("Finished lighting %s\n", lightmodel->name); #ifdef MULTITHREAD - if (relightthread) + if (relightthreads) { int i; wantrelight = false; @@ -288,10 +288,12 @@ void RMod_Think (void) VFS_WRITE(f, "QLIT\1\0\0\0", 8); VFS_WRITE(f, lightmodel->lightdata, numlightdata*3); VFS_CLOSE(f); + COM_FlushFSCache(); } else Con_Printf("Unable to write \"%s\"\n", filename); } + lightmodel = NULL; } } #endif @@ -1666,6 +1668,8 @@ void RMod_LoadLighting (lump_t *l) #ifdef RUNTIMELIGHTING if (r_loadlits.value == 2 && !lightmodel && (!litdata || (!luxdata && r_deluxemapping.ival))) { + if (!litdata) + writelitfile = true; numlightdata = l->filelen; lightmodel = loadmodel; relitsurface = 0; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index f291d40c..4afd430a 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -59,8 +59,11 @@ typedef struct mesh_s unsigned int vbofirstvert; unsigned int vbofirstelement; + float xyz_blendw[2]; + /*arrays used for rendering*/ vecV_t *xyz_array; + vecV_t *xyz2_array; vec3_t *normals_array; /*required for lighting*/ vec3_t *snormals_array;/*required for rtlighting*/ vec3_t *tnormals_array;/*required for rtlighting*/ @@ -268,7 +271,10 @@ typedef struct vbo_s vboarray_t indicies; void *vertdata; /*internal use*/ + int vao; + unsigned int vaodynamic; /*mask of the attributes that are dynamic*/ vboarray_t coord; + vboarray_t coord2; vboarray_t texcoord; vboarray_t lmcoord; diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index ab048fa5..618fec66 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -61,6 +61,7 @@ static void R_LineGraph (int x, int h) ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)0xff; } +/* static void Draw_CharToNetGraph (int x, int y, int num) { int row, col; @@ -83,7 +84,7 @@ static void Draw_CharToNetGraph (int x, int y, int num) source += 128; } } - +*/ /* ============== diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 14f35134..d69437a3 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -133,6 +133,8 @@ void GL_InitSceneProcessingShaders (void) { GL_InitSceneProcessingShaders_WaterWarp(); } + + gl_dither.modified = true; //fixme: bad place for this, but hey } #define PP_WARP_TEX_SIZE 64 @@ -456,8 +458,9 @@ void R_SetupGL (void) qglLoadMatrixf(r_refdef.m_view); } - if (!gl_config.gles) + if (!gl_config.gles && gl_dither.modified) { + gl_dither.modified = false; if (gl_dither.ival) { qglEnable(GL_DITHER); @@ -785,6 +788,8 @@ void R_Clear (void) } if (qglDepthRange) qglDepthRange (gldepthmin, gldepthmax); + else if (qglDepthRangef) + qglDepthRangef (gldepthmin, gldepthmax); } #if 0 @@ -868,7 +873,7 @@ static void R_RenderMotionBlur(void) PPL_RevertToKnownState(); - GL_LazyBind(0, GL_TEXTURE_2D, sceneblur_texture, false); + GL_LazyBind(0, GL_TEXTURE_2D, sceneblur_texture); // go 2d qglMatrixMode(GL_PROJECTION); @@ -1089,8 +1094,7 @@ void GLR_RenderView (void) { double time1 = 0, time2; - if (qglGetError()) - Con_Printf("GL Error before drawing scene\n"); + checkglerror(); if (r_norefresh.value || !vid.pixelwidth || !vid.pixelheight) { @@ -1167,8 +1171,7 @@ void GLR_RenderView (void) // Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); } - while (qglGetError()) - Con_Printf("GL Error drawing scene\n"); + checkglerror(); if (r_refdef.flags & Q2RDF_NOWORLDMODEL) return; @@ -1202,8 +1205,7 @@ void GLR_RenderView (void) } } - if (qglGetError()) - Con_Printf("GL Error drawing post processing\n"); + checkglerror(); } #endif diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index eb506ae2..69356d5b 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -56,7 +56,9 @@ void GLBE_ClearVBO(vbo_t *vbo) memset(vbo, 0, sizeof(*vbo)); } -static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int elementsize) +void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic); + +static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int elementsize, unsigned int vaodynamic) { unsigned int vbos[2]; @@ -64,21 +66,6 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int return false; qglGenBuffersARB(1+(elementsize>0), vbos); - GL_SelectVBO(vbos[0]); - qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vsize, vdata, GL_STATIC_DRAW_ARB); - if (elementsize>0) - { - GL_SelectEBO(vbos[1]); - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, elementsize, edata, GL_STATIC_DRAW_ARB); - } - - if (qglGetError()) - { - GL_SelectVBO(0); - GL_SelectEBO(0); - qglDeleteBuffersARB(1+(elementsize>0), vbos); - return false; - } //opengl ate our data, fixup the vbo arrays to point to the vbo instead of the raw data @@ -123,6 +110,14 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int vbo->colours.gl.addr = (vec4_t*)((char*)vbo->colours.gl.addr - (char*)vdata); } + GLBE_SetupVAO(vbo, vaodynamic); + + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vsize, vdata, GL_STATIC_DRAW_ARB); + if (elementsize>0) + { + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, elementsize, edata, GL_STATIC_DRAW_ARB); + } + return true; } @@ -291,7 +286,7 @@ void GLBE_GenBrushModelVBO(model_t *mod) vcount += v; } - if (GL_BuildVBO(vbo, vbo->vertdata, vcount*pervertsize, indicies, ecount*sizeof(index_t))) + if (GL_BuildVBO(vbo, vbo->vertdata, vcount*pervertsize, indicies, ecount*sizeof(index_t), 0)) { BZ_Free(vbo->vertdata); vbo->vertdata = NULL; diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 237138f2..dc9001ba 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -224,7 +224,25 @@ char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight) int i, c; qbyte *ret; - if (gl_config.gles) + /*if (1) + { + float *p; + + p = BZ_Malloc(vid.pixelwidth*vid.pixelheight*sizeof(float)); + qglReadPixels (0, 0, vid.pixelwidth, vid.pixelheight, GL_DEPTH_COMPONENT, GL_FLOAT, p); + + ret = BZ_Malloc(prepadbytes + vid.pixelwidth*vid.pixelheight*3); + + c = vid.pixelwidth*vid.pixelheight; + for (i = 1; i < c; i++) + { + ret[prepadbytes+i*3+0]=p[i]*p[i]*p[i]*255; + ret[prepadbytes+i*3+1]=p[i]*p[i]*p[i]*255; + ret[prepadbytes+i*3+2]=p[i]*p[i]*p[i]*255; + } + BZ_Free(p); + } + else*/ if (gl_config.gles) { qbyte *p; diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 32dff6db..96b2c0a0 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -804,11 +804,11 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip "#define BUMP\n", "#define SPECULAR\n", "#define FULLBRIGHT\n", - "#define LOWER\n", - "#define UPPER\n", + "#define UPPERLOWER\n", "#define OFFSETMAPPING\n", "#define SKELETAL\n", "#define FOG\n", + "#define FRAMEBLEND\n", NULL }; char *permutationdefines[sizeof(permutationname)/sizeof(permutationname[0]) + 64 + 1]; @@ -824,11 +824,14 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip cvarnames[cvarcount] = NULL; + prog->nofixedcompat = true; for(;;) { while (*script == ' ' || *script == '\r' || *script == '\n' || *script == '\t') script++; - if (!strncmp(script, "!!cvarf", 7)) + if (!strncmp(script, "!!fixed", 7)) + prog->nofixedcompat = false; + else if (!strncmp(script, "!!cvarf", 7)) { script += 7; while (*script == ' ' || *script == '\t') @@ -871,8 +874,13 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip for (p = 0; permutationname[p]; p++) { if (!strncmp(permutationname[p]+8, script, end - script) && permutationname[p][8+end-script] == '\n') + { nopermutation &= ~(1u<failed = !Shader_LoadPermutations(name, &g->prog, sbuiltins[i].body, sbuiltins[i].qrtype, sbuiltins[i].apiver); + g->failed = !Shader_LoadPermutations(name, &g->prog, sbuiltins[i].body, sbuiltins[i].qrtype, ver); + + if (g->failed) + continue; g->prog.refs++; return &g->prog; @@ -2481,19 +2496,24 @@ void Shader_WriteOutGenerics_f(void) } } -struct shader_field_names_s shader_field_names[] = +struct shader_field_names_s shader_attr_names[] = { /*vertex attributes*/ - {"v_position", SP_ATTR_VERTEX}, - {"v_colour", SP_ATTR_COLOUR}, - {"v_texcoord", SP_ATTR_TEXCOORD}, - {"v_lmcoord", SP_ATTR_LMCOORD}, - {"v_normal", SP_ATTR_NORMALS}, - {"v_svector", SP_ATTR_SNORMALS}, - {"v_tvector", SP_ATTR_TNORMALS}, - {"v_bone", SP_ATTR_BONENUMS}, - {"v_weight", SP_ATTR_BONEWEIGHTS}, + {"v_position", VATTR_VERTEX1}, + {"v_position2", VATTR_VERTEX2}, + {"v_colour", VATTR_COLOUR}, + {"v_texcoord", VATTR_TEXCOORD}, + {"v_lmcoord", VATTR_LMCOORD}, + {"v_normal", VATTR_NORMALS}, + {"v_svector", VATTR_SNORMALS}, + {"v_tvector", VATTR_TNORMALS}, + {"v_bone", VATTR_BONENUMS}, + {"v_weight", VATTR_BONEWEIGHTS}, + {NULL} +}; +struct shader_field_names_s shader_unif_names[] = +{ /*matricies*/ {"m_model", SP_M_MODEL}, {"m_view", SP_M_VIEW}, @@ -2509,6 +2529,7 @@ struct shader_field_names_s shader_field_names[] = {"w_fog", SP_W_FOG}, /*ent properties*/ + {"e_vblend", SP_E_VBLEND}, {"e_lmscale", SP_E_LMSCALE}, /*overbright shifting*/ {"e_origin", SP_E_ORIGIN}, {"e_time", SP_E_TIME}, @@ -2546,10 +2567,27 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { - if (gl_config.nofixedfunc) - prog->nofixedcompat = true; + //figure out visible attributes + for (p = 0; p < PERMUTATIONS; p++) + { + if (!prog->handle[p].glsl) + continue; + GLSlang_UseProgram(prog->handle[p].glsl); + for (i = 0; shader_attr_names[i].name; i++) + { + uniformloc = qglGetAttribLocationARB(prog->handle[p].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<handle[p].glsl) continue; GLSlang_UseProgram(prog->handle[p].glsl); - if (shader_field_names[i].ptype >= SP_FIRSTUNIFORM) - uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, shader_field_names[i].name); - else - uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, shader_field_names[i].name); + + uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, shader_unif_names[i].name); if (uniformloc != -1) found = true; + if (prog->numparams == SHADER_PROGPARMS_MAX) { if (found) @@ -2574,14 +2611,11 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty if (found) { if (prog->numparams == SHADER_PROGPARMS_MAX) - Con_Printf("Too many paramters for program (ignoring %s)\n", shader_field_names[i].name); + Con_Printf("Too many paramters for program (ignoring %s)\n", shader_unif_names[i].name); else { - prog->parm[prog->numparams].type = shader_field_names[i].ptype; + prog->parm[prog->numparams].type = shader_unif_names[i].ptype; prog->numparams++; - - if (shader_field_names[i].ptype < SP_FIRSTUNIFORM) - prog->nofixedcompat = true; } } } @@ -2624,6 +2658,8 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty { if (!prog->handle[p].glsl) continue; + if (!(prog->attrmask[p] & (1u<attrmask[p] |= (1u<handle[p].glsl); for (i = 0; i < 8; i++) { @@ -2670,28 +2706,20 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty } } } - for (i = 0; shader_field_names[i].name; i++) + for (i = 0; shader_unif_names[i].name; i++) { found = false; for (p = 0; p < PERMUTATIONS; p++) { - if (shader_field_names[i].ptype >= SP_FIRSTUNIFORM) - { - uniformloc = D3DShader_FindUniform(&prog->handle[p], 0, shader_field_names[i].name); - } - else - uniformloc = -1; + uniformloc = D3DShader_FindUniform(&prog->handle[p], 0, shader_unif_names[i].name); if (uniformloc != -1) found = true; prog->parm[prog->numparams].handle[p] = uniformloc; } if (found) { - prog->parm[prog->numparams].type = shader_field_names[i].ptype; + prog->parm[prog->numparams].type = shader_unif_names[i].ptype; prog->numparams++; - - if (shader_field_names[i].ptype < SP_FIRSTUNIFORM) - prog->nofixedcompat = true; } } /*set texture uniforms*/ @@ -2904,11 +2932,10 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p if (!prog->handle[p].glsl) continue; GLSlang_UseProgram(prog->handle[p].glsl); - if (parmtype >= SP_FIRSTUNIFORM) - uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, token); - else - uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, token); + + uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, token); prog->parm[prog->numparams].handle[p] = uniformloc; + if (uniformloc != -1) { foundone = true; @@ -3186,7 +3213,7 @@ static void Shaderpass_VideoMap (shader_t *shader, shaderpass_t *pass, char **pt pass->cin = Media_StartCin(token); if (!pass->cin) pass->cin = Media_StartCin(va("video/%s.roq", token)); - else + if (!pass->cin) Con_DPrintf (CON_WARNING "(shader %s) Couldn't load video %s\n", shader->name, token); if (pass->cin) diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 26141764..0fd67b18 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -2310,6 +2310,11 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q if (!r_drawentities.value) return; +#ifdef GLQUAKE + if (gl_config.nofixedfunc) + return; /*hackzone*/ +#endif + // draw sprites seperately, because of alpha blending for (i=0 ; icolor[0], dl->color[1], dl->color[2]); qglDisable(GL_STENCIL_TEST); @@ -2465,7 +2469,6 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) // qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); Sh_DrawStencilLightShadows(dl, lvis, vvis, false); qglDisable(GL_POLYGON_OFFSET_FILL); - checkglerror(); qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } #endif @@ -2741,7 +2744,7 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches) /*requires an FBO, as stated above*/ if (!gl_config.ext_framebuffer_objects) return; -//checkglerror(); + if (!crepuscular_fbo_id) { qglGenFramebuffersEXT(1, &crepuscular_fbo_id); @@ -2772,20 +2775,15 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches) } else qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, crepuscular_fbo_id); -//checkglerror(); BE_SelectMode(BEM_CREPUSCULAR); BE_SelectDLight(dl, colours); -//checkglerror(); GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_BLEND); -//checkglerror(); //fixme: check regular post-proc qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - checkglerror(); BE_SelectMode(BEM_STANDARD); GLBE_DrawMesh_Single(crepuscular_shader, &mesh, NULL, &crepuscular_shader->defaulttextures, 0); - checkglerror(); #endif } @@ -2844,14 +2842,6 @@ void Sh_DrawLights(qbyte *vis, batch_t **mbatches) #ifdef GLQUAKE case QR_OPENGL: /*no stencil?*/ - if (gl_config.nofixedfunc) - { - Con_Printf("FTE does not support stencil shadows without a fixed-function pipeline\n"); - r_shadow_realtime_world.ival = 0; - r_shadow_realtime_dlight.ival = 0; - return; - } - if (!gl_config.arb_shader_objects) { Con_Printf("Missing GL extensions: switching off realtime lighting.\n"); diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 85f4daae..4ce2ca53 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -27,6 +27,7 @@ void (APIENTRY *qglCullFace) (GLenum mode); void (APIENTRY *qglDepthFunc) (GLenum func); void (APIENTRY *qglDepthMask) (GLboolean flag); void (APIENTRY *qglDepthRange) (GLclampd zNear, GLclampd zFar); +void (APIENTRY *qglDepthRangef) (GLclampf zNear, GLclampf zFar); void (APIENTRY *qglDisable) (GLenum cap); void (APIENTRY *qglDrawBuffer) (GLenum mode); void (APIENTRY *qglDrawPixels) (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); @@ -113,6 +114,9 @@ void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei size, void *(APIENTRY *qglMapBufferARB)(GLenum target, GLenum access); GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target); +void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays); +void (APIENTRY *qglBindVertexArray)(GLuint vaoarray); + const GLubyte * (APIENTRY * qglGetStringi) (GLenum name, GLuint index); void (APIENTRY *qglGenFramebuffersEXT)(GLsizei n, GLuint* ids); @@ -165,6 +169,7 @@ FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; FTEPFNGLUNIFORM3FVARBPROC qglUniform3fvARB; +FTEPFNGLUNIFORM4FVARBPROC qglUniform2fvARB; FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB; FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; @@ -345,17 +350,68 @@ void APIENTRY GL_ClientStateStub(GLenum array) #define getglcore getglfunction #define getglext(name) getglfunction(name) -void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) +void GL_CheckExtensions (void *(*getglfunction) (char *name)) { + unsigned int gl_major_version = 0; + unsigned int gl_minor_version = 0; memset(&gl_config, 0, sizeof(gl_config)); - gl_config.glversion = ver; - if (!strncmp(gl_version, "OpenGL ES", 9)) gl_config.gles = true; else gl_config.gles = false; + if (!gl_config.gles) + { + if (qglGetError()) + Con_Printf("glGetError %s:%i\n", __FILE__, __LINE__); + qglGetIntegerv(GL_MAJOR_VERSION, &gl_major_version); + qglGetIntegerv(GL_MINOR_VERSION, &gl_minor_version); + } + if (!gl_major_version || qglGetError()) + { + /*GL_MAJOR_VERSION not supported? try and parse (es-aware)*/ + const char *s; + for (s = gl_version; *s && (*s < '0' || *s > '9'); s++) + ; + gl_major_version = atoi(s); + while(*s >= '0' && *s <= '9') + s++; + if (*s == '.') + s++; + gl_minor_version = atoi(s); + } + 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*/ + { + int i; + qglGetIntegerv(GL_NUM_EXTENSIONS, &gl_num_extensions); + if (developer.value) + { + Con_Printf ("GL_EXTENSIONS:\n"); + for (i = 0; i < gl_num_extensions; i++) + { + Con_Printf (" %s", qglGetStringi(GL_EXTENSIONS, i)); + Con_Printf("\n"); + } + Con_Printf ("end of list\n"); + } + else + Con_DPrintf ("GL_EXTENSIONS: %i extensions\n", gl_num_extensions); + gl_extensions = NULL; + } + else + { + gl_num_extensions = 0; + gl_extensions = qglGetString (GL_EXTENSIONS); + Con_DPrintf ("GL_EXTENSIONS: %s\n", gl_extensions); + + if (!gl_extensions) + Sys_Error("no extensions\n"); + } + if (gl_config.gles) gl_config.nofixedfunc = gl_config.glversion >= 2; else @@ -481,6 +537,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) mtexid0 = GL_TEXTURE0_ARB; if (!gl_config.nofixedfunc) qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_mtexarbable); + else + gl_mtexarbable = 8; } else if (GL_CheckExtension("GL_ARB_multitexture") && !COM_CheckParm("-noamtex")) { //ARB multitexture is the popular choice. @@ -523,10 +581,12 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) mtexid0 = GL_TEXTURE0_SGIS; } - if (GL_CheckExtension("GL_EXT_stencil_wrap")) + if ((gl_config.gles && gl_config.glversion >= 2) || GL_CheckExtension("GL_EXT_stencil_wrap")) gl_config.ext_stencil_wrap = true; - if (GL_CheckExtension("GL_ATI_separate_stencil")) + if (gl_config.gles && gl_config.glversion >= 2) + qglStencilOpSeparateATI = (void *) getglext("glStencilOpSeparate"); + else if (GL_CheckExtension("GL_ATI_separate_stencil")) qglStencilOpSeparateATI = (void *) getglext("glStencilOpSeparateATI"); if (GL_CheckExtension("GL_EXT_stencil_two_side")) qglActiveStencilFaceEXT = (void *) getglext("glActiveStencilFaceEXT"); @@ -650,6 +710,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) qglUniform4fvARB = (void *)getglext("glUniform4fv"); qglUniform3fARB = (void *)getglext("glUniform3f"); qglUniform3fvARB = (void *)getglext("glUniform3fv"); + qglUniform2fvARB = (void *)getglext("glUniform2fv"); qglUniform1iARB = (void *)getglext("glUniform1i"); qglUniform1fARB = (void *)getglext("glUniform1f"); Con_DPrintf("GLSL available\n"); @@ -686,6 +747,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) qglUniform4fvARB = (void *)getglext("glUniform4fvARB"); qglUniform3fARB = (void *)getglext("glUniform3fARB"); qglUniform3fvARB = (void *)getglext("glUniform3fvARB"); + qglUniform2fvARB = (void *)getglext("glUniform2fvARB"); qglUniform1iARB = (void *)getglext("glUniform1iARB"); qglUniform1fARB = (void *)getglext("glUniform1fARB"); @@ -866,7 +928,7 @@ static const char *glsl_hdrs[] = "uniform float cvar_r_glsl_offsetmapping_scale;\n" "vec2 offsetmap(sampler2D normtex, vec2 base, vec3 eyevector)\n" "{\n" - "#if defined(RELIEFMAPPING)\n" + "#if defined(RELIEFMAPPING) && !defined(GL_ES)\n" "float i, f;\n" "vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * vec2(1.0, -1.0), -1.0);\n" "vec3 RT = vec3(vec2(base.xy"/* - OffsetVector.xy*OffsetMapping_Bias*/"), 1.0);\n" @@ -1038,6 +1100,11 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan { prstrings[strings] = "attribute vec3 v_position;\n" + "#ifdef FRAMEBLEND\n" + "attribute vec3 v_position2;\n" + "uniform vec2 e_vblend;\n" + "#define v_position ((v_position*e_vblend.x)+(v_position2*e_vblend.y))\n" + "#endif\n" "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n" "uniform mat4 m_modelviewprojection;\n" ; @@ -1047,9 +1114,17 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan else { prstrings[strings] = - "#define ftetransform ftransform\n" - "#define v_position gl_Vertex\n" + "#ifdef FRAMEBLEND\n" + "attribute vec3 v_position2;\n" + "uniform vec2 e_vblend;\n" + "#define v_position (gl_Vertex.xyz*e_vblend.x+v_position2*e_vblend.y)\n" + "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n" "uniform mat4 m_modelviewprojection;\n" + "#else\n" + "#define v_position gl_Vertex\n" + "#define ftetransform ftransform\n" + "uniform mat4 m_modelviewprojection;\n" + "#endif\n" ; length[strings] = strlen(prstrings[strings]); strings++; @@ -1159,15 +1234,16 @@ GLhandleARB GLSlang_CreateProgramObject (GLhandleARB vert, GLhandleARB frag, qbo qglAttachObjectARB(program, vert); qglAttachObjectARB(program, frag); - qglBindAttribLocationARB(program, gl_config.nofixedfunc?0:7, "v_position"); - qglBindAttribLocationARB(program, 1, "v_colour"); - qglBindAttribLocationARB(program, 2, "v_texcoord"); - qglBindAttribLocationARB(program, 3, "v_lmcoord"); - qglBindAttribLocationARB(program, 4, "v_normal"); - qglBindAttribLocationARB(program, 5, "v_snormal"); - qglBindAttribLocationARB(program, 6, "v_tnormal"); - qglBindAttribLocationARB(program, 8, "v_bone"); - qglBindAttribLocationARB(program, 9, "v_weight"); + qglBindAttribLocationARB(program, VATTR_VERTEX1, "v_position"); + qglBindAttribLocationARB(program, VATTR_COLOUR, "v_colour"); + qglBindAttribLocationARB(program, VATTR_TEXCOORD, "v_texcoord"); + qglBindAttribLocationARB(program, VATTR_LMCOORD, "v_lmcoord"); + qglBindAttribLocationARB(program, VATTR_NORMALS, "v_normal"); + qglBindAttribLocationARB(program, VATTR_SNORMALS, "v_svector"); + qglBindAttribLocationARB(program, VATTR_TNORMALS, "v_tvector"); + qglBindAttribLocationARB(program, VATTR_BONENUMS, "v_bone"); + qglBindAttribLocationARB(program, VATTR_BONEWEIGHTS, "v_weight"); + qglBindAttribLocationARB(program, VATTR_VERTEX2, "v_position2"); qglLinkProgramARB(program); @@ -1212,6 +1288,8 @@ GLhandleARB GLSlang_CreateProgram(char *name, int ver, char **precompilerconstan qglDeleteShaderObject_(vs); qglDeleteShaderObject_(fs); + checkglerror(); + return handle; } @@ -1228,9 +1306,6 @@ GLint GLSlang_GetUniformLocation (int prog, char *name) //the vid routines have initialised a window, and now they are giving us a reference to some of of GetProcAddress to get pointers to the funcs. void GL_Init(void *(*getglfunction) (char *name)) { - unsigned int gl_major_version; - unsigned int gl_minor_version; - qglAlphaFunc = (void *)getglcore("glAlphaFunc"); qglBegin = (void *)getglcore("glBegin"); qglBlendFunc = (void *)getglcore("glBlendFunc"); @@ -1253,6 +1328,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglDepthFunc = (void *)getglcore("glDepthFunc"); qglDepthMask = (void *)getglcore("glDepthMask"); qglDepthRange = (void *)getglcore("glDepthRange"); + qglDepthRangef = (void *)getglcore("glDepthRangef"); qglDisable = (void *)getglcore("glDisable"); qglDrawBuffer = (void *)getglcore("glDrawBuffer"); qglDrawPixels = (void *)getglcore("glDrawPixels"); @@ -1328,6 +1404,9 @@ void GL_Init(void *(*getglfunction) (char *name)) qglPopAttrib = (void *)getglcore("glPopAttrib"); qglScissor = (void *)getglcore("glScissor"); + qglGenVertexArrays = (void *)getglext("glGenVertexArrays"); + qglBindVertexArray = (void *)getglext("glBindVertexArray"); + //does this need to be non-core as well? qglFogi = (void *)getglcore("glFogi"); qglFogf = (void *)getglcore("glFogf"); @@ -1357,52 +1436,7 @@ void GL_Init(void *(*getglfunction) (char *name)) gl_version = qglGetString (GL_VERSION); Con_SafePrintf ("GL_VERSION: %s\n", gl_version); - if (qglGetError()) - Con_Printf("glGetError %s:%i\n", __FILE__, __LINE__); - qglGetIntegerv(GL_MAJOR_VERSION, &gl_major_version); - qglGetIntegerv(GL_MINOR_VERSION, &gl_minor_version); - if (qglGetError()) - { - /*GL_MAJOR_VERSION not supported? try and parse (es-aware)*/ - const char *s; - for (s = gl_version; *s && (*s < '0' || *s > '9'); s++) - ; - gl_major_version = atoi(s); - while(*s >= '0' && *s <= '9') - s++; - if (*s == '.') - s++; - gl_minor_version = atoi(s); - } - /*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*/ - { - int i; - qglGetIntegerv(GL_NUM_EXTENSIONS, &gl_num_extensions); - if (developer.value) - { - Con_Printf ("GL_EXTENSIONS:\n"); - for (i = 0; i < gl_num_extensions; i++) - { - Con_Printf (" %s", qglGetStringi(GL_EXTENSIONS, i)); - Con_Printf("\n"); - } - Con_Printf ("end of list\n"); - } - else - Con_DPrintf ("GL_EXTENSIONS: %i extensions\n", gl_num_extensions); - gl_extensions = NULL; - } - else - { - gl_num_extensions = 0; - gl_extensions = qglGetString (GL_EXTENSIONS); - Con_DPrintf ("GL_EXTENSIONS: %s\n", gl_extensions); - - if (!gl_extensions) - Sys_Error("no extensions\n"); - } - GL_CheckExtensions (getglfunction, gl_major_version + (gl_minor_version/10.f)); + GL_CheckExtensions (getglfunction); if (gl_config.gles && gl_config.glversion >= 2) { diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 2f9e81dd..ee93aabb 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -178,6 +178,157 @@ static qboolean usingminidriver; static char reqminidriver[MAX_OSPATH]; static char opengldllname[MAX_OSPATH]; +#ifdef _DEBUG +static char *gles2funcs[] = +{ +#define f(n) #n, + f(glActiveTexture) + f(glAttachShader) + f(glBindAttribLocation) + f(glBindBuffer) + f(glBindFramebuffer) + f(glBindRenderbuffer) + f(glBindTexture) + f(glBlendColor) + f(glBlendEquation) + f(glBlendEquationSeparate) + f(glBlendFunc) + f(glBlendFuncSeparate) + f(glBufferData) + f(glBufferSubData) + f(glCheckFramebufferStatus) + f(glClear) + f(glClearColor) + f(glClearDepthf) + f(glClearStencil) + f(glColorMask) + f(glCompileShader) + f(glCompressedTexImage2D) + f(glCompressedTexSubImage2D) + f(glCopyTexImage2D) + f(glCopyTexSubImage2D) + f(glCreateProgram) + f(glCreateShader) + f(glCullFace) + f(glDeleteBuffers) + f(glDeleteFramebuffers) + f(glDeleteProgram) + f(glDeleteRenderbuffers) + f(glDeleteShader) + f(glDeleteTextures) + f(glDepthFunc) + f(glDepthMask) + f(glDepthRangef) + f(glDetachShader) + f(glDisable) + f(glDisableVertexAttribArray) + f(glDrawArrays) + f(glDrawElements) + f(glEnable) + f(glEnableVertexAttribArray) + f(glFinish) + f(glFlush) + f(glFramebufferRenderbuffer) + f(glFramebufferTexture2D) + f(glFrontFace) + f(glGenBuffers) + f(glGenerateMipmap) + f(glGenFramebuffers) + f(glGenRenderbuffers) + f(glGenTextures) + f(glGetActiveAttrib) + f(glGetActiveUniform) + f(glGetAttachedShaders) + f(glGetAttribLocation) + f(glGetBooleanv) + f(glGetBufferParameteriv) + f(glGetError) + f(glGetFloatv) + f(glGetFramebufferAttachmentParameteriv) + f(glGetIntegerv) + f(glGetProgramiv) + f(glGetProgramInfoLog) + f(glGetRenderbufferParameteriv) + f(glGetShaderiv) + f(glGetShaderInfoLog) + f(glGetShaderPrecisionFormat) + f(glGetShaderSource) + f(glGetString) + f(glGetTexParameterfv) + f(glGetTexParameteriv) + f(glGetUniformfv) + f(glGetUniformiv) + f(glGetUniformLocation) + f(glGetVertexAttribfv) + f(glGetVertexAttribiv) + f(glGetVertexAttribPointerv) + f(glHint) + f(glIsBuffer) + f(glIsEnabled) + f(glIsFramebuffer) + f(glIsProgram) + f(glIsRenderbuffer) + f(glIsShader) + f(glIsTexture) + f(glLineWidth) + f(glLinkProgram) + f(glPixelStorei) + f(glPolygonOffset) + f(glReadPixels) + f(glReleaseShaderCompiler) + f(glRenderbufferStorage) + f(glSampleCoverage) + f(glScissor) + f(glShaderBinary) + f(glShaderSource) + f(glStencilFunc) + f(glStencilFuncSeparate) + f(glStencilMask) + f(glStencilMaskSeparate) + f(glStencilOp) + f(glStencilOpSeparate) + f(glTexImage2D) + f(glTexParameterf) + f(glTexParameterfv) + f(glTexParameteri) + f(glTexParameteriv) + f(glTexSubImage2D) + f(glUniform1f) + f(glUniform1fv) + f(glUniform1i) + f(glUniform1iv) + f(glUniform2f) + f(glUniform2fv) + f(glUniform2i) + f(glUniform2iv) + f(glUniform3f) + f(glUniform3fv) + f(glUniform3i) + f(glUniform3iv) + f(glUniform4f) + f(glUniform4fv) + f(glUniform4i) + f(glUniform4iv) + f(glUniformMatrix2fv) + f(glUniformMatrix3fv) + f(glUniformMatrix4fv) + f(glUseProgram) + f(glValidateProgram) + f(glVertexAttrib1f) + f(glVertexAttrib1fv) + f(glVertexAttrib2f) + f(glVertexAttrib2fv) + f(glVertexAttrib3f) + f(glVertexAttrib3fv) + f(glVertexAttrib4f) + f(glVertexAttrib4fv) + f(glVertexAttribPointer) + f(glViewport) + f(wglCreateContextAttribsARB) + NULL +}; +#endif + //just GetProcAddress with a safty net. void *getglfunc(char *name) { @@ -187,9 +338,24 @@ void *getglfunc(char *name) { proc = GetProcAddress(hInstGL, name); TRACE(("dbg: getglfunc: gpa %s: success %i\n", name, !!proc)); - return proc; } - TRACE(("dbg: getglfunc: glgpa %s: success %i\n", name, !!proc)); + else + { + TRACE(("dbg: getglfunc: glgpa %s: success %i\n", name, !!proc)); + } + +#ifdef _DEBUG + if (vid_gl_context_es2.ival == 2) + { + int i; + for (i = 0; gles2funcs[i]; i++) + { + if (!strcmp(name, gles2funcs[i])) + return proc; + } + return NULL; + } +#endif return proc; } void *getwglfunc(char *name) @@ -982,7 +1148,7 @@ qboolean VID_AttachGL (rendererstate_t *info) } qwglCreateContextAttribsARB = getglfunc("wglCreateContextAttribsARB"); -#ifdef _DEBUG +#if 1//def _DEBUG //attempt to promote that to opengl3. if (qwglCreateContextAttribsARB) { diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 9ce54720..81385f0b 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -633,7 +633,7 @@ static void GL_DrawSkyGrid (texture_t *tex) int i; float time = cl.gametime+realtime-cl.gametimemark; - GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.base, false); + GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.base); speedscale = time*8; speedscale -= (int)speedscale & ~127; @@ -646,7 +646,7 @@ static void GL_DrawSkyGrid (texture_t *tex) } qglEnable (GL_BLEND); - GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.fullbright, false); + GL_LazyBind(0, GL_TEXTURE_2D, tex->shader->defaulttextures.fullbright); speedscale = time*16; speedscale -= (int)speedscale & ~127; diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 1b4a466d..9f587f59 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -161,6 +161,7 @@ typedef void (APIENTRYP FTEPFNGLUNIFORMMATRIXPROC) (GLint location, GLsizei co typedef void (APIENTRYP FTEPFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, GLfloat *value); typedef void (APIENTRYP FTEPFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRYP FTEPFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, GLfloat *value); +typedef void (APIENTRYP FTEPFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, GLfloat *value); typedef void (APIENTRYP FTEPFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); typedef void (APIENTRYP FTEPFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); @@ -307,8 +308,8 @@ void Sh_PreGenerateLights(void); #ifdef GLQUAKE void R_TranslatePlayerSkin (int playernum); -void GL_MTBind(int tmu, int target, texid_t texnum); /*use this if you're going to change the texture object*/ -void GL_LazyBind(int tmu, int target, texid_t texnum, qboolean arrays); /*use this if you don't care about the object itself, only that it is bound*/ +void GL_MTBind(int tmu, int target, texid_t texnum); /*use this if you're going to change the texture object (ensures glActiveTexture(tmu))*/ +void GL_LazyBind(int tmu, int target, texid_t texnum); /*use this if you don't care about the active tmu, only that it is bound on that tmu (does not guarentee glActiveTexture) (ie: no glTexImage etc)*/ void GL_CullFace(unsigned int sflags); void GL_TexEnv(GLenum mode); void GL_FlushBackEnd (void); @@ -408,7 +409,7 @@ void R_SaveRTLights_f(void); // // gl_heightmap.c // -#ifdef GLQUAKE +#ifdef TERRAIN void GL_DrawHeightmapModel (batch_t **batch, entity_t *e); qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer); void HeightMap_Purge(model_t *mod); @@ -511,6 +512,7 @@ extern void (APIENTRY *qglDeleteTextures) (GLsizei n, const GLuint *textures); extern void (APIENTRY *qglDepthFunc) (GLenum func); extern void (APIENTRY *qglDepthMask) (GLboolean flag); extern void (APIENTRY *qglDepthRange) (GLclampd zNear, GLclampd zFar); +extern void (APIENTRY *qglDepthRangef) (GLclampf zNear, GLclampf zFar); extern void (APIENTRY *qglDisable) (GLenum cap); extern void (APIENTRY *qglDisableClientState) (GLenum array); extern void (APIENTRY *qglDrawArrays) (GLenum mode, GLint first, GLsizei count); @@ -808,6 +810,9 @@ extern void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei extern void *(APIENTRY *qglMapBufferARB)(GLenum target, GLenum access); extern GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target); +extern void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays); +extern void (APIENTRY *qglBindVertexArray)(GLuint vaoarray); + extern const GLubyte * (APIENTRY * qglGetStringi) (GLenum name, GLuint index); extern void (APIENTRY *qglGenFramebuffersEXT)(GLsizei n, GLuint* ids); @@ -859,6 +864,7 @@ extern FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; extern FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; extern FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; extern FTEPFNGLUNIFORM3FVARBPROC qglUniform3fvARB; +extern FTEPFNGLUNIFORM2FVARBPROC qglUniform2fvARB; extern FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB; extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; @@ -882,6 +888,7 @@ void GL_SelectProgram(int program); #endif + extern FTEPFNGLLOCKARRAYSEXTPROC qglLockArraysEXT; extern FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT; diff --git a/engine/gl/shader.h b/engine/gl/shader.h index a573b7ad..d38823e6 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -258,32 +258,43 @@ enum{ PERMUTATION_BUMPMAP = 1, PERMUTATION_SPECULAR = 2, PERMUTATION_FULLBRIGHT = 4, - PERMUTATION_LOWER = 8, - PERMUTATION_UPPER = 16, - PERMUTATION_OFFSET = 32, - PERMUTATION_SKELETAL = 64, - PERMUTATION_FOG = 128, - + PERMUTATION_UPPERLOWER = 8, + PERMUTATION_OFFSET = 16, + PERMUTATION_SKELETAL = 32, + PERMUTATION_FOG = 64, + PERMUTATION_FRAMEBLEND = 128, PERMUTATIONS = 256 }; +enum shaderattribs_e +{ + VATTR_LEG_VERTEX, + + VATTR_VERTEX1, + VATTR_VERTEX2, + VATTR_COLOUR, + VATTR_TEXCOORD, + VATTR_LMCOORD, + VATTR_NORMALS, + VATTR_SNORMALS, + VATTR_TNORMALS, + VATTR_BONENUMS, /*skeletal only*/ + VATTR_BONEWEIGHTS, /*skeletal only*/ + + VATTR_LEG_COLOUR, + VATTR_LEG_ELEMENTS, + VATTR_LEG_TMU0, + + + VATTR_LEG_FIRST=VATTR_LEG_COLOUR +}; + typedef struct { enum shaderprogparmtype_e { SP_BAD, //never set (hopefully) - SP_ATTR_VERTEX, - SP_ATTR_COLOUR, - SP_ATTR_TEXCOORD, - SP_ATTR_LMCOORD, - SP_ATTR_NORMALS, - SP_ATTR_SNORMALS, - SP_ATTR_TNORMALS, - SP_ATTR_BONENUMS, /*skeletal only*/ - SP_ATTR_BONEWEIGHTS, /*skeletal only*/ - - SP_FIRSTUNIFORM, //never set - /*entity properties*/ + SP_E_VBLEND, SP_E_LMSCALE, SP_E_ORIGIN, SP_E_COLOURS, @@ -354,6 +365,7 @@ 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]; } program_t; diff --git a/engine/http/httpserver.c b/engine/http/httpserver.c index cd69600e..bdfff5ac 100644 --- a/engine/http/httpserver.c +++ b/engine/http/httpserver.c @@ -332,6 +332,7 @@ cont: } else if (!stricmp(mode, "GET") || !stricmp(mode, "HEAD") || !stricmp(mode, "POST")) { + qboolean gzipped = false; if (*resource != '/') { resource[0] = '/'; @@ -342,10 +343,21 @@ cont: cl->file = IWebGenerateFile(resource+1, content, contentlen); else { - if (!SV_AllowDownload(resource+1)) - cl->file = NULL; - else - cl->file = FS_OpenVFS(resource+1, "rb", FS_GAME); + cl->file = NULL; + if (SV_AllowDownload(resource+1)) + { + char nbuf[MAX_OSPATH]; + if (HTTPmarkup >= 3 && strlen(resource+1) < sizeof(nbuf)-4) + { + sprintf(nbuf, "%s.gz", resource+1); + cl->file = FS_OpenVFS(nbuf, "rb", FS_GAME); + } + + if (cl->file) + gzipped = true; + else + cl->file = FS_OpenVFS(resource+1, "rb", FS_GAME); + } if (!cl->file) { @@ -355,6 +367,8 @@ cont: if (!cl->file) { + IWebPrintf("Download rejected\n"); + if (HTTPmarkup >= 3) msg = "HTTP/1.1 404 Not Found\r\n" "Content-Type: text/plain\r\n" "Content-Length: 15\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n" "404 Bad address"; else if (HTTPmarkup == 2) @@ -373,9 +387,9 @@ cont: else { if (HTTPmarkup>=3) - sprintf(resource, "HTTP/1.1 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"text/html":"text/plain", (int)VFS_GETLEN(cl->file)); + sprintf(resource, "HTTP/1.1 200 OK\r\n" "%s%s" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"Content-Type: text/html\r\n":"", gzipped?"Content-Encoding: gzip\r\nCache-Control: public, max-age=86400\r\n":"", (int)VFS_GETLEN(cl->file)); else if (HTTPmarkup==2) - sprintf(resource, "HTTP/1.0 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"text/html":"text/plain", (int)VFS_GETLEN(cl->file)); + sprintf(resource, "HTTP/1.0 200 OK\r\n" "%s%s" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"Content-Type: text/html\r\n":"", gzipped?"Content-Encoding: gzip\r\nCache-Control: public, max-age=86400\r\n":"", (int)VFS_GETLEN(cl->file)); else if (HTTPmarkup) sprintf(resource, "HTTP/0.9 200 OK\r\n\r\n"); else diff --git a/engine/nacl/gl_vidppapi.c b/engine/nacl/gl_vidppapi.c index d3fa4d87..8813c0a2 100644 --- a/engine/nacl/gl_vidppapi.c +++ b/engine/nacl/gl_vidppapi.c @@ -1,10 +1,13 @@ #include "quakedef.h" #include "glquake.h" -#include "ppapi/c/pp_completion_callback.h" -#include "ppapi/gles2/gl2ext_ppapi.h" -#include "ppapi/c/ppb_graphics_3d.h" -#include "ppapi/c/ppb_instance.h" +#include +#include +#include +#include +#include + +extern PPB_Core *ppb_core; extern PPB_GetInterface sys_gbi; extern PPB_Graphics3D* graphics3d_interface; extern PP_Instance pp_instance; @@ -30,6 +33,7 @@ void GL_DoSwap(void) if (delayedswap) { struct PP_CompletionCallback ccb = { swap_callback, NULL, PP_COMPLETIONCALLBACK_FLAG_OPTIONAL}; + glFlush(); graphics3d_interface->SwapBuffers(glcontext, ccb); delayedswap = false; } @@ -219,6 +223,21 @@ void *PPAPI_GetGLSymbol(char *symname) return NULL; } + +void GL_Resized(int width, int height) +{ + extern cvar_t vid_conautoscale, vid_conwidth; + if (glcontext) + { + graphics3d_interface->ResizeBuffers(glcontext, width, height); + vid.pixelwidth = width; + vid.pixelheight = height; + + Cvar_ForceCallback(&vid_conautoscale); + Cvar_ForceCallback(&vid_conwidth); + } +} + qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) { int32_t attribs[] = {PP_GRAPHICS3DATTRIB_WIDTH, info->width, @@ -259,7 +278,8 @@ void GLVID_Shutdown (void) GL_EndRendering(); GL_DoSwap(); - glTerminatePPAPI(); + ppb_core->ReleaseResource(glcontext); +// glTerminatePPAPI(); } void GLVID_DeInit (void) { diff --git a/engine/nacl/sys_ppapi.c b/engine/nacl/sys_ppapi.c index d8ded1c7..3460122f 100644 --- a/engine/nacl/sys_ppapi.c +++ b/engine/nacl/sys_ppapi.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -46,7 +48,8 @@ PPB_Audio *audio_interface = NULL; PPB_AudioConfig *audioconfig_interface = NULL; PPB_MouseLock *ppb_mouselock_interface = NULL; PPB_Fullscreen *ppb_fullscreen_interface = NULL; -PPB_WebSocket *ppb_websocket_interface = NULL;; +PPB_WebSocket *ppb_websocket_interface = NULL; +PPB_View *ppb_view_instance = NULL; PP_Instance pp_instance; PPB_GetInterface sys_gbi; static double lasttime; @@ -211,6 +214,19 @@ void VARGS Sys_Printf (char *fmt, ...) if (pp_instance) ppb_messaging_interface->PostMessage(pp_instance, CStrToVar(string)); } +void ppp_handlemessage(PP_Instance instance, struct PP_Var message) +{ + char *clean; + const char *msg; + unsigned int len; + msg = ppb_var_interface->VarToUtf8(message, &len); + clean = malloc(len+2); + clean[len+0] = '\n'; + clean[len+1] = 0; + memcpy(clean, msg, len); + Cbuf_AddText(clean, RESTRICT_INSECURE); + free(clean); +} void Sys_Quit (void) { @@ -229,6 +245,10 @@ qboolean Sys_remove (char *path) { return false; } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return false; +} #include static int secbase; @@ -537,8 +557,14 @@ PP_Bool InputEvent_HandleEvent(PP_Instance pp_instance, PP_Resource resource) static void Instance_DidDestroy(PP_Instance instance) { } +void GL_Resized(int width, int height); static void Instance_DidChangeView(PP_Instance instance, PP_Resource view_resource) { + int newwidth; + int newheight; + struct PP_Rect rect; + ppb_view_instance->GetRect(view_resource, &rect); + GL_Resized(rect.size.width, rect.size.height); } static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { @@ -572,6 +598,7 @@ PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface g ppb_mouselock_interface = (PPB_MouseLock*)(get_browser(PPB_MOUSELOCK_INTERFACE)); ppb_fullscreen_interface = (PPB_Fullscreen*)(get_browser(PPB_FULLSCREEN_INTERFACE)); ppb_websocket_interface = (PPB_WebSocket*)(get_browser(PPB_WEBSOCKET_INTERFACE)); + ppb_view_instance = (PPB_View*)(get_browser(PPB_VIEW_INTERFACE)); glInitializePPAPI(sys_gbi); @@ -599,7 +626,7 @@ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) }; return &input_event_interface; } - if (strcmp(interface_name, PPP_MOUSELOCK_INTERFACE ) == 0) + if (strcmp(interface_name, PPP_MOUSELOCK_INTERFACE) == 0) { static PPP_MouseLock mouselock_interface = { @@ -607,6 +634,14 @@ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) }; return &mouselock_interface; } + if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) + { + static PPP_Messaging messaging_interface = + { + ppp_handlemessage + }; + return &messaging_interface; + } return NULL; } PP_EXPORT void PPP_ShutdownModule() diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 8c849307..e19b9430 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -283,6 +283,7 @@ int QCC_CheckParm (char *check); void QCC_BspModels (void) { +/* int p; char *gamedir; int i; @@ -311,6 +312,7 @@ void QCC_BspModels (void) if (result != 0) QCC_Error(ERR_INTERNAL, "QCC_BspModels() system returned non zero (failure) with: qbsp %s/%s ; light -extra %s/%s (%i)\n", gamedir, name, gamedir, name, errno); } +*/ } // CopyString returns an offset from the string heap diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 85609ef0..3c9e81e7 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -831,22 +831,24 @@ void NPP_NQCheckDest(int dest) Con_Printf("Not a client\n"); return; } - if ((cldest && cldest != cl) || writedest) + if (bufferlen && ((cldest && cldest != cl) || writedest)) { Con_Printf("MSG destination changed in the middle of a packet %i.\n", (int)*buffer); NPP_NQFlush(); } + writedest = NULL; cldest = cl; destprim = &cldest->netchan.message.prim; } else { sizebuf_t *ndest = QWWriteDest(dest); - if (cldest || (writedest && writedest != ndest)) + if (bufferlen && (cldest || (writedest && writedest != ndest))) { Con_DPrintf("NQCheckDest: MSG destination changed in the middle of a packet %i.\n", (int)*buffer); NPP_NQFlush(); } + cldest = NULL; writedest = ndest; destprim = &writedest->prim; } @@ -1463,21 +1465,23 @@ void NPP_QWFlush(void) // bufferlen = 0; break; case svc_muzzleflash: - //we need to make a fake muzzleflash position. - multicastpos = 4; + if (bufferlen < 3) + Con_Printf("Dodgy muzzleflash\n"); + else { short data; float org[3]; edict_t *ent = EDICT_NUM(svprogfuncs, LittleShort((*(short*)&buffer[1]))); VectorCopy(ent->v->origin, org); + //we need to make a fake muzzleflash position for multicast to work properly. + multicastpos = 4; data = LittleShort((short)(org[0]*8)); NPP_AddData(&data, sizeof(short)); data = LittleShort((short)(org[1]*8)); NPP_AddData(&data, sizeof(short)); data = LittleShort((short)(org[2]*8)); NPP_AddData(&data, sizeof(short)); - } bufferlen = 0; //can't send this to nq. :( break; @@ -1655,29 +1659,30 @@ void NPP_QWCheckDest(int dest) { if (dest == MSG_ONE) { -/* client_t *cl = Write_GetClient(); + client_t *cl = Write_GetClient(); if (!cl) { Con_Printf("Not a client\n"); return; } - if ((cldest && cldest != cl) || writedest) + if (bufferlen && ((cldest && cldest != cl) || writedest)) { Con_Printf("MSG destination changed in the middle of a packet %i.\n", (int)*buffer); NPP_QWFlush(); } + writedest = NULL; cldest = cl; -*/ - cldest = NULL; + destprim = &cldest->netchan.message.prim; } else { sizebuf_t *ndest = NQWriteDest(dest); - if (cldest || (writedest && writedest != ndest)) + if (bufferlen && (cldest || (writedest && writedest != ndest))) { Con_DPrintf("QWCheckDest: MSG destination changed in the middle of a packet %i.\n", (int)*buffer); NPP_QWFlush(); } + cldest = NULL; writedest = ndest; destprim = &writedest->prim; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 06418842..2c05ac6c 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -4407,8 +4407,7 @@ void QCBUILTIN PF_WriteByte (progfuncs_t *prinst, struct globalvars_s *pr_global NPP_QWWriteByte(dest, (qbyte)G_FLOAT(OFS_PARM1)); return; } -#endif - +#else if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); @@ -4419,11 +4418,13 @@ void QCBUILTIN PF_WriteByte (progfuncs_t *prinst, struct globalvars_s *pr_global } else MSG_WriteByte (QWWriteDest(G_FLOAT(OFS_PARM0)), G_FLOAT(OFS_PARM1)); +#endif } void QCBUILTIN PF_WriteChar (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteChar(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); return; @@ -4438,17 +4439,17 @@ void QCBUILTIN PF_WriteChar (progfuncs_t *prinst, struct globalvars_s *pr_global if (progstype == PROG_NQ || progstype == PROG_H2) { - NPP_NQWriteChar(G_FLOAT(OFS_PARM0), (char)G_FLOAT(OFS_PARM1)); + NPP_NQWriteChar(dest, (char)G_FLOAT(OFS_PARM1)); return; } #ifdef NQPROT else { - NPP_QWWriteChar(G_FLOAT(OFS_PARM0), (char)G_FLOAT(OFS_PARM1)); + NPP_QWWriteChar(dest, (char)G_FLOAT(OFS_PARM1)); return; } #else - if (G_FLOAT(OFS_PARM0) == MSG_ONE) + if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); if (!cl) @@ -4457,13 +4458,14 @@ void QCBUILTIN PF_WriteChar (progfuncs_t *prinst, struct globalvars_s *pr_global ClientReliableWrite_Char(cl, G_FLOAT(OFS_PARM1)); } else - MSG_WriteChar (QWWriteDest(G_FLOAT(OFS_PARM0)), G_FLOAT(OFS_PARM1)); + MSG_WriteChar (QWWriteDest(dest), G_FLOAT(OFS_PARM1)); #endif } void QCBUILTIN PF_WriteShort (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteShort(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); return; @@ -4478,17 +4480,17 @@ void QCBUILTIN PF_WriteShort (progfuncs_t *prinst, struct globalvars_s *pr_globa if (progstype == PROG_NQ || progstype == PROG_H2) { - NPP_NQWriteShort(G_FLOAT(OFS_PARM0), (short)(int)G_FLOAT(OFS_PARM1)); + NPP_NQWriteShort(dest, (short)(int)G_FLOAT(OFS_PARM1)); return; } #ifdef NQPROT else { - NPP_QWWriteShort(G_FLOAT(OFS_PARM0), (short)(int)G_FLOAT(OFS_PARM1)); + NPP_QWWriteShort(dest, (short)(int)G_FLOAT(OFS_PARM1)); return; } #else - if (G_FLOAT(OFS_PARM0) == MSG_ONE) + if (desf == MSG_ONE) { client_t *cl = Write_GetClient(); if (!cl) @@ -4497,13 +4499,14 @@ void QCBUILTIN PF_WriteShort (progfuncs_t *prinst, struct globalvars_s *pr_globa ClientReliableWrite_Short(cl, G_FLOAT(OFS_PARM1)); } else - MSG_WriteShort (QWWriteDest(G_FLOAT(OFS_PARM0)), G_FLOAT(OFS_PARM1)); + MSG_WriteShort (QWWriteDest(dest), G_FLOAT(OFS_PARM1)); #endif } void QCBUILTIN PF_WriteLong (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteLong(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); return; @@ -4518,17 +4521,17 @@ void QCBUILTIN PF_WriteLong (progfuncs_t *prinst, struct globalvars_s *pr_global if (progstype == PROG_NQ || progstype == PROG_H2) { - NPP_NQWriteLong(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + NPP_NQWriteLong(dest, G_FLOAT(OFS_PARM1)); return; } #ifdef NQPROT else { - NPP_QWWriteLong(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + NPP_QWWriteLong(dest, G_FLOAT(OFS_PARM1)); return; } #else - if (G_FLOAT(OFS_PARM0) == MSG_ONE) + if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); if (!cl) @@ -4537,13 +4540,14 @@ void QCBUILTIN PF_WriteLong (progfuncs_t *prinst, struct globalvars_s *pr_global ClientReliableWrite_Long(cl, G_FLOAT(OFS_PARM1)); } else - MSG_WriteLong (QWWriteDest(G_FLOAT(OFS_PARM0)), G_FLOAT(OFS_PARM1)); + MSG_WriteLong (QWWriteDest(dest), G_FLOAT(OFS_PARM1)); #endif } void QCBUILTIN PF_WriteAngle (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteAngle(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); return; @@ -4558,17 +4562,17 @@ void QCBUILTIN PF_WriteAngle (progfuncs_t *prinst, struct globalvars_s *pr_globa if (progstype == PROG_NQ || progstype == PROG_H2) { - NPP_NQWriteAngle(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + NPP_NQWriteAngle(dest, G_FLOAT(OFS_PARM1)); return; } #ifdef NQPROT else { - NPP_QWWriteAngle(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + NPP_QWWriteAngle(dest, G_FLOAT(OFS_PARM1)); return; } #else - if (G_FLOAT(OFS_PARM0) == MSG_ONE) + if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); if (!cl) @@ -4577,13 +4581,14 @@ void QCBUILTIN PF_WriteAngle (progfuncs_t *prinst, struct globalvars_s *pr_globa ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1)); } else - MSG_WriteAngle (QWWriteDest(G_FLOAT(OFS_PARM0)), G_FLOAT(OFS_PARM1)); + MSG_WriteAngle (QWWriteDest(dest), G_FLOAT(OFS_PARM1)); #endif } void QCBUILTIN PF_WriteCoord (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteCoord(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); return; @@ -4598,17 +4603,17 @@ void QCBUILTIN PF_WriteCoord (progfuncs_t *prinst, struct globalvars_s *pr_globa if (progstype == PROG_NQ || progstype == PROG_H2) { - NPP_NQWriteCoord(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + NPP_NQWriteCoord(dest, G_FLOAT(OFS_PARM1)); return; } #ifdef NQPROT else { - NPP_QWWriteCoord(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + NPP_QWWriteCoord(dest, G_FLOAT(OFS_PARM1)); return; } #else - if (G_FLOAT(OFS_PARM0) == MSG_ONE) + if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); if (!cl) @@ -4617,13 +4622,14 @@ void QCBUILTIN PF_WriteCoord (progfuncs_t *prinst, struct globalvars_s *pr_globa ClientReliableWrite_Coord(cl, G_FLOAT(OFS_PARM1)); } else - MSG_WriteCoord (QWWriteDest(G_FLOAT(OFS_PARM0)), G_FLOAT(OFS_PARM1)); + MSG_WriteCoord (QWWriteDest(dest), G_FLOAT(OFS_PARM1)); #endif } void QCBUILTIN PF_WriteFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteFloat(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); return; @@ -4681,7 +4687,8 @@ static void QCBUILTIN PF_WriteString (progfuncs_t *prinst, struct globalvars_s * void QCBUILTIN PF_WriteEntity (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteShort(&csqcmsgbuffer, G_EDICTNUM(prinst, OFS_PARM1)); return; @@ -4696,17 +4703,17 @@ void QCBUILTIN PF_WriteEntity (progfuncs_t *prinst, struct globalvars_s *pr_glob if (progstype == PROG_NQ || progstype == PROG_H2) { - NPP_NQWriteEntity(G_FLOAT(OFS_PARM0), (short)G_EDICTNUM(prinst, OFS_PARM1)); + NPP_NQWriteEntity(dest, (short)G_EDICTNUM(prinst, OFS_PARM1)); return; } #ifdef NQPROT else { - NPP_QWWriteEntity(G_FLOAT(OFS_PARM0), (short)G_EDICTNUM(prinst, OFS_PARM1)); + NPP_QWWriteEntity(dest, (short)G_EDICTNUM(prinst, OFS_PARM1)); return; } #else - if (G_FLOAT(OFS_PARM0) == MSG_ONE) + if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); if (!cl) @@ -4715,7 +4722,7 @@ void QCBUILTIN PF_WriteEntity (progfuncs_t *prinst, struct globalvars_s *pr_glob ClientReliableWrite_Short(cl, G_EDICTNUM(prinst, OFS_PARM1)); } else - MSG_WriteShort (QWWriteDest(G_FLOAT(OFS_PARM0)), G_EDICTNUM(prinst, OFS_PARM1)); + MSG_WriteShort (QWWriteDest(dest), G_EDICTNUM(prinst, OFS_PARM1)); #endif } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 45639078..caa59cda 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -2103,7 +2103,7 @@ client_t *SVC_DirectConnect(void) { /*single player logic*/ if (sv.allocated_client_slots == 1 && net_from.type == NA_LOOPBACK) - if (svs.clients[0].state) + if (svs.clients[0].state >= cs_connected) SV_DropClient(svs.clients); // if at server limits, refuse connection @@ -2320,7 +2320,10 @@ client_t *SVC_DirectConnect(void) else newcl->netchan.compress = false; if (mtu >= 64) + { newcl->netchan.fragmentsize = mtu; + newcl->netchan.message.maxsize = sizeof(newcl->netchan.message_buf); + } newcl->protocol = protocol; #ifdef NQPROT @@ -2793,6 +2796,27 @@ void SVC_ACK (void) Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); } +//returns false to block replies +//this is to mitigate wasted bandwidth if we're used as a udp escilation +qboolean SVC_ThrottleInfo (void) +{ +#define THROTTLE_PPS 20 + static unsigned int blockuntil; + unsigned int curtime = Sys_Milliseconds(); + unsigned int inc = 1000/THROTTLE_PPS; + + /*don't go too far back*/ + //if (blockuntil < curtime - 1000) + if (1000 < curtime - blockuntil) + blockuntil = curtime - 1000; + + /*don't allow it to go beyond curtime or we get issues with the logic above*/ + if (inc > curtime-blockuntil) + return true; + + blockuntil += inc; + return false; +} /* ================= SV_ConnectionlessPacket @@ -2831,12 +2855,21 @@ qboolean SV_ConnectionlessPacket (void) else if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') ) SVC_ACK (); else if (!strcmp(c,"status")) - SVC_Status (); + { + if (SVC_ThrottleInfo()) + SVC_Status (); + } else if (!strcmp(c,"log")) - SVC_Log (); + { + if (SVC_ThrottleInfo()) + SVC_Log (); + } #ifdef Q2SERVER else if (!strcmp(c, "info")) - SVC_InfoQ2 (); + { + if (SVC_ThrottleInfo()) + SVC_InfoQ2 (); + } #endif else if (!strncmp(c,"connect", 7)) { @@ -2881,9 +2914,15 @@ qboolean SV_ConnectionlessPacket (void) #ifdef NQPROT /*for DP*/ else if (!strcmp(c, "getstatus")) - SVC_GetInfo(Cmd_Args(), true); + { + if (SVC_ThrottleInfo()) + SVC_GetInfo(Cmd_Args(), true); + } else if (!strcmp(c, "getinfo")) - SVC_GetInfo(Cmd_Args(), false); + { + if (SVC_ThrottleInfo()) + SVC_GetInfo(Cmd_Args(), false); + } #endif else if (!strcmp(c, "rcon")) SVC_RemoteCommand (); diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 26bdb7bd..1b7e06e3 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -2676,7 +2676,7 @@ void SV_MVDRemove_f (void) // stop recording first; snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, list->name); - if (!FS_Remove(path, FS_GAMEONLY)) + if (FS_Remove(path, FS_GAMEONLY)) { Con_Printf("removing %s...\n", list->name); i++; @@ -2707,7 +2707,7 @@ void SV_MVDRemove_f (void) if (sv.mvdrecording && !strcmp(name, demo.name)) SV_MVDStop_f(); - if (!FS_Remove(path, FS_GAMEONLY)) + if (FS_Remove(path, FS_GAMEONLY)) { Con_Printf("demo %s successfully removed\n", name); } @@ -2745,7 +2745,7 @@ void SV_MVDRemoveNum_f (void) SV_MVDStop_f(); snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name); - if (!FS_Remove(path, FS_GAMEONLY)) + if (FS_Remove(path, FS_GAMEONLY)) { Con_Printf("demo %s succesfully removed\n", name); } @@ -2843,7 +2843,7 @@ void SV_MVDInfoRemove_f (void) snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name); } - if (FS_Remove(path, FS_GAMEONLY)) + if (!FS_Remove(path, FS_GAMEONLY)) Con_Printf("failed to remove the file\n"); else Con_Printf("file removed\n"); } diff --git a/engine/server/sv_rankin.c b/engine/server/sv_rankin.c index 4ea141c2..e0b8b02d 100644 --- a/engine/server/sv_rankin.c +++ b/engine/server/sv_rankin.c @@ -1,5 +1,4 @@ #include "qwsvdef.h" -#include "errno.h" #ifndef CLIENTONLY @@ -24,7 +23,7 @@ typedef struct { #define swapfloat LittleFloat rankfileheader_t rankfileheader; -FILE *rankfile; +vfsfile_t *rankfile; cvar_t rank_autoadd = CVARD("rank_autoadd", "1", "Automatically register players into the ranking system"); cvar_t rank_needlogin = CVARD("rank_needlogin", "0", "If set to 1, prohibits players from joining if they're not already registered."); @@ -41,11 +40,11 @@ void inline READ_PLAYERSTATS(int x, rankstats_t *os) int i; size_t result; - fseek(rankfile, sizeof(rankfileheader_t)+sizeof(rankheader_t)+((x-1)*sizeof(rankinfo_t)), SEEK_SET); - result = fread(os, 1, sizeof(rankstats_t), rankfile); + VFS_SEEK(rankfile, sizeof(rankfileheader_t)+sizeof(rankheader_t)+((x-1)*sizeof(rankinfo_t))); + result = VFS_READ(rankfile, os, sizeof(rankstats_t)); if (result != sizeof(rankstats_t)) - Con_Printf("READ_PLAYERSTATS() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankstats_t),(unsigned int)result,strerror(errno)); + Con_Printf("READ_PLAYERSTATS() fread: expected %lu, result was %u\n",(long unsigned int)sizeof(rankstats_t),(unsigned int)result); os->kills = swaplong(os->kills); os->deaths = swaplong(os->deaths); @@ -63,7 +62,7 @@ void inline WRITE_PLAYERSTATS(int x, rankstats_t *os) rankstats_t ns; int i; - fseek(rankfile, sizeof(rankfileheader_t)+sizeof(rankheader_t)+((x-1)*sizeof(rankinfo_t)), SEEK_SET); + VFS_SEEK(rankfile, sizeof(rankfileheader_t)+sizeof(rankheader_t)+((x-1)*sizeof(rankinfo_t))); ns.kills = swaplong(os->kills); ns.deaths = swaplong(os->deaths); @@ -75,19 +74,19 @@ void inline WRITE_PLAYERSTATS(int x, rankstats_t *os) ns.pad2 = (os->pad2); ns.pad3 = (os->pad3); - fwrite(&ns, 1, sizeof(rankstats_t), rankfile); + VFS_WRITE(rankfile, &ns, sizeof(rankstats_t)); } void inline READ_PLAYERHEADER(int x, rankheader_t *oh) { size_t result; - fseek(rankfile, sizeof(rankfileheader_t)+((x-1)*sizeof(rankinfo_t)), SEEK_SET); + VFS_SEEK(rankfile, sizeof(rankfileheader_t)+((x-1)*sizeof(rankinfo_t))); - result = fread(oh, 1, sizeof(rankheader_t), rankfile); + result = VFS_READ(rankfile, oh, sizeof(rankheader_t)); if (result != sizeof(rankheader_t)) - Con_Printf("READ_PLAYERHEADER() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankheader_t),(unsigned int)result,strerror(errno)); + Con_Printf("READ_PLAYERHEADER() fread: expected %lu, result was %u\n",(long unsigned int)sizeof(rankheader_t),(unsigned int)result); oh->prev = swaplong(oh->prev); //score is held for convineance. oh->next = swaplong(oh->next); @@ -100,7 +99,7 @@ void inline WRITE_PLAYERHEADER(int x, rankheader_t *oh) { rankheader_t nh; - fseek(rankfile, sizeof(rankfileheader_t)+((x-1)*sizeof(rankinfo_t)), SEEK_SET); + VFS_SEEK(rankfile, sizeof(rankfileheader_t)+((x-1)*sizeof(rankinfo_t))); nh.prev = swaplong(oh->prev); //score is held for convineance. nh.next = swaplong(oh->next); @@ -108,7 +107,7 @@ void inline WRITE_PLAYERHEADER(int x, rankheader_t *oh) nh.pwd = swaplong(oh->pwd); nh.score = swapfloat(oh->score); - fwrite(&nh, 1, sizeof(rankheader_t), rankfile); + VFS_WRITE(rankfile, &nh, sizeof(rankheader_t)); } void inline READ_PLAYERINFO(int x, rankinfo_t *inf) @@ -127,8 +126,8 @@ void inline WRITEHEADER(void) nh.leader = swaplong(rankfileheader.leader); nh.freeslot = swaplong(rankfileheader.freeslot); - fseek(rankfile, 0, SEEK_SET); - fwrite(&nh, 1, sizeof(rankfileheader_t), rankfile); + VFS_SEEK(rankfile, 0); + VFS_WRITE(rankfile, &nh, sizeof(rankfileheader_t)); } //#define WRITEHEADER() {fseek(rankfile, 0, SEEK_SET);fwrite(&rankfileheader, 1, sizeof(rankfileheader_t), rankfile);} @@ -149,10 +148,10 @@ qboolean Rank_OpenRankings(void) if (!FS_NativePath(rank_filename.string, FS_GAMEONLY, syspath, sizeof(syspath))) return false; - rankfile = fopen(syspath, "r+b"); + rankfile = FS_OpenVFS(rank_filename.string, "r+b", FS_GAMEONLY); if (!rankfile) //hmm... try creating { - rankfile = fopen(syspath, "w+b"); + rankfile = FS_OpenVFS(rank_filename.string, "w+b", FS_GAMEONLY); created = true; } else @@ -162,11 +161,11 @@ qboolean Rank_OpenRankings(void) memset(&rankfileheader, 0, sizeof(rankfileheader)); - fseek(rankfile, 0, SEEK_SET); - result = fread(&rankfileheader, 1, sizeof(rankfileheader_t), rankfile); + VFS_SEEK(rankfile, 0); + result = VFS_READ(rankfile, &rankfileheader, sizeof(rankfileheader_t)); if (result != sizeof(rankfileheader_t)) - Con_Printf("Rank_OpenRankings() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankfileheader_t),(unsigned int)result,strerror(errno)); + Con_Printf("Rank_OpenRankings() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankfileheader_t),(unsigned int)result); rankfileheader.version = swaplong(rankfileheader.version); rankfileheader.usedslots = swaplong(rankfileheader.usedslots); @@ -176,7 +175,7 @@ qboolean Rank_OpenRankings(void) if (!created && (rankfileheader.version != RANKFILE_VERSION || rankfileheader.ident != RANKFILE_IDENT)) { Con_Printf("Rank file is version %i not %i\nEither delete the file or use an equivelent version of " DISTRIBUTION "\n", rankfileheader.version, RANKFILE_VERSION); - fclose(rankfile); + VFS_CLOSE(rankfile); rankfile = NULL; return false; @@ -367,7 +366,7 @@ void Rank_SetPlayerStats(int id, rankstats_t *stats) if (!nid) //Hmm. First player! { LINKAFTER(0, id, &nh); - fflush(rankfile); + VFS_FLUSH(rankfile); return; } while(nid) @@ -377,13 +376,13 @@ void Rank_SetPlayerStats(int id, rankstats_t *stats) { LINKAFTER(rh.prev, id, &nh); //LINKBEFORE(nid, id, &nh); //we are doing better than this guy. - fflush(rankfile); + VFS_FLUSH(rankfile); return; } if (!rh.next) { LINKAFTER(nid, id, &nh); //Bum. We got to the end of the list and we are the WORST player! - fflush(rankfile); + VFS_FLUSH(rankfile); return; } nid = rh.next; @@ -444,7 +443,7 @@ int Rank_GetPlayerID(char *guid, char *name, int pwd, qboolean allowadd, qboolea rs.trustlevel = 1; Rank_SetPlayerStats(id, &rs); - fflush(rankfile); + VFS_FLUSH(rankfile); return id; } @@ -463,7 +462,7 @@ int Rank_GetPlayerID(char *guid, char *name, int pwd, qboolean allowadd, qboolea Rank_SetPlayerStats(id, &rs); - fflush(rankfile); + VFS_FLUSH(rankfile); return id; } @@ -540,7 +539,7 @@ void Rank_AddUser_f (void) rs.trustlevel = userlevel; Rank_SetPlayerStats(id, &rs); - fflush(rankfile); + VFS_FLUSH(rankfile); return; } @@ -559,7 +558,7 @@ void Rank_AddUser_f (void) Rank_SetPlayerStats(id, &rs); - fflush(rankfile); + VFS_FLUSH(rankfile); } void Rank_SetPass_f (void) @@ -723,7 +722,7 @@ void Rank_Remove_f (void) rankfileheader.freeslot = id; WRITE_PLAYERHEADER(id, &ri.h); WRITEHEADER(); - fflush(rankfile); + VFS_FLUSH(rankfile); Con_Printf("Client %s removed from rankings\n", ri.h.name); return; @@ -825,7 +824,7 @@ void Rank_Refresh_f(void) } if (rankfile) { - fclose(rankfile); + VFS_CLOSE(rankfile); rankfile = NULL; } } @@ -876,7 +875,7 @@ void Rank_RCon_f(void) if (!ri.h.pwd && newlevel > 1) Con_Printf("WARNING: user has no password set\n"); - fflush(rankfile); + VFS_FLUSH(rankfile); return; } @@ -915,7 +914,7 @@ void Rank_Flush (void) //new game dir? Rank_Refresh_f(); if (!rankfile) return; - fclose(rankfile); + VFS_CLOSE(rankfile); rankfile=NULL; } } diff --git a/engine/server/sv_sys_unix.c b/engine/server/sv_sys_unix.c index 193e2c7f..c23dab78 100644 --- a/engine/server/sv_sys_unix.c +++ b/engine/server/sv_sys_unix.c @@ -99,6 +99,11 @@ qboolean Sys_remove (char *path) return system(va("rm \"%s\"", path)); } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return !rename(oldfname, newfname); +} + int Sys_DebugLog(char *file, char *fmt, ...) { va_list argptr; diff --git a/engine/server/sv_sys_win.c b/engine/server/sv_sys_win.c index 0eb94ac8..8c6cbbfc 100644 --- a/engine/server/sv_sys_win.c +++ b/engine/server/sv_sys_win.c @@ -413,6 +413,10 @@ qboolean Sys_remove (char *path) return true; } +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return !rename(oldfname, newfname); +} int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm) { diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 3c7effec..78872eb5 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -642,7 +642,7 @@ void SVQ2_ConfigStrings_f (void) // write a packet full of data - while ( host_client->netchan.message.cursize < MAX_QWMSGLEN/2 + while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2 && start < Q2MAX_CONFIGSTRINGS) { str = sv.strings.configstring[start]; @@ -819,7 +819,7 @@ void SVQ2_BaseLines_f (void) // write a packet full of data - while ( host_client->netchan.message.cursize < MAX_QWMSGLEN/2 + while ( host_client->netchan.message.cursize < host_client->netchan.message.maxsize/2 && start < Q2MAX_EDICTS) { base = &sv_baselines[start]; @@ -908,7 +908,7 @@ void SV_PK3List_f (void) for (; ; i++) { - if (host_client->netchan.message.cursize < (MAX_QWMSGLEN/2)) + if (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) { //user's buffer was too small MSG_WriteByte(&host_client->netchan.message, svc_stufftext); MSG_WriteString(&host_client->netchan.message, va("cmd pk3list %i %i\n", svs.spawncount, 0)); @@ -1001,7 +1001,7 @@ void SV_Soundlist_f (void) if (sv.democausesreconnect) //read the list from somewhere else { for (i = 1+n; - *sv.demsound_precache[i] && host_client->netchan.message.cursize < (MAX_QWMSGLEN/2); + *sv.demsound_precache[i] && host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2); i++, n++) MSG_WriteString (&host_client->netchan.message, sv.demsound_precache[i]); @@ -1013,7 +1013,7 @@ void SV_Soundlist_f (void) #endif { for (i = 1+n; - i < maxclientsupportedsounds && *sv.strings.sound_precache[i] && host_client->netchan.message.cursize < (MAX_QWMSGLEN/2); + i < maxclientsupportedsounds && *sv.strings.sound_precache[i] && host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2); i++, n++) { MSG_WriteString (&host_client->netchan.message, sv.strings.sound_precache[i]); @@ -1095,7 +1095,7 @@ void SV_Modellist_f (void) if (sv.democausesreconnect) //read the list from somewhere else { for (i = 1+n; - *sv.demmodel_precache[i] && ((n&255)==0||host_client->netchan.message.cursize < (MAX_QWMSGLEN/2)); + *sv.demmodel_precache[i] && ((n&255)==0||host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)); i++, n++) MSG_WriteString (&host_client->netchan.message, sv.demmodel_precache[i]); @@ -1106,7 +1106,7 @@ void SV_Modellist_f (void) #endif { for (i = 1+n; - i < host_client->maxmodels && sv.strings.model_precache[i] && (((i-1)&255)==0 || host_client->netchan.message.cursize < (MAX_QWMSGLEN/2)); //make sure we don't send a 0 next... + i < host_client->maxmodels && sv.strings.model_precache[i] && (((i-1)&255)==0 || host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)); //make sure we don't send a 0 next... i++) { MSG_WriteString (&host_client->netchan.message, sv.strings.model_precache[i]); @@ -1500,7 +1500,7 @@ void SV_Spawn_f (void) if (!sv.strings.lightstyles[i]) continue; #ifdef PEXT_LIGHTSTYLECOL - if ((host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && sv.strings.lightstylecolours[i]!=7) + if ((host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && sv.strings.lightstylecolours[i]!=7 && sv.strings.lightstyles[i]) { ClientReliableWrite_Begin (host_client, svcfte_lightstylecol, 3 + (sv.strings.lightstyles[i] ? strlen(sv.strings.lightstyles[i]) : 1)); diff --git a/engine/server/svq2_game.c b/engine/server/svq2_game.c index 376bb878..67406dc2 100644 --- a/engine/server/svq2_game.c +++ b/engine/server/svq2_game.c @@ -552,6 +552,7 @@ static q2trace_t VARGS SVQ2_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_ VectorCopy(tr.endpos, ret.endpos); VectorCopy(tr.plane.normal, ret.plane.normal); ret.plane.dist = tr.plane.dist; + ret.ent = tr.ent; // memcpy(&ret, &tr, sizeof(q2trace_t)); return ret; }