diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-09 17:35:32 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-09 17:35:32 +0100 |
| commit | d5f78a4c2e7b626a492643efd62ddeb394276722 (patch) | |
| tree | cdf38c3d64f6bf417975ce396572fc425d6f8910 /doc/HOT_RELOAD.md | |
| parent | 802e97ee695de1bc8657c5cbca653bb2f13b90a8 (diff) | |
feat: Add debug-only file change detection for rapid iteration
Enables --hot-reload flag to watch config files and notify on changes.
Detects modifications to assets/sequences/music for rebuild workflow.
Completely stripped from release builds (0 bytes overhead).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'doc/HOT_RELOAD.md')
| -rw-r--r-- | doc/HOT_RELOAD.md | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/doc/HOT_RELOAD.md b/doc/HOT_RELOAD.md new file mode 100644 index 0000000..681d0aa --- /dev/null +++ b/doc/HOT_RELOAD.md @@ -0,0 +1,162 @@ +# Hot-Reload System + +## Overview + +The hot-reload system enables rapid iteration during development by detecting changes to configuration files at runtime. This feature is **debug-only** and completely stripped from release builds (adds 0 bytes to final binary). + +## Status + +**Implemented:** +- File change detection (`FileWatcher` class) +- Command-line flag `--hot-reload` +- Notification when config files change + +**Not Implemented (Requires Rebuild):** +- Asset reloading (`assets/final/demo_assets.txt`) +- Sequence reloading (`assets/demo.seq`) +- Music reloading (`assets/music.track`) + +Currently, the system **detects** file changes and informs the user to rebuild. Full runtime reload would require significant refactoring of the compile-time asset system. + +## Usage + +```bash +# Launch with hot-reload enabled +./build/demo64k --hot-reload + +# Edit config files while running +vim assets/demo.seq + +# Demo will print: +# [Hot-Reload] Config files changed - rebuild required +# [Hot-Reload] Run: cmake --build build -j4 && ./build/demo64k +``` + +## Architecture + +### File Watcher (`src/util/file_watcher.h`) + +Simple polling-based file change detection using `stat()` mtime: + +```cpp +#if !defined(STRIP_ALL) +FileWatcher watcher; +watcher.add_file("assets/demo.seq"); + +if (watcher.check_changes()) { + // File changed + watcher.reset(); +} +#endif +``` + +**Design:** +- Polls file mtimes in main loop (~60Hz) +- Cross-platform (POSIX stat) +- 1-second mtime granularity (filesystem dependent) + +**Watched Files:** +- `assets/final/demo_assets.txt` - Asset definitions +- `assets/demo.seq` - Visual effect timeline +- `assets/music.track` - Audio patterns + +### Integration (`src/main.cc`) + +```cpp +#if !defined(STRIP_ALL) +bool hot_reload_enabled = false; + +// Command-line parsing +if (strcmp(argv[i], "--hot-reload") == 0) { + hot_reload_enabled = true; +} + +// Setup +FileWatcher file_watcher; +if (hot_reload_enabled) { + file_watcher.add_file("assets/final/demo_assets.txt"); + file_watcher.add_file("assets/demo.seq"); + file_watcher.add_file("assets/music.track"); +} + +// Main loop +if (hot_reload_enabled && file_watcher.check_changes()) { + printf("[Hot-Reload] Config files changed - rebuild required\n"); + file_watcher.reset(); +} +#endif +``` + +## Why Not Full Reload? + +The current architecture compiles all assets at build time: + +1. **Assets** (`demo_assets.txt`): + - Parsed by `asset_packer` tool + - Generates C++ arrays in `generated/assets.h` + - Linked into binary as static data + - Runtime reload would need file I/O + dynamic memory + +2. **Sequences** (`demo.seq`): + - Parsed by `seq_compiler` tool + - Generates `LoadTimeline()` function in C++ + - Effect objects created with compile-time parameters + - Runtime reload would need C++ code generation or scripting + +3. **Music** (`music.track`): + - Parsed by `tracker_compiler` tool + - Generates static pattern/score data + - Referenced by pointers in audio engine + - Runtime reload needs atomic pointer swap + memory management + +Implementing full reload would require: +- Runtime parsers (duplicate build-time compilers) +- Dynamic memory allocation (conflicts with size optimization) +- Effect state preservation (complex) +- Thread-safe audio data swap +- ~20-25 hours of work (per the plan) + +## Size Impact + +**Debug build:** +800 bytes (FileWatcher + main loop logic) +**STRIP_ALL build:** 0 bytes (all code removed by `#if !defined(STRIP_ALL)`) + +## Testing + +Unit test: `src/tests/test_file_watcher.cc` + +```bash +# Run test +cd build && ctest -R FileWatcherTest + +# Note: Test sleeps 1 second to ensure mtime changes +# (some filesystems have 1s mtime granularity) +``` + +## Future Work + +If hot-reload becomes critical for workflow, consider: + +1. **Incremental approach:** + - Phase 1: Asset cache clearing (easy, limited value) + - Phase 2: Sequence state preservation (medium, high value) + - Phase 3: Tracker atomic swap (hard, high value) + +2. **External scripting:** + - Watch files externally (fswatch/inotifywait) + - Auto-rebuild + restart demo + - Preserves current architecture + +3. **Hybrid approach:** + - Keep compile-time for release + - Add optional runtime parsers for debug + - Conditional on `--hot-reload` flag + +## Related Files + +- `src/util/file_watcher.h` - File change detection API +- `src/util/file_watcher.cc` - Implementation +- `src/util/asset_manager.cc` - Stub `ReloadAssetsFromFile()` (clears cache) +- `src/main.cc` - Main loop integration +- `src/tests/test_file_watcher.cc` - Unit tests +- `CMakeLists.txt` - Build system integration |
