summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/util/asset_manager.cc30
-rw-r--r--src/util/asset_manager.h19
-rw-r--r--tools/asset_packer.cc65
4 files changed, 68 insertions, 48 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d460131..f752a63 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -93,6 +93,7 @@ add_executable(demo64k
src/audio/idct.cc
src/audio/window.cc
src/audio/synth.cc
+ src/util/asset_manager.cc
third_party/glfw3webgpu/glfw3webgpu.c
${GENERATED_ASSETS_DATA_CC}
)
@@ -155,6 +156,7 @@ if(DEMO_BUILD_TESTS)
add_executable(test_assets
src/tests/test_assets.cc
+ src/util/asset_manager.cc
${GENERATED_ASSETS_DATA_CC}
)
target_include_directories(test_assets PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src src)
diff --git a/src/util/asset_manager.cc b/src/util/asset_manager.cc
new file mode 100644
index 0000000..80f8f85
--- /dev/null
+++ b/src/util/asset_manager.cc
@@ -0,0 +1,30 @@
+// 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.
+
+#include "util/asset_manager.h"
+#include "assets.h"
+
+// These are defined in the generated assets_data.cc
+extern const AssetRecord g_assets[];
+extern const size_t g_assets_count;
+
+const uint8_t *GetAsset(AssetId asset_id, size_t *out_size) {
+ uint16_t index = static_cast<uint16_t>(asset_id);
+ if (index >= g_assets_count) {
+ if (out_size)
+ *out_size = 0;
+ return nullptr;
+ }
+
+ const AssetRecord &record = g_assets[index];
+ if (out_size)
+ *out_size = record.size;
+ return record.data;
+}
+
+void DropAsset(AssetId asset_id, const uint8_t *asset) {
+ (void)asset_id;
+ (void)asset;
+ // Implementation for lazy decompression will go here
+}
diff --git a/src/util/asset_manager.h b/src/util/asset_manager.h
new file mode 100644
index 0000000..1b5e510
--- /dev/null
+++ b/src/util/asset_manager.h
@@ -0,0 +1,19 @@
+// This file is part of the 64k demo project.
+// It defines the core structures and interface for asset management.
+// Used for efficient retrieval of embedded binary resources.
+
+#pragma once
+#include <cstddef>
+#include <cstdint>
+
+// Forward declaration of the generated enum
+enum class AssetId : uint16_t;
+
+struct AssetRecord {
+ const uint8_t *data;
+ size_t size;
+};
+
+// Generic interface
+const uint8_t *GetAsset(AssetId asset_id, size_t *out_size = nullptr);
+void DropAsset(AssetId asset_id, const uint8_t *asset);
diff --git a/tools/asset_packer.cc b/tools/asset_packer.cc
index 1e29578..bf8e60b 100644
--- a/tools/asset_packer.cc
+++ b/tools/asset_packer.cc
@@ -1,6 +1,6 @@
// This file is part of the 64k demo project.
// It implements the asset packer tool for demoscene resource management.
-// Converts external files into embedded C++ byte arrays.
+// Converts external files into embedded C++ byte arrays and look-up records.
#include <fstream>
#include <iostream>
@@ -43,13 +43,12 @@ int main(int argc, char *argv[]) {
// Generate assets.h
assets_h_file << "#pragma once\n";
- assets_h_file << "#include <cstddef>\n";
assets_h_file << "#include <cstdint>\n\n";
assets_h_file << "enum class AssetId : uint16_t {\n";
// Generate assets_data.cc header
+ assets_data_cc_file << "#include \"util/asset_manager.h\"\n";
assets_data_cc_file << "#include \"assets.h\"\n\n";
- assets_data_cc_file << "#include <vector>\n\n";
std::string line;
int asset_id_counter = 0;
@@ -57,33 +56,25 @@ int main(int argc, char *argv[]) {
while (std::getline(assets_txt_file, line)) {
if (line.empty() || line[0] == '#')
- continue; // Skip empty lines and comments
+ continue;
size_t first_comma = line.find(',');
- if (first_comma == std::string::npos) {
- std::cerr << "Warning: Skipping malformed line in assets.txt: " << line
- << "\n";
+ if (first_comma == std::string::npos)
continue;
- }
std::string asset_name = line.substr(0, first_comma);
asset_name.erase(0, asset_name.find_first_not_of(" \t\r\n"));
asset_name.erase(asset_name.find_last_not_of(" \t\r\n") + 1);
size_t second_comma = line.find(',', first_comma + 1);
- if (second_comma == std::string::npos) {
- std::cerr << "Warning: Skipping malformed line in assets.txt (missing "
- "filename): "
- << line << "\n";
+ if (second_comma == std::string::npos)
continue;
- }
std::string filename =
line.substr(first_comma + 1, second_comma - first_comma - 1);
filename.erase(0, filename.find_first_not_of(" \t\r\n"));
filename.erase(filename.find_last_not_of(" \t\r\n") + 1);
- // Read the actual file
std::string base_dir =
assets_txt_path.substr(0, assets_txt_path.find_last_of("/\\") + 1);
std::ifstream asset_file(base_dir + filename, std::ios::binary);
@@ -104,7 +95,7 @@ int main(int argc, char *argv[]) {
<< ",\n";
// Write data to assets_data.cc
- assets_data_cc_file << "const uint8_t ASSET_DATA_" << asset_name
+ assets_data_cc_file << "static const uint8_t ASSET_DATA_" << asset_name
<< "[] = {";
for (size_t i = 0; i < buffer.size(); ++i) {
if (i % 12 == 0)
@@ -112,51 +103,29 @@ int main(int argc, char *argv[]) {
assets_data_cc_file << "0x" << std::hex << (int)buffer[i] << std::dec
<< (i == buffer.size() - 1 ? "" : ", ");
}
- assets_data_cc_file << "\n};\n";
- assets_data_cc_file << "const size_t ASSET_SIZE_" << asset_name << " = "
- << buffer.size() << ";\n\n";
+ assets_data_cc_file << "\n};\n\n";
asset_id_counter++;
}
assets_h_file << "};\n\n";
-
- // Generate GetAsset function declaration in assets.h
- assets_h_file << "const uint8_t *GetAsset(AssetId asset_id, size_t *out_size "
- "= nullptr);\n";
- assets_h_file << "void DropAsset(AssetId asset_id, const uint8_t *asset); // "
- "For lazy decompression scaffolding\n";
+ assets_h_file << "#include \"util/asset_manager.h\"\n";
assets_h_file.close();
- // Generate GetAsset function implementation in assets_data.cc
- assets_data_cc_file
- << "const uint8_t *GetAsset(AssetId asset_id, size_t *out_size) {\n";
- assets_data_cc_file << " if (out_size) *out_size = 0;\n"; // Default for now
- assets_data_cc_file << " switch (asset_id) {\n";
+ // Generate the lookup array in assets_data.cc
+ assets_data_cc_file << "extern const AssetRecord g_assets[] = {\n";
for (const std::string &name : asset_names) {
- assets_data_cc_file << " case AssetId::ASSET_" << name << ":\n";
- assets_data_cc_file << " if (out_size) *out_size = ASSET_SIZE_" << name
- << ";\n";
- assets_data_cc_file << " return ASSET_DATA_" << name << ";\n";
+ assets_data_cc_file << " { ASSET_DATA_" << name << ", sizeof(ASSET_DATA_"
+ << name << ") },\n";
}
- assets_data_cc_file << " default:\n";
- assets_data_cc_file << " return nullptr;\n";
- assets_data_cc_file << " }\n";
- assets_data_cc_file << "}\n\n";
-
- // Dummy DropAsset implementation
- assets_data_cc_file
- << "void DropAsset(AssetId asset_id, const uint8_t *asset) {\n";
- assets_data_cc_file << " (void)asset_id;\n";
- assets_data_cc_file << " (void)asset;\n";
- assets_data_cc_file << " // No-op for now, actual implementation for lazy "
- "decompression goes here\n";
- assets_data_cc_file << "}\n";
+ assets_data_cc_file << "};\n\n";
+ assets_data_cc_file << "extern const size_t g_assets_count = "
+ "sizeof(g_assets) / sizeof(g_assets[0]);\n";
assets_data_cc_file.close();
- std::cout << "Asset packer successfully generated: " << output_assets_h_path
- << " and " << output_assets_data_cc_path << "\n";
+ std::cout << "Asset packer successfully generated records for "
+ << asset_names.size() << " assets.\n";
return 0;
}