summaryrefslogtreecommitdiff
path: root/doc/ASSET_SYSTEM.md
blob: 8f31a6a3551d545f76a015c679f459e67cb15dc6 (plain)
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

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<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 `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