Skip to content

Commit

Permalink
Global resource storage
Browse files Browse the repository at this point in the history
Keeps track of all the currently loaded resources (currently only
sprites but can be extended to sounds).
This should eventually allow Lua to access them by name.

Not sure if name-based access to currently-loaded sprites
is something that we'll ever want (might be too unstructured),
but at least this is useful for debugging sprite issues.

If this only ends up useful for debugging, we can add a couple
of `ifdefs` to only keep track of the sprites in debug mode.
  • Loading branch information
glebm committed Aug 6, 2024
1 parent df3d76c commit 359a0b8
Show file tree
Hide file tree
Showing 28 changed files with 587 additions and 126 deletions.
2 changes: 2 additions & 0 deletions Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ set(libdevilutionx_SRCS
engine/animationinfo.cpp
engine/assets.cpp
engine/backbuffer_state.cpp
engine/resource_store.cpp
engine/direction.cpp
engine/dx.cpp
engine/events.cpp
Expand Down Expand Up @@ -147,6 +148,7 @@ set(libdevilutionx_SRCS
lua/modules/dev/player/stats.cpp
lua/modules/dev/quests.cpp
lua/modules/dev/search.cpp
lua/modules/dev/resources.cpp
lua/modules/dev/towners.cpp
lua/modules/log.cpp
lua/modules/render.cpp
Expand Down
11 changes: 6 additions & 5 deletions Source/cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ void CreateHalfSizeItemSprites()
OwnedSurface ownedItemSurface { MaxWidth, MaxHeight };
OwnedSurface ownedHalfSurface { MaxWidth / 2, MaxHeight / 2 };

const auto createHalfSize = [&, redTrn](const ClxSprite itemSprite, size_t outputIndex) {
const auto createHalfSize = [&, redTrn](const ClxSprite itemSprite, size_t outputIndex, int cursId) {
if (itemSprite.width() <= 28 && itemSprite.height() <= 28) {
// Skip creating half-size sprites for 1x1 items because we always render them at full size anyway.
return;
Expand All @@ -495,22 +495,23 @@ void CreateHalfSizeItemSprites()
const Surface halfSurface = ownedHalfSurface.subregion(0, 0, itemSurface.w() / 2, itemSurface.h() / 2);
SDL_Rect halfSurfaceRect = MakeSdlRect(0, 0, halfSurface.w(), halfSurface.h());
SDL_SetClipRect(halfSurface.surface, &halfSurfaceRect);
std::string name = StrCat("runtime\\objcurs_half_size\\", cursId);
BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1);
HalfSizeItemSprites[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1));
HalfSizeItemSprites[outputIndex].emplace(SurfaceToClx(std::string(name), /*trnName=*/ {}, halfSurface, 1, 1));

SDL_FillRect(itemSurface.surface, nullptr, 1);
ClxDrawTRN(itemSurface, { 0, itemSurface.h() }, itemSprite, redTrn);
BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1);
HalfSizeItemSpritesRed[outputIndex].emplace(SurfaceToClx(halfSurface, 1, 1));
HalfSizeItemSpritesRed[outputIndex].emplace(SurfaceToClx(std::move(name), /*trnName=*/"red", halfSurface, 1, 1));
};

size_t outputIndex = 0;
for (size_t i = static_cast<int>(CURSOR_FIRSTITEM) - 1, n = pCursCels->numSprites(); i < n; ++i, ++outputIndex) {
createHalfSize((*pCursCels)[i], outputIndex);
createHalfSize((*pCursCels)[i], outputIndex, i + 1);
}
if (gbIsHellfire) {
for (size_t i = 0, n = pCursCels2->numSprites(); i < n; ++i, ++outputIndex) {
createHalfSize((*pCursCels2)[i], outputIndex);
createHalfSize((*pCursCels2)[i], outputIndex, i + pCursCels->numSprites() + 1);
}
}
}
Expand Down
109 changes: 86 additions & 23 deletions Source/engine/clx_sprite.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <memory>

#include "appfat.h"
#include "engine/resource_store.hpp"
#include "utils/endian.hpp"
#include "utils/intrusive_optional.hpp"

Expand Down Expand Up @@ -114,7 +115,7 @@ class ClxSpriteList {

ClxSpriteList(const OwnedClxSpriteList &owned);

[[nodiscard]] OwnedClxSpriteList clone() const;
[[nodiscard]] OwnedClxSpriteList clone(std::string_view name, std::string_view trnName = {}) const;

[[nodiscard]] constexpr uint32_t numSprites() const
{
Expand Down Expand Up @@ -335,20 +336,35 @@ class OwnedClxSpriteListOrSheet;
/**
* @brief Implicitly convertible to `ClxSpriteList` and owns its data.
*/
class OwnedClxSpriteList {
class OwnedClxSpriteList : public OwnedResource<OwnedClxSpriteList> {
public:
explicit OwnedClxSpriteList(std::unique_ptr<uint8_t[]> &&data)
: data_(std::move(data))
explicit OwnedClxSpriteList(std::string_view name, std::string_view trnName, std::unique_ptr<uint8_t[]> &&data)
: OwnedResource<OwnedClxSpriteList>(name, trnName)
, data_(std::move(data))
{
assert(data_ != nullptr);
}

explicit OwnedClxSpriteList(std::string &&name, std::string &&trnName, std::unique_ptr<uint8_t[]> &&data)
: OwnedResource<OwnedClxSpriteList>(std::move(name), std::move(trnName))
, data_(std::move(data))
{
assert(data_ != nullptr);
}

explicit OwnedClxSpriteList(ResourceStoreHandle &&handle, std::unique_ptr<uint8_t[]> &&data)
: OwnedResource<OwnedClxSpriteList>(std::move(handle))
, data_(std::move(data))
{
assert(data_ != nullptr);
}

OwnedClxSpriteList(OwnedClxSpriteList &&) noexcept = default;
OwnedClxSpriteList &operator=(OwnedClxSpriteList &&) noexcept = default;

[[nodiscard]] OwnedClxSpriteList clone() const
[[nodiscard]] OwnedClxSpriteList clone(std::string_view trnName = {}) const
{
return ClxSpriteList { *this }.clone();
return ClxSpriteList { *this }.clone(resourceName(), trnName);
}

[[nodiscard]] ClxSprite operator[](size_t spriteIndex) const
Expand Down Expand Up @@ -382,21 +398,40 @@ inline ClxSpriteList::ClxSpriteList(const OwnedClxSpriteList &owned)
{
}

inline OwnedClxSpriteList ClxSpriteList::clone() const
inline OwnedClxSpriteList ClxSpriteList::clone(std::string_view name, std::string_view trnName) const
{
const size_t size = dataSize();
std::unique_ptr<uint8_t[]> data { new uint8_t[size] };
memcpy(data.get(), data_, size);
return OwnedClxSpriteList { std::move(data) };
return OwnedClxSpriteList { name, trnName, std::move(data) };
}

/**
* @brief Implicitly convertible to `ClxSpriteSheet` and owns its data.
*/
class OwnedClxSpriteSheet {
class OwnedClxSpriteSheet : public OwnedResource<OwnedClxSpriteSheet> {
public:
OwnedClxSpriteSheet(std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)
: data_(std::move(data))
OwnedClxSpriteSheet(std::string_view name, std::string_view trnName, std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)
: OwnedResource<OwnedClxSpriteSheet>(name, trnName)
, data_(std::move(data))
, num_lists_(numLists)
{
assert(data_ != nullptr);
assert(numLists > 0);
}

OwnedClxSpriteSheet(std::string &&name, std::string &&trnName, std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)
: OwnedResource<OwnedClxSpriteSheet>(std::move(name), std::move(trnName))
, data_(std::move(data))
, num_lists_(numLists)
{
assert(data_ != nullptr);
assert(numLists > 0);
}

explicit OwnedClxSpriteSheet(ResourceStoreHandle &&handle, std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)
: OwnedResource<OwnedClxSpriteSheet>(std::move(handle))
, data_(std::move(data))
, num_lists_(numLists)
{
assert(data_ != nullptr);
Expand Down Expand Up @@ -472,6 +507,8 @@ class ClxSpriteListOrSheet {

ClxSpriteListOrSheet(const OwnedClxSpriteListOrSheet &listOrSheet);

[[nodiscard]] OwnedClxSpriteListOrSheet clone(std::string_view name, std::string_view trnName = {}) const;

[[nodiscard]] constexpr ClxSpriteList list() const
{
assert(num_lists_ == 0);
Expand Down Expand Up @@ -509,32 +546,50 @@ class OptionalOwnedClxSpriteListOrSheet;
/**
* @brief A CLX sprite list or a sprite sheet (list of lists).
*/
class OwnedClxSpriteListOrSheet {
class OwnedClxSpriteListOrSheet : public OwnedResource<OwnedClxSpriteListOrSheet> {
public:
static OwnedClxSpriteListOrSheet FromBuffer(std::unique_ptr<uint8_t[]> &&data, size_t size)
static OwnedClxSpriteListOrSheet fromBuffer(
std::string_view name, std::string_view trnName, std::unique_ptr<uint8_t[]> &&data, size_t size)
{
const uint16_t numLists = GetNumListsFromClxListOrSheetBuffer(data.get(), size);
return OwnedClxSpriteListOrSheet { std::move(data), numLists };
return OwnedClxSpriteListOrSheet { name, trnName, std::move(data), numLists };
}

explicit OwnedClxSpriteListOrSheet(std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)
: data_(std::move(data))
explicit OwnedClxSpriteListOrSheet(std::string_view name, std::string_view trnName, std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)
: OwnedResource<OwnedClxSpriteListOrSheet>(name, trnName)
, data_(std::move(data))
, num_lists_(numLists)
{
}

explicit OwnedClxSpriteListOrSheet(OwnedClxSpriteSheet &&sheet)
: data_(std::move(sheet.data_))
explicit OwnedClxSpriteListOrSheet(std::string &&name, std::string &&trnName, std::unique_ptr<uint8_t[]> &&data, uint16_t numLists)
: OwnedResource<OwnedClxSpriteListOrSheet>(std::move(name), std::move(trnName))
, data_(std::move(data))
, num_lists_(numLists)
{
}

explicit OwnedClxSpriteListOrSheet(OwnedClxSpriteSheet &&sheet) noexcept
: OwnedResource<OwnedClxSpriteListOrSheet>(std::move(sheet.handle_))
, data_(std::move(sheet.data_))
, num_lists_(sheet.num_lists_)
{
}

explicit OwnedClxSpriteListOrSheet(OwnedClxSpriteList &&list)
: data_(std::move(list.data_))
, num_lists_(0)
explicit OwnedClxSpriteListOrSheet(OwnedClxSpriteList &&list) noexcept
: OwnedResource<OwnedClxSpriteListOrSheet>(std::move(list.handle_))
, data_(std::move(list.data_))
{
}

OwnedClxSpriteListOrSheet(OwnedClxSpriteListOrSheet &&) noexcept = default;
OwnedClxSpriteListOrSheet &operator=(OwnedClxSpriteListOrSheet &&) noexcept = default;

[[nodiscard]] OwnedClxSpriteListOrSheet clone(std::string_view trnName = {}) const
{
return ClxSpriteListOrSheet { *this }.clone(resourceName(), trnName);
}

[[nodiscard]] ClxSpriteList list() const &
{
assert(num_lists_ == 0);
Expand All @@ -544,7 +599,7 @@ class OwnedClxSpriteListOrSheet {
[[nodiscard]] OwnedClxSpriteList list() &&
{
assert(num_lists_ == 0);
return OwnedClxSpriteList { std::move(data_) };
return OwnedClxSpriteList { std::move(handle_), std::move(data_) };
}

[[nodiscard]] ClxSpriteSheet sheet() const &
Expand All @@ -556,7 +611,7 @@ class OwnedClxSpriteListOrSheet {
[[nodiscard]] OwnedClxSpriteSheet sheet() &&
{
assert(num_lists_ != 0);
return OwnedClxSpriteSheet { std::move(data_), num_lists_ };
return OwnedClxSpriteSheet { std::move(handle_), std::move(data_), num_lists_ };
}

[[nodiscard]] bool isSheet() const
Expand Down Expand Up @@ -588,6 +643,14 @@ inline ClxSpriteListOrSheet::ClxSpriteListOrSheet(const OwnedClxSpriteListOrShee
{
}

inline OwnedClxSpriteListOrSheet ClxSpriteListOrSheet::clone(std::string_view name, std::string_view trnName) const
{
const size_t size = this->dataSize();
std::unique_ptr<uint8_t[]> data { new uint8_t[size] };
memcpy(data.get(), data_, size);
return OwnedClxSpriteListOrSheet { name, trnName, std::move(data), num_lists_ };
}

/**
* @brief Equivalent to `std::optional<ClxSprite>` but smaller.
*/
Expand Down
2 changes: 1 addition & 1 deletion Source/engine/load_cel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ OwnedClxSpriteListOrSheet LoadCelListOrSheet(const char *pszName, PointerOrValue
#ifdef DEBUG_CEL_TO_CL2_SIZE
std::cout << path;
#endif
return CelToClx(data.get(), size, widthOrWidths);
return CelToClx(pszName, /*trnName=*/ {}, data.get(), size, widthOrWidths);
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion Source/engine/load_cl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ OwnedClxSpriteListOrSheet LoadCl2ListOrSheet(const char *pszName, PointerOrValue
#else
size_t size;
std::unique_ptr<uint8_t[]> data = LoadFileInMem<uint8_t>(path, &size);
return Cl2ToClx(std::move(data), size, widthOrWidths);
return Cl2ToClx(pszName, /*trnName=*/ {}, std::move(data), size, widthOrWidths);
#endif
}

Expand Down
6 changes: 3 additions & 3 deletions Source/engine/load_cl2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace devilution {
OwnedClxSpriteListOrSheet LoadCl2ListOrSheet(const char *pszName, PointerOrValue<uint16_t> widthOrWidths);

template <size_t MaxCount>
OwnedClxSpriteSheet LoadMultipleCl2Sheet(tl::function_ref<const char *(size_t)> filenames, size_t count, uint16_t width)
OwnedClxSpriteSheet LoadMultipleCl2Sheet(std::string_view name, tl::function_ref<const char *(size_t)> filenames, size_t count, uint16_t width)
{
StaticVector<std::array<char, MaxMpqPathSize>, MaxCount> paths;
StaticVector<AssetRef, MaxCount> files;
Expand Down Expand Up @@ -64,9 +64,9 @@ OwnedClxSpriteSheet LoadMultipleCl2Sheet(tl::function_ref<const char *(size_t)>
accumulatedSize += size;
}
#ifdef UNPACKED_MPQS
return OwnedClxSpriteSheet { std::move(data), static_cast<uint16_t>(count) };
return OwnedClxSpriteSheet { name, /*trnName=*/ {}, std::move(data), static_cast<uint16_t>(count) };
#else
return Cl2ToClx(std::move(data), accumulatedSize, frameWidth).sheet();
return Cl2ToClx(name, /*trnName=*/ {}, std::move(data), accumulatedSize, frameWidth).sheet();
#endif
}

Expand Down
11 changes: 8 additions & 3 deletions Source/engine/load_clx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
#endif

#include "engine/assets.hpp"
#include "engine/clx_sprite.hpp"
#include "engine/load_file.hpp"

namespace devilution {

OptionalOwnedClxSpriteListOrSheet LoadOptionalClxListOrSheet(const char *path)
{
AssetRef ref = FindAsset(path);
std::string_view pathStrView = path;
AssetRef ref = FindAsset(pathStrView);
if (!ref.ok())
return std::nullopt;
const size_t size = ref.size();
Expand All @@ -25,14 +27,17 @@ OptionalOwnedClxSpriteListOrSheet LoadOptionalClxListOrSheet(const char *path)
if (!handle.ok() || !handle.read(data.get(), size))
return std::nullopt;
}
return OwnedClxSpriteListOrSheet::FromBuffer(std::move(data), size);
pathStrView.remove_suffix(4);
return OwnedClxSpriteListOrSheet::fromBuffer(pathStrView, /*trnName=*/ {}, std::move(data), size);
}

OwnedClxSpriteListOrSheet LoadClxListOrSheet(const char *path)
{
size_t size;
std::unique_ptr<uint8_t[]> data = LoadFileInMem<uint8_t>(path, &size);
return OwnedClxSpriteListOrSheet::FromBuffer(std::move(data), size);
std::string_view pathStrView = path;
pathStrView.remove_suffix(4);
return OwnedClxSpriteListOrSheet::fromBuffer(pathStrView, /*trnName=*/ {}, std::move(data), size);
}

} // namespace devilution
2 changes: 1 addition & 1 deletion Source/engine/load_pcx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ OptionalOwnedClxSpriteList LoadPcxSpriteList(const char *filename, int numFrames
#ifdef DEBUG_PCX_TO_CL2_SIZE
std::cout << filename;
#endif
OptionalOwnedClxSpriteList result = PcxToClx(handle, fileSize, numFramesOrFrameHeight, transparentColor, outPalette);
OptionalOwnedClxSpriteList result = PcxToClx(filename, handle, fileSize, numFramesOrFrameHeight, transparentColor, outPalette);
if (!result)
return std::nullopt;
return result;
Expand Down
Loading

0 comments on commit 359a0b8

Please sign in to comment.