diff options
| -rw-r--r-- | CMakeLists.txt | 160 | ||||
| -rw-r--r-- | assets/final/assets.txt | 2 | ||||
| -rw-r--r-- | assets/final/null.bin | 0 | ||||
| -rw-r--r-- | assets/final/test_asset.txt | 3 | ||||
| -rw-r--r-- | src/tests/test_assets.cc | 29 | ||||
| -rw-r--r-- | tools/asset_packer.cc | 64 |
6 files changed, 154 insertions, 104 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d06033..d460131 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,33 @@ else() list(APPEND DEMO_LIBS pthread m dl) endif() +option(DEMO_BUILD_TOOLS "Build tools" OFF) + +# Asset Packing Tool (needed during build if any assets exist) +if(DEMO_BUILD_TOOLS OR NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/src/assets_data.cc) + add_executable(asset_packer + tools/asset_packer.cc + ) +endif() + +# Configure asset generation +set(ASSETS_TXT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/assets/final/assets.txt) +set(GENERATED_ASSETS_H ${CMAKE_CURRENT_BINARY_DIR}/src/assets.h) +set(GENERATED_ASSETS_DATA_CC ${CMAKE_CURRENT_BINARY_DIR}/src/assets_data.cc) + +add_custom_command( + OUTPUT ${GENERATED_ASSETS_H} ${GENERATED_ASSETS_DATA_CC} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/src + COMMAND asset_packer ${ASSETS_TXT_PATH} ${GENERATED_ASSETS_H} ${GENERATED_ASSETS_DATA_CC} + DEPENDS asset_packer ${ASSETS_TXT_PATH} + COMMENT "Generating assets.h and assets_data.cc" +) + +add_custom_target(generate_assets ALL + DEPENDS ${GENERATED_ASSETS_H} ${GENERATED_ASSETS_DATA_CC} +) + +# Main Demo Target add_executable(demo64k src/main.cc src/platform.cc @@ -67,9 +94,12 @@ add_executable(demo64k src/audio/window.cc src/audio/synth.cc third_party/glfw3webgpu/glfw3webgpu.c + ${GENERATED_ASSETS_DATA_CC} ) +add_dependencies(demo64k generate_assets) target_link_libraries(demo64k PRIVATE ${DEMO_LIBS}) +target_include_directories(demo64k PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) if (DEMO_SIZE_OPT) if (MSVC) @@ -84,6 +114,7 @@ if (DEMO_SIZE_OPT) endif() endif() +# Tests option(DEMO_BUILD_TESTS "Build tests" OFF) enable_testing() @@ -104,104 +135,55 @@ if(DEMO_BUILD_TESTS) target_include_directories(test_synth PRIVATE src) add_test(NAME SynthEngineTest COMMAND test_synth) - add_executable(test_spectool - - src/tests/test_spectool.cc - - src/audio/audio.cc - - src/audio/window.cc - - src/audio/fdct.cc - - src/audio/synth.cc - - src/audio/idct.cc - - third_party/glfw3webgpu/glfw3webgpu.c - - ) - - target_include_directories(test_spectool PRIVATE - - src - - third_party - - ${WGPU_INCLUDE_DIR} - - third_party/glfw3webgpu - - ) + add_executable(test_spectool + src/tests/test_spectool.cc + src/audio/audio.cc + src/audio/window.cc + src/audio/fdct.cc + src/audio/synth.cc + src/audio/idct.cc + third_party/glfw3webgpu/glfw3webgpu.c + ) + target_include_directories(test_spectool PRIVATE + src + third_party + ${WGPU_INCLUDE_DIR} + third_party/glfw3webgpu + ) target_link_libraries(test_spectool PRIVATE ${DEMO_LIBS}) add_test(NAME SpectoolEndToEndTest COMMAND test_spectool) -endif() -option(DEMO_BUILD_TOOLS "Build tools" OFF) + add_executable(test_assets + src/tests/test_assets.cc + ${GENERATED_ASSETS_DATA_CC} + ) + target_include_directories(test_assets PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src src) + add_dependencies(test_assets generate_assets) + add_test(NAME AssetManagerTest COMMAND test_assets) +endif() +# Tools if(DEMO_BUILD_TOOLS) - add_executable(spectool - tools/spectool.cc - src/platform.cc - src/audio/audio.cc - src/audio/fdct.cc - src/audio/idct.cc - src/audio/window.cc - src/audio/synth.cc - third_party/glfw3webgpu/glfw3webgpu.c - ) - target_include_directories(spectool PRIVATE - src - third_party - ${WGPU_INCLUDE_DIR} - third_party/glfw3webgpu - ) + add_executable(spectool + tools/spectool.cc + src/platform.cc + src/audio/audio.cc + src/audio/fdct.cc + src/audio/idct.cc + src/audio/window.cc + src/audio/synth.cc + third_party/glfw3webgpu/glfw3webgpu.c + ) + target_include_directories(spectool PRIVATE + src + third_party + ${WGPU_INCLUDE_DIR} + third_party/glfw3webgpu + ) target_link_libraries(spectool PRIVATE ${DEMO_LIBS}) add_executable(specview tools/specview.cc ) target_include_directories(specview PRIVATE src) - - add_executable(asset_packer - tools/asset_packer.cc - ) endif() - -# Configure asset generation -set(ASSETS_TXT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/assets/final/assets.txt) -set(GENERATED_ASSETS_H ${CMAKE_CURRENT_BINARY_DIR}/src/assets.h) -set(GENERATED_ASSETS_DATA_CC ${CMAKE_CURRENT_BINARY_DIR}/src/assets_data.cc) - -add_custom_command( - OUTPUT ${GENERATED_ASSETS_H} ${GENERATED_ASSETS_DATA_CC} - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/src - COMMAND asset_packer ${ASSETS_TXT_PATH} ${GENERATED_ASSETS_H} ${GENERATED_ASSETS_DATA_CC} - DEPENDS tools/asset_packer.cc ${ASSETS_TXT_PATH} - COMMENT "Generating assets.h and assets_data.cc" -) - -add_custom_target(generate_assets ALL - DEPENDS ${GENERATED_ASSETS_H} ${GENERATED_ASSETS_DATA_CC} -) - -add_executable(demo64k - src/main.cc - src/platform.cc - src/gpu/gpu.cc - src/audio/audio.cc - src/audio/fdct.cc - src/audio/idct.cc - src/audio/window.cc - src/audio/synth.cc - third_party/glfw3webgpu/glfw3webgpu.c - ${GENERATED_ASSETS_DATA_CC} -) - -# Ensure demo64k depends on the generated assets -add_dependencies(demo64k generate_assets) - -target_link_libraries(demo64k PRIVATE ${DEMO_LIBS}) - -# Include generated assets header for compilation -target_include_directories(demo64k PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
\ No newline at end of file diff --git a/assets/final/assets.txt b/assets/final/assets.txt index e69de29..c22fad8 100644 --- a/assets/final/assets.txt +++ b/assets/final/assets.txt @@ -0,0 +1,2 @@ +NULL_ASSET, null.bin, NONE, "Empty asset" +TEST_ASSET, test_asset.txt, NONE, "Test asset for verification" diff --git a/assets/final/null.bin b/assets/final/null.bin new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/assets/final/null.bin diff --git a/assets/final/test_asset.txt b/assets/final/test_asset.txt new file mode 100644 index 0000000..8a18097 --- /dev/null +++ b/assets/final/test_asset.txt @@ -0,0 +1,3 @@ +This is a test asset file. +It contains some text data to verify the asset packing system. +1234567890 diff --git a/src/tests/test_assets.cc b/src/tests/test_assets.cc new file mode 100644 index 0000000..eedc92b --- /dev/null +++ b/src/tests/test_assets.cc @@ -0,0 +1,29 @@ +#include "assets.h" +#include <assert.h> +#include <stdio.h> +#include <string.h> + +int main() { + printf("Running AssetManager test...\n"); + + size_t size = 0; + const uint8_t *data = GetAsset(AssetId::ASSET_TEST_ASSET, &size); + + assert(data != nullptr); + assert(size > 0); + + const char *expected_prefix = "This is a test asset file."; + if (strncmp((const char *)data, expected_prefix, strlen(expected_prefix)) == + 0) { + printf("Asset content verification: SUCCESS\n"); + } else { + printf("Asset content verification: FAILED\n"); + printf("Got: %.*s\n", (int)size, (const char *)data); + return 1; + } + + printf("Asset size: %zu bytes\n", size); + printf("AssetManager test PASSED\n"); + + return 0; +} diff --git a/tools/asset_packer.cc b/tools/asset_packer.cc index 8b06829..a67ddcc 100644 --- a/tools/asset_packer.cc +++ b/tools/asset_packer.cc @@ -39,7 +39,8 @@ int main(int argc, char *argv[]) { // Generate assets.h assets_h_file << "#pragma once\n"; - assets_h_file << "#include <cstdint>\n\n"; + assets_h_file << "#include <cstdint>\n"; + assets_h_file << "#include <cstddef>\n\n"; assets_h_file << "enum class AssetId : uint16_t {\n"; // Generate assets_data.cc header @@ -65,23 +66,51 @@ int main(int argc, char *argv[]) { 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); - if (asset_name.empty()) { - std::cerr << "Warning: Skipping line with empty asset name: " << line - << "\n"; + 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"; 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); + if (!asset_file.is_open()) { + std::cerr << "Error: Could not open asset file: " << base_dir + filename + << "\n"; + return 1; + } + + std::vector<uint8_t> buffer((std::istreambuf_iterator<char>(asset_file)), + std::istreambuf_iterator<char>()); + asset_file.close(); + asset_names.push_back(asset_name); // Add to assets.h enum assets_h_file << " ASSET_" << asset_name << " = " << asset_id_counter << ",\n"; - // Placeholder for assets_data.cc (empty data for now) + // Write data to assets_data.cc assets_data_cc_file << "const uint8_t ASSET_DATA_" << asset_name - << "[] = {};\n"; - assets_data_cc_file << "const size_t ASSET_SIZE_" << asset_name - << " = 0;\n\n"; + << "[] = {"; + for (size_t i = 0; i < buffer.size(); ++i) { + if (i % 12 == 0) + assets_data_cc_file << "\n "; + 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"; asset_id_counter++; } @@ -89,19 +118,22 @@ int main(int argc, char *argv[]) { 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 - << "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"; + << "void DropAsset(AssetId asset_id, const uint8_t *asset); // For lazy " + "decompression scaffolding\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 + << "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"; 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 << " if (out_size) *out_size = ASSET_SIZE_" << name + << ";\n"; assets_data_cc_file << " return ASSET_DATA_" << name << ";\n"; } assets_data_cc_file << " default:\n"; @@ -110,10 +142,12 @@ int main(int argc, char *argv[]) { 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 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 << " // No-op for now, actual implementation for lazy " + "decompression goes here\n"; assets_data_cc_file << "}\n"; assets_data_cc_file.close(); |
