1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# 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
Files: `workspaces/main/assets.txt`, `workspaces/test/assets.txt`
Format (CSV):
```
ASSET_NAME, COMPRESSION, filename.ext, "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 workspace `assets.txt`
2. Read files from workspace `assets/` or `assets/common/`
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<const char*>(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 workspace `assets/` (or `assets/common/` for shared)
2. Edit workspace `assets.txt`:
```
MY_ASSET, NONE, assets/myfile.ext, "Description"
```
3. Rebuild: `cmake --build build -j4` (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
|