summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/asset_packer.cc189
1 files changed, 119 insertions, 70 deletions
diff --git a/tools/asset_packer.cc b/tools/asset_packer.cc
index a91552a..46934ce 100644
--- a/tools/asset_packer.cc
+++ b/tools/asset_packer.cc
@@ -2,18 +2,19 @@
// It implements the asset packer tool for demoscene resource management.
// Converts external files into embedded C++ byte arrays and look-up records.
-#include <cstdio> // for simplicity, use fprintf() for output generation
+#include <cstdio> // for simplicity, use fprintf() for output generation
#include <fstream>
#include <map>
+#include <regex> // For std::regex
+#include <stdexcept> // For std::stof exceptions
#include <string>
#include <vector>
-#include <stdexcept> // For std::stof exceptions
-#include <regex> // For std::regex
#include "procedural/generator.h" // For ProcGenFunc and procedural functions
#include "util/asset_manager.h" // For AssetRecord and AssetId
-// Map of procedural function names to their pointers (used only internally by asset_packer here, not generated)
+// Map of procedural function names to their pointers (used only internally by
+// asset_packer here, not generated)
static const std::map<std::string, ProcGenFunc> kAssetPackerProcGenFuncMap = {
{"gen_noise", procedural::gen_noise},
{"gen_grid", procedural::gen_grid},
@@ -22,21 +23,24 @@ static const std::map<std::string, ProcGenFunc> kAssetPackerProcGenFuncMap = {
// Helper struct to hold all information about an asset during parsing
struct AssetBuildInfo {
- std::string name;
- std::string filename; // Original filename for static assets
- bool is_procedural;
- std::string proc_func_name; // Function name string
+ std::string name;
+ std::string filename; // Original filename for static assets
+ bool is_procedural;
+ std::string proc_func_name; // Function name string
std::vector<float> proc_params; // Parameters for procedural function
// For generated C++ code
- std::string data_array_name; // ASSET_DATA_xxx for static
- std::string params_array_name; // ASSET_PROC_PARAMS_xxx for procedural
+ std::string data_array_name; // ASSET_DATA_xxx for static
+ std::string params_array_name; // ASSET_PROC_PARAMS_xxx for procedural
std::string func_name_str_name; // ASSET_PROC_FUNC_STR_xxx for procedural
};
int main(int argc, char* argv[]) {
if (argc != 4) {
- fprintf(stderr, "Usage: %s <assets.txt_path> <output_assets_h_path> <output_assets_data_cc_path>\n", argv[0]);
+ fprintf(stderr,
+ "Usage: %s <assets.txt_path> <output_assets_h_path> "
+ "<output_assets_data_cc_path>\n",
+ argv[0]);
return 1;
}
@@ -46,57 +50,77 @@ int main(int argc, char* argv[]) {
std::ifstream assets_txt_file(assets_txt_path);
if (!assets_txt_file.is_open()) {
- fprintf(stderr, "Error: Could not open assets.txt at %s\n", assets_txt_path.c_str());
+ fprintf(stderr, "Error: Could not open assets.txt at %s\n",
+ assets_txt_path.c_str());
return 1;
}
FILE* assets_h_file = std::fopen(output_assets_h_path.c_str(), "w");
if (!assets_h_file) {
- fprintf(stderr, "Error: Could not open output assets.h at %s\n", output_assets_h_path.c_str());
+ fprintf(stderr, "Error: Could not open output assets.h at %s\n",
+ output_assets_h_path.c_str());
return 1;
}
- FILE* assets_data_cc_file = std::fopen(output_assets_data_cc_path.c_str(), "w");
+ FILE* assets_data_cc_file =
+ std::fopen(output_assets_data_cc_path.c_str(), "w");
if (!assets_data_cc_file) {
- fprintf(stderr, "Error: Could not open output assets_data.cc at %s\n", output_assets_data_cc_path.c_str());
+ fprintf(stderr, "Error: Could not open output assets_data.cc at %s\n",
+ output_assets_data_cc_path.c_str());
return 1;
}
// Generate assets.h header
- fprintf(assets_h_file, "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n");
+ fprintf(
+ assets_h_file,
+ "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n");
fprintf(assets_h_file, "#pragma once\n");
fprintf(assets_h_file, "#include <cstdint>\n\n");
fprintf(assets_h_file, "enum class AssetId : uint16_t {\n");
- std::string generated_header_name = output_assets_h_path.substr(output_assets_h_path.find_last_of("/\\") + 1);
+ std::string generated_header_name =
+ output_assets_h_path.substr(output_assets_h_path.find_last_of("/\\") + 1);
// Generate assets_data.cc header
- fprintf(assets_data_cc_file, "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n");
+ fprintf(
+ assets_data_cc_file,
+ "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n");
fprintf(assets_data_cc_file, "#include \"util/asset_manager.h\"\n");
- fprintf(assets_data_cc_file, "#include \"generated/%s\"\n\n", generated_header_name.c_str());
+ fprintf(assets_data_cc_file, "#include \"generated/%s\"\n\n",
+ generated_header_name.c_str());
// Forward declare procedural functions for AssetRecord initialization
- fprintf(assets_data_cc_file, "namespace procedural { void gen_noise(uint8_t*, int, int, const float*, int); }\n");
- fprintf(assets_data_cc_file, "namespace procedural { void gen_grid(uint8_t*, int, int, const float*, int); }\n");
- fprintf(assets_data_cc_file, "namespace procedural { void make_periodic(uint8_t*, int, int, const float*, int); }\n\n");
+ fprintf(assets_data_cc_file,
+ "namespace procedural { void gen_noise(uint8_t*, int, int, const "
+ "float*, int); }\n");
+ fprintf(assets_data_cc_file,
+ "namespace procedural { void gen_grid(uint8_t*, int, int, const "
+ "float*, int); }\n");
+ fprintf(assets_data_cc_file,
+ "namespace procedural { void make_periodic(uint8_t*, int, int, const "
+ "float*, int); }\n\n");
std::vector<AssetBuildInfo> asset_build_infos;
int asset_id_counter = 0;
std::string line;
- // Updated regex pattern for new asset list format (Name, CompressionType, Filename, Description)
+ // Updated regex pattern for new asset list format (Name, CompressionType,
+ // Filename, Description)
std::regex asset_line_regex(
R"(^\s*([A-Z0-9_]+)\s*,\s*(PROC\([^)]*\)|[^,]+)\s*(?:,\s*([^,]*))?\s*(?:,\s*\"(.*)\")?\s*$)");
while (std::getline(assets_txt_file, line)) {
- if (line.empty() || line[0] == '#') continue;
+ if (line.empty() || line[0] == '#')
+ continue;
std::smatch matches;
- if (std::regex_search(line, matches, asset_line_regex) && matches.size() >= 3) {
+ if (std::regex_search(line, matches, asset_line_regex) &&
+ matches.size() >= 3) {
AssetBuildInfo info;
info.name = matches[1].str();
std::string compression_type_str = matches[2].str();
// Filename is now matches[3]
- info.filename = (matches.size() >= 4 && matches[3].matched) ? matches[3].str() : "_";
+ info.filename =
+ (matches.size() >= 4 && matches[3].matched) ? matches[3].str() : "_";
info.data_array_name = "ASSET_DATA_" + info.name;
info.params_array_name = "ASSET_PROC_PARAMS_" + info.name;
@@ -107,103 +131,128 @@ int main(int argc, char* argv[]) {
info.is_procedural = true;
size_t open_paren = compression_type_str.find('(');
size_t close_paren = compression_type_str.rfind(')');
- if (open_paren == std::string::npos || close_paren == std::string::npos) {
- fprintf(stderr, "Error: Invalid PROC() syntax for asset: %s, string: [%s]\n", info.name.c_str(), compression_type_str.c_str());
+ if (open_paren == std::string::npos ||
+ close_paren == std::string::npos) {
+ fprintf(stderr,
+ "Error: Invalid PROC() syntax for asset: %s, string: [%s]\n",
+ info.name.c_str(), compression_type_str.c_str());
return 1;
}
- std::string func_and_params_str = compression_type_str.substr(open_paren + 1, close_paren - open_paren - 1);
-
+ std::string func_and_params_str = compression_type_str.substr(
+ open_paren + 1, close_paren - open_paren - 1);
+
size_t params_start = func_and_params_str.find(',');
if (params_start != std::string::npos) {
std::string params_str = func_and_params_str.substr(params_start + 1);
info.proc_func_name = func_and_params_str.substr(0, params_start);
-
+
size_t current_pos = 0;
while (current_pos < params_str.length()) {
size_t comma_pos = params_str.find(',', current_pos);
- std::string param_val_str = (comma_pos == std::string::npos) ? params_str.substr(current_pos) : params_str.substr(current_pos, comma_pos - current_pos);
+ std::string param_val_str =
+ (comma_pos == std::string::npos)
+ ? params_str.substr(current_pos)
+ : params_str.substr(current_pos, comma_pos - current_pos);
param_val_str.erase(0, param_val_str.find_first_not_of(" \t\r\n"));
param_val_str.erase(param_val_str.find_last_not_of(" \t\r\n") + 1);
try {
info.proc_params.push_back(std::stof(param_val_str));
} catch (...) {
- fprintf(stderr, "Error: Invalid proc param for %s: %s\n", info.name.c_str(), param_val_str.c_str());
+ fprintf(stderr, "Error: Invalid proc param for %s: %s\n",
+ info.name.c_str(), param_val_str.c_str());
return 1;
}
- if (comma_pos == std::string::npos) break;
+ if (comma_pos == std::string::npos)
+ break;
current_pos = comma_pos + 1;
}
} else {
- info.proc_func_name = func_and_params_str;
+ info.proc_func_name = func_and_params_str;
}
// Validate procedural function name
// kAssetPackerProcGenFuncMap is defined globally for validation
- if (kAssetPackerProcGenFuncMap.find(info.proc_func_name) == kAssetPackerProcGenFuncMap.end()) {
- fprintf(stderr, "Error: Unknown procedural function: %s for asset: %s\n", info.proc_func_name.c_str(), info.name.c_str());
+ if (kAssetPackerProcGenFuncMap.find(info.proc_func_name) ==
+ kAssetPackerProcGenFuncMap.end()) {
+ fprintf(stderr,
+ "Error: Unknown procedural function: %s for asset: %s\n",
+ info.proc_func_name.c_str(), info.name.c_str());
return 1;
}
}
-
+
asset_build_infos.push_back(info);
- fprintf(assets_h_file, " ASSET_%s = %d,\n", info.name.c_str(), asset_id_counter++);
+ fprintf(assets_h_file, " ASSET_%s = %d,\n", info.name.c_str(),
+ asset_id_counter++);
} else {
- fprintf(stderr, "Warning: Skipping malformed line in assets.txt: %s\n", line.c_str());
+ fprintf(stderr, "Warning: Skipping malformed line in assets.txt: %s\n",
+ line.c_str());
}
}
fprintf(assets_h_file, " ASSET_LAST_ID = %d,\n", asset_id_counter);
fprintf(assets_h_file, "};\n");
- fprintf(assets_h_file, "#include \"util/asset_manager.h\"\n"); // Include here AFTER enum definition
+ fprintf(assets_h_file,
+ "#include \"util/asset_manager.h\"\n"); // Include here AFTER enum
+ // definition
std::fclose(assets_h_file);
for (const auto& info : asset_build_infos) {
- if (!info.is_procedural) {
- std::string base_dir = assets_txt_path.substr(0, assets_txt_path.find_last_of("/\\") + 1);
- std::ifstream asset_file(base_dir + info.filename, std::ios::binary);
- if (!asset_file.is_open()) {
- fprintf(stderr, "Error: Could not open asset file: %s\n", (base_dir + info.filename).c_str());
- return 1;
- }
- std::vector<uint8_t> buffer((std::istreambuf_iterator<char>(asset_file)), std::istreambuf_iterator<char>());
- fprintf(assets_data_cc_file, "static const uint8_t %s[] = {\n ", info.data_array_name.c_str());
- for (size_t i = 0; i < buffer.size(); ++i) {
- if (i > 0 && i % 12 == 0) fprintf(assets_data_cc_file, "\n ");
- fprintf(assets_data_cc_file, "0x%02x%s", buffer[i], (i == buffer.size() - 1 ? "" : ", "));
- }
- fprintf(assets_data_cc_file, "\n};\n");
- } else {
- fprintf(assets_data_cc_file, "static const float %s[] = {", info.params_array_name.c_str());
- for (size_t i = 0; i < info.proc_params.size(); ++i) {
- if (i > 0) fprintf(assets_data_cc_file, ", ");
- fprintf(assets_data_cc_file, "%f", info.proc_params[i]);
- }
- fprintf(assets_data_cc_file, "};\n\n");
- fprintf(assets_data_cc_file, "static const char* %s = \"%s\";\n\n", info.func_name_str_name.c_str(), info.proc_func_name.c_str());
+ if (!info.is_procedural) {
+ std::string base_dir =
+ assets_txt_path.substr(0, assets_txt_path.find_last_of("/\\") + 1);
+ std::ifstream asset_file(base_dir + info.filename, std::ios::binary);
+ if (!asset_file.is_open()) {
+ fprintf(stderr, "Error: Could not open asset file: %s\n",
+ (base_dir + info.filename).c_str());
+ return 1;
}
+ std::vector<uint8_t> buffer((std::istreambuf_iterator<char>(asset_file)),
+ std::istreambuf_iterator<char>());
+ fprintf(assets_data_cc_file, "static const uint8_t %s[] = {\n ",
+ info.data_array_name.c_str());
+ for (size_t i = 0; i < buffer.size(); ++i) {
+ if (i > 0 && i % 12 == 0)
+ fprintf(assets_data_cc_file, "\n ");
+ fprintf(assets_data_cc_file, "0x%02x%s", buffer[i],
+ (i == buffer.size() - 1 ? "" : ", "));
+ }
+ fprintf(assets_data_cc_file, "\n};\n");
+ } else {
+ fprintf(assets_data_cc_file, "static const float %s[] = {",
+ info.params_array_name.c_str());
+ for (size_t i = 0; i < info.proc_params.size(); ++i) {
+ if (i > 0)
+ fprintf(assets_data_cc_file, ", ");
+ fprintf(assets_data_cc_file, "%f", info.proc_params[i]);
+ }
+ fprintf(assets_data_cc_file, "};\n\n");
+ fprintf(assets_data_cc_file, "static const char* %s = \"%s\";\n\n",
+ info.func_name_str_name.c_str(), info.proc_func_name.c_str());
+ }
}
fprintf(assets_data_cc_file, "extern const AssetRecord g_assets[] = {\n");
for (const auto& info : asset_build_infos) {
fprintf(assets_data_cc_file, " { ");
if (info.is_procedural) {
- fprintf(assets_data_cc_file, "nullptr, 0, true, %s, %s, %zu",
- info.func_name_str_name.c_str(),
- info.params_array_name.c_str(),
+ fprintf(assets_data_cc_file, "nullptr, 0, true, %s, %s, %zu",
+ info.func_name_str_name.c_str(), info.params_array_name.c_str(),
info.proc_params.size());
} else {
fprintf(assets_data_cc_file, "%s, sizeof(%s), false, nullptr, nullptr, 0",
- info.data_array_name.c_str(),
- info.data_array_name.c_str());
+ info.data_array_name.c_str(), info.data_array_name.c_str());
}
fprintf(assets_data_cc_file, " },\n");
}
fprintf(assets_data_cc_file, "};\n");
- fprintf(assets_data_cc_file, "extern const size_t g_assets_count = sizeof(g_assets) / sizeof(g_assets[0]);\n");
+ fprintf(assets_data_cc_file,
+ "extern const size_t g_assets_count = sizeof(g_assets) / "
+ "sizeof(g_assets[0]);\n");
std::fclose(assets_data_cc_file);
-
+
printf("Asset packer successfully generated records for %zu assets.\n",
asset_build_infos.size());