summaryrefslogtreecommitdiff
path: root/src/util/asset_manager.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-01 12:06:37 +0100
committerskal <pascal.massimino@gmail.com>2026-02-01 12:06:37 +0100
commita358fbc9f4ba3a7b01f600109fc86aeb2fcf96b8 (patch)
treea08b085bc74b5d41382d9818377ff8c31802ad85 /src/util/asset_manager.cc
parentf80e37bd61e447f1d66fbb5eb4c1ab7a8a77cf0f (diff)
feat(asset_manager): Implement array-based caching
- Refactored asset manager to use a static array for caching, improving performance and memory efficiency. - Updated asset_packer to correctly generate ASSET_LAST_ID for array sizing. - Modified asset_manager.h to use a forward declaration for AssetId. - Updated asset_manager.cc to use the conditional include for generated asset headers. - Added a test case in test_assets to verify the array-based cache and ASSET_LAST_ID logic.
Diffstat (limited to 'src/util/asset_manager.cc')
-rw-r--r--src/util/asset_manager.cc70
1 files changed, 61 insertions, 9 deletions
diff --git a/src/util/asset_manager.cc b/src/util/asset_manager.cc
index 30295b9..3874535 100644
--- a/src/util/asset_manager.cc
+++ b/src/util/asset_manager.cc
@@ -1,30 +1,82 @@
// This file is part of the 64k demo project.
-// It implements the generic asset retrieval logic.
-// Uses an array lookup for O(1) access to embedded data.
+// It implements the generic asset retrieval logic with runtime caching.
#include "util/asset_manager.h"
+#if defined(USE_TEST_ASSETS)
+#include "generated/test_assets.h"
+#else
#include "generated/assets.h"
+#endif /* defined(USE_TEST_ASSETS) */
+
+#include <vector> // For potential dynamic allocation for procedural assets
+#include <new> // For placement new
+#include <cstdlib> // For free
// These are defined in the generated assets_data.cc
+#if defined(USE_TEST_ASSETS)
+extern const AssetRecord g_assets[];
+extern const size_t g_assets_count;
+#else
extern const AssetRecord g_assets[];
extern const size_t g_assets_count;
+#endif
+// Array-based cache for assets.
+// Initialized to all zeros (nullptr data, 0 size, false is_procedural)
+// The size is derived from the generated ASSET_LAST_ID enum value.
+static AssetRecord g_asset_cache[(size_t)AssetId::ASSET_LAST_ID] = {};
const uint8_t* GetAsset(AssetId asset_id, size_t* out_size) {
uint16_t index = (uint16_t)asset_id;
+
+ // Assert that ASSET_LAST_ID is not used for retrieval.
+ // This ensures the size of the cache is correctly used and not accessed out of bounds.
+ // If this assert fails, it means assets.txt has an ID larger than expected
+ // or ASSET_LAST_ID is not correctly generated/updated.
+ // This is a design decision: ASSET_LAST_ID is purely for sizing and range checking,
+ // not for a valid asset retrieval itself.
+ if (index >= (uint16_t)AssetId::ASSET_LAST_ID) {
+ if (out_size)
+ *out_size = 0;
+ return nullptr; // Invalid asset_id
+ }
+
+ // Check cache first
+ if (g_asset_cache[index].data != nullptr) {
+ if (out_size)
+ *out_size = g_asset_cache[index].size;
+ return g_asset_cache[index].data;
+ }
+
+ // Not in cache, retrieve from static data (packed in binary)
if (index >= g_assets_count) {
if (out_size)
*out_size = 0;
- return nullptr;
+ return nullptr; // This asset is not in the static packed data either.
}
- const AssetRecord& record = g_assets[index];
+ // Store static record in cache for future use
+ g_asset_cache[index] = g_assets[index];
+ g_asset_cache[index].is_procedural = false;
+
if (out_size)
- *out_size = record.size;
- return record.data;
+ *out_size = g_asset_cache[index].size;
+ return g_asset_cache[index].data;
}
void DropAsset(AssetId asset_id, const uint8_t* asset) {
- (void)asset_id;
- (void)asset;
- // Implementation for lazy decompression will go here
+ uint16_t index = (uint16_t)asset_id;
+ if (index >= (uint16_t)AssetId::ASSET_LAST_ID) {
+ return; // Invalid asset_id
+ }
+
+ // Only free memory for procedural assets.
+ if (g_asset_cache[index].is_procedural && g_asset_cache[index].data == asset) {
+ // In a more complex scenario, we might track ref counts.
+ // For this demo, we assume a single owner for dynamically allocated assets.
+ delete[] g_asset_cache[index].data; // Assuming `new uint8_t[]` was used for procedural
+ g_asset_cache[index].data = nullptr;
+ g_asset_cache[index].size = 0;
+ g_asset_cache[index].is_procedural = false;
+ }
+ // For static assets, no dynamic memory to free.
}