diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 3149aa904..79bce8bbd 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -45,8 +45,6 @@ enum TM_MODHINTS, //using the mod's //at hints TM_STATS //parsing mvd stats and making our own choices } autotrackmode; -int autotrack_hint; //the latest hint from the mod, might be negative for invalid. -int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to. char *autotrack_statsrule; static void QDECL CL_AutoTrackChanged(cvar_t *v, char *oldval) { @@ -148,10 +146,13 @@ static int CL_FindHighTrack(int seat, char *rule) //set a default to the currently tracked player, to reuse the current player we're tracking if someone lower equalises. j = cl.playerview[seat].cam_spec_track; - if (j >= 0) + if (j >= 0 && cl.players[j].name[0] && !cl.players[j].spectator) max = CL_TrackScore(&cl.players[j], rule); else + { max = -9999; + j = -1; + } for (i = 0; i < cl.allocated_client_slots; i++) { @@ -183,15 +184,15 @@ static int CL_AutoTrack_Choose(int seat) { int best = -1; if (autotrackmode == TM_KILLER) - best = autotrack_killer; - if (autotrackmode == TM_MODHINTS && seat == 0 && autotrack_hint >= 0) - best = autotrack_hint; + best = cl.autotrack_killer; + if (autotrackmode == TM_MODHINTS && seat == 0 && cl.autotrack_hint >= 0) + best = cl.autotrack_hint; if (autotrackmode == TM_STATS && cls.demoplayback == DPB_MVD) best = CL_FindHighTrack(seat, autotrack_statsrule); if (autotrackmode == TM_HIGHTRACK || best == -1) best = CL_FindHighTrack(seat, "f"); //TM_USER should generally avoid autotracking - autotrack_killer = best; //killer should continue to track whatever is currently tracked until its changed by frag message parsing + cl.autotrack_killer = best; //killer should continue to track whatever is currently tracked until its changed by frag message parsing return best; } @@ -402,8 +403,13 @@ static void Cam_CheckHighTarget(playerview_t *pv) j = CL_AutoTrack_Choose(pv - cl.playerview); if (j >= 0) { - if (!pv->cam_locked || pv->cam_spec_track != j) + if (pv->cam_spec_track != j || !pv->cam_locked) { + if (cl.teamplay) + Stats_Message("Now tracking:\n%s\n%s", cl.players[j].name, cl.players[j].team); + else + Stats_Message("Now tracking:\n%s", cl.players[j].name); + pv->cam_auto++; Cam_Lock(pv, j); //un-lock any higher seats watching our new target. this keeps things ordered. for (spv = pv+1; spv >= cl.playerview && spv < &cl.playerview[cl.splitclients]; spv++) @@ -577,12 +583,12 @@ void Cam_SetAutoTrack(int userid) { //this is a hint from the server about who to track int slot; playerview_t *pv = &cl.playerview[0]; - autotrack_hint = -1; + cl.autotrack_hint = -1; for (slot = 0; slot < cl.allocated_client_slots; slot++) { if (cl.players[slot].userid == userid) { - autotrack_hint = slot; + cl.autotrack_hint = slot; return; } } @@ -719,6 +725,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd) { Cam_Unlock(pv); VectorCopy(pv->viewangles, cmd->angles); + autotrackmode = TM_USER; return; } } @@ -728,7 +735,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd) else { pv->cam_oldbuttons &= ~BUTTON_ATTACK; - if (!pv->cam_auto) + if (!pv->cam_auto && autotrackmode == TM_USER) { if ((cmd->buttons & BUTTON_JUMP) && !(pv->cam_oldbuttons & BUTTON_JUMP)) Cam_TrackCrosshairedPlayer(pv); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 673709622..9484d3d22 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -322,6 +322,7 @@ void CL_MakeActive(char *gamename) Con_DPrintf("%i additional FS searches\n", fs_finds); fs_finds = 0; } + cl.matchgametimestart = 0; cls.state = ca_active; S_Purge(true); CL_UpdateWindowTitle(); @@ -1408,6 +1409,8 @@ void CL_ClearState (void) cl.gametime = 0; cl.gametimemark = 0; cl.splitclients = 1; + cl.autotrack_hint = -1; + cl.autotrack_killer = -1; } /* @@ -1932,7 +1935,7 @@ void CL_CheckServerInfo(void) else cl.matchstate = MATCH_DONTKNOW; if (oldstate != cl.matchstate) - cl.matchgametime = 0; + cl.matchgametimestart = cl.gametime; CL_CheckServerPacks(); @@ -4688,10 +4691,6 @@ double Host_Frame (double time) spare = 0; host_frametime = (realtime - oldrealtime)*cl.gamespeed; - if (!cl.paused) - { - cl.matchgametime += host_frametime; - } oldrealtime = realtime; CL_ProgressDemoTime(); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index ee6f3f172..f80b4bc68 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -5384,13 +5384,31 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags) *(msg - 2) = 0; // it's assumed that msg has 2 chars before it due to strstr }*/ + if (*msg == '\r') + { + name = msg; + msg = strstr(msg, ": "); + if (msg) + { + name++; + *msg = 0; + msg+=2; + plrflags &= ~TPM_TEAM|TPM_OBSERVEDTEAM; + } + else + { + msg = name; + name = NULL; + } + } + if (msg[0] == '/' && msg[1] == 'm' && msg[2] == 'e' && msg[3] == ' ') { msg += 4; memessage = true; // special /me formatting } - if (plr) // use special formatting with a real chat message + if (plr && !name) // use special formatting with a real chat message name = plr->name; // use player's name if (cl_standardchat.ival) @@ -5463,6 +5481,8 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags) else Q_strncatz(fullchatmessage, " ", sizeof(fullchatmessage)); } + else + Q_strncatz(fullchatmessage, "\1", sizeof(fullchatmessage)); // print message if (cl_parsewhitetext.value && (cl_parsewhitetext.value == 1 || (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)))) @@ -6668,8 +6688,9 @@ void CLNQ_ParseProQuakeMessage (char *s) break; case pqc_match_time: - cl.matchgametime = MSG_ReadBytePQ(&s)*60; - cl.matchgametime += MSG_ReadBytePQ(&s); + cl.matchgametimestart = MSG_ReadBytePQ(&s)*60; + cl.matchgametimestart += MSG_ReadBytePQ(&s); + cl.matchgametimestart = cl.gametime - cl.matchgametimestart; break; case pqc_match_reset: diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 9dab7866f..51c7f6854 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -239,6 +239,7 @@ cvar_t show_speed = SCVAR("show_speed", "0"); cvar_t show_speed_x = SCVAR("show_speed_x", "-1"); cvar_t show_speed_y = SCVAR("show_speed_y", "-9"); cvar_t scr_loadingrefresh = SCVAR("scr_loadingrefresh", "0"); +cvar_t scr_showobituaries = CVAR("scr_showobituaries", "0"); void *scr_curcursor; @@ -263,6 +264,7 @@ void CLSCR_Init(void) Cvar_Register(&show_speed_x, cl_screengroup); Cvar_Register(&show_speed_y, cl_screengroup); Cvar_Register(&scr_neticontimeout, cl_screengroup); + Cvar_Register(&scr_showobituaries, cl_screengroup); memset(&key_customcursor, 0, sizeof(key_customcursor)); @@ -425,6 +427,8 @@ void VARGS Stats_Message(char *msg, ...) va_list argptr; char str[2048]; cprint_t *p = &scr_centerprint[0]; + if (!scr_showobituaries.ival) + return; if (p->time_off >= 0) return; @@ -1433,23 +1437,18 @@ void SCR_DrawGameClock(void) else timelimit = 0; - if (cl.playerview[0].statsf[STAT_MATCHSTARTTIME]) + if (cl.matchstate == MATCH_STANDBY) + showtime = cl.servertime; + else if (cl.playerview[0].statsf[STAT_MATCHSTARTTIME]) showtime = timelimit - (cl.servertime - cl.playerview[0].statsf[STAT_MATCHSTARTTIME]); - else - showtime = timelimit - cl.matchgametime; + else + showtime = timelimit - (cl.servertime - cl.matchgametimestart); if (showtime < 0) - { showtime *= -1; - minutes = showtime/60; - seconds = (int)showtime - (minutes*60); - } - else - { - minutes = showtime/60; - seconds = (int)showtime - (minutes*60); - } + minutes = showtime/60; + seconds = (int)showtime - (minutes*60); sprintf(str, " %02i:%02i", minutes, seconds); SCR_StringXY(str, show_gameclock_x.value, show_gameclock_y.value); diff --git a/engine/client/client.h b/engine/client/client.h index 24ff6b27d..3aa96d9b2 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -632,6 +632,7 @@ struct playerview_s int cam_oldbuttons; // vec3_t cam_viewangles; // double cam_lastviewtime; // + float cam_reautotrack; // timer to throttle tracking changes. int cam_spec_track; // player# of who we are tracking enum { @@ -682,6 +683,8 @@ typedef struct int movesequence; // client->server frames int spectator; + int autotrack_hint; //the latest hint from the mod, might be negative for invalid. + int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to. double last_ping_request; // while showing scoreboard double last_servermessage; @@ -818,7 +821,7 @@ typedef struct qboolean sendprespawn; int contentstage; - double matchgametime; + double matchgametimestart; enum { MATCH_DONTKNOW, MATCH_COUNTDOWN, diff --git a/engine/client/fragstats.c b/engine/client/fragstats.c index cacdf1f7e..506f82459 100644 --- a/engine/client/fragstats.c +++ b/engine/client/fragstats.c @@ -111,6 +111,11 @@ qboolean Stats_HaveKills(void) void VARGS Stats_Message(char *msg, ...); +qboolean Stats_TrackerImageLoaded(char *in) +{ + qboolean error; + return Font_TrackerValid(unicode_decode(&error, in, &in, true)); +} static char *Stats_GenTrackerImageString(char *in) { //images are of the form "foo \sg\ bar \q\" //which should eg be remapped to: "foo ^Ue200 bar foo ^Ue201" @@ -237,7 +242,7 @@ void Stats_FragMessage(int p1, int wid, int p2, qboolean teamkill) } } - Q_snprintfz(message, sizeof(message), "%s%s ^7%s %s%s\n", p1c, p1n, w->image?w->image:w->abrev, p2c, p2n); + Q_snprintfz(message, sizeof(message), "%s%s ^7%s %s%s\n", p1c, p1n, Stats_TrackerImageLoaded(w->image)?w->image:w->abrev, p2c, p2n); tracker = Con_FindConsole("tracker"); if (!tracker) diff --git a/engine/client/screen.h b/engine/client/screen.h index 0b352b3ae..3ae498215 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -99,6 +99,7 @@ void SCR_SetLoadingFile(char *str); void Font_Init(void); void Font_Shutdown(void); int Font_RegisterTrackerImage(const char *image); //returns a unicode char value that can be used to embed the char within a line of text. +qboolean Font_TrackerValid(unsigned int imid); struct font_s *Font_LoadFont(float height, const char *fontfilename); void Font_Free(struct font_s *f); void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py); diff --git a/engine/client/view.c b/engine/client/view.c index 7cae3beba..9437e5cca 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1342,7 +1342,7 @@ void V_CalcRefdef (playerview_t *pv) viewheight += pv->crouch; - if (pv->stats[STAT_HEALTH] < 0 && pv->cam_spec_track >= 0 && v_deathtilt.value) // PF_GIB will also set PF_DEAD + if (pv->stats[STAT_HEALTH] < 0 && (!cl.spectator || pv->cam_locked) && v_deathtilt.value) // PF_GIB will also set PF_DEAD { if (!cl.spectator || cl_chasecam.ival) r_refdef.viewangles[ROLL] = 80*v_deathtilt.value; // dead view angle diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 50eb67fea..bae3b0ff9 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -2207,9 +2207,13 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr) *plr = player; } } - } - if (!flags) // search for fake player +// if (i == cl.allocated_client_slots) +// return flags; + + } +/* + if (!flags) // search for fake/non player { if ((name = strstr(s, ": "))) // use name as temp { @@ -2220,6 +2224,7 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr) flags |= TPM_TEAM; } } +*/ return flags; } diff --git a/engine/common/cmd.c b/engine/common/cmd.c index b99d422cf..79cdb3070 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -2967,9 +2967,8 @@ void Cmd_WriteConfig_f(void) #else snprintf(fname, sizeof(fname), "fte.cfg"); #endif - FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname)); - FS_CreatePath(fname, FS_GAMEONLY); - f = FS_OpenVFS(fname, "wbp", FS_GAMEONLY); + + f = FS_OpenWithFriends(fname, sysname, sizeof(sysname), 3, "quake.rc", "*.cfg", "configs/*.cfg"); all = cfg_save_all.ival; } diff --git a/engine/common/common.c b/engine/common/common.c index 6f841fdf0..56b4afd87 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -2182,7 +2182,7 @@ unsigned int unicode_decode(int *error, const void *in, char **out, qboolean mar if (markup && ((char*)in)[0] == '^' && ((char*)in)[1] == 'U' && ishexcode(((char*)in)[2]) && ishexcode(((char*)in)[3]) && ishexcode(((char*)in)[4]) && ishexcode(((char*)in)[5])) { *out = (char*)in + 6; - charcode = (dehex(((char*)in)[2]) << 12) | (dehex(((char*)in)[2]) << 8) | (dehex(((char*)in)[2]) << 4) | (dehex(((char*)in)[2]) << 0); + charcode = (dehex(((char*)in)[2]) << 12) | (dehex(((char*)in)[3]) << 8) | (dehex(((char*)in)[4]) << 4) | (dehex(((char*)in)[5]) << 0); } else if (markup && ((char*)in)[0] == '^' && ((char*)in)[1] == '{') { @@ -4720,6 +4720,7 @@ static void Sys_ErrorThread(void *ctx, void *data, size_t a, size_t b) } void COM_WorkerAbort(char *message) { + int us; struct com_work_s work; com_fatalerror = true; if (Sys_IsMainThread()) @@ -4728,6 +4729,7 @@ void COM_WorkerAbort(char *message) if (!com_workercondition[0]) return; //Sys_IsMainThread was probably called too early... + memset(&work, 0, sizeof(work)); work.func = Sys_ErrorThread; work.ctx = NULL; work.data = message; @@ -4745,8 +4747,36 @@ void COM_WorkerAbort(char *message) Sys_ConditionSignal(com_workercondition[0]); Sys_UnlockConditional(com_workercondition[0]); - while(com_fatalerror) - Sys_Sleep(0.1); + //find out which worker we are + for (us = WORKERTHREADS-1; us > 0; us--) + if (Sys_IsThread(com_workerthread[us])) + break; + if (us) + { + //and post any pending work we have back over to the main thread, because we're going down as soon as we can. + while(!com_workerdone[us]) + { + struct com_work_s *w; + Sys_LockConditional(com_workercondition[us]); + w = com_work_head[us]; + if (w) + com_work_head[us] = w->next; + if (!com_work_head[us]) + com_work_head[us] = com_work_tail[us] = NULL; + Sys_UnlockConditional(com_workercondition[us]); + if (w) + { + COM_AddWork(0, w->func, w->ctx, w->data, w->a, w->b); + Z_Free(w); + } + else + Sys_ConditionSignal(com_workercondition[0]); + + Sys_Sleep(0.1); + } + com_workerdone[0] = true; + Sys_ConditionSignal(com_workercondition[0]); + } Sys_ThreadAbort(); } //return if there's *any* loading that needs to be done anywhere. @@ -4880,6 +4910,7 @@ void COM_AssertMainThread(const char *msg) void COM_DestroyWorkerThread(void) { int i; + COM_WorkerFullSync(); com_fatalerror = false; for (i = 0; i < WORKERTHREADS; i++) { @@ -4917,6 +4948,7 @@ void COM_DestroyWorkerThread(void) if (com_workercondition[i]) Sys_DestroyConditional(com_workercondition[i]); com_workercondition[i] = NULL; + com_workerthread[i] = NULL; } if (com_resourcemutex) diff --git a/engine/common/common.h b/engine/common/common.h index 59da3672c..f778a385a 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -459,6 +459,8 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r vfsfile_t *FS_OpenTemp(void); vfsfile_t *FS_OpenTCP(const char *name, int defaultport); +vfsfile_t *FS_OpenWithFriends(const char *fname, char *sysname, size_t sysnamesize, int numfriends, ...); + #define countof(array) (sizeof(array)/sizeof(array[0])) #ifdef _WIN32 //windows doesn't support utf-8. Which is a shame really, because that's the charset we expect from everything. @@ -485,7 +487,6 @@ qbyte *QDECL COM_LoadStackFile (const char *path, void *buffer, int bufsize, siz qbyte *COM_LoadTempFile (const char *path, size_t *fsize); qbyte *COM_LoadTempMoreFile (const char *path, size_t *fsize); //allocates a little bit more without freeing old temp //qbyte *COM_LoadHunkFile (const char *path); -qbyte *COM_LoadMallocFile (const char *path, size_t *fsize); searchpathfuncs_t *COM_IteratePaths (void **iterator, char *pathbuffer, int pathbuffersize, char *dirname, int dirnamesize); void COM_FlushFSCache(qboolean purge, qboolean domutex); //a file was written using fopen diff --git a/engine/common/fs.c b/engine/common/fs.c index 114622b35..2a40c1c67 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1480,7 +1480,66 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out return true; } -/*locates and opens a file*/ +//returns false to stop the enumeration. check the return value of the fs enumerator to see if it was canceled by this return value. +static int QDECL FS_NullFSEnumerator(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath) +{ + return FALSE; +} + +//opens a file in the same (writable) path that contains an existing version of the file or one of the other patterns listed +vfsfile_t *FS_OpenWithFriends(const char *fname, char *sysname, size_t sysnamesize, int numfriends, ...) +{ + searchpath_t *search; + searchpath_t *lastwritable = NULL; + flocation_t loc; + va_list ap; + int i; + char cleanname[MAX_QPATH]; + + fname = FS_GetCleanPath(fname, cleanname, sizeof(cleanname)); + if (!fname) + return NULL; + + for (search = com_searchpaths; search ; search = search->next) + { + if ((search->flags & SPF_EXPLICIT) && (search->flags & SPF_WRITABLE)) + lastwritable = search; + if (search->handle->FindFile(search->handle, &loc, fname, NULL)) + break; + + va_start(ap, numfriends); + for (i = 0; i < numfriends; i++) + { + char *path = va_arg(ap, char*); + if (!search->handle->EnumerateFiles(search->handle, path, FS_NullFSEnumerator, NULL)) + break; + } + va_end(ap); + if (i < numfriends) + break; + } + if (lastwritable) + { + //figure out the system path + Q_strncpyz(sysname, lastwritable->logicalpath, sysnamesize); + FS_CleanDir(sysname, sysnamesize); + Q_strncatz(sysname, fname, sysnamesize); + + //create the dir if needed and open the file. + COM_CreatePath(sysname); + return VFSOS_Open(sysname, "wbp"); + } + return NULL; +} + +/*locates and opens a file +modes: +r = read +w = write +a = append +t = text mode (because windows sucks). binary is otherwise assumed. +p = persist (ie: saved games and configs, but not downloads or large content) +*/ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto) { char cleanname[MAX_QPATH]; @@ -2164,6 +2223,8 @@ static searchpath_t *FS_AddPathHandle(searchpath_t **oldpaths, const char *purep Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); Q_strncpyz(search->logicalpath, logicalpath, sizeof(search->logicalpath)); + flags &= ~SPF_WRITABLE; + //temp packages also do not nest if (!(flags & SPF_TEMPORARY)) { @@ -2908,21 +2969,21 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags) { //paths with a leading * are private, and not announced to clients that ask what the current gamedir is. Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir+1); - FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE); + FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE|(com_homepathenabled?0:SPF_WRITABLE)); if (com_homepathenabled) { Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir+1); - FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE); + FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE|SPF_WRITABLE); } } else { Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir); - FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT); + FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT|(com_homepathenabled?0:SPF_WRITABLE)); if (com_homepathenabled) { Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir); - FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT); + FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT|SPF_WRITABLE); } } } diff --git a/engine/common/fs.h b/engine/common/fs.h index c48576b00..eb6977ee2 100644 --- a/engine/common/fs.h +++ b/engine/common/fs.h @@ -74,4 +74,5 @@ void FS_EnumerateKnownGames(qboolean (*callback)(void *usr, ftemanifest_t *man), #define SPF_EXPLICIT 8 //a root gamedir (bumps depth on gamedir depth checks). #define SPF_UNTRUSTED 16 //has been downloaded from somewhere. configs inside it should never be execed with local access rights. #define SPF_PRIVATE 32 //private to the client. ie: the fte dir. +#define SPF_WRITABLE 64 //safe to write here. lots of weird rules etc. qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, int *crc, unsigned int flags); diff --git a/engine/common/fs_pak.c b/engine/common/fs_pak.c index 78093e3f0..f3a58569c 100644 --- a/engine/common/fs_pak.c +++ b/engine/common/fs_pak.c @@ -476,7 +476,7 @@ newsection: if (!strcmp(filename, "p_start")) { section = 3; - sprintf (newfiles[i].name, "patches/%s", filename); //the map loader will find these. + sprintf (newfiles[i].name, "patches/%s.pat", filename); //the map loader will find these. break; } if (!strcmp(filename, "f_start")) @@ -547,7 +547,7 @@ newsection: section = 0; goto newsection; } - sprintf (newfiles[i].name, "patches/%s", filename); + sprintf (newfiles[i].name, "patches/%s.pat", filename); break; case 4: //flats section if (!strcmp(filename, "f_end")) @@ -555,7 +555,7 @@ newsection: section = 0; goto newsection; } - sprintf (newfiles[i].name, "flats/%s", filename); + sprintf (newfiles[i].name, "flats/%s.raw", filename); break; } } @@ -572,6 +572,8 @@ newsection: Con_TPrintf ("Added packfile %s (%i files)\n", desc, numpackfiles); + pack->mutex = Sys_CreateMutex(); + pack->pub.fsver = FSVER; pack->pub.GetPathDetails = FSPAK_GetPathDetails; pack->pub.ClosePath = FSPAK_ClosePath; diff --git a/engine/common/sys.h b/engine/common/sys.h index 37e143b03..6485f2862 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -102,6 +102,7 @@ void Sys_SetThreadName(unsigned int dwThreadID, char *threadName); void Sys_ThreadsInit(void); //qboolean Sys_IsThread(void *thread); qboolean Sys_IsMainThread(void); +qboolean Sys_IsThread(void *thread); void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize); void Sys_WaitOnThread(void *thread); void Sys_DetachThread(void *thread); diff --git a/engine/common/sys_win_threads.c b/engine/common/sys_win_threads.c index f0bc515c8..55f26b1b4 100644 --- a/engine/common/sys_win_threads.c +++ b/engine/common/sys_win_threads.c @@ -157,12 +157,12 @@ qboolean Sys_IsMainThread(void) { return mainthread == GetCurrentThreadId(); } -/* + qboolean Sys_IsThread(void *thread) { return GetThreadId(thread) == GetCurrentThreadId(); } -*/ + /* Mutex calls */ /* diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 05d6891da..d9ed09e33 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -300,6 +300,25 @@ static image_t *Font_GetTrackerImage(unsigned int imid) return NULL; return trackerimages[imid].image; } +qboolean Font_TrackerValid(unsigned int imid) +{ + imid -= TRACKERFIRST; + if (imid >= countof(trackerimages)) + return false; + if (!trackerimages[imid].image) + { + if (!*trackerimages[imid].name) + return false; + trackerimages[imid].image = Image_GetTexture(trackerimages[imid].name, NULL, 0, NULL, NULL, 0, 0, TF_INVALID); + } + if (!trackerimages[imid].image) + return false; + if (trackerimages[imid].image->status == TEX_LOADING) + COM_WorkerPartialSync(trackerimages[imid].image, &trackerimages[imid].image->status, TEX_LOADING); + if (trackerimages[imid].image->status != TEX_LOADED) + return false; + return true; +} //called at load time - initalises font buffers void Font_Init(void) @@ -1121,13 +1140,14 @@ void Doom_ExpandPatch(doompatch_t *p, unsigned char *b, int stride) if (col->length + col->topdelta > p->height) break; - src = (unsigned char *)col + 3; /*why 3? why not, I suppose*/ + src = (unsigned char *)col + 2; /*why 3? why not, I suppose*/ dst = b + stride*col->topdelta; for (y = 0; y < col->length; y++) { *dst = *src++; dst += stride; } + src++; col = (doomcolumn_t *)((unsigned char*)col + col->length + 4); } b++; @@ -1245,14 +1265,18 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) f->charheight = h; } - FS_FreeFile(dp); } /*if all loaded okay, replicate the chars to the quake-compat range (both white+red chars)*/ if (i == '_'+1) { + //doom doesn't have many chars, so make sure the lower case chars exist. + for (i = 'a'; i <= 'z'; i++) + f->chars[i] = f->chars[i-'a'+'A']; + //no space char either f->chars[' '].advance = 8; + f->singletexture = R_LoadTexture8("doomfont", PLANEWIDTH, PLANEHEIGHT, buf, 0, true); for (i = 0xe000; i <= 0xe0ff; i++) { diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index a234b2ffb..a7aba38a9 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -62,7 +62,7 @@ model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose); static void Mod_PrintFormats_f(void); #ifdef MAP_DOOM -qboolean Mod_LoadDoomLevel(model_t *mod); +qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize); #endif #ifdef DSPMODELS @@ -1392,7 +1392,7 @@ TRACE(("dbg: Mod_LoadTextures: inittexturedescs\n")); if (!*mt->name) //I HATE MAPPERS! { sprintf(mt->name, "unnamed%i", i); - Con_Printf(CON_WARNING "warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, mt->name); + Con_DPrintf(CON_WARNING "warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, mt->name); } mt->width = LittleLong (mt->width); diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index ea5796fa2..bf9745067 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -1520,7 +1520,7 @@ static qboolean Sh_VisOverlaps(qbyte *v1, qbyte *v2) { int i, m; if (!v2 || !v1) - return false; + return true; m = (cl.worldmodel->numclusters+7)>>3; for (i=(m&~3) ; iallsolid = trace->startsolid = false; //Con_Printf("total = %f\n", trace->fraction); - return trace->fraction==1; #endif + return trace->fraction==1; } @@ -688,7 +707,7 @@ void Doom_LoadPalette(void) if (!paletteloaded) { paletteloaded = true; - file = FS_LoadMallocFile("wad/playpal"); + file = FS_LoadMallocFile("wad/playpal", NULL); if (file) { memcpy(doompalette, file, 768); @@ -706,10 +725,9 @@ void Doom_LoadPalette(void) } } #endif -int Doom_LoadFlat(char *flatname) +int Doom_LoadFlat(model_t *mod, char *flatname) { #ifndef SERVERONLY - char *file; char texname[64]; int texnum; @@ -725,23 +743,10 @@ int Doom_LoadFlat(char *flatname) memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures])); numgldoomtextures++; - strncpy(gldoomtextures[texnum].name, texname, 8); - - gldoomtextures[texnum].shader = R_RegisterShader(texname, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n"); + Q_strncpyz(gldoomtextures[texnum].name, texname, sizeof(gldoomtextures[texnum].name)); gldoomtextures[texnum].width = 64; gldoomtextures[texnum].height = 64; - gldoomtextures[texnum].meshptr = &gldoomtextures[texnum].mesh; - gldoomtextures[texnum].batch.mesh = &gldoomtextures[texnum].meshptr; - gldoomtextures[texnum].batch.next = loadmodel->batches[gldoomtextures[texnum].shader->sort]; - loadmodel->batches[gldoomtextures[texnum].shader->sort] = &gldoomtextures[texnum].batch; - - file = FS_LoadMallocFile(texname); - if (file) - { - gldoomtextures[texnum].shader->defaulttextures.base = R_LoadTexture8Pal24(texname, 64, 64, file, doompalette, 0); - Z_Free(file); - } return texnum; #else @@ -814,7 +819,8 @@ static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float z1, mesh->numvertexes += 4; mesh->numindexes += 6; - BE_DrawMesh_Single(tex->shader, mesh, NULL, &tex->shader->defaulttextures, 0); + if (tex->shader) + BE_DrawMesh_Single(tex->shader, mesh, NULL, 0); } static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int ceilheight, int numverts, unsigned short *verts, unsigned int colour4b) @@ -859,7 +865,8 @@ static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int mesh->numvertexes += numverts; mesh->numindexes += numverts; - BE_DrawMesh_Single(floortex->shader, mesh, NULL, &floortex->shader->defaulttextures, 0); + if (floortex->shader) + BE_DrawMesh_Single(floortex->shader, mesh, NULL, 0); } //ceiling @@ -898,7 +905,8 @@ static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int mesh->numvertexes += numverts; mesh->numindexes += numverts; - BE_DrawMesh_Single(ceiltex->shader, mesh, NULL, &ceiltex->shader->defaulttextures, 0); + if (ceiltex->shader) + BE_DrawMesh_Single(ceiltex->shader, mesh, NULL, 0); } } @@ -1125,7 +1133,7 @@ void GLR_DoomWorld(void) for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan. { t = &gldoomtextures[texnum]; - if (t->mesh.numindexes) + if (t->mesh.numindexes && t->shader) { t->batch.next = cl.worldmodel->batches[t->shader->sort]; cl.worldmodel->batches[t->shader->sort] = &t->batch; @@ -1375,7 +1383,7 @@ static unsigned short *Triangulate_Finish(int *numtris, unsigned short *old, int return out; } -static void Triangulate_Sectors(dsector_t *sectorl, qboolean glbspinuse) +static void Triangulate_Sectors(model_t *mod, dsector_t *sectorl, qboolean glbspinuse) { int seg, nsec; int i, sec=-1; @@ -1448,8 +1456,8 @@ static void Triangulate_Sectors(dsector_t *sectorl, qboolean glbspinuse) for (i = 0; i < sectorc; i++) { - sectorm[i].ceilingtex = Doom_LoadFlat(sectorl[i].ceilingtexture); - sectorm[i].floortex = Doom_LoadFlat(sectorl[i].floortexture); + sectorm[i].ceilingtex = Doom_LoadFlat(mod, sectorl[i].ceilingtexture); + sectorm[i].floortex = Doom_LoadFlat(mod, sectorl[i].floortexture); sectorm[i].lightlev = sectorl[i].lightlevel; sectorm[i].specialtype = sectorl[i].specialtype; sectorm[i].tag = sectorl[i].tag; @@ -1464,9 +1472,9 @@ static void *textures2; static char *pnames; static void Doom_LoadTextureInfos(void) { - textures1 = FS_LoadMallocFile("wad/texture1"); - textures2 = FS_LoadMallocFile("wad/texture2"); - pnames = FS_LoadMallocFile("wad/pnames"); + textures1 = FS_LoadMallocFile("wad/texture1", NULL); + textures2 = FS_LoadMallocFile("wad/texture2", NULL); + pnames = FS_LoadMallocFile("wad/pnames", NULL); } typedef struct { @@ -1494,7 +1502,7 @@ typedef struct { short ypos; } doomimage_t; -static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, int outwidth, int outheight, int x, int y) +static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, size_t imgsize, int outwidth, int outheight, int x, int y) { unsigned int *colpointers; int c, fr, rc, extra; @@ -1518,7 +1526,7 @@ static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, int outwidth, if (c+x >= outwidth) break; - if (colpointers[c] >= com_filesize) + if (colpointers[c] >= imgsize) break; coldata = data + colpointers[c]; while(1) @@ -1535,7 +1543,8 @@ static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, int outwidth, if (fr<0) { - coldata -= fr; //plus + coldata += -fr; //plus + rc -= -fr; fr = 0; } @@ -1587,11 +1596,16 @@ static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned shor tc = (ddoomtexturecomponant_t*)(tx+1); for (i = 0; i < tx->componantcount; i++, tc++) { + doomimage_t *img; + size_t imgsize; strncpy(patch+8, pnames+4+8*tc->patchnum, 8); Q_strlwr(patch+8); patch[16] = '\0'; + Q_strncatz(patch, ".pat", sizeof(patch)); - Doom_ExtractPName(tex, (doomimage_t *)COM_LoadTempFile(patch), tx->width, tx->height, tc->xoffset, tc->yoffset); + img = (doomimage_t *)FS_LoadMallocFile(patch, &imgsize); + Doom_ExtractPName(tex, img, imgsize, tx->width, tx->height, tc->xoffset, tc->yoffset); + BZ_Free(img); } *hasalpha = false; @@ -1614,15 +1628,15 @@ static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned shor return r_nulltex; } -static int Doom_LoadPatch(char *name) +static int Doom_LoadPatch(model_t *mod, char *name) { - texid_t tex; qboolean hasalpha = false; int texnum; + size_t nlen = strnlen(name, 8); for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan. { - if(!strncmp(name, gldoomtextures[texnum].name, 8)) + if(!memcmp(name, gldoomtextures[texnum].name, nlen) && !gldoomtextures[texnum].name[nlen]) { return texnum; } @@ -1634,32 +1648,59 @@ static int Doom_LoadPatch(char *name) memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures])); numgldoomtextures++; - strncpy(gldoomtextures[texnum].name, name, 8); - - tex = r_nulltex; - if (textures1 && !TEXVALID(tex)) - tex = Doom_LoadPatchFromTexWad(name, textures1, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha); - if (textures2 && !TEXVALID(tex)) - tex = Doom_LoadPatchFromTexWad(name, textures2, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha); - if (!TEXVALID(tex)) - { - //all else failed. - gldoomtextures[texnum].width = image_width; - gldoomtextures[texnum].height = image_height; - gldoomtextures[texnum].meshptr = &gldoomtextures[texnum].mesh; - gldoomtextures[texnum].batch.mesh = &gldoomtextures[texnum].meshptr; - gldoomtextures[texnum].batch.next = loadmodel->batches[gldoomtextures[texnum].shader->sort]; - loadmodel->batches[gldoomtextures[texnum].shader->sort] = &gldoomtextures[texnum].batch; - } - - if (hasalpha) - gldoomtextures[texnum].shader = R_RegisterShader(name, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\nalphafunc ge128\n}\n}\n"); - else - gldoomtextures[texnum].shader = R_RegisterShader(name, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n"); - gldoomtextures[texnum].shader->defaulttextures.base = tex; + memcpy(gldoomtextures[texnum].name, name, nlen); + gldoomtextures[texnum].name[nlen] = 0; return texnum; } + +static void Doom_LoadShaders(void *ctx, void *data, size_t a, size_t b) +{ + model_t *mod = ctx; + texnums_t tn; + qboolean hasalpha = false; + qboolean isflat; + int texnum; + char tmp[MAX_QPATH]; + + for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan. + { + isflat = !strncmp(gldoomtextures[texnum].name, "flats/", 6); + memset(&tn, 0, sizeof(tn)); + if (isflat) + { + void *file = FS_LoadMallocFile(va2(tmp, sizeof(tmp), "%s.raw", gldoomtextures[texnum].name), NULL); + if (file) + { + tn.base = Image_GetTexture(gldoomtextures[texnum].name, NULL, 0, file, doompalette, 64, 64, TF_8PAL24); + Z_Free(file); + } + gldoomtextures[texnum].width = 64; + gldoomtextures[texnum].height = 64; + } + else + { + if (textures1 && !TEXVALID(tn.base)) + tn.base = Doom_LoadPatchFromTexWad(gldoomtextures[texnum].name, textures1, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha); + if (textures2 && !TEXVALID(tn.base)) + tn.base = Doom_LoadPatchFromTexWad(gldoomtextures[texnum].name, textures2, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha); + } + if (!TEXVALID(tn.base)) + { + gldoomtextures[texnum].width = 64; + gldoomtextures[texnum].height = 64; + hasalpha = false; + } + + if (hasalpha) + gldoomtextures[texnum].shader = R_RegisterShader(gldoomtextures[texnum].name, SUF_NONE, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\nalphafunc ge128\n}\n}\n"); + else + gldoomtextures[texnum].shader = R_RegisterShader(gldoomtextures[texnum].name, SUF_NONE, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n"); + + R_BuildDefaultTexnums(&tn, gldoomtextures[texnum].shader); + } +}; + static void Doom_Purge (struct model_s *mod) { int texnum; @@ -1674,7 +1715,7 @@ static void Doom_Purge (struct model_s *mod) gldoomtextures = NULL; } #endif -static void CleanWalls(dsidedef_t *sidedefsl) +static void CleanWalls(model_t *mod, dsidedef_t *sidedefsl) { int i; char texname[64]; @@ -1697,7 +1738,7 @@ static void CleanWalls(dsidedef_t *sidedefsl) else { strncpy(lastmiddle, texname, 8); - sidedefsm[i].middletex = lastmidtex = Doom_LoadPatch(texname);//Mod_LoadHiResTexture(texname, true, false); + sidedefsm[i].middletex = lastmidtex = Doom_LoadPatch(mod, texname); } } @@ -1712,7 +1753,7 @@ static void CleanWalls(dsidedef_t *sidedefsl) else { strncpy(lastlower, texname, 8); - sidedefsm[i].lowertex = lastlowtex = Doom_LoadPatch(texname);//Mod_LoadHiResTexture(texname, true, true); + sidedefsm[i].lowertex = lastlowtex = Doom_LoadPatch(mod, texname); } } @@ -1727,7 +1768,7 @@ static void CleanWalls(dsidedef_t *sidedefsl) else { strncpy(lastupper, texname, 8); - sidedefsm[i].uppertex = lastuptex = Doom_LoadPatch(texname);//Mod_LoadHiResTexture(texname, true, false); + sidedefsm[i].uppertex = lastuptex = Doom_LoadPatch(mod, texname); } } #endif @@ -1737,14 +1778,16 @@ static void CleanWalls(dsidedef_t *sidedefsl) } } -void QuakifyThings(dthing_t *thingsl) +void QuakifyThings(model_t *mod, dthing_t *thingsl) { int sector; int spawnflags; char *name; int i; int zpos; - static char newlump[1024*1024]; + static char newlump[1024*1024]; //FIXME + char thingname[MAX_QPATH]; + char *ptr = newlump; vec3_t point; @@ -1793,7 +1836,7 @@ void QuakifyThings(dthing_t *thingsl) break; default: - name = va("thing_%i", thingsl[i].type); + name = va2(thingname, sizeof(thingname), "thing_%i", thingsl[i].type); break; } @@ -1815,7 +1858,7 @@ void QuakifyThings(dthing_t *thingsl) if (thingsl[i].flags & THING_DEAF) spawnflags |= 1; - sprintf(ptr, "{\n" + Q_snprintfz(ptr, newlump+sizeof(newlump)-ptr, "{\n" "\"classname\" \"%s\"\n" "\"origin\" \"%i %i %i\"\n" "\"spawnflags\" \"%i\"\n" @@ -1829,8 +1872,8 @@ void QuakifyThings(dthing_t *thingsl) ptr += strlen(ptr); } - loadmodel->entities = BZ_Malloc(ptr-newlump+1); - memcpy(loadmodel->entities, newlump, ptr-newlump+1); + mod->entities = BZ_Malloc(ptr-newlump+1); + memcpy(mod->entities, newlump, ptr-newlump+1); } void Doom_GeneratePlanes(ddoomnode_t *nodel) @@ -1949,11 +1992,13 @@ static void Doom_LoadVerticies(char *name) int stdc, glc; int *gl2; int i; + size_t fsize; + char tmp[MAX_QPATH]; - std = (void *)COM_LoadTempFile (va("%s.vertexes", name)); - stdc = com_filesize/sizeof(*std); + std = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.vertexes", name), &fsize); + stdc = fsize/sizeof(*std); - gl2 = (void *)COM_LoadTempMoreFile (va("%s.gl_vert", name)); + gl2 = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.gl_vert", name), &fsize); if (!gl2) { glc = 0; @@ -1962,53 +2007,57 @@ static void Doom_LoadVerticies(char *name) else if (gl2[0] == *(int*)"gNd2") { gl2++; - glc = (com_filesize-4)/sizeof(int)/2; + glc = (fsize-4)/sizeof(int)/2; gl1 = NULL; } else { - glc = com_filesize/sizeof(*gl1); + glc = fsize/sizeof(*gl1); gl1 = (ddoomvertex_t*)gl2; } - if (!stdc) - return; - - vertexesc = stdc + glc; - vertexesl = BZ_Malloc(vertexesc*sizeof(*vertexesl)); - - vertexsglbase = stdc; - - for (i = 0; i < stdc; i++) + if (stdc) { - vertexesl[i].xpos = std[i].xpos; - vertexesl[i].ypos = std[i].ypos; - } - if (gl1) - { - for (i = 0; i < glc; i++) + vertexesc = stdc + glc; + vertexesl = BZ_Malloc(vertexesc*sizeof(*vertexesl)); + + vertexsglbase = stdc; + + for (i = 0; i < stdc; i++) { - vertexesl[stdc+i].xpos = gl1[i].xpos; - vertexesl[stdc+i].ypos = gl1[i].ypos; - } - } - else - { - for (i = 0; i < glc; i++) - { - vertexesl[stdc+i].xpos = (float)gl2[i*2] / 0x10000; - vertexesl[stdc+i].ypos = (float)gl2[i*2+1] / 0x10000; + vertexesl[i].xpos = std[i].xpos; + vertexesl[i].ypos = std[i].ypos; + } + if (gl1) + { + for (i = 0; i < glc; i++) + { + vertexesl[stdc+i].xpos = gl1[i].xpos; + vertexesl[stdc+i].ypos = gl1[i].ypos; + } + } + else + { + for (i = 0; i < glc; i++) + { + vertexesl[stdc+i].xpos = (float)gl2[i*2] / 0x10000; + vertexesl[stdc+i].ypos = (float)gl2[i*2+1] / 0x10000; + } } } + Z_Free(std); + Z_Free(gl2); } static void Doom_LoadSSectors(char *name) { - ssectorsl = (void *)FS_LoadMallocFile (va("%s.gl_ssect", name)); + size_t fsize; + char tmp[MAX_QPATH]; + ssectorsl = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_ssect", name), &fsize); if (!ssectorsl) - ssectorsl = (void *)FS_LoadMallocFile (va("%s.ssectors", name)); + ssectorsl = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.ssectors", name), &fsize); //FIXME: "gNd3" means that it's glbsp version 3. - ssectorsc = com_filesize/sizeof(*ssectorsl); + ssectorsc = fsize/sizeof(*ssectorsl); } static void Doom_LoadSSegs(char *name) @@ -2019,12 +2068,14 @@ static void Doom_LoadSSegs(char *name) dgl_seg1_t *s1; dseg_t *s0; int i; + size_t fsize; + char tmp[MAX_QPATH]; - file = (void *)FS_LoadMallocFile (va("%s.gl_segs", name)); + file = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_segs", name), &fsize); if (!file) { - s0 = (void *)FS_LoadMallocFile (va("%s.segs", name)); - segsc = com_filesize/sizeof(*s0); + s0 = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.segs", name), &fsize); + segsc = fsize/sizeof(*s0); segsl = BZ_Malloc(segsc * sizeof(*segsl)); for (i = 0; i < segsc; i++) @@ -2039,7 +2090,7 @@ static void Doom_LoadSSegs(char *name) else if (*(int *)file == *(int *)"gNd3") { s3 = file; - segsc = com_filesize/sizeof(*s3); + segsc = fsize/sizeof(*s3); segsl = s3; } @@ -2048,7 +2099,7 @@ static void Doom_LoadSSegs(char *name) else { s1 = file; - segsc = com_filesize/sizeof(*s1); + segsc = fsize/sizeof(*s1); segsl = BZ_Malloc(segsc * sizeof(*segsl)); for (i = 0; i < segsc; i++) @@ -2071,37 +2122,38 @@ static void Doom_LoadSSegs(char *name) } } -qboolean Mod_LoadDoomLevel(model_t *mod) +qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize) { int h; dsector_t *sectorl; dsidedef_t *sidedefsl; char name[MAX_QPATH]; + char tmp[MAX_QPATH]; int *gl_nodes; - COM_StripExtension(mod->name, name, sizeof(name)); - - if (!COM_LoadTempFile(va("%s", mod->name))) + if (fsize != 4) { - Con_Printf("Wad map %s does not exist\n", mod->name); + Con_Printf("Wad map %s does actually exist... weird.\n", mod->name); return false; } - gl_nodes = (void *)FS_LoadMallocFile (va("%s.gl_nodes", name)); - if (gl_nodes && com_filesize>0) + COM_StripExtension(mod->name, name, sizeof(name)); + + gl_nodes = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.gl_nodes", name), &fsize); + if (gl_nodes && fsize>0) { nodel = (void *)gl_nodes; - nodec = com_filesize/sizeof(*nodel); + nodec = fsize/sizeof(*nodel); } else { gl_nodes=NULL; - nodel = (void *)FS_LoadMallocFile (va("%s.nodes", name)); - nodec = com_filesize/sizeof(*nodel); + nodel = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.nodes", name), &fsize); + nodec = fsize/sizeof(*nodel); } - sectorl = (void *)FS_LoadMallocFile (va("%s.sectors", name)); - sectorc = com_filesize/sizeof(*sectorl); + sectorl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sectors", name), &fsize); + sectorc = fsize/sizeof(*sectorl); #ifndef SERVERONLY numgldoomtextures=0; @@ -2114,14 +2166,14 @@ qboolean Mod_LoadDoomLevel(model_t *mod) Doom_LoadSSegs(name); Doom_LoadSSectors(name); - thingsl = (void *)FS_LoadMallocFile (va("%s.things", name)); - thingsc = com_filesize/sizeof(*thingsl); - linedefsl = (void *)FS_LoadMallocFile (va("%s.linedefs", name)); - linedefsc = com_filesize/sizeof(*linedefsl); - sidedefsl = (void *)FS_LoadMallocFile (va("%s.sidedefs", name)); - sidedefsc = com_filesize/sizeof(*sidedefsl); - blockmapl = (void *)FS_LoadMallocFile (va("%s.blockmap", name)); -// blockmaps = com_filesize; + thingsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.things", name), &fsize); + thingsc = fsize/sizeof(*thingsl); + linedefsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.linedefs", name), &fsize); + linedefsc = fsize/sizeof(*linedefsl); + sidedefsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sidedefs", name), &fsize); + sidedefsc = fsize/sizeof(*sidedefsl); + blockmapl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.blockmap", name), &fsize); +// blockmaps = fsize; #ifndef SERVERONLY Doom_LoadTextureInfos(); #endif @@ -2151,17 +2203,17 @@ qboolean Mod_LoadDoomLevel(model_t *mod) Doom_SetModelFunc(mod); - mod->needload = false; mod->fromgame = fg_doom; mod->type = mod_brush; mod->nodes = (void*)0x1; - CleanWalls(sidedefsl); + CleanWalls(mod, sidedefsl); - Triangulate_Sectors(sectorl, !!gl_nodes); + Triangulate_Sectors(mod, sectorl, !!gl_nodes); - QuakifyThings(thingsl); + QuakifyThings(mod, thingsl); + COM_AddWork(0, Doom_LoadShaders, mod, NULL, 0, 0); return true; } diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 713f0a0ba..ce6903f28 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -466,7 +466,7 @@ static edict_t *QDECL Q1QVMPF_EntAlloc(pubprogfuncs_t *pf) static int QDECL Q1QVMPF_LoadEnts(pubprogfuncs_t *pf, const char *mapstring, float spawnflags) { q1qvmentstring = mapstring; - VM_Call(q1qvm, GAME_LOADENTS); + VM_Call(q1qvm, GAME_LOADENTS, 0, 0, 0); q1qvmentstring = NULL; return sv.world.edict_size; } @@ -1310,6 +1310,7 @@ void Q1QVM_Shutdown(void) Q_strncpyz(svs.clients[i].namebuf, svs.clients[i].name, sizeof(svs.clients[i].namebuf)); svs.clients[i].name = svs.clients[i].namebuf; } + VM_Call(q1qvm, GAME_SHUTDOWN, 0, 0, 0); VM_Destroy(q1qvm); q1qvm = NULL; VM_fcloseall(VMFSID_Q1QVM); @@ -1332,7 +1333,7 @@ void Q1QVM_Event_Touch(world_t *w, wedict_t *s, wedict_t *o) pr_global_struct->self = EDICT_TO_PROG(w->progs, s); pr_global_struct->other = EDICT_TO_PROG(w->progs, o); pr_global_struct->time = w->physicstime; - VM_Call(q1qvm, GAME_EDICT_TOUCH); + VM_Call(q1qvm, GAME_EDICT_TOUCH, 0, 0, 0); pr_global_struct->self = oself; pr_global_struct->other = oother; @@ -1342,7 +1343,7 @@ void Q1QVM_Event_Think(world_t *w, wedict_t *s) { pr_global_struct->self = EDICT_TO_PROG(w->progs, s); pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); - VM_Call(q1qvm, GAME_EDICT_THINK); + VM_Call(q1qvm, GAME_EDICT_THINK, 0, 0, 0); } qboolean Q1QVM_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype) @@ -1424,7 +1425,7 @@ qboolean PR_LoadQ1QVM(void) q1qvmprogfuncs.stringtable = VM_MemoryBase(q1qvm); - ret = VM_Call(q1qvm, GAME_INIT, (qintptr_t)(sv.time*1000), rand()); + ret = VM_Call(q1qvm, GAME_INIT, (qintptr_t)(sv.time*1000), rand(), 0, 0, 0); if (!ret) { Q1QVM_Shutdown(); @@ -1466,9 +1467,6 @@ qboolean PR_LoadQ1QVM(void) sv.world.edict_size = gd->sizeofent; vevars = (qintptr_t)gd->ents; evars = ((char*)VM_MemoryBase(q1qvm) + vevars); - //FIXME: range check this pointer - //FIXME: range check the globals pointer - //WARNING: global is not remapped yet... //This code is written evilly, but works well enough @@ -1527,7 +1525,7 @@ qboolean PR_LoadQ1QVM(void) pr_global_ptrs->dimension_send = &dimensionsend; pr_global_ptrs->physics_mode = &physics_mode; - dimensionsend = 255; + dimensionsend = dimensiondefault = 255; for (i = 0; i < 16; i++) pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i)); for (; i < NUM_SPAWN_PARMS; i++) @@ -1571,12 +1569,12 @@ void Q1QVM_ClientConnect(client_t *cl) // call the spawn function pr_global_struct->time = sv.world.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); - VM_Call(q1qvm, GAME_CLIENT_CONNECT, cl->spectator); + VM_Call(q1qvm, GAME_CLIENT_CONNECT, cl->spectator, 0, 0, 0); // actually spawn the player pr_global_struct->time = sv.world.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); - VM_Call(q1qvm, GAME_PUT_CLIENT_IN_SERVER, cl->spectator); + VM_Call(q1qvm, GAME_PUT_CLIENT_IN_SERVER, cl->spectator, 0, 0, 0); } qboolean Q1QVM_GameConsoleCommand(void) @@ -1595,7 +1593,7 @@ qboolean Q1QVM_GameConsoleCommand(void) pr_global_struct->self = 0; pr_global_struct->other = 0; - VM_Call(q1qvm, GAME_CONSOLE_COMMAND); //mod uses Cmd_Argv+co to get args + VM_Call(q1qvm, GAME_CONSOLE_COMMAND, 0, 0, 0); //mod uses Cmd_Argv+co to get args pr_global_struct->self = oldself; pr_global_struct->other = oldother; @@ -1610,7 +1608,7 @@ qboolean Q1QVM_ClientSay(edict_t *player, qboolean team) pr_global_struct->time = sv.world.physicstime; pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player); - washandled = VM_Call(q1qvm, GAME_CLIENT_SAY, team); + washandled = VM_Call(q1qvm, GAME_CLIENT_SAY, team, 0, 0, 0); return washandled; } @@ -1622,53 +1620,53 @@ qboolean Q1QVM_UserInfoChanged(edict_t *player) pr_global_struct->time = sv.world.physicstime; pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player); - return VM_Call(q1qvm, GAME_CLIENT_USERINFO_CHANGED); + return VM_Call(q1qvm, GAME_CLIENT_USERINFO_CHANGED, 0, 0, 0); } void Q1QVM_PlayerPreThink(void) { - VM_Call(q1qvm, GAME_CLIENT_PRETHINK, host_client->spectator); + VM_Call(q1qvm, GAME_CLIENT_PRETHINK, host_client->spectator, 0, 0, 0); } void Q1QVM_RunPlayerThink(void) { - VM_Call(q1qvm, GAME_EDICT_THINK); - VM_Call(q1qvm, GAME_CLIENT_THINK, host_client->spectator); + VM_Call(q1qvm, GAME_EDICT_THINK, 0, 0, 0); + VM_Call(q1qvm, GAME_CLIENT_THINK, host_client->spectator, 0, 0, 0); } void Q1QVM_PostThink(void) { - VM_Call(q1qvm, GAME_CLIENT_POSTTHINK, host_client->spectator); + VM_Call(q1qvm, GAME_CLIENT_POSTTHINK, host_client->spectator, 0, 0, 0); } void Q1QVM_StartFrame(void) { - VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000)); + VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000), 0, 0, 0); } void Q1QVM_Blocked(void) { - VM_Call(q1qvm, GAME_EDICT_BLOCKED); + VM_Call(q1qvm, GAME_EDICT_BLOCKED, 0, 0, 0); } void Q1QVM_SetNewParms(void) { - VM_Call(q1qvm, GAME_SETNEWPARMS); + VM_Call(q1qvm, GAME_SETNEWPARMS, 0, 0, 0); } void Q1QVM_SetChangeParms(void) { - VM_Call(q1qvm, GAME_SETCHANGEPARMS); + VM_Call(q1qvm, GAME_SETCHANGEPARMS, 0, 0, 0); } void Q1QVM_ClientCommand(void) { - VM_Call(q1qvm, GAME_CLIENT_COMMAND); + VM_Call(q1qvm, GAME_CLIENT_COMMAND, 0, 0, 0); } void Q1QVM_GameCodePausedTic(float pausedduration) { - VM_Call(q1qvm, GAME_PAUSED_TIC, (qintptr_t)(pausedduration*1000)); + VM_Call(q1qvm, GAME_PAUSED_TIC, (qintptr_t)(pausedduration*1000), 0, 0, 0); } void Q1QVM_DropClient(client_t *cl) @@ -1677,7 +1675,7 @@ void Q1QVM_DropClient(client_t *cl) Q_strncpyz(cl->namebuf, cl->name, sizeof(cl->namebuf)); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); - VM_Call(q1qvm, GAME_CLIENT_DISCONNECT); + VM_Call(q1qvm, GAME_CLIENT_DISCONNECT, 0, 0, 0); cl->name = cl->namebuf; }