#pragma once #include #include #include "appfat.h" #include "engine/clx_sprite.hpp" #include "engine/load_file.hpp" #include "utils/cl2_to_clx.hpp" #include "utils/endian.hpp" #include "utils/pointer_value_union.hpp" #include "utils/static_vector.hpp" #include "utils/str_cat.hpp" #ifdef UNPACKED_MPQS #define DEVILUTIONX_CL2_EXT ".clx" #else #define DEVILUTIONX_CL2_EXT ".cl2" #endif namespace devilution { OwnedClxSpriteListOrSheet LoadCl2ListOrSheet(const char *pszName, PointerOrValue widthOrWidths); template OwnedClxSpriteSheet LoadMultipleCl2Sheet(tl::function_ref filenames, size_t count, uint16_t width) { StaticVector files; StaticVector fileSizes; const size_t sheetHeaderSize = 4 * count; size_t totalSize = sheetHeaderSize; for (size_t i = 0; i < count; ++i) { const char *filename = filenames(i); AssetRef file = FindAsset(filename); if (!file.ok()) { app_fatal(StrCat("Failed to open file:\n", filename, "\n\n", file.error())); } size_t size = file.size(); fileSizes.emplace_back(size); totalSize += size; } auto data = std::unique_ptr { new uint8_t[totalSize] }; #ifndef UNPACKED_MPQS const PointerOrValue frameWidth { width }; #endif size_t accumulatedSize = sheetHeaderSize; for (size_t i = 0; i < count; ++i) { const size_t size = fileSizes[i]; AssetHandle file = OpenAsset(filenames(i)); if (!file.read(&data[accumulatedSize], size)) app_fatal(StrCat("Read failed:\n", file.error())); WriteLE32(&data[i * 4], accumulatedSize); #ifndef UNPACKED_MPQS [[maybe_unused]] const uint16_t numLists = Cl2ToClx(&data[accumulatedSize], size, frameWidth); assert(numLists == 0); #endif accumulatedSize += size; } return OwnedClxSpriteSheet { std::move(data), static_cast(count) }; } inline OwnedClxSpriteList LoadCl2(const char *pszName, uint16_t width) { return LoadCl2ListOrSheet(pszName, PointerOrValue { width }).list(); } inline OwnedClxSpriteList LoadCl2(const char *pszName, const uint16_t *widths) { return LoadCl2ListOrSheet(pszName, PointerOrValue { widths }).list(); } inline OwnedClxSpriteSheet LoadCl2Sheet(const char *pszName, uint16_t width) { return LoadCl2ListOrSheet(pszName, PointerOrValue { width }).sheet(); } } // namespace devilution