diff --git a/CMakeLists.txt b/CMakeLists.txt index 453718045..1d8899603 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,11 @@ -cmake_minimum_required( VERSION 2.8.7 ) +cmake_minimum_required( VERSION 3.1.0 ) project(Demolition) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + + if( COMMAND cmake_policy ) if( POLICY CMP0011 ) cmake_policy( SET CMP0011 NEW ) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index ccf90b616..162793ccf 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 2.8.7 ) +cmake_minimum_required( VERSION 3.1.0 ) include(precompiled_headers) @@ -789,6 +789,7 @@ set (PCH_SOURCES common/gamecvars.cpp common/gamecontrol.cpp common/inputstate.cpp + common/searchpaths.cpp common/2d/v_2ddrawer.cpp common/2d/v_draw.cpp diff --git a/source/blood/CMakeLists.txt b/source/blood/CMakeLists.txt index 83b8a2c10..250ff20a2 100644 --- a/source/blood/CMakeLists.txt +++ b/source/blood/CMakeLists.txt @@ -1,8 +1,4 @@ -cmake_minimum_required( VERSION 2.8.7 ) - -if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" ) -endif() +cmake_minimum_required( VERSION 3.1.0 ) if (MSVC) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /J" ) diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp index 828668a35..3d9ed8e71 100644 --- a/source/build/src/sdlayer.cpp +++ b/source/build/src/sdlayer.cpp @@ -475,6 +475,9 @@ GameInterface *CheckFrontend() void ChooseGame() { + gi = CheckFrontend(); + return; +#if 0 auto dir = Args->CheckValue("-game"); if (dir && !chdir(dir)) { @@ -548,6 +551,7 @@ void ChooseGame() } if (gi == nullptr) exit(1); } +#endif } diff --git a/source/common/filesystem/file_directory.cpp b/source/common/filesystem/file_directory.cpp index 3bc15b951..1cfc68a90 100644 --- a/source/common/filesystem/file_directory.cpp +++ b/source/common/filesystem/file_directory.cpp @@ -126,7 +126,7 @@ int FDirectory::AddDirectory(const char *dirpath) dirmatch += '*'; - if ((handle = _wfindfirst(wdirmatch, &fileinfo)) == -1) + if ((handle = _wfindfirst(dirmatch.c_str(), &fileinfo)) == -1) { Printf("Could not scan '%s': %s\n", dirpath, strerror(errno)); } @@ -157,7 +157,7 @@ int FDirectory::AddDirectory(const char *dirpath) } else { - if (strstr(fileinfo.name, ".orig") || strstr(fileinfo.name, ".bak")) + if (strstr(fi, ".orig") || strstr(fi, ".bak")) { // We shouldn't add backup files to the lump directory continue; diff --git a/source/common/gameconfigfile.cpp b/source/common/gameconfigfile.cpp index dd5c5f57f..96cd9be49 100644 --- a/source/common/gameconfigfile.cpp +++ b/source/common/gameconfigfile.cpp @@ -554,10 +554,14 @@ CCMD (whereisini) FGameConfigFile* GameConfig; static FString GameName; -void G_LoadConfig(const char* game) +void G_LoadConfig() { OSD_Init(); GameConfig = new FGameConfigFile(); +} + +void G_ReadConfig(const char* game) +{ GameConfig->DoGlobalSetup(); GameConfig->DoGameSetup(game); GameConfig->DoKeySetup(game); diff --git a/source/common/gameconfigfile.h b/source/common/gameconfigfile.h index 1a52dc890..7fb43561a 100644 --- a/source/common/gameconfigfile.h +++ b/source/common/gameconfigfile.h @@ -72,7 +72,8 @@ private: }; extern FGameConfigFile *GameConfig; -void G_LoadConfig(const char*); +void G_LoadConfig(); +void G_ReadConfig(const char*); void G_SaveConfig(); #endif //__GAMECONFIGFILE_H__ diff --git a/source/common/gamecontrol.cpp b/source/common/gamecontrol.cpp index 7948fe0fb..49dba9c6d 100644 --- a/source/common/gamecontrol.cpp +++ b/source/common/gamecontrol.cpp @@ -17,6 +17,7 @@ InputState inputState; void SetClipshapes(); +TArray CollectSearchPaths(); struct GameFuncNameDesc { @@ -295,9 +296,6 @@ void UserConfig::ProcessOptions() void CONFIG_Init() { - LumpFilter = currentGame; - if (LumpFilter.Compare("Redneck") == 0) LumpFilter = "Redneck.Redneck"; - else if (LumpFilter.Compare("RedneckRides") == 0) LumpFilter = "Redneck.RidesAgain"; SetClipshapes(); // This must be done before initializing any data, so doing it late in the startup process won't work. @@ -307,10 +305,22 @@ void CONFIG_Init() } userConfig.ProcessOptions(); - CONFIG_ReadCombatMacros(); - + G_LoadConfig(); // Startup dialog must be presented here so that everything can be set up before reading the keybinds. - G_LoadConfig(currentGame); + + TArray paths = CollectSearchPaths(); + for (auto& path : paths) + { + OutputDebugStringA(path); + OutputDebugStringA("\r\n"); + } + LumpFilter = currentGame; + if (LumpFilter.Compare("Redneck") == 0) LumpFilter = "Redneck.Redneck"; + else if (LumpFilter.Compare("RedneckRides") == 0) LumpFilter = "Redneck.RidesAgain"; + + CONFIG_ReadCombatMacros(); + G_ReadConfig(currentGame); + if (userConfig.CommandName.IsNotEmpty()) { @@ -318,7 +328,6 @@ void CONFIG_Init() } - int index = 0; for(auto &gf : gamefuncs) { diff --git a/source/common/i_specialpaths.h b/source/common/i_specialpaths.h index a1ef210b1..092c7f47f 100644 --- a/source/common/i_specialpaths.h +++ b/source/common/i_specialpaths.h @@ -12,6 +12,10 @@ FString M_GetScreenshotsPath(); FString M_GetSavegamesPath(); FString M_GetDocumentsPath(); +#ifdef _WIN32 +int ReadRegistryValue(char const* const SubKey, char const* const Value, char* const Output, unsigned long* OutputSize); +#endif + #ifdef __APPLE__ FString M_GetMacAppSupportPath(const bool create = true); void M_GetMacSearchDirectories(FString& user_docs, FString& user_app_support, FString& local_app_support); diff --git a/source/common/searchpaths.cpp b/source/common/searchpaths.cpp index 2feaa321a..3e9ad329b 100644 --- a/source/common/searchpaths.cpp +++ b/source/common/searchpaths.cpp @@ -21,42 +21,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- +#include +#include "i_specialpaths.h" +#include "compat.h" +#include "gameconfigfile.h" +#include "cmdlib.h" +#include "utf8.h" // // Search path management // +namespace fs = std::filesystem; -#if defined _WIN32 -//------------------------------------------------------------------------- -// -// -// -//------------------------------------------------------------------------- -static int G_ReadRegistryValue(char const * const SubKey, char const * const Value, char * const Output, DWORD * OutputSize) -{ - // KEY_WOW64_32KEY gets us around Wow6432Node on 64-bit builds - REGSAM const wow64keys[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY }; - - for (auto &wow64key : wow64keys) - { - HKEY hkey; - LONG keygood = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NULL, 0, KEY_READ | wow64key, &hkey); - - if (keygood != ERROR_SUCCESS) - continue; - - LONG retval = SHGetValueA(hkey, SubKey, Value, NULL, Output, OutputSize); - - RegCloseKey(hkey); - - if (retval == ERROR_SUCCESS) - return 1; - } - - return 0; -} -#elif defined (__APPLE__) || defined (__FreeBSD__) || defined(__OpenBSD__) || defined (__linux__) +#ifndef _WIN32 //------------------------------------------------------------------------- // // @@ -346,14 +324,14 @@ void G_AddExternalSearchPaths(TArray &searchpaths) // Duke Nukem 3D: 20th Anniversary World Tour (Steam) bufsize = sizeof(buf); - if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 434050)", "InstallLocation", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 434050)", "InstallLocation", buf, &bufsize)) { searchpaths.Push(buf); } // Duke Nukem 3D: Megaton Edition (Steam) bufsize = sizeof(buf); - if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 225140)", "InstallLocation", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 225140)", "InstallLocation", buf, &bufsize)) { char * const suffix = buf + bufsize - 1; size_t const remaining = sizeof(buf) - bufsize; @@ -370,7 +348,7 @@ void G_AddExternalSearchPaths(TArray &searchpaths) // Duke Nukem 3D (3D Realms Anthology (Steam) / Kill-A-Ton Collection 2015) bufsize = sizeof(buf); - if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 359850)", "InstallLocation", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 359850)", "InstallLocation", buf, &bufsize)) { char * const suffix = buf + bufsize - 1; size_t const remaining = sizeof(buf) - bufsize; @@ -381,25 +359,25 @@ void G_AddExternalSearchPaths(TArray &searchpaths) // Duke Nukem 3D: Atomic Edition (GOG.com) bufsize = sizeof(buf); - if (G_ReadRegistryValue("SOFTWARE\\GOG.com\\GOGDUKE3D", "PATH", buf, &bufsize)) + if (ReadRegistryValue("SOFTWARE\\GOG.com\\GOGDUKE3D", "PATH", buf, &bufsize)) { searchpaths.Push(buf); } // Duke Nukem 3D (3D Realms Anthology) bufsize = sizeof(buf); - if (G_ReadRegistryValue("SOFTWARE\\3DRealms\\Duke Nukem 3D", NULL, buf, &bufsize)) + if (ReadRegistryValue("SOFTWARE\\3DRealms\\Duke Nukem 3D", NULL, buf, &bufsize)) { char * const suffix = buf + bufsize - 1; size_t const remaining = sizeof(buf) - bufsize; - Bstrncpy(suffix, "/Duke Nukem 3D", remaining); + strncpy(suffix, "/Duke Nukem 3D", remaining); searchpaths.Push(buf); } // 3D Realms Anthology bufsize = sizeof(buf); - if (G_ReadRegistryValue("SOFTWARE\\3DRealms\\Anthology", NULL, buf, &bufsize)) + if (ReadRegistryValue("SOFTWARE\\3DRealms\\Anthology", NULL, buf, &bufsize)) { char * const suffix = buf + bufsize - 1; size_t const remaining = sizeof(buf) - bufsize; @@ -410,7 +388,7 @@ void G_AddExternalSearchPaths(TArray &searchpaths) // NAM (Steam) bufsize = sizeof(buf); - if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 329650)", "InstallLocation", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 329650)", "InstallLocation", buf, &bufsize)) { char * const suffix = buf + bufsize - 1; size_t const remaining = sizeof(buf) - bufsize; @@ -421,7 +399,7 @@ void G_AddExternalSearchPaths(TArray &searchpaths) // WWII GI (Steam) bufsize = sizeof(buf); - if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 376750)", "InstallLocation", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 376750)", "InstallLocation", buf, &bufsize)) { char * const suffix = buf + bufsize - 1; size_t const remaining = sizeof(buf) - bufsize; @@ -432,35 +410,35 @@ void G_AddExternalSearchPaths(TArray &searchpaths) // Redneck Rampage (GOG.com) bufsize = sizeof(buf); - if (G_ReadRegistryValue("SOFTWARE\\GOG.com\\GOGREDNECKRAMPAGE", "PATH", buf, &bufsize)) + if (ReadRegistryValue("SOFTWARE\\GOG.com\\GOGREDNECKRAMPAGE", "PATH", buf, &bufsize)) { searchpaths.Push(buf); } // Redneck Rampage Rides Again (GOG.com) bufsize = sizeof(buf); - if (G_ReadRegistryValue("SOFTWARE\\GOG.com\\GOGCREDNECKRIDESAGAIN", "PATH", buf, &bufsize)) + if (ReadRegistryValue("SOFTWARE\\GOG.com\\GOGCREDNECKRIDESAGAIN", "PATH", buf, &bufsize)) { searchpaths.Push(buf); } // Blood: One Unit Whole Blood (Steam) bufsize = sizeof(buf); - if (G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 299030)", "InstallLocation", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 299030)", "InstallLocation", buf, &bufsize)) { searchpaths.Push(buf); } // Blood: One Unit Whole Blood (GOG.com) bufsize = sizeof(buf); - if (G_ReadRegistryValue("SOFTWARE\\GOG.com\\GOGONEUNITONEBLOOD", "PATH", buf, &bufsize)) + if (ReadRegistryValue("SOFTWARE\\GOG.com\\GOGONEUNITONEBLOOD", "PATH", buf, &bufsize)) { searchpaths.Push(buf); } // Blood: Fresh Supply (Steam) bufsize = sizeof(buf); - if (!found && G_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 1010750)", "InstallLocation", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 1010750)", "InstallLocation", buf, &bufsize)) { searchpaths.Push(buf); strncat(buf, R"(\addons\Cryptic Passage)", 23); @@ -469,7 +447,7 @@ void G_AddExternalSearchPaths(TArray &searchpaths) // Blood: Fresh Supply (GOG.com) bufsize = sizeof(buf); - if (!found && G_ReadRegistryValue(R"(SOFTWARE\Wow6432Node\GOG.com\Games\1374469660)", "path", buf, &bufsize)) + if (ReadRegistryValue(R"(SOFTWARE\Wow6432Node\GOG.com\Games\1374469660)", "path", buf, &bufsize)) { searchpaths.Push(buf); strncat(buf, R"(\addons\Cryptic Passage)", 23); @@ -478,18 +456,7 @@ void G_AddExternalSearchPaths(TArray &searchpaths) } #endif -//------------------------------------------------------------------------- -// -// -// -//------------------------------------------------------------------------- -void AddExpandedPath(TArray &searchpaths, const char *basepath) -{ - -} - -#ifdef _WIN32 //========================================================================== // // Windows version @@ -498,109 +465,29 @@ void AddExpandedPath(TArray &searchpaths, const char *basepath) void CollectSubdirectories(TArray &searchpath, const char *dirmatch) { - struct _wfinddata_t fileinfo; - intptr_t handle; - FString dirpath; - int count = 0; - auto wdirmatch = WideString(dirmatch); - - dirpath.Truncate(dirpath.Len()-1); // remove the '*' - - if ((handle = _wfindfirst(wdirmatch, &fileinfo)) == -1) + try { - // silently ignore non-existent paths - return; - } - else - { - do + FString dirpath = MakeUTF8(dirmatch); // convert into clean UTF-8 + dirpath.Truncate(dirpath.Len() - 1); // remove the '*' + fs::path path = fs::u8path(dirpath.GetChars()); + if (fs::exists(path) && fs::is_directory(path)) { - if (fileinfo.attrib & _A_HIDDEN) + for (const auto& entry : fs::directory_iterator(path)) { - // Skip hidden files and directories. (Prevents SVN bookkeeping - // info from being included.) - continue; - } - FString fi = FString(fileinfo.name); - if (fileinfo.attrib & _A_SUBDIR) - { - - if (fi[0] == '.' && - (fi[1] == '\0' || - (fi[1] == '.' && fi[2] == '\0'))) + if (fs::is_directory(entry.status())) { - // Do not record . and .. directories. - continue; + auto filename = entry.path().filename().u8string(); + FString newdir = dirpath + filename.c_str(); + searchpath.Push(newdir); } - FString newdir = dirpath + fi; - count += AddDirectory(newdir); } - } while (_wfindnext(handle, &fileinfo) == 0); - _findclose(handle); + } } - return count; -} - -#else - -//========================================================================== -// -// add_dirs -// 4.4BSD version -// -//========================================================================== - -void FDirectory::AddDirectory(const char *dirpath) -{ - char *argv [2] = { NULL, NULL }; - argv[0] = new char[strlen(dirpath)+1]; - strcpy(argv[0], dirpath); - FTS *fts; - FTSENT *ent; - - fts = fts_open(argv, FTS_LOGICAL, NULL); - if (fts == NULL) + catch (fs::filesystem_error &) { - return 0; + // Just ignore this path if it caused an error. } - - const size_t namepos = strlen(dirpath); - FString pathfix; - - while ((ent = fts_read(fts)) != NULL) - { - if (ent->fts_info != FTS_D) - { - // We're only interested in getting directories. - continue; - } - fts_set(fts, ent, FTS_SKIP); - if (ent->fts_name[0] == '.') - { - // Skip hidden directories. (Prevents SVN bookkeeping - // info from being included.) - } - - // Some implementations add an extra separator between - // root of the hierarchy and entity's path. - // It needs to be removed in order to resolve - // lumps' relative paths properly. - const char* path = ent->fts_path; - - if ('/' == path[namepos]) - { - pathfix = FString(path, namepos); - pathfix.AppendCStrPart(&path[namepos + 1], ent->fts_pathlen - namepos - 1); - - path = pathfix.GetChars(); - } - - searchpaths.Push(path); - } - fts_close(fts); - delete[] argv[0]; } -#endif //========================================================================== // @@ -612,7 +499,7 @@ void FDirectory::AddDirectory(const char *dirpath) TArray CollectSearchPaths() { - TArray searchpths; + TArray searchpaths; if (GameConfig->SetSection("GameSearch.Directories")) { @@ -627,31 +514,33 @@ TArray CollectSearchPaths() if (nice.Len() > 0) { #ifdef _WIN32 - if (isalpha(nice[0] && nice[1] == ':' && nice[2] != '/') continue; // ignore drive relative paths because they are meaningless. + if (isalpha(nice[0] && nice[1] == ':' && nice[2] != '/')) continue; // ignore drive relative paths because they are meaningless. #endif // A path ending with "/*" means to add all subdirectories. if (nice[nice.Len()-2] == '/' && nice[nice.Len()-1] == '*') { - AddExpandedPath(searchpaths, nice); + CollectSubdirectories(searchpaths, nice); } // Checking Steam via a list entry allows easy removal if not wanted. - else if (nice.CompareNoCase("$STEAM")) + else if (nice.CompareNoCase("$STEAM") == 0) { G_AddExternalSearchPaths(searchpaths); } else { - mSearchPaths.Push(nice); + searchpaths.Push(nice); } } } } } // Unify and remove trailing slashes - for (auto &str : mSearchPaths) + for (auto &str : searchpaths) { str.Substitute("\\", "/"); + str.Substitute("//", "/"); // Double slashes can happen when constructing paths so just get rid of them here. if (str.Back() == '/') str.Truncate(str.Len() - 1); } + return searchpaths; } diff --git a/source/duke3d/CMakeLists.txt b/source/duke3d/CMakeLists.txt index 153ad1f71..cc2f42243 100644 --- a/source/duke3d/CMakeLists.txt +++ b/source/duke3d/CMakeLists.txt @@ -1,8 +1,4 @@ -cmake_minimum_required( VERSION 2.8.7 ) - -if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" ) -endif() +cmake_minimum_required( VERSION 3.1.0 ) if (MSVC) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /J" ) diff --git a/source/platform/win32/i_specialpaths.cpp b/source/platform/win32/i_specialpaths.cpp index e9c9bd41b..466972856 100644 --- a/source/platform/win32/i_specialpaths.cpp +++ b/source/platform/win32/i_specialpaths.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include "i_specialpaths.h" #include "printf.h" @@ -334,3 +335,35 @@ FString M_GetDocumentsPath() } return path; } + +//=========================================================================== +// +// ReadRegistryValue Windows +// +// Reads a value from the registry +// +//=========================================================================== + +int ReadRegistryValue(char const* const SubKey, char const* const Value, char* const Output, unsigned long* OutputSize) +{ + // KEY_WOW64_32KEY gets us around Wow6432Node on 64-bit builds + REGSAM const wow64keys[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY }; + + for (auto& wow64key : wow64keys) + { + HKEY hkey; + LONG keygood = RegOpenKeyExA(HKEY_LOCAL_MACHINE, NULL, 0, KEY_READ | wow64key, &hkey); + + if (keygood != ERROR_SUCCESS) + continue; + + LONG retval = SHGetValueA(hkey, SubKey, Value, NULL, Output, OutputSize); + + RegCloseKey(hkey); + + if (retval == ERROR_SUCCESS) + return 1; + } + + return 0; +} diff --git a/source/rr/CMakeLists.txt b/source/rr/CMakeLists.txt index 2aaf3c322..609bfc634 100644 --- a/source/rr/CMakeLists.txt +++ b/source/rr/CMakeLists.txt @@ -1,8 +1,4 @@ -cmake_minimum_required( VERSION 2.8.7 ) - -if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" ) -endif() +cmake_minimum_required( VERSION 3.1.0 ) if (MSVC) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /J" ) diff --git a/source/sw/CMakeLists.txt b/source/sw/CMakeLists.txt index 59bf7a64e..529a6cbfd 100644 --- a/source/sw/CMakeLists.txt +++ b/source/sw/CMakeLists.txt @@ -1,8 +1,4 @@ -cmake_minimum_required( VERSION 2.8.7 ) - -if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" ) -endif() +cmake_minimum_required( VERSION 3.1.0 ) if (MSVC) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /J" )