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.
76 lines
2.3 KiB
76 lines
2.3 KiB
#include "engine/assets.hpp" |
|
|
|
#include <algorithm> |
|
#include <cstdint> |
|
#include <cstring> |
|
|
|
#include "init.h" |
|
#include "mpq/mpq_sdl_rwops.hpp" |
|
#include "utils/file_util.h" |
|
#include "utils/log.hpp" |
|
#include "utils/paths.h" |
|
|
|
namespace devilution { |
|
|
|
namespace { |
|
|
|
bool OpenMpqFile(const char *filename, MpqArchive **archive, uint32_t *fileNumber) |
|
{ |
|
const MpqArchive::FileHash fileHash = MpqArchive::CalculateFileHash(filename); |
|
const auto at = [=](std::optional<MpqArchive> &src) -> bool { |
|
if (src && src->GetFileNumber(fileHash, *fileNumber)) { |
|
*archive = &(*src); |
|
return true; |
|
} |
|
return false; |
|
}; |
|
|
|
return at(font_mpq) || at(lang_mpq) || at(devilutionx_mpq) |
|
|| (gbIsHellfire && (at(hfvoice_mpq) || at(hfmusic_mpq) || at(hfbarb_mpq) || at(hfbard_mpq) || at(hfmonk_mpq) || at(hellfire_mpq))) || at(spawn_mpq) || at(diabdat_mpq); |
|
} |
|
|
|
} // namespace |
|
|
|
SDL_RWops *OpenAsset(const char *filename, bool threadsafe) |
|
{ |
|
std::string relativePath = filename; |
|
#ifndef _WIN32 |
|
std::replace(relativePath.begin(), relativePath.end(), '\\', '/'); |
|
#endif |
|
|
|
if (relativePath[0] == '/') |
|
return SDL_RWFromFile(relativePath.c_str(), "rb"); |
|
|
|
// Files next to the MPQ archives override MPQ contents. |
|
SDL_RWops *rwops; |
|
{ |
|
const std::string path = paths::PrefPath() + relativePath; |
|
// Avoid spamming DEBUG messages if the file does not exist. |
|
if ((FileExists(path.c_str())) && (rwops = SDL_RWFromFile(path.c_str(), "rb")) != nullptr) { |
|
LogVerbose("Loaded MPQ file override: {}", path); |
|
return rwops; |
|
} |
|
} |
|
|
|
// Load from all the MPQ archives. |
|
MpqArchive *archive; |
|
uint32_t fileNumber; |
|
if (OpenMpqFile(filename, &archive, &fileNumber)) |
|
return SDL_RWops_FromMpqFile(*archive, fileNumber, filename, threadsafe); |
|
|
|
// Load from the `/assets` directory next to the devilutionx binary. |
|
const std::string path = paths::AssetsPath() + relativePath; |
|
if ((rwops = SDL_RWFromFile(path.c_str(), "rb")) != nullptr) |
|
return rwops; |
|
|
|
#if defined(__ANDROID__) || defined(__APPLE__) |
|
// Fall back to the bundled assets on supported systems. |
|
// This is handled by SDL when we pass a relative path. |
|
if (!paths::AssetsPath().empty() && (rwops = SDL_RWFromFile(relativePath.c_str(), "rb"))) |
|
return rwops; |
|
#endif |
|
|
|
return nullptr; |
|
} |
|
|
|
} // namespace devilution
|
|
|