# Compact Asset System for the 64k Demo This file describes the asset system architecture and runtime API. ## Core Concept All assets are const byte arrays embedded in the binary. Runtime retrieval via `GetAsset(AssetId)` returns direct pointers with O(1) lookup. ## Runtime Asset Retrieval ```cpp #include "assets.h" const uint8_t* mysample = GetAsset(ASSET_SAMPLE_142, &size); // ... use asset DropAsset(ASSET_SAMPLE_142, mysample); // For lazy decompression cleanup ``` ## Asset Manifest Format File: `assets/final/demo_assets.txt` Format (CSV): ``` ASSET_NAME, filename.ext, COMPRESSION, "Description" ``` Example: ``` SAMPLE_142, sample_142.spec, NONE, "This is a drum kick sample" SHADER_COMMON, shaders/common.wgsl, NONE, "Common utilities" ``` This generates: ```cpp enum class AssetId : uint16_t { ASSET_SAMPLE_142 = 6323, SHADER_COMMON = 6324, // ... }; ``` ## Build Pipeline Tool: `tools/asset_packer.cc` 1. Parse `demo_assets.txt` 2. Read binary files from `assets/final/` 3. Generate `assets.h` (enum definitions) 4. Generate `assets_data.cc` (embedded byte arrays) 5. Auto-triggered by CMake on manifest changes ## Technical Guarantees 1. **Alignment**: All arrays declared `alignas(16)` for safe `reinterpret_cast` 2. **String Safety**: Null-terminator appended (safe as C-string) 3. **Size Reporting**: `size` reflects original file size (buffer is `size + 1`) ## Shader Asset Usage ```cpp size_t size; const uint8_t* shader_src = GetAsset(AssetId::SHADER_COMMON, &size); std::string_view code(reinterpret_cast(shader_src), size); ShaderComposer::register_snippet("common", code); ``` ## Procedural Assets Format: `PROC(function_name, params...)` Example: ``` NOISE_TEX, PROC(gen_noise, 1234, 16), NONE, "Noise texture seed=1234 freq=16" ``` Runtime: First `GetAsset()` call invokes generator, caches result. ## Design Strengths - Enum-based type safety (no magic numbers) - Zero runtime cost for static assets - Procedural generation support (size savings) - Thread-safe for immutable assets ## Design Weaknesses - **No compression**: Only `NONE` supported (critical blocker for 64k) - **STL dependencies**: `std::map` in runtime code (conflicts with CRT removal) - **Hardcoded procedural dimensions**: Assumes 256×256 RGBA8 - **No integrity checks**: No CRC/hash validation ## Developer Workflow **Add new asset:** 1. Place file in `assets/final/` 2. Edit `assets/final/demo_assets.txt`: ``` MY_ASSET, myfile.ext, NONE, "Description" ``` 3. Regenerate: `./scripts/gen_assets.sh` or rebuild (auto-triggered) 4. Use in code: `GetAsset(AssetId::MY_ASSET, &size)` **Modify existing asset:** - Edit source file in `assets/final/` - CMake auto-detects change and rebuilds ## Planned Improvements See **TODO.md** for detailed task breakdown: - **Task #27**: Asset compression (zlib, RLE) - **Task #28**: Spectrogram quantization (float32 → uint16_t) - **Task #29**: WGSL shader minification - **Task #30**: Procedural asset generalization - **Task #31**: Asset integrity validation (CRC32) - **Task #32**: Hot-reloading (dev builds) - **Task #33**: Dead asset elimination ## Current Manifest 33 assets total: - 15 audio samples (`.spec`) - 17 WGSL shaders - 1 procedural texture