You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
4.0 KiB
176 lines
4.0 KiB
#include "utils/paths.h" |
|
|
|
#include <string> |
|
|
|
#include <SDL.h> |
|
|
|
#include "appfat.h" |
|
#include "utils/file_util.h" |
|
#include "utils/log.hpp" |
|
#include "utils/sdl_ptrs.h" |
|
#include "utils/stdcompat/optional.hpp" |
|
|
|
#ifdef __IPHONEOS__ |
|
#include "platform/ios/ios_paths.h" |
|
#endif |
|
|
|
#ifdef NXDK |
|
#define NOMINMAX 1 |
|
#define WIN32_LEAN_AND_MEAN |
|
#include <windows.h> |
|
#endif |
|
|
|
#ifdef USE_SDL1 |
|
#include "utils/sdl2_to_1_2_backports.h" |
|
#endif |
|
|
|
namespace devilution { |
|
|
|
namespace paths { |
|
|
|
namespace { |
|
|
|
std::optional<std::string> basePath; |
|
std::optional<std::string> prefPath; |
|
std::optional<std::string> configPath; |
|
std::optional<std::string> assetsPath; |
|
|
|
void AddTrailingSlash(std::string &path) |
|
{ |
|
if (!path.empty() && path.back() != DirectorySeparator) |
|
path += DirectorySeparator; |
|
} |
|
|
|
std::string FromSDL(char *s) |
|
{ |
|
SDLUniquePtr<char> pinned(s); |
|
std::string result = (s != nullptr ? s : ""); |
|
if (s == nullptr) { |
|
Log("{}", SDL_GetError()); |
|
SDL_ClearError(); |
|
} |
|
return result; |
|
} |
|
|
|
#ifdef NXDK |
|
const std::string &NxdkGetPrefPath() |
|
{ |
|
static const std::string Path = []() { |
|
const char *path = "E:\\UDATA\\devilutionx\\"; |
|
if (CreateDirectoryA(path, nullptr) == FALSE && ::GetLastError() != ERROR_ALREADY_EXISTS) { |
|
DirErrorDlg(path); |
|
} |
|
return path; |
|
}(); |
|
return Path; |
|
} |
|
#endif |
|
|
|
} // namespace |
|
|
|
const std::string &BasePath() |
|
{ |
|
if (!basePath) { |
|
basePath = FromSDL(SDL_GetBasePath()); |
|
} |
|
return *basePath; |
|
} |
|
|
|
const std::string &PrefPath() |
|
{ |
|
if (!prefPath) { |
|
#if defined(__IPHONEOS__) |
|
prefPath = FromSDL(IOSGetPrefPath()); |
|
#elif defined(NXDK) |
|
prefPath = NxdkGetPrefPath(); |
|
#else |
|
prefPath = FromSDL(SDL_GetPrefPath("diasurgical", "devilution")); |
|
#if !defined(__amigaos__) |
|
if (FileExistsAndIsWriteable("diablo.ini")) { |
|
prefPath = std::string("." DIRECTORY_SEPARATOR_STR); |
|
} |
|
#endif |
|
#endif |
|
} |
|
return *prefPath; |
|
} |
|
|
|
const std::string &ConfigPath() |
|
{ |
|
if (!configPath) { |
|
#if defined(__IPHONEOS__) |
|
configPath = FromSDL(IOSGetPrefPath()); |
|
#elif defined(NXDK) |
|
configPath = NxdkGetPrefPath(); |
|
#else |
|
configPath = FromSDL(SDL_GetPrefPath("diasurgical", "devilution")); |
|
#if !defined(__amigaos__) |
|
if (FileExistsAndIsWriteable("diablo.ini")) { |
|
configPath = std::string("." DIRECTORY_SEPARATOR_STR); |
|
} |
|
#endif |
|
#endif |
|
} |
|
return *configPath; |
|
} |
|
|
|
const std::string &AssetsPath() |
|
{ |
|
if (!assetsPath) { |
|
#if __EMSCRIPTEN__ |
|
assetsPath.emplace("assets/"); |
|
#elif defined(NXDK) |
|
assetsPath.emplace("D:\\assets\\"); |
|
#elif defined(__3DS__) || defined(__SWITCH__) |
|
assetsPath.emplace("romfs:/"); |
|
#elif defined(__APPLE__) && defined(USE_SDL1) |
|
// In `Info.plist` we have |
|
// |
|
// <key>SDL_FILESYSTEM_BASE_DIR_TYPE</key> |
|
// <string>resource</string> |
|
// |
|
// This means `SDL_GetBasePath()` returns exedir for non-bundled |
|
// and the `app_dir.app/Resources/` for bundles. |
|
// |
|
// Our built-in resources are directly in the `devilutionx.app/Resources` directory |
|
// and are normally looked up via a relative lookup in `FindAsset`. |
|
// In SDL2, this is implemented by calling `SDL_OpenFPFromBundleOrFallback` |
|
// from `SDL_RWFromFile` but SDL1 doesn't do it, so we set the directory explicitly. |
|
// |
|
// Note that SDL3 reverts to SDL1 behaviour! |
|
// https://github.com/libsdl-org/SDL/blob/962268ca21ed10b9cee31198c22681099293f20a/docs/README-migration.md?plain=1#L1623 |
|
assetsPath.emplace(FromSDL(SDL_GetBasePath())); |
|
#else |
|
assetsPath.emplace(FromSDL(SDL_GetBasePath()) + ("assets" DIRECTORY_SEPARATOR_STR)); |
|
#endif |
|
} |
|
return *assetsPath; |
|
} |
|
|
|
void SetBasePath(const std::string &path) |
|
{ |
|
basePath = path; |
|
AddTrailingSlash(*basePath); |
|
} |
|
|
|
void SetPrefPath(const std::string &path) |
|
{ |
|
prefPath = path; |
|
AddTrailingSlash(*prefPath); |
|
} |
|
|
|
void SetConfigPath(const std::string &path) |
|
{ |
|
configPath = path; |
|
AddTrailingSlash(*configPath); |
|
} |
|
|
|
void SetAssetsPath(const std::string &path) |
|
{ |
|
assetsPath = path; |
|
AddTrailingSlash(*assetsPath); |
|
} |
|
|
|
} // namespace paths |
|
|
|
} // namespace devilution
|
|
|