diff --git a/source/blood/CMakeLists.txt b/source/blood/CMakeLists.txt index 306638486..263bcf1ea 100644 --- a/source/blood/CMakeLists.txt +++ b/source/blood/CMakeLists.txt @@ -55,6 +55,7 @@ set( PCH_SOURCES src/mirrors.cpp src/misc.cpp src/network.cpp + src/nnexts.cpp src/osdcmd.cpp src/player.cpp src/qav.cpp diff --git a/source/common/searchpaths.cpp b/source/common/searchpaths.cpp index 839deabe5..bd52ed57e 100644 --- a/source/common/searchpaths.cpp +++ b/source/common/searchpaths.cpp @@ -58,6 +58,7 @@ int g_gameType; void AddSearchPath(TArray& searchpaths, const char* path) { auto fpath = M_GetNormalizedPath(path); + if (fpath.Back() == '/') fpath.Truncate(fpath.Len() - 1); if (DirExists(fpath)) { if (searchpaths.Find(fpath) == searchpaths.Size()) @@ -83,8 +84,8 @@ void G_AddExternalSearchPaths(TArray &searchpaths) struct RegistryPathInfo { - const char *regPath; - const char *regKey; + const wchar_t *regPath; + const wchar_t *regKey; const char **subpaths; }; @@ -96,29 +97,39 @@ static const char * ww2gi[] = { "/WW2GI", nullptr}; static const char * bloodfs[] = { "", R"(\addons\Cryptic Passage)", nullptr}; static const char * sw[] = { "/Shadow Warrior", nullptr}; +#ifndef _WIN64 +#define WOW64 "\\" +#else +#define WOW64 "\\Wow6432Node\\" +#endif + static const RegistryPathInfo paths[] = { - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 434050)", "InstallLocation", nullptr }, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 225140)", "InstallLocation", dukeaddons }, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 359850)", "InstallLocation", dn3d }, - { "SOFTWARE\\GOG.com\\GOGDUKE3D", "PATH", nullptr }, - { "SOFTWARE\\3DRealms\\Duke Nukem 3D", nullptr, dn3d }, - { "SOFTWARE\\3DRealms\\Anthology", nullptr, dn3d }, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 329650)", "InstallLocation", nam }, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 376750)", "InstallLocation", ww2gi }, - { "SOFTWARE\\GOG.com\\GOGREDNECKRAMPAGE", "PATH", nullptr }, - { "SOFTWARE\\GOG.com\\GOGCREDNECKRIDESAGAIN", "PATH", nullptr }, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 299030)", "InstallLocation", nullptr }, // Blood: One Unit Whole Blood (Steam) - { "SOFTWARE\\GOG.com\\GOGONEUNITONEBLOOD", "PATH", nullptr}, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 1010750)", "InstallLocation", bloodfs}, - { R"(SOFTWARE\Wow6432Node\GOG.com\Games\1374469660)", "path", bloodfs}, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 225160)", "InstallLocation", gameroot }, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 238070)", "InstallLocation", gameroot}, // Shadow Warrior Classic (1997) - Steam - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 358400)", "InstallLocation", sw}, - { "SOFTWARE\\GOG.com\\GOGSHADOWARRIOR", "PATH", nullptr}, - { "SOFTWARE\\3DRealms\\Shadow Warrior", nullptr, sw}, - { "SOFTWARE\\3DRealms\\Anthology", nullptr, sw}, - { R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 562860)", "InstallLocation", nullptr}, // Ion Fury (Steam) - { R"(SOFTWARE\GOG.com\Games\1740836875)", "path", nullptr}, + { L"SOFTWARE" WOW64 "GOG.com\\GOGDUKE3D", L"PATH", nullptr }, + { L"SOFTWARE" WOW64 "GOG.com\\GOGREDNECKRAMPAGE", L"PATH", nullptr }, + { L"SOFTWARE" WOW64 "GOG.com\\GOGCREDNECKRIDESAGAIN", L"PATH", nullptr }, + { L"SOFTWARE" WOW64 "GOG.com\\GOGONEUNITONEBLOOD", L"PATH", nullptr}, + { L"SOFTWARE" WOW64 "GOG.com\\GOGSHADOWARRIOR", L"PATH", nullptr}, + { L"SOFTWARE" WOW64 "GOG.com\\Games\\1374469660", L"path", bloodfs}, + { L"SOFTWARE" WOW64 "GOG.com\\Games\\1740836875", L"path", nullptr}, + + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 434050", L"InstallLocation", nullptr }, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 225140", L"InstallLocation", dukeaddons }, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 359850", L"InstallLocation", dn3d }, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 329650", L"InstallLocation", nam }, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 376750", L"InstallLocation", ww2gi }, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 299030", L"InstallLocation", nullptr }, // Blood: One Unit Whole Blood (Steam) + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 1010750",L"InstallLocation", bloodfs}, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 225160", L"InstallLocation", gameroot }, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 238070", L"InstallLocation", gameroot}, // Shadow Warrior Classic (1997) - Steam + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 358400", L"InstallLocation", sw}, + { L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 562860", L"InstallLocation", nullptr}, // Ion Fury (Steam) +#if 0 + { L"SOFTWARE\\3DRealms\\Duke Nukem 3D", nullptr, dn3d }, + { L"SOFTWARE\\3DRealms\\Anthology", nullptr, dn3d }, + { L"SOFTWARE\\3DRealms\\Shadow Warrior", nullptr, sw}, + { L"SOFTWARE\\3DRealms\\Anthology", nullptr, sw}, +#endif + { nullptr} }; @@ -128,10 +139,10 @@ void G_AddExternalSearchPaths(TArray &searchpaths) for (auto &entry : paths) { // 3D Realms Anthology - char buf[PATH_MAX]; - size_t bufsize = sizeof(buf); - if (I_ReadRegistryValue(entry.regPath, entry.regKey, buf, &bufsize)) + FString buf; + if (I_QueryPathKey(entry.regPath, entry.regKey, buf)) { + FixPathSeperator(buf); if (!entry.subpaths) AddSearchPath(searchpaths, buf); else { diff --git a/source/platform/win32/i_system.cpp b/source/platform/win32/i_system.cpp index 6bdd904eb..291886093 100644 --- a/source/platform/win32/i_system.cpp +++ b/source/platform/win32/i_system.cpp @@ -979,145 +979,6 @@ const char *I_FindName(findstate_t *fileinfo) return fileinfo->UTF8Name.GetChars(); } -//========================================================================== -// -// QueryPathKey -// -// Returns the value of a registry key into the output variable value. -// -//========================================================================== - -static bool QueryPathKey(HKEY key, const wchar_t *keypath, const wchar_t *valname, FString &value) -{ - HKEY pathkey; - DWORD pathtype; - DWORD pathlen; - LONG res; - - value = ""; - if(ERROR_SUCCESS == RegOpenKeyEx(key, keypath, 0, KEY_QUERY_VALUE, &pathkey)) - { - if (ERROR_SUCCESS == RegQueryValueEx(pathkey, valname, 0, &pathtype, NULL, &pathlen) && - pathtype == REG_SZ && pathlen != 0) - { - // Don't include terminating null in count - TArray chars(pathlen + 1, true); - res = RegQueryValueEx(pathkey, valname, 0, NULL, (LPBYTE)chars.Data(), &pathlen); - if (res == ERROR_SUCCESS) value = FString(chars.Data()); - } - RegCloseKey(pathkey); - } - return value.IsNotEmpty(); -} - -//========================================================================== -// -// I_GetGogPaths -// -// Check the registry for GOG installation paths, so we can search for IWADs -// that were bought from GOG.com. This is a bit different from the Steam -// version because each game has its own independent installation path, no -// such thing as /SteamApps/common/. -// -//========================================================================== - -TArray I_GetGogPaths() -{ - TArray result; - FString path; - std::wstring gamepath; - -#ifdef _WIN64 - std::wstring gogregistrypath = L"Software\\Wow6432Node\\GOG.com\\Games"; -#else - // If a 32-bit ZDoom runs on a 64-bit Windows, this will be transparently and - // automatically redirected to the Wow6432Node address instead, so this address - // should be safe to use in all cases. - std::wstring gogregistrypath = L"Software\\GOG.com\\Games"; -#endif - - // Look for Ultimate Doom - gamepath = gogregistrypath + L"\\1435827232"; - if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) - { - result.Push(path); // directly in install folder - } - - // Look for Doom II - gamepath = gogregistrypath + L"\\1435848814"; - if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) - { - result.Push(path + "/doom2"); // in a subdirectory - // If direct support for the Master Levels is ever added, they are in path + /master/wads - } - - // Look for Final Doom - gamepath = gogregistrypath + L"\\1435848742"; - if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) - { - // in subdirectories - result.Push(path + "/TNT"); - result.Push(path + "/Plutonia"); - } - - // Look for Doom 3: BFG Edition - gamepath = gogregistrypath + L"\\1135892318"; - if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) - { - result.Push(path + "/base/wads"); // in a subdirectory - } - - // Look for Strife: Veteran Edition - gamepath = gogregistrypath + L"\\1432899949"; - if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) - { - result.Push(path); // directly in install folder - } - - return result; -} - -//========================================================================== -// -// I_GetSteamPath -// -// Check the registry for the path to Steam, so that we can search for -// IWADs that were bought with Steam. -// -//========================================================================== - -TArray I_GetSteamPath() -{ - TArray result; - static const char *const steam_dirs[] = - { - "doom 2/base", - "final doom/base", - "heretic shadow of the serpent riders/base", - "hexen/base", - "hexen deathkings of the dark citadel/base", - "ultimate doom/base", - "DOOM 3 BFG Edition/base/wads", - "Strife" - }; - - FString path; - - if (!QueryPathKey(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", L"SteamPath", path)) - { - if (!QueryPathKey(HKEY_LOCAL_MACHINE, L"Software\\Valve\\Steam", L"InstallPath", path)) - return result; - } - path += "/SteamApps/common/"; - - for(unsigned int i = 0; i < countof(steam_dirs); ++i) - { - result.Push(path + steam_dirs[i]); - } - - return result; -} - //========================================================================== // // I_MakeRNGSeed @@ -1294,35 +1155,34 @@ void I_SetThreadNumaNode(std::thread &thread, int numaNode) } } -# ifndef KEY_WOW64_64KEY -# define KEY_WOW64_64KEY 0x0100 -# endif -# ifndef KEY_WOW64_32KEY -# define KEY_WOW64_32KEY 0x0200 -# endif +//========================================================================== +// +// QueryPathKey +// +// Returns the value of a registry key into the output variable value. +// +//========================================================================== -int I_ReadRegistryValue(char const * const SubKey, char const * const Value, char * const Output, size_t * OutputSize) +bool I_QueryPathKey(const wchar_t* keypath, const wchar_t* valname, FString& value) { - // KEY_WOW64_32KEY gets us around Wow6432Node on 64-bit builds - REGSAM const wow64keys[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY }; + HKEY pathkey; + DWORD pathtype; + DWORD pathlen; + LONG res; - for (auto &wow64key : wow64keys) - { - HKEY hkey; - LONG keygood = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NULL, 0, KEY_READ | wow64key, &hkey); - - if (keygood != ERROR_SUCCESS) - continue; - - DWORD os = 0; - LONG retval = SHGetValueA(hkey, SubKey, Value, NULL, Output, &os); - *OutputSize = os; - - RegCloseKey(hkey); - - if (retval == ERROR_SUCCESS) - return 1; - } - - return 0; + value = ""; + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, keypath, 0, KEY_QUERY_VALUE, &pathkey)) + { + if (ERROR_SUCCESS == RegQueryValueEx(pathkey, valname, 0, &pathtype, NULL, &pathlen) && + pathtype == REG_SZ && pathlen != 0) + { + // Don't include terminating null in count + TArray chars(pathlen + 1, true); + res = RegQueryValueEx(pathkey, valname, 0, NULL, (LPBYTE)chars.Data(), &pathlen); + if (res == ERROR_SUCCESS) value = FString(chars.Data()); + } + RegCloseKey(pathkey); + } + return value.IsNotEmpty(); } + diff --git a/source/platform/win32/i_system.h b/source/platform/win32/i_system.h index fac4d60ea..308997b3f 100644 --- a/source/platform/win32/i_system.h +++ b/source/platform/win32/i_system.h @@ -153,7 +153,6 @@ inline int I_FindAttr(findstate_t *fileinfo) int I_GetNumaNodeCount(); int I_GetNumaNodeThreadCount(int numaNode); void I_SetThreadNumaNode(std::thread &thread, int numaNode); - -int I_ReadRegistryValue(char const * const SubKey, char const * const Value, char * const Output, size_t * OutputSize); +bool I_QueryPathKey(const wchar_t* keypath, const wchar_t* valname, FString& value); #endif