From 0c850e8ddd5fe5c4ae70593d25404e094b17cae2 Mon Sep 17 00:00:00 2001 From: slatenails Date: Sun, 28 Jul 2013 14:58:30 +0300 Subject: [PATCH 1/9] Results for console tab-completion are now color-coded. CCMDs appear blue, CVars green and aliases red. --- src/c_console.cpp | 15 ++++++++++++++- src/c_dispatch.cpp | 5 +++++ src/c_dispatch.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 170cc97d4..0ecd600e4 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -2121,7 +2121,20 @@ static bool C_TabCompleteList () Printf (TEXTCOLOR_BLUE "Completions for %s:\n", CmdLine+2); for (i = TabPos; nummatches > 0; ++i, --nummatches) { - Printf ("%-*s", int(maxwidth), TabCommands[i].TabName.GetChars()); + // [Dusk] Print console commands blue, CVars green, aliases red. + const char* colorcode = ""; + FConsoleCommand* ccmd; + if (FindCVar (TabCommands[i].TabName, NULL)) + colorcode = "\\c[Green]"; + else if ((ccmd = FConsoleCommand::FindByName (TabCommands[i].TabName)) != NULL) + { + if (ccmd->IsAlias()) + colorcode = "\\c[Red]"; + else + colorcode = "\\c[Light Blue]"; + } + + Printf ("%s%-*s", strbin1 (colorcode).GetChars(), int(maxwidth), TabCommands[i].TabName.GetChars()); x += maxwidth; if (x > ConCols - maxwidth) { diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index d25354986..76b6e395d 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -955,6 +955,11 @@ bool FConsoleCommand::AddToHash (FConsoleCommand **table) return true; } +FConsoleCommand* FConsoleCommand::FindByName (const char* name) +{ + return FindNameInHashTable (Commands, name, strlen (name)); +} + FConsoleCommand::FConsoleCommand (const char *name, CCmdRun runFunc) : m_RunFunc (runFunc) { diff --git a/src/c_dispatch.h b/src/c_dispatch.h index 12ea559de..96dc50644 100644 --- a/src/c_dispatch.h +++ b/src/c_dispatch.h @@ -93,6 +93,7 @@ public: void PrintCommand () { Printf ("%s\n", m_Name); } virtual void Run (FCommandLine &args, APlayerPawn *instigator, int key); + static FConsoleCommand* FindByName (const char* name); FConsoleCommand *m_Next, **m_Prev; char *m_Name; From 6dee878b2e29fc6107c81b5b76ab5b72fa4bf05b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 28 Jul 2013 17:15:47 +0200 Subject: [PATCH 2/9] - used TEXTCOLOR_ #defines for colorizing CCMD list, remove use of strbin1. --- src/c_console.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 0ecd600e4..e5d3d97ab 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -2125,16 +2125,16 @@ static bool C_TabCompleteList () const char* colorcode = ""; FConsoleCommand* ccmd; if (FindCVar (TabCommands[i].TabName, NULL)) - colorcode = "\\c[Green]"; + colorcode = TEXTCOLOR_GREEN; else if ((ccmd = FConsoleCommand::FindByName (TabCommands[i].TabName)) != NULL) { if (ccmd->IsAlias()) - colorcode = "\\c[Red]"; + colorcode = TEXTCOLOR_RED; else - colorcode = "\\c[Light Blue]"; + colorcode = TEXTCOLOR_LIGHTBLUE; } - Printf ("%s%-*s", strbin1 (colorcode).GetChars(), int(maxwidth), TabCommands[i].TabName.GetChars()); + Printf ("%s%-*s", colorcode, int(maxwidth), TabCommands[i].TabName.GetChars()); x += maxwidth; if (x > ConCols - maxwidth) { From c4af738bf6b0d7f093ccdb0b060a04b8c4ff0cad Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Mon, 29 Jul 2013 18:30:26 -0400 Subject: [PATCH 3/9] - Fixed: crash when closing ZDoom in the save menu and a memory leak. --- src/menu/loadsavemenu.cpp | 3 ++- src/sdl/i_system.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 20779a221..9a87bb806 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -131,7 +131,8 @@ void ClearSaveGames() { for(unsigned i=0;ibNoDelete) + delete DLoadSaveMenu::SaveGames[i]; } DLoadSaveMenu::SaveGames.Clear(); } diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 292da5930..def35606a 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -749,6 +749,8 @@ int I_FindClose (void *handle) findstate_t *state = (findstate_t *)handle; if (handle != (void*)-1 && state->count > 0) { + for(int i = 0;i < state->count;++i) + free (state->namelist[i]); state->count = 0; free (state->namelist); state->namelist = NULL; From 28e5cc536aa28a5b5ccad032da524d5a99d6cce3 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 29 Aug 2013 21:16:11 -0500 Subject: [PATCH 4/9] Add some awareness of short file names - Added I_GetLongPathName(). It wraps the Win32 API's GetLongPathName(). DArgs::CollectFiles() now calls this for every argument it processes, so any arguments passed using short file names will be converted to long file names. This is mainly of interest so that savegames will never record the short file name, which can change based on what else is in the directory. --- src/m_argv.cpp | 9 +++++++++ src/win32/i_system.cpp | 28 ++++++++++++++++++++++++++++ src/win32/i_system.h | 3 +++ 3 files changed, 40 insertions(+) diff --git a/src/m_argv.cpp b/src/m_argv.cpp index 54d9ffda4..816a2d54c 100644 --- a/src/m_argv.cpp +++ b/src/m_argv.cpp @@ -35,6 +35,7 @@ #include #include "m_argv.h" #include "cmdlib.h" +#include "i_system.h" IMPLEMENT_CLASS (DArgs) @@ -391,6 +392,14 @@ void DArgs::CollectFiles(const char *param, const char *extension) } } + // Optional: Replace short path names with long path names +#ifdef _WIN32 + for (i = 0; i < work.Size(); ++i) + { + work[i] = I_GetLongPathName(work[i]); + } +#endif + // Step 3: Add work back to Argv, as long as it's non-empty. if (work.Size() > 0) { diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index b5843ec7a..a82cb65f9 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -1569,3 +1569,31 @@ unsigned int I_MakeRNGSeed() CryptReleaseContext(prov, 0); return seed; } + +//========================================================================== +// +// I_GetLongPathName +// +// Returns the long version of the path, or the original if there isn't +// anything worth changing. +// +//========================================================================== + +FString I_GetLongPathName(FString shortpath) +{ + DWORD buffsize = GetLongPathName(shortpath.GetChars(), NULL, 0); + if (buffsize == 0) + { // nothing to change (it doesn't exist, maybe?) + return shortpath; + } + TCHAR *buff = new TCHAR[buffsize]; + DWORD buffsize2 = GetLongPathName(shortpath.GetChars(), buff, buffsize); + if (buffsize2 >= buffsize) + { // Failure! Just return the short path + delete[] buff; + return shortpath; + } + FString longpath(buff, buffsize2); + delete[] buff; + return longpath; +} diff --git a/src/win32/i_system.h b/src/win32/i_system.h index 6bafdc01c..9fbf2db5c 100644 --- a/src/win32/i_system.h +++ b/src/win32/i_system.h @@ -155,6 +155,9 @@ typedef _W64 long WLONG_PTR; typedef long WLONG_PTR; #endif +// Wrapper for GetLongPathName +FString I_GetLongPathName(FString shortpath); + // Directory searching routines // Mirror WIN32_FIND_DATAA in From aac0de3e48f3d869ed3fce584cab42e68cfb3d0b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 29 Aug 2013 21:40:01 -0500 Subject: [PATCH 5/9] Fixed: Make A_SetTics work with weapons. - When A_SetTics is called from a weapon, we need to set the tics for the psprite instead of the actor itself. --- src/thingdef/thingdef_codeptr.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 456a1d6e3..ee3e4ee2f 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4935,6 +4935,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics) ACTION_PARAM_START(1); ACTION_PARAM_INT(tics_to_set, 0); + if (stateowner != self && self->player != NULL) + { // Is this a weapon? Need to check psp states for a match, then. Blah. + for (int i = 0; i < NUMPSPRITES; ++i) + { + if (self->player->psprites[i].state == CallingState) + { + self->player->psprites[i].tics = tics_to_set; + return; + } + } + } + // Just set tics for self. self->tics = tics_to_set; } From 7143ae49e1f4048f74000bd8390c351cecc1c719 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 29 Aug 2013 21:45:37 -0500 Subject: [PATCH 6/9] Fixed: CheckPlayerCamera not sync safe - If a player is spying through another player, CheckPlayerCamera will return the TID of the player you are "spying", but as coopspy isn't a net command, this wont be reflected by all nodes. So to fix this, CheckPlayerCamera now returns -1 if a player's camera is that of any player at all. (thanks edward850) --- src/p_acs.cpp | 2 +- src/thingdef/thingdef_codeptr.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index dc696ca45..b707f4444 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -8394,7 +8394,7 @@ scriptwait: { int playernum = STACK(1); - if (playernum < 0 || playernum >= MAXPLAYERS || !playeringame[playernum] || players[playernum].camera == NULL) + if (playernum < 0 || playernum >= MAXPLAYERS || !playeringame[playernum] || players[playernum].camera == NULL || players[playernum].camera->player != NULL) { STACK(1) = -1; } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index ee3e4ee2f..f5ef45f45 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4935,7 +4935,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics) ACTION_PARAM_START(1); ACTION_PARAM_INT(tics_to_set, 0); - if (stateowner != self && self->player != NULL) + if (stateowner != self && self->player != NULL && stateowner->IsKindOf(RUNTIME_CLASS(AWeapon))) { // Is this a weapon? Need to check psp states for a match, then. Blah. for (int i = 0; i < NUMPSPRITES; ++i) { From 0f0d9da839742701da4998a51ddc3850282e0530 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 29 Aug 2013 22:22:30 -0500 Subject: [PATCH 7/9] Reset FirstFreeEntry in ACSStringPool::ReadStrings() - Fixed: When an ACS string pool was read from a savegame, FirstFreeEntry would not be updatedt, except by the Clear() function. This left FirstFreeEntry at 0, which meant the next string added to the pool would always go in slot 0, whether it was free or not. --- src/p_acs.cpp | 25 ++++++++++++++++++++----- src/p_acs.h | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index b707f4444..32a70cd15 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -575,11 +575,7 @@ int ACSStringPool::InsertString(FString &str, unsigned int h, unsigned int bucke } else { // Scan for the next free entry - unsigned int i; - for (i = FirstFreeEntry + 1; i < Pool.Size() && Pool[i].Next != FREE_ENTRY; ++i) - { - } - FirstFreeEntry = i; + FindFirstFreeEntry(FirstFreeEntry + 1); } PoolEntry *entry = &Pool[index]; entry->Str = str; @@ -590,6 +586,23 @@ int ACSStringPool::InsertString(FString &str, unsigned int h, unsigned int bucke return index | STRPOOL_LIBRARYID_OR; } +//============================================================================ +// +// ACSStringPool :: FindFirstFreeEntry +// +// Finds the first free entry, starting at base. +// +//============================================================================ + +void ACSStringPool::FindFirstFreeEntry(unsigned base) +{ + while (base < Pool.Size() && Pool[base].Next != FREE_ENTRY) + { + base++; + } + FirstFreeEntry = base; +} + //============================================================================ // // ACSStringPool :: ReadStrings @@ -638,6 +651,7 @@ void ACSStringPool::ReadStrings(PNGHandle *png, DWORD id) { delete[] str; } + FindFirstFreeEntry(0); } } @@ -690,6 +704,7 @@ void ACSStringPool::Dump() const Printf("%4u. (%2d) \"%s\"\n", i, Pool[i].LockCount, Pool[i].Str.GetChars()); } } + Printf("First free %u\n", FirstFreeEntry); } //============================================================================ diff --git a/src/p_acs.h b/src/p_acs.h index 1a0fb3f60..ec41ab886 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -100,6 +100,7 @@ public: private: int FindString(const char *str, size_t len, unsigned int h, unsigned int bucketnum); int InsertString(FString &str, unsigned int h, unsigned int bucketnum, const SDWORD *stack, int stackdepth); + void FindFirstFreeEntry(unsigned int base); enum { NUM_BUCKETS = 251 }; enum { FREE_ENTRY = 0xFFFFFFFE }; // Stored in PoolEntry's Next field From b0371e18048ac12bc469a66679945ebf67ec287e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Aug 2013 22:38:57 -0500 Subject: [PATCH 8/9] Don't abort when merely checking if a non-map is a map - When P_OpenMapData() is called by P_CheckMapData(), we don't actually care if any required lumps are missing. This just means it isn't a valid map, so don't abort with I_Error(). --- src/compatibility.cpp | 2 +- src/g_level.cpp | 2 +- src/p_setup.cpp | 20 +++++++++++++++----- src/p_setup.h | 2 +- src/statistics.cpp | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/compatibility.cpp b/src/compatibility.cpp index 7bbff7322..dca0d3485 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -541,7 +541,7 @@ CCMD (mapchecksum) } for (int i = 1; i < argv.argc(); ++i) { - map = P_OpenMapData(argv[i]); + map = P_OpenMapData(argv[i], true); if (map == NULL) { Printf("Cannot load %s as a map\n", argv[i]); diff --git a/src/g_level.cpp b/src/g_level.cpp index 7e56d8843..0b07ae2b5 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1923,7 +1923,7 @@ CCMD(listmaps) for(unsigned i = 0; i < wadlevelinfos.Size(); i++) { level_info_t *info = &wadlevelinfos[i]; - MapData *map = P_OpenMapData(info->mapname); + MapData *map = P_OpenMapData(info->mapname, true); if (map != NULL) { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 784e6946f..3693e9f7e 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -250,7 +250,7 @@ static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname, // //=========================================================================== -MapData *P_OpenMapData(const char * mapname) +MapData *P_OpenMapData(const char * mapname, bool justcheck) { MapData * map = new MapData; FileReader * wadReader = NULL; @@ -331,13 +331,18 @@ MapData *P_OpenMapData(const char * mapname) const char * lumpname = Wads.GetLumpFullName(lump_name + i); try { - index = GetMapIndex(mapname, index, lumpname, true); + index = GetMapIndex(mapname, index, lumpname, !justcheck); } catch(...) { delete map; throw; } + if (index == -2) + { + delete map; + return NULL; + } if (index == ML_BEHAVIOR) map->HasBehavior = true; // The next lump is not part of this map anymore @@ -471,13 +476,18 @@ MapData *P_OpenMapData(const char * mapname) { try { - index = GetMapIndex(maplabel, index, lumpname, true); + index = GetMapIndex(maplabel, index, lumpname, !justcheck); } catch(...) { delete map; throw; } + if (index == -2) + { + delete map; + return NULL; + } if (index == ML_BEHAVIOR) map->HasBehavior = true; // The next lump is not part of this map anymore @@ -508,7 +518,7 @@ MapData *P_OpenMapData(const char * mapname) bool P_CheckMapData(const char *mapname) { - MapData *mapd = P_OpenMapData(mapname); + MapData *mapd = P_OpenMapData(mapname, true); if (mapd == NULL) return false; delete mapd; return true; @@ -3610,7 +3620,7 @@ void P_SetupLevel (char *lumpname, int position) P_FreeLevelData (); interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. - MapData *map = P_OpenMapData(lumpname); + MapData *map = P_OpenMapData(lumpname, true); if (map == NULL) { I_Error("Unable to open map '%s'\n", lumpname); diff --git a/src/p_setup.h b/src/p_setup.h index 6e0a90a1d..4a41a76f9 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -94,7 +94,7 @@ struct MapData void GetChecksum(BYTE cksum[16]); }; -MapData * P_OpenMapData(const char * mapname); +MapData * P_OpenMapData(const char * mapname, bool justcheck); bool P_CheckMapData(const char * mapname); diff --git a/src/statistics.cpp b/src/statistics.cpp index aa8d9afc1..81cd88983 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -463,7 +463,7 @@ void STAT_ChangeLevel(const char *newl) { // we reached the end of this episode int wad = 0; - MapData * map = P_OpenMapData(StartEpisode->mEpisodeMap); + MapData * map = P_OpenMapData(StartEpisode->mEpisodeMap, false); if (map != NULL) { wad = Wads.GetLumpFile(map->lumpnum); From 260ce62175e0a6f16bcc2fa6a61c2399db7633d6 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 30 Aug 2013 23:10:20 -0500 Subject: [PATCH 9/9] Don't abort for TEXTUREx lumps that define textures with no patches - A texture defined in TEXTUREx without any patches isn't necessarily an error, so accept. This also means they shouldn't be used for determining if a TEXTURE directory belongs to Strife instead of Doom. --- src/textures/multipatchtexture.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 3083735a9..fd2b59fb1 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -233,13 +233,13 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl NumParts = SAFESHORT(mtexture.d->patchcount); } - if (NumParts <= 0) + if (NumParts < 0) { I_FatalError ("Bad texture directory"); } UseType = FTexture::TEX_Wall; - Parts = new TexPart[NumParts]; + Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; Width = SAFESHORT(mtexture.d->width); Height = SAFESHORT(mtexture.d->height); strncpy (Name, (const char *)mtexture.d->name, 8); @@ -906,7 +906,7 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d // There is bizzarely a Doom editing tool that writes to the // first two elements of columndirectory, so I can't check those. - if (SAFESHORT(tex->patchcount) <= 0 || + if (SAFESHORT(tex->patchcount) < 0 || tex->columndirectory[2] != 0 || tex->columndirectory[3] != 0) {