From 438333cf6f1dcd9f8d6a94fc702a952b070353b4 Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 28 Jan 2026 09:45:18 +0100 Subject: refactor(assets): Optimize asset retrieval using array lookup This refactors the asset management system to be more efficient and cleaner. - Moved common GetAsset/DropAsset logic to src/util/asset_manager.cc. - Changed retrieval to use an array of records (AssetRecord) for O(1) lookups instead of a switch statement. - Updated asset_packer to generate only raw data and the record array. --- tools/asset_packer.cc | 65 ++++++++++++++------------------------------------- 1 file changed, 17 insertions(+), 48 deletions(-) (limited to 'tools') 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 #include @@ -43,13 +43,12 @@ int main(int argc, char *argv[]) { // Generate assets.h assets_h_file << "#pragma once\n"; - assets_h_file << "#include \n"; assets_h_file << "#include \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 \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; } -- cgit v1.2.3