mirror of https://github.com/AxioDL/metaforce.git
106 lines
3.3 KiB
C++
106 lines
3.3 KiB
C++
#include "hecl/SteamFinder.hpp"
|
|
#include "hecl/hecl.hpp"
|
|
#ifdef WIN32
|
|
#include <winreg.h>
|
|
#define PATH_SEP L'\\'
|
|
#else
|
|
#define PATH_SEP '/'
|
|
#endif
|
|
|
|
namespace hecl {
|
|
|
|
/* Used to extract alternate steam install directories from libraryfolders.vdf */
|
|
static const std::regex regSteamPath(R"(^\s+\"[0-9]+\"\s+\"(.*)\")", std::regex::ECMAScript | std::regex::optimize);
|
|
|
|
hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name) {
|
|
hecl::SystemString steamInstallDir;
|
|
hecl::Sstat theStat;
|
|
|
|
#ifdef WIN32
|
|
#if !WINDOWS_STORE
|
|
HKEY hkey;
|
|
hecl::SystemChar _steamInstallDir[MAX_PATH] = {0};
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _SYS_STR("Software\\Valve\\Steam"), 0, KEY_QUERY_VALUE, &hkey) !=
|
|
ERROR_SUCCESS) {
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _SYS_STR("Software\\Valve\\Steam"), 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY,
|
|
&hkey) != ERROR_SUCCESS)
|
|
return {};
|
|
}
|
|
|
|
DWORD size = MAX_PATH;
|
|
if (RegQueryValueEx(hkey, _SYS_STR("InstallPath"), nullptr, nullptr, (LPBYTE)_steamInstallDir, &size) ==
|
|
ERROR_SUCCESS)
|
|
steamInstallDir = _steamInstallDir;
|
|
RegCloseKey(hkey);
|
|
|
|
if (steamInstallDir.empty())
|
|
return {};
|
|
#else
|
|
return {};
|
|
#endif
|
|
|
|
#elif defined(__APPLE__)
|
|
steamInstallDir = getenv("HOME");
|
|
steamInstallDir += "/Library/Application Support/Steam";
|
|
if (hecl::Stat(steamInstallDir.c_str(), &theStat) || !S_ISDIR(theStat.st_mode))
|
|
return {};
|
|
|
|
#else
|
|
steamInstallDir = getenv("HOME");
|
|
steamInstallDir += "/.local/share/Steam";
|
|
if (hecl::Stat(steamInstallDir.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) {
|
|
steamInstallDir = getenv("HOME");
|
|
steamInstallDir += "/.steam/steam";
|
|
if (hecl::Stat(steamInstallDir.c_str(), &theStat) || !S_ISDIR(theStat.st_mode))
|
|
return {};
|
|
}
|
|
|
|
#endif
|
|
|
|
const hecl::SystemString appPath = hecl::SystemString(_SYS_STR("common")) + PATH_SEP + name;
|
|
|
|
/* Try main steam install directory first */
|
|
const hecl::SystemString steamAppsMain = steamInstallDir + PATH_SEP + _SYS_STR("steamapps");
|
|
const hecl::SystemString mainAppPath = steamAppsMain + PATH_SEP + appPath;
|
|
if (!hecl::Stat(mainAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) {
|
|
return mainAppPath;
|
|
}
|
|
|
|
/* Iterate alternate steam install dirs */
|
|
const hecl::SystemString libraryFoldersVdfPath = steamAppsMain + PATH_SEP + _SYS_STR("libraryfolders.vdf");
|
|
auto fp = hecl::FopenUnique(libraryFoldersVdfPath.c_str(), _SYS_STR("r"));
|
|
if (fp == nullptr) {
|
|
return {};
|
|
}
|
|
hecl::FSeek(fp.get(), 0, SEEK_END);
|
|
const int64_t fileLen = hecl::FTell(fp.get());
|
|
if (fileLen <= 0) {
|
|
return {};
|
|
}
|
|
hecl::FSeek(fp.get(), 0, SEEK_SET);
|
|
std::string fileBuf(fileLen, '\0');
|
|
if (std::fread(fileBuf.data(), 1, fileLen, fp.get()) != fileLen) {
|
|
return {};
|
|
}
|
|
|
|
std::smatch dirMatch;
|
|
auto begin = fileBuf.cbegin();
|
|
const auto end = fileBuf.cend();
|
|
while (std::regex_search(begin, end, dirMatch, regSteamPath)) {
|
|
const std::string match = dirMatch[1].str();
|
|
const hecl::SystemStringConv otherInstallDir(match);
|
|
const auto otherAppPath =
|
|
hecl::SystemString(otherInstallDir.sys_str()) + PATH_SEP + _SYS_STR("steamapps") + PATH_SEP + appPath;
|
|
|
|
if (!hecl::Stat(otherAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) {
|
|
return otherAppPath;
|
|
}
|
|
|
|
begin = dirMatch.suffix().first;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
} // namespace hecl
|