# CLAUDE.md ## Project Overview DOOM-fire-zig is a terminal-based DOOM fire effect renderer written in Zig. It's a TTY stress test that pushes ~180KB per frame using ANSI escape codes and the half-block character (`▀`) for pixel rendering. Fork of https://github.com/const-void/DOOM-fire-zig. Single source file: `src/main.zig`. No dependencies beyond libc. ## Build & Run ```bash zig build run -Doptimize=ReleaseFast # build and run (recommended) zig build # build only zig build --global-cache-dir /tmp/claude/zig-cache # if global cache is read-only ``` The binary is output to `zig-out/bin/DOOM-fire`. Requires libc (`link_libc = true` in build.zig). Exit: Ctrl+C (no graceful key polling yet). At pause prompts: `q` + Enter to quit, Enter to continue. ## Zig Version Tracks latest Zig master (currently `0.17.0-dev.607+456b2ec07`). Version is recorded in three places that must stay in sync: - `.zigversion` - `build.zig.zon` `.version` field - `build.zig.zon` `.minimum_zig_version` field ## Architecture Everything lives in `src/main.zig`. The program flow is: 1. `main()` -> `initTerm()` -> `checkTermSz()` -> `showTermCap()` -> `showDoomFire()` 2. **initTerm**: Sets up colors, terminal mode (ANSI escape sequences, Windows console API), terminal size, RNG 3. **checkTermSz**: Warns if terminal is smaller than 120x22 4. **showTermCap**: Renders color palette and scrolling marquee animation to verify terminal capabilities 5. **showDoomFire**: The main fire simulation loop - updates fire buffer, renders to screen buffer, paints ### Key Design Patterns - **Cross-platform via compile-time branching**: `if (builtin.os.tag == .windows)` guards throughout. Windows uses kernel32 API; Linux/macOS uses libc + ANSI. - **Never use `\n` directly**: On Windows, newlines are emulated via ANSI cursor movement (`line_new`). Use `nl` constant everywhere. - **Buffered rendering**: Fire frames are built in `bs` (buffer string) via `drawBuf()`, then flushed in one `emit()` call via `paintBuf()` for performance. - **emit() for all output**: All terminal output goes through `emit()` which uses `std.c.write` on Linux or `WriteConsoleA` on Windows. - **Half-height pixels**: Each character cell represents two vertical pixels using `▀` with fg=top pixel color, bg=bottom pixel color. ### Timing Uses `std.c.clock_gettime(.MONOTONIC, ...)` for both RNG seeding and FPS measurement. No `std.time.Instant` or `std.time.Timer` (removed from std in recent Zig versions). ## Windows Support The `win32` struct at the bottom of `main.zig` contains all Windows kernel32 FFI declarations. Windows uses UTF-16 via `WriteConsoleW` for wide chars but the project currently uses `WriteConsoleA` (ASCII) due to Zig's UTF-8 string model. Windows doesn't get fancy UTF-8 glyphs as a result. ## Updating Zig Version When updating to a new Zig nightly: 1. Update `.zigversion`, `build.zig.zon` (version + minimum_zig_version) 2. Run `zig build` and fix any std library API breakage 3. Common breakage areas: `std.time`, `std.c`, `std.posix` APIs change frequently in Zig master 4. If the global zig cache is read-only, use `--global-cache-dir /tmp/claude/zig-cache` 5. Clear `.zig-cache/` if you see stale cache errors after a version change ## License GPL-3.0. Copyright 2022-2025 const-void.