/** * libra3assets - read (and write) Red Alert 3's built-in resource files. * * The primary module interface re-exports every partition: * * - `:error` - the `asset_error` exception family * - `:bytes` - bounds-checked little-/big-endian readers and writers * - `:refpack` - EA's RefPack codec (decompress and compress) * - `:big` - `BIG4` archives (`Data\*.big`), read and write * - `:binary` - compiled `BinaryAsset` streams (`*.bin` + `.manifest`) * - `:csf` - SAGE `.csf` string tables * - `:map` - SAGE `.map` containers (`CkMp`), read and write * * Nothing here reads game data on its own: callers point the library at their * own installation (`RA3_GAME_DIR` / `C:\Red Alert 3`). */ export module ra3.assets; export import :error; export import :bytes; export import :refpack; export import :big; export import :binary; export import :csf; export import :map; import std; export namespace ra3::assets { /** * Locate a Red Alert 3 installation. * * Resolution order: the explicit argument, then `$RA3_GAME_DIR`, then the * default `C:\Red Alert 3`. A directory qualifies only if it has a `Data` * subdirectory. */ [[nodiscard]] inline auto find_game_dir(const std::optional &explicit_dir = std::nullopt) -> std::optional { const auto qualifies = [](const std::filesystem::path &candidate) { std::error_code ec; return !candidate.empty() && std::filesystem::is_directory(candidate / "Data", ec); }; if (explicit_dir && qualifies(*explicit_dir)) return explicit_dir; if (const auto *env = std::getenv("RA3_GAME_DIR"); env != nullptr && *env != '\0') { const std::filesystem::path candidate{env}; if (qualifies(candidate)) return candidate; } const std::filesystem::path default_dir{"C:/Red Alert 3"}; if (qualifies(default_dir)) return default_dir; return std::nullopt; } /** Every `Data\*.big` archive in an installation, sorted by name. */ [[nodiscard]] inline auto list_archives(const std::filesystem::path &game_dir) -> std::vector { std::vector archives; std::error_code ec; for (const auto &entry: std::filesystem::directory_iterator(game_dir / "Data", ec)) { if (entry.is_regular_file() && entry.path().extension() == ".big") archives.push_back(entry.path()); } std::ranges::sort(archives); return archives; } } // namespace ra3::assets