diff --git a/appveyor.yml b/appveyor.yml index 0edc7ce28..c64e69665 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,8 +55,6 @@ cache: install: - if [%CONFIGURATION%] == [SDL64] ( set "X86_64=1" ) - if [%CONFIGURATION%] == [SDL64] ( set "CONFIGURATION=SDL" ) -- if [%CONFIGURATION%] == [DD64] ( set "X86_64=1" ) -- if [%CONFIGURATION%] == [DD64] ( set "CONFIGURATION=DD" ) - if [%X86_64%] == [1] ( set "MINGW_SDK=%MINGW_SDK_64%" ) - if [%X86_64%] == [1] ( set "CCACHE_CC=%CCACHE_CC_64%" ) @@ -75,13 +73,6 @@ install: configuration: - SDL - SDL64 -- DD -- DD64 - -matrix: - allow_failures: - - configuration: DD - - configuration: DD64 before_build: - set "Path=%MINGW_SDK%\bin;%Path%" diff --git a/src/android/i_system.c b/src/android/i_system.c index 58fca7c19..752e9f6c6 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -245,6 +245,8 @@ void I_GetJoystick2Events(void){} void I_GetMouseEvents(void){} +void I_UpdateMouseGrab(void){} + char *I_GetEnv(const char *name) { LOGW("I_GetEnv() called?!"); diff --git a/src/android/i_video.c b/src/android/i_video.c index 2d0151f5e..b8bb4fefb 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -19,6 +19,7 @@ boolean allow_fullscreen = false; consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void I_StartupGraphics(void){} +void I_StartupHardwareGraphics(void){} void I_ShutdownGraphics(void){} @@ -51,6 +52,11 @@ INT32 VID_SetMode(INT32 modenum) return 0; } +void VID_CheckRenderer(void) +{ + // .............. +} + const char *VID_GetModeName(INT32 modenum) { return "A320x240"; diff --git a/src/b_bot.c b/src/b_bot.c index dfb5ee1cf..51dc4d2f2 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -335,27 +335,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) jump_last = jump; spin_last = spin; - // ******** - // Thinkfly overlay - if (thinkfly) - { - if (!tails->hnext) - { - P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY)); - if (tails->hnext) - { - P_SetTarget(&tails->hnext->target, tails); - P_SetTarget(&tails->hnext->hprev, tails); - P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR); - } - } - } - else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR) - { - P_RemoveMobj(tails->hnext); - P_SetTarget(&tails->hnext, NULL); - } - // Turn the virtual keypresses into ticcmd_t. B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin); @@ -565,3 +544,30 @@ void B_RespawnBot(INT32 playernum) P_SetScale(tails, sonic->scale); tails->destscale = sonic->destscale; } + +void B_HandleFlightIndicator(player_t *player) +{ + mobj_t *tails = player->mo; + + if (!tails) + return; + + if (thinkfly && player->bot == 1 && tails->health) + { + if (!tails->hnext) + { + P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY)); + if (tails->hnext) + { + P_SetTarget(&tails->hnext->target, tails); + P_SetTarget(&tails->hnext->hprev, tails); + P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR); + } + } + } + else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR) + { + P_RemoveMobj(tails->hnext); + P_SetTarget(&tails->hnext, NULL); + } +} diff --git a/src/b_bot.h b/src/b_bot.h index b42577c5c..54ef300a3 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -15,3 +15,4 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward boolean B_CheckRespawn(player_t *player); void B_MoveBlocked(player_t *player); void B_RespawnBot(INT32 playernum); +void B_HandleFlightIndicator(player_t *player); diff --git a/src/command.c b/src/command.c index 33d8ead96..2893106dd 100644 --- a/src/command.c +++ b/src/command.c @@ -54,13 +54,15 @@ static void COM_Add_f(void); static void CV_EnforceExecVersion(void); static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr); static boolean CV_Command(void); -static consvar_t *CV_FindVar(const char *name); +consvar_t *CV_FindVar(const char *name); static const char *CV_StringValue(const char *var_name); static consvar_t *consvar_vars; // list of registered console variables static char com_token[1024]; static char *COM_Parse(char *data); +static char * COM_Purge (char *text, int *lenp); + CV_PossibleValue_t CV_OnOff[] = {{0, "Off"}, {1, "On"}, {0, NULL}}; CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}}; CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; @@ -100,31 +102,61 @@ static cmdalias_t *com_alias; // aliases list static vsbuf_t com_text; // variable sized buffer +/** Purges control characters out of some text. + * + * \param s The text. + * \param np Optionally a pointer to fill with the new string length. + * \return The text. + * \sa COM_ExecuteString + */ +static char * +COM_Purge (char *s, int *np) +{ + char *t; + char *p; + int n; + n = strlen(s); + t = s + n + 1; + p = s; + while (( p = strchr(p, '\033') )) + { + memmove(p, &p[1], t - p - 1); + n--; + } + if (np) + (*np) = n; + return s; +} + /** Adds text into the command buffer for later execution. * * \param ptext The text to add. - * \sa COM_BufInsertText + * \sa COM_BufInsertTextEx */ -void COM_BufAddText(const char *ptext) +void COM_BufAddTextEx(const char *ptext, int flags) { - size_t l; + int l; + char *text; - l = strlen(ptext); + text = COM_Purge(Z_StrDup(ptext), &l); - if (com_text.cursize + l >= com_text.maxsize) + if (com_text.cursize + 2 + l >= com_text.maxsize) { CONS_Alert(CONS_WARNING, M_GetText("Command buffer full!\n")); return; } - VS_Write(&com_text, ptext, l); + + VS_WriteEx(&com_text, text, l, flags); + + Z_Free(text); } /** Adds command text and executes it immediately. * * \param ptext The text to execute. A newline is automatically added. - * \sa COM_BufAddText + * \sa COM_BufAddTextEx */ -void COM_BufInsertText(const char *ptext) +void COM_BufInsertTextEx(const char *ptext, int flags) { char *temp = NULL; size_t templen; @@ -138,7 +170,7 @@ void COM_BufInsertText(const char *ptext) } // add the entire text of the file (or alias) - COM_BufAddText(ptext); + COM_BufAddTextEx(ptext, flags); COM_BufExecute(); // do it right away // add the copied off data @@ -272,6 +304,7 @@ static size_t com_argc; static char *com_argv[MAX_ARGS]; static const char *com_null_string = ""; static char *com_args = NULL; // current command args or NULL +static int com_flags; static void Got_NetVar(UINT8 **p, INT32 playernum); @@ -394,12 +427,21 @@ static void COM_TokenizeString(char *ptext) com_argc = 0; com_args = NULL; + com_flags = 0; while (com_argc < MAX_ARGS) { // Skip whitespace up to a newline. while (*ptext != '\0' && *ptext <= ' ' && *ptext != '\n') - ptext++; + { + if (ptext[0] == '\033') + { + com_flags = (unsigned)ptext[1]; + ptext += 2; + } + else + ptext++; + } // A newline means end of command in buffer, // thus end of this command's args too. @@ -1016,6 +1058,15 @@ void VS_Write(vsbuf_t *buf, const void *data, size_t length) M_Memcpy(VS_GetSpace(buf, length), data, length); } +void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, int flags) +{ + char *p; + p = VS_GetSpace(buf, 2 + length); + p[0] = '\033'; + p[1] = flags; + M_Memcpy(&p[2], data, length); +} + /** Prints text in a variable buffer. Like VS_Write() plus a * trailing NUL. * @@ -1055,7 +1106,7 @@ static const char *cv_null_string = ""; * \return Pointer to the variable if found, or NULL. * \sa CV_FindNetVar */ -static consvar_t *CV_FindVar(const char *name) +consvar_t *CV_FindVar(const char *name) { consvar_t *cvar; @@ -2015,6 +2066,9 @@ static boolean CV_Command(void) if (!v) return false; + if (( com_flags & COM_SAFE ) && ( v->flags & CV_NOLUA )) + return false; + // perform a variable print or set if (COM_Argc() == 1) { @@ -2116,8 +2170,13 @@ skipwhite: com_token[len] = 0; return data; } - com_token[len] = c; - len++; + if (c == '\033') + data++; + else + { + com_token[len] = c; + len++; + } } } @@ -2133,10 +2192,22 @@ skipwhite: // parse a regular word do { - com_token[len] = c; - data++; - len++; - c = *data; + if (c == '\033') + { + do + { + data += 2; + c = *data; + } + while (c == '\033') ; + } + else + { + com_token[len] = c; + data++; + len++; + c = *data; + } if (c == '{' || c == '}' || c == ')'|| c == '(' || c == '\'') break; } while (c > 32); diff --git a/src/command.h b/src/command.h index 51e161cd0..42bd6eb84 100644 --- a/src/command.h +++ b/src/command.h @@ -20,6 +20,11 @@ // Command buffer & command execution //=================================== +enum +{ + COM_SAFE = 1, +}; + typedef void (*com_func_t)(void); void COM_AddCommand(const char *name, com_func_t func); @@ -36,10 +41,12 @@ size_t COM_FirstOption(void); const char *COM_CompleteCommand(const char *partial, INT32 skips); // insert at queu (at end of other command) -void COM_BufAddText(const char *btext); +#define COM_BufAddText(s) COM_BufAddTextEx(s, 0) +void COM_BufAddTextEx(const char *btext, int flags); // insert in head (before other command) -void COM_BufInsertText(const char *btext); +#define COM_BufInsertText(s) COM_BufInsertTextEx(s, 0) +void COM_BufInsertTextEx(const char *btext, int flags); // don't bother inserting, just do immediately void COM_ImmedExecute(const char *ptext); @@ -71,6 +78,7 @@ void VS_Free(vsbuf_t *buf); void VS_Clear(vsbuf_t *buf); void *VS_GetSpace(vsbuf_t *buf, size_t length); void VS_Write(vsbuf_t *buf, const void *data, size_t length); +void VS_WriteEx(vsbuf_t *buf, const void *data, size_t length, int flags); void VS_Print(vsbuf_t *buf, const char *data); // strcats onto the sizebuf //================== @@ -100,7 +108,8 @@ typedef enum CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console // can only be set when we have the pointer to it // used on menus - CV_CHEAT = 2048 // Don't let this be used in multiplayer unless cheats are on. + CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on. + CV_NOLUA = 4096,/* don't let this be called from Lua */ } cvflags_t; typedef struct CV_PossibleValue_s @@ -140,6 +149,9 @@ void CV_ToggleExecVersion(boolean enable); // register a variable for use at the console void CV_RegisterVar(consvar_t *variable); +// returns a console variable by name +consvar_t *CV_FindVar(const char *name); + // sets changed to 0 for every console variable void CV_ClearChangedFlags(void); diff --git a/src/console.c b/src/console.c index 1fbca75b4..01d1ddaa2 100644 --- a/src/console.c +++ b/src/console.c @@ -20,6 +20,7 @@ #include "g_input.h" #include "hu_stuff.h" #include "keys.h" +#include "r_main.h" #include "r_defs.h" #include "sounds.h" #include "st_stuff.h" @@ -591,6 +592,8 @@ void CON_ToggleOff(void) CON_ClearHUD(); con_forcepic = 0; con_clipviewtop = -1; // remove console clipping of view + + I_UpdateMouseGrab(); } boolean CON_Ready(void) @@ -615,6 +618,7 @@ void CON_Ticker(void) consoletoggle = false; con_destlines = 0; CON_ClearHUD(); + I_UpdateMouseGrab(); } // console key was pushed @@ -627,6 +631,7 @@ void CON_Ticker(void) { con_destlines = 0; CON_ClearHUD(); + I_UpdateMouseGrab(); } else CON_ChangeHeight(); @@ -1285,10 +1290,10 @@ void CONS_Printf(const char *fmt, ...) con_scrollup = 0; // if not in display loop, force screen update - if (con_startup) + if (con_startup && (!setrenderneeded)) { #ifdef _WINDOWS - patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_CACHE); + patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); // Jimita: CON_DrawBackpic just called V_DrawScaledPatch V_DrawScaledPatch(0, 0, 0, con_backpic); @@ -1545,7 +1550,7 @@ static void CON_DrawConsole(void) // draw console background if (cons_backpic.value || con_forcepic) { - patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_CACHE); + patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); // Jimita: CON_DrawBackpic just called V_DrawScaledPatch V_DrawScaledPatch(0, 0, 0, con_backpic); @@ -1602,8 +1607,18 @@ void CON_Drawer(void) if (!con_started || !graphics_started) return; + if (needpatchrecache) + { + W_FlushCachedPatches(); + HU_LoadGraphics(); + } + if (con_recalc) + { CON_RecalcSize(); + if (con_curlines <= 0) + CON_ClearHUD(); + } if (con_curlines > 0) CON_DrawConsole(); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4448aaae0..98ff3a6f8 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1265,8 +1265,12 @@ static boolean CL_SendJoin(void) if (splitscreen || botingame) localplayers++; netbuffer->u.clientcfg.localplayers = localplayers; + netbuffer->u.clientcfg._255 = 255; + netbuffer->u.clientcfg.packetversion = PACKETVERSION; netbuffer->u.clientcfg.version = VERSION; netbuffer->u.clientcfg.subversion = SUBVERSION; + strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application); strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); @@ -1277,15 +1281,20 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) UINT8 *p; netbuffer->packettype = PT_SERVERINFO; + netbuffer->u.serverinfo._255 = 255; + netbuffer->u.serverinfo.packetversion = PACKETVERSION; netbuffer->u.serverinfo.version = VERSION; netbuffer->u.serverinfo.subversion = SUBVERSION; + strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION, + sizeof netbuffer->u.serverinfo.application); // return back the time value so client can compute their ping netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; - netbuffer->u.serverinfo.gametype = (UINT8)gametype; + strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], + sizeof netbuffer->u.serverinfo.gametypename); netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated; @@ -1712,12 +1721,21 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) if (serverlistcount >= MAXSERVERLIST) return; // list full + if (info->_255 != 255) + return;/* old packet format */ + + if (info->packetversion != PACKETVERSION) + return;/* old new packet format */ + if (info->version != VERSION) return; // Not same version. if (info->subversion != SUBVERSION) return; // Close, but no cigar. + if (strcmp(info->application, SRB2APPLICATION)) + return;/* that's a different mod */ + i = serverlistcount++; } @@ -2105,13 +2123,10 @@ static void CL_ConnectToServer(boolean viams) if (i != -1) { - UINT16 num = serverlist[i].info.gametype; - const char *gametypestr = NULL; + char *gametypestr = serverlist[i].info.gametypename; CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); - if (num < gametypecount) - gametypestr = Gametype_Names[num]; - if (gametypestr) - CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); + gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0'; + CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, serverlist[i].info.version%100, serverlist[i].info.subversion); } @@ -2987,8 +3002,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) CL_RemovePlayer(pnum, kickreason); } -consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; -consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done +consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; @@ -3509,6 +3524,12 @@ static void HandleConnect(SINT8 node) if (bannednode && bannednode[node]) SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server")); + else if (netbuffer->u.clientcfg._255 != 255 || + netbuffer->u.clientcfg.packetversion != PACKETVERSION) + SV_SendRefuse(node, "Incompatible packet formats."); + else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application)) + SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible."); else if (netbuffer->u.clientcfg.version != VERSION || netbuffer->u.clientcfg.subversion != SUBVERSION) SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION)); @@ -3631,6 +3652,10 @@ static void HandleServerInfo(SINT8 node) const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; + netbuffer->u.serverinfo.application + [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; + netbuffer->u.serverinfo.gametypename + [sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0'; SL_InsertServer(&netbuffer->u.serverinfo, node); } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 4ba4ee0eb..c797e5ca8 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -19,6 +19,16 @@ #include "tables.h" #include "d_player.h" +/* +The 'packet version' may be used with packets whose +format is expected to change between versions. + +This version is independent of the mod name, and standard +version and subversion. It should only account for the +basic fields of the packet, and change infrequently. +*/ +#define PACKETVERSION 1 + // Network play related stuff. // There is a data struct that stores network // communication related stuff, and another @@ -320,8 +330,13 @@ typedef struct { #pragma warning(default : 4200) #endif +#define MAXAPPLICATION 16 + typedef struct { + UINT8 _255;/* see serverinfo_pak */ + UINT8 packetversion; + char application[MAXAPPLICATION]; UINT8 version; // Different versions don't work UINT8 subversion; // Contains build version UINT8 localplayers; @@ -334,11 +349,19 @@ typedef struct // This packet is too large typedef struct { + /* + In the old packet, 'version' is the first field. Now that field is set + to 255 always, so older versions won't be confused with the new + versions or vice-versa. + */ + UINT8 _255; + UINT8 packetversion; + char application[MAXAPPLICATION]; UINT8 version; UINT8 subversion; UINT8 numberofplayer; UINT8 maxplayer; - UINT8 gametype; + char gametypename[24]; UINT8 modifiedgame; UINT8 cheatsenabled; UINT8 isdedicated; diff --git a/src/d_main.c b/src/d_main.c index 0654e0927..432dfd34f 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -108,6 +108,8 @@ boolean devparm = false; // started game with -devparm boolean singletics = false; // timedemo boolean lastdraw = false; +static void D_CheckRendererState(void); + postimg_t postimgtype = postimg_none; INT32 postimgparam; postimg_t postimgtype2 = postimg_none; @@ -212,6 +214,7 @@ INT16 wipetypepost = -1; static void D_Display(void) { + INT32 setrenderstillneeded = 0; boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; @@ -222,11 +225,38 @@ static void D_Display(void) if (nodrawers) return; // for comparative timing/profiling - // check for change of screen size (video mode) - if (setmodeneeded && !wipe) - SCR_SetMode(); // change video mode + // Lactozilla: Switching renderers works by checking + // if the game has to do it right when the frame + // needs to render. If so, five things will happen: + // 1. Interface functions will be called so + // that switching to OpenGL creates a + // GL context, and switching to Software + // allocates screen buffers. + // 2. Software will set drawer functions, + // and OpenGL will load textures and + // create plane polygons, if necessary. + // 3. Functions related to switching video + // modes (resolution) are called. + // 4. Patch data is freed from memory, + // and recached if necessary. + // 5. The frame is ready to be drawn! - if (vid.recalc) + // stop movie if needs to change renderer + if (setrenderneeded && (moviemode == MM_APNG)) + M_StopMovie(); + + // check for change of renderer or screen size (video mode) + if ((setrenderneeded || setmodeneeded) && !wipe) + { + if (setrenderneeded) + { + CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded); + setrenderstillneeded = setrenderneeded; + } + SCR_SetMode(); // change video mode + } + + if (vid.recalc || setrenderstillneeded) { SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() #ifdef HWRENDER @@ -237,12 +267,15 @@ static void D_Display(void) } // change the view size if needed - if (setsizeneeded) + if (setsizeneeded || setrenderstillneeded) { R_ExecuteSetViewSize(); forcerefresh = true; // force background redraw } + // Lactozilla: Renderer switching + D_CheckRendererState(); + // draw buffered stuff to screen // Used only by linux GGI version I_UpdateNoBlit(); @@ -457,7 +490,7 @@ static void D_Display(void) py = 4; else py = viewwindowy + 4; - patch = W_CachePatchName("M_PAUSE", PU_CACHE); + patch = W_CachePatchName("M_PAUSE", PU_PATCH); V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch); #else INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2)); @@ -557,6 +590,25 @@ static void D_Display(void) I_FinishUpdate(); // page flip or blit buffer } + + needpatchflush = false; + needpatchrecache = false; +} + +// Lactozilla: Check the renderer's state +// after a possible renderer switch. +void D_CheckRendererState(void) +{ + // flush all patches from memory + // (also frees memory tagged with PU_CACHE) + // (which are not necessarily patches but I don't care) + if (needpatchflush) + Z_FlushCachedPatches(); + + // some patches have been freed, + // so cache them again + if (needpatchrecache) + R_ReloadHUDGraphics(); } // ========================================================================= @@ -600,8 +652,7 @@ void D_SRB2Loop(void) // hack to start on a nice clear console screen. COM_ImmedExecute("cls;version"); - if (rendermode == render_soft) - V_DrawScaledPatch(0, 0, 0, (patch_t *)W_CacheLumpNum(W_GetNumForName("CONSBACK"), PU_CACHE)); + V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE)); I_FinishUpdate(); // page flip or blit buffer for (;;) @@ -715,7 +766,7 @@ void D_StartTitle(void) if (netgame) { - if (gametype == GT_COOP) + if (gametyperules & GTR_CAMPAIGN) { G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat @@ -1118,26 +1169,6 @@ void D_SRB2Main(void) if (M_CheckParm("-server") || dedicated) netgame = server = true; - if (M_CheckParm("-warp") && M_IsNextParm()) - { - const char *word = M_GetNextParm(); - char ch; // use this with sscanf to catch non-digits with - if (fastncmp(word, "MAP", 3)) // MAPxx name - pstartmap = M_MapNumber(word[3], word[4]); - else if (sscanf(word, "%d%c", &pstartmap, &ch) != 1) // a plain number - I_Error("Cannot warp to map %s (invalid map name)\n", word); - // Don't check if lump exists just yet because the wads haven't been loaded! - // Just do a basic range check here. - if (pstartmap < 1 || pstartmap > NUMMAPS) - I_Error("Cannot warp to map %d (out of range)\n", pstartmap); - else - { - if (!M_CheckParm("-server")) - G_SetGameModified(true); - autostart = true; - } - } - CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n"); Z_Init(); @@ -1194,6 +1225,20 @@ void D_SRB2Main(void) mainwadstally = packetsizetally; // technically not accurate atm, remember to port the two-stage -file process from kart in 2.2.x + if (M_CheckParm("-warp") && M_IsNextParm()) + { + const char *word = M_GetNextParm(); + pstartmap = G_FindMapByNameOrCode(word, 0); + if (! pstartmap) + I_Error("Cannot find a map remotely named '%s'\n", word); + else + { + if (!M_CheckParm("-server")) + G_SetGameModified(true); + autostart = true; + } + } + cht_Init(); //---------------------------------------------------- READY SCREEN @@ -1239,6 +1284,16 @@ void D_SRB2Main(void) // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); + // Lactozilla: Does the render mode need to change? + if ((setrenderneeded != 0) && (setrenderneeded != rendermode)) + { + needpatchflush = true; + needpatchrecache = true; + VID_CheckRenderer(); + SCR_ChangeRendererCVars(setrenderneeded); + } + D_CheckRendererState(); + wipegamestate = gamestate; savedata.lives = 0; // flag this as not-used diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4e14ca25f..19e1f1dad 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -848,6 +848,10 @@ void D_RegisterClientCommands(void) // screen.c CV_RegisterVar(&cv_fullscreen); CV_RegisterVar(&cv_renderview); + CV_RegisterVar(&cv_renderer); +#ifdef HWRENDER + CV_RegisterVar(&cv_newrenderer); +#endif CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_height); @@ -1809,18 +1813,15 @@ static void Command_Map_f(void) boolean newresetplayers; boolean mustmodifygame; - boolean usemapcode = false; INT32 newmapnum; char * mapname; - size_t mapnamelen; char *realmapname = NULL; INT32 newgametype = gametype; INT32 d; - char *p; if (client && !IsPlayerAdmin(consoleplayer)) { @@ -1880,43 +1881,8 @@ static void Command_Map_f(void) } mapname = ConcatCommandArgv(1, first_option); - mapnamelen = strlen(mapname); - if (mapnamelen == 2)/* maybe two digit code */ - { - if (( newmapnum = M_MapNumber(mapname[0], mapname[1]) )) - usemapcode = true; - } - else if (mapnamelen == 5 && strnicmp(mapname, "MAP", 3) == 0) - { - if (( newmapnum = M_MapNumber(mapname[3], mapname[4]) ) == 0) - { - CONS_Alert(CONS_ERROR, M_GetText("Invalid map code '%s'.\n"), mapname); - Z_Free(mapname); - return; - } - usemapcode = true; - } - - if (!usemapcode) - { - /* Now detect map number in base 10, which no one asked for. */ - newmapnum = strtol(mapname, &p, 10); - if (*p == '\0')/* we got it */ - { - if (newmapnum < 1 || newmapnum > NUMMAPS) - { - CONS_Alert(CONS_ERROR, M_GetText("Invalid map number %d.\n"), newmapnum); - Z_Free(mapname); - return; - } - usemapcode = true; - } - else - { - newmapnum = G_FindMap(mapname, &realmapname, NULL, NULL); - } - } + newmapnum = G_FindMapByNameOrCode(mapname, &realmapname); if (newmapnum == 0) { @@ -1925,11 +1891,6 @@ static void Command_Map_f(void) return; } - if (usemapcode) - { - realmapname = G_BuildMapTitle(newmapnum); - } - if (mustmodifygame && option_force) { G_SetGameModified(false); @@ -2209,6 +2170,8 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) else S_ResumeAudio(); } + + I_UpdateMouseGrab(); } // Command for stuck characters in netgames, griefing, etc. @@ -3745,7 +3708,7 @@ static void CoopStarposts_OnChange(void) { INT32 i; - if (!(netgame || multiplayer) || gametype != GT_COOP) + if (!(netgame || multiplayer) || !G_GametypeUsesCoopStarposts()) return; switch (cv_coopstarposts.value) @@ -3800,7 +3763,7 @@ static void CoopLives_OnChange(void) { INT32 i; - if (!(netgame || multiplayer) || gametype != GT_COOP) + if (!(netgame || multiplayer) || !G_GametypeUsesCoopLives()) return; switch (cv_cooplives.value) diff --git a/src/dehacked.c b/src/dehacked.c index 4c90211cc..161a41c46 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4804,11 +4804,13 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) if (introchanged) { menuactive = false; + I_UpdateMouseGrab(); COM_BufAddText("playintro"); } else if (titlechanged) { menuactive = false; + I_UpdateMouseGrab(); COM_BufAddText("exitgame"); // Command_ExitGame_f() but delayed } } @@ -8904,32 +8906,35 @@ static const char *const GAMETYPERULE_LIST[] = { "CAMPAIGN", "RINGSLINGER", "SPECTATORS", - "FRIENDLYFIRE", "LIVES", "TEAMS", + "FIRSTPERSON", + "POWERSTONES", + "TEAMFLAGS", + "FRIENDLY", + "SPECIALSTAGES", + "EMERALDTOKENS", + "EMERALDHUNT", "RACE", "TAG", "POINTLIMIT", "TIMELIMIT", - "HIDETIME", + "OVERTIME", + "HURTMESSAGES", + "FRIENDLYFIRE", + "STARTCOUNTDOWN", "HIDEFROZEN", "BLINDFOLDED", - "FIRSTPERSON", - "MATCHEMERALDS", - "TEAMFLAGS", + "RESPAWNDELAY", "PITYSHIELD", "DEATHPENALTY", "NOSPECTATORSPAWN", "DEATHMATCHSTARTS", - "SPECIALSTAGES", - "EMERALDTOKENS", - "EMERALDHUNT", + "SPAWNINVUL", "SPAWNENEMIES", "ALLOWEXIT", "NOTITLECARD", - "OVERTIME", - "HURTMESSAGES", - "SPAWNINVUL", + "CUTSCENES", NULL }; @@ -9746,6 +9751,7 @@ struct { {"CV_HIDEN",CV_HIDEN}, {"CV_HIDDEN",CV_HIDEN}, {"CV_CHEAT",CV_CHEAT}, + {"CV_NOLUA",CV_NOLUA}, // v_video flags {"V_NOSCALEPATCH",V_NOSCALEPATCH}, diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c index 56570b7bf..02c7a842b 100644 --- a/src/djgppdos/i_video.c +++ b/src/djgppdos/i_video.c @@ -338,3 +338,8 @@ void I_StartupGraphics(void) graphics_started = true; } + +void I_StartupHardwareGraphics(void) +{ + // oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y +} diff --git a/src/djgppdos/vid_vesa.c b/src/djgppdos/vid_vesa.c index ec7b8b886..c8ce7dae5 100644 --- a/src/djgppdos/vid_vesa.c +++ b/src/djgppdos/vid_vesa.c @@ -378,6 +378,11 @@ INT32 VID_SetMode (INT32 modenum) //, UINT8 *palette) return 1; } +void VID_CheckRenderer(void) +{ + // .............. +} + // converts a segm:offs 32bit pair to a 32bit flat ptr diff --git a/src/doomdef.h b/src/doomdef.h index 0d673a426..0a98c874a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -130,6 +130,9 @@ extern FILE *logstream; extern char logfilename[1024]; #endif +/* A mod name to further distinguish versions. */ +#define SRB2APPLICATION "SRB2" + //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 #ifdef DEVELOP #define VERSION 0 // Game version @@ -626,6 +629,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +/// Cache patches in Lua in a way that renderer switching will work flawlessly. +//#define LUA_PATCH_SAFETY + /// Sprite rotation #define ROTSPRITE #define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) diff --git a/src/doomstat.h b/src/doomstat.h index b7bb7a362..6d1d6eb36 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -397,32 +397,35 @@ enum GameTypeRules GTR_CAMPAIGN = 1, // Linear Co-op map progression, don't allow random maps GTR_RINGSLINGER = 1<<1, // Outside of Co-op, Competition, and Race (overriden by cv_ringslinger) GTR_SPECTATORS = 1<<2, // Outside of Co-op, Competition, and Race - GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire - GTR_LIVES = 1<<4, // Co-op and Competition - GTR_TEAMS = 1<<5, // Team Match, CTF - GTR_RACE = 1<<6, // Race and Competition - GTR_TAG = 1<<7, // Tag and Hide and Seek - GTR_POINTLIMIT = 1<<8, // Ringslinger point limit - GTR_TIMELIMIT = 1<<9, // Ringslinger time limit - GTR_HIDETIME = 1<<10, // Hide time (Tag and Hide and Seek) - GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag) - GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek) - GTR_FIRSTPERSON = 1<<13, // First person camera - GTR_MATCHEMERALDS = 1<<14, // Ringslinger emeralds (Match and CTF) - GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF) - GTR_PITYSHIELD = 1<<16, // Award pity shield - GTR_DEATHPENALTY = 1<<17, // Death score penalty - GTR_NOSPECTATORSPAWN = 1<<18, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators - GTR_DEATHMATCHSTARTS = 1<<19, // Use deathmatch starts - GTR_SPECIALSTAGES = 1<<20, // Allow special stages - GTR_EMERALDTOKENS = 1<<21, // Spawn emerald tokens - GTR_EMERALDHUNT = 1<<22, // Emerald Hunt - GTR_SPAWNENEMIES = 1<<23, // Spawn enemies - GTR_ALLOWEXIT = 1<<24, // Allow exit sectors - GTR_NOTITLECARD = 1<<25, // Don't show the title card - GTR_OVERTIME = 1<<26, // Allow overtime - GTR_HURTMESSAGES = 1<<27, // Hit and death messages - GTR_SPAWNINVUL = 1<<28, // Babysitting deterrent + GTR_LIVES = 1<<3, // Co-op and Competition + GTR_TEAMS = 1<<4, // Team Match, CTF + GTR_FIRSTPERSON = 1<<5, // First person camera + GTR_POWERSTONES = 1<<6, // Power stones (Match and CTF) + GTR_TEAMFLAGS = 1<<7, // Gametype has team flags (CTF) + GTR_FRIENDLY = 1<<8, // Co-op + GTR_SPECIALSTAGES = 1<<9, // Allow special stages + GTR_EMERALDTOKENS = 1<<10, // Spawn emerald tokens + GTR_EMERALDHUNT = 1<<11, // Emerald Hunt + GTR_RACE = 1<<12, // Race and Competition + GTR_TAG = 1<<13, // Tag and Hide and Seek + GTR_POINTLIMIT = 1<<14, // Ringslinger point limit + GTR_TIMELIMIT = 1<<15, // Ringslinger time limit + GTR_OVERTIME = 1<<16, // Allow overtime + GTR_HURTMESSAGES = 1<<17, // Hit and death messages + GTR_FRIENDLYFIRE = 1<<18, // Always allow friendly fire + GTR_STARTCOUNTDOWN = 1<<19, // Hide time countdown (Tag and Hide and Seek) + GTR_HIDEFROZEN = 1<<20, // Frozen after hide time (Hide and Seek, but not Tag) + GTR_BLINDFOLDED = 1<<21, // Blindfolded view (Tag and Hide and Seek) + GTR_RESPAWNDELAY = 1<<22, // Respawn delay + GTR_PITYSHIELD = 1<<23, // Award pity shield + GTR_DEATHPENALTY = 1<<24, // Death score penalty + GTR_NOSPECTATORSPAWN = 1<<25, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators + GTR_DEATHMATCHSTARTS = 1<<26, // Use deathmatch starts + GTR_SPAWNINVUL = 1<<27, // Babysitting deterrent + GTR_SPAWNENEMIES = 1<<28, // Spawn enemies + GTR_ALLOWEXIT = 1<<29, // Allow exit sectors + GTR_NOTITLECARD = 1<<30, // Don't show the title card + GTR_CUTSCENES = 1<<31, // Play cutscenes, ending, credits, and evaluation }; // String names for gametypes diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index a3fe3077c..5c0f7eb99 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -150,6 +150,8 @@ void I_GetJoystick2Events(void){} void I_GetMouseEvents(void){} +void I_UpdateMouseGrab(void){} + char *I_GetEnv(const char *name) { (void)name; diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index e167e833f..fafeee000 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -11,6 +11,7 @@ boolean allow_fullscreen = false; consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void I_StartupGraphics(void){} +void I_StartupHardwareGraphics(void){} void I_ShutdownGraphics(void){} @@ -39,6 +40,11 @@ INT32 VID_SetMode(INT32 modenum) return 0; } +void VID_CheckRenderer(void) +{ + // .............. +} + const char *VID_GetModeName(INT32 modenum) { (void)modenum; diff --git a/src/f_finale.c b/src/f_finale.c index 124fedc28..317a57f3d 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -530,78 +530,78 @@ static void F_IntroDrawScene(void) case 0: break; case 1: - background = W_CachePatchName("INTRO1", PU_CACHE); + background = W_CachePatchName("INTRO1", PU_PATCH); break; case 2: - background = W_CachePatchName("INTRO2", PU_CACHE); + background = W_CachePatchName("INTRO2", PU_PATCH); break; case 3: - background = W_CachePatchName("INTRO3", PU_CACHE); + background = W_CachePatchName("INTRO3", PU_PATCH); break; case 4: - background = W_CachePatchName("INTRO4", PU_CACHE); + background = W_CachePatchName("INTRO4", PU_PATCH); break; case 5: if (intro_curtime >= 5*TICRATE) - background = W_CachePatchName("RADAR", PU_CACHE); + background = W_CachePatchName("RADAR", PU_PATCH); else - background = W_CachePatchName("DRAT", PU_CACHE); + background = W_CachePatchName("DRAT", PU_PATCH); break; case 6: - background = W_CachePatchName("INTRO6", PU_CACHE); + background = W_CachePatchName("INTRO6", PU_PATCH); cx = 180; cy = 8; break; case 7: { if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2)) - background = W_CachePatchName("SGRASS5", PU_CACHE); + background = W_CachePatchName("SGRASS5", PU_PATCH); else if (intro_curtime >= 7*TICRATE + (TICRATE/7)) - background = W_CachePatchName("SGRASS4", PU_CACHE); + background = W_CachePatchName("SGRASS4", PU_PATCH); else if (intro_curtime >= 7*TICRATE) - background = W_CachePatchName("SGRASS3", PU_CACHE); + background = W_CachePatchName("SGRASS3", PU_PATCH); else if (intro_curtime >= 6*TICRATE) - background = W_CachePatchName("SGRASS2", PU_CACHE); + background = W_CachePatchName("SGRASS2", PU_PATCH); else - background = W_CachePatchName("SGRASS1", PU_CACHE); + background = W_CachePatchName("SGRASS1", PU_PATCH); break; } case 8: - background = W_CachePatchName("WATCHING", PU_CACHE); + background = W_CachePatchName("WATCHING", PU_PATCH); break; case 9: - background = W_CachePatchName("ZOOMING", PU_CACHE); + background = W_CachePatchName("ZOOMING", PU_PATCH); break; case 10: break; case 11: - background = W_CachePatchName("INTRO5", PU_CACHE); + background = W_CachePatchName("INTRO5", PU_PATCH); break; case 12: - background = W_CachePatchName("REVENGE", PU_CACHE); + background = W_CachePatchName("REVENGE", PU_PATCH); cx = 208; cy = 8; break; case 13: - background = W_CachePatchName("CONFRONT", PU_CACHE); + background = W_CachePatchName("CONFRONT", PU_PATCH); cy += 48; break; case 14: - background = W_CachePatchName("TAILSSAD", PU_CACHE); + background = W_CachePatchName("TAILSSAD", PU_PATCH); bgxoffs = 144; cx = 8; cy = 8; break; case 15: if (intro_curtime >= 7*TICRATE) - background = W_CachePatchName("SONICDO2", PU_CACHE); + background = W_CachePatchName("SONICDO2", PU_PATCH); else - background = W_CachePatchName("SONICDO1", PU_CACHE); + background = W_CachePatchName("SONICDO1", PU_PATCH); cx = 224; cy = 8; break; case 16: - background = W_CachePatchName("INTRO7", PU_CACHE); + background = W_CachePatchName("INTRO7", PU_PATCH); break; default: break; @@ -631,30 +631,30 @@ static void F_IntroDrawScene(void) S_ChangeMusicInternal("_stjr", false); x = (BASEVIDWIDTH< 6) { - V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH2", PU_CACHE)), aspect); + V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH2", PU_PATCH)), aspect); W_UnlockCachedPatch(patch); } if (finalecount > 10) { - V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH3", PU_CACHE)), aspect); + V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH3", PU_PATCH)), aspect); W_UnlockCachedPatch(patch); } if (finalecount > 14) { - V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH4", PU_CACHE)), aspect); + V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH4", PU_PATCH)), aspect); W_UnlockCachedPatch(patch); } } else if (finalecount-30 < 20) { // Big eggy - background = W_CachePatchName("FEEDIN", PU_CACHE); + background = W_CachePatchName("FEEDIN", PU_PATCH); x = (BASEVIDWIDTH< 4*TICRATE) { // Door is being raised! int ftime = (finalecount-TICRATE/2-4*TICRATE); y -= FixedDiv((ftime*ftime)< 5*TICRATE && timetonext < 6*TICRATE) { if (!(finalecount & 3)) - background = W_CachePatchName("BRITEGG1", PU_CACHE); + background = W_CachePatchName("BRITEGG1", PU_PATCH); else - background = W_CachePatchName("DARKEGG1", PU_CACHE); + background = W_CachePatchName("DARKEGG1", PU_PATCH); V_DrawSmallScaledPatch(0, 0, 0, background); } else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE) { if (!(finalecount & 3)) - background = W_CachePatchName("BRITEGG2", PU_CACHE); + background = W_CachePatchName("BRITEGG2", PU_PATCH); else - background = W_CachePatchName("DARKEGG2", PU_CACHE); + background = W_CachePatchName("DARKEGG2", PU_PATCH); V_DrawSmallScaledPatch(0, 0, 0, background); } else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE) { if (!(finalecount & 3)) - background = W_CachePatchName("BRITEGG3", PU_CACHE); + background = W_CachePatchName("BRITEGG3", PU_PATCH); else - background = W_CachePatchName("DARKEGG3", PU_CACHE); + background = W_CachePatchName("DARKEGG3", PU_PATCH); V_DrawSmallScaledPatch(0, 0, 0, background); } @@ -768,79 +768,79 @@ static void F_IntroDrawScene(void) knucklesx += sonicx; sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3); - V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_CACHE))); + V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH))); V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch); W_UnlockCachedPatch(patch); - V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_CACHE))); + V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH))); V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch); W_UnlockCachedPatch(patch); if (finalecount & 1) { // Sonic - V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_CACHE))); + V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH))); W_UnlockCachedPatch(patch); // Appendages if (finalecount & 2) { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_CACHE))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_CACHE))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); W_UnlockCachedPatch(patch); } else { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_CACHE))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_CACHE))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); W_UnlockCachedPatch(patch); } // Tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_CACHE))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH))); W_UnlockCachedPatch(patch); // Knuckles - V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_CACHE))); + V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH))); W_UnlockCachedPatch(patch); } else { // Sonic - V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_CACHE))); + V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH))); W_UnlockCachedPatch(patch); // Appendages if (finalecount & 2) { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_CACHE))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_CACHE))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); W_UnlockCachedPatch(patch); } else { // Sonic's feet - V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_CACHE))); + V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH))); W_UnlockCachedPatch(patch); // Tails' tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_CACHE))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); W_UnlockCachedPatch(patch); } // Tails - V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_CACHE))); + V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH))); W_UnlockCachedPatch(patch); // Knuckles - V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_CACHE))); + V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH))); W_UnlockCachedPatch(patch); } @@ -873,8 +873,8 @@ static void F_IntroDrawScene(void) y += (30*(FRACUNIT-scale)); } - rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_LEVEL); - glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_LEVEL); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH); + glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH); if (worktics >= 5) trans = (worktics-5)>>1; @@ -988,7 +988,7 @@ void F_IntroDrawer(void) { if (intro_scenenum == 5 && intro_curtime == 5*TICRATE) { - patch_t *radar = W_CachePatchName("RADAR", PU_CACHE); + patch_t *radar = W_CachePatchName("RADAR", PU_PATCH); F_WipeStartScreen(); F_WipeColorFill(31); @@ -1001,7 +1001,7 @@ void F_IntroDrawer(void) } else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here { - patch_t *grass = W_CachePatchName("SGRASS2", PU_CACHE); + patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH); F_WipeStartScreen(); F_WipeColorFill(31); @@ -1014,7 +1014,7 @@ void F_IntroDrawer(void) } /*else if (intro_scenenum == 12 && intro_curtime == 7*TICRATE) { - patch_t *confront = W_CachePatchName("CONFRONT", PU_CACHE); + patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH); F_WipeStartScreen(); F_WipeColorFill(31); @@ -1027,7 +1027,7 @@ void F_IntroDrawer(void) }*/ if (intro_scenenum == 15 && intro_curtime == 7*TICRATE) { - patch_t *sdo = W_CachePatchName("SONICDO2", PU_CACHE); + patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH); F_WipeStartScreen(); F_WipeColorFill(31); @@ -1359,14 +1359,14 @@ void F_CreditDrawer(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Zig Zagz - V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_CACHE)); - V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_CACHE)); - V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_CACHE)); - V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_CACHE)); + V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); + V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); + V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); + V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); // Draw background pictures first for (i = 0; credits_pics[i].patch; i++) - V_DrawSciencePatch(credits_pics[i].x<>1); + V_DrawSciencePatch(credits_pics[i].x<>1); // Dim the background V_DrawFadeScreen(0xFF00, 16); @@ -1574,14 +1574,14 @@ void F_GameEvaluationDrawer(void) if (goodending) { - rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_LEVEL); - glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_LEVEL); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH); + glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH); x -= FRACUNIT; } else { rockpat = W_CachePatchName("ROID0000", PU_LEVEL); - glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_LEVEL); + glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH); } if (finalecount >= 5) @@ -1613,20 +1613,20 @@ void F_GameEvaluationDrawer(void) // if j == 0 - alternate between 0 and 1 // 1 - 1 and 2 // 2 - 2 and not rendered - V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_LEVEL), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE)); + V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE)); } j--; } } else { - patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_LEVEL); + patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH); V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]); if (trans < 10) V_DrawFixedPatch(x, y, scale, trans< (XTRA_ENDING+2)) + { + sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + // character head, skin specific + sprframe = &sprdef->spriteframes[XTRA_ENDING]; + endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + sprframe = &sprdef->spriteframes[XTRA_ENDING+1]; + endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + sprframe = &sprdef->spriteframes[XTRA_ENDING+2]; + endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + } + else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) + { + endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH); + endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH); + endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH); + } + + endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH); + } + else + { + // eggman, skin nonspecific + endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH); + endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH); + endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH); + + endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL); + } +} + +static void F_CacheGoodEnding(void) +{ + endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH); + endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH); + + endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH); + endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH); + + endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH); +} + void F_StartEnding(void) { G_SetGamestate(GS_ENDING); @@ -1768,7 +1845,7 @@ void F_StartEnding(void) gameaction = ga_nothing; paused = false; CON_ToggleOff(); - S_StopMusic(); + S_StopMusic(); // todo: placeholder S_StopSounds(); finalecount = -10; // what? this totally isn't a hack. why are you asking? @@ -1776,68 +1853,7 @@ void F_StartEnding(void) memset(sparkloffs, 0, sizeof(INT32)*3*2); sparklloop = 0; - endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_LEVEL); - - endegrk[0] = W_CachePatchName("ENDEGRK0", PU_LEVEL); - endegrk[1] = W_CachePatchName("ENDEGRK1", PU_LEVEL); - - endglow[0] = W_CachePatchName("ENDGLOW0", PU_LEVEL); - endglow[1] = W_CachePatchName("ENDGLOW1", PU_LEVEL); - - endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_LEVEL); - endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_LEVEL); - endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_LEVEL); - - endspkl[0] = W_CachePatchName("ENDSPKL0", PU_LEVEL); - endspkl[1] = W_CachePatchName("ENDSPKL1", PU_LEVEL); - endspkl[2] = W_CachePatchName("ENDSPKL2", PU_LEVEL); - - endxpld[0] = W_CachePatchName("ENDXPLD0", PU_LEVEL); - endxpld[1] = W_CachePatchName("ENDXPLD1", PU_LEVEL); - endxpld[2] = W_CachePatchName("ENDXPLD2", PU_LEVEL); - endxpld[3] = W_CachePatchName("ENDXPLD3", PU_LEVEL); - - endescp[0] = W_CachePatchName("ENDESCP0", PU_LEVEL); - endescp[1] = W_CachePatchName("ENDESCP1", PU_LEVEL); - endescp[2] = W_CachePatchName("ENDESCP2", PU_LEVEL); - endescp[3] = W_CachePatchName("ENDESCP3", PU_LEVEL); - endescp[4] = W_CachePatchName("ENDESCP4", PU_LEVEL); - - // so we only need to check once - if ((goodending = ALL7EMERALDS(emeralds))) - { - UINT8 skinnum = players[consoleplayer].skin; - spritedef_t *sprdef; - spriteframe_t *sprframe; - if (skins[skinnum].sprites[SPR2_XTRA].numframes > (XTRA_ENDING+2)) - { - sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - // character head, skin specific - sprframe = &sprdef->spriteframes[XTRA_ENDING]; - endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); - sprframe = &sprdef->spriteframes[XTRA_ENDING+1]; - endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); - sprframe = &sprdef->spriteframes[XTRA_ENDING+2]; - endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); - } - else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) - { - endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_LEVEL); - endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_LEVEL); - endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_LEVEL); - } - - endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_LEVEL); - } - else - { - // eggman, skin nonspecific - endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL); - endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL); - endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL); - - endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL); - } + F_CacheEnding(); } void F_EndingTicker(void) @@ -1853,15 +1869,7 @@ void F_EndingTicker(void) S_ChangeMusicInternal((goodending ? "_endg" : "_endb"), false); if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets - { - endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL); - endegrk[1] = W_CachePatchName("ENDEGRK3", PU_LEVEL); - - endglow[0] = W_CachePatchName("ENDGLOW2", PU_LEVEL); - endglow[1] = W_CachePatchName("ENDGLOW3", PU_LEVEL); - - endxpld[0] = W_CachePatchName("ENDEGRK4", PU_LEVEL); - } + F_CacheGoodEnding(); if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again { @@ -1880,10 +1888,17 @@ void F_EndingDrawer(void) INT32 x, y, i, j, parallaxticker; patch_t *rockpat; + if (needpatchrecache) + { + F_CacheEnding(); + if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets + F_CacheGoodEnding(); + } + if (!goodending || finalecount < INFLECTIONPOINT) - rockpat = W_CachePatchName("ROID0000", PU_LEVEL); + rockpat = W_CachePatchName("ROID0000", PU_PATCH); else - rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_LEVEL); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); @@ -2367,11 +2382,11 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname) if (!scrollxspeed && !scrollyspeed) { - V_DrawPatchFill(W_CachePatchName(patchname, PU_CACHE)); + V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH)); return; } - pat = W_CachePatchName(patchname, PU_CACHE); + pat = W_CachePatchName(patchname, PU_PATCH); patwidth = SHORT(pat->width); patheight = SHORT(pat->height); @@ -2432,6 +2447,45 @@ else if (strlen(name) <= 6) \ else \ arr[0] = 0; +static void F_CacheTitleScreen(void) +{ + switch(curttmode) + { + case TTMODE_OLD: + case TTMODE_NONE: + ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL); + ttwing = W_CachePatchName("TTWING", PU_LEVEL); + ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL); + ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL); + ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL); + ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL); + ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL); + ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL); + ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL); + ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL); + ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL); + ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL); + ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL); + ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL); + ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL); + break; + + // don't load alacroix gfx yet; we do that upon first draw. + case TTMODE_ALACROIX: + break; + + case TTMODE_USER: + { + UINT16 i; + lumpnum_t lumpnum; + char lumpname[9]; + + LOADTTGFX(ttuser, curttname, TTMAX_USER) + break; + } + } +} + void F_StartTitleScreen(void) { if (menupres[MN_MAIN].musname[0]) @@ -2528,41 +2582,7 @@ void F_StartTitleScreen(void) demoDelayLeft = demoDelayTime; demoIdleLeft = demoIdleTime; - switch(curttmode) - { - case TTMODE_OLD: - case TTMODE_NONE: - ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL); - ttwing = W_CachePatchName("TTWING", PU_LEVEL); - ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL); - ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL); - ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL); - ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL); - ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL); - ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL); - ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL); - ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL); - ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL); - ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL); - ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL); - ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL); - ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL); - break; - - // don't load alacroix gfx yet; we do that upon first draw. - case TTMODE_ALACROIX: - break; - - case TTMODE_USER: - { - UINT16 i; - lumpnum_t lumpnum; - char lumpname[9]; - - LOADTTGFX(ttuser, curttname, TTMAX_USER) - break; - } - } + F_CacheTitleScreen(); } static void F_UnloadAlacroixGraphics(SINT8 oldttscale) @@ -2711,6 +2731,9 @@ void F_TitleScreenDrawer(void) if (modeattacking) return; // We likely came here from retrying. Don't do a damn thing. + if (needpatchrecache && (curttmode != TTMODE_ALACROIX)) + F_CacheTitleScreen(); + // Draw that sky! if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); @@ -2734,6 +2757,12 @@ void F_TitleScreenDrawer(void) return; #endif + if (needpatchrecache && (curttmode == TTMODE_ALACROIX)) + { + ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0; + F_LoadAlacroixGraphics(activettscale); + } + switch(curttmode) { case TTMODE_OLD: @@ -3681,7 +3710,7 @@ void F_ContinueDrawer(void) V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?"); // Two stars... - patch = W_CachePatchName("CONTSTAR", PU_CACHE); + patch = W_CachePatchName("CONTSTAR", PU_PATCH); V_DrawScaledPatch(x-32, 160, 0, patch); V_DrawScaledPatch(x+32, 160, 0, patch); @@ -3689,14 +3718,14 @@ void F_ContinueDrawer(void) if (timeleft > 9) { numbuf[7] = '1'; - V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); numbuf[7] = '0'; - V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); } else { numbuf[7] = '0'+timeleft; - V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_CACHE)); + V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); } // Draw the continue markers! Show continues. @@ -3723,7 +3752,7 @@ void F_ContinueDrawer(void) } // Spotlight - V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_CACHE)); + V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH)); // warping laser if (continuetime) @@ -3760,7 +3789,7 @@ void F_ContinueDrawer(void) #define drawchar(dx, dy, n) {\ sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\ sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\ - patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_CACHE);\ + patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH);\ V_DrawFixedPatch((dx), (dy), FRACUNIT, (sprframe->flip & (1<scene[scenenum].pichires[picnum]) V_DrawSmallScaledPatch(picxpos, picypos, 0, - W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE)); + W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); else V_DrawScaledPatch(picxpos,picypos, 0, - W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE)); + W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); } if (dofadenow && rendermode != render_none) @@ -4513,10 +4542,10 @@ void F_TextPromptDrawer(void) { if (textprompts[cutnum]->page[scenenum].pichires[picnum]) V_DrawSmallScaledPatch(picxpos, picypos, 0, - W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_CACHE)); + W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); else V_DrawScaledPatch(picxpos,picypos, 0, - W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_CACHE)); + W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); } // Draw background @@ -4526,7 +4555,7 @@ void F_TextPromptDrawer(void) if (iconlump != LUMPERROR) { INT32 iconx, icony, scale, scaledsize; - patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_CACHE); + patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH); // scale and center if (patch->width > patch->height) diff --git a/src/g_game.c b/src/g_game.c index efb580f21..b4f5d4c64 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1718,6 +1718,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver B_BuildTiccmd(player, cmd); } + B_HandleFlightIndicator(player); } if (cv_analog2.value) { @@ -1839,6 +1840,7 @@ void G_DoLoadLevel(boolean resetplayer) titlemapinaction = TITLEMAP_OFF; G_SetGamestate(GS_LEVEL); + I_UpdateMouseGrab(); for (i = 0; i < MAXPLAYERS; i++) { @@ -1854,8 +1856,7 @@ void G_DoLoadLevel(boolean resetplayer) return; } - if (!resetplayer) - P_FindEmerald(); + P_FindEmerald(); displayplayer = consoleplayer; // view the guy you are playing if (!splitscreen && !botingame) @@ -2689,8 +2690,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- DM/Tag/CTF-spectator/etc -- // Order: DM->CTF->Coop - else if ((gametyperules & GTR_DEATHMATCHSTARTS) || gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF - || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) + else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT)) { if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start && !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start @@ -2891,11 +2891,11 @@ void G_DoReborn(INT32 playernum) if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP)) resetlevel = true; - else if (gametype == GT_COOP && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) + else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap)) { boolean notgameover = true; - if (cv_cooplives.value != 0 && player->lives <= 0) // consider game over first + if (G_GametypeUsesCoopLives() && (cv_cooplives.value != 0 && player->lives <= 0)) // consider game over first { for (i = 0; i < MAXPLAYERS; i++) { @@ -2930,7 +2930,7 @@ void G_DoReborn(INT32 playernum) } } - if (notgameover && cv_coopstarposts.value == 2) + if (G_GametypeUsesCoopStarposts() && (notgameover && cv_coopstarposts.value == 2)) { for (i = 0; i < MAXPLAYERS; i++) { @@ -3006,7 +3006,7 @@ void G_DoReborn(INT32 playernum) } // restore time in netgame (see also p_setup.c) - if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2) { // is this a hack? maybe tic_t maxstarposttime = 0; @@ -3077,7 +3077,7 @@ void G_AddPlayer(INT32 playernum) if (!players[i].exiting) notexiting++; - if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum))) + if (!(cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (p->starpostnum < players[i].starpostnum))) continue; p->starpostscale = players[i].starpostscale; @@ -3194,24 +3194,24 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] = UINT32 gametypedefaultrules[NUMGAMETYPES] = { // Co-op - GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, + GTR_CAMPAIGN|GTR_LIVES|GTR_FRIENDLY|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES|GTR_CUTSCENES, // Competition GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Race GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT, // Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD|GTR_DEATHPENALTY, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY, // Team Match - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, // Tag - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // Hide and Seek - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY, // CTF - GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD, + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD, }; // @@ -3252,50 +3252,68 @@ INT16 G_AddGametype(UINT32 rules) // void G_AddGametypeConstant(INT16 gtype, const char *newgtconst) { - char *gtconst = Z_Malloc(strlen(newgtconst) + 3, PU_STATIC, NULL); - // Copy GT_ and the gametype name. - strcpy(gtconst, "GT_"); - strcat(gtconst, newgtconst); + size_t r = 0; // read + size_t w = 0; // write + char *gtconst = Z_Calloc(strlen(newgtconst) + 3, PU_STATIC, NULL); + char *tmpconst = Z_Calloc(strlen(newgtconst), PU_STATIC, NULL); + + // Copy the gametype name. + strcpy(tmpconst, newgtconst); + // Make uppercase. - strupr(gtconst); - // Remove characters. -#define REMOVECHAR(chr) \ - { \ - char *chrfind = strchr(gtconst, chr); \ - while (chrfind) \ - { \ - *chrfind = '_'; \ - chrfind = strchr(chrfind, chr); \ - } \ + strupr(tmpconst); + + // Prepare to write the new constant string now. + strcpy(gtconst, "GT_"); + + // Remove characters that will not be allowed in the constant string. + for (; r < strlen(tmpconst); r++) + { + boolean writechar = true; + char rc = tmpconst[r]; + switch (rc) + { + // Space, at sign and question mark + case ' ': + case '@': + case '?': + // Used for operations + case '+': + case '-': + case '*': + case '/': + case '%': + case '^': + case '&': + case '!': + // Part of Lua's syntax + case '#': + case '=': + case '~': + case '<': + case '>': + case '(': + case ')': + case '{': + case '}': + case '[': + case ']': + case ':': + case ';': + case ',': + case '.': + writechar = false; + break; + } + if (writechar) + { + gtconst[3 + w] = rc; + w++; + } } - // Space - REMOVECHAR(' ') - // Used for operations - REMOVECHAR('+') - REMOVECHAR('-') - REMOVECHAR('*') - REMOVECHAR('/') - REMOVECHAR('%') - REMOVECHAR('^') - // Part of Lua's syntax - REMOVECHAR('#') - REMOVECHAR('=') - REMOVECHAR('~') - REMOVECHAR('<') - REMOVECHAR('>') - REMOVECHAR('(') - REMOVECHAR(')') - REMOVECHAR('{') - REMOVECHAR('}') - REMOVECHAR('[') - REMOVECHAR(']') - REMOVECHAR(':') - REMOVECHAR(';') - REMOVECHAR(',') - REMOVECHAR('.') - -#undef REMOVECHAR + // Free the temporary string. + Z_Free(tmpconst); // Finally, set the constant string. Gametype_ConstantNames[gtype] = gtconst; @@ -3398,7 +3416,7 @@ INT32 G_GetGametypeByName(const char *gametypestr) { INT32 i; - for (i = 0; i < NUMGAMETYPES; i++) + for (i = 0; i < gametypecount; i++) if (!stricmp(gametypestr, Gametype_Names[i])) return i; @@ -3440,6 +3458,28 @@ boolean G_GametypeUsesLives(void) return false; } +// +// G_GametypeUsesCoopLives +// +// Returns true if the current gametype uses +// the cooplives CVAR. False otherwise. +// +boolean G_GametypeUsesCoopLives(void) +{ + return (gametyperules & (GTR_LIVES|GTR_FRIENDLY)) == (GTR_LIVES|GTR_FRIENDLY); +} + +// +// G_GametypeUsesCoopStarposts +// +// Returns true if the current gametype uses +// the coopstarposts CVAR. False otherwise. +// +boolean G_GametypeUsesCoopStarposts(void) +{ + return (gametyperules & GTR_FRIENDLY); +} + // // G_GametypeHasTeams // @@ -3493,6 +3533,16 @@ boolean G_TagGametype(void) return (gametyperules & GTR_TAG); } +// +// G_CompetitionGametype +// +// For gametypes that are race gametypes, and have lives. +// +boolean G_CompetitionGametype(void) +{ + return ((gametyperules & GTR_RACE) && (gametyperules & GTR_LIVES)); +} + /** Get the typeoflevel flag needed to indicate support of a gametype. * In single-player, this always returns TOL_SP. * \param gametype The gametype for which support is desired. @@ -3734,7 +3784,7 @@ void G_AfterIntermission(void) HU_ClearCEcho(); - if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); else { @@ -3844,7 +3894,7 @@ static void G_DoContinued(void) void G_EndGame(void) { // Only do evaluation and credits in coop games. - if (gametype == GT_COOP) + if (gametyperules & GTR_CUTSCENES) { if (nextmap == 1103-1) // end game with ending { @@ -4547,7 +4597,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean automapactive = false; imcontinuing = false; - if (!skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); else G_DoLoadLevel(resetplayer); @@ -4780,6 +4830,61 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc) Z_Free(freq); } +INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep) +{ + boolean usemapcode = false; + + INT32 newmapnum; + + size_t mapnamelen; + + char *p; + + mapnamelen = strlen(mapname); + + if (mapnamelen == 2)/* maybe two digit code */ + { + if (( newmapnum = M_MapNumber(mapname[0], mapname[1]) )) + usemapcode = true; + } + else if (mapnamelen == 5 && strnicmp(mapname, "MAP", 3) == 0) + { + if (( newmapnum = M_MapNumber(mapname[3], mapname[4]) )) + usemapcode = true; + } + + if (!usemapcode) + { + /* Now detect map number in base 10, which no one asked for. */ + newmapnum = strtol(mapname, &p, 10); + if (*p == '\0')/* we got it */ + { + if (newmapnum < 1 || newmapnum > NUMMAPS) + { + CONS_Alert(CONS_ERROR, M_GetText("Invalid map number %d.\n"), newmapnum); + return 0; + } + usemapcode = true; + } + else + { + newmapnum = G_FindMap(mapname, realmapnamep, NULL, NULL); + } + } + + if (usemapcode) + { + /* we can't check mapheaderinfo for this hahahaha */ + if (W_CheckNumForName(G_BuildMapName(newmapnum)) == LUMPERROR) + return 0; + + if (realmapnamep) + (*realmapnamep) = G_BuildMapTitle(newmapnum); + } + + return newmapnum; +} + // // DEMO RECORDING // diff --git a/src/g_game.h b/src/g_game.h index 238dd1964..cb51faaca 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -130,6 +130,9 @@ INT32 G_FindMap(const char *query, char **foundmapnamep, mapsearchfreq_t **freqp, INT32 *freqc); void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc); +/* Match map name by search + 2 digit map code or map number. */ +INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep); + // XMOD spawning mapthing_t *G_FindCTFStart(INT32 playernum); mapthing_t *G_FindMatchStart(INT32 playernum); @@ -218,11 +221,14 @@ void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolo INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); +boolean G_GametypeUsesCoopLives(void); +boolean G_GametypeUsesCoopStarposts(void); boolean G_GametypeHasTeams(void); boolean G_GametypeHasSpectators(void); boolean G_RingSlingerGametype(void); boolean G_PlatformGametype(void); boolean G_TagGametype(void); +boolean G_CompetitionGametype(void); boolean G_EnoughPlayersFinished(void); void G_ExitLevel(void); void G_NextLevel(void); diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 9e454bcd5..f8d4f43d9 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -836,8 +836,10 @@ static INT32 SolveTProblem(void) return 0; CONS_Debug(DBG_RENDER, "Solving T-joins. This may take a while. Please wait...\n"); +#ifdef HWR_LOADING_SCREEN CON_Drawer(); //let the user know what we are doing I_FinishUpdate(); // page flip or blit buffer +#endif numsplitpoly = 0; @@ -964,9 +966,9 @@ void HWR_CreatePlanePolygons(INT32 bspnum) CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n"); #ifdef HWR_LOADING_SCREEN ls_count = ls_percent = 0; // reset the loading status -#endif CON_Drawer(); //let the user know what we are doing I_FinishUpdate(); // page flip or blit buffer +#endif HWR_ClearPolys(); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index ea16fb6d7..c47833187 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -764,13 +764,12 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm // CACHING HANDLING // ================================================= -static size_t gr_numtextures; // Texture count +static size_t gr_numtextures = 0; // Texture count static GLTexture_t *gr_textures; // For all textures static GLTexture_t *gr_flats; // For all (texture) flats, as normal flats don't need to be cached void HWR_InitTextureCache(void) { - gr_numtextures = 0; gr_textures = NULL; gr_flats = NULL; } @@ -958,6 +957,9 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) { UINT8 *flat; + if (needpatchflush) + W_FlushCachedPatches(); + // setup the texture info #ifdef GLIDE_API_COMPATIBILITY grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; @@ -983,6 +985,9 @@ void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) if (flatlumpnum == LUMPERROR) return; + if (needpatchflush) + W_FlushCachedPatches(); + grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFlat(grmip, flatlumpnum); @@ -1061,6 +1066,9 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) // -----------------+ void HWR_GetPatch(GLPatch_t *gpatch) { + if (needpatchflush) + W_FlushCachedPatches(); + // is it in hardware cache if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data) { @@ -1091,6 +1099,9 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) { GLMipmap_t *grmip, *newmip; + if (needpatchflush) + W_FlushCachedPatches(); + if (colormap == colormaps || colormap == NULL) { // Load the default (green) color in doom cache (temporary?) AND hardware cache @@ -1216,6 +1227,9 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) { GLPatch_t *grpatch; + if (needpatchflush) + W_FlushCachedPatches(); + grpatch = HWR_GetCachedGLPatch(lumpnum); if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data) @@ -1419,6 +1433,9 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { GLMipmap_t *grmip; + if (needpatchflush) + W_FlushCachedPatches(); + grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; if (!grmip->downloaded && !grmip->grInfo.data) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 4519e1280..598a635aa 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -992,7 +992,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // top edge if (clearlines > basewindowy - 8) { - patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH); for (x = 0; x < baseviewwidth; x += 8) HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8, 0); @@ -1001,7 +1001,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // bottom edge if (clearlines > basewindowy + baseviewheight) { - patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH); for (x = 0; x < baseviewwidth; x += 8) HWR_DrawPatch(patch, basewindowx + x, basewindowy + baseviewheight, 0); @@ -1010,7 +1010,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // left edge if (clearlines > basewindowy) { - patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); for (y = 0; y < baseviewheight && basewindowy + y < clearlines; y += 8) { @@ -1022,7 +1022,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // right edge if (clearlines > basewindowy) { - patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); for (y = 0; y < baseviewheight && basewindowy+y < clearlines; y += 8) { @@ -1034,22 +1034,22 @@ void HWR_DrawViewBorder(INT32 clearlines) // Draw beveled corners. if (clearlines > basewindowy - 8) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL], - PU_CACHE), + PU_PATCH), basewindowx - 8, basewindowy - 8, 0); if (clearlines > basewindowy - 8) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR], - PU_CACHE), + PU_PATCH), basewindowx + baseviewwidth, basewindowy - 8, 0); if (clearlines > basewindowy+baseviewheight) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL], - PU_CACHE), + PU_PATCH), basewindowx - 8, basewindowy + baseviewheight, 0); if (clearlines > basewindowy + baseviewheight) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR], - PU_CACHE), + PU_PATCH), basewindowx + baseviewwidth, basewindowy + baseviewheight, 0); } diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 4df71d145..8545a88b3 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -374,7 +374,6 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_ADST &lspr[NOLIGHT], // SPR_MCRT &lspr[NOLIGHT], // SPR_MCSP - &lspr[NOLIGHT], // SPR_NON2 &lspr[NOLIGHT], // SPR_SALD &lspr[NOLIGHT], // SPR_TRAE &lspr[NOLIGHT], // SPR_TRAI diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 48e66e114..276a66670 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -832,7 +832,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) if (!M_PointInBox(segbbox,splat->v1.x,splat->v1.y) && !M_PointInBox(segbbox,splat->v2.x,splat->v2.y)) continue; - gpatch = W_CachePatchNum(splat->patch, PU_CACHE); + gpatch = W_CachePatchNum(splat->patch, PU_PATCH); HWR_GetPatch(gpatch); wallVerts[0].x = wallVerts[3].x = FIXED_TO_FLOAT(splat->v1.x); @@ -6656,7 +6656,13 @@ void HWR_AddCommands(void) void HWR_AddSessionCommands(void) { + static boolean alreadycalled = false; + if (alreadycalled) + return; + CV_RegisterVar(&cv_granisotropicmode); + + alreadycalled = true; } // -------------------------------------------------------------------------- @@ -6692,6 +6698,17 @@ void HWR_Startup(void) startupdone = true; } +// -------------------------------------------------------------------------- +// Called after switching to the hardware renderer +// -------------------------------------------------------------------------- +void HWR_Switch(void) +{ + // Set special states from CVARs + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_grmodellighting.value); + HWD.pfnSetSpecialState(HWD_SET_FOG_DENSITY, cv_grfogdensity.value); + HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); + HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); +} // -------------------------------------------------------------------------- // Free resources allocated by the hardware renderer diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index e46aa9801..573338226 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -29,6 +29,7 @@ // Startup & Shutdown the hardware mode renderer void HWR_Startup(void); +void HWR_Switch(void); void HWR_Shutdown(void); void HWR_drawAMline(const fline_t *fl, INT32 color); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index d9801793b..f558b8c0c 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1173,6 +1173,8 @@ void HU_clearChatChars(void) w_chat[i] = 0; // reset this. chat_on = false; c_input = 0; + + I_UpdateMouseGrab(); } #ifndef NONET @@ -1323,6 +1325,7 @@ boolean HU_Responder(event_t *ev) chat_on = false; c_input = 0; // reset input cursor chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) + I_UpdateMouseGrab(); } else if (c == KEY_ESCAPE || ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1] @@ -1331,6 +1334,7 @@ boolean HU_Responder(event_t *ev) { chat_on = false; c_input = 0; // reset input cursor + I_UpdateMouseGrab(); } else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0 && !OLDCHAT) // CHAT SCROLLING YAYS! { @@ -2117,6 +2121,9 @@ static void HU_DrawDemoInfo(void) // void HU_Drawer(void) { + if (needpatchrecache) + R_ReloadHUDGraphics(); + #ifndef NONET // draw chat string plus cursor if (chat_on) @@ -2434,7 +2441,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } } - if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) { @@ -2743,7 +2750,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); - if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); diff --git a/src/i_system.h b/src/i_system.h index 2532ba0ee..a60b56310 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -288,6 +288,10 @@ void I_GetJoystick2Events(void); */ void I_GetMouseEvents(void); +/** \brief Checks if the mouse needs to be grabbed +*/ +void I_UpdateMouseGrab(void); + char *I_GetEnv(const char *name); INT32 I_PutEnv(char *variable); diff --git a/src/i_video.h b/src/i_video.h index d8f11fb13..76b984d25 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -44,6 +44,7 @@ extern boolean highcolor; /** \brief setup video mode */ void I_StartupGraphics(void); +void I_StartupHardwareGraphics(void); /** \brief restore old video mode */ @@ -84,6 +85,7 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h); \return currect video mode */ INT32 VID_SetMode(INT32 modenum); +void VID_CheckRenderer(void); /** \brief The VID_GetModeName function diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6798ac8b8..8c4739b02 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2855,6 +2855,22 @@ static int lib_gGametypeUsesLives(lua_State *L) return 1; } +static int lib_gGametypeUsesCoopLives(lua_State *L) +{ + //HUDSAFE + INLEVEL + lua_pushboolean(L, G_GametypeUsesCoopLives()); + return 1; +} + +static int lib_gGametypeUsesCoopStarposts(lua_State *L) +{ + //HUDSAFE + INLEVEL + lua_pushboolean(L, G_GametypeUsesCoopStarposts()); + return 1; +} + static int lib_gGametypeHasTeams(lua_State *L) { //HUDSAFE @@ -2895,6 +2911,14 @@ static int lib_gTagGametype(lua_State *L) return 1; } +static int lib_gCompetitionGametype(lua_State *L) +{ + //HUDSAFE + INLEVEL + lua_pushboolean(L, G_CompetitionGametype()); + return 1; +} + static int lib_gTicsToHours(lua_State *L) { tic_t rtic = luaL_checkinteger(L, 1); @@ -3140,11 +3164,14 @@ static luaL_Reg lib[] = { {"G_ExitLevel",lib_gExitLevel}, {"G_IsSpecialStage",lib_gIsSpecialStage}, {"G_GametypeUsesLives",lib_gGametypeUsesLives}, + {"G_GametypeUsesCoopLives",lib_gGametypeUsesCoopLives}, + {"G_GametypeUsesCoopStarposts",lib_gGametypeUsesCoopStarposts}, {"G_GametypeHasTeams",lib_gGametypeHasTeams}, {"G_GametypeHasSpectators",lib_gGametypeHasSpectators}, {"G_RingSlingerGametype",lib_gRingSlingerGametype}, {"G_PlatformGametype",lib_gPlatformGametype}, {"G_TagGametype",lib_gTagGametype}, + {"G_CompetitionGametype",lib_gCompetitionGametype}, {"G_TicsToHours",lib_gTicsToHours}, {"G_TicsToMinutes",lib_gTicsToMinutes}, {"G_TicsToSeconds",lib_gTicsToSeconds}, diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 58e720c85..558540829 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -245,7 +245,7 @@ static int lib_comBufAddText(lua_State *L) return LUA_ErrInvalid(L, "player_t"); if (plr != &players[consoleplayer]) return 0; - COM_BufAddText(va("%s\n", luaL_checkstring(L, 2))); + COM_BufAddTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); return 0; } @@ -262,7 +262,7 @@ static int lib_comBufInsertText(lua_State *L) return LUA_ErrInvalid(L, "player_t"); if (plr != &players[consoleplayer]) return 0; - COM_BufInsertText(va("%s\n", luaL_checkstring(L, 2))); + COM_BufInsertTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); return 0; } @@ -427,6 +427,26 @@ static int lib_cvRegisterVar(lua_State *L) return 1; } +static int lib_cvFindVar(lua_State *L) +{ + consvar_t *cv; + if (( cv = CV_FindVar(luaL_checkstring(L,1)) )) + { + lua_settop(L,1);/* We only want one argument in the stack. */ + lua_pushlightuserdata(L, cv);/* Now the second value on stack. */ + luaL_getmetatable(L, META_CVAR); + /* + The metatable is the last value on the stack, so this + applies it to the second value, which is the cvar. + */ + lua_setmetatable(L,2); + lua_pushvalue(L,2); + return 1; + } + else + return 0; +} + // CONS_Printf for a single player // Use 'print' in baselib for a global message. static int lib_consPrintf(lua_State *L) @@ -466,6 +486,7 @@ static luaL_Reg lib[] = { {"COM_BufAddText", lib_comBufAddText}, {"COM_BufInsertText", lib_comBufInsertText}, {"CV_RegisterVar", lib_cvRegisterVar}, + {"CV_FindVar", lib_cvFindVar}, {"CONS_Printf", lib_consPrintf}, {NULL, NULL} }; diff --git a/src/lua_hook.h b/src/lua_hook.h index 68efbce93..023090897 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -53,6 +53,7 @@ enum hook { hook_IntermissionThinker, hook_TeamSwitch, hook_ViewpointSwitch, + hook_SeenPlayer, hook_MAX // last hook }; @@ -97,5 +98,8 @@ void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode +#ifdef SEENAMES +boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK +#endif #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 91b4c6992..5faa625b3 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -64,6 +64,7 @@ const char *const hookNames[hook_MAX+1] = { "IntermissionThinker", "TeamSwitch", "ViewpointSwitch", + "SeenPlayer", NULL }; @@ -207,6 +208,7 @@ static int lib_addHook(lua_State *L) case hook_PlayerCanDamage: case hook_TeamSwitch: case hook_ViewpointSwitch: + case hook_SeenPlayer: case hook_ShieldSpawn: case hook_ShieldSpecial: lastp = &playerhooks; @@ -1412,7 +1414,7 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean return 0; lua_settop(gL, 0); - hud_running = true; + hud_running = true; // local hook for (hookp = playerhooks; hookp; hookp = hookp->next) { @@ -1453,4 +1455,49 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean return canSwitchView; } +// Hook for MT_NAMECHECK +#ifdef SEENAMES +boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) +{ + hook_p hookp; + boolean hasSeenPlayer = true; + if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8)))) + return 0; + + lua_settop(gL, 0); + hud_running = true; // local hook + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_SeenPlayer) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, seenfriend, META_PLAYER); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + hasSeenPlayer = false; // Hasn't seen player + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + hud_running = false; + + return hasSeenPlayer; +} +#endif // SEENAMES + #endif diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 12ae1b5fc..58af64359 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -36,6 +36,11 @@ static UINT8 hud_enabled[(hud_MAX/8)+1]; static UINT8 hudAvailable; // hud hooks field +#ifdef LUA_PATCH_SAFETY +static patchinfo_t *patchinfo, *patchinfohead; +static int numluapatches; +#endif + // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -256,12 +261,17 @@ static int colormap_get(lua_State *L) static int patch_get(lua_State *L) { +#ifdef LUA_PATCH_SAFETY patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); +#else + patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH)); +#endif enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); // patches are CURRENTLY always valid, expected to be cached with PU_STATIC // this may change in the future, so patch.valid still exists - I_Assert(patch != NULL); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); switch (field) { @@ -358,8 +368,59 @@ static int libd_patchExists(lua_State *L) static int libd_cachePatch(lua_State *L) { +#ifdef LUA_PATCH_SAFETY + int i; + lumpnum_t lumpnum; + patchinfo_t *luapat; + patch_t *realpatch; + HUDONLY - LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_STATIC), META_PATCH); + + luapat = patchinfohead; + lumpnum = W_CheckNumForName(luaL_checkstring(L, 1)); + if (lumpnum == LUMPERROR) + lumpnum = W_GetNumForName("MISSING"); + + for (i = 0; i < numluapatches; i++) + { + // check if already cached + if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum)) + { + LUA_PushUserdata(L, luapat, META_PATCH); + return 1; + } + luapat = luapat->next; + if (!luapat) + break; + } + + if (numluapatches > 0) + { + patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); + patchinfo = patchinfo->next; + } + else + { + patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); + patchinfohead = patchinfo; + } + + realpatch = W_CachePatchNum(lumpnum, PU_PATCH); + + patchinfo->width = realpatch->width; + patchinfo->height = realpatch->height; + patchinfo->leftoffset = realpatch->leftoffset; + patchinfo->topoffset = realpatch->topoffset; + + patchinfo->wadnum = WADFILENUM(lumpnum); + patchinfo->lumpnum = LUMPNUM(lumpnum); + + LUA_PushUserdata(L, patchinfo, META_PATCH); + numluapatches++; +#else + HUDONLY + LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); +#endif return 1; } @@ -415,7 +476,7 @@ static int libd_getSpritePatch(lua_State *L) return 0; // push both the patch and it's "flip" value - LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_STATIC), META_PATCH); + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); lua_pushboolean(L, (sprframe->flip & (1<lumppat[angle], PU_STATIC), META_PATCH); + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); lua_pushboolean(L, (sprframe->flip & (1<wadnum<<16)+luapat->lumpnum, PU_PATCH); +#else patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); +#endif flags = luaL_optinteger(L, 4, 0); if (!lua_isnoneornil(L, 5)) colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); @@ -540,6 +611,9 @@ static int libd_drawScaled(lua_State *L) fixed_t x, y, scale; INT32 flags; patch_t *patch; +#ifdef LUA_PATCH_SAFETY + patchinfo_t *luapat; +#endif const UINT8 *colormap = NULL; HUDONLY @@ -548,7 +622,14 @@ static int libd_drawScaled(lua_State *L) scale = luaL_checkinteger(L, 3); if (scale < 0) return luaL_error(L, "negative scale"); +#ifdef LUA_PATCH_SAFETY + luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH)); + patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH); +#else patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); +#endif flags = luaL_optinteger(L, 5, 0); if (!lua_isnoneornil(L, 6)) colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP)); @@ -1047,6 +1128,10 @@ int LUA_HudLib(lua_State *L) { memset(hud_enabled, 0xff, (hud_MAX/8)+1); +#ifdef LUA_PATCH_SAFETY + numluapatches = 0; +#endif + lua_newtable(L); // HUD registry table lua_newtable(L); luaL_register(L, NULL, lib_draw); diff --git a/src/lua_script.c b/src/lua_script.c index 18d9a87c2..eb1afaf09 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -299,9 +299,7 @@ int LUA_PushGlobals(lua_State *L, const char *word) // See the above. int LUA_CheckGlobals(lua_State *L, const char *word) { - if (fastcmp(word, "gametyperules")) - gametyperules = (UINT32)luaL_checkinteger(L, 2); - else if (fastcmp(word, "redscore")) + if (fastcmp(word, "redscore")) redscore = (UINT32)luaL_checkinteger(L, 2); else if (fastcmp(word, "bluescore")) bluescore = (UINT32)luaL_checkinteger(L, 2); diff --git a/src/m_menu.c b/src/m_menu.c index b3ff8ce71..7e739e42e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -309,6 +309,7 @@ static void M_ChangeControl(INT32 choice); // Video & Sound menu_t OP_VideoOptionsDef, OP_VideoModeDef, OP_ColorOptionsDef; #ifdef HWRENDER +static void M_OpenGLOptionsMenu(void); menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef; #endif menu_t OP_SoundOptionsDef; @@ -388,6 +389,9 @@ static void M_ResetCvars(void); // Consvar onchange functions static void Newgametype_OnChange(void); +#ifdef HWRENDER +static void Newrenderer_OnChange(void); +#endif static void Dummymares_OnChange(void); // ========================================================================== @@ -412,6 +416,11 @@ CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; consvar_t cv_newgametype = {"newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL}; +#ifdef HWRENDER +consvar_t cv_newrenderer = {"newrenderer", "Software", CV_HIDEN|CV_CALL, cv_renderer_t, Newrenderer_OnChange, 0, NULL, NULL, 0, 0, NULL}; +static int newrenderer_set = 1;/* Software doesn't need confirmation! */ +#endif + static CV_PossibleValue_t serversort_cons_t[] = { {0,"Ping"}, {1,"Modified State"}, @@ -1211,9 +1220,10 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 11}, #endif {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16}, - #ifdef HWRENDER - {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 21}, + {IT_STRING | IT_CVAR, NULL, "Renderer", &cv_newrenderer, 21}, +#else + {IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 21}, #endif {IT_HEADER, NULL, "Color Profile", NULL, 30}, @@ -1254,6 +1264,11 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 190}, {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 195}, {IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 200}, + +#ifdef HWRENDER + {IT_HEADER, NULL, "Renderer", NULL, 208}, + {IT_CALL | IT_STRING, NULL, "OpenGL Options...", M_OpenGLOptionsMenu, 214}, +#endif }; static menuitem_t OP_VideoModeMenu[] = @@ -2009,6 +2024,14 @@ menu_t OP_MonitorToggleDef = }; #ifdef HWRENDER +static void M_OpenGLOptionsMenu(void) +{ + if (rendermode == render_opengl) + M_SetupNextMenu(&OP_OpenGLOptionsDef); + else + M_StartMessage(M_GetText("You must be in OpenGL mode\nto access this menu.\n\n(Press a key)\n"), NULL, MM_NOTHING); +} + menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE( MN_OP_MAIN + (MN_OP_VIDEO << 6) + (MN_OP_OPENGL << 12), "M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); @@ -2214,6 +2237,46 @@ static void Newgametype_OnChange(void) } } +#ifdef HWRENDER +static void Newrenderer_AREYOUSURE(INT32 c) +{ + int n; + switch (c) + { + case 'y': + case KEY_ENTER: + n = cv_newrenderer.value; + newrenderer_set |= n; + CV_SetValue(&cv_renderer, n); + break; + default: + CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); + } +} + +static void Newrenderer_OnChange(void) +{ + /* Well this works for now because there's only two options. */ + int n; + n = cv_newrenderer.value; + newrenderer_set |= cv_renderer.value; + if (( newrenderer_set & n )) + CV_SetValue(&cv_renderer, n); + else + { + M_StartMessage( + "The OpenGL renderer is incomplete.\n" + "Some visuals may fail to appear, or\n" + "appear incorrectly.\n" + "Do you still want to switch to it?\n" + "\n" + "(Press 'y' or 'n')", + Newrenderer_AREYOUSURE, MM_YESNO + ); + } +} +#endif/*HWRENDER*/ + void Screenshot_option_Onchange(void) { OP_ScreenshotOptionsMenu[op_screenshot_folder].status = @@ -2814,6 +2877,7 @@ static void M_GoBack(INT32 choice) menuactive = false; wipetypepre = menupres[M_GetYoungestChildMenu()].exitwipe; + I_UpdateMouseGrab(); D_StartTitle(); } else @@ -2920,7 +2984,7 @@ static void M_NextOpt(void) itemOn = 0; else itemOn++; - } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); + } while (oldItemOn != itemOn && ( (currentMenu->menuitems[itemOn].status & IT_TYPE) & IT_SPACE )); } static void M_PrevOpt(void) @@ -2932,7 +2996,7 @@ static void M_PrevOpt(void) itemOn = currentMenu->numitems - 1; else itemOn--; - } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); + } while (oldItemOn != itemOn && ( (currentMenu->menuitems[itemOn].status & IT_TYPE) & IT_SPACE )); } // lock out further input in a tic when important buttons are pressed @@ -3158,10 +3222,7 @@ boolean M_Responder(event_t *ev) case KEY_ESCAPE: // Pop up menu if (chat_on) - { HU_clearChatChars(); - chat_on = false; - } else M_StartControlPanel(); return true; @@ -3539,6 +3600,8 @@ void M_ClearMenus(boolean callexitmenufunc) currentMenu = &MainDef; // Not like it matters menuactive = false; hidetitlemap = false; + + I_UpdateMouseGrab(); } // @@ -3566,11 +3629,11 @@ void M_SetupNextMenu(menu_t *menudef) // the curent item can be disabled, // this code go up until an enabled item found - if ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE) + if (( (currentMenu->menuitems[itemOn].status & IT_TYPE) & IT_SPACE )) { for (i = 0; i < currentMenu->numitems; i++) { - if ((currentMenu->menuitems[i].status & IT_TYPE) != IT_SPACE) + if (!( (currentMenu->menuitems[i].status & IT_TYPE) & IT_SPACE )) { itemOn = i; break; @@ -3654,14 +3717,6 @@ void M_Init(void) quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n......right?\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG6] = M_GetText("Aww, is Egg Rock Zone too\ndifficult for you?\n\n(Press 'Y' to quit)"); -#ifdef HWRENDER - // Permanently hide some options based on render mode - if (rendermode == render_soft) - OP_VideoOptionsMenu[4].status = IT_DISABLED; - else if (rendermode == render_opengl) - OP_ScreenshotOptionsMenu[op_screenshot_colorprofile].status = IT_GRAYEDOUT; -#endif - /* Well the menu sucks for forcing us to have an item set at all if every item just calls the same function, and @@ -3738,19 +3793,19 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv) centerlump[1] = W_GetNumForName("M_THERMM"); cursorlump = W_GetNumForName("M_THERMO"); - V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_CACHE)); + V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_PATCH)); xx += SHORT(p->width) - SHORT(p->leftoffset); for (i = 0; i < 16; i++) { - V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_CACHE)); + V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_PATCH)); xx += 8; } - V_DrawScaledPatch(xx, y, 0, W_CachePatchNum(rightlump, PU_CACHE)); + V_DrawScaledPatch(xx, y, 0, W_CachePatchNum(rightlump, PU_PATCH)); xx = (cv->value - cv->PossibleValue[0].value) * (15*8) / (cv->PossibleValue[1].value - cv->PossibleValue[0].value); - V_DrawScaledPatch((x + 8) + xx, y, 0, W_CachePatchNum(cursorlump, PU_CACHE)); + V_DrawScaledPatch((x + 8) + xx, y, 0, W_CachePatchNum(cursorlump, PU_PATCH)); } // A smaller 'Thermo', with range given as percents (0-100) @@ -3762,9 +3817,9 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) x = BASEVIDWIDTH - x - SLIDER_WIDTH; - V_DrawScaledPatch(x, y, 0, W_CachePatchName("M_SLIDEL", PU_CACHE)); + V_DrawScaledPatch(x, y, 0, W_CachePatchName("M_SLIDEL", PU_PATCH)); - p = W_CachePatchName("M_SLIDEM", PU_CACHE); + p = W_CachePatchName("M_SLIDEM", PU_PATCH); for (i = 1; i < SLIDER_RANGE; i++) V_DrawScaledPatch (x+i*8, y, 0,p); @@ -3776,11 +3831,11 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) '\x1D' | V_YELLOWMAP, false); } - p = W_CachePatchName("M_SLIDER", PU_CACHE); + p = W_CachePatchName("M_SLIDER", PU_PATCH); V_DrawScaledPatch(x+i*8, y, 0, p); // draw the slider cursor - p = W_CachePatchName("M_SLIDEC", PU_CACHE); + p = W_CachePatchName("M_SLIDEC", PU_PATCH); for (i = 0; cv->PossibleValue[i+1].strvalue; i++); @@ -3833,15 +3888,15 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) // draw left side cx = x; cy = y; - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TL], PU_CACHE)); + V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TL], PU_PATCH)); cy += boff; - p = W_CachePatchNum(viewborderlump[BRDR_L], PU_CACHE); + p = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); for (n = 0; n < boxlines; n++) { V_DrawScaledPatch(cx, cy, V_WRAPY, p); cy += step; } - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BL], PU_CACHE)); + V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BL], PU_PATCH)); // draw middle V_DrawFlatFill(x + boff, y + boff, width*step, boxlines*step, st_borderpatchnum); @@ -3850,23 +3905,23 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) cy = y; while (width > 0) { - V_DrawScaledPatch(cx, cy, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_T], PU_CACHE)); - V_DrawScaledPatch(cx, y + boff + boxlines*step, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_B], PU_CACHE)); + V_DrawScaledPatch(cx, cy, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH)); + V_DrawScaledPatch(cx, y + boff + boxlines*step, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH)); width--; cx += step; } // draw right side cy = y; - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TR], PU_CACHE)); + V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TR], PU_PATCH)); cy += boff; - p = W_CachePatchNum(viewborderlump[BRDR_R], PU_CACHE); + p = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); for (n = 0; n < boxlines; n++) { V_DrawScaledPatch(cx, cy, V_WRAPY, p); cy += step; } - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BR], PU_CACHE)); + V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BR], PU_PATCH)); */ } @@ -3877,7 +3932,7 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_ patch_t *patch; fixed_t sw, pw; - patch = W_CachePatchName("LSSTATIC", PU_CACHE); + patch = W_CachePatchName("LSSTATIC", PU_PATCH); pw = SHORT(patch->width) - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2 /*if (pw > 0) -- model code for modders providing weird LSSTATIC @@ -3906,15 +3961,15 @@ static void M_DrawSaveLoadBorder(INT32 x,INT32 y) { INT32 i; - V_DrawScaledPatch (x-8,y+7,0,W_CachePatchName("M_LSLEFT",PU_CACHE)); + V_DrawScaledPatch (x-8,y+7,0,W_CachePatchName("M_LSLEFT",PU_PATCH)); for (i = 0;i < 24;i++) { - V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSCNTR",PU_CACHE)); + V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSCNTR",PU_PATCH)); x += 8; } - V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSRGHT",PU_CACHE)); + V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSRGHT",PU_PATCH)); } #endif @@ -3957,10 +4012,10 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y) lasttype = curtype; if (emblem->collected) - V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), + V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else - V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_PATCH)); emblem = M_GetLevelEmblems(-1); x -= 12; @@ -3971,7 +4026,7 @@ static void M_DrawMenuTitle(void) { if (currentMenu->menutitlepic) { - patch_t *p = W_CachePatchName(currentMenu->menutitlepic, PU_CACHE); + patch_t *p = W_CachePatchName(currentMenu->menutitlepic, PU_PATCH); if (p->height > 24) // title is larger than normal { @@ -4023,13 +4078,13 @@ static void M_DrawGenericMenu(void) if (currentMenu->menuitems[i].status & IT_CENTER) { patch_t *p; - p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH); V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); } else { V_DrawScaledPatch(x, y, 0, - W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE)); + W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH)); } } /* FALLTHRU */ @@ -4098,7 +4153,7 @@ static void M_DrawGenericMenu(void) case IT_GRAYPATCH: if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0]) V_DrawMappedPatch(x, y, 0, - W_CachePatchName(currentMenu->menuitems[i].patch,PU_CACHE), graymap); + W_CachePatchName(currentMenu->menuitems[i].patch,PU_PATCH), graymap); y += LINEHEIGHT; break; case IT_TRANSTEXT: @@ -4132,12 +4187,12 @@ static void M_DrawGenericMenu(void) || ((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_NOTHING)) { V_DrawScaledPatch(currentMenu->x + SKULLXOFF, cursory - 5, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } else { V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); } } @@ -4261,7 +4316,18 @@ static void M_DrawGenericScrollMenu(void) } break; case IT_TRANSTEXT: - V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text); + switch (currentMenu->menuitems[i].status & IT_TYPE) + { + case IT_PAIR: + V_DrawString(x, y, + V_TRANSLUCENT, currentMenu->menuitems[i].patch); + V_DrawRightAlignedString(BASEVIDWIDTH - x, y, + V_TRANSLUCENT, currentMenu->menuitems[i].text); + break; + default: + V_DrawString(x, y, + V_TRANSLUCENT, currentMenu->menuitems[i].text); + } break; case IT_QUESTIONMARKS: V_DrawString(x, y, V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text)); @@ -4275,7 +4341,7 @@ static void M_DrawGenericScrollMenu(void) // DRAW THE SKULL CURSOR V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } static void M_DrawPauseMenu(void) @@ -4396,10 +4462,10 @@ static void M_DrawPauseMenu(void) continue; if (emblem->collected) - V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), + V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else - V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_PATCH)); switch (emblem->type) { @@ -4445,13 +4511,13 @@ static void M_DrawCenteredMenu(void) if (currentMenu->menuitems[i].status & IT_CENTER) { patch_t *p; - p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH); V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); } else { V_DrawScaledPatch(x, y, 0, - W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE)); + W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH)); } } /* FALLTHRU */ @@ -4526,7 +4592,7 @@ static void M_DrawCenteredMenu(void) case IT_GRAYPATCH: if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0]) V_DrawMappedPatch(x, y, 0, - W_CachePatchName(currentMenu->menuitems[i].patch,PU_CACHE), graymap); + W_CachePatchName(currentMenu->menuitems[i].patch,PU_PATCH), graymap); y += LINEHEIGHT; break; } @@ -4537,12 +4603,12 @@ static void M_DrawCenteredMenu(void) || ((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_NOTHING)) { V_DrawScaledPatch(x + SKULLXOFF, cursory - 5, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } else { V_DrawScaledPatch(x - V_StringWidth(currentMenu->menuitems[itemOn].text, 0)/2 - 24, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); V_DrawCenteredString(x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); } } @@ -4690,7 +4756,7 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) return true; - if (gt > 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt])) + if (gt >= 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt])) return true; return false; @@ -4786,6 +4852,22 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) return rows; } +// +// M_CacheLevelPlatter +// +// Cache every patch used by the level platter. +// +static void M_CacheLevelPlatter(void) +{ + levselp[0][0] = W_CachePatchName("SLCT1LVL", PU_PATCH); + levselp[0][1] = W_CachePatchName("SLCT2LVL", PU_PATCH); + levselp[0][2] = W_CachePatchName("BLANKLVL", PU_PATCH); + + levselp[1][0] = W_CachePatchName("SLCT1LVW", PU_PATCH); + levselp[1][1] = W_CachePatchName("SLCT2LVW", PU_PATCH); + levselp[1][2] = W_CachePatchName("BLANKLVW", PU_PATCH); +} + // // M_PrepareLevelPlatter // @@ -4935,24 +5017,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) } #endif - if (levselp[0][0]) // never going to have some provided but not all, saves individually checking - { - W_UnlockCachedPatch(levselp[0][0]); - W_UnlockCachedPatch(levselp[0][1]); - W_UnlockCachedPatch(levselp[0][2]); - - W_UnlockCachedPatch(levselp[1][0]); - W_UnlockCachedPatch(levselp[1][1]); - W_UnlockCachedPatch(levselp[1][2]); - } - - levselp[0][0] = W_CachePatchName("SLCT1LVL", PU_STATIC); - levselp[0][1] = W_CachePatchName("SLCT2LVL", PU_STATIC); - levselp[0][2] = W_CachePatchName("BLANKLVL", PU_STATIC); - - levselp[1][0] = W_CachePatchName("SLCT1LVW", PU_STATIC); - levselp[1][1] = W_CachePatchName("SLCT2LVW", PU_STATIC); - levselp[1][2] = W_CachePatchName("BLANKLVW", PU_STATIC); + M_CacheLevelPlatter(); return true; } @@ -5173,6 +5238,9 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo if (map <= 0) return; + if (needpatchrecache) + M_CacheLevelPlatter(); + // A 564x100 image of the level as entry MAPxxW if (!(levelselect.rows[row].mapavailable[col])) { @@ -5182,7 +5250,7 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo else { if (W_CheckNumForName(va("%sW", G_BuildMapName(map))) != LUMPERROR) - patch = W_CachePatchName(va("%sW", G_BuildMapName(map)), PU_CACHE); + patch = W_CachePatchName(va("%sW", G_BuildMapName(map)), PU_PATCH); else patch = levselp[1][2]; // don't static to indicate that it's just a normal level @@ -5204,6 +5272,9 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea if (map <= 0) return; + if (needpatchrecache) + M_CacheLevelPlatter(); + // A 160x100 image of the level as entry MAPxxP if (!(levelselect.rows[row].mapavailable[col])) { @@ -5213,7 +5284,7 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea else { if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) - patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_CACHE); + patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_PATCH); else patch = levselp[0][2]; // don't static to indicate that it's just a normal level @@ -5273,8 +5344,8 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) // new menus static void M_DrawRecordAttackForeground(void) { - patch_t *fg = W_CachePatchName("RECATKFG", PU_CACHE); - patch_t *clock = W_CachePatchName("RECCLOCK", PU_CACHE); + patch_t *fg = W_CachePatchName("RECATKFG", PU_PATCH); + patch_t *clock = W_CachePatchName("RECCLOCK", PU_PATCH); angle_t fa; INT32 i; @@ -5312,7 +5383,7 @@ static void M_DrawNightsAttackMountains(void) { static INT32 bgscrollx; INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - patch_t *background = W_CachePatchName(curbgname, PU_CACHE); + patch_t *background = W_CachePatchName(curbgname, PU_PATCH); INT32 x = FixedInt(bgscrollx) % SHORT(background->width); INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2; @@ -5335,16 +5406,16 @@ static void M_DrawNightsAttackBackground(void) INT32 i; // top - patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_CACHE); - patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_CACHE); + patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_PATCH); + patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_PATCH); INT32 backtopwidth = SHORT(backtopfg->width); //INT32 backtopheight = SHORT(backtopfg->height); INT32 fronttopwidth = SHORT(fronttopfg->width); //INT32 fronttopheight = SHORT(fronttopfg->height); // bottom - patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_CACHE); - patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_CACHE); + patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_PATCH); + patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_PATCH); INT32 backbottomwidth = SHORT(backbottomfg->width); INT32 backbottomheight = SHORT(backbottomfg->height); INT32 frontbottomwidth = SHORT(frontbottomfg->width); @@ -5488,7 +5559,7 @@ static void M_DrawLevelPlatterMenu(void) #if 0 if (levelselect.rows[lsrow].maplist[lscol] > 0) - V_DrawScaledPatch(lsbasex + cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawScaledPatch(lsbasex + cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_PATCH)); #endif // handle movement of cursor box @@ -5758,7 +5829,7 @@ static void M_DrawImageDef(void) V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text)); else { - patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); + patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_PATCH); if (patch->width <= BASEVIDWIDTH) V_DrawScaledPatch(0,0,0,patch); else @@ -5817,6 +5888,27 @@ static void M_AddonsOptions(INT32 choice) #define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!" //#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!" +static void M_LoadAddonsPatches(void) +{ + addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_PATCH); + addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_PATCH); + addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_PATCH); + addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_PATCH); + addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_PATCH); + addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_PATCH); +#ifdef USE_KART + addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_PATCH); +#endif + addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_PATCH); + addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_PATCH); + addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_PATCH); + addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_PATCH); + addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_PATCH); + addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_PATCH); + addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_PATCH); + addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_PATCH); +} + static void M_Addons(INT32 choice) { const char *pathname = "."; @@ -5860,30 +5952,7 @@ static void M_Addons(INT32 choice) else dir_on[menudepthleft] = 0; - if (addonsp[0]) // never going to have some provided but not all, saves individually checking - { - size_t i; - for (i = 0; i < NUM_EXT+5; i++) - W_UnlockCachedPatch(addonsp[i]); - } - - addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); - addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); - addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC); - addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); - addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); - addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); -#ifdef USE_KART - addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_STATIC); -#endif - addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); - addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); - addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); - addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC); - addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_STATIC); - addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_STATIC); - addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC); - addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_STATIC); + M_LoadAddonsPatches(); MISC_AddonsDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_AddonsDef); @@ -6023,6 +6092,10 @@ static void M_DrawAddons(void) return; } + // Lactozilla: Load addons menu patches. + if (needpatchrecache) + M_LoadAddonsPatches(); + if (Playing()) V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); else @@ -6958,13 +7031,13 @@ static void M_DrawEmblemHints(void) if (emblem->collected) { collected = V_GREENMAP; - V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), + V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); } else { collected = 0; - V_DrawScaledPatch(12, 12+(28*j), 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawScaledPatch(12, 12+(28*j), 0, W_CachePatchName("NEEDIT", PU_PATCH)); } if (emblem->hint[0]) @@ -7018,11 +7091,29 @@ static tic_t st_time = 0; static patch_t* st_radio[9]; static patch_t* st_launchpad[4]; +static void M_CacheSoundTest(void) +{ + UINT8 i; + char buf[8]; + + STRBUFCPY(buf, "M_RADIOn"); + for (i = 0; i < 9; i++) + { + buf[7] = (char)('0'+i); + st_radio[i] = W_CachePatchName(buf, PU_PATCH); + } + + STRBUFCPY(buf, "M_LPADn"); + for (i = 0; i < 4; i++) + { + buf[6] = (char)('0'+i); + st_launchpad[i] = W_CachePatchName(buf, PU_PATCH); + } +} + static void M_SoundTest(INT32 choice) { INT32 ul = skyRoomMenuTranslations[choice-1]; - UINT8 i; - char buf[8]; soundtestpage = (UINT8)(unlockables[ul].variable); if (!soundtestpage) @@ -7034,23 +7125,7 @@ static void M_SoundTest(INT32 choice) return; } - STRBUFCPY(buf, "M_RADIOn"); - for (i = 0; i < 9; i++) - { - if (st_radio[i]) - W_UnlockCachedPatch(st_radio[i]); - buf[7] = (char)('0'+i); - st_radio[i] = W_CachePatchName(buf, PU_STATIC); - } - - STRBUFCPY(buf, "M_LPADn"); - for (i = 0; i < 4; i++) - { - if (st_launchpad[i]) - W_UnlockCachedPatch(st_launchpad[i]); - buf[6] = (char)('0'+i); - st_launchpad[i] = W_CachePatchName(buf, PU_STATIC); - } + M_CacheSoundTest(); curplaying = NULL; st_time = 0; @@ -7069,6 +7144,9 @@ static void M_DrawSoundTest(void) fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0; UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY}; + if (needpatchrecache) + M_CacheSoundTest(); + // let's handle the ticker first. ideally we'd tick this somewhere else, BUT... if (curplaying) { @@ -7641,6 +7719,17 @@ static INT32 saveSlotSelected = 1; static INT32 loadgamescroll = 0; static UINT8 loadgameoffset = 0; +static void M_CacheLoadGameData(void) +{ + savselp[0] = W_CachePatchName("SAVEBACK", PU_PATCH); + savselp[1] = W_CachePatchName("SAVENONE", PU_PATCH); + savselp[2] = W_CachePatchName("ULTIMATE", PU_PATCH); + + savselp[3] = W_CachePatchName("GAMEDONE", PU_PATCH); + savselp[4] = W_CachePatchName("BLACXLVL", PU_PATCH); + savselp[5] = W_CachePatchName("BLANKLVL", PU_PATCH); +} + static void M_DrawLoadGameData(void) { INT32 i, savetodraw, x, y, hsep = 90; @@ -7649,6 +7738,9 @@ static void M_DrawLoadGameData(void) if (vid.width != BASEVIDWIDTH*vid.dupx) hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx); + if (needpatchrecache) + M_CacheLoadGameData(); + for (i = -2; i <= 2; i++) { savetodraw = (saveSlotSelected + i + numsaves)%numsaves; @@ -7757,7 +7849,7 @@ static void M_DrawLoadGameData(void) { lumpnum_t lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName((savegameinfo[savetodraw].gamemap) & 8191))); if (lumpnum != LUMPERROR) - patch = W_CachePatchNum(lumpnum, PU_CACHE); + patch = W_CachePatchNum(lumpnum, PU_PATCH); else patch = savselp[5]; } @@ -7813,7 +7905,7 @@ static void M_DrawLoadGameData(void) goto skipbot; colormap = R_GetTranslationColormap(savegameinfo[savetodraw].botskin, charbotskin->prefcolor, 0); sprframe = &sprdef->spriteframes[0]; - patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); V_DrawFixedPatch( tempx + (18<numframes) goto skipsign; sprframe = &sprdef->spriteframes[0]; - patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); V_DrawFixedPatch( tempx, @@ -7859,7 +7951,7 @@ skipsign: if (!sprdef->numframes) goto skiplife; sprframe = &sprdef->spriteframes[0]; - patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); V_DrawFixedPatch( (tempx + 4)< 0) { - V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_CACHE)); + V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_PATCH)); V_DrawScaledPatch(tempx + 9, y + 2, 0, patch); V_DrawString(tempx + 16, y, 0, va("%d", savegameinfo[savetodraw].continues)); } else { - V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_CACHE)); - V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_CACHE)); + V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_PATCH)); + V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_PATCH)); V_DrawString(tempx + 16, y, V_GRAYMAP, "0"); } } @@ -8125,24 +8217,7 @@ static void M_ReadSaveStrings(void) M_ReadSavegameInfo(i); } - if (savselp[0]) // never going to have some provided but not all, saves individually checking - { - W_UnlockCachedPatch(savselp[0]); - W_UnlockCachedPatch(savselp[1]); - W_UnlockCachedPatch(savselp[2]); - - W_UnlockCachedPatch(savselp[3]); - W_UnlockCachedPatch(savselp[4]); - W_UnlockCachedPatch(savselp[5]); - } - - savselp[0] = W_CachePatchName("SAVEBACK", PU_STATIC); - savselp[1] = W_CachePatchName("SAVENONE", PU_STATIC); - savselp[2] = W_CachePatchName("ULTIMATE", PU_STATIC); - - savselp[3] = W_CachePatchName("GAMEDONE", PU_STATIC); - savselp[4] = W_CachePatchName("BLACXLVL", PU_STATIC); - savselp[5] = W_CachePatchName("BLANKLVL", PU_STATIC); + M_CacheLoadGameData(); } // @@ -8322,6 +8397,43 @@ void M_ForceSaveSlotSelected(INT32 sslot) // CHARACTER SELECT // ================ +// lactozilla: sometimes the renderer changes and these patches don't exist anymore +static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) +{ + if (!(description[i].picname[0])) + { + if (skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) + { + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; + description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + } + else + description[i].charpic = W_CachePatchName("MISSING", PU_PATCH); + } + else + description[i].charpic = W_CachePatchName(description[i].picname, PU_PATCH); + + if (description[i].nametag[0]) + description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); +} + +static void M_CacheCharacterSelect(void) +{ + INT32 i, skinnum; + + for (i = 0; i < 32; i++) + { + if (!description[i].used) + continue; + + // Already set in M_SetupChoosePlayer + skinnum = description[i].skinnum[0]; + if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) + M_CacheCharacterSelectEntry(i, skinnum); + } +} + static void M_SetupChoosePlayer(INT32 choice) { INT32 skinnum; @@ -8369,27 +8481,7 @@ static void M_SetupChoosePlayer(INT32 choice) if (i == char_on) allowed = true; - if (!(description[i].picname[0])) - { - if (skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) - { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; - description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); - } - else - description[i].charpic = W_CachePatchName("MISSING", PU_CACHE); - } - else - description[i].charpic = W_CachePatchName(description[i].picname, PU_CACHE); - - if (description[i].nametag[0]) - { - const char *nametag = description[i].nametag; - description[i].namepic = NULL; - if (W_LumpExists(nametag)) - description[i].namepic = W_CachePatchName(nametag, PU_CACHE); - } + M_CacheCharacterSelectEntry(i, skinnum); } // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. } @@ -8528,8 +8620,8 @@ static void M_DrawSetupChoosePlayerMenu(void) UINT8 *colormap = NULL; INT32 prev = -1, next = -1; - patch_t *charbg = W_CachePatchName("CHARBG", PU_CACHE); - patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); + patch_t *charbg = W_CachePatchName("CHARBG", PU_PATCH); + patch_t *charfg = W_CachePatchName("CHARFG", PU_PATCH); INT16 bgheight = SHORT(charbg->height); INT16 fgheight = SHORT(charfg->height); INT16 bgwidth = SHORT(charbg->width); @@ -8537,6 +8629,10 @@ static void M_DrawSetupChoosePlayerMenu(void) INT32 x, y; INT32 w = (vid.width/vid.dupx); + // lactozilla: the renderer changed so recache patches + if (needpatchrecache) + M_CacheCharacterSelect(); + if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); else // close enough. @@ -8715,7 +8811,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Alternative menu header #ifdef CHOOSEPLAYER_DRAWHEADER { - patch_t *header = W_CachePatchName("M_PICKP", PU_CACHE); + patch_t *header = W_CachePatchName("M_PICKP", PU_PATCH); INT32 xtitle = 146; INT32 ytitle = (35 - SHORT(header->height))/2; V_DrawFixedPatch(xtitle<collected) - V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem, false), PU_CACHE), + V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE)); else - V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_PATCH)); V_DrawString(20, y, V_YELLOWMAP|V_ALLOWLOWERCASE, va("%s", exemblem->description)); } @@ -8964,7 +9060,7 @@ static void M_DrawLevelStats(void) V_DrawString(20, 56, V_GREENMAP, "(complete)"); V_DrawString(36, 64, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems)); - V_DrawSmallScaledPatch(20, 64, 0, W_CachePatchName("EMBLICON", PU_STATIC)); + V_DrawSmallScaledPatch(20, 64, 0, W_CachePatchName("EMBLICON", PU_PATCH)); sprintf(beststr, "%u", bestscore); V_DrawString(BASEVIDWIDTH/2, 48, V_YELLOWMAP, "SCORE:"); @@ -9096,7 +9192,7 @@ void M_DrawTimeAttackMenu(void) } // DRAW THE SKULL CURSOR - V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_PATCH)); V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); // Character face! @@ -9105,10 +9201,10 @@ void M_DrawTimeAttackMenu(void) { spritedef_t *sprdef = &skins[cv_chooseskin.value-1].sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; - PictureOfUrFace = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + PictureOfUrFace = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); } else - PictureOfUrFace = W_CachePatchName("MISSING", PU_CACHE); + PictureOfUrFace = W_CachePatchName("MISSING", PU_PATCH); if (PictureOfUrFace->width >= 256) V_DrawTinyScaledPatch(224, 120, 0, PictureOfUrFace); @@ -9136,9 +9232,9 @@ void M_DrawTimeAttackMenu(void) lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_PATCH); else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH); y = 32+lsheadingheight; V_DrawSmallScaledPatch(216, y, 0, PictureOfLevel); @@ -9183,7 +9279,7 @@ void M_DrawTimeAttackMenu(void) goto skipThisOne; } - empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_CACHE); + empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_PATCH); empatx = SHORT(empatch->leftoffset)/2; empaty = SHORT(empatch->topoffset)/2; @@ -9192,7 +9288,7 @@ void M_DrawTimeAttackMenu(void) V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch, R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else - V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDITL", PU_CACHE)); + V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDITL", PU_PATCH)); skipThisOne: em = M_GetLevelEmblems(-1); @@ -9372,7 +9468,7 @@ void M_DrawNightsAttackMenu(void) } // DRAW THE SKULL CURSOR - V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_PATCH)); V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); // Level record list @@ -9396,9 +9492,9 @@ void M_DrawNightsAttackMenu(void) lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_PATCH); else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH); y = 32+lsheadingheight; V_DrawSmallScaledPatch(208, y, 0, PictureOfLevel); @@ -9470,10 +9566,10 @@ void M_DrawNightsAttackMenu(void) } if (em->collected) - V_DrawSmallMappedPatch(xpos, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em, false), PU_CACHE), + V_DrawSmallMappedPatch(xpos, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else - V_DrawSmallScaledPatch(xpos, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(xpos, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_PATCH)); skipThisOne: em = M_GetLevelEmblems(-1); @@ -9509,8 +9605,8 @@ static void M_NightsAttack(INT32 choice) // This is really just to make sure Sonic is the played character, just in case M_PatchSkinNameTable(); - ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_CACHE); - ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_CACHE); + ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH); + ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH); G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please @@ -9896,7 +9992,7 @@ static void M_DrawRoomMenu(void) static void M_DrawConnectMenu(void) { UINT16 i; - const char *gt = "Unknown"; + char *gt; INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++) @@ -9940,14 +10036,17 @@ static void M_DrawConnectMenu(void) V_DrawSmallString(currentMenu->x, S_LINEY(i)+8, globalflags, va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time))); - gt = "Unknown"; - if (serverlist[slindex].info.gametype < gametypecount) - gt = Gametype_Names[serverlist[slindex].info.gametype]; + gt = serverlist[slindex].info.gametypename; V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer)); - V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, va("Gametype: %s", gt)); + if (strlen(gt) > 11) + gt = va("Gametype: %.11s...", gt); + else + gt = va("Gametype: %s", gt); + + V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, gt); MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL; } @@ -9988,7 +10087,15 @@ SERVER_LIST_ENTRY_COMPARATOR(time) SERVER_LIST_ENTRY_COMPARATOR(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer) -SERVER_LIST_ENTRY_COMPARATOR(gametype) + +static int ServerListEntryComparator_gametypename(const void *entry1, const void *entry2) +{ + const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; + int c; + if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) )) + return c; + return strcmp(sa->info.servername, sb->info.servername); \ +} // Special one for modified state. static int ServerListEntryComparator_modified(const void *entry1, const void *entry2) @@ -10028,7 +10135,7 @@ void M_SortServerList(void) qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse); break; case 5: // Gametype. - qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametype); + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename); break; } #endif @@ -10232,9 +10339,9 @@ static void M_DrawServerMenu(void) lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_PATCH); else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH); V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + imgheight, 0, PictureOfLevel); } @@ -10551,7 +10658,7 @@ static void M_DrawSetupMultiPlayerMenu(void) multi_frame = 0; sprframe = &sprdef->spriteframes[multi_frame]; - patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); if (sprframe->flip & 1) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! @@ -10572,7 +10679,7 @@ faildraw: return; // Can't render! sprframe = &sprdef->spriteframes[0]; - patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); if (sprframe->flip & 1) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! @@ -10643,7 +10750,7 @@ colordraw: cursory = y; V_DrawScaledPatch(x - 17, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } // Handle 1P/2P MP Setup @@ -10969,7 +11076,7 @@ static void M_DrawJoystick(void) if (i == itemOn) { V_DrawScaledPatch(currentMenu->x - 24, OP_JoystickSetDef.y+LINEHEIGHT*i-4, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } } } @@ -11287,7 +11394,7 @@ static void M_DrawControl(void) } V_DrawScaledPatch(currentMenu->x - 20, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } #undef controlbuffer @@ -11579,7 +11686,7 @@ static void M_DrawVideoMode(void) j = OP_VideoModeDef.y + 14 + ((vidm_selected % vidm_column_size)*8); V_DrawScaledPatch(i - 8, j, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } // Just M_DrawGenericScrollMenu but showing a backing behind the headers. @@ -11707,7 +11814,7 @@ static void M_DrawColorMenu(void) // DRAW THE SKULL CURSOR V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); + W_CachePatchName("M_CURSOR", PU_PATCH)); } // special menuitem key handler for video mode list @@ -11785,17 +11892,7 @@ static void M_HandleVideoMode(INT32 ch) static void M_DrawScreenshotMenu(void) { - M_DrawGenericScrollMenu(); -#ifdef HWRENDER - if ((rendermode == render_opengl) && (itemOn < 7)) // where it starts to go offscreen; change this number if you change the layout of the screenshot menu - { - INT32 y = currentMenu->y+currentMenu->menuitems[op_screenshot_colorprofile].alphaKey*2; - if (itemOn == 6) - y -= 10; - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, y, V_REDMAP, "ON"); - } -#endif } // =============== @@ -11880,7 +11977,7 @@ void M_QuitResponse(INT32 ch) ptime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds Tails 03-26-2001 while (ptime > I_GetTime()) { - V_DrawScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001 + V_DrawScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_PATCH)); // Demo 3 Quit Screen Tails 06-16-2001 I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 I_Sleep(); } diff --git a/src/m_menu.h b/src/m_menu.h index 19858e2fc..48a4ba6f0 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -222,13 +222,14 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); // flags for items in the menu // menu handle (what we do when key is pressed -#define IT_TYPE 14 // (2+4+8) +#define IT_TYPE 15 // (1+2+4+8) #define IT_CALL 0 // call the function +#define IT_SPACE 1 // no handling #define IT_ARROWS 2 // call function with 0 for left arrow and 1 for right arrow in param #define IT_KEYHANDLER 4 // call with the key in param #define IT_SUBMENU 6 // go to sub menu #define IT_CVAR 8 // handle as a cvar -#define IT_SPACE 10 // no handling +#define IT_PAIR 11 // no handling, define both sides of text #define IT_MSGHANDLER 12 // same as key but with event and sometime can handle y/n key (special for message) #define IT_DISPLAY (48+64+128) // 16+32+64+128 diff --git a/src/p_inter.c b/src/p_inter.c index d42bb51c0..71740822e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1451,7 +1451,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->starpostnum >= special->health) return; // Already hit this post - if (cv_coopstarposts.value && gametype == GT_COOP && (netgame || multiplayer)) + if (cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (netgame || multiplayer)) { for (i = 0; i < MAXPLAYERS; i++) { @@ -1807,7 +1807,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_MINECARTSPAWNER: - if (!player->bot && (special->fuse < TICRATE || player->powers[pw_carry] != CR_MINECART)) + if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART) { mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); P_SetTarget(&mcart->target, toucher); @@ -2481,9 +2481,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget P_SetMobjState(scoremobj, scorestate); - // On ground? No chain starts. - if (source->player->powers[pw_invulnerability] || !P_IsObjectOnGround(source)) - source->player->scoreadd = locscoreadd; + source->player->scoreadd = locscoreadd; } } @@ -2523,7 +2521,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->colorized = false; G_GhostAddColor(GHC_NORMAL); - if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0)) + if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0)) ; else if (!target->player->bot && !target->player->spectator && (target->player->lives != INFLIVES) && G_GametypeUsesLives()) @@ -2533,7 +2531,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (target->player->lives <= 0) // Tails 03-14-2000 { boolean gameovermus = false; - if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1)) + if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value != 1)) { INT32 i; for (i = 0; i < MAXPLAYERS; i++) @@ -3201,10 +3199,12 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) player->powers[pw_carry] = CR_NONE; // Burst weapons and emeralds in Match/CTF only - if (source && (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) + if (source) { - P_PlayerRingBurst(player, player->rings); - P_PlayerEmeraldBurst(player, false); + if ((gametyperules & GTR_RINGSLINGER) && !(gametyperules & GTR_TAG)) + P_PlayerRingBurst(player, player->rings); + if (gametyperules & GTR_POWERSTONES) + P_PlayerEmeraldBurst(player, false); } // Get rid of shield diff --git a/src/p_map.c b/src/p_map.c index 25da9c58d..b291c4841 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -745,9 +745,8 @@ static boolean PIT_CheckThing(mobj_t *thing) // So that NOTHING ELSE can see MT_NAMECHECK because it is client-side. if (tmthing->type == MT_NAMECHECK) { - // Ignore things that aren't players, ignore spectators, ignore yourself. - // (also don't bother to check that tmthing->target->player is non-NULL because we're not actually using it here.) - if (!thing->player || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player)) + // Ignore things that aren't players, ignore spectators, ignore yourself. + if (!thing->player || !(tmthing->target && tmthing->target->player) || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player)) return true; // Now check that you actually hit them. @@ -760,6 +759,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath +#ifdef HAVE_BLUA + // REX HAS SEEN YOU + if (!LUAh_SeenPlayer(tmthing->target->player, thing->player)) + return false; +#endif + seenplayer = thing->player; return false; } @@ -829,13 +834,13 @@ static boolean PIT_CheckThing(mobj_t *thing) for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) P_KillMobj(iter, tmthing, tmthing, 0); + return true; } else { - thing->health = 0; - P_KillMobj(thing, tmthing, tmthing, 0); + if (P_DamageMobj(thing, tmthing, tmthing, 1, 0)) + return true; } - return true; } // vectorise metal - done in a special case as at this point neither has the right flags for touching diff --git a/src/p_mobj.c b/src/p_mobj.c index 5c0ed1292..e8461957f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11823,7 +11823,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) if (!cv_powerstones.value) return false; - if (!(gametyperules & GTR_MATCHEMERALDS)) + if (!(gametyperules & GTR_POWERSTONES)) return false; runemeraldmanager = true; diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 4709e5e6f..36a9ba613 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1825,6 +1825,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (po->thinker == NULL) po->thinker = &th->thinker; +/* // Find out target first. // We redo this each tic to make savegame compatibility easier. for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) @@ -1843,6 +1844,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th) break; } } +*/ + + target = th->target; if (!target) { @@ -2025,6 +2029,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) target = waypoint; th->pointnum = target->health; + // Set the mobj as your target! -- Monster Iestyn 27/12/19 + P_SetTarget(&th->target, target); // calculate MOMX/MOMY/MOMZ for next waypoint // change slope @@ -2651,6 +2657,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Set pointnum th->pointnum = target->health; + th->target = NULL; // set to NULL first so the below doesn't go wrong + // Set the mobj as your target! -- Monster Iestyn 27/12/19 + P_SetTarget(&th->target, target); // We don't deal with the mirror crap here, we'll // handle that in the T_Thinker function. diff --git a/src/p_polyobj.h b/src/p_polyobj.h index ffacf628b..339390c0a 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -161,6 +161,8 @@ typedef struct polywaypoint_s fixed_t diffx; fixed_t diffy; fixed_t diffz; + + mobj_t *target; // next waypoint mobj } polywaypoint_t; typedef struct polyslidedoor_s diff --git a/src/p_saveg.c b/src/p_saveg.c index 3dd6bac0f..1e6451164 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2083,6 +2083,7 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) WRITEFIXED(save_p, ht->diffx); WRITEFIXED(save_p, ht->diffy); WRITEFIXED(save_p, ht->diffz); + WRITEUINT32(save_p, SaveMobjnum(ht->target)); } // @@ -3272,6 +3273,7 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) ht->diffx = READFIXED(save_p); ht->diffy = READFIXED(save_p); ht->diffz = READFIXED(save_p); + ht->target = LoadMobj(READUINT32(save_p)); return &ht->thinker; } @@ -3566,6 +3568,7 @@ static void P_NetUnArchiveThinkers(void) case tc_polywaypoint: th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); + restoreNum = true; break; case tc_polyslidedoor: @@ -3627,9 +3630,9 @@ static void P_NetUnArchiveThinkers(void) if (restoreNum) { executor_t *delay = NULL; + polywaypoint_t *polywp = NULL; UINT32 mobjnum; - for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; - currentthinker = currentthinker->next) + for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay) continue; @@ -3638,6 +3641,15 @@ static void P_NetUnArchiveThinkers(void) continue; delay->caller = P_FindNewPosition(mobjnum); } + for (currentthinker = thlist[THINK_POLYOBJ].next; currentthinker != &thlist[THINK_POLYOBJ]; currentthinker = currentthinker->next) + { + if (currentthinker->function.acp1 != (actionf_p1)T_PolyObjWaypoint) + continue; + polywp = (void *)currentthinker; + if (!(mobjnum = (UINT32)(size_t)polywp->target)) + continue; + polywp->target = P_FindNewPosition(mobjnum); + } } } diff --git a/src/p_setup.c b/src/p_setup.c index 86e4b2ac6..6ed7fbffb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2557,69 +2557,6 @@ static void P_ProcessLinedefsWithSidedefs(void) } } -static void P_CompressSidedefs(void) -{ - side_t *newsides; - size_t numnewsides = 0; - size_t z; - size_t i; - - for (i = 0; i < numsides; i++) - { - size_t j, k; - line_t *ld; - - if (!sides[i].sector) - continue; - - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == i) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == i) - ld->sidenum[1] = (UINT16)numnewsides; - } - - for (j = i + 1; j < numsides; j++) - { - if (!sides[j].sector) - continue; - - if (!memcmp(&sides[i], &sides[j], sizeof(side_t))) - { - // Find the linedefs that belong to this one - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == j) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == j) - ld->sidenum[1] = (UINT16)numnewsides; - } - sides[j].sector = NULL; // Flag for deletion - } - } - numnewsides++; - } - - // We're loading crap into this block anyhow, so no point in zeroing it out. - newsides = Z_Malloc(numnewsides*sizeof(*newsides), PU_LEVEL, NULL); - - // Copy the sides to their new block of memory. - for (i = 0, z = 0; i < numsides; i++) - { - if (sides[i].sector) - M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t)); - } - - CONS_Debug(DBG_SETUP, "P_CompressSidedefs: Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides)); - - Z_Free(sides); - sides = newsides; - numsides = numnewsides; -} - // // P_LinkMapData // Builds sector line lists and subsector sector numbers. @@ -2786,8 +2723,6 @@ static boolean P_LoadMapFromFile(void) P_LoadMapLUT(virt); P_ProcessLinedefsWithSidedefs(); - if (M_CheckParm("-compress")) - P_CompressSidedefs(); P_LinkMapData(); P_MakeMapMD5(virt, &mapmd5); @@ -2889,7 +2824,7 @@ static void P_InitLevelSettings(void) // earthquake camera memset(&quake,0,sizeof(struct quake)); - if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2) { for (i = 0; i < MAXPLAYERS; i++) { @@ -2907,7 +2842,7 @@ static void P_InitLevelSettings(void) { G_PlayerReborn(i, true); - if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) + if (canresetlives && (netgame || multiplayer) && playeringame[i] && (G_CompetitionGametype() || players[i].lives <= 0)) { // In Co-Op, replenish a user's lives if they are depleted. players[i].lives = cv_startinglives.value; @@ -3197,17 +3132,10 @@ static void P_SetupCamera(void) { mapthing_t *thing; - switch (gametype) - { - case GT_MATCH: - case GT_TAG: + if (gametyperules & GTR_DEATHMATCHSTARTS) thing = deathmatchstarts[0]; - break; - - default: + else thing = playerstarts[0]; - break; - } if (thing) { @@ -3422,7 +3350,7 @@ static void P_InitGametype(void) P_InitPlayers(); // restore time in netgame (see also g_game.c) - if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2) + if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2) { // is this a hack? maybe tic_t maxstarposttime = 0; @@ -3466,6 +3394,7 @@ boolean P_LoadLevel(boolean fromnetsave) // This is needed. Don't touch. maptol = mapheaderinfo[gamemap-1]->typeoflevel; + gametyperules = gametypedefaultrules[gametype]; CON_Drawer(); // let the user know what we are going to do I_FinishUpdate(); // page flip or blit buffer @@ -3668,23 +3597,14 @@ boolean P_LoadLevel(boolean fromnetsave) P_SpawnPrecipitation(); #ifdef HWRENDER // not win32 only 19990829 by Kin + // Lactozilla: Free extrasubsectors regardless of renderer. + // Maybe we're not in OpenGL anymore. + if (extrasubsectors) + free(extrasubsectors); + extrasubsectors = NULL; + // stuff like HWR_CreatePlanePolygons is called there if (rendermode == render_opengl) - { - // Lactozilla (December 8, 2019) - // Level setup used to free EVERY mipmap from memory. - // Even mipmaps that aren't related to level textures. - // Presumably, the hardware render code used to store textures as level data. - // Meaning, they had memory allocated and marked with the PU_LEVEL tag. - // Level textures are only reloaded after R_LoadTextures, which is - // when the texture list is loaded. -#ifdef ALAM_LIGHTING - // BP: reset light between levels (we draw preview frame lights on current frame) - HWR_ResetLights(); -#endif - // Correct missing sidedefs & deep water trick - HWR_CorrectSWTricks(); - HWR_CreatePlanePolygons((INT32)numnodes - 1); - } + HWR_SetupLevel(); #endif // oh god I hope this helps @@ -3764,6 +3684,26 @@ boolean P_LoadLevel(boolean fromnetsave) return true; } +#ifdef HWRENDER +void HWR_SetupLevel(void) +{ + // Lactozilla (December 8, 2019) + // Level setup used to free EVERY mipmap from memory. + // Even mipmaps that aren't related to level textures. + // Presumably, the hardware render code used to store textures as level data. + // Meaning, they had memory allocated and marked with the PU_LEVEL tag. + // Level textures are only reloaded after R_LoadTextures, which is + // when the texture list is loaded. +#ifdef ALAM_LIGHTING + // BP: reset light between levels (we draw preview frame lights on current frame) + HWR_ResetLights(); +#endif + // Correct missing sidedefs & deep water trick + HWR_CorrectSWTricks(); + HWR_CreatePlanePolygons((INT32)numnodes - 1); +} +#endif + // // P_RunSOC // diff --git a/src/p_setup.h b/src/p_setup.h index be3d220d8..d7e2d8861 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -98,6 +98,9 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); #endif void P_RespawnThings(void); boolean P_LoadLevel(boolean fromnetsave); +#ifdef HWRENDER +void HWR_SetupLevel(void); +#endif boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); diff --git a/src/p_slopes.c b/src/p_slopes.c index e66d7ed21..2cf2c74ba 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -50,10 +50,10 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v // Set some defaults for a non-sloped "slope" if (vec1.z == 0 && vec2.z == 0) { - /// \todo Fix fully flat cases. - slope->zangle = slope->xydirection = 0; slope->zdelta = slope->d.x = slope->d.y = 0; + slope->normal.x = slope->normal.y = 0; + slope->normal.z = FRACUNIT; } else { @@ -653,7 +653,9 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) // Handles slope ejection for objects void P_SlopeLaunch(mobj_t *mo) { - if (!(mo->standingslope->flags & SL_NOPHYSICS)) // If there's physics, time for launching. + if (!(mo->standingslope->flags & SL_NOPHYSICS) // If there's physics, time for launching. + && (mo->standingslope->normal.x != 0 + || mo->standingslope->normal.y != 0)) { // Double the pre-rotation Z, then halve the post-rotation Z. This reduces the // vertical launch given from slopes while increasing the horizontal launch @@ -710,8 +712,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) { vector3_t mom; // Ditto. - - if (slope->flags & SL_NOPHYSICS) { // No physics, no need to make anything complicated. + if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { thing->standingslope = slope; diff --git a/src/p_user.c b/src/p_user.c index fbcc17d24..d0b49000f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -347,6 +347,11 @@ void P_GiveEmerald(boolean spawnObj) continue; P_SetTarget(&emmo->target, players[i].mo); P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); + + // Make sure we're not being carried before our tracer is changed + if (players[i].powers[pw_carry] != CR_NIGHTSMODE) + players[i].powers[pw_carry] = CR_NONE; + P_SetTarget(&players[i].mo->tracer, emmo); if (pnum == 255) @@ -1230,13 +1235,13 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) if (gamestate == GS_LEVEL) { - if (player->lives == INFLIVES || (gametype != GT_COOP && gametype != GT_COMPETITION)) + if (player->lives == INFLIVES || !(gametyperules & GTR_LIVES)) { P_GivePlayerRings(player, 100*numlives); return; } - if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) + if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) { P_GivePlayerRings(player, 100*numlives); if (player->lives - prevlives >= numlives) @@ -1267,7 +1272,7 @@ docooprespawn: void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound) { - if (!((netgame || multiplayer) && gametype == GT_COOP)) + if (!((netgame || multiplayer) && G_GametypeUsesCoopLives())) { P_GivePlayerLives(player, numlives); if (sound) @@ -1395,7 +1400,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) player->score = MAXSCORE; // check for extra lives every 50000 pts - if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametype == GT_COMPETITION || gametype == GT_COOP)) + if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametyperules & GTR_LIVES)) { P_GivePlayerLives(player, (player->score/50000) - (oldscore/50000)); P_PlayLivesJingle(player); @@ -4631,6 +4636,12 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) S_StartSound(player->mo, sfx_spin); break; } + if (player->dashspeed < player->mindash) + player->dashspeed = player->mindash; + + if (player->dashspeed > player->maxdash) + player->dashspeed = player->maxdash; + if (player->dashspeed < player->maxdash && player->mindash != player->maxdash) { #define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) @@ -7780,6 +7791,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->fuse = TICRATE*7; // takes about an extra second to hit the ground flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); + flame->flags2 = (flame->flags2 & ~MF2_OBJECTFLIP)|(player->mo->flags2 & MF2_OBJECTFLIP); flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale)); P_SetObjectMomZ(flame, 3*FRACUNIT, false); @@ -9298,7 +9310,7 @@ boolean P_GetLives(player_t *player) { INT32 i, maxlivesplayer = -1, livescheck = 1; if (!(netgame || multiplayer) - || (gametype != GT_COOP) + || !G_GametypeUsesCoopLives() || (player->lives == INFLIVES)) return true; @@ -9447,7 +9459,7 @@ static void P_DeathThink(player_t *player) player->playerstate = PST_REBORN; else if ((player->lives > 0 || j != MAXPLAYERS) && !(!(netgame || multiplayer) && G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages! { - if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) + if (G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2) { P_ConsiderAllGone(); if ((player->deadtimer > TICRATE<<1) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) @@ -9462,19 +9474,22 @@ static void P_DeathThink(player_t *player) // Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes. if (cmd->buttons & BT_JUMP) { - if (gametype != GT_COOP && player->spectator) + // You're a spectator, so respawn right away. + if ((gametyperules & GTR_SPECTATORS) && player->spectator) player->playerstate = PST_REBORN; - else switch(gametype) { - case GT_COOP: - case GT_COMPETITION: - case GT_RACE: - if (player->deadtimer > TICRATE) - player->playerstate = PST_REBORN; - break; - default: - if (player->deadtimer > cv_respawntime.value*TICRATE) - player->playerstate = PST_REBORN; - break; + else + { + // Give me one second. + INT32 respawndelay = TICRATE; + + // Non-platform gametypes + if (gametyperules & GTR_RESPAWNDELAY) + respawndelay = (cv_respawntime.value*TICRATE); + + // You've been dead for enough time. + // You may now respawn. + if (player->deadtimer > respawndelay) + player->playerstate = PST_REBORN; } } @@ -9488,7 +9503,7 @@ static void P_DeathThink(player_t *player) INT32 i, deadtimercheck = INT32_MAX; // In a net/multiplayer game, and out of lives - if (gametype == GT_COMPETITION) + if (G_CompetitionGametype()) { for (i = 0; i < MAXPLAYERS; i++) { @@ -11244,7 +11259,10 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (panim == PA_WALK) { if (stat != fume->info->spawnstate) + { + fume->threshold = 0; P_SetMobjState(fume, fume->info->spawnstate); + } return; } } @@ -11275,6 +11293,12 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (underwater) { fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10); + fume->threshold = 1; + } + else if (fume->threshold) + { + fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame; + fume->threshold = 0; } } @@ -11534,7 +11558,7 @@ void P_PlayerThink(player_t *player) #else if (player->spectator && #endif - gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2) + G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2) P_ConsiderAllGone(); if (player->playerstate == PST_DEAD) diff --git a/src/r_data.c b/src/r_data.c index cecd4840c..bfd83a62d 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2095,7 +2095,6 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) ///////////////////// // This code creates the colormap array used by software renderer ///////////////////// - if (rendermode == render_soft) { double r, g, b, cbrightness; int p; @@ -2717,7 +2716,7 @@ void R_PrecacheLevel(void) lump = sf->lumppat[k]; if (devparm) spritememory += W_LumpLength(lump); - W_CachePatchNum(lump, PU_CACHE); + W_CachePatchNum(lump, PU_PATCH); } } } diff --git a/src/r_defs.h b/src/r_defs.h index 8e9e96920..683e289eb 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -734,9 +734,9 @@ typedef struct boolean cached[8]; #ifdef HWRENDER aatree_t *hardware_patch[8]; -#endif +#endif/*HWRENDER*/ } rotsprite_t; -#endif +#endif/*ROTSPRITE*/ typedef enum { @@ -748,6 +748,24 @@ typedef enum SRF_NONE = 0xff // Initial value } spriterotateflags_t; // SRF's up! +// Same as a patch_t, except just the header +// and the wadnum/lumpnum combination that points +// to wherever the patch is in memory. +struct patchinfo_s +{ + INT16 width; // bounding box size + INT16 height; + INT16 leftoffset; // pixels to the left of origin + INT16 topoffset; // pixels below the origin + + UINT16 wadnum; // the software patch lump num for when the patch + UINT16 lumpnum; // was flushed, and we need to re-create it + + // next patchinfo_t in memory + struct patchinfo_s *next; +}; +typedef struct patchinfo_s patchinfo_t; + // // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. diff --git a/src/r_main.c b/src/r_main.c index 115db8cb5..a5f4bc118 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -19,6 +19,7 @@ #include "r_local.h" #include "r_splats.h" // faB(21jan): testing #include "r_sky.h" +#include "hu_stuff.h" #include "st_stuff.h" #include "p_local.h" #include "keys.h" @@ -28,6 +29,7 @@ #include "d_main.h" #include "v_video.h" #include "p_spec.h" // skyboxmo +#include "p_setup.h" #include "z_zone.h" #include "m_random.h" // quake camera shake #include "r_portal.h" @@ -1154,6 +1156,26 @@ void R_RenderPlayerView(player_t *player) free(masks); } +// Lactozilla: Renderer switching +#ifdef HWRENDER +void R_InitHardwareMode(void) +{ + HWR_AddSessionCommands(); + HWR_Switch(); + HWR_LoadTextures(numtextures); + if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) + HWR_SetupLevel(); +} +#endif + +void R_ReloadHUDGraphics(void) +{ + CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n"); + ST_LoadGraphics(); + HU_LoadGraphics(); + ST_ReloadSkinFaceGraphics(); +} + // ========================================================================= // ENGINE COMMANDS & VARS // ========================================================================= diff --git a/src/r_main.h b/src/r_main.h index 58c23cd81..143cc1de0 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -89,6 +89,10 @@ extern consvar_t cv_tailspickup; // Called by startup code. void R_Init(void); +#ifdef HWRENDER +void R_InitHardwareMode(void); +#endif +void R_ReloadHUDGraphics(void); // just sets setsizeneeded true extern boolean setsizeneeded; diff --git a/src/r_patch.c b/src/r_patch.c index 0519d6dc9..fbb64e362 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1396,4 +1396,19 @@ void R_FreeSkinRotSprite(size_t skinnum) skinsprites++; } } + +// +// R_FreeAllRotSprite +// +// Free ALL sprite rotation data from memory. +// +void R_FreeAllRotSprite(void) +{ + INT32 i; + size_t s; + for (s = 0; s < numsprites; s++) + R_FreeSingleRotSprite(&sprites[s]); + for (i = 0; i < numskins; ++i) + R_FreeSkinRotSprite(i); +} #endif diff --git a/src/r_patch.h b/src/r_patch.h index 72371f253..2961448a0 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -68,6 +68,7 @@ void R_FreeSingleRotSprite(spritedef_t *spritedef); void R_FreeSkinRotSprite(size_t skinnum); extern fixed_t rollcosang[ROTANGLES]; extern fixed_t rollsinang[ROTANGLES]; +void R_FreeAllRotSprite(void); #endif #endif // __R_PATCH__ diff --git a/src/r_segs.c b/src/r_segs.c index 0fc91a823..1af1cb2a2 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -165,7 +165,7 @@ static void R_DrawWallSplats(void) mfloorclip = floorclip; mceilingclip = ceilingclip; - patch = W_CachePatchNum(splat->patch, PU_CACHE); + patch = W_CachePatchNum(splat->patch, PU_PATCH); dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz; if (splat->yoffset) diff --git a/src/r_splats.c b/src/r_splats.c index 414e93eb6..f690dfa94 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -147,7 +147,7 @@ void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, f splat->flags = flags; // bad.. but will be needed for drawing anyway.. - patch = W_CachePatchNum(splat->patch, PU_CACHE); + patch = W_CachePatchNum(splat->patch, PU_PATCH); // offset needed by draw code for texture mapping linelength = P_SegLength((seg_t *)wallline); diff --git a/src/r_things.c b/src/r_things.c index cd7e40064..927d199a5 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -126,11 +126,10 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch for (ang = 0; ang < ROTANGLES; ang++) sprtemp[frame].rotsprite.patch[r][ang] = NULL; #ifdef HWRENDER - if (rendermode == render_opengl) - sprtemp[frame].rotsprite.hardware_patch[r] = M_AATreeAlloc(AATREE_ZUSER); -#endif // HWRENDER + sprtemp[frame].rotsprite.hardware_patch[r] = M_AATreeAlloc(AATREE_ZUSER); +#endif/*HWRENDER*/ } -#endif +#endif/*ROTSPRITE*/ if (rotation == 0) { @@ -988,7 +987,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) // // R_SplitSprite -// runs through a sector's lightlist and +// runs through a sector's lightlist and Knuckles static void R_SplitSprite(vissprite_t *sprite) { INT32 i, lightnum, lindex; diff --git a/src/s_sound.c b/src/s_sound.c index a49499040..0235d8376 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -61,7 +61,9 @@ static void GameMIDIMusic_OnChange(void); static void GameSounds_OnChange(void); static void GameDigiMusic_OnChange(void); +#ifdef HAVE_OPENMPT static void ModFilter_OnChange(void); +#endif static lumpnum_t S_GetMusicLumpNum(const char *mname); diff --git a/src/screen.c b/src/screen.c index 507067705..5bb304c08 100644 --- a/src/screen.c +++ b/src/screen.c @@ -53,6 +53,7 @@ void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); // ------------------ viddef_t vid; INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set + 1) +UINT8 setrenderneeded = 0; static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}}; @@ -62,7 +63,17 @@ consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, N consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static void SCR_ChangeFullscreen (void); +static void SCR_ActuallyChangeRenderer(void); +CV_PossibleValue_t cv_renderer_t[] = { + {1, "Software"}, +#ifdef HWRENDER + {2, "OpenGL"}, +#endif + {0, NULL} +}; +consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer, 0, NULL, NULL, 0, 0, NULL}; + +static void SCR_ChangeFullscreen(void); consvar_t cv_fullscreen = {"fullscreen", "Yes", CV_SAVE|CV_CALL, CV_YesNo, SCR_ChangeFullscreen, 0, NULL, NULL, 0, 0, NULL}; @@ -87,19 +98,8 @@ boolean R_3DNow = false; boolean R_MMXExt = false; boolean R_SSE2 = false; - -void SCR_SetMode(void) +void SCR_SetDrawFuncs(void) { - if (dedicated) - return; - - if (!setmodeneeded || WipeInAction) - return; // should never happen and don't change it during a wipe, BAD! - - VID_SetMode(--setmodeneeded); - - V_SetPalette(0); - // // setup the right draw routines for either 8bpp or 16bpp // @@ -193,9 +193,37 @@ void SCR_SetMode(void) if (SCR_IsAspectCorrect(vid.width, vid.height)) CONS_Alert(CONS_WARNING, M_GetText("Resolution is not aspect-correct!\nUse a multiple of %dx%d\n"), BASEVIDWIDTH, BASEVIDHEIGHT); */ +} + +void SCR_SetMode(void) +{ + if (dedicated) + return; + + if (!(setmodeneeded || setrenderneeded) || WipeInAction) + return; // should never happen and don't change it during a wipe, BAD! + + // Lactozilla: Renderer switching + if (setrenderneeded) + { + Z_PreparePatchFlush(); + needpatchflush = true; + needpatchrecache = true; + VID_CheckRenderer(); + if (!setmodeneeded) + VID_SetMode(vid.modenum); + } + + if (setmodeneeded) + VID_SetMode(--setmodeneeded); + + V_SetPalette(0); + + SCR_SetDrawFuncs(); // set the apprpriate drawer for the sky (tall or INT16) setmodeneeded = 0; + setrenderneeded = 0; } // do some initial settings for the game loading screen @@ -383,6 +411,8 @@ void SCR_CheckDefaultMode(void) // see note above setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; } + + SCR_ActuallyChangeRenderer(); } // sets the modenum as the new default video mode to be saved in the config file @@ -412,6 +442,55 @@ void SCR_ChangeFullscreen(void) #endif } +static int target_renderer = 0; + +void SCR_ActuallyChangeRenderer(void) +{ + setrenderneeded = target_renderer; + // setting the same renderer twice WILL crash your game, so let's not, please + if (rendermode == setrenderneeded) + setrenderneeded = 0; +} + +// Lactozilla: Renderer switching +void SCR_ChangeRenderer(void) +{ + setrenderneeded = 0; + + if (con_startup) + { + target_renderer = cv_renderer.value; +#ifdef HWRENDER + if (M_CheckParm("-opengl")) + target_renderer = rendermode = render_opengl; + else +#endif + if (M_CheckParm("-software")) + target_renderer = rendermode = render_soft; + // set cv_renderer back + SCR_ChangeRendererCVars(rendermode); + return; + } + + if (cv_renderer.value == 1) + target_renderer = render_soft; + else if (cv_renderer.value == 2) + target_renderer = render_opengl; + SCR_ActuallyChangeRenderer(); +} + +void SCR_ChangeRendererCVars(INT32 mode) +{ + // set cv_renderer back + if (mode == render_soft) + CV_StealthSetValue(&cv_renderer, 1); + else if (mode == render_opengl) + CV_StealthSetValue(&cv_renderer, 2); +#ifdef HWRENDER + CV_StealthSetValue(&cv_newrenderer, cv_renderer.value); +#endif +} + boolean SCR_IsAspectCorrect(INT32 width, INT32 height) { return diff --git a/src/screen.h b/src/screen.h index 470acb4b9..02b336f75 100644 --- a/src/screen.h +++ b/src/screen.h @@ -170,18 +170,29 @@ extern boolean R_SSE2; // ---------------- // screen variables // ---------------- + extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 +void SCR_ChangeRenderer(void); +void SCR_ChangeRendererCVars(INT32 mode); +extern UINT8 setrenderneeded; + extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders -extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen; +extern CV_PossibleValue_t cv_renderer_t[]; + +extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen; +#ifdef HWRENDER +extern consvar_t cv_newrenderer; +#endif // wait for page flipping to end or not extern consvar_t cv_vidwait; // Change video mode, only at the start of a refresh. void SCR_SetMode(void); +void SCR_SetDrawFuncs(void); // Recalc screen size dependent stuff void SCR_Recalc(void); // Check parms once at startup diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index e054381ee..e6a40327b 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -67,10 +67,12 @@ #include "../s_sound.h" #include "../i_joy.h" #include "../st_stuff.h" +#include "../hu_stuff.h" #include "../g_game.h" #include "../i_video.h" #include "../console.h" #include "../command.h" +#include "../r_main.h" #include "sdlmain.h" #ifdef HWRENDER #include "../hardware/hw_main.h" @@ -98,6 +100,7 @@ boolean highcolor = false; // synchronize page flipping with screen refresh consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; UINT8 graphics_started = 0; // Is used in console.c and screen.c @@ -107,6 +110,7 @@ static SDL_bool disable_fullscreen = SDL_FALSE; #define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value static SDL_bool disable_mouse = SDL_FALSE; #define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && havefocus) +#define IGNORE_MOUSE (!cv_alwaysgrabmouse.value && (menuactive || paused || con_destlines || chat_on || gamestate != GS_LEVEL)) #define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menuactive && !USE_FULLSCREEN) #define MOUSEBUTTONS_MAX MOUSEBUTTONS @@ -377,12 +381,15 @@ static void SDLdoUngrabMouse(void) void SDLforceUngrabMouse(void) { if (SDL_WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO && window != NULL) - { - SDL_ShowCursor(SDL_ENABLE); - SDL_SetWindowGrab(window, SDL_FALSE); - wrapmouseok = SDL_FALSE; - SDL_SetRelativeMouseMode(SDL_FALSE); - } + SDLdoUngrabMouse(); +} + +void I_UpdateMouseGrab(void) +{ + if (SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO && window != NULL + && SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window + && !IGNORE_MOUSE) + SDLdoGrabMouse(); } static void VID_Command_NumModes_f (void) @@ -589,7 +596,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) } //else firsttimeonmouse = SDL_FALSE; - if (USE_MOUSEINPUT) + if (USE_MOUSEINPUT && !IGNORE_MOUSE) SDLdoGrabMouse(); } else if (!mousefocus && !kbfocus) @@ -636,11 +643,14 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type) static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) { + static boolean firstmove = true; + if (USE_MOUSEINPUT) { - if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window)) + if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window) || (IGNORE_MOUSE && !firstmove)) { SDLdoUngrabMouse(); + firstmove = false; return; } @@ -654,6 +664,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) mousemovey += -evt.yrel; SDL_SetWindowGrab(window, SDL_TRUE); } + firstmove = false; return; } @@ -661,6 +672,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) // of the screen then ignore it. if ((evt.x == realwidth/2) && (evt.y == realheight/2)) { + firstmove = false; return; } @@ -673,6 +685,8 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) SDLdoGrabMouse(); } } + + firstmove = false; } static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type) @@ -686,7 +700,7 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type) // this apparently makes a mouse button down event but not a mouse button up event, // resulting in whatever key was pressed down getting "stuck" if we don't ignore it. // -- Monster Iestyn (28/05/18) - if (SDL_GetMouseFocus() != window) + if (SDL_GetMouseFocus() != window || IGNORE_MOUSE) return; /// \todo inputEvent.button.which @@ -1068,7 +1082,7 @@ void I_StartupMouse(void) } else firsttimeonmouse = SDL_FALSE; - if (cv_usemouse.value) + if (cv_usemouse.value && !IGNORE_MOUSE) SDLdoGrabMouse(); else SDLdoUngrabMouse(); @@ -1208,7 +1222,6 @@ void I_FinishUpdate(void) SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); } - #ifdef HWRENDER else if (rendermode == render_opengl) { @@ -1408,37 +1421,53 @@ void VID_PrepareModeList(void) #endif } -INT32 VID_SetMode(INT32 modeNum) +static SDL_bool Impl_CreateContext(void) { - SDLdoUngrabMouse(); - - vid.recalc = 1; - vid.bpp = 1; - - if (modeNum >= 0 && modeNum < MAXWINMODES) + // Renderer-specific stuff +#ifdef HWRENDER + if (rendermode == render_opengl) { - vid.width = windowedModes[modeNum][0]; - vid.height = windowedModes[modeNum][1]; - vid.modenum = modeNum; + if (!sdlglcontext) + sdlglcontext = SDL_GL_CreateContext(window); + if (sdlglcontext == NULL) + { + SDL_DestroyWindow(window); + I_Error("Failed to create a GL context: %s\n", SDL_GetError()); + } + SDL_GL_MakeCurrent(window, sdlglcontext); } else +#endif + if (rendermode == render_soft) { - // just set the desktop resolution as a fallback - SDL_DisplayMode mode; - SDL_GetWindowDisplayMode(window, &mode); - if (mode.w >= 2048) + int flags = 0; // Use this to set SDL_RENDERER_* flags now + if (usesdl2soft) + flags |= SDL_RENDERER_SOFTWARE; + else if (cv_vidwait.value) + flags |= SDL_RENDERER_PRESENTVSYNC; + + if (!renderer) + renderer = SDL_CreateRenderer(window, -1, flags); + if (renderer == NULL) { - vid.width = 1920; - vid.height = 1200; + CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError()); + return SDL_FALSE; } - else - { - vid.width = mode.w; - vid.height = mode.h; - } - vid.modenum = -1; + SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); + } + return SDL_TRUE; +} + +void VID_CheckRenderer(void) +{ + if (dedicated) + return; + + if (setrenderneeded) + { + rendermode = setrenderneeded; + Impl_CreateContext(); } - //Impl_SetWindowName("SRB2 "VERSIONSTRING); SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); Impl_VideoSetupBuffer(); @@ -1450,8 +1479,39 @@ INT32 VID_SetMode(INT32 modeNum) SDL_FreeSurface(bufSurface); bufSurface = NULL; } +#ifdef HWRENDER + HWR_FreeTextureCache(); +#endif + SCR_SetDrawFuncs(); } +#ifdef HWRENDER + else if (rendermode == render_opengl) + { + I_StartupHardwareGraphics(); + R_InitHardwareMode(); + HWR_Switch(); + } +#endif +} +INT32 VID_SetMode(INT32 modeNum) +{ + SDLdoUngrabMouse(); + + vid.recalc = 1; + vid.bpp = 1; + + if (modeNum < 0) + modeNum = 0; + if (modeNum >= MAXWINMODES) + modeNum = MAXWINMODES-1; + + vid.width = windowedModes[modeNum][0]; + vid.height = windowedModes[modeNum][1]; + vid.modenum = modeNum; + + //Impl_SetWindowName("SRB2 "VERSIONSTRING); + VID_CheckRenderer(); return SDL_TRUE; } @@ -1472,8 +1532,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) flags |= SDL_WINDOW_BORDERLESS; #ifdef HWRENDER - if (rendermode == render_opengl) - flags |= SDL_WINDOW_OPENGL; + flags |= SDL_WINDOW_OPENGL; #endif // Create a window @@ -1486,38 +1545,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) return SDL_FALSE; } - // Renderer-specific stuff -#ifdef HWRENDER - if (rendermode == render_opengl) - { - sdlglcontext = SDL_GL_CreateContext(window); - if (sdlglcontext == NULL) - { - SDL_DestroyWindow(window); - I_Error("Failed to create a GL context: %s\n", SDL_GetError()); - } - SDL_GL_MakeCurrent(window, sdlglcontext); - } - else -#endif - if (rendermode == render_soft) - { - flags = 0; // Use this to set SDL_RENDERER_* flags now - if (usesdl2soft) - flags |= SDL_RENDERER_SOFTWARE; - else if (cv_vidwait.value) - flags |= SDL_RENDERER_PRESENTVSYNC; - - renderer = SDL_CreateRenderer(window, -1, flags); - if (renderer == NULL) - { - CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError()); - return SDL_FALSE; - } - SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); - } - - return SDL_TRUE; + return Impl_CreateContext(); } /* @@ -1572,17 +1600,14 @@ static void Impl_VideoSetupSDLBuffer(void) static void Impl_VideoSetupBuffer(void) { // Set up game's software render buffer - //if (rendermode == render_soft) + vid.rowbytes = vid.width * vid.bpp; + vid.direct = NULL; + if (vid.buffer) + free(vid.buffer); + vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS); + if (!vid.buffer) { - vid.rowbytes = vid.width * vid.bpp; - vid.direct = NULL; - if (vid.buffer) - free(vid.buffer); - vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS); - if (!vid.buffer) - { - I_Error("%s", M_GetText("Not enough memory for video buffer\n")); - } + I_Error("%s", M_GetText("Not enough memory for video buffer\n")); } } @@ -1602,6 +1627,7 @@ void I_StartupGraphics(void) COM_AddCommand ("vid_mode", VID_Command_Mode_f); CV_RegisterVar (&cv_vidwait); CV_RegisterVar (&cv_stretch); + CV_RegisterVar (&cv_alwaysgrabmouse); disable_mouse = M_CheckParm("-nomouse"); disable_fullscreen = M_CheckParm("-win") ? 1 : 0; @@ -1626,10 +1652,13 @@ void I_StartupGraphics(void) )) framebuffer = SDL_TRUE; } - if (M_CheckParm("-software")) - { + +#ifdef HWRENDER + if (M_CheckParm("-opengl")) + rendermode = render_opengl; + else if (M_CheckParm("-software")) +#endif rendermode = render_soft; - } usesdl2soft = M_CheckParm("-softblit"); borderlesswindow = M_CheckParm("-borderless"); @@ -1637,44 +1666,7 @@ void I_StartupGraphics(void) //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); VID_Command_ModeList_f(); #ifdef HWRENDER - if (M_CheckParm("-opengl") || rendermode == render_opengl) - { - rendermode = render_opengl; - HWD.pfnInit = hwSym("Init",NULL); - HWD.pfnFinishUpdate = NULL; - HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); - HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); - HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); - HWD.pfnSetBlend = hwSym("SetBlend",NULL); - HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); - HWD.pfnSetTexture = hwSym("SetTexture",NULL); - HWD.pfnReadRect = hwSym("ReadRect",NULL); - HWD.pfnGClipRect = hwSym("GClipRect",NULL); - HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); - HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); - HWD.pfnSetPalette = hwSym("SetPalette",NULL); - HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); - HWD.pfnDrawModel = hwSym("DrawModel",NULL); - HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); - HWD.pfnSetTransform = hwSym("SetTransform",NULL); - HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); - HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); - HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); - HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); - HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); - HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); - HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); - HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); - HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); - HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - // check gl renderer lib - if (HWD.pfnGetRenderVersion() != VERSION) - I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n")); - if (!HWD.pfnInit(I_Error)) // let load the OpenGL library - { - rendermode = render_soft; - } - } + I_StartupHardwareGraphics(); #endif // Fury: we do window initialization after GL setup to allow @@ -1724,16 +1716,55 @@ void I_StartupGraphics(void) SDL_RaiseWindow(window); if (mousegrabok && !disable_mouse) - { - SDL_ShowCursor(SDL_DISABLE); - SDL_SetRelativeMouseMode(SDL_TRUE); - wrapmouseok = SDL_TRUE; - SDL_SetWindowGrab(window, SDL_TRUE); - } + SDLdoGrabMouse(); graphics_started = true; } +void I_StartupHardwareGraphics(void) +{ +#ifdef HWRENDER + static boolean glstartup = false; + if (!glstartup) + { + HWD.pfnInit = hwSym("Init",NULL); + HWD.pfnFinishUpdate = NULL; + HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); + HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); + HWD.pfnSetBlend = hwSym("SetBlend",NULL); + HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); + HWD.pfnSetTexture = hwSym("SetTexture",NULL); + HWD.pfnReadRect = hwSym("ReadRect",NULL); + HWD.pfnGClipRect = hwSym("GClipRect",NULL); + HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); + HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); + HWD.pfnSetPalette = hwSym("SetPalette",NULL); + HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); + HWD.pfnDrawModel = hwSym("DrawModel",NULL); + HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); + HWD.pfnSetTransform = hwSym("SetTransform",NULL); + HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); + HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); + HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); + HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); + HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); + HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); + HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); + HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); + HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); + HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); + // check gl renderer lib + if (HWD.pfnGetRenderVersion() != VERSION) + I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n")); + if (!HWD.pfnInit(I_Error)) // let load the OpenGL library + rendermode = render_soft; + else + glstartup = true; + } +#endif +} + void I_ShutdownGraphics(void) { const rendermode_t oldrendermode = rendermode; diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 33b366bf6..b8991293c 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -1432,6 +1432,8 @@ static void I_ResumeGME(void) boolean I_LoadSong(char *data, size_t len) { + (void)data; + (void)len; return false; } @@ -1493,6 +1495,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms (void)target_volume; (void)source_volume; (void)ms; + (void)callback; return false; } @@ -1500,6 +1503,7 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { (void)target_volume; (void)ms; + (void)callback; return false; } diff --git a/src/sounds.c b/src/sounds.c index 175bd8960..720ba851e 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -187,6 +187,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pity Shield"}, // generic GET! {"wirlsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind Shield"}, // Whirlwind GET! {"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Force Shield"}, // Force GET! + {"frcssg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weak Force Shield"}, // Force GET...? (consider making a custom shield with this instead of a single-hit force shield!) {"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Elemental Shield"}, // Elemental GET! {"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon Shield"}, // Armaggeddon GET! {"attrsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction Shield"}, // Attract GET! @@ -220,6 +221,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"}, {"lvfal1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rumble"}, {"pscree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "SCREE!"}, + {"iceb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ice crack"}, + {"shattr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shattering"}, + {"antiri", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Depletion"}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, @@ -233,6 +237,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"wepchg", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weapon change"}, // Weapon switch is identical to menu for now {"wtrdng", true, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, // make sure you can hear the DING DING! Tails 03-08-2000 {"zelda", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, + {"adderr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Error"}, + {"notadd", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Reject"}, + {"addfil", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accept"}, // NiGHTS {"ideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"}, @@ -427,24 +434,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // S3&K sounds + {"s3k2b", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald! {"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // stereo in original game, identical to latter {"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // mono in original game, identical to previous {"s3k35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, @@ -566,6 +558,21 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3ka9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, {"s3kaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, {"s3kab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kaba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabe", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, {"s3kac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Continue"}, {"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "GO!"}, {"s3kae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pinball flipper"}, @@ -604,7 +611,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, // ditto {"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, {"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto - {"s3kc7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, + {"s3kc7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, + {"s3kc7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, // ditto {"s3kc8s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, {"s3kc8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, // ditto {"s3kc9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Swinging"}, diff --git a/src/sounds.h b/src/sounds.h index e520c6243..039349d4f 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -236,6 +236,7 @@ typedef enum sfx_shield, sfx_wirlsg, sfx_forcsg, + sfx_frcssg, sfx_elemsg, sfx_armasg, sfx_attrsg, @@ -269,6 +270,9 @@ typedef enum sfx_sprong, sfx_lvfal1, sfx_pscree, + sfx_iceb, + sfx_shattr, + sfx_antiri, // Menu, interface sfx_chchng, @@ -282,6 +286,9 @@ typedef enum sfx_wepchg, sfx_wtrdng, sfx_zelda, + sfx_adderr, + sfx_notadd, + sfx_addfil, // NiGHTS sfx_ideya, @@ -476,24 +483,9 @@ typedef enum sfx_s25e, sfx_s25f, sfx_s260, - sfx_s261, - sfx_s262, - sfx_s263, - sfx_s264, - sfx_s265, - sfx_s266, - sfx_s267, - sfx_s268, - sfx_s269, - sfx_s26a, - sfx_s26b, - sfx_s26c, - sfx_s26d, - sfx_s26e, - sfx_s26f, - sfx_s270, // S3&K sounds + sfx_s3k2b, sfx_s3k33, sfx_s3k34, sfx_s3k35, @@ -615,6 +607,21 @@ typedef enum sfx_s3ka9, sfx_s3kaa, sfx_s3kab, + sfx_s3kab1, + sfx_s3kab2, + sfx_s3kab3, + sfx_s3kab4, + sfx_s3kab5, + sfx_s3kab6, + sfx_s3kab7, + sfx_s3kab8, + sfx_s3kab9, + sfx_s3kaba, + sfx_s3kabb, + sfx_s3kabc, + sfx_s3kabd, + sfx_s3kabe, + sfx_s3kabf, sfx_s3kac, sfx_s3kad, sfx_s3kae, @@ -653,7 +660,8 @@ typedef enum sfx_s3kc5l, sfx_s3kc6s, sfx_s3kc6l, - sfx_s3kc7, + sfx_s3kc7s, + sfx_s3kc7l, sfx_s3kc8s, sfx_s3kc8l, sfx_s3kc9s, diff --git a/src/st_stuff.c b/src/st_stuff.c index 5e05030c3..9a1505ce3 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -694,7 +694,7 @@ static void ST_drawTime(void) else { // Counting down the hidetime? - if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime <= (hidetime*TICRATE))) + if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime <= (hidetime*TICRATE))) { tics = (hidetime*TICRATE - stplyr->realtime); if (tics < 3*TICRATE) @@ -705,7 +705,7 @@ static void ST_drawTime(void) else { // Hidetime finish! - if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime < ((hidetime+1)*TICRATE))) + if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime < ((hidetime+1)*TICRATE))) ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime); // Time limit? @@ -723,7 +723,7 @@ static void ST_drawTime(void) downwards = true; } // Post-hidetime normal. - else if (gametyperules & GTR_TAG) + else if (gametyperules & GTR_STARTCOUNTDOWN) tics = stplyr->realtime - hidetime*TICRATE; // "Shadow! What are you doing? Hurry and get back here // right now before the island blows up with you on it!" @@ -845,69 +845,13 @@ static void ST_drawLivesArea(void) hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, faceprefix[stplyr->skin], colormap); } - // Lives number + // Metal Sonic recording if (metalrecording) { if (((2*leveltime)/TICRATE) & 1) V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC"); } - else if (G_GametypeUsesLives() || gametype == GT_RACE) - { - // x - V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, - hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex); - - // lives number - if (gametype == GT_RACE) - { - livescount = INFLIVES; - notgreyedout = true; - } - else if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3) - { - INT32 i; - livescount = 0; - notgreyedout = (stplyr->lives > 0); - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - if (players[i].lives < 1) - continue; - - if (players[i].lives > 1) - notgreyedout = true; - - if (players[i].lives == INFLIVES) - { - livescount = INFLIVES; - break; - } - else if (livescount < 99) - livescount += (players[i].lives); - } - } - else - { - livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives); - notgreyedout = true; - } - - if (livescount == INFLIVES) - V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8, - '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); - else - { - if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1))) - livescount++; - if (livescount > 99) - livescount = 99; - V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, - hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount)); - } - } // Spectator else if (stplyr->spectator) v_colmap = V_GRAYMAP; @@ -934,11 +878,89 @@ static void ST_drawLivesArea(void) v_colmap = V_BLUEMAP; } } + // Lives number + else + { + boolean candrawlives = true; + + // Co-op and Competition, normal life counter + if (G_GametypeUsesLives()) + { + // Handle cooplives here + if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 3) + { + INT32 i; + livescount = 0; + notgreyedout = (stplyr->lives > 0); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].lives < 1) + continue; + + if (players[i].lives > 1) + notgreyedout = true; + + if (players[i].lives == INFLIVES) + { + livescount = INFLIVES; + break; + } + else if (livescount < 99) + livescount += (players[i].lives); + } + } + else + { + livescount = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives); + notgreyedout = true; + } + } + // Infinity symbol (Race) + else if (G_PlatformGametype() && !(gametyperules & GTR_LIVES)) + { + livescount = INFLIVES; + notgreyedout = true; + } + // Otherwise nothing, sorry. + // Special Stages keep not showing lives, + // as G_GametypeUsesLives() returns false in + // Special Stages, and the infinity symbol + // cannot show up because Special Stages + // still have the GTR_LIVES gametype rule + // by default. + else + candrawlives = false; + + // Draw the lives counter here. + if (candrawlives) + { + // x + V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex); + if (livescount == INFLIVES) + V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8, + '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); + else + { + if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1))) + livescount++; + if (livescount > 99) + livescount = 99; + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, + hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount)); + } + } +#undef ST_drawLivesX + } // name v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER); if (strlen(skins[stplyr->skin].hudname) <= 5) V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); + else if (V_StringWidth(skins[stplyr->skin].hudname, v_colmap) <= 48) + V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); else if (V_ThinStringWidth(skins[stplyr->skin].hudname, v_colmap) <= 40) V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); else @@ -2202,7 +2224,7 @@ static void ST_drawTextHUD(void) donef12 = true; } } - else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text. + else if ((gametyperules & GTR_RESPAWNDELAY) && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text. { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; @@ -2226,7 +2248,7 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) else if (G_PlatformGametype()) { - if (gametype == GT_COOP) + if (G_GametypeUsesCoopLives()) { if (stplyr->lives <= 0 && cv_cooplives.value == 2 @@ -2637,7 +2659,7 @@ static void ST_overlayDrawer(void) INT32 i = MAXPLAYERS; INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1)); - if ((gametype == GT_COOP) + if (G_GametypeUsesCoopLives() && (netgame || multiplayer) && (cv_cooplives.value != 1)) { @@ -2766,6 +2788,9 @@ static void ST_overlayDrawer(void) void ST_Drawer(void) { + if (needpatchrecache) + R_ReloadHUDGraphics(); + #ifdef SEENAMES if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) { diff --git a/src/v_video.c b/src/v_video.c index c91e5f213..4785a1541 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1045,13 +1045,13 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skin { spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE]; - patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); V_DrawMappedPatch(x, y, flags, patch, colormap); } else - V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); + V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_PATCH)); } // diff --git a/src/w_wad.c b/src/w_wad.c index 62992441a..1aa281426 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -55,6 +55,7 @@ #include "dehacked.h" #include "d_clisrv.h" #include "r_defs.h" +#include "r_data.h" #include "i_system.h" #include "md5.h" #include "lua_script.h" @@ -1375,7 +1376,6 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag) void *W_CacheLumpNum(lumpnum_t lumpnum, INT32 tag) { - return W_CacheLumpNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); } @@ -1488,12 +1488,31 @@ void *W_CacheLumpName(const char *name, INT32 tag) // Cache a patch into heap memory, convert the patch format as necessary // +void W_FlushCachedPatches(void) +{ + if (needpatchflush) + { + Z_FreeTag(PU_CACHE); + Z_FreeTag(PU_PATCH); + Z_FreeTag(PU_HUDGFX); + Z_FreeTag(PU_HWRPATCHINFO); + Z_FreeTag(PU_HWRMODELTEXTURE); + Z_FreeTag(PU_HWRCACHE); + Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRPATCHINFO_UNLOCKED); + } + needpatchflush = false; +} + +// Software-only compile cache the data without conversion void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { #ifdef HWRENDER GLPatch_t *grPatch; #endif + if (needpatchflush) + W_FlushCachedPatches(); + if (!TestValidLump(wad, lump)) return NULL; diff --git a/src/w_wad.h b/src/w_wad.h index 8008a577c..aca67c00f 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -196,6 +196,7 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); // return a patch_t void W_UnlockCachedPatch(void *patch); +void W_FlushCachedPatches(void); void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index c9fdb1c97..42733c309 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -1354,6 +1354,8 @@ getBufferedData: } } +void I_UpdateMouseGrab(void) {} + // =========================================================================================== // DIRECT INPUT JOYSTICK // =========================================================================================== diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 39a60cd93..d0aab92b3 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -239,6 +239,11 @@ void I_StartupGraphics(void) if (!dedicated) graphics_started = true; } +void I_StartupHardwareGraphics(void) +{ + // oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y +} + // ------------------ // I_ShutdownGraphics // Close the screen, restore previous video mode. @@ -946,6 +951,11 @@ INT32 VID_SetMode(INT32 modenum) return 1; } +void VID_CheckRenderer(void) +{ + // .............. +} + // ======================================================================== // Free the video buffer of the last video mode, // allocate a new buffer for the video mode to set. diff --git a/src/y_inter.c b/src/y_inter.c index b26c0797e..214dee92e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -161,6 +161,7 @@ typedef struct boolean usebuffer = false; static boolean useinterpic; +static boolean safetorender = true; static y_buffer_t *y_buffer; static INT32 intertic; @@ -177,6 +178,7 @@ static void Y_CalculateCompetitionWinners(void); static void Y_CalculateTimeRaceWinners(void); static void Y_CalculateMatchWinners(void); static void Y_UnloadData(void); +static void Y_CleanupData(void); // Stuff copy+pasted from st_stuff.c #define ST_DrawNumFromHud(h,n) V_DrawTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, n) @@ -335,8 +337,19 @@ void Y_IntermissionDrawer(void) } if (!usebuffer) + // Lactozilla: Renderer switching + if (needpatchrecache) + { + Y_CleanupData(); + safetorender = false; + } + + if (!usebuffer || !safetorender) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + if (!safetorender) + goto dontdrawbg; + if (useinterpic) V_DrawScaledPatch(0, 0, 0, interpic); else if (!usetile) @@ -377,6 +390,7 @@ void Y_IntermissionDrawer(void) goto skiptallydrawer; #endif +dontdrawbg: if (intertype == int_coop) { INT32 bonusy; @@ -426,14 +440,17 @@ void Y_IntermissionDrawer(void) bonusy = 150; // Total - V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal); - V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total); + if (safetorender) + { + V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal); + V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total); + } bonusy -= (3*SHORT(tallnum[0]->height)/2) + 1; // Draw bonuses for (i = 3; i >= 0; --i) { - if (data.coop.bonuses[i].display) + if (data.coop.bonuses[i].display && safetorender) { V_DrawScaledPatch(152, bonusy, 0, data.coop.bonuspatches[i]); V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.bonuses[i].points); @@ -662,7 +679,8 @@ void Y_IntermissionDrawer(void) char strtime[10]; // draw the header - V_DrawScaledPatch(112, 2, 0, data.match.result); + if (safetorender) + V_DrawScaledPatch(112, 2, 0, data.match.result); // draw the level name V_DrawCenteredString(BASEVIDWIDTH/2, 20, 0, data.match.levelstring); @@ -1194,6 +1212,8 @@ void Y_StartIntermission(void) I_Error("endtic is dirty"); #endif + safetorender = true; + if (!multiplayer) { timer = 0; @@ -1249,20 +1269,20 @@ void Y_StartIntermission(void) data.coop.tics = players[consoleplayer].realtime; for (i = 0; i < 4; ++i) - data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_STATIC); - data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_STATIC); + data.coop.bonuspatches[i] = W_CachePatchName(data.coop.bonuses[i].patch, PU_PATCH); + data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH); // get act number data.coop.actnum = mapheaderinfo[gamemap-1]->actnum; // get background patches - widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC); - bgpatch = W_CachePatchName("INTERSCR", PU_STATIC); + widebgpatch = W_CachePatchName("INTERSCW", PU_PATCH); + bgpatch = W_CachePatchName("INTERSCR", PU_PATCH); // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_STATIC); + interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; usebuffer = false; } @@ -1320,18 +1340,18 @@ void Y_StartIntermission(void) Y_AwardSpecialStageBonus(); for (i = 0; i < 2; ++i) - data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_STATIC); + data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_PATCH); - data.spec.pscore = W_CachePatchName("YB_SCORE", PU_STATIC); - data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_STATIC); + data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); + data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); // get background tile - bgtile = W_CachePatchName("SPECTILE", PU_STATIC); + bgtile = W_CachePatchName("SPECTILE", PU_PATCH); // grab an interscreen if appropriate if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') { - interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_STATIC); + interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); useinterpic = true; } else @@ -1343,14 +1363,14 @@ void Y_StartIntermission(void) // get special stage specific patches /* if (!stagefailed && ALL7EMERALDS(emeralds)) { - data.spec.cemerald = W_CachePatchName("GOTEMALL", PU_STATIC); + data.spec.cemerald = W_CachePatchName("GOTEMALL", PU_PATCH); data.spec.headx = 70; data.spec.nowsuper = players[consoleplayer].skin - ? NULL : W_CachePatchName("NOWSUPER", PU_STATIC); + ? NULL : W_CachePatchName("NOWSUPER", PU_PATCH); } else { - data.spec.cemerald = W_CachePatchName("CEMERALD", PU_STATIC); + data.spec.cemerald = W_CachePatchName("CEMERALD", PU_PATCH); data.spec.headx = 48; data.spec.nowsuper = NULL; } */ @@ -1428,9 +1448,9 @@ void Y_StartIntermission(void) // get RESULT header data.match.result = - W_CachePatchName("RESULT", PU_STATIC); + W_CachePatchName("RESULT", PU_PATCH); - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); + bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1456,9 +1476,9 @@ void Y_StartIntermission(void) data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; // get RESULT header - data.match.result = W_CachePatchName("RESULT", PU_STATIC); + data.match.result = W_CachePatchName("RESULT", PU_PATCH); - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); + bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1495,7 +1515,7 @@ void Y_StartIntermission(void) data.match.blueflag = bmatcico; } - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); + bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1521,7 +1541,7 @@ void Y_StartIntermission(void) data.competition.levelstring[sizeof data.competition.levelstring - 1] = '\0'; // get background tile - bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); + bgtile = W_CachePatchName("SRB2BACK", PU_PATCH); usetile = true; useinterpic = false; break; @@ -1977,7 +1997,7 @@ static void Y_AwardCoopBonuses(void) if (i == consoleplayer) { - data.coop.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives); + data.coop.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives); M_Memcpy(&data.coop.bonuses, &localbonuses, sizeof(data.coop.bonuses)); } } @@ -2032,7 +2052,7 @@ static void Y_AwardSpecialStageBonus(void) if (i == consoleplayer) { - data.spec.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives); + data.spec.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives); M_Memcpy(&data.spec.bonuses, &localbonuses, sizeof(data.spec.bonuses)); // Continues related @@ -2059,7 +2079,8 @@ void Y_EndIntermission(void) usebuffer = false; } -#define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL +#define UNLOAD(x) if (x) {Z_ChangeTag(x, PU_CACHE);} x = NULL; +#define CLEANUP(x) x = NULL; // // Y_UnloadData @@ -2110,5 +2131,47 @@ static void Y_UnloadData(void) //are not handled break; } - +} + +static void Y_CleanupData(void) +{ + // unload the background patches + CLEANUP(bgpatch); + CLEANUP(widebgpatch); + CLEANUP(bgtile); + CLEANUP(interpic); + + switch (intertype) + { + case int_coop: + // unload the coop and single player patches + CLEANUP(data.coop.bonuspatches[3]); + CLEANUP(data.coop.bonuspatches[2]); + CLEANUP(data.coop.bonuspatches[1]); + CLEANUP(data.coop.bonuspatches[0]); + CLEANUP(data.coop.ptotal); + break; + case int_spec: + // unload the special stage patches + //CLEANUP(data.spec.cemerald); + //CLEANUP(data.spec.nowsuper); + CLEANUP(data.spec.bonuspatches[1]); + CLEANUP(data.spec.bonuspatches[0]); + CLEANUP(data.spec.pscore); + CLEANUP(data.spec.pcontinues); + break; + case int_match: + case int_race: + CLEANUP(data.match.result); + break; + case int_ctf: + CLEANUP(data.match.blueflag); + CLEANUP(data.match.redflag); + break; + default: + //without this default, + //int_none, int_tag, int_chaos, and int_classicrace + //are not handled + break; + } } diff --git a/src/z_zone.c b/src/z_zone.c index daad5489d..5a0ff638b 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -27,6 +27,7 @@ #include "doomdef.h" #include "doomstat.h" +#include "r_patch.h" #include "i_system.h" // I_GetFreeMem #include "i_video.h" // rendermode #include "z_zone.h" @@ -497,6 +498,35 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) // Utility functions // ----------------- +// for renderer switching, free a bunch of stuff +boolean needpatchflush = false; +boolean needpatchrecache = false; + +// flush all patches from memory +// (also frees memory tagged with PU_CACHE) +// (which are not necessarily patches but I don't care) +void Z_FlushCachedPatches(void) +{ + CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); + Z_FreeTag(PU_CACHE); + Z_FreeTag(PU_PATCH); + Z_FreeTag(PU_HUDGFX); + Z_FreeTag(PU_HWRPATCHINFO); + Z_FreeTag(PU_HWRMODELTEXTURE); + Z_FreeTag(PU_HWRCACHE); + Z_FreeTag(PU_HWRCACHE_UNLOCKED); + Z_FreeTag(PU_HWRPATCHINFO_UNLOCKED); +} + +// happens before a renderer switch +void Z_PreparePatchFlush(void) +{ + CONS_Debug(DBG_RENDER, "Z_PreparePatchFlush()...\n"); +#ifdef ROTSPRITE + R_FreeAllRotSprite(); +#endif +} + // starting value of nextcleanup #define CLEANUPCOUNT 2000 diff --git a/src/z_zone.h b/src/z_zone.h index 635c334cf..9e5f74343 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -43,6 +43,7 @@ enum PU_SOUND = 11, // static while playing PU_MUSIC = 12, // static while playing PU_HUDGFX = 13, // static until WAD added + PU_PATCH = 14, // static until renderer change PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch @@ -142,4 +143,10 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); char *Z_StrDup(const char *in); #define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed +// For renderer switching +extern boolean needpatchflush; +extern boolean needpatchrecache; +void Z_FlushCachedPatches(void); +void Z_PreparePatchFlush(void); + #endif