diff --git a/engine/Makefile b/engine/Makefile index 6e6e95bd0..3cfc8eaa7 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -596,13 +596,13 @@ ifeq ($(FTE_TARGET),win32) SV_EXE_NAME=../fteqwsv.exe SV_LDFLAGS=libs/zlib.lib -lwsock32 -lwinmm SV_DIR=sv_mingw - SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(WINDOWSSERVERONLY_OBJS) resources.o + SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(WINDOWSSERVERONLY_OBJS) fs_win32.o resources.o ifeq ($(USEASM),true) - GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o resources.o + GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o resources.o else - GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o resources.o + GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o resources.o endif GL_EXE_NAME=../fteglqw.exe GLCL_EXE_NAME=../fteglqwcl.exe @@ -612,9 +612,9 @@ endif GLCL_DIR=glcl_mgw ifeq ($(USEASM),true) - NPQTVCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o npplug.o sys_npqtv.o ../../ftequake/npapi.def + NPQTVCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o npplug.o sys_npqtv.o ../../ftequake/npapi.def else - NPQTVCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o npplug.o sys_npqtv.o ../../ftequake/npapi.def + NPQTVCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) fs_win32.o gl_vidnt.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o npplug.o sys_npqtv.o ../../ftequake/npapi.def endif NPQTV_DLL_NAME=../npqtv.dll NPQTVCL_DLL_NAME=../npqtvcl.dll @@ -624,9 +624,9 @@ endif NPQTVCL_DIR=npqtvcl_mgw ifeq ($(USEASM),true) - SWCL_OBJS=$(SOFTWARE_OBJS) vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o resources.o + SWCL_OBJS=$(SOFTWARE_OBJS) fs_win32.o vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o resources.o else - SWCL_OBJS=$(SOFTWARE_OBJS) vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o resources.o + SWCL_OBJS=$(SOFTWARE_OBJS) fs_win32.o vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o resources.o endif SW_EXE_NAME=../fteswqw.exe SWCL_EXE_NAME=../fteswqwcl.exe @@ -636,9 +636,9 @@ endif SWCL_DIR=swcl_mgw ifeq ($(USEASM),true) - MCL_OBJS=$(GLQUAKE_OBJS) $(SOFTWARE_OBJS) gl_vidnt.o vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o resources.o + MCL_OBJS=$(GLQUAKE_OBJS) $(SOFTWARE_OBJS) fs_win32.o gl_vidnt.o vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_dosa.o resources.o else - MCL_OBJS=$(GLQUAKE_OBJS) $(SOFTWARE_OBJS) gl_vidnt.o vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o resources.o + MCL_OBJS=$(GLQUAKE_OBJS) $(SOFTWARE_OBJS) fs_win32.o gl_vidnt.o vid_ddraw.o vid_dib.o vid_win2.o snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o resources.o endif M_EXE_NAME=../fteqw.exe MCL_EXE_NAME=../fteqwcl.exe diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 99249dbe4..9d43141eb 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -357,6 +357,7 @@ static void Cam_CheckHighTarget(int pnum) { int i, j, max; player_info_t *s; + int sp; j = -1; for (i = 0, max = -9999; i < MAX_CLIENTS; i++) @@ -364,14 +365,29 @@ static void Cam_CheckHighTarget(int pnum) s = &cl.players[i]; if (s->name[0] && !s->spectator && s->frags > max) { - max = s->frags; - j = i; + for (sp = pnum-1; sp >= 0; sp--) + { + if (Cam_TrackNum(sp) == i) + break; + } + if (sp == -1) + { + max = s->frags; + j = i; + } } } if (j >= 0) { if (!locked[pnum] || cl.players[j].frags > cl.players[spec_track[pnum]].frags) + { Cam_Lock(pnum, j); + for (sp = pnum+1; sp < cl.splitclients; sp++) + { + if (Cam_TrackNum(sp) == j) + locked[sp] = false; + } + } } else Cam_Unlock(pnum); diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 01b27ff22..6dcc2ee61 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -949,7 +949,8 @@ static int CG_SystemCallsEx(void *offset, unsigned int mask, int fn, const int * VM_LONG(ret) = Sys_Milliseconds(); break; case CG_REAL_TIME: - VM_FLOAT(ret) = realtime; + //really local time + VM_LONG(ret) = Sys_Milliseconds(); break; case CG_SNAPVECTOR: // ( float *v ) @@ -1114,6 +1115,7 @@ void CG_Stop (void) void CG_Start (void) { + SCR_SetLoadingStage(0); if (cls.protocol != CP_QUAKE3) { //q3 clients only. CG_Stop(); @@ -1140,8 +1142,8 @@ void CG_Start (void) cgvm = VM_Create(NULL, "vm/cgame", CG_SystemCalls, CG_SystemCallsEx); if (cgvm) { //hu... cgame doesn't appear to have a query version call! - VM_Call(cgvm, CG_INIT, ccs.serverMessageNum, ccs.lastServerCommandNum, cl.playernum[0]); SCR_EndLoadingPlaque(); + VM_Call(cgvm, CG_INIT, ccs.serverMessageNum, ccs.lastServerCommandNum, cl.playernum[0]); } else { diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 57f457255..2bccf9488 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -3185,6 +3185,8 @@ void CL_SetUpPlayerPrediction(qboolean dopred) struct predicted_player *pplayer; extern cvar_t cl_nopred; + int s; + playertime = realtime - cls.latency + 0.02; if (playertime > realtime) playertime = realtime; @@ -3226,12 +3228,16 @@ void CL_SetUpPlayerPrediction(qboolean dopred) // note that the local player is special, since he moves locally // we use his last predicted postition - if (j == cl.playernum[0]) + for (s = 0; s < cl.splitclients; s++) { - VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum[0]].origin, - pplayer->origin); + if (j == cl.playernum[s]) + { + VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum[s]].origin, + pplayer->origin); + break; + } } - else + if (s == cl.splitclients) { // only predict half the move to minimize overruns msec = 500*(playertime - state->state_time); @@ -3358,7 +3364,6 @@ void CL_EmitEntities (void) CL_LinkPacketEntities (); CL_LinkProjectiles (); CL_UpdateTEnts (); - CL_LinkViewModel (); } @@ -3415,6 +3420,7 @@ static void MVD_InitInterpolation(void) frame_t *frame, *oldframe; vec3_t dist; struct predicted_player *pplayer; + int s; #define ISDEAD(i) ( (i) >= 41 && (i) <= 102 ) @@ -3460,7 +3466,12 @@ static void MVD_InitInterpolation(void) } // we dont interpolate ourself if we are spectating - if (i == cl.playernum[0] && cl.spectator) + for (s = 0; s < cl.splitclients; s++) + { + if (i == cl.playernum[s] && cl.spectator) + break; + } + if (s != cl.splitclients) continue; memset(state->velocity, 0, sizeof(state->velocity)); @@ -3508,15 +3519,19 @@ void MVD_Interpolate(void) struct predicted_player *pplayer; static float old; extern float demtime; + int s; - self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[0]]; - oldself = &cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].playerstate[cl.playernum[0]]; + for (s = 0; s < cl.splitclients; s++) + { + self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum[s]]; + oldself = &cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].playerstate[cl.playernum[s]]; - self->messagenum = cl.parsecount; + self->messagenum = cl.parsecount; - VectorCopy(oldself->origin, self->origin); - VectorCopy(oldself->velocity, self->velocity); - VectorCopy(oldself->viewangles, self->viewangles); + VectorCopy(oldself->origin, self->origin); + VectorCopy(oldself->velocity, self->velocity); + VectorCopy(oldself->viewangles, self->viewangles); + } if (old != nextdemotime) { diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index a08fdbeb2..187b0adc3 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -44,6 +44,7 @@ cvar_t cl_instantrotate = SCVARF("cl_instantrotate", "1", CVAR_SEMICHEAT); cvar_t prox_inmenu = SCVAR("prox_inmenu", "0"); usercmd_t independantphysics[MAX_SPLITS]; +vec3_t mousemovements[MAX_SPLITS]; /* =============================================================================== @@ -448,7 +449,7 @@ CL_AdjustAngles Moves the local angle positions ================ */ -void CL_AdjustAngles (int pnum) +void CL_AdjustAngles (int pnum, double frametime) { float speed, quant; float up, down; @@ -456,12 +457,12 @@ void CL_AdjustAngles (int pnum) if (in_speed.state[pnum] & 1) { if (ruleset_allow_frj.value) - speed = host_frametime * cl_anglespeedkey.value; + speed = frametime * cl_anglespeedkey.value; else - speed = host_frametime * bound(-2, cl_anglespeedkey.value, 2); + speed = frametime * bound(-2, cl_anglespeedkey.value, 2); } else - speed = host_frametime; + speed = frametime; if (in_rotate && pnum==0 && !(cl.fpd & FPD_LIMIT_YAW)) { @@ -1013,7 +1014,10 @@ unsigned long _stdcall CL_IndepPhysicsThread(void *param) time -= spare/1000.0f; EnterCriticalSection(&indepcriticialsection); if (cls.state) - CL_SendCmd(time - lasttime); + { + Sys_SendKeyEvents(); + CL_SendCmd(time - lasttime, false); + } lasttime = time; LeaveCriticalSection(&indepcriticialsection); } @@ -1110,7 +1114,7 @@ void *CL_IndepPhysicsThread(void *param) time -= spare/1000.0f; pthread_mutex_lock(&indepcriticalsection); if (cls.state) - CL_SendCmd(time - lasttime); + CL_SendCmd(time - lasttime, false); lasttime = time; pthread_mutex_unlock(&indepcriticalsection); } @@ -1369,7 +1373,7 @@ qboolean CL_SendCmdQW (sizebuf_t *buf) return dontdrop; } -void CL_SendCmd (double frametime) +void CL_SendCmd (double frametime, qboolean mainloop) { extern cvar_t cl_indepphysics; sizebuf_t buf; @@ -1388,6 +1392,23 @@ void CL_SendCmd (double frametime) extern cvar_t cl_maxfps; clcmdbuf_t *next; + if (runningindepphys) + { + double curtime; + static double lasttime; + curtime = Sys_DoubleTime(); + frametime = curtime - lasttime; + lasttime = curtime; + +/* for (plnum = 0; plnum < cl.splitclients; plnum++) + { + CL_AdjustAngles(plnum, frametime); + IN_Move(mousemovements[plnum], plnum); + } + return; +*/ + } + CL_ProxyMenuHooks(); if (cls.demoplayback != DPB_NONE) @@ -1413,12 +1434,16 @@ void CL_SendCmd (double frametime) cmd->msec = frametime*1000; independantphysics[0].msec = 0; - CL_AdjustAngles (plnum); + CL_AdjustAngles (plnum, frametime); // get basic movement from keyboard CL_BaseMove (cmd, plnum, 1, 1); // allow mice or other external controllers to add to the move - IN_Move (cmd, plnum); + IN_Move (mousemovements[plnum], plnum); + independantphysics[plnum].forwardmove += mousemovements[plnum][0]; + independantphysics[plnum].sidemove += mousemovements[plnum][1]; + independantphysics[plnum].upmove += mousemovements[plnum][2]; + VectorClear(mousemovements[plnum]); // if we are spectator, try autocam if (cl.spectator) @@ -1461,6 +1486,8 @@ void CL_SendCmd (double frametime) msecs=0; //erm. msecstouse = (int)msecs; //casts round down. + if (msecstouse == 0) + return; #ifdef IRCCONNECT if (cls.netchan.remote_address.type != NA_IRC) #endif @@ -1479,7 +1506,7 @@ void CL_SendCmd (double frametime) fullsend = true; - if (!cl_indepphysics.value) + if (!runningindepphys) { // while we're not playing send a slow keepalive fullsend to stop mvdsv from screwing up if (cls.state < ca_active && CL_FilterTime(msecstouse, @@ -1511,8 +1538,12 @@ void CL_SendCmd (double frametime) for (plnum = 0; plnum < cl.splitclients; plnum++) { // CL_BaseMove (&independantphysics[plnum], plnum, (msecstouse - independantphysics[plnum].msec), wantfps); - CL_AdjustAngles (plnum); - IN_Move (&independantphysics[plnum], plnum); + CL_AdjustAngles (plnum, frametime); + IN_Move (mousemovements[plnum], plnum); + independantphysics[plnum].forwardmove += mousemovements[plnum][0]; + independantphysics[plnum].sidemove += mousemovements[plnum][1]; + independantphysics[plnum].upmove += mousemovements[plnum][2]; + VectorClear(mousemovements[plnum]); for (i=0 ; i<3 ; i++) independantphysics[plnum].angles[i] = ((int)(cl.viewangles[plnum][i]*65536.0/360)&65535); @@ -1530,6 +1561,10 @@ void CL_SendCmd (double frametime) independantphysics[plnum].msec = msecstouse; } + //the main loop isn't allowed to send + if (runningindepphys && mainloop) + return; + // if (skipcmd) // return; #ifdef NQPROT @@ -1606,7 +1641,7 @@ void CL_SendCmd (double frametime) return; // Q3 does it's own thing #endif default: - Host_Error("Invalid protocol in CL_SendCmd: %i", cls.protocol); + Host_EndGame("Invalid protocol in CL_SendCmd: %i", cls.protocol); return; } } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 2dcce224b..cdafcc608 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1162,7 +1162,10 @@ void CL_Disconnect (void) cls.downloadqw = NULL; } if (!cls.downloadmethod) - *cls.downloadname = '\0'; + { + *cls.downloadlocalname = '\0'; + *cls.downloadremotename = '\0'; + } { downloadlist_t *next; @@ -2661,7 +2664,7 @@ void CL_Download_f (void) void CL_DownloadSize_f(void) { downloadlist_t *dl; - char *name; + char *rname; char *size; char *redirection; @@ -2670,37 +2673,37 @@ void CL_DownloadSize_f(void) if (cls.demoplayback) return; - name = Cmd_Argv(1); + rname = Cmd_Argv(1); size = Cmd_Argv(2); if (!strcmp(size, "e")) { - Con_Printf("Download of \"%s\" failed. Not found.\n", name); - CL_DownloadFailed(name); + Con_Printf("Download of \"%s\" failed. Not found.\n", rname); + CL_DownloadFailed(rname); } else if (!strcmp(size, "p")) { - Con_Printf("Download of \"%s\" failed. Not allowed.\n", name); - CL_DownloadFailed(name); + Con_Printf("Download of \"%s\" failed. Not allowed.\n", rname); + CL_DownloadFailed(rname); } else if (!strcmp(size, "r")) { redirection = Cmd_Argv(3); - dl = CL_DownloadFailed(name); + dl = CL_DownloadFailed(rname); if (allow_download_redirection.value) { - Con_DPrintf("Download of \"%s\" redirected to \"%s\".\n", name, redirection); + Con_DPrintf("Download of \"%s\" redirected to \"%s\".\n", rname, redirection); CL_CheckOrEnqueDownloadFile(redirection, NULL, dl->flags); } else - Con_Printf("Download of \"%s\" redirected to \"%s\". Prevented by allow_download_redirection.\n", name, redirection); + Con_Printf("Download of \"%s\" redirected to \"%s\". Prevented by allow_download_redirection.\n", rname, redirection); } else { for (dl = cl.downloadlist; dl; dl = dl->next) { - if (!strcmp(dl->name, name)) + if (!strcmp(dl->rname, rname)) { dl->size = strtoul(size, NULL, 0); return; @@ -2728,7 +2731,7 @@ void CL_ForceStopDownload (qboolean finish) cls.downloadqw = NULL; if (finish) - CL_DownloadFinished(cls.downloadname, cls.downloadtempname); + CL_DownloadFinished(); else { char *tempname; @@ -2736,14 +2739,15 @@ void CL_ForceStopDownload (qboolean finish) if (*cls.downloadtempname) tempname = cls.downloadtempname; else - tempname = cls.downloadname; + tempname = cls.downloadlocalname; if (strncmp(tempname,"skins/",6)) FS_Remove(tempname, FS_GAME); else FS_Remove(tempname+6, FS_SKINS); } - *cls.downloadname = '\0'; + *cls.downloadlocalname = '\0'; + *cls.downloadremotename = '\0'; cls.downloadpercent = 0; // get another file if needed @@ -3344,8 +3348,6 @@ void Host_Frame (double time) // fetch results from server CL_ReadPackets (); - CL_AllowIndependantSendCmd(true); - // send intentions now // resend a connection request if necessary if (cls.state == ca_disconnected) @@ -3355,15 +3357,14 @@ void Host_Frame (double time) } else { - extern qboolean runningindepphys; - if (!runningindepphys) - CL_SendCmd (host_frametime/cl.gamespeed); + CL_SendCmd (host_frametime/cl.gamespeed, true); if (cls.state == ca_onserver && cl.validsequence && cl.worldmodel) { // first update is the final signon stage CL_MakeActive("QuakeWorld"); } } + CL_AllowIndependantSendCmd(true); RSpeedEnd(RSPEED_PROTOCOL); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index f881ded8a..e360af8a4 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -307,7 +307,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) for (dl = cl.faileddownloads; dl; dl = dl->next) //yeah, so it failed... Ignore it. { - if (!strcmp(dl->name, filename)) + if (!strcmp(dl->rname, filename)) { if (flags & DLLF_VERBOSE) Con_Printf("We've failed to download \"%s\" already\n", filename); @@ -318,7 +318,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) for (dl = cl.downloadlist; dl; dl = dl->next) //It's already on our list. Ignore it. { - if (!strcmp(dl->name, filename)) + if (!strcmp(dl->rname, filename)) { if (flags & DLLF_VERBOSE) Con_Printf("Already waiting for \"%s\"\n", filename); @@ -326,7 +326,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) } } - if (!strcmp(cls.downloadname, filename)) + if (!strcmp(cls.downloadremotename, filename)) { if (flags & DLLF_VERBOSE) Con_Printf("Already downloading \"%s\"\n", filename); @@ -340,7 +340,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) } dl = Z_Malloc(sizeof(downloadlist_t)); - Q_strncpyz(dl->name, filename, sizeof(dl->name)); + Q_strncpyz(dl->rname, filename, sizeof(dl->rname)); Q_strncpyz(dl->localname, localname, sizeof(dl->localname)); dl->next = cl.downloadlist; cl.downloadlist = dl; @@ -352,7 +352,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) | PEXT_PK3DOWNLOADS #endif )) - CL_SendClientCommand(true, "dlsize \"%s\"", dl->name); + CL_SendClientCommand(true, "dlsize \"%s\"", dl->rname); if (flags & DLLF_VERBOSE) Con_Printf("Enqued download of \"%s\"\n", filename); @@ -391,7 +391,7 @@ void CL_DisenqueDownload(char *filename) downloadlist_t *dl, *nxt; if(cl.downloadlist) //remove from enqued download list { - if (!strcmp(cl.downloadlist->name, filename)) + if (!strcmp(cl.downloadlist->rname, filename)) { dl = cl.downloadlist; cl.downloadlist = cl.downloadlist->next; @@ -401,7 +401,7 @@ void CL_DisenqueDownload(char *filename) { for (dl = cl.downloadlist; dl->next; dl = dl->next) { - if (!strcmp(dl->next->name, filename)) + if (!strcmp(dl->next->rname, filename)) { nxt = dl->next->next; Z_Free(dl->next); @@ -413,10 +413,11 @@ void CL_DisenqueDownload(char *filename) } } -void CL_SendDownloadRequest(char *filename, char *localname) +void CL_SendDownloadStartRequest(char *filename, char *localname) { - strcpy (cls.downloadname, localname); - Con_TPrintf (TL_DOWNLOADINGFILE, cls.downloadname); + strcpy (cls.downloadremotename, filename); + strcpy (cls.downloadlocalname, localname); + Con_TPrintf (TL_DOWNLOADINGFILE, cls.downloadlocalname); // download to a temp name, and only rename // to the real name when done, so if interrupted @@ -434,13 +435,16 @@ void CL_SendDownloadRequest(char *filename, char *localname) } //Do any reloading for the file that just reloaded. -void CL_DownloadFinished(char *filename, char *tempname) +void CL_DownloadFinished(void) { int i; extern int mod_numknown; char *ext; extern model_t mod_known[]; + char *filename = cls.downloadlocalname; + char *tempname = cls.downloadtempname; + COM_RefreshFSCache_f(); cls.downloadmethod = DL_NONE; @@ -577,7 +581,7 @@ qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname, unsigned downloadlist_t *dl; for (dl = cl.faileddownloads; dl; dl = dl->next) { - if (!strcmp(dl->name, filename)) + if (!strcmp(dl->rname, filename)) { //if its on the failed list, don't block waiting for it to download return true; @@ -710,7 +714,8 @@ static qboolean CL_CheckModelResources (char *name) return false; // checking for skins in the model - file = COM_LoadMallocFile (name); + + FS_LoadFile(name, &file); if (!file) { return false; // couldn't load it @@ -723,7 +728,7 @@ static qboolean CL_CheckModelResources (char *name) ret = CL_CheckQ2BspWals(file); else ret = false; - BZ_Free(file); + FS_FreeFile(file); return ret; } @@ -1022,10 +1027,10 @@ void Sound_CheckDownloads (void) // Con_TPrintf (TLC_CHECKINGSOUNDS); #ifdef CSQC_DAT - if (cls.fteprotocolextensions & PEXT_CSQC) +// if (cls.fteprotocolextensions & PEXT_CSQC) { s = Info_ValueForKey(cl.serverinfo, "*csprogs"); - if (*s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches. + if (*s) //only allow csqc if the server says so, and the 'checksum' matches. { extern cvar_t allow_download_csprogs; unsigned int chksum = strtoul(s, NULL, 0); @@ -1106,11 +1111,11 @@ void CL_RequestNextDownload (void) dl = cl.downloadlist; if ((dl->flags & DLLF_OVERWRITE) || !COM_FCheckExists (dl->localname)) - CL_SendDownloadRequest(dl->name, dl->localname); + CL_SendDownloadStartRequest(dl->rname, dl->localname); else { Con_Printf("Already have %s\n", dl->localname); - CL_DisenqueDownload(dl->name); + CL_DisenqueDownload(dl->rname); //recurse a bit. CL_RequestNextDownload(); @@ -1275,10 +1280,10 @@ downloadlist_t *CL_DownloadFailed(char *name) failed = Z_Malloc(sizeof(downloadlist_t)); failed->next = cl.faileddownloads; cl.faileddownloads = failed; - Q_strncpyz(failed->name, name, sizeof(failed->name)); + Q_strncpyz(failed->rname, name, sizeof(failed->rname)); //if this is what we're currently downloading, close it up now. - if (!stricmp(cls.downloadname, name) || !*name) + if (!stricmp(cls.downloadremotename, name) || !*name) { cls.downloadmethod = DL_NONE; @@ -1288,14 +1293,15 @@ downloadlist_t *CL_DownloadFailed(char *name) cls.downloadqw = NULL; CL_SendClientCommand(true, "stopdownload"); } - *cls.downloadname = 0; + *cls.downloadlocalname = 0; + *cls.downloadremotename = 0; } link = &cl.downloadlist; while(*link) { dl = *link; - if (!strcmp(dl->name, name)) + if (!strcmp(dl->rname, name)) { *link = dl->next; failed->flags |= dl->flags; @@ -1361,6 +1367,7 @@ void CL_ParseChunkedDownload(void) else Con_Printf("Couldn't find file \"%s\" on the server\n", svname); + cls.downloadmethod = 0; CL_DownloadFailed(svname); CL_RequestNextDownload(); @@ -1370,9 +1377,8 @@ void CL_ParseChunkedDownload(void) if (cls.downloadmethod == DL_QWCHUNKS) Host_EndGame("Received second download - \"%s\"\n", svname); - if (stricmp(cls.downloadname, svname)) - if (stricmp(svname, "csprogs.dat") || strnicmp(cls.downloadname, "csprogsvers/", 12)) - Host_EndGame("Server sent the wrong download - \"%s\" instead of \"%s\"\n", svname, cls.downloadname); + if (stricmp(cls.downloadremotename, svname)) + Host_EndGame("Server sent the wrong download - \"%s\" instead of \"%s\"\n", svname, cls.downloadremotename); //start the new download @@ -1500,11 +1506,12 @@ int CL_RequestADownloadChunk(void) cls.downloadqw = NULL; CL_SendClientCommand(true, "stopdownload"); - CL_DownloadFinished(cls.downloadname, cls.downloadtempname); + CL_DownloadFinished(); Con_Printf("Download took %i seconds (%i more)\n", (int)(Sys_DoubleTime() - downloadstarttime), CL_CountQueuedDownloads()); - *cls.downloadname = '\0'; + *cls.downloadlocalname = '\0'; + *cls.downloadremotename = '\0'; cls.downloadpercent = 0; return -1; @@ -1546,12 +1553,14 @@ void CL_ParseDownload (void) return; // not in demo playback } - if (!*cls.downloadname) //huh... that's not right... + if (!*cls.downloadlocalname) //huh... that's not right... { Con_Printf(CON_WARNING "Warning: Server sending unknown file.\n"); - strcpy(cls.downloadname, "unknown.txt"); + strcpy(cls.downloadlocalname, "unknown.txt"); strcpy(cls.downloadtempname, "unknown.tmp"); } + if (!*cls.downloadremotename) + strcpy(cls.downloadremotename, "unknown.txt"); if (size < 0) { @@ -1562,15 +1571,8 @@ void CL_ParseDownload (void) VFS_CLOSE (cls.downloadqw); cls.downloadqw = NULL; } - if (cl.downloadlist && !strcmp(cl.downloadlist->name, cls.downloadname)) - { - downloadlist_t *next; - next = cl.downloadlist->next; - Z_Free(cl.downloadlist); - cl.downloadlist = next; - } - CL_DownloadFailed(cls.downloadname); + CL_DownloadFailed(cls.downloadremotename); CL_RequestNextDownload (); return; @@ -1595,7 +1597,7 @@ void CL_ParseDownload (void) { msg_readcount += size; Con_TPrintf (TL_FAILEDTOOPEN, cls.downloadtempname); - CL_DownloadFailed(cls.downloadname); + CL_DownloadFailed(cls.downloadremotename); CL_RequestNextDownload (); return; } @@ -1647,8 +1649,9 @@ void CL_ParseDownload (void) { VFS_CLOSE (cls.downloadqw); - CL_DownloadFinished(cls.downloadname, cls.downloadtempname); - *cls.downloadname = '\0'; + CL_DownloadFinished(); + *cls.downloadlocalname = '\0'; + *cls.downloadremotename = '\0'; cls.downloadqw = NULL; cls.downloadpercent = 0; @@ -1733,7 +1736,7 @@ void CLDP_ParseDownloadBegin(char *s) } } else - CL_DownloadFailed(cls.downloadname); + CL_DownloadFailed(cls.downloadremotename); downloadstarttime = Sys_DoubleTime(); } @@ -1768,7 +1771,7 @@ void CLDP_ParseDownloadFinished(char *s) else { Con_Printf("Download failed: unable to check CRC of download\n"); - CL_DownloadFailed(cls.downloadname); + CL_DownloadFailed(cls.downloadremotename); return; } @@ -1776,18 +1779,19 @@ void CLDP_ParseDownloadFinished(char *s) if (size != atoi(Cmd_Argv(1))) { Con_Printf("Download failed: wrong file size\n"); - CL_DownloadFailed(cls.downloadname); + CL_DownloadFailed(cls.downloadremotename); return; } if (runningcrc != atoi(Cmd_Argv(2))) { Con_Printf("Download failed: wrong crc\n"); - CL_DownloadFailed(cls.downloadname); + CL_DownloadFailed(cls.downloadremotename); return; } - CL_DownloadFinished(cls.downloadname, cls.downloadtempname); - *cls.downloadname = '\0'; + CL_DownloadFinished(); + *cls.downloadlocalname = '\0'; + *cls.downloadremotename = '\0'; cls.downloadqw = NULL; cls.downloadpercent = 0; @@ -2039,6 +2043,9 @@ void CL_ParseServerData (void) int i; MSG_ReadFloat(); cl.playernum[0] = MAX_CLIENTS - 1; + cl.playernum[1] = MAX_CLIENTS - 2; + cl.playernum[2] = MAX_CLIENTS - 3; + cl.playernum[3] = MAX_CLIENTS - 4; cl.spectator = true; for (i = 0; i < UPDATE_BACKUP; i++) cl.frames[i].playerstate[cl.playernum[0]].pm_type = PM_SPECTATOR; @@ -2754,6 +2761,7 @@ void CL_ParseModellist (qboolean lots) return; } + Sound_CheckDownloads(); Model_CheckDownloads(); CL_AllowIndependantSendCmd(false); //stop it now, the indep stuff *could* require model tracing. @@ -4064,12 +4072,12 @@ void CL_ParsePrint(char *msg, int level) } // CL_PlayerColor: returns color and mask for player_info_t -int CL_PlayerColor(player_info_t *plr, int *name_ormask) +int CL_PlayerColor(player_info_t *plr, qboolean *name_coloured) { char *t; int c; - *name_ormask = 0; + *name_coloured = false; if (cl.teamfortress) //override based on team { @@ -4078,35 +4086,35 @@ int CL_PlayerColor(player_info_t *plr, int *name_ormask) { //translate q1 skin colours to console colours case 10: case 1: - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; case 4: //red c = 1; break; case 11: - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; case 3: // green c = 2; break; case 5: - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; case 12: c = 3; break; case 6: case 7: - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; case 8: case 9: c = 6; break; case 2: // light blue - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; case 13: //blue case 14: //blue c = 5; break; default: - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; case 0: // white c = 7; break; @@ -4133,7 +4141,7 @@ int CL_PlayerColor(player_info_t *plr, int *name_ormask) } if ((c / 7) & 1) - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; c = 1 + (c % 7); } @@ -4151,7 +4159,7 @@ int CL_PlayerColor(player_info_t *plr, int *name_ormask) c = plr->userid; // Quake2 can start from 0 if ((c / 7) & 1) - *name_ormask = CON_HIGHCHARSMASK; + *name_coloured = true; c = 1 + (c % 7); } @@ -4165,10 +4173,12 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) { char *name = NULL; int c; - int name_ormask = 0; + qboolean name_coloured = false; extern cvar_t cl_parsewhitetext; qboolean memessage = false; - + char fullchatmessage[2048]; + + fullchatmessage[0] = 0; if (plrflags & TPM_FAKED) { name = rawmsg; // use rawmsg pointer and msg modification to generate null-terminated string @@ -4187,7 +4197,7 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) if (cl_standardchat.value) { - name_ormask = CON_HIGHCHARSMASK; + name_coloured = true; c = 7; } else @@ -4199,16 +4209,16 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) c = 0; // blacken () on observers else { - name_ormask = CON_HIGHCHARSMASK; + name_coloured = true; c = 7; } } else if (plr) - c = CL_PlayerColor(plr, &name_ormask); + c = CL_PlayerColor(plr, &name_coloured); else { // defaults for fake clients - name_ormask = CON_HIGHCHARSMASK; + name_coloured = true; c = 7; } } @@ -4219,44 +4229,41 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) { if (memessage) { - con_ormask = CON_HIGHCHARSMASK; if (!cl_standardchat.value && (plrflags & TPM_SPECTATOR)) - Con_Printf ("^0*^7 "); + Q_strncatz(fullchatmessage, "^m^0*^7 ", sizeof(fullchatmessage)); else - Con_Printf ("* "); + Q_strncatz(fullchatmessage, "^m* ", sizeof(fullchatmessage)); } 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 - con_ormask = name_ormask; - Con_Printf("^%c(", c); - con_ormask = CON_HIGHCHARSMASK; - Con_Printf("%s", name); - con_ormask = name_ormask; - Con_Printf("^%c)", c); + 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)); + } + else if (cl_standardchat.value) + { + Q_strncatz(fullchatmessage, va("\1%s", name), sizeof(fullchatmessage)); } else { - con_ormask = name_ormask; - Con_Printf("^%c%s", c, name); + Q_strncatz(fullchatmessage, va("\1%s^%c%s^d", name_coloured?"":"^m", c, name), sizeof(fullchatmessage)); } if (!memessage) { // only print seperator with an actual player name - con_ormask = CON_HIGHCHARSMASK; if (!cl_standardchat.value && (plrflags & TPM_SPECTATOR)) - Con_Printf ("^0:^7 "); + Q_strncatz(fullchatmessage, "^0: ^d", sizeof(fullchatmessage)); else - Con_Printf (": "); + Q_strncatz(fullchatmessage, ": ", sizeof(fullchatmessage)); } else - Con_Printf (" "); + Q_strncatz(fullchatmessage, " ", sizeof(fullchatmessage)); } // print message - con_ormask = CON_HIGHCHARSMASK; if (cl_parsewhitetext.value && (cl_parsewhitetext.value == 1 || (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)))) { char *t, *u; @@ -4268,35 +4275,35 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) { *t = 0; *u = 0; - Con_Printf("%s", msg); - con_ormask = 0; - Con_Printf("%s", t+1); - con_ormask = CON_HIGHCHARSMASK; + Q_strncatz(fullchatmessage, va("%s", msg), sizeof(fullchatmessage)); + Q_strncatz(fullchatmessage, va("^m%s^m", t+1), sizeof(fullchatmessage)); msg = u+1; } else break; } - Con_Printf("%s", msg); - con_ormask = 0; + Q_strncatz(fullchatmessage, va("%s", msg), sizeof(fullchatmessage)); } else { - Con_Printf ("%s", msg); + Q_strncatz(fullchatmessage, va("%s", msg), sizeof(fullchatmessage)); } - con_ormask = 0; + CSQC_ParsePrint(fullchatmessage, PRINT_CHAT); } // CL_PrintStandardMessage: takes non-chat net messages and performs name coloring // NOTE: msg is considered destroyable char acceptedchars[] = {'.', '?', '!', '\'', ',', ':', ' ', '\0'}; -void CL_PrintStandardMessage(char *msg) +void CL_PrintStandardMessage(char *msg, int printlevel) { int i; player_info_t *p; extern cvar_t cl_standardmsg; char *begin = msg; + char fullmessage[2048]; + + fullmessage[0] = 0; // search for player names in message for (i = 0, p = cl.players; i < MAX_CLIENTS; p++, i++) @@ -4304,7 +4311,7 @@ void CL_PrintStandardMessage(char *msg) char *v; char *name; int len; - int ormask; + qboolean coloured; char c; name = p->name; @@ -4340,30 +4347,29 @@ void CL_PrintStandardMessage(char *msg) } *v = 0; // cut off message - con_ormask = 0; + // print msg chunk - Con_Printf("%s", msg); + Q_strncatz(fullmessage, msg, sizeof(fullmessage)); msg = v + len; // update search point // get name color if (p->spectator || cl_standardmsg.value) { - ormask = 0; + coloured = false; c = '7'; } else - c = '0' + CL_PlayerColor(p, &ormask); + c = '0' + CL_PlayerColor(p, &coloured); // print name - con_ormask = ormask; - Con_Printf("^%c%s^7", c, name); + Q_strncatz(fullmessage, va("%s^%c%s^7", coloured?"\1":"", c, name), sizeof(fullmessage)); break; } } // print final chunk - con_ormask = 0; - Con_Printf("%s", msg); + Q_strncatz(fullmessage, msg, sizeof(fullmessage)); + CSQC_ParsePrint(fullmessage, printlevel); } char stufftext[4096]; @@ -4626,7 +4632,7 @@ void CL_ParseServerMessage (void) #endif { CL_ParsePrint(s, i); - CL_PrintStandardMessage(s); + CL_PrintStandardMessage(s, i); } } break; @@ -5135,10 +5141,9 @@ void CLQ2_ParseServerMessage (void) #endif { CL_ParsePrint(s, i); - CL_PrintStandardMessage(s); + CL_PrintStandardMessage(s, i); } } - con_ormask = 0; break; case svcq2_stufftext: //11 // [string] stuffed into client's console buffer, should be \n terminated s = MSG_ReadString (); @@ -5372,10 +5377,9 @@ void CLNQ_ParseServerMessage (void) #endif { CL_ParsePrint(s, PRINT_HIGH); - CL_PrintStandardMessage(s); + CL_PrintStandardMessage(s, PRINT_HIGH); } } - con_ormask = 0; break; case svc_disconnect: diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index ca8f2715d..f721d373a 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -255,103 +255,6 @@ int scr_center_lines[MAX_SPLITS]; int scr_erase_lines[MAX_SPLITS]; int scr_erase_center[MAX_SPLITS]; -void CopyAndMarkup(conchar_t *dest, qbyte *src, int maxlength) -{ - conchar_t ext = CON_WHITEMASK; - conchar_t extstack[20]; - int extstackdepth = 0; - - if (maxlength < 0) - return; // ... - - while(*src && maxlength>0) - { - if (*src == '^') - { - src++; - if (*src >= '0' && *src <= '9') - { - ext = q3codemasks[*src - '0'] | (ext&~CON_Q3MASK); - src++; - continue; - } - else if (*src == '&') // extended code - { - if (isextendedcode(src[1]) && isextendedcode(src[2])) - { - src++; // foreground char - if (*src == '-') // default for FG - ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~CON_FGMASK); - else if (*src >= 'A') - ext = ((*src - ('A' - 10)) << CON_FGSHIFT) | (ext&~CON_FGMASK); - else - ext = ((*src - '0') << CON_FGSHIFT) | (ext&~CON_FGMASK); - src++; // background char - if (*src == '-') // default (clear) for BG - ext &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (*src >= 'A') - ext = ((*src - ('A' - 10)) << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; - else - ext = ((*src - '0') << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; - src++; - continue; - } - // else invalid code - *dest++ = '^' | ext; - maxlength--; - if (maxlength <= 0) - break; // need an extra check for writing length - } - else if (*src == 'b') // toggle blink bit - { - src++; - ext ^= CON_BLINKTEXT; - continue; - } - else if (*src == 'a') // toggle alternate charset - { - src++; - ext ^= CON_2NDCHARSETTEXT; - continue; - } - else if (*src == 'h') - { - src++; - ext ^= CON_HALFALPHA; - continue; - } - else if (*src == 's') - { - src++; - if (extstackdepth < sizeof(extstack)/sizeof(extstack[0])) - { - extstack[extstackdepth] = ext; - extstackdepth++; - } - continue; - } - else if (*src == 'r') - { - src++; - if (extstackdepth) - { - extstackdepth--; - ext = extstack[extstackdepth]; - } - continue; - } - else if (*src != '^') - src--; - } - if (*src == '\n') - *dest++ = *src++; - else - *dest++ = *src++ | ext; - maxlength--; - } - *dest = 0; -} - // SCR_StringToRGB: takes in "" or " " and converts to an RGB vector void SCR_StringToRGB (char *rgbstring, float *rgb, float rgbinputscale) { @@ -455,7 +358,7 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode) Cbuf_AddText("f_centerprint\n", RESTRICT_LOCAL); } - CopyAndMarkup (scr_centerstring[pnum], str, sizeof(scr_centerstring[pnum])); + COM_ParseFunString(CON_WHITEMASK, str, scr_centerstring[pnum], sizeof(scr_centerstring[pnum])); scr_centertime_off[pnum] = scr_centertime.value; scr_centertime_start[pnum] = cl.time; @@ -735,7 +638,7 @@ void SCR_ShowPics_Draw(void) for (failed = cl.faileddownloads; failed; failed = failed->next) { //don't try displaying ones that we know to have failed. - if (!strcmp(failed->name, sp->picname)) + if (!strcmp(failed->rname, sp->picname)) break; } if (failed) @@ -1573,7 +1476,7 @@ void SCR_DrawLoading (void) //downloading files? if (cls.downloadmethod) Draw_String(x+8, y+4, va("Downloading %s... %i%%", - cls.downloadname, + cls.downloadlocalname, cls.downloadpercent)); if (tsize > 1024*1024*16) diff --git a/engine/client/client.h b/engine/client/client.h index 9161ff214..f94e2e8a0 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -337,7 +337,8 @@ typedef struct enum {DL_NONE, DL_QW, DL_QWCHUNKS, DL_Q3, DL_DARKPLACES, DL_QWPENDING, DL_HTTP, DL_FTP} downloadmethod; vfsfile_t *downloadqw; // file transfer from server char downloadtempname[MAX_OSPATH]; - char downloadname[MAX_OSPATH]; + char downloadlocalname[MAX_OSPATH]; + char downloadremotename[MAX_OSPATH]; int downloadpercent; int downloadchunknum; @@ -401,7 +402,7 @@ extern client_static_t cls; extern int nq_dp_protocol; typedef struct downloadlist_s { - char name[128]; + char rname[128]; char localname[128]; unsigned int size; unsigned int flags; @@ -753,7 +754,7 @@ void CL_MakeActive(char *gamename); void CL_RegisterSplitCommands(void); void CL_InitInput (void); -void CL_SendCmd (double frametime); +void CL_SendCmd (double frametime, qboolean mainloop); void CL_SendMove (usercmd_t *cmd); #ifdef NQPROT void CL_ParseTEnt (qboolean nqprot); diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index 1de2e48eb..4485ece62 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -414,8 +414,8 @@ void CLQ3_ParseDownload(void) { VFS_CLOSE(cls.downloadqw); cls.downloadqw = NULL; - FS_Rename(cls.downloadtempname, cls.downloadname, FS_ROOT); // -> - *cls.downloadtempname = *cls.downloadname = 0; + FS_Rename(cls.downloadtempname, cls.downloadlocalname, FS_ROOT); // -> + *cls.downloadtempname = *cls.downloadlocalname = *cls.downloadremotename = 0; cls.downloadmethod = DL_NONE; FS_ReloadPackFiles(); @@ -492,7 +492,8 @@ qboolean CLQ3_SystemInfoChanged(char *str) Con_Printf("Sending request to download %s\n", com_token); CLQ3_SendClientCommand("download %s.pk3", com_token); ccs.downloadchunknum = 0; - snprintf(cls.downloadname, sizeof(cls.downloadname), "%s.pk3", com_token); + snprintf(cls.downloadlocalname, sizeof(cls.downloadlocalname), "%s.pk3", com_token); + snprintf(cls.downloadremotename, sizeof(cls.downloadremotename), "%s.pk3", com_token); snprintf(cls.downloadtempname, sizeof(cls.downloadtempname), "%s.tmp", com_token); cls.downloadmethod = DL_Q3; cls.downloadpercent = 0; diff --git a/engine/client/console.c b/engine/client/console.c index 637a53e39..424dd0a99 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -conchar_t con_ormask; console_t con_main; console_t *con_current; // point to either con_main @@ -569,126 +568,31 @@ If no console is visible, the notify window will pop up. ================ */ -#define INVIS_CHAR1 (char)12 //red -#define INVIS_CHAR2 (char)138 //green -#define INVIS_CHAR3 (char)160 //blue - void Con_PrintCon (console_t *con, char *txt) { + conchar_t expanded[4096]; + conchar_t *c; int y; - int c, l; + int l; static int cr; - int mask; - int maskstack[4]; - int maskstackdepth = 0; + COM_ParseFunString(CON_WHITEMASK, txt, expanded, sizeof(expanded)); - con->unseentext = true; - - if (txt[0] == 1 || txt[0] == 2) + c = expanded; + while (*c) { - mask = CON_HIGHCHARSMASK|CON_WHITEMASK; // go to colored text - txt++; - } - else - mask = CON_WHITEMASK; - - - while ( (c = *txt) ) - { - if (c == '^') - { - if (txt[1]>='0' && txt[1]<='9') - { - mask = q3codemasks[txt[1]-'0'] + (mask&~CON_Q3MASK); //change colour only. - txt+=2; - continue; - } - if (txt[1] == '&') // extended code - { - if (isextendedcode(txt[2]) && isextendedcode(txt[3])) - { - if (txt[2] == '-') // default for FG - mask = (COLOR_WHITE << CON_FGSHIFT) | (mask&~CON_FGMASK); - else if (txt[2] >= 'A') - mask = ((txt[2] - ('A' - 10)) << CON_FGSHIFT) | (mask&~CON_FGMASK); - else - mask = ((txt[2] - '0') << CON_FGSHIFT) | (mask&~CON_FGMASK); - if (txt[3] == '-') // default (clear) for BG - mask &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (txt[3] >= 'A') - mask = ((txt[3]- ('A' - 10)) << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - else - mask = ((txt[3] - '0') << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - txt+=4; - continue; - } - } - if (txt[1] == 'b') - { - mask ^= CON_BLINKTEXT; - txt+=2; - continue; - } - if (txt[1] == 'a') - { - mask ^= CON_2NDCHARSETTEXT; - txt+=2; - continue; - } - if (txt[1] == 'h') - { - mask ^= CON_HALFALPHA; - txt+=2; - continue; - } - if (txt[1] == 's') - { - if (maskstackdepth < sizeof(maskstack)/sizeof(maskstack[0])) - { - maskstack[maskstackdepth] = mask; - maskstackdepth++; - } - txt+=2; - continue; - } - if (txt[1] == 'r') - { - if (maskstackdepth) - { - maskstackdepth--; - mask = maskstack[maskstackdepth]; - } - txt+=2; - continue; - } - } - if (c == '&' && txt[1] == 'c') - { - // ezQuake color codes - - if (ishexcode(txt[2]) && ishexcode(txt[3]) && ishexcode(txt[4])) - { - // Just strip it for now - // TODO: Colorize the console properly - txt += 5; - continue; - } - } - if (c=='\t') - c = ' '; + if (*c&CON_CHARMASK=='\t') + *c = (*c&~CON_CHARMASK)|' '; // count word length for (l=0 ; l< con->linewidth ; l++) - if ( txt[l] <= ' ') + if ( c[l]&CON_CHARMASK <= ' ') break; // word wrap if (l != con->linewidth && (con->x + l > con->linewidth) ) con->x = 0; - txt++; - if (cr) { con->current--; @@ -703,7 +607,7 @@ void Con_PrintCon (console_t *con, char *txt) con_times[con->current % NUM_CON_TIMES] = realtime; } - switch (c) + switch (*c & (CON_CHARMASK&~CON_HIGHCHARSMASK)) { case '\n': con->x = 0; @@ -716,12 +620,13 @@ void Con_PrintCon (console_t *con, char *txt) default: // display character and advance y = con->current % con->totallines; - con->text[y*con->linewidth+con->x] = (qbyte)c | mask | con_ormask; + con->text[y*con->linewidth+con->x] = *c; con->x++; if (con->x >= con->linewidth) con->x = 0; break; } + c++; } } @@ -1404,7 +1309,7 @@ void Con_DrawConsole (int lines, qboolean noback) { unsigned int count, total; qboolean extra; - progresstext = cls.downloadname; + progresstext = cls.downloadlocalname; progresspercent = cls.downloadpercent; if ((int)(realtime/2)&1) diff --git a/engine/client/in_macos.c b/engine/client/in_macos.c index ed64d84bd..67fe04195 100644 --- a/engine/client/in_macos.c +++ b/engine/client/in_macos.c @@ -49,7 +49,7 @@ void IN_ModeChanged (void) } // called whenever screen dimensions change -void IN_Move (usercmd_t *cmd, int pnum) +void IN_Move (float *movements, int pnum) { float tx, ty, filterfrac; @@ -71,7 +71,7 @@ void IN_Move (usercmd_t *cmd, int pnum) if ((in_strafe.state[pnum] & 1) || (lookstrafe.value && in_mlook.state[pnum])) { - cmd->sidemove += m_side.value * mouse_x; + movements[1] += m_side.value * mouse_x; } else { @@ -88,7 +88,7 @@ void IN_Move (usercmd_t *cmd, int pnum) } else { - cmd->forwardmove -= m_forward.value * mouse_y; + movements[0] -= m_forward.value * mouse_y; } mouse_x = mouse_y = 0.0; diff --git a/engine/client/in_sdl.c b/engine/client/in_sdl.c index e33a13393..0088772ae 100644 --- a/engine/client/in_sdl.c +++ b/engine/client/in_sdl.c @@ -297,7 +297,7 @@ void IN_Init (void) #endif IN_ReInit(); } -void IN_Move (usercmd_t *cmd, int pnum) //add mouse movement to cmd +void IN_Move (float *movements, int pnum) //add mouse movement to cmd { mouse_x *= sensitivity.value*in_sensitivityscale; mouse_y *= sensitivity.value*in_sensitivityscale; @@ -307,7 +307,7 @@ void IN_Move (usercmd_t *cmd, int pnum) //add mouse movement to cmd { // add mouse X/Y movement to cmd if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) )) - cmd->sidemove += m_side.value * mouse_x; + movements[1] += m_side.value * mouse_x; else cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x; @@ -323,9 +323,9 @@ void IN_Move (usercmd_t *cmd, int pnum) //add mouse movement to cmd else { if ((in_strafe.state[pnum] & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; + movements[2] -= m_forward.value * mouse_y; else - cmd->forwardmove -= m_forward.value * mouse_y; + movements[0] -= m_forward.value * mouse_y; } } diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 18ec79eb7..ad41237d3 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -280,7 +280,7 @@ void IN_RawInput_DeInit(void); // forward-referenced functions void IN_StartupJoystick (void); void Joy_AdvancedUpdate_f (void); -void IN_JoyMove (usercmd_t *cmd, int pnum); +void IN_JoyMove (float *movements, int pnum); /* =========== @@ -1397,7 +1397,7 @@ void IN_MouseEvent (int mstate) } } -static void ProcessMouse(mouse_t *mouse, usercmd_t *cmd, int pnum) +static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) { extern int mousecursor_x, mousecursor_y; extern int mousemove_x, mousemove_y; @@ -1522,7 +1522,7 @@ static void ProcessMouse(mouse_t *mouse, usercmd_t *cmd, int pnum) } - if (!cmd) + if (!movements) { return; } @@ -1532,7 +1532,7 @@ static void ProcessMouse(mouse_t *mouse, usercmd_t *cmd, int pnum) // add mouse X/Y movement to cmd if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) )) - cmd->sidemove += m_side.value * mouse_x; + movements[1] += m_side.value * mouse_x; else { // if ((int)((cl.viewangles[pnum][PITCH]+89.99)/180) & 1) @@ -1552,9 +1552,9 @@ static void ProcessMouse(mouse_t *mouse, usercmd_t *cmd, int pnum) else { if ((in_strafe.state[pnum] & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; + movements[2] -= m_forward.value * mouse_y; else - cmd->forwardmove -= m_forward.value * mouse_y; + movements[0] -= m_forward.value * mouse_y; } } @@ -1565,7 +1565,7 @@ static void ProcessMouse(mouse_t *mouse, usercmd_t *cmd, int pnum) IN_MouseMove =========== */ -void IN_MouseMove (usercmd_t *cmd, int pnum) +void IN_MouseMove (float *movements, int pnum) { #ifdef RGLQUAKE extern int glwidth, glheight; @@ -1744,22 +1744,22 @@ void IN_MouseMove (usercmd_t *cmd, int pnum) for (x = 0; x < rawmicecount; x++) { - ProcessMouse(rawmice + x, cmd, 0); + ProcessMouse(rawmice + x, movements, 0); } } else if (pnum < rawmicecount) { - ProcessMouse(rawmice + pnum, cmd, pnum); + ProcessMouse(rawmice + pnum, movements, pnum); } } #endif if (pnum == 0) - ProcessMouse(&sysmouse, cmd, pnum); + ProcessMouse(&sysmouse, movements, pnum); #ifdef SERIALMOUSE if (pnum == 1 || cl.splitclients<2) - ProcessMouse(&serialmouse, cmd, pnum); + ProcessMouse(&serialmouse, movements, pnum); #endif } @@ -1769,14 +1769,14 @@ void IN_MouseMove (usercmd_t *cmd, int pnum) IN_Move =========== */ -void IN_Move (usercmd_t *cmd, int pnum) +void IN_Move (float *movements, int pnum) { if (ActiveApp && !Minimized) { - IN_MouseMove (cmd, pnum); + IN_MouseMove (movements, pnum); if (pnum == 1 || cl.splitclients<2) - IN_JoyMove (cmd, pnum); + IN_JoyMove (movements, pnum); } } @@ -2219,7 +2219,7 @@ qboolean IN_ReadJoystick (void) IN_JoyMove =========== */ -void IN_JoyMove (usercmd_t *cmd, int pnum) +void IN_JoyMove (float *movements, int pnum) { float speed, aspeed; float fAxisValue, fTemp; @@ -2313,7 +2313,7 @@ void IN_JoyMove (usercmd_t *cmd, int pnum) // user wants forward control to be forward control if (fabs(fAxisValue) > joy_forwardthreshold.value) { - cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; + movements[0] += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; } } break; @@ -2321,7 +2321,7 @@ void IN_JoyMove (usercmd_t *cmd, int pnum) case AxisSide: if (fabs(fAxisValue) > joy_sidethreshold.value) { - cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + movements[1] += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; } break; @@ -2331,7 +2331,7 @@ void IN_JoyMove (usercmd_t *cmd, int pnum) // user wants turn control to become side control if (fabs(fAxisValue) > joy_sidethreshold.value) { - cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; + movements[2] -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; } } else diff --git a/engine/client/input.h b/engine/client/input.h index 9d2e168e6..29ee743ea 100644 --- a/engine/client/input.h +++ b/engine/client/input.h @@ -28,7 +28,7 @@ void IN_Shutdown (void); void IN_Commands (void); // oportunity for devices to stick commands on the script buffer -void IN_Move (usercmd_t *cmd, int pnum); +void IN_Move (float *movements, int pnum); // add additional movement on top of the keyboard move cmd void IN_ModeChanged (void); diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index ee2b90457..2351a7237 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -1229,34 +1229,35 @@ cin_t *Media_Static_TryLoad(char *name) int imagewidth; int imageheight; + int fsize; char fullname[MAX_QPATH]; qbyte *file; sprintf(fullname, "%s", name); - file = COM_LoadMallocFile(fullname); //read file + fsize = FS_LoadFile(fullname, &file); if (!file) { sprintf(fullname, "pics/%s", name); - file = COM_LoadMallocFile(fullname); //read file + fsize = FS_LoadFile(fullname, &file); if (!file) return NULL; } - if ((staticfilmimage = ReadPCXFile(file, com_filesize, &imagewidth, &imageheight)) || //convert to 32 rgba if not corrupt - (staticfilmimage = ReadTargaFile(file, com_filesize, &imagewidth, &imageheight, false)) || + if ((staticfilmimage = ReadPCXFile(file, fsize, &imagewidth, &imageheight)) || //convert to 32 rgba if not corrupt + (staticfilmimage = ReadTargaFile(file, fsize, &imagewidth, &imageheight, false)) || #ifdef AVAIL_JPEGLIB - (staticfilmimage = ReadJPEGFile(file, com_filesize, &imagewidth, &imageheight)) || + (staticfilmimage = ReadJPEGFile(file, fsize, &imagewidth, &imageheight)) || #endif #ifdef AVAIL_PNGLIB - (staticfilmimage = ReadPNGFile(file, com_filesize, &imagewidth, &imageheight, fullname)) || + (staticfilmimage = ReadPNGFile(file, fsize, &imagewidth, &imageheight, fullname)) || #endif 0) { - BZ_Free(file); //got image data + FS_FreeFile(file); //got image data } else { - BZ_Free(file); //got image data + FS_FreeFile(file); //got image data Con_Printf("Static cinematic format not supported.\n"); //not supported format return NULL; } diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 2d72ffd7e..2c8fe6c26 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -268,22 +268,22 @@ void MSetup_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) extern qbyte translationTable[256]; setupmenu_t *info = menu->data; mpic_t *p; - qbyte *f; + void *f; if (info->skinedit->modified) { info->skinedit->modified = false; - f = COM_LoadMallocFile (va("gfx/player/%s.lmp", info->skinedit->text)); + FS_LoadFile(va("gfx/player/%s.lmp", info->skinedit->text), &f); if (!f) - f = COM_LoadMallocFile("gfx/menuplyr.lmp"); + FS_LoadFile("gfx/menuplyr.lmp", &f); if (f) { info->tiwidth = ((int*)f)[0]; info->tiheight = ((int*)f)[1]; memcpy(info->translationimage, f+8, info->tiwidth*info->tiheight); - BZ_Free(f); + FS_FreeFile(f); } } diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 3b9eeeab5..b73a0ecbd 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -1445,14 +1445,15 @@ static void P_LoadParticleSet(char *name, qboolean first) Cbuf_AddText(particle_set_tsshaft, RESTRICT_LOCAL); else { - char *file = COM_LoadMallocFile(va("particles/%s.cfg", name)); + char *file; + FS_LoadFile(va("particles/%s.cfg", name), (void**)&file); if (!file) - file = COM_LoadMallocFile(va("%s.cfg", name)); + FS_LoadFile(va("%s.cfg", name), (void**)&file); if (file) { Cbuf_AddText(file, restrictlevel); Cbuf_AddText("\n", restrictlevel); - BZ_Free(file); + FS_FreeFile(file); } else if (first) { @@ -4368,4 +4369,4 @@ particleengine_t pe_script = }; #endif -#endif \ No newline at end of file +#endif diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index cda90e15c..03592cf70 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -65,6 +65,8 @@ static int csqc_fakereadbyte; static int csqc_lplayernum; static qboolean csqc_isdarkplaces; +static char csqc_printbuffer[8192]; + #define CSQCPROGSGROUP "CSQC progs control" cvar_t pr_csmaxedicts = SCVAR("pr_csmaxedicts", "3072"); cvar_t cl_csqcdebug = SCVAR("cl_csqcdebug", "0"); //prints entity numbers which arrive (so I can tell people not to apply it to players...) @@ -145,6 +147,7 @@ typedef enum globalfunction(draw_function, "CSQC_UpdateView"); \ globalfunction(parse_stuffcmd, "CSQC_Parse_StuffCmd"); \ globalfunction(parse_centerprint, "CSQC_Parse_CenterPrint"); \ + globalfunction(parse_print, "CSQC_Parse_Print"); \ globalfunction(input_event, "CSQC_InputEvent"); \ globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \ globalfunction(console_command, "CSQC_ConsoleCommand"); \ @@ -2133,6 +2136,51 @@ static void PF_cs_particleeffectnum (progfuncs_t *prinst, struct globalvars_s *p G_FLOAT(OFS_RETURN) = pe->FindParticleType(effectname)+1; } +static void PF_cs_sendevent (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + csqcedict_t *ent; + int i; + char *eventname = PR_GetStringOfs(prinst, OFS_PARM0); + char *argtypes = PR_GetStringOfs(prinst, OFS_PARM1); + + MSG_WriteByte(&cls.netchan.message, clc_qcrequest); + for (i = 0; i < 6; i++) + { + if (argtypes[i] == 's') + { + MSG_WriteByte(&cls.netchan.message, ev_string); + MSG_WriteString(&cls.netchan.message, PR_GetStringOfs(prinst, OFS_PARM2+i*3)); + } + else if (argtypes[i] == 'f') + { + MSG_WriteByte(&cls.netchan.message, ev_float); + MSG_WriteFloat(&cls.netchan.message, G_FLOAT(OFS_PARM2+i*3)); + } + else if (argtypes[i] == 'i') + { + MSG_WriteByte(&cls.netchan.message, ev_integer); + MSG_WriteFloat(&cls.netchan.message, G_FLOAT(OFS_PARM2+i*3)); + } + else if (argtypes[i] == 'v') + { + MSG_WriteByte(&cls.netchan.message, ev_vector); + MSG_WriteFloat(&cls.netchan.message, G_FLOAT(OFS_PARM2+i*3+0)); + MSG_WriteFloat(&cls.netchan.message, G_FLOAT(OFS_PARM2+i*3+1)); + MSG_WriteFloat(&cls.netchan.message, G_FLOAT(OFS_PARM2+i*3+2)); + } + else if (argtypes[i] == 'e') + { + ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM2+i*3); + MSG_WriteByte(&cls.netchan.message, ev_entity); + MSG_WriteShort(&cls.netchan.message, ent->v->entnum); + } + else + break; + } + MSG_WriteByte(&cls.netchan.message, 0); + MSG_WriteString(&cls.netchan.message, eventname); +} + static void cs_set_input_state (usercmd_t *cmd) { if (csqcg.input_timelength) @@ -5105,13 +5153,13 @@ static struct { {"freepic", PF_CL_free_pic, 319}, // #319 void(string name) freepic (EXT_CSQC) //320 {"drawcharacter", PF_CL_drawcharacter, 320}, // #320 float(vector position, float character, vector scale, vector rgb, float alpha [, float flag]) drawcharacter (EXT_CSQC, [EXT_CSQC_???]) - {"drawstring", PF_CL_drawstring, 321}, // #321 float(vector position, string text, vector scale, vector rgb, float alpha [, float flag]) drawstring (EXT_CSQC, [EXT_CSQC_???]) + {"drawrawstring", PF_CL_drawrawstring, 321}, // #321 float(vector position, string text, vector scale, vector rgb, float alpha [, float flag]) drawstring (EXT_CSQC, [EXT_CSQC_???]) {"drawpic", PF_CL_drawpic, 322}, // #322 float(vector position, string pic, vector size, vector rgb, float alpha [, float flag]) drawpic (EXT_CSQC, [EXT_CSQC_???]) {"drawfill", PF_CL_drawfill, 323}, // #323 float(vector position, vector size, vector rgb, float alpha [, float flag]) drawfill (EXT_CSQC, [EXT_CSQC_???]) {"drawsetcliparea", PF_CL_drawsetcliparea, 324}, // #324 void(float x, float y, float width, float height) drawsetcliparea (EXT_CSQC_???) {"drawresetcliparea", PF_CL_drawresetcliparea, 325}, // #325 void(void) drawresetcliparea (EXT_CSQC_???) - {"drawcolorcodedstring", PF_CL_drawstring, 326}, // #326 + {"drawstring", PF_CL_drawcolouredstring, 326}, // #326 {"stringwidth", PF_CL_stringwidth, 327}, // #327 EXT_CSQC_'DARKPLACES' {"drawsubpic", PF_CL_drawsubpic, 328}, // #328 EXT_CSQC_'DARKPLACES' // {"?", PF_Fixme, 329}, // #329 EXT_CSQC_'DARKPLACES' @@ -5158,7 +5206,7 @@ static struct { // {"?", PF_Fixme, 356}, // #356 // {"?", PF_Fixme, 357}, // #357 // {"?", PF_Fixme, 358}, // #358 -// {"?", PF_Fixme, 359}, // #359 + {"sendevent", PF_cs_sendevent, 359}, // #359 void(string evname, string evargs, ...) (EXT_CSQC_1) //360 //note that 'ReadEntity' is pretty hard to implement reliably. Modders should use a combination of ReadShort, and findfloat, and remember that it might not be known clientside (pvs culled or other reason) @@ -5622,15 +5670,21 @@ qboolean CSQC_Init (unsigned int checksum) CSQC_InitFields(); //let the qclib know the field order that the engine needs. csqc_isdarkplaces = false; - if (PR_LoadProgs(csqcprogs, "csprogs.dat", 32199, NULL, 0) < 0) //no per-progs builtins. + if (PR_LoadProgs(csqcprogs, "csprogs.dat", 22390, NULL, 0) < 0) //no per-progs builtins. { if (PR_LoadProgs(csqcprogs, "csprogs.dat", 52195, NULL, 0) < 0) //no per-progs builtins. { - CSQC_Shutdown(); - //failed to load or something - return false; + if (PR_LoadProgs(csqcprogs, "csprogs.dat", 0, NULL, 0) < 0) //no per-progs builtins. + { + CSQC_Shutdown(); + //failed to load or something + return false; + } } - csqc_isdarkplaces = true; + else + csqc_isdarkplaces = true; + + Con_Printf(CON_WARNING "Running outdated or unknown csprogs.dat version\n"); } if (setjmp(csqc_abort)) { @@ -5873,7 +5927,7 @@ qboolean CSQC_DrawView(void) */ if (csqcg.cltime) *csqcg.cltime = cl.time; - if (csqcg.cltime) + if (csqcg.svtime) *csqcg.svtime = cl.servertime; CSQC_RunThreads(); //wake up any qc threads @@ -5971,6 +6025,64 @@ qboolean CSQC_LoadResource(char *resname, char *restype) return !!G_FLOAT(OFS_RETURN); } +void CSQC_ParsePrint(char *message, int printlevel) +{ + void *pr_globals; + int bufferpos; + char *nextline; + qboolean doflush; + if (!csqcprogs || !csqcg.parse_print) + { + Con_Printf("%s", message); + return; + } + + bufferpos = strlen(csqc_printbuffer); + + //fix-up faked bot chat + if (*message == '\1' && *csqc_printbuffer == '\1') + message++; + + while(*message) + { + nextline = strchr(message, '\n'); + if (nextline) + { + nextline+=1; + doflush = true; + } + else + { + nextline = message+strlen(message); + doflush = false; + } + + if (bufferpos + nextline-message >= sizeof(csqc_printbuffer)) + { + //if this would overflow the buffer, cap its length and flush the buffer + //this copes with too many strings and too long strings. + nextline = message + sizeof(csqc_printbuffer)-1 - bufferpos; + doflush = true; + } + + memcpy(csqc_printbuffer+bufferpos, message, nextline-message); + bufferpos += nextline-message; + csqc_printbuffer[bufferpos] = '\0'; + message = nextline; + + if (doflush) + { + pr_globals = PR_globals(csqcprogs, PR_CURRENT); + (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, csqc_printbuffer)); + G_FLOAT(OFS_PARM1) = printlevel; + PR_ExecuteProgram (csqcprogs, csqcg.parse_print); + + bufferpos = 0; + csqc_printbuffer[bufferpos] = 0; + } + } +} + qboolean CSQC_StuffCmd(int lplayernum, char *cmd) { void *pr_globals; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 9e9916afd..e594bc94b 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -382,8 +382,8 @@ void PF_CL_drawcharacter (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = 1; } -//float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455; -void PF_CL_drawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +//float drawrawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455; +void PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *pos = G_VECTOR(OFS_PARM0); char *text = PR_GetStringOfs(prinst, OFS_PARM1); @@ -406,10 +406,36 @@ void PF_CL_drawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) } } +//float drawstring(vector position, string text, vector scale, float alpha, float flag) = #455; +void PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *pos = G_VECTOR(OFS_PARM0); + char *text = PR_GetStringOfs(prinst, OFS_PARM1); + float *size = G_VECTOR(OFS_PARM2); +// float *alpha = G_FLOAT(OFS_PARM3); +// float flag = G_FLOAT(OFS_PARM4); + + if (!text) + { + G_FLOAT(OFS_RETURN) = -1; //was null.. + return; + } + + Draw_FunString(pos[0], pos[1], text); +} + void PF_CL_stringwidth(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - PF_strlen(prinst, pr_globals); -// G_FLOAT(OFS_RETURN)*=8; + char *text = PR_GetStringOfs(prinst, OFS_PARM0); + qboolean usecolours = G_FLOAT(OFS_PARM1); + if (usecolours) + { + G_FLOAT(OFS_RETURN) = COM_FunStringLength(text)*8; + } + else + { + G_FLOAT(OFS_RETURN) = strlen(text)*8; + } } #define DRAWFLAG_NORMAL 0 @@ -1389,7 +1415,7 @@ builtin_t menu_builtins[] = { PF_CL_precache_pic,//2 PF_CL_free_pic,//3 PF_CL_drawcharacter,//4 - PF_CL_drawstring,//5 + PF_CL_drawrawstring,//5 PF_CL_drawpic,//6 PF_CL_drawfill,//7 PF_CL_drawsetcliparea,//8 diff --git a/engine/client/sbar.c b/engine/client/sbar.c index d40a00538..6965fe8cd 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -146,222 +146,32 @@ int Sbar_BottomColour(player_info_t *p) return p->rbottomcolor; } -void Draw_FunString(int x, int y, unsigned char *str) +void Draw_ExpandedString(int x, int y, conchar_t *str) { - int ext = CON_WHITEMASK; - int extstack[4]; - int extstackdepth = 0; - - while(*str) { - if (*str == '^') - { - str++; - if (*str >= '0' && *str <= '9') - { - ext = q3codemasks[*str++-'0'] | (ext&~CON_Q3MASK); //change colour only. - continue; - } - else if (*str == '&') // extended code - { - if (isextendedcode(str[1]) && isextendedcode(str[2])) - { - str++;// foreground char - if (*str == '-') // default for FG - ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~CON_FGMASK); - else if (*str >= 'A') - ext = ((*str - ('A' - 10)) << CON_FGSHIFT) | (ext&~CON_FGMASK); - else - ext = ((*str - '0') << CON_FGSHIFT) | (ext&~CON_FGMASK); - str++; // background char - if (*str == '-') // default (clear) for BG - ext &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (*str >= 'A') - ext = ((*str - ('A' - 10)) << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; - else - ext = ((*str - '0') << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; - str++; - continue; - } - // else invalid code - goto messedup; - } - else if (*str == 'a') - { - str++; - ext ^= CON_2NDCHARSETTEXT; - continue; - } - else if (*str == 'b') - { - str++; - ext ^= CON_BLINKTEXT; - continue; - } - else if (*str == 'h') - { - str++; - ext ^= CON_HALFALPHA; - continue; - } - else if (*str == 's') //store on stack (it's great for names) - { - str++; - if (extstackdepth < sizeof(extstack)/sizeof(extstack[0])) - { - extstack[extstackdepth] = ext; - extstackdepth++; - } - continue; - } - else if (*str == 'r') //restore from stack (it's great for names) - { - str++; - if (extstackdepth) - { - extstackdepth--; - ext = extstack[extstackdepth]; - } - continue; - } - else if (*str == '^') - { - Draw_ColouredCharacter(x, y, '^' | ext); - str++; - } - else - { - Draw_ColouredCharacter(x, y, '^' | ext); - x += 8; - Draw_ColouredCharacter (x, y, (*str++) | ext); - } - x += 8; - continue; - } - if (*str == '&' && str[1] == 'c') - { - // ezQuake color codes - if (ishexcode(str[2]) && ishexcode(str[3]) && ishexcode(str[4])) - { - // Just strip it for now - // TODO: Colorize the console properly - str += 5; - continue; - } - } -messedup: - Draw_ColouredCharacter (x, y, (*str++) | ext); + Draw_ColouredCharacter (x, y, *str++); x += 8; } } -void Draw_FunStringLen(int x, int y, unsigned char *str, int len) +void Draw_FunString(int x, int y, unsigned char *str) { - int ext = CON_WHITEMASK; - int extstack[4]; - int extstackdepth = 0; + conchar_t buffer[2048]; + COM_ParseFunString(CON_WHITEMASK, str, buffer, sizeof(buffer)); + Draw_ExpandedString(x, y, buffer); +} - while(*str) - { - if (*str == '^') - { - str++; - if (*str >= '0' && *str <= '9') - { - ext = q3codemasks[*str++-'0'] | (ext&~CON_Q3MASK); //change colour only. - continue; - } - else if (*str == '&') // extended code - { - if (isextendedcode(str[1]) && isextendedcode(str[2])) - { - str++; // foreground char - if (*str == '-') // default for FG - ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~CON_FGMASK); - else if (*str >= 'A') - ext = ((*str - ('A' - 10)) << CON_FGSHIFT) | (ext&~CON_FGMASK); - else - ext = ((*str - '0') << CON_FGSHIFT) | (ext&~CON_FGMASK); - str++; // background char - if (*str == '-') // default (clear) for BG - ext &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (*str >= 'A') - ext = ((*str - ('A' - 10)) << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; - else - ext = ((*str - '0') << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; - str++; - continue; - } - // else invalid code - Draw_ColouredCharacter(x, y, '^' | ext); - Draw_ColouredCharacter(x, y, '&' | ext); - str++; - continue; - } - else if (*str == 'a') - { - str++; - ext ^= CON_2NDCHARSETTEXT; - continue; - } - else if (*str == 'b') - { - str++; - ext ^= CON_BLINKTEXT; - continue; - } - else if (*str == 'h') - { - str++; - ext ^= CON_HALFALPHA; - continue; - } - else if (*str == 's') //store on stack (it's great for names) - { - str++; - if (extstackdepth < sizeof(extstack)/sizeof(extstack[0])) - { - extstack[extstackdepth] = ext; - extstackdepth++; - } - } - else if (*str == 'r') //restore from stack (it's great for names) - { - str++; - if (extstackdepth) - { - extstackdepth--; - ext = extstack[extstackdepth]; - } - continue; - } - else if (*str == '^') - { - if (--len< 0) - break; - Draw_ColouredCharacter(x, y, '^' | ext); - str++; - } - else - { - if (--len< 0) - break; - if (--len< 0) - break; - Draw_ColouredCharacter(x, y, '^' | ext); - x += 8; - Draw_ColouredCharacter (x, y, (*str++) | ext); - } - x += 8; - continue; - } - if (--len< 0) - break; - Draw_ColouredCharacter (x, y, (*str++) | ext); - x += 8; - } +void Draw_FunStringLen(int x, int y, unsigned char *str, int numchars) +{ + conchar_t buffer[2048]; + + if (numchars > sizeof(buffer)-1) + numchars = sizeof(buffer)-1; + COM_ParseFunString(CON_WHITEMASK, str, buffer, numchars+1); + + Draw_ExpandedString(x, y, buffer); } static qboolean largegame = false; diff --git a/engine/client/view.c b/engine/client/view.c index f14cd3537..53392c260 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1393,6 +1393,7 @@ void R_DrawNameTags(void) void V_RenderPlayerViews(int plnum) { + int oldnuments; #ifdef SIDEVIEWS int viewnum; #endif @@ -1416,6 +1417,9 @@ void V_RenderPlayerViews(int plnum) V_CalcRefdef (plnum); } + oldnuments = cl_numvisedicts; + CL_LinkViewModel (); + #ifdef SWQUAKE if (cl.splitclients>1) r_viewchanged = true; @@ -1432,6 +1436,8 @@ void V_RenderPlayerViews(int plnum) R_DrawNameTags(); } + cl_numvisedicts = oldnuments; + if (scr_chatmode == 2) { extern vec3_t desired_position[MAX_SPLITS]; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index e71292cbd..fe86d8ca4 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -521,9 +521,10 @@ void Cmd_Exec_f (void) else Q_strncpyz(name, Cmd_Argv(1), sizeof(name)); - if ((f = (char *)COM_LoadMallocFile(name))) + FS_LoadFile(name, &f); + if (FS_LoadFile(name, &f) != -1) ; - else if ((f = (char *)COM_LoadMallocFile(va("%s.cfg", name)))) + else if (FS_LoadFile(va("%s.cfg", name), &f) != -1) ; else { @@ -535,7 +536,7 @@ void Cmd_Exec_f (void) // don't execute anything as if it was from server Cbuf_InsertText (f, Cmd_FromGamecode() ? RESTRICT_INSECURE : Cmd_ExecLevel, true); - BZ_Free(f); + FS_FreeFile(f); } diff --git a/engine/common/common.c b/engine/common/common.c index 3cffbbc4e..544da1399 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1665,7 +1665,7 @@ conchar_t q3codemasks[MAXQ3COLOURS] = { //Strips out the flags -void COM_DeFunString(unsigned long *str, char *out, int outsize, qboolean ignoreflags) +void COM_DeFunString(conchar_t *str, char *out, int outsize, qboolean ignoreflags) { if (ignoreflags) { @@ -1746,12 +1746,30 @@ void COM_DeFunString(unsigned long *str, char *out, int outsize, qboolean ignore } //Takes a q3-style fun string, and returns an expanded string-with-flags -void COM_ParseFunString(char *str, unsigned long *out, int outsize) +void COM_ParseFunString(conchar_t defaultflags, char *str, conchar_t *out, int outsize) { - int ext = CON_WHITEMASK; - int extstack[4]; + conchar_t extstack[4]; int extstackdepth = 0; + conchar_t ext; + +#if 0 + while(*str) + { + *out++ = CON_WHITEMASK|(unsigned char)*str++; + } + *out = 0; + return; +#endif + + if (*str == 1 || *str == 2) + { + defaultflags |= CON_HIGHCHARSMASK; + str++; + } + + ext = defaultflags; + while(*str) { if (*str == '^') @@ -1798,6 +1816,18 @@ void COM_ParseFunString(char *str, unsigned long *out, int outsize) ext ^= CON_BLINKTEXT; continue; } + else if (*str == 'd') + { + str++; + ext = defaultflags; + continue; + } + else if (*str == 'm') + { + str++; + ext ^= CON_HIGHCHARSMASK; + continue; + } else if (*str == 'h') { str++; @@ -1838,14 +1868,62 @@ void COM_ParseFunString(char *str, unsigned long *out, int outsize) *out++ = '^' | ext; if (!--outsize) break; - *out++ = (*str++) | ext; + *out++ = (unsigned char)(*str++) | ext; } continue; } + if (*str == '&' && str[1] == 'c') + { + // ezQuake color codes + + if (ishexcode(str[2]) && ishexcode(str[3]) && ishexcode(str[4])) + { + //we don't support the full 12bit colour depth (only 4-bit CGA) + //so find the closest that we do support + int best = 1; + float bd = 255*255*255, d; + int c; + float r, g, b; + if (str[2] >= '0' && str[2] <= '9') + r = (str[2]-'0') / (float)0xf; + else if (str[2] >= 'A' && str[2] <= 'F') + r = (str[2]-'A'+10) / (float)0xf; + else + r = (str[2]-'a'+10) / (float)0xf; + if (str[3] >= '0' && str[3] <= '9') + g = (str[3]-'0') / (float)0xf; + else if (str[3] >= 'A' && str[3] <= 'F') + g = (str[3]-'A'+10) / (float)0xf; + else + g = (str[3]-'a'+10) / (float)0xf; + if (str[4] >= '0' && str[4] <= '9') + b = (str[4]-'0') / (float)0xf; + else if (str[4] >= 'A' && str[4] <= 'F') + b = (str[4]-'A'+10) / (float)0xf; + else + b = (str[4]-'a'+10) / (float)0xf; + + for (c = 0; c < sizeof(consolecolours)/sizeof(consolecolours[0]); c++) + { + d = (consolecolours[c].fr-r)*(consolecolours[c].fr-r) + + (consolecolours[c].fg-g)*(consolecolours[c].fg-g) + + (consolecolours[c].fb-b)*(consolecolours[c].fb-b); + if (d < bd) + { + best = c; + bd = d; + } + } + ext = (best << CON_FGSHIFT) | (ext&~CON_FGMASK); + + str += 5; + continue; + } + } messedup: if (!--outsize) break; - *out++ = (*str++) | ext; + *out++ = (unsigned char)(*str++) | ext; } *out = 0; } @@ -1888,6 +1966,12 @@ int COM_FunStringLength(unsigned char *str) } continue; } + if (*str == '&' && str[1] == 'c' && ishexcode(str[2]) && ishexcode(str[3]) && ishexcode(str[4])) + { + //ezquake colour codes + str += 5; + continue; + } messedup: len++; str++; @@ -2983,7 +3067,7 @@ void COM_Effectinfo_Reload(void) COM_Effectinfo_Add(dpnames[i]); - f = COM_LoadMallocFile("effectinfo.txt"); + FS_LoadFile("effectinfo.txt", &f); if (!f) return; while (*f) @@ -3004,6 +3088,7 @@ void COM_Effectinfo_Reload(void) } while(*f && strcmp(com_token, "\n")); } } + FS_FreeFile(f); } unsigned int COM_Effectinfo_ForName(const char *efname) diff --git a/engine/common/common.h b/engine/common/common.h index b4a5d1b98..e2ff67ff4 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -256,14 +256,16 @@ void COM_Init (void); void COM_InitArgv (int argc, const char **argv); void COM_ParsePlusSets (void); +typedef unsigned int conchar_t; +void COM_DeFunString(conchar_t *str, char *out, int outsize, qboolean ignoreflags); +void COM_ParseFunString(conchar_t ext, char *str, conchar_t *out, int outsize); //ext is usually CON_WHITEMASK +int COM_FunStringLength(unsigned char *str); + char *COM_SkipPath (const char *pathname); void COM_StripExtension (const char *in, char *out, int outlen); void COM_FileBase (const char *in, char *out, int outlen); int COM_FileSize(const char *path); void COM_DefaultExtension (char *path, char *extension, int maxlen); -void COM_DeFunString(unsigned long *str, char *out, int outsize, qboolean ignoreflags); -void COM_ParseFunString(char *str, unsigned long *out, int outsize); -int COM_FunStringLength(unsigned char *str); char *COM_FileExtension (const char *in); void COM_CleanUpPath(char *str); @@ -367,7 +369,6 @@ qbyte *COM_LoadStackFile (const char *path, void *buffer, int bufsize); qbyte *COM_LoadTempFile (const char *path); qbyte *COM_LoadTempFile2 (const char *path); //allocates a little bit more without freeing old temp qbyte *COM_LoadHunkFile (const char *path); -qbyte *COM_LoadMallocFile (const char *path); void COM_LoadCacheFile (const char *path, struct cache_user_s *cu); void COM_CreatePath (char *path); void COM_Gamedir (const char *dir); @@ -377,6 +378,9 @@ char *COM_NextPath (char *prevpath); void COM_FlushFSCache(void); //a file was written using fopen void COM_RefreshFSCache_f(void); +int FS_LoadFile(char *name, void **file); +void FS_FreeFile(void *file); + qboolean COM_LoadMapPackFile(const char *name, int offset); void COM_FlushTempoaryPacks(void); diff --git a/engine/common/console.h b/engine/common/console.h index ce640e170..3ed2bcc1f 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // console // -typedef unsigned int conchar_t; - #define MAXCONCOLOURS 16 typedef struct { float fr, fg, fb; @@ -109,8 +107,6 @@ typedef struct console_s extern console_t con_main; extern console_t *con_current; // point to either con_main or con_chat -extern conchar_t con_ormask; - extern int scr_chatmode; //extern int con_totallines; diff --git a/engine/common/fs.c b/engine/common/fs.c index 539245118..f86262cb6 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1265,10 +1265,12 @@ qbyte *COM_LoadStackFile (const char *path, void *buffer, int bufsize) } - +/*warning: at some point I'll change this function to return only read-only buffers*/ int FS_LoadFile(char *name, void **file) { *file = COM_LoadMallocFile(name); + if (!*file) + return -1; return com_filesize; } void FS_FreeFile(void *file) @@ -1581,9 +1583,9 @@ char *COM_NextPath (char *prevpath) #ifndef CLIENTONLY char *COM_GetPathInfo (int i, int *crc) { -#ifdef WEBSERVER - extern cvar_t httpserver; -#endif +//#ifdef WEBSERVER +// extern cvar_t httpserver; +//#endif searchpath_t *s; static char name[MAX_OSPATH]; @@ -2000,6 +2002,9 @@ void FS_ReloadPackFiles_f(void) #ifdef _WIN32 #include +#ifdef MINGW +#define byte BYTE //some versions of mingw headers are broken slightly. this lets it compile. +#endif #include qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *basepath, int basepathlen) { @@ -2131,7 +2136,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base //append SteamApps\common\hexen 2 } -#ifndef NPQTV //this is *really* unfortunate, but doing this crashes the browser +#if !defined(NPQTV) && !defined(SERVERONLY) //this is *really* unfortunate, but doing this crashes the browser //I assume its because the client if (poshname) diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index 9c0ebc1e1..d663e7db3 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -1,38 +1,44 @@ #include "quakedef.h" #include "fs.h" +#ifndef _WIN32 +#define VFSSTDIO_Open VFSOS_Open +#define stdiofilefuncs osfilefuncs +#endif +#define FSSTDIO_OpenTemp FS_OpenTemp + typedef struct { vfsfile_t funcs; FILE *handle; -} vfsosfile_t; -int VFSOS_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +} vfsstdiofile_t; +static int VFSSTDIO_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) { - vfsosfile_t *intfile = (vfsosfile_t*)file; + vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return fread(buffer, 1, bytestoread, intfile->handle); } -int VFSOS_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) +static int VFSSTDIO_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) { - vfsosfile_t *intfile = (vfsosfile_t*)file; + vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return fwrite(buffer, 1, bytestoread, intfile->handle); } -qboolean VFSOS_Seek (struct vfsfile_s *file, unsigned long pos) +static qboolean VFSSTDIO_Seek (struct vfsfile_s *file, unsigned long pos) { - vfsosfile_t *intfile = (vfsosfile_t*)file; + vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return fseek(intfile->handle, pos, SEEK_SET) == 0; } -unsigned long VFSOS_Tell (struct vfsfile_s *file) +static unsigned long VFSSTDIO_Tell (struct vfsfile_s *file) { - vfsosfile_t *intfile = (vfsosfile_t*)file; + vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return ftell(intfile->handle); } -void VFSOS_Flush(struct vfsfile_s *file) +static void VFSSTDIO_Flush(struct vfsfile_s *file) { - vfsosfile_t *intfile = (vfsosfile_t*)file; + vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; fflush(intfile->handle); } -unsigned long VFSOS_GetSize (struct vfsfile_s *file) +static unsigned long VFSSTDIO_GetSize (struct vfsfile_s *file) { - vfsosfile_t *intfile = (vfsosfile_t*)file; + vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; unsigned int curpos; unsigned int maxlen; @@ -43,39 +49,39 @@ unsigned long VFSOS_GetSize (struct vfsfile_s *file) return maxlen; } -void VFSOS_Close(vfsfile_t *file) +static void VFSSTDIO_Close(vfsfile_t *file) { - vfsosfile_t *intfile = (vfsosfile_t*)file; + vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; fclose(intfile->handle); Z_Free(file); } -vfsfile_t *FS_OpenTemp(void) +vfsfile_t *FSSTDIO_OpenTemp(void) { FILE *f; - vfsosfile_t *file; + vfsstdiofile_t *file; f = tmpfile(); if (!f) return NULL; - file = Z_Malloc(sizeof(vfsosfile_t)); - file->funcs.ReadBytes = VFSOS_ReadBytes; - file->funcs.WriteBytes = VFSOS_WriteBytes; - file->funcs.Seek = VFSOS_Seek; - file->funcs.Tell = VFSOS_Tell; - file->funcs.GetLen = VFSOS_GetSize; - file->funcs.Close = VFSOS_Close; - file->funcs.Flush = VFSOS_Flush; + file = Z_Malloc(sizeof(vfsstdiofile_t)); + file->funcs.ReadBytes = VFSSTDIO_ReadBytes; + file->funcs.WriteBytes = VFSSTDIO_WriteBytes; + file->funcs.Seek = VFSSTDIO_Seek; + file->funcs.Tell = VFSSTDIO_Tell; + file->funcs.GetLen = VFSSTDIO_GetSize; + file->funcs.Close = VFSSTDIO_Close; + file->funcs.Flush = VFSSTDIO_Flush; file->handle = f; return (vfsfile_t*)file; } -vfsfile_t *VFSOS_Open(const char *osname, const char *mode) +vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode) { FILE *f; - vfsosfile_t *file; + vfsstdiofile_t *file; qboolean read = !!strchr(mode, 'r'); qboolean write = !!strchr(mode, 'w'); qboolean append = !!strchr(mode, 'a'); @@ -99,20 +105,20 @@ vfsfile_t *VFSOS_Open(const char *osname, const char *mode) if (!f) return NULL; - file = Z_Malloc(sizeof(vfsosfile_t)); - file->funcs.ReadBytes = strchr(mode, 'r')?VFSOS_ReadBytes:NULL; - file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSOS_WriteBytes:NULL; - file->funcs.Seek = VFSOS_Seek; - file->funcs.Tell = VFSOS_Tell; - file->funcs.GetLen = VFSOS_GetSize; - file->funcs.Close = VFSOS_Close; - file->funcs.Flush = VFSOS_Flush; + file = Z_Malloc(sizeof(vfsstdiofile_t)); + file->funcs.ReadBytes = strchr(mode, 'r')?VFSSTDIO_ReadBytes:NULL; + file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSSTDIO_WriteBytes:NULL; + file->funcs.Seek = VFSSTDIO_Seek; + file->funcs.Tell = VFSSTDIO_Tell; + file->funcs.GetLen = VFSSTDIO_GetSize; + file->funcs.Close = VFSSTDIO_Close; + file->funcs.Flush = VFSSTDIO_Flush; file->handle = f; return (vfsfile_t*)file; } -vfsfile_t *FSOS_OpenVFS(void *handle, flocation_t *loc, const char *mode) +static vfsfile_t *FSSTDIO_OpenVFS(void *handle, flocation_t *loc, const char *mode) { char diskname[MAX_OSPATH]; @@ -123,22 +129,22 @@ vfsfile_t *FSOS_OpenVFS(void *handle, flocation_t *loc, const char *mode) return VFSOS_Open(diskname, mode); } -void FSOS_PrintPath(void *handle) +static void FSSTDIO_PrintPath(void *handle) { Con_Printf("%s\n", handle); } -void FSOS_ClosePath(void *handle) +static void FSSTDIO_ClosePath(void *handle) { Z_Free(handle); } -int FSOS_RebuildFSHash(const char *filename, int filesize, void *data) +static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data) { if (filename[strlen(filename)-1] == '/') { //this is actually a directory char childpath[256]; sprintf(childpath, "%s*", filename); - Sys_EnumerateFiles((char*)data, childpath, FSOS_RebuildFSHash, data); + Sys_EnumerateFiles((char*)data, childpath, FSSTDIO_RebuildFSHash, data); return true; } if (!Hash_GetInsensative(&filesystemhash, filename)) @@ -156,11 +162,11 @@ int FSOS_RebuildFSHash(const char *filename, int filesize, void *data) fs_hash_dups++; return true; } -void FSOS_BuildHash(void *handle) +static void FSSTDIO_BuildHash(void *handle) { - Sys_EnumerateFiles(handle, "*", FSOS_RebuildFSHash, handle); + Sys_EnumerateFiles(handle, "*", FSSTDIO_RebuildFSHash, handle); } -qboolean FSOS_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { FILE *f; int len; @@ -198,7 +204,7 @@ qboolean FSOS_FLocate(void *handle, flocation_t *loc, const char *filename, void return true; } -void FSOS_ReadFile(void *handle, flocation_t *loc, char *buffer) +static void FSSTDIO_ReadFile(void *handle, flocation_t *loc, char *buffer) { FILE *f; f = fopen(loc->rawname, "rb"); @@ -208,19 +214,19 @@ void FSOS_ReadFile(void *handle, flocation_t *loc, char *buffer) fread(buffer, 1, loc->len, f); fclose(f); } -int FSOS_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm) +static int FSSTDIO_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm) { return Sys_EnumerateFiles(handle, match, func, parm); } -searchpathfuncs_t osfilefuncs = { - FSOS_PrintPath, - FSOS_ClosePath, - FSOS_BuildHash, - FSOS_FLocate, - FSOS_ReadFile, - FSOS_EnumerateFiles, +searchpathfuncs_t stdiofilefuncs = { + FSSTDIO_PrintPath, + FSSTDIO_ClosePath, + FSSTDIO_BuildHash, + FSSTDIO_FLocate, + FSSTDIO_ReadFile, + FSSTDIO_EnumerateFiles, NULL, NULL, - FSOS_OpenVFS + FSSTDIO_OpenVFS }; diff --git a/engine/common/fs_win32.c b/engine/common/fs_win32.c new file mode 100644 index 000000000..26886a996 --- /dev/null +++ b/engine/common/fs_win32.c @@ -0,0 +1,276 @@ +#include "quakedef.h" +#include "fs.h" +#include + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ~0 +#endif + +//read-only memory mapped files. +//for write access, we use the stdio module as a fallback. + +#define VFSW32_Open VFSOS_Open +#define w32filefuncs osfilefuncs + +typedef struct { + vfsfile_t funcs; + HANDLE hand; + HANDLE mmh; + void *mmap; + unsigned int length; + unsigned int offset; +} vfsw32file_t; +static int VFSW32_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +{ + DWORD read; + vfsw32file_t *intfile = (vfsw32file_t*)file; + if (intfile->mmap) + { + if (intfile->offset+bytestoread > intfile->length) + bytestoread = intfile->length-intfile->offset; + + memcpy(buffer, (char*)intfile->mmap + intfile->offset, bytestoread); + intfile->offset += bytestoread; + return bytestoread; + } + if (!ReadFile(intfile->hand, buffer, bytestoread, &read, NULL)) + return 0; + return read; +} +static int VFSW32_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) +{ + DWORD written; + vfsw32file_t *intfile = (vfsw32file_t*)file; + if (intfile->mmap) + { + if (intfile->offset+bytestoread > intfile->length) + bytestoread = intfile->length-intfile->offset; + + memcpy((char*)intfile->mmap + intfile->offset, buffer, bytestoread); + intfile->offset += bytestoread; + return bytestoread; + } + + if (!WriteFile(intfile->hand, buffer, bytestoread, &written, NULL)) + return 0; + return written; +} +static qboolean VFSW32_Seek (struct vfsfile_s *file, unsigned long pos) +{ + vfsw32file_t *intfile = (vfsw32file_t*)file; + if (intfile->mmap) + { + intfile->offset = pos; + return true; + } + + return SetFilePointer(intfile->hand, pos, NULL, FILE_BEGIN) != INVALID_SET_FILE_POINTER; +} +static unsigned long VFSW32_Tell (struct vfsfile_s *file) +{ + vfsw32file_t *intfile = (vfsw32file_t*)file; + if (intfile->mmap) + return intfile->offset; + return SetFilePointer(intfile->hand, 0, NULL, FILE_CURRENT); +} +static void VFSW32_Flush(struct vfsfile_s *file) +{ + vfsw32file_t *intfile = (vfsw32file_t*)file; + if (intfile->mmap) + FlushViewOfFile(intfile->mmap, intfile->length); + FlushFileBuffers(intfile->hand); +} +static unsigned long VFSW32_GetSize (struct vfsfile_s *file) +{ + vfsw32file_t *intfile = (vfsw32file_t*)file; + + if (intfile->mmap) + return intfile->length; + return GetFileSize(intfile->hand, NULL); +} +static void VFSW32_Close(vfsfile_t *file) +{ + vfsw32file_t *intfile = (vfsw32file_t*)file; + if (intfile->mmap) + { + UnmapViewOfFile(intfile->mmap); + CloseHandle(intfile->mmh); + } + CloseHandle(intfile->hand); + Z_Free(file); +} + +vfsfile_t *VFSW32_Open(const char *osname, const char *mode) +{ + HANDLE h, mh; + unsigned int fsize; + void *mmap; + + vfsw32file_t *file; + qboolean read = !!strchr(mode, 'r'); + qboolean write = !!strchr(mode, 'w'); + qboolean append = !!strchr(mode, 'a'); + qboolean text = !!strchr(mode, 't'); + write |= append; + + if (write && read) + h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + else if (write) + h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + else if (read) + h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + return NULL; + + if (write || append || text) + { + fsize = 0; + mh = INVALID_HANDLE_VALUE; + mmap = NULL; + } + else + { + fsize = GetFileSize(h, NULL); + mh = CreateFileMapping(h, NULL, PAGE_READONLY, 0, 0, NULL); + if (mh == INVALID_HANDLE_VALUE) + mmap = NULL; + else + { + mmap = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, fsize); + if (mmap == NULL) + { + CloseHandle(mh); + mh = INVALID_HANDLE_VALUE; + } + } + } + + file = Z_Malloc(sizeof(vfsw32file_t)); + file->funcs.ReadBytes = read?VFSW32_ReadBytes:NULL; + file->funcs.WriteBytes = (write||append)?VFSW32_WriteBytes:NULL; + file->funcs.Seek = VFSW32_Seek; + file->funcs.Tell = VFSW32_Tell; + file->funcs.GetLen = VFSW32_GetSize; + file->funcs.Close = VFSW32_Close; + file->funcs.Flush = VFSW32_Flush; + file->hand = h; + file->mmh = mh; + file->mmap = mmap; + file->offset = 0; + file->length = fsize; + + return (vfsfile_t*)file; +} + +static vfsfile_t *VFSW32_OpenVFS(void *handle, flocation_t *loc, const char *mode) +{ + char diskname[MAX_OSPATH]; + + //path is already cleaned, as anything that gets a valid loc needs cleaning up first. + + snprintf(diskname, sizeof(diskname), "%s/%s", (char*)handle, loc->rawname); + + return VFSW32_Open(diskname, mode); +} + +static void VFSW32_PrintPath(void *handle) +{ + Con_Printf("%s\n", handle); +} +static void VFSW32_ClosePath(void *handle) +{ + Z_Free(handle); +} +static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *data) +{ + if (filename[strlen(filename)-1] == '/') + { //this is actually a directory + + char childpath[256]; + sprintf(childpath, "%s*", filename); + Sys_EnumerateFiles((char*)data, childpath, VFSW32_RebuildFSHash, data); + return true; + } + if (!Hash_GetInsensative(&filesystemhash, filename)) + { + bucket_t *bucket = (bucket_t*)BZ_Malloc(sizeof(bucket_t) + strlen(filename)+1); + strcpy((char *)(bucket+1), filename); +#ifdef _WIN32 + Q_strlwr((char *)(bucket+1)); +#endif + Hash_AddInsensative(&filesystemhash, (char *)(bucket+1), data, bucket); + + fs_hash_files++; + } + else + fs_hash_dups++; + return true; +} +static void VFSW32_BuildHash(void *handle) +{ + Sys_EnumerateFiles(handle, "*", VFSW32_RebuildFSHash, handle); +} +static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +{ + FILE *f; + int len; + char netpath[MAX_OSPATH]; + + + if (hashedresult && (void *)hashedresult != handle) + return false; + +/* + if (!static_registered) + { // if not a registered version, don't ever go beyond base + if ( strchr (filename, '/') || strchr (filename,'\\')) + continue; + } +*/ + +// check a file in the directory tree + snprintf (netpath, sizeof(netpath)-1, "%s/%s",(char*)handle, filename); + + f = fopen(netpath, "rb"); + if (!f) + return false; + + fseek(f, 0, SEEK_END); + len = ftell(f); + fclose(f); + if (loc) + { + loc->len = len; + loc->offset = 0; + loc->index = 0; + Q_strncpyz(loc->rawname, filename, sizeof(loc->rawname)); + } + + return true; +} +static void VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer) +{ + FILE *f; + f = fopen(loc->rawname, "rb"); + if (!f) //err... + return; + fseek(f, loc->offset, SEEK_SET); + fread(buffer, 1, loc->len, f); + fclose(f); +} +static int VFSW32_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm) +{ + return Sys_EnumerateFiles(handle, match, func, parm); +} + +searchpathfuncs_t w32filefuncs = { + VFSW32_PrintPath, + VFSW32_ClosePath, + VFSW32_BuildHash, + VFSW32_FLocate, + VFSW32_ReadFile, + VFSW32_EnumerateFiles, + NULL, + NULL, + VFSW32_OpenVFS +}; diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 0841377bf..9044fab2e 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -1042,7 +1042,7 @@ int VARGS Plug_FS_Open(void *offset, unsigned int mask, const int *arg) if (arg[2] == 1) { - data = COM_LoadMallocFile(VM_POINTER(arg[0])); + FS_LoadFile(VM_POINTER(arg[0]), (void**)&data); if (!data) return -1; @@ -1306,8 +1306,12 @@ void Plug_Net_Close_Internal(int handle) { case STREAM_FILE: if (*pluginstreamarray[handle].file.filename) + { COM_WriteFile(pluginstreamarray[handle].file.filename, pluginstreamarray[handle].file.buffer, pluginstreamarray[handle].file.curlen); - BZ_Free(pluginstreamarray[handle].file.buffer); + BZ_Free(pluginstreamarray[handle].file.buffer); + } + else + FS_FreeFile(pluginstreamarray[handle].file.buffer); break; case STREAM_NONE: break; diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 9716f38b3..1e61a8e32 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1389,7 +1389,6 @@ void PF_vtos (progfuncs_t *prinst, struct globalvars_s *pr_globals) char pr_string_temp[64]; //sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); sprintf (pr_string_temp, "'%f %f %f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); - PR_TempString(prinst, pr_string_temp); RETURN_TSTRING(pr_string_temp); } @@ -1531,7 +1530,7 @@ void PF_strdecolorize (progfuncs_t *prinst, struct globalvars_s *pr_globals) char *in = PR_GetStringOfs(prinst, OFS_PARM0); char result[8192]; unsigned long flagged[8192]; - COM_ParseFunString(in, flagged, sizeof(flagged)/sizeof(flagged[0])); + COM_ParseFunString(CON_WHITEMASK, in, flagged, sizeof(flagged)/sizeof(flagged[0])); COM_DeFunString(flagged, result, sizeof(result), true); RETURN_TSTRING(result); diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index e2fb3225b..a811602c2 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -251,7 +251,8 @@ void PF_CL_is_cached_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_precache_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_free_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_drawcharacter (progfuncs_t *prinst, struct globalvars_s *pr_globals); -void PF_CL_drawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_drawpic (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_drawline (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_drawfill (progfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 908b45ec6..fab82fdc9 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -335,6 +335,9 @@ enum clcq2_ops_e #define clcdp_ackframe 50 #define clcdp_ackdownloaddata 51 +#define clc_qcrequest 81 +#define clc_prydoncursor 82 + //============================================== diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 6bf673b5d..2d2043c91 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -155,7 +155,6 @@ void QVM_UnloadDLL(dllhandle_t *handle) // ------------------------- * QVM files * ------------------------- #define VM_MAGIC 0x12721444 #define VM_MAGIC2 0x12721445 -#define LL(x) x = LittleLong(x) #pragma pack(push,1) typedef struct vmHeader_s @@ -318,47 +317,46 @@ typedef enum qvm_op_e qvm_t *QVM_LoadVM(const char *name, sys_callqvm_t syscall) { char path[MAX_QPATH]; - vmHeader_t *header; + vmHeader_t header, *srcheader; qvm_t *qvm; qbyte *raw; int n; int i; sprintf(path, "%s.qvm", name); - raw = COM_LoadMallocFile(path); -// FS_LoadFile(path, &raw, false); + FS_LoadFile(path, &raw); // file not found if(!raw) return NULL; - header=(vmHeader_t*)raw; + srcheader=(vmHeader_t*)raw; - LL(header->vmMagic); - LL(header->instructionCount); - LL(header->codeOffset); - LL(header->codeLength); - LL(header->dataOffset); - LL(header->dataLength); - LL(header->litLength); - LL(header->bssLength); + header.vmMagic = LittleLong(srcheader->vmMagic); + header.instructionCount = LittleLong(srcheader->instructionCount); + header.codeOffset = LittleLong(srcheader->codeOffset); + header.codeLength = LittleLong(srcheader->codeLength); + header.dataOffset = LittleLong(srcheader->dataOffset); + header.dataLength = LittleLong(srcheader->dataLength); + header.litLength = LittleLong(srcheader->litLength); + header.bssLength = LittleLong(srcheader->bssLength); - if (header->vmMagic==VM_MAGIC2) + if (header.vmMagic==VM_MAGIC2) { //version2 cotains a jump table of sorts //it is redundant information and can be ignored //its also more useful for jit rather than bytecode - LL(header->jtrgLength); + header.jtrgLength = LittleLong(srcheader->jtrgLength); } // check file - if(header->vmMagic!=VM_MAGIC && header->vmMagic!=VM_MAGIC2 || header->instructionCount<=0 || header->codeLength<=0) + if(header.vmMagic!=VM_MAGIC && header.vmMagic!=VM_MAGIC2 || header.instructionCount<=0 || header.codeLength<=0) { Con_Printf("%s: invalid qvm file\n", name); - BZ_Free(raw); + FS_FreeFile(raw); return NULL; } // create vitrual machine qvm=Z_Malloc(sizeof(qvm_t)); - qvm->len_cs=header->instructionCount+1; //bad opcode padding. - qvm->len_ds=header->dataLength+header->litLength+header->bssLength; + qvm->len_cs=header.instructionCount+1; //bad opcode padding. + qvm->len_ds=header.dataLength+header.litLength+header.bssLength; qvm->len_ss=256*1024; // 256KB stack space // memory @@ -399,9 +397,9 @@ qvm_t *QVM_LoadVM(const char *name, sys_callqvm_t syscall) // load instructions { - qbyte *src=raw+header->codeOffset; + qbyte *src=raw+header.codeOffset; int *dst=(int*)qvm->cs; - int total=header->instructionCount; + int total=header.instructionCount; qvm_op_t op; for(n=0; ndataOffset); + int *src=(int*)(raw+header.dataOffset); int *dst=(int*)qvm->ds; - int total=header->dataLength/4; + int total=header.dataLength/4; for(n=0; nlitLength); + memcpy(dst, src, header.litLength); } - BZ_Free(raw); + FS_FreeFile(raw); return qvm; } diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 7139a4abc..21ed3e45d 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -6247,6 +6247,10 @@ SOURCE=..\common\fs_stdio.c # End Source File # Begin Source File +SOURCE=..\common\fs_win32.c +# End Source File +# Begin Source File + SOURCE=..\common\fs_zip.c # End Source File # Begin Source File @@ -6365,7 +6369,7 @@ SOURCE=..\qclib\execloop.h !IF "$(CFG)" == "ftequake - Win32 Release" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6387,7 +6391,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 Debug" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6409,7 +6413,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6431,7 +6435,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6453,7 +6457,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6475,7 +6479,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6497,7 +6501,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6519,7 +6523,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6541,7 +6545,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6563,7 +6567,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6585,7 +6589,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6607,7 +6611,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6629,7 +6633,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ @@ -6651,7 +6655,7 @@ BuildCmds= \ !ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" # Begin Custom Build -InputDir=\Quake\ftesrc\engine\QCLIB +InputDir=\Games\Quake\ftesrc\engine\QCLIB InputPath=..\qclib\execloop.h BuildCmds= \ diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index b2d97b255..605ace709 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -380,7 +380,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) char *mem; char alternatename[MAX_QPATH]; snprintf(alternatename, sizeof(alternatename), "pics/%s.pcx", path); - data = COM_LoadMallocFile (alternatename); + FS_LoadFile(alternatename, (void**)&data); if (data) { strcpy(pic->name, path); @@ -400,7 +400,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) glmenu_numcachepics++; return &pic->pic; } - BZ_Free(data); + FS_FreeFile(data); } } @@ -408,7 +408,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) char *mem; char alternatename[MAX_QPATH]; snprintf(alternatename, MAX_QPATH-1, "%s", path); - data = COM_LoadMallocFile (alternatename); + FS_LoadFile(alternatename, &data); if (data) { strcpy(pic->name, path); @@ -441,7 +441,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) glmenu_numcachepics++; return &pic->pic; } - BZ_Free(data); + FS_FreeFile(data); } } @@ -450,7 +450,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) char *mem; char alternatename[MAX_QPATH]; snprintf(alternatename, MAX_QPATH-1,"%s.jpg", path); - data = COM_LoadMallocFile (alternatename); + FS_LoadFile(alternatename, (void**)&data); if (data) { strcpy(pic->name, path); @@ -470,7 +470,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) glmenu_numcachepics++; return &pic->pic; } - BZ_Free(data); + FS_FreeFile(data); } } #endif @@ -863,8 +863,9 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); { //gulp... so it's come to this has it? rework the hexen2 conchars into the q1 system. - char *tempchars = COM_LoadMallocFile("gfx/menu/conchars.lmp"); + char *tempchars; char *in, *out; + FS_LoadFile("gfx/menu/conchars.lmp", (void**)&tempchars); if (tempchars) { draw_chars = BZ_Malloc(8*8*256*8); @@ -900,7 +901,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); *out++ = *in++; } } - Z_Free(tempchars); + FS_FreeFile(tempchars); // add ocrana leds if (con_ocranaleds.value && con_ocranaleds.value != 2) @@ -999,7 +1000,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); glmenu_numcachepics++; } TRACE(("dbg: GLDraw_ReInit: gfx/menu/bigfont\n")); - bigfont = (qpic_t *)COM_LoadMallocFile ("gfx/menu/bigfont.lmp"); + FS_LoadFile("gfx/menu/bigfont.lmp", (void**)&bigfont); if (bigfont) { char *data; @@ -1019,6 +1020,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); gl->sh = 1; gl->th = 1; glmenu_numcachepics++; + FS_FreeFile(bigfont); } diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index caf0eacfc..1fab0c73f 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -205,9 +205,7 @@ void GLMod_Shutdown (void) Cmd_RemoveCommand("mod_texturelist"); Cmd_RemoveCommand("mod_usetexture"); -#ifdef RUNTIMELIGHTING - lightmodel = NULL; -#endif + GLMod_ClearAll(); } /* @@ -276,6 +274,24 @@ mleaf_t *GLMod_PointInLeaf (model_t *model, vec3_t p) return NULL; // never reached } +#if defined(RUNTIMELIGHTING) && defined(MULTITHREAD) +void *relightthread; +volatile qboolean wantrelight; + +void RelightThread(void *arg) +{ + while (wantrelight && relitsurface < lightmodel->numsurfaces) + { + LightFace(relitsurface); + lightmodel->surfaces[relitsurface].cached_dlight = -1; + + relitsurface++; + + lightmodel->surfaces[relitsurface].cached_dlight = -1; + } +} +#endif + /* =================== Mod_ClearAll @@ -284,17 +300,47 @@ Mod_ClearAll void GLMod_ClearAll (void) { int i; + int t; model_t *mod; #ifdef RUNTIMELIGHTING +#ifdef MULTITHREAD + if (relightthread) + { + wantrelight = false; + Sys_WaitOnThread(relightthread); + relightthread = NULL; + } +#endif lightmodel = NULL; #endif + //when the hunk is reset, all bsp models need to be reloaded for (i=0 , mod=mod_known ; ineedload) + continue; + + if (mod->type == mod_brush) + { + for (t = 0; t < mod->numtextures; t++) + { + if (!mod->textures[t]) + continue; + if (mod->textures[t]->gl_vboe) + qglDeleteBuffersARB(1, &mod->textures[t]->gl_vboe); + if (mod->textures[t]->gl_vbov) + qglDeleteBuffersARB(1, &mod->textures[t]->gl_vbov); + mod->textures[t]->gl_vboe = 0; + mod->textures[t]->gl_vbov = 0; + } + } + if (mod->type != mod_alias && mod->type != mod_halflife ) mod->needload = true; + } } void GLMod_Think (void) @@ -306,21 +352,31 @@ void GLMod_Think (void) { return; } +#ifdef MULTITHREAD + if (!relightthread) + { + wantrelight = true; + relightthread = Sys_CreateThread(RelightThread, lightmodel, 0); + } +#else LightFace(relitsurface); GLMod_UpdateLightmap(relitsurface); relitsurface++; - +#endif if (relitsurface >= lightmodel->numsurfaces) { char filename[MAX_QPATH]; - char *f; - Con_Printf("Finished lighting level\n"); + Con_Printf("Finished lighting %s\n", lightmodel->name); - - strcpy(filename, lightmodel->name); - f = COM_SkipPath(filename); - *f = '\0'; +#ifdef MULTITHREAD + if (relightthread) + { + wantrelight = false; + Sys_WaitOnThread(relightthread); + relightthread = NULL; + } +#endif if (lightmodel->deluxdata) { @@ -410,7 +466,6 @@ model_t *GLMod_LoadModel (model_t *mod, qboolean crash) unsigned *buf = NULL; qbyte stackbuf[1024]; // avoid dirtying the cache heap char mdlbase[MAX_QPATH]; - qboolean lastload = false; char *replstr; qboolean doomsprite = false; @@ -730,10 +785,10 @@ static char *GLMod_TD_Section(char *file, const char *sectionname) void GLMod_InitTextureDescs(char *mapname) { if (advtexturedesc) - BZ_Free(advtexturedesc); - advtexturedesc = COM_LoadMallocFile(va("maps/shaders/%s.shaders", mapname)); + FS_FreeFile(advtexturedesc); + FS_LoadFile(va("maps/shaders/%s.shaders", mapname), (void**)&advtexturedesc); if (!advtexturedesc) - advtexturedesc = COM_LoadMallocFile(va("shaders/%s.shaders", mapname)); + FS_LoadFile(va("shaders/%s.shaders", mapname), (void**)&advtexturedesc); if (advtexturedesc) { mapsection = advtexturedesc; @@ -741,7 +796,7 @@ void GLMod_InitTextureDescs(char *mapname) } else { - advtexturedesc = COM_LoadMallocFile(va("map.shaders", mapname)); + FS_LoadFile(va("map.shaders", mapname), (void**)&advtexturedesc); mapsection = GLMod_TD_Section(advtexturedesc, mapname); defaultsection = GLMod_TD_Section(advtexturedesc, "default"); } @@ -1045,7 +1100,8 @@ TRACE(("dbg: GLMod_LoadTextures: inittexturedescs\n")); char *star; //find the * if (!strcmp(gl_shadeq1_name.string, "*")) - tx->shader = R_RegisterCustom(mt->name, NULL); //just load the regular name. + // tx->shader = R_RegisterCustom(mt->name, NULL); //just load the regular name. + tx->shader = R_RegisterShader(mt->name); //just load the regular name. else if (!(star = strchr(gl_shadeq1_name.string, '*')) || (strlen(gl_shadeq1_name.string)+strlen(mt->name)+1>=sizeof(altname))) //it's got to fit. tx->shader = R_RegisterCustom(gl_shadeq1_name.string, NULL); else @@ -2082,7 +2138,7 @@ void GLMod_LoadCrouchHull(void) COM_StripExtension(loadmodel->name, crouchhullname, sizeof(crouchhullname)); COM_DefaultExtension(crouchhullname, ".crh",sizeof(crouchhullname)); //crouch hull - crouchhullfile = COM_LoadMallocFile(crouchhullname); //or otherwise temporary storage. load on hunk if you want, but that would be a waste. + FS_LoadFile(crouchhullname, &crouchhullfile); if (!crouchhullfile) return; @@ -2816,7 +2872,7 @@ qboolean GLMod_LoadBrushModel (model_t *mod, void *buffer) if (crouchhullfile) { - BZ_Free(crouchhullfile); + FS_FreeFile(crouchhullfile); crouchhullfile=NULL; } diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index e28f143b0..09068635b 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -70,6 +70,10 @@ typedef struct { typedef struct mesh_s { + unsigned int vbofirstvert; + unsigned int vbofirstelement; + + int numvertexes; vec3_t *xyz_array; vec3_t *normals_array; @@ -176,6 +180,9 @@ typedef struct texture_s struct shader_s *shader; + int gl_vbov; + int gl_vboe; + struct msurface_s *texturechain; // for gl_texsort drawing int anim_total; // total tenths in sequence ( 0 = no) int anim_min, anim_max; // time for this frame min <=time< max @@ -184,6 +191,9 @@ typedef struct texture_s unsigned offsets[MIPLEVELS]; // four mip maps stored } texture_t; +//the per-texture vbos have this stride (v_pos/st/lm_st) +#define VBOSTRIDE (3+2+2)*sizeof(float) + #define SURF_DRAWSKYBOX 0x00001 #define SURF_PLANEBACK 0x00002 #define SURF_DRAWSKY 0x00004 diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index 58f58eb54..d528f88a8 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -487,6 +487,123 @@ static void PPL_BaseChain_NoBump_2TMU_Overbright(msurface_t *s, texture_t *tex) qglDisable(GL_ALPHA_TEST); } +static void PPL_BaseChain_VBO_NoBump_2TMU_Overbright(msurface_t *s, texture_t *tex) +{ //doesn't merge surfaces, but tells gl to do each vertex arrayed surface individually, which means no vertex copying. + int vi; + glRect_t *theRect; + + varrayactive = false; + qglDisableClientState(GL_COLOR_ARRAY); + qglEnableClientState(GL_VERTEX_ARRAY); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tex->gl_vbov); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tex->gl_vboe); + + qglVertexPointer(3, GL_FLOAT, VBOSTRIDE, NULL); + + if (tex->alphaed || currententity->shaderRGBAf[3]<1) + { + if (*tex->name == '{') + { + qglEnable(GL_ALPHA_TEST); + qglDisable(GL_BLEND); + GL_TexEnv(GL_REPLACE); + } + else + { + qglEnable(GL_BLEND); + GL_TexEnv(GL_MODULATE); + } + } + else + { + qglDisable(GL_BLEND); + GL_TexEnv(GL_REPLACE); + } + + + GL_MBind(GL_TEXTURE0_ARB, tex->gl_texturenum); + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + qglTexCoordPointer(2, GL_FLOAT, VBOSTRIDE, (void*)(3*sizeof(float))); + + GL_SelectTexture(GL_TEXTURE1_ARB); + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + qglTexCoordPointer(2, GL_FLOAT, VBOSTRIDE, (void*)(5*sizeof(float))); + + GL_TexEnv(GL_MODULATE); + + +/* if (currententity->shaderRGBAf[3]<1) + { + s->lightmaptexturenum = -1; + qglBlendFunc(GL_SRC_COLOR, GL_ONE); + } +*/ + if (overbright != 1) + { + GL_TexEnv(GL_COMBINE_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); + qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, overbright); //this is the key + } + +// numidxs = 0; + vi = -1; + for (; s ; s=s->texturechain) + { + if (!s->mesh) //urm. + continue; + if (s->mesh->numvertexes <= 1) + continue; + if (vi != s->lightmaptexturenum) + { + if (vi<0) + qglEnable(GL_TEXTURE_2D); + vi = s->lightmaptexturenum; + + if (vi>=0) + { + GL_Bind(lightmap_textures[vi] ); + if (lightmap[vi]->modified) + { + lightmap[vi]->modified = false; + theRect = &lightmap[vi]->rectchange; + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, + lightmap[vi]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*lightmap_bytes); + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + } + } + else + qglDisable(GL_TEXTURE_2D); + } + qglDrawRangeElements(GL_TRIANGLES, s->mesh->vbofirstvert, s->mesh->numvertexes, s->mesh->numindexes, GL_INDEX_TYPE, (index_t*)(s->mesh->vbofirstelement*sizeof(index_t))); + } + + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + + if (overbright != 1) + { + qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1); //just in case + GL_TexEnv(GL_MODULATE); + } + + //tmu 1 should be selected here + qglDisable(GL_TEXTURE_2D); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + + GL_SelectTexture(GL_TEXTURE0_ARB); + qglDisableClientState(GL_TEXTURE_COORD_ARRAY); + qglDisable(GL_TEXTURE_2D); + + if (tex->alphaed) + qglDisable(GL_ALPHA_TEST); +} + /* static void PPL_BaseChain_NoBump_2TMU_TEST(msurface_t *s, texture_t *tex) { //this was just me testing efficiency between arrays/glbegin. @@ -1534,6 +1651,7 @@ static void PPL_BaseChain_NPR_Sketch(msurface_t *first) static void PPL_BaseTextureChain(msurface_t *first) { texture_t *t; + shader_t *shader; if (r_drawflat.value||!r_lightmapintensity) { if (r_drawflat.value == 2) @@ -1553,8 +1671,12 @@ static void PPL_BaseTextureChain(msurface_t *first) return; } } + + t = R_TextureAnimation (first->texinfo->texture); + #ifdef Q3SHADERS - if (first->texinfo->texture->shader) + shader = t->shader; + if (shader)// && shader->style != SSTYLE_LIGHTMAPPED) { meshbuffer_t mb; msurface_t *s; @@ -1563,7 +1685,7 @@ static void PPL_BaseTextureChain(msurface_t *first) int dlb; glRect_t *theRect; - if (first->texinfo->texture->shader->flags & SHADER_FLARE ) + if (shader->flags & SHADER_FLARE ) { dlight_t *dl; while(first) @@ -1588,7 +1710,7 @@ static void PPL_BaseTextureChain(msurface_t *first) R_IBrokeTheArrays(); mb.entity = &r_worldentity; - mb.shader = first->texinfo->texture->shader; + mb.shader = shader; mb.mesh = NULL; mb.fog = NULL; mb.infokey = -2; @@ -1675,10 +1797,6 @@ static void PPL_BaseTextureChain(msurface_t *first) - - - t = R_TextureAnimation (first->texinfo->texture); - if (first->flags & SURF_DRAWTURB) { GL_DisableMultitexture(); @@ -1726,7 +1844,10 @@ static void PPL_BaseTextureChain(msurface_t *first) { // PPL_BaseChain_NoBump_2TMU_TEST(first, t); // PPL_BaseChain_NoBump_2TMU(first, t); - PPL_BaseChain_NoBump_2TMU_Overbright(first, t); + if (t->gl_vbov) + PPL_BaseChain_VBO_NoBump_2TMU_Overbright(first, t); + else + PPL_BaseChain_NoBump_2TMU_Overbright(first, t); } } } diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index adfbcb4bc..534a3bf02 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -3397,8 +3397,7 @@ void GL_BuildSurfaceDisplayList (msurface_t *fa) if (lnumverts<3) return; //q3 map. -//#ifdef Q3SHADERS -// if (fa->texinfo->texture->shader) + { //build a nice mesh instead of a poly. int size = sizeof(mesh_t) + sizeof(index_t)*(lnumverts-2)*3 + (sizeof(vec3_t) + sizeof(vec3_t) + 2*sizeof(vec2_t) + sizeof(byte_vec4_t))*lnumverts; mesh_t *mesh; @@ -3470,109 +3469,7 @@ void GL_BuildSurfaceDisplayList (msurface_t *fa) mesh->colors_array[i][2] = 255; mesh->colors_array[i][3] = 255; } - - return; } -//#endif - // - // draw texture - // - /* - poly = Hunk_AllocName (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float), "SDList"); - poly->next = fa->polys; - fa->polys = poly; - poly->numverts = lnumverts; - - for (i=0 ; isurfedges[fa->firstedge + i]; - - if (lindex > 0) - { - r_pedge = &pedges[lindex]; - vec = r_pcurrentvertbase[r_pedge->v[0]].position; - } - else - { - r_pedge = &pedges[-lindex]; - vec = r_pcurrentvertbase[r_pedge->v[1]].position; - } - - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - - VectorCopy (vec, poly->verts[i]); - poly->verts[i][3] = s/fa->texinfo->texture->width; - poly->verts[i][4] = t/fa->texinfo->texture->height; - - // - // lightmap texture coordinates - // - s -= fa->texturemins[0]; - lm = s*fa->light_t; - s += fa->light_s*16; - s += 8; - s /= LMBLOCK_WIDTH*16; - - t -= fa->texturemins[1]; - lm += t; - t += fa->light_t*16; - t += 8; - t /= LMBLOCK_HEIGHT*16; - - poly->verts[i][5] = s; - poly->verts[i][6] = t; - -#ifdef SPECULAR - if (fa->flags & SURF_PLANEBACK) - VectorNegate(fa->plane->normal, (poly->verts[i]+7)); - else - VectorCopy(fa->plane->normal, (poly->verts[i]+7)); -#endif - } - - // - // remove co-linear points - Ed - // - if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) ) - { - for (i = 0 ; i < lnumverts ; ++i) - { - vec3_t v1, v2; - float *prev, *this, *next; - - prev = poly->verts[(i + lnumverts - 1) % lnumverts]; - this = poly->verts[i]; - next = poly->verts[(i + 1) % lnumverts]; - - VectorSubtract( this, prev, v1 ); - VectorNormalize( v1 ); - VectorSubtract( next, prev, v2 ); - VectorNormalize( v2 ); - - // skip co-linear points - #define COLINEAR_EPSILON 0.001 - if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) && - (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && - (fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON)) - { - int j; - for (j = i + 1; j < lnumverts; ++j) - { - int k; - for (k = 0; k < VERTEXSIZE; ++k) - poly->verts[j - 1][k] = poly->verts[j][k]; - } - --lnumverts; - ++nColinElim; - // retry next vertex next time, which is now current vertex - --i; - } - } - } - - poly->numverts = lnumverts; - */ } /* @@ -3643,6 +3540,84 @@ void GLSurf_DeInit(void) numlightmaps=0; } +void GL_GenBrushModelVBO(model_t *mod) +{ + unsigned int maxvboverts; + unsigned int maxvboelements; + + unsigned int t; + unsigned int i; + unsigned int vbov, vboe; + unsigned int v; + unsigned int vcount, ecount; + void *vbovdata; + index_t *vboedata; + mesh_t *m; +#define VBOSTRIDE (3+2+2)*4 + if (!qglGenBuffersARB || !mod->numsurfaces) + return; + + for (t = 0; t < mod->numtextures; t++) + { + if (!mod->textures[t]) + continue; + + mod->textures[t]->gl_vbov = 0; + mod->textures[t]->gl_vboe = 0; + + maxvboverts = 0; + maxvboelements = 0; + for (i=0 ; inumsurfaces ; i++) + { + if (mod->surfaces[i].texinfo->texture != mod->textures[t]) + continue; + m = mod->surfaces[i].mesh; + + maxvboelements += m->numindexes; + maxvboverts += m->numvertexes; + } + if (maxvboverts > (1<<(sizeof(index_t)*8))-1) + continue; + if (!maxvboverts) + continue; + + //fixme: stop this from leaking! + qglGenBuffersARB(1, &vbov); + qglGenBuffersARB(1, &vboe); + mod->textures[t]->gl_vbov = vbov; + mod->textures[t]->gl_vboe = vboe; + vcount = 0; + ecount = 0; + vbovdata = Hunk_TempAlloc(maxvboverts*VBOSTRIDE); + vboedata = Hunk_TempAllocMore(maxvboelements*sizeof(index_t)); + for (i=0 ; inumsurfaces ; i++) + { + if (mod->surfaces[i].texinfo->texture != mod->textures[t]) + continue; + m = mod->surfaces[i].mesh; + + m->vbofirstvert = vcount; + m->vbofirstelement = ecount; + for (v = 0; v < m->numindexes; v++) + vboedata[ecount++] = vcount + m->indexes[v]; + for (v = 0; v < m->numvertexes; v++) + { + memcpy((char*)vbovdata+(vcount+v)*VBOSTRIDE + 0, &m->xyz_array[v], sizeof(vec3_t)); + if (m->st_array) + memcpy((char*)vbovdata+(vcount+v)*VBOSTRIDE + 12, &m->st_array[v], sizeof(vec2_t)); + if (m->lmst_array) + memcpy((char*)vbovdata+(vcount+v)*VBOSTRIDE + 20, &m->lmst_array[v], sizeof(vec2_t)); + } + vcount += v; + } + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbov); + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vcount*VBOSTRIDE, vbovdata, GL_STATIC_DRAW_ARB); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vboe); + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ecount*sizeof(vboedata[0]), vboedata, GL_STATIC_DRAW_ARB); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } +} /* ================== @@ -3747,7 +3722,7 @@ void GL_BuildLightmaps (void) for (t = 0; t < m->numtextures; t++) { for (i=0 ; inumsurfaces ; i++) - {//extra surface loop so we get slightly less texture switches + {//extra texture loop so we get slightly less texture switches if (m->surfaces[i].texinfo->texture == m->textures[t]) { GL_CreateSurfaceLightmap (m->surfaces + i, shift); @@ -3758,6 +3733,8 @@ void GL_BuildLightmaps (void) } } } + + GL_GenBrushModelVBO(m); } // diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 29bc9f243..2408fc71d 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -628,7 +628,6 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p if (uniformloc == -1) { Con_Printf("shader %s: param without uniform \"%s\"\n", shader->name, token); - return; } else { @@ -2144,6 +2143,8 @@ void Shader_DefaultBSP(char *shortname, shader_t *s) s->features = MF_STCOORDS|MF_LMCOORDS|MF_TRNORMALS; s->sort = SHADER_SORT_OPAQUE; s->registration_sequence = 1;//fizme: registration_sequence; + + s->style = SSTYLE_LIGHTMAPPED; } void Shader_DefaultBSPVertex(char *shortname, shader_t *s) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index eba33d162..6e6e1002c 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -99,6 +99,12 @@ void (APIENTRY *qglFogfv) (GLenum pname, const GLfloat *params); void (APIENTRY *qglDeleteTextures) (GLsizei n, const GLuint *textures); +void (APIENTRY *qglGenBuffersARB)(GLsizei n, GLuint* ids); +void (APIENTRY *qglDeleteBuffersARB)(GLsizei n, GLuint* ids); +void (APIENTRY *qglBindBufferARB)(GLenum target, GLuint id); +void (APIENTRY *qglBufferDataARB)(GLenum target, GLsizei size, const void* data, GLenum usage); +void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei size, void* data); + /* PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB; PFNGLGETPROGRAMIVARBPROC qglGetProgramivARB; @@ -338,6 +344,15 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) if (gl_mtexarbable && gl_config.arb_texture_cube_map && gl_config.arb_texture_env_combine && gl_config.arb_texture_env_dot3 && !COM_CheckParm("-nobump") && gl_bump.value) gl_bumpmappingpossible = true; + if (strstr(gl_extensions, "GL_ARB_vertex_buffer_object")) + { + qglGenBuffersARB = (void *)getglext("glGenBuffersARB"); + qglDeleteBuffersARB = (void *)getglext("glDeleteBuffersARB"); + qglBindBufferARB = (void *)getglext("glBindBufferARB"); + qglBufferDataARB = (void *)getglext("glBufferDataARB"); + qglBufferSubDataARB = (void *)getglext("glBufferSubDataARB"); + } + /* if (!!strstr(gl_extensions, "GL_ARB_fragment_program")) { diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index 5cdf73952..3d61728b1 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -1030,7 +1030,7 @@ void IN_Commands (void) IN_Move =========== */ -void IN_MouseMove (usercmd_t *cmd, int pnum) +void IN_MouseMove (float *movements, int pnum) { extern int mouseusedforgui, mousecursor_x, mousecursor_y; extern int mousemove_x, mousemove_y; @@ -1088,11 +1088,11 @@ void IN_MouseMove (usercmd_t *cmd, int pnum) if(in_xflip.value) mouse_x *= -1; #endif - if (cmd) + if (movements) { // add mouse X/Y movement to cmd if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) )) - cmd->sidemove += m_side.value * mouse_x; + movements[1] += m_side.value * mouse_x; else cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x; @@ -1107,17 +1107,17 @@ void IN_MouseMove (usercmd_t *cmd, int pnum) else { if ((in_strafe.state[pnum] & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; + movements[2] -= m_forward.value * mouse_y; else - cmd->forwardmove -= m_forward.value * mouse_y; + movements[0] -= m_forward.value * mouse_y; } } mouse_x = mouse_y = 0.0; } -void IN_Move (usercmd_t *cmd, int pnum) +void IN_Move (float *movements, int pnum) { - IN_MouseMove(cmd, pnum); + IN_MouseMove(movements, pnum); } #endif diff --git a/engine/gl/gl_vidnull.c b/engine/gl/gl_vidnull.c index 2cb05c7dc..b5d7c2e10 100644 --- a/engine/gl/gl_vidnull.c +++ b/engine/gl/gl_vidnull.c @@ -90,7 +90,7 @@ void IN_Commands(void) { } -void IN_Move(usercmd_t *cmd, int pnum) +void IN_Move(float *movements, int pnum) { } diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 507ed4092..b548bcd93 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -820,6 +820,12 @@ extern BOOL (WINAPI *qSwapBuffers)(HDC); extern void (APIENTRY *qglDrawRangeElements) (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +extern void (APIENTRY *qglGenBuffersARB)(GLsizei n, GLuint* ids); +extern void (APIENTRY *qglDeleteBuffersARB)(GLsizei n, GLuint* ids); +extern void (APIENTRY *qglBindBufferARB)(GLenum target, GLuint id); +extern void (APIENTRY *qglBufferDataARB)(GLenum target, GLsizei size, const void* data, GLenum usage); +extern void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei size, void* data); + /* extern qboolean gl_arb_fragment_program; extern PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB; diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index a8b59d253..90b13f034 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -542,6 +542,40 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei #define GL_MULTISAMPLE_ARB 0x809D +#ifndef GL_ARB_vertex_buffer_object +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA +#endif + diff --git a/engine/gl/shader.h b/engine/gl/shader.h index a7ed4dc6d..cc1925a07 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -209,6 +209,11 @@ typedef struct { } shaderprogparm_t; typedef struct shader_s { + enum { + SSTYLE_CUSTOM, + SSTYLE_FULLBRIGHT, + SSTYLE_LIGHTMAPPED + } style; int numpasses; //careful... 0 means it's not loaded... and not actually a proper shader. struct shader_s *next; char name[MAX_QPATH]; diff --git a/engine/http/ftpclient.c b/engine/http/ftpclient.c index 4e5b87c1f..4cc16c276 100644 --- a/engine/http/ftpclient.c +++ b/engine/http/ftpclient.c @@ -224,9 +224,10 @@ iwboolean FTP_ClientConnThink (FTPclientconn_t *con) //true to kill con int len; if (con->type == ftp_getting) { - if (!cls.downloadmethod || (cls.downloadmethod == DL_FTP && !strcmp(cls.downloadname, con->localfile))) + if (!cls.downloadmethod || (cls.downloadmethod == DL_FTP && !strcmp(cls.downloadlocalname, con->localfile))) { - strcpy(cls.downloadname, con->localfile); + strcpy(cls.downloadlocalname, con->localfile); + strcpy(cls.downloadremotename, con->localfile); cls.downloadmethod = DL_FTP; if (con->transfersize == -1) cls.downloadpercent=50; @@ -640,7 +641,7 @@ void FTP_ClientThink (void) if (con->NotifyFunction) con->NotifyFunction(con->localfile, false); - if (cls.downloadmethod == DL_FTP && !strcmp(cls.downloadname, con->localfile)) + if (cls.downloadmethod == DL_FTP && !strcmp(cls.downloadlocalname, con->localfile)) { //this was us cls.downloadmethod = DL_NONE; } diff --git a/engine/http/httpclient.c b/engine/http/httpclient.c index 5da155b21..d97288f2a 100644 --- a/engine/http/httpclient.c +++ b/engine/http/httpclient.c @@ -369,11 +369,12 @@ void HTTP_CL_Think(void) cls.downloadpercent = 50; else cls.downloadpercent = con->bufferused*100.0f/con->contentlength; - strcpy(cls.downloadname, con->filename); + strcpy(cls.downloadlocalname, con->filename); + strcpy(cls.downloadremotename, con->filename); } else if (cls.downloadmethod == DL_HTTP) { - if (!strcmp(cls.downloadname, con->filename)) + if (!strcmp(cls.downloadlocalname, con->filename)) { if (con->state != HC_GETTING) cls.downloadpercent = 0; diff --git a/engine/http/httpserver.c b/engine/http/httpserver.c index c15aaaa16..4ce2a2eac 100644 --- a/engine/http/httpserver.c +++ b/engine/http/httpserver.c @@ -138,19 +138,19 @@ void HTTP_RunExisting (void) int HTTPmarkup; //version int localerrno; - HTTP_active_connections_t *prev, *cl = HTTP_ServerConnections; + HTTP_active_connections_t **link, *cl; - prev = NULL; - for (prev = NULL; cl; cl=(prev=cl)->next) + link = &HTTP_ServerConnections; + for (link = &HTTP_ServerConnections; *link;) { int ammount, wanted; + cl = *link; + if (cl->close) { - if (prev) - prev->next = cl->next; - else - HTTP_ServerConnections = cl->next; + + *link = cl->next; closesocket(cl->datasock); cl->datasock = INVALID_SOCKET; if (cl->inbuffer) @@ -161,10 +161,11 @@ void HTTP_RunExisting (void) VFS_CLOSE(cl->file); IWebFree(cl); httpconnectioncount--; - cl = prev; - break; + continue; } + link = &(*link)->next; + switch(cl->mode) { case HTTP_WAITINGFORREQUEST: @@ -332,14 +333,26 @@ cont: else if (!stricmp(mode, "GET") || !stricmp(mode, "HEAD") || !stricmp(mode, "POST")) { if (*resource != '/') + { + resource[0] = '/'; resource[1] = 0; //I'm lazy, they need to comply + } Con_Printf("Download request for \"%s\"\n", resource+1); if (!strnicmp(mode, "P", 1)) //when stuff is posted, data is provided. Give an error message if we couldn't do anything with that data. 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); + { + if (!SV_AllowDownload(resource+1)) + cl->file = NULL; + else + cl->file = FS_OpenVFS(resource+1, "rb", FS_GAME); + + if (!cl->file) + { + cl->file = IWebGenerateFile(resource+1, content, contentlen); + } + } + if (!cl->file) { if (HTTPmarkup >= 3) @@ -418,11 +431,11 @@ notimplemented: break; case HTTP_SENDING: - if (cl->outbufferused < 128) + if (cl->outbufferused < 8192) { if (cl->file) { - ExpandOutBuffer(cl, 1500, true); + ExpandOutBuffer(cl, 32768, true); wanted = cl->outbuffersize - cl->outbufferused; ammount = VFS_READ(cl->file, cl->outbuffer+cl->outbufferused, wanted); @@ -483,10 +496,12 @@ notimplemented: qboolean HTTP_ServerPoll(qboolean httpserverwanted, int portnum) //loop while true { - struct sockaddr_in from; + struct sockaddr_qstorage from; int fromlen; int clientsock; int _true = true; + char buf[128]; + netadr_t na; HTTP_active_connections_t *cl; @@ -534,7 +549,8 @@ qboolean HTTP_ServerPoll(qboolean httpserverwanted, int portnum) //loop while tr return false; } - Con_Printf("New connection\n"); + SockadrToNetadr(&from, &na); + Con_Printf("New http connection from %s\n", NET_AdrToString(buf, sizeof(buf), na)); cl = IWebMalloc(sizeof(HTTP_active_connections_t)); diff --git a/engine/http/webgen.c b/engine/http/webgen.c index 1a58d8fc7..dcf8a69ab 100644 --- a/engine/http/webgen.c +++ b/engine/http/webgen.c @@ -25,11 +25,13 @@ void IWeb_MoreGeneratedResize(int newsize) ob = IWeb_GenerationBuffer; IWeb_GenerationBuffer = BZ_Malloc(sizeof(IWeb_GenerationBuffer) + newsize); + memset(IWeb_GenerationBuffer, 0, sizeof(*IWeb_GenerationBuffer)); IWeb_GenerationBuffer->data = (char *)(IWeb_GenerationBuffer+1); if (ob) { memcpy(IWeb_GenerationBuffer->data, ob->data, ob->len); + IWeb_GenerationBuffer->len = ob->len; BZ_Free(ob); } @@ -378,12 +380,17 @@ unsigned long VFSGen_GetLen(vfsfile_t *f) void VFSGen_Close(vfsfile_t *f) { + int fnum; vfsgen_t *g = (vfsgen_t*)f; g->buffer->references--; if (!g->buffer->references) { Z_Free(g->buffer->data); Z_Free(g->buffer); + + for (fnum = 0; fnum < sizeof(IWebFiles) / sizeof(IWebFile_t); fnum++) + if (IWebFiles[fnum].buffer == g->buffer) + IWebFiles[fnum].buffer = NULL; } Z_Free(g); } @@ -401,6 +408,9 @@ vfsfile_t *VFSGen_Create(IWeb_FileGen_t *gen) ret->funcs.GetLen = VFSGen_GetLen; ret->funcs.Close = VFSGen_Close; + ret->buffer = gen; + gen->references++; + return (vfsfile_t*)ret; } diff --git a/engine/qclib/Makefile b/engine/qclib/Makefile index 9010c21ca..bd425050b 100644 --- a/engine/qclib/Makefile +++ b/engine/qclib/Makefile @@ -1,4 +1,6 @@ -QCC_OBJS=qccmain.o qcc_cmdlib.o qcc_pr_comp.o qcc_pr_lex.o comprout.o hash.o qcd_main.o +COMMON_OBJS=comprout.o hash.o qcc_cmdlib.o qcd_main.o +QCC_OBJS=qccmain.o qcc_pr_comp.o qcc_pr_lex.o +VM_OBJS=pr_exec.o pr_edict.o pr_multi.o initlib.o qcdecomp.o GTKGUI_OBJS=qcc_gtk.o qccguistuff.o WIN32GUI_OBJS=qccgui.o qccguistuff.o LIB_OBJS= @@ -11,16 +13,16 @@ all: qcc USEGUI_CFLAGS= # set to -DUSEGUI when compiling the GUI -BASE_CFLAGS=-ggdb -DQCCONLY $(USEGUI_CFLAGS) +BASE_CFLAGS=-ggdb $(USEGUI_CFLAGS) lib: -R_win_nocyg: $(QCC_OBJS) $(WIN32GUI_OBJS) - $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 -s $(QCC_OBJS) $(WIN32GUI_OBJS) -mno-cygwin -mwindows -lcomctl32 -R_nocyg: $(QCC_OBJS) $(WIN32GUI_OBJS) - $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 -s $(QCC_OBJS) $(WIN32GUI_OBJS) -mno-cygwin -lcomctl32 -R_win: $(QCC_OBJS) $(WIN32GUI_OBJS) - $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 -s $(QCC_OBJS) $(WIN32GUI_OBJS) -mwindows -lcomctl32 +R_win_nocyg: $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) + $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 -s $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) -mno-cygwin -mwindows -lcomctl32 +R_nocyg: $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) + $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 -s $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) -mno-cygwin -lcomctl32 +R_win: $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) + $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 -s $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) -mwindows -lcomctl32 win_nocyg: $(MAKE) USEGUI_CFLAGS=-DUSEGUI R_win_nocyg nocyg: @@ -28,8 +30,8 @@ nocyg: win: $(MAKE) USEGUI_CFLAGS=-DUSEGUI R_win -qcc: $(QCC_OBJS) - $(CC) $(BASE_CFLAGS) -o fteqcc.bin -O3 -s $(QCC_OBJS) +qcc: $(QCC_OBJS) $(COMMON_OBJS) + $(CC) $(BASE_CFLAGS) -o fteqcc.bin -O3 -s $(QCC_OBJS) $(COMMON_OBJS) qccmain.o: qccmain.c qcc.h $(DO_CC) @@ -58,10 +60,23 @@ qccguistuff.o: qccguistuff.c qcc.h qcc_gtk.o: qcc_gtk.c qcc.h $(DO_CC) `pkg-config --cflags gtk+-2.0` -R_gtkgui: $(QCC_OBJS) $(GTKGUI_OBJS) - $(CC) $(BASE_CFLAGS) -DQCCONLY -DUSEGUI -o fteqccgui.bin -O3 $(GTKGUI_OBJS) $(QCC_OBJS) `pkg-config --libs gtk+-2.0` +R_gtkgui: $(QCC_OBJS) $(COMMON_OBJS) $(GTKGUI_OBJS) + $(CC) $(BASE_CFLAGS) $(USEGUI_CFLAGS) -o fteqccgui.bin -O3 $(GTKGUI_OBJS) $(QCC_OBJS) $(COMMON_OBJS) `pkg-config --libs gtk+-2.0` gtkgui: - $(MAKE) USEGUI_CFLAGS=-DUSEGUI R_gtkgui + $(MAKE) USEGUI_CFLAGS="-DUSEGUI -DQCCONLY" R_gtkgui clean: - $(RM) fteqcc.bin fteqcc.exe $(QCC_OBJS) $(GTKGUI_OBJS) $(WIN32GUI_OBJS) + $(RM) fteqcc.bin fteqcc.exe $(QCC_OBJS) $(COMMON_OBJS) $(VM_OBJS) $(GTKGUI_OBJS) $(WIN32GUI_OBJS) + +qcvm.so: $(QCC_OBJS) $(VM_OBJS) $(COMMON_OBJS) + $(CC) $(BASE_CFLAGS) -o $@ -O3 -s $(QCC_OBJS) $(VM_OBJS) $(COMMON_OBJS) -shared + + +test.o: test.c + $(DO_CC) + +testapp.bin: qcvm.so test.o + $(CC) $(BASE_CFLAGS) -o testapp.bin -O3 -s qcvm.so test.o + +regressiontest: testapp.bin + ./testapp.bin regression.dat -srcfile regression.src \ No newline at end of file diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index d48f93173..b7d00f60a 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -2452,6 +2452,14 @@ retry: return false; } + if (pr_progs->version == PROG_EXTENDEDVERSION && pr_progs->blockscompressed && !QC_decodeMethodSupported(2)) + { + printf ("%s uses compression\n", filename); + PRHunkFree(progfuncs, hmark); + pr_progs=NULL; + return false; + } + fnc = pr_functions = (dfunction_t *)((qbyte *)pr_progs + pr_progs->ofs_functions); pr_strings = ((char *)pr_progs + pr_progs->ofs_strings); current_progstate->globaldefs = *(void**)&gd16 = (void *)((qbyte *)pr_progs + pr_progs->ofs_globaldefs); diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index 0668d0164..54381ab70 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -206,10 +206,10 @@ void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...) Q_vsnprintf (string,sizeof(string)-1, error,argptr); va_end (argptr); - { - void SV_EndRedirect (void); - SV_EndRedirect(); - } +// { +// void SV_EndRedirect (void); +// SV_EndRedirect(); +// } // PR_PrintStatement (pr_statements + pr_xstatement); PR_StackTrace (progfuncs); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 4b2e05012..a07a568ed 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -7374,7 +7374,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname) QCC_def_t *fasttrackpossible; if (flag_fasttrackarrays) - fasttrackpossible = QCC_PR_GetDef(NULL, "__ext__fasttrackarrays", NULL, true, 1, false); + fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 1, false); else fasttrackpossible = NULL; diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index d74fee144..ebed86b1e 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -267,7 +267,7 @@ int ParsePrecompilerIf(void) { c = QCC_PR_CheckCompConstDefined(pr_token); if (!c) - eval = false; + eval = atoi(pr_token); else eval = atoi(c->value); } @@ -806,6 +806,11 @@ pbool QCC_PR_Precompiler(void) QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n"); strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1); } + else if (!strncmp(qcc_token, "compress", 8)) + { + extern pbool compressoutput; + compressoutput = atoi(msg); + } else if (!strncmp(qcc_token, "forcecrc", 8)) { ForcedCRC = atoi(msg); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 1c9d6bead..49aa54874 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -1881,6 +1881,8 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) switch (crc) { + case 12923: //#pragma sourcefile usage + break; case 54730: printf("Recognised progs as QuakeWorld\n"); break; @@ -1902,9 +1904,13 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) printf("Recognised progs as Hexen2 (demo)\n"); break; - case 32199: + case 22390: //EXT_CSQC_1 printf("Recognised progs as a CSQC module\n"); break; + case 17105: + case 32199: //outdated ext_csqc + printf("Recognised progs as outdated CSQC module\n"); + break; case 52195: printf("Recognised progs as outdated CSQC module\n"); break; diff --git a/engine/qclib/qcd.h b/engine/qclib/qcd.h index 71fdbe42c..fd7817eb4 100644 --- a/engine/qclib/qcd.h +++ b/engine/qclib/qcd.h @@ -1,3 +1,4 @@ +pbool QC_decodeMethodSupported(int method); char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char *info, char *buffer); int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle); diff --git a/engine/qclib/qcd_main.c b/engine/qclib/qcd_main.c index a7ce16f43..2493c423a 100644 --- a/engine/qclib/qcd_main.c +++ b/engine/qclib/qcd_main.c @@ -1,17 +1,34 @@ #include "progsint.h" //#include "qcc.h" +//#define AVAIL_ZLIB + #ifdef AVAIL_ZLIB #ifdef _WIN32 #define ZEXPORT VARGS #include "../libs/zlib.h" -//# pragma comment (lib, "zip/zlib.lib") +# pragma comment (lib, "../libs/zlib.lib") #else #include #endif #endif +pbool QC_decodeMethodSupported(int method) +{ + if (method == 0) + return true; + if (method == 1) + return true; + if (method == 2) + { +#ifdef AVAIL_ZLIB + return false; +#endif + } + return false; +} + char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char *info, char *buffer) { int i; @@ -20,15 +37,15 @@ char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char * if (complen != len) Sys_Error("lengths do not match"); memcpy(buffer, info, len); } - else if (method == 1) //encryption + else if (method == 1) //xor encryption { if (complen != len) Sys_Error("lengths do not match"); for (i = 0; i < len; i++) buffer[i] = info[i] ^ 0xA5; } -#ifdef AVAIL_ZLIB else if (method == 2) //compression (ZLIB) { +#ifdef AVAIL_ZLIB z_stream strm = { info, complen, @@ -54,8 +71,8 @@ char *QC_decode(progfuncs_t *progfuncs, int complen, int len, int method, char * if (Z_STREAM_END != inflate(&strm, Z_FINISH)) //decompress it in one go. Sys_Error("Failed block decompression\n"); inflateEnd(&strm); - } #endif + } //add your decryption/decompression routine here. else Sys_Error("Bad file encryption routine\n"); @@ -76,16 +93,16 @@ int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle) SafeWrite(handle, in, len); return len; } - else if (method == 1) //encryption + else if (method == 1) //xor encryption { for (i = 0; i < len; i++) in[i] = in[i] ^ 0xA5; SafeWrite(handle, in, len); return len; } -#ifdef AVAIL_ZLIB else if (method == 2) //compression (ZLIB) { +#ifdef AVAIL_ZLIB char out[8192]; z_stream strm = { @@ -122,8 +139,10 @@ int QC_encode(progfuncs_t *progfuncs, int len, int method, char *in, int handle) i+=sizeof(out) - strm.avail_out; deflateEnd(&strm); return i; - } #endif + Sys_Error("ZLIB compression not supported in this build"); + return 0; + } //add your compression/decryption routine here. else { diff --git a/engine/qclib/test.c b/engine/qclib/test.c index b93ecf1cc..eec05fbb8 100644 --- a/engine/qclib/test.c +++ b/engine/qclib/test.c @@ -13,9 +13,6 @@ #include #include -//the only function that is required externally. :/ -void SV_EndRedirect (void) {} - @@ -97,7 +94,7 @@ pbool Sys_WriteFile (char *fname, void *data, int len) return 1; } -void runtest(void) +void runtest(char *progsname) { progfuncs_t *pf; func_t func; @@ -115,9 +112,9 @@ void runtest(void) pf = InitProgs(&ext); pf->Configure(pf, 1024*1024, 1); //memory quantity of 1mb. Maximum progs loadable into the instance of 1 //If you support multiple progs types, you should tell the VM the offsets here, via RegisterFieldVar - pn = pf->LoadProgs(pf, "testprogs.dat", 0, builtins, sizeof(builtins)/sizeof(builtins[0])); //load the progs, don't care about the crc, and use those builtins. + pn = pf->LoadProgs(pf, progsname, 0, builtins, sizeof(builtins)/sizeof(builtins[0])); //load the progs, don't care about the crc, and use those builtins. if (pn < 0) - printf("Failed to load progs\n"); + printf("test: Failed to load progs \"%s\"\n", progsname); else { //allocate qc-acessable strings here for 64bit cpus. (allocate via AddString, tempstringbase is a holding area not used by the actual vm) @@ -139,25 +136,28 @@ void runtest(void) //Run a compiler and nothing else. //Note that this could be done with an autocompile of PR_COMPILEALWAYS. -void compile(void) +void compile(int argc, char **argv) { progfuncs_t *pf; progparms_t ext; - char *testsrcfile = //newstyle progs.src must start with a #. - //it's newstyle to avoid using multiple source files. - "#pragma PROGS_DAT \"testprogs.dat\"\r\n" - "//INTERMEDIATE FILE - EDIT TEST.C INSTEAD\r\n" - "\r\n" - "void(...) print = #1;\r\n" - "void() main =\r\n" - "{\r\n" - " print(\"hello world\\n\");\r\n" - "};\r\n"; + if (0) + { + char *testsrcfile = //newstyle progs.src must start with a #. + //it's newstyle to avoid using multiple source files. + "#pragma PROGS_DAT \"testprogs.dat\"\r\n" + "//INTERMEDIATE FILE - EDIT TEST.C INSTEAD\r\n" + "\r\n" + "void(...) print = #1;\r\n" + "void() main =\r\n" + "{\r\n" + " print(\"hello world\\n\");\r\n" + "};\r\n"; - //so that the file exists. We could insert it via the callbacks instead - Sys_WriteFile("progs.src", testsrcfile, strlen(testsrcfile)); + //so that the file exists. We could insert it via the callbacks instead + Sys_WriteFile("progs.src", testsrcfile, strlen(testsrcfile)); + } memset(&ext, 0, sizeof(ext)); ext.progsversion = PROGSTRUCT_VERSION; @@ -168,18 +168,29 @@ void compile(void) ext.printf = printf; pf = InitProgs(&ext); - if (pf->StartCompile(pf, 0, NULL)) + if (pf->StartCompile) { - while(pf->ContinueCompile(pf) == 1) - ; + if (pf->StartCompile(pf, argc, argv)) + { + while(pf->ContinueCompile(pf) == 1) + ; + } } + else + printf("no compiler in this qcvm build\n"); CloseProgs(pf); } -int main(void) +int main(int argc, char **argv) { - compile(); - runtest(); + if (argc < 2) + { + printf("Invalid arguments!\nPlease run as, for example:\n%s testprogs.dat --srcfile progs.src\nThe first argument is the name of the progs.dat to run, the remaining arguments are the qcc args to use", argv[0]); + return 0; + } + + compile(argc-2, argv+2); + runtest(argv[1]); return 0; } diff --git a/engine/server/server.h b/engine/server/server.h index 6ba71db5a..da6b902a5 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -469,6 +469,7 @@ typedef struct client_s //===== NETWORK ============ int chokecount; + qboolean waschoked; int delta_sequence; // -1 = no compression int last_sequence; netchan_t netchan; diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index fc702e2c3..a3f19c123 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -568,7 +568,7 @@ void SV_Map_f (void) { cvar_t *gametype; - gametype = Cvar_Get("mapname", "0", CVAR_LATCH|CVAR_SERVERINFO, "Q3 compatability"); + gametype = Cvar_Get("mapname", "", CVAR_LATCH|CVAR_SERVERINFO, "Q3 compatability"); gametype->flags |= CVAR_SERVERINFO; Cvar_ForceSet(gametype, level); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 0994a43ea..d8b7a0a5f 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -37,6 +37,7 @@ extern cvar_t sv_cheats; extern cvar_t sv_bigcoords; extern cvar_t sv_gamespeed; extern cvar_t sv_csqcdebug; +extern cvar_t sv_csqc_progname; extern qboolean sv_allow_cheats; /* @@ -830,18 +831,29 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us //do we allow csprogs? #ifdef PEXT_CSQC - file = COM_LoadTempFile("csprogs.dat"); + if (*sv_csqc_progname.string) + file = COM_LoadTempFile(sv_csqc_progname.string); + else + file = NULL; if (file) { char text[64]; sv.csqcchecksum = Com_BlockChecksum(file, com_filesize); sprintf(text, "0x%x", sv.csqcchecksum); Info_SetValueForStarKey(svs.info, "*csprogs", text, MAX_SERVERINFO_STRING); + sprintf(text, "0x%x", com_filesize); + Info_SetValueForStarKey(svs.info, "*csprogssize", text, MAX_SERVERINFO_STRING); + if (strcmp(sv_csqc_progname.string, "csprogs.dat")) + Info_SetValueForStarKey(svs.info, "*csprogsname", sv_csqc_progname.string, MAX_SERVERINFO_STRING); + else + Info_SetValueForStarKey(svs.info, "*csprogsname", "", MAX_SERVERINFO_STRING); } else { sv.csqcchecksum = 0; Info_SetValueForStarKey(svs.info, "*csprogs", "", MAX_SERVERINFO_STRING); + Info_SetValueForStarKey(svs.info, "*csprogssize", "", MAX_SERVERINFO_STRING); + Info_SetValueForStarKey(svs.info, "*csprogsname", "", MAX_SERVERINFO_STRING); } sv.csqcdebug = sv_csqcdebug.value; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 4188570eb..238a0c4ca 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -151,6 +151,7 @@ cvar_t sv_masterport = SCVAR("sv_masterport", "0"); cvar_t sv_voicechat = SCVAR("sv_voicechat", "0"); //still development. cvar_t sv_gamespeed = SCVAR("sv_gamespeed", "1"); cvar_t sv_csqcdebug = SCVAR("sv_csqcdebug", "0"); +cvar_t sv_csqc_progname = SCVAR("sv_csqc_progname", "csprogs.dat"); #ifdef TCPCONNECT cvar_t sv_port_tcp = SCVARC("sv_port_tcp", "", SV_Tcpport_Callback); #ifdef IPPROTO_IPV6 @@ -595,25 +596,27 @@ void PIN_LoadMessages(void) char message[1024]; int i; - char *file; + char *file, *end; char *lstart; + int len; dopinnedload = false; while(pinned) PIN_DeleteOldestMessage(); - file = COM_LoadMallocFile("pinned.txt"); + len = FS_LoadFile("pinned.txt", (void**)&file); if (!file) return; + end = file+len; lstart = file; for(;;) { - while (*lstart <= ' ' && *lstart) + while (lstart 0) { diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index c46701c1d..606e1753d 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -2153,8 +2153,10 @@ void SV_SendClientMessages (void) if (!sv.paused && !Netchan_CanPacket (&c->netchan, SV_RateForClient(c))) { c->chokecount++; + c->waschoked = true; continue; // bandwidth choke } + c->waschoked = false; if (c->state == cs_spawned) SV_SendClientDatagram (c); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 70bcc157c..a0d4accd9 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1778,6 +1778,9 @@ void SV_NextChunkedDownload(unsigned int chunknum, int ezpercent, int ezfilenum) if (!ezfilenum) return; + if (host_client->waschoked) + return; //don't let chunked downloads flood out the standard packets. + if (!Netchan_CanPacket(&host_client->netchan, SV_RateForClient(host_client))) return; } @@ -3729,7 +3732,7 @@ void Cmd_FPSList_f(void) client_t *cl; int c; int f; - double minf = DBL_MIN, maxf = DBL_MAX, this; + double minf = 1000, maxf = 0, this; double ftime; int frames; @@ -3749,11 +3752,14 @@ void Cmd_FPSList_f(void) { if (cl->frameunion.frames[f].move_msecs >= 0) { - this = 1000.0f/cl->frameunion.frames[f].move_msecs; + if (!cl->frameunion.frames[f].move_msecs) + this = 1001; + else + this = 1000.0f/cl->frameunion.frames[f].move_msecs; ftime += this; - if (minf < this) + if (minf > this) minf = this; - if (maxf > this) + if (maxf < this) maxf = this; frames++; } @@ -5234,6 +5240,125 @@ void SV_PostRunCmd(void) } } +void SV_ReadPrydonCursor(void) +{ + float f; + int entnum; + eval_t *cursor_screen, *cursor_start, *cursor_impact, *cursor_entitynumber; + + if (svprogfuncs) + { + cursor_screen = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_screen", NULL); + cursor_start = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_start", NULL); + cursor_impact = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_impact", NULL); + cursor_entitynumber = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_entitynumber", NULL); + } + else + { + cursor_screen = NULL; + cursor_start = NULL; + cursor_impact = NULL; + cursor_entitynumber = NULL; + } + + f = MSG_ReadShort() * (1.0f / 32767.0f); + if (cursor_screen) cursor_screen->_vector[0] = f; + f = MSG_ReadShort() * (1.0f / 32767.0f); + if (cursor_screen) cursor_screen->_vector[1] = f; + + f = MSG_ReadFloat(); + if (cursor_start) cursor_start->_vector[0] = f; + f = MSG_ReadFloat(); + if (cursor_start) cursor_start->_vector[1] = f; + f = MSG_ReadFloat(); + if (cursor_start) cursor_start->_vector[2] = f; + + f = MSG_ReadFloat(); + if (cursor_impact) cursor_impact->_vector[0] = f; + f = MSG_ReadFloat(); + if (cursor_impact) cursor_impact->_vector[1] = f; + f = MSG_ReadFloat(); + if (cursor_impact) cursor_impact->_vector[2] = f; + + entnum = (unsigned short)MSG_ReadShort(); + if (entnum >= sv.max_edicts) + { + Con_DPrintf("SV_ReadPrydonCursor: client send bad cursor_entitynumber\n"); + entnum = 0; + } + // as requested by FrikaC, cursor_trace_ent is reset to world if the + // entity is free at time of receipt + if (!svprogfuncs || EDICT_NUM(svprogfuncs, entnum)->isfree) + entnum = 0; + if (msg_badread) Con_Printf("SV_ReadPrydonCursor: badread at %s:%i\n", __FILE__, __LINE__); + + if (cursor_entitynumber) cursor_entitynumber->edict = entnum; +} + +void SV_ReadQCRequest(void) +{ + int e; + char args[9]; + char *rname; + func_t f; + int i; + globalvars_t *pr_globals; + + if (!svprogfuncs) + { + msg_badread = true; + return; + } + + pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + + for (i = 0; ; i++) + { + if (i >= sizeof(args)) + if (MSG_ReadByte() != ev_void) + { + msg_badread = true; + return; + } + switch(MSG_ReadByte()) + { + case ev_void: + i = 6; + break; + case ev_float: + args[i] = 'f'; + G_FLOAT(OFS_PARM0+i*3) = MSG_ReadFloat(); + break; + case ev_vector: + args[i] = 'v'; + G_FLOAT(OFS_PARM0+i*3+0) = MSG_ReadFloat(); + G_FLOAT(OFS_PARM0+i*3+1) = MSG_ReadFloat(); + G_FLOAT(OFS_PARM0+i*3+2) = MSG_ReadFloat(); + break; + case ev_integer: + args[i] = 'i'; + G_INT(OFS_PARM0+i*3) = MSG_ReadLong(); + break; + case ev_string: + args[i] = 's'; + G_INT(OFS_PARM0+i*3) = PR_TempString(svprogfuncs, MSG_ReadString()); + break; + case ev_entity: + args[i] = 's'; + e = MSG_ReadShort(); + if (e < 0 || e >= sv.num_edicts) + e = 0; + G_INT(OFS_PARM0+i*3) = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, e)); + break; + } + } + + rname = MSG_ReadString(); + f = PR_FindFunc(svprogfuncs, va("Cmd_%s_%s", rname, args), PR_ANY); + if (f) + PR_ExecuteProgram(svprogfuncs, f); +} + /* =================== SV_ExecuteClientMessage @@ -5515,6 +5640,12 @@ haveannothergo: sv_player = cl->edict; break; + case clc_prydoncursor: + SV_ReadPrydonCursor(); + break; + case clc_qcrequest: + SV_ReadQCRequest(); + break; case clc_stringcmd: s = MSG_ReadString (); @@ -5762,47 +5893,7 @@ void SVNQ_ReadClientMove (usercmd_t *move) if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7) { - float f; - int entnum; - eval_t *cursor_screen, *cursor_start, *cursor_impact, *cursor_entitynumber; - - cursor_screen = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_screen", NULL); - cursor_start = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_start", NULL); - cursor_impact = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_impact", NULL); - cursor_entitynumber = svprogfuncs->GetEdictFieldValue(svprogfuncs, host_client->edict, "cursor_entitynumber", NULL); - - f = MSG_ReadShort() * (1.0f / 32767.0f); - if (cursor_screen) cursor_screen->_vector[0] = f; - f = MSG_ReadShort() * (1.0f / 32767.0f); - if (cursor_screen) cursor_screen->_vector[1] = f; - - f = MSG_ReadFloat(); - if (cursor_start) cursor_start->_vector[0] = f; - f = MSG_ReadFloat(); - if (cursor_start) cursor_start->_vector[1] = f; - f = MSG_ReadFloat(); - if (cursor_start) cursor_start->_vector[2] = f; - - f = MSG_ReadFloat(); - if (cursor_impact) cursor_impact->_vector[0] = f; - f = MSG_ReadFloat(); - if (cursor_impact) cursor_impact->_vector[1] = f; - f = MSG_ReadFloat(); - if (cursor_impact) cursor_impact->_vector[2] = f; - - entnum = (unsigned short)MSG_ReadShort(); - if (entnum >= sv.max_edicts) - { - Con_DPrintf("SV_ReadClientMessage: client send bad cursor_entitynumber\n"); - entnum = 0; - } - // as requested by FrikaC, cursor_trace_ent is reset to world if the - // entity is free at time of receipt - if (EDICT_NUM(svprogfuncs, entnum)->isfree) - entnum = 0; - if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); - - if (cursor_entitynumber) cursor_entitynumber->edict = entnum; + SV_ReadPrydonCursor(); } if (SV_RunFullQCMovement(host_client, move)) diff --git a/engine/sw/vid_fodquake.c b/engine/sw/vid_fodquake.c index 5f0300c37..714813914 100644 --- a/engine/sw/vid_fodquake.c +++ b/engine/sw/vid_fodquake.c @@ -298,7 +298,7 @@ void IN_Move(usercmd_t *cmd, int pnum) #endif if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) )) - cmd->sidemove += m_side.value * mouse_x; + movements[1] += m_side.value * mouse_x; else cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x; if (in_mlook.state[pnum] & 1) @@ -314,9 +314,9 @@ void IN_Move(usercmd_t *cmd, int pnum) if (cmd) { if ((in_strafe.state[pnum] & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; + movements[2] -= m_forward.value * mouse_y; else - cmd->forwardmove -= m_forward.value * mouse_y; + movements[0] -= m_forward.value * mouse_y; } } mouse_x = mouse_y = 0.0; diff --git a/engine/sw/vid_null.c b/engine/sw/vid_null.c index 9cb1c438b..0e31343ed 100644 --- a/engine/sw/vid_null.c +++ b/engine/sw/vid_null.c @@ -81,7 +81,7 @@ void IN_Commands(void) { } -void IN_Move(usercmd_t *cmd, int pnum) +void IN_Move(float *movements, int pnum) { } diff --git a/engine/sw/vid_x.c b/engine/sw/vid_x.c index 1fa2a643c..4a3a8cc33 100644 --- a/engine/sw/vid_x.c +++ b/engine/sw/vid_x.c @@ -1360,7 +1360,7 @@ void IN_Commands (void) } extern int mousecursor_x, mousecursor_y; -void IN_Move (usercmd_t *cmd, int pnum) +void IN_Move (float *movements, int pnum) { float mx, my; float mouse_deltadist; @@ -1414,7 +1414,7 @@ void IN_Move (usercmd_t *cmd, int pnum) #endif if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) )) - cmd->sidemove += m_side.value * mouse_x; + movements[1] += m_side.value * mouse_x; else cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x; if (in_mlook.state[pnum] & 1) @@ -1430,9 +1430,9 @@ void IN_Move (usercmd_t *cmd, int pnum) if (cmd) { if ((in_strafe.state[pnum] & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; + movements[2] -= m_forward.value * mouse_y; else - cmd->forwardmove -= m_forward.value * mouse_y; + movements[0] -= m_forward.value * mouse_y; } } mouse_x = mouse_y = 0.0;