blob: 387453599fb000429fedb500cf72b5833bd5d743 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
// This file is part of the 64k demo project.
// 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; // This asset is not in the static packed data either.
}
// 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 = g_asset_cache[index].size;
return g_asset_cache[index].data;
}
void DropAsset(AssetId asset_id, const uint8_t* asset) {
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.
}
|