# SpinalVoodoo
**Repository Path**: tangdk/SpinalVoodoo
## Basic Information
- **Project Name**: SpinalVoodoo
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-03-30
- **Last Updated**: 2026-03-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# SpinalVoodoo
SpinalHDL implementation of the 3dfx Voodoo Graphics GPU.
## Simulation Gallery
 Logo |
 Screamer 2 |
 Quake |
 Valley of Ra |
## Implementation Status
### FBI (Frame Buffer Interface)
- Rasterization
- [x] Triangle setup (bounding-box scan + edge function testing)
- [x] Span generation (serpentine scan)
- [x] Scissor clipping (clipLeftRight, clipLowYHighY)
- [x] Y-origin transform (fbzMode bit 17, fbiInit3[31:22])
- [ ] Stipple patterns
- Gradient Interpolation
- [x] Color (R, G, B, A) - 12.12 fixed-point
- [x] Depth (Z) - 20.12 fixed-point
- [x] Texture coordinates (S, T, W) - 14.18 / 2.30 fixed-point
- [x] Parameter adjustment for sub-pixel vertices (fbzColorPath bit 26)
- Color Combine Unit (CCU)
- [x] c_other source selection (iterated, texture, color1, LFB)
- [x] c_local source selection (iterated, color0)
- [x] cc_localselect_override (texture alpha bit 7 selects color0)
- [x] zero_other, sub_clocal
- [x] All mselect modes (ZERO, CLOCAL, AOTHER, ALOCAL, TEXTURE_ALPHA, TEXTURE_RGB)
- [x] reverse_blend (factor inversion)
- [x] Add modes (NONE, CLOCAL, ALOCAL)
- [x] Invert output
- Alpha Combine Unit (ACU)
- [x] a_other source selection (iterated, texture, color1, LFB)
- [x] a_local source selection (iterated, color0, iterated_z)
- [x] alpha_zero_other, alpha_sub_clocal
- [x] All alpha mselect modes
- [x] alpha_reverse_blend, alpha_add, alpha_invert_output
- Fog
- [x] W-based fog table lookup
- [x] Iterated fog (alpha/Z based)
- [x] Fog color blending
- Alpha Test
- [x] Comparison functions (never, <, ==, <=, >, !=, >=, always)
- [x] Reference alpha
- Depth Buffer
- [x] Z-buffer read/compare
- [x] Depth function selection
- [x] Z-buffer write
- [x] W-buffer mode
- [x] Depth bias
- [x] Depth source select (iterated Z or W)
- Alpha Blending
- [x] Source blend factors (10 modes)
- [x] Destination blend factors (10 modes)
- [x] Framebuffer read for blending (fork-queue-join BMB pattern)
- Chroma Key
- [x] Color key comparison (post color-combine, matching real hardware)
- [ ] Chroma range
- Dithering
- [x] 4x4 ordered dither (86Box ground-truth LUTs)
- [x] 2x2 ordered dither (86Box ground-truth LUTs)
- Framebuffer Write
- [x] 16-bit RGB565 output
- [x] Draw buffer selection
- [x] Depth/alpha planes selection (fbzMode bit 18)
- [x] RGB write mask
- [x] Aux write mask
- Linear Frame Buffer (LFB)
- [x] Direct CPU writes (bypass mode, all write formats)
- [x] Pixel format conversion (RGB565, RGB555, ARGB1555, XRGB8888, ARGB8888, Depth+color, Depth-only)
- [x] Dual-pixel (16-bit formats) and single-pixel (32-bit formats) modes
- [x] RGBA lane swizzle (ARGB, ABGR, RGBA, BGRA)
- [x] Word swap and byte swizzle
- [x] Dithering support
- [x] Pipeline routing option (pixelPipelineEnable=1)
- [x] LFB reads
- Commands
- [x] triangleCMD / ftriangleCMD
- [x] fastfillCMD (screen clear via clip rectangle, color1/zaColor, with dithering)
- [x] nopCMD
- [x] swapbufferCMD (immediate + vsync-synchronized, swapsPending tracking)
### TMU (Texture Mapping Unit)
- Texture Coordinates
- [x] S/T/W interpolation
- [x] Perspective correction (S/W, T/W division via 257-entry reciprocal LUT)
- LOD (Level of Detail)
- [x] LOD calculation from gradients (max gradient MSB position)
- [x] Mipmap base offset calculation (per-LOD cumulative sizes)
- [x] LOD bias (tLOD bits 17:12)
- [x] LOD clamping (lodmin, lodmax)
- [x] Per-pixel LOD adjustment (perspective-corrected W)
- [x] Aspect ratio / non-square textures (tLOD lodAspect + lodSIsWider)
- [ ] Trilinear blending (lod_frac)
- Texture Address
- [x] texBaseAddr register
- [x] Texel address generation (row-major, 8/16-bit stride)
- [x] Clamp and wrap modes (per-axis, textureMode bits 6-7)
- [x] Clamp W (negative W forces S=T=0, textureMode bit 3)
- [ ] texBaseAddr_1/2/3_8 (per-LOD base addresses)
- Texture Filtering
- [x] Point sampling (nearest)
- [x] Bilinear filtering (min/mag)
- Texture Formats (decode logic)
- [x] RGB332 (8-bit)
- [x] A8 (8-bit, alpha only)
- [x] I8 (8-bit, intensity)
- [x] AI44 (8-bit, alpha + intensity)
- [x] ARGB8332 (16-bit)
- [x] RGB565 (16-bit)
- [x] ARGB1555 (16-bit)
- [x] ARGB4444 (16-bit)
- [x] AI88 (16-bit, alpha + intensity)
- [x] YIQ422 / AYIQ8422 (NCC compressed)
- [x] P8 / AP88 (palettized)
- Texture Combine
- [x] Texture output to color combine unit
- [ ] Multi-texture (TMU chaining)
- [x] NCC table decode
- [x] Palette RAM (256-entry, loaded via NCC table 0 I/Q registers)
- [ ] LOD dither
- [ ] Data swizzle/swap
### Bus Interface / Register System
- [x] BMB bus adapter (BmbBusInterface)
- [x] 64-entry PCI FIFO with categorized routing (fifoBypass / syncRequired)
- [x] Pipeline drain blocking for sync registers (triangleCMD, swapbufferCMD, etc.)
- [x] Address remapping (fbiInit3 bit 0, external bit 21)
- [x] CPU bus address decode (PCI BAR regions: registers, LFB, texture)
- [x] texBaseAddr write relocation (SST-1 spec 5.53)
- [ ] PCI configuration space (initEnable, busSnoop)
- [ ] Memory FIFO (off-screen framebuffer extension)
### Display Controller
- [ ] Video timing generator (hSync, vSync, backPorch, videoDimensions)
- [ ] Framebuffer scan-out
- [ ] Gamma correction CLUT (clutData)
- [ ] DAC programming (dacData)
- vRetrace is currently an external input (no internal generation)
## Scala CLI Commands
```bash
# Run tests
scala-cli test .
# Format code
scalafmt
# Compile
scala-cli compile .
```
## Glide Simulation Tests
Run the Glide2x test suite against the Verilator model:
```bash
make native/sim/run/test00 # single test
make native/sim/run-all # all screenshot tests
TRACE=1 make native/sim/run/test00 # with FST waveform dump
```
Screenshots are saved to `output//screenshot.png`.
**Environment variables** (set at runtime):
| Variable | Description |
|---|---|
| `SIM_FST` | Path for FST waveform output (requires `TRACE=1` build) |
| `SIM_CYCLE_LIMIT` | Max simulation ticks before clean exit (0 = unlimited) |
| `SIM_FBWRITE_LOG` | Path to log framebuffer writes |
| `SIM_TMU_LOG` | Path to log TMU/rasterizer activity |
## DOSBox-X (32-bit Glide Path)
The sim backend builds a **32-bit** `libglide2x`, so DOSBox-X must also be
32-bit to `dlopen()` it.
```bash
# Linux-hosted sim test
make native/sim/run/test00
# Linux-hosted trace capture
make native/trace/run/df00sim
# Build and run a DOS guest binary inside DOSBox-X through its built-in GLIDE2X.OVL
make dos/sim/run/df00sdk
# Headless DOS guest variant
make dos/sim/headless/df00sdk
# DOS guest with trace backend
make dos/trace/run/df00sdk
# Launch a raw DOSBox-X session with the sim Glide backend injected
make dos/dosbox
```
Common top-level commands:
- `make native/help` prints the Linux-hosted and trace command surface.
- `make native/sim/build` builds all Linux-hosted Glide test binaries.
- `make native/sim/build/` builds one Linux-hosted test binary.
- `make native/sim/run/` runs one Linux-hosted test and writes screenshot output under `output/`.
- `make native/trace/run/` rebuilds the host Glide runtime with the trace harness and captures `traces/.bin`.
- `make native/sim/check/` replays an existing trace through the check pipeline.
- `make native/sim/test/` captures and checks in one step.
- `make native/sim/check-all` replays every existing trace under `traces/`.
- `make dos/help` prints the DOS and Tomb command surface.
- `make dos/sim/build` builds all DOS SDK-style test binaries from `emu/glide/glide2x/sst1/glide/tests/Makefile.sdkwat`.
- `make dos/sim/build/` builds one DOS SDK-style binary, for example `make dos/sim/build/df00sdk`.
- `make dos/sim/run/` mounts `emu/glide/glide2x/sst1/glide/tests` as `C:` in DOSBox-X and runs `.exe` with the sim backend.
- `make dos/sim/headless/` does the same with `DOSBOXX32_HEADLESS=1`.
- `make dos/trace/run/` runs a DOS guest against the trace-capture Glide runtime and writes `traces/dos/.bin`.
- `make dos/trace/headless/` does the same headlessly.
- `make dos/dosbox ARGS='...'` launches DOSBox-X with the sim Glide backend and forwards extra DOSBox-X arguments.
- `make tomb/help` prints the Tomb Raider setup requirements.
- `make tomb/prepare ARGS='--game-dir ... --patch ... --iso ...'` prepares a reusable Tomb Raider source tree from your game files and 3dfx patch assets.
- `make tomb/sim/run`, `make tomb/sim/headless`, and `make tomb/sim/capture` run Tomb Raider against the sim backend.
- `make tomb/sim/trace` runs Tomb Raider against the live sim runtime and also dumps a trace to `traces/tomb_live/trace.bin`.
- `make tomb/sim/trace/check` replays `traces/tomb_live/trace.bin` into `output/tomb/trace_replay_live/`.
- `make tomb/trace/run` and `make tomb/trace/headless` run Tomb Raider against the trace runtime and write `traces/tomb/trace.bin` automatically.
- `make tomb/trace/check` replays `traces/tomb/trace.bin` directly into `output/tomb/trace_replay/` without pulling in any stale `state.bin` from an old trace directory.
The hierarchy is intentional:
- `native//[/]` is for Linux-hosted test binaries.
- `dos//[/]` is for DOS guest binaries inside DOSBox-X.
- `tomb//` is for Tomb Raider convenience flows.
- `de10/` is for board-oriented workflows using the `de10` runtime.
Runtimes are explicit and non-stateful:
- `sim` means the normal in-process Verilator-backed Glide runtime.
- `trace` means the trace-capture Glide runtime.
- `de10` means the board/MMIO-backed Glide runtime.
In practice:
- `native/...` and `dos/...` currently expose `sim` and `trace` directly in the command path.
- `de10/...` keeps the runtime implicit in the namespace because every `de10` command already targets the board runtime.
- `SIM_INTERFACE=de10` is the closest host-side reproduction of the board interface: it still uses the `sim` runtime, but swaps the Verilated top-level from `CoreSim` to `CoreDe10` and drives the DE10-style MMIO plus Avalon memory ports from the host harness.
Examples:
```bash
make native/sim/run/test00 SIM_INTERFACE=de10
make dos/sim/run/df00sdk SIM_INTERFACE=de10
```
### Tomb Raider Setup
The Tomb helper scripts expect a prepared source tree at `DOSBOX_TOMB_SRC`.
By default that is `/tmp/tr1-3dfx`.
The easiest way to create it is:
```bash
make tomb/prepare ARGS='--game-dir /path/to/TOMBRAID --patch /path/to/3dfx-patch.zip --iso /path/to/tr1disc01.iso'
```
That helper:
- copies your source game directory into `DOSBOX_TOMB_SRC/TOMBRAID`
- copies the ISO into `DOSBOX_TOMB_SRC/tr1disc01.iso` if provided
- overlays the supplied 3dfx patch directory or archive onto the game directory
It accepts either a patch directory or a `.zip`/tar archive. Add `--output /path/to/tree`
to prepare somewhere other than `DOSBOX_TOMB_SRC`, and `--force` to replace an existing tree.
Expected layout by default:
```text
/tmp/tr1-3dfx/
tr1disc01.iso
TOMBRAID/
TOMB.EXE
... game files ...
```
Typical flow:
- Prepare the tree with `make tomb/prepare ...`, or assemble the layout manually.
- Run `make tomb/help` to print the current assumptions.
- Run `make tomb/sim/run` or `make tomb/sim/headless`.
At launch time the helper scripts copy the source tree into `DOSBOX_TOMB_STAGE_ROOT`
(default `/tmp/tr1-run`) and automatically rename any bundled `glide2x.ovl` so that
DOSBox-X's built-in `GLIDE2X.OVL` guest bridge is used instead.
You can override the defaults with these environment variables:
- `DOSBOX_TOMB_SRC`
- `DOSBOX_TOMB_STAGE_ROOT`
- `DOSBOX_TOMB_GAME_DIR`
- `DOSBOX_TOMB_ISO`
- `DOSBOX_TOMB_EXE`
Notes:
- `scripts/run-dosboxx32-glide` prefers `DOSBOXX32_BIN` if set.
- If `dosbox-x` on `PATH` is already 32-bit, it uses that.
- Otherwise it auto-resolves Nix `pkgsi686Linux.dosbox-x`.
- The script appends `scripts/dosboxx32-glide.conf` (enables `glide=true`, `voodoo_card=false`, `lfb=full_noaux`).
- For low-level manual control you can still use `scripts/run-dosboxx32-glide` directly.
## Trace-Based Testing
Glide trace files (`.bin`) capture PCI bus operations for offline replay against both
the RTL simulation and a software reference model:
```bash
# Capture a trace from a Linux-hosted test
make native/trace/run/test_alphabet
# Replay one trace through the reference model and RTL simulator
make native/sim/check/test_alphabet
# Capture and replay in one step
make native/sim/test/test_alphabet
# Replay every existing trace
make native/sim/check-all
```
Replay outputs are written to `test-output//` as `_ref.png`, `_sim.png`, and `_diff.png`.
Trace files are stored in `traces/` and compared pixel-by-pixel against a reference model.
## DE10-Nano
The DE10-Nano flow is meant for three practical tasks:
- generate FPGA-ready RTL and bitstreams
- program or deploy a board
- run workloads on real hardware
Common commands:
```bash
make de10/help
# Generate RTL / FPGA build inputs
make de10/rtl
make de10/qsys
make de10/bitstream
# Program or deploy to the default board (fpga@debian-fpga.local)
make de10/setup/program
make de10/setup/deploy
# Basic board validation
make de10/check/mmio
# Run workloads on hardware
make de10/run/dos/df00sdk
make de10/run/tomb
```
Useful defaults and assumptions:
- Default board target is `fpga@debian-fpga.local` unless `DE10_HOST` or `DE10_USER` override it.
- Default deployed runtime prefix is `/home/fpga/spinalvoodoo` unless `DE10_REMOTE_PREFIX` overrides it.
- `make de10/run/dos/` uses the deployed launcher on the board and mounts `DE10_RUNTIME_DIR` (default `/home/fpga/de10-cross`) as `C:`.
- `make de10/run/tomb` expects a prepared remote Tomb tree at `DE10_TOMB_SRC` (default `/home/fpga/tr1-3dfx`) containing the game directory and ISO.
Extra DE10 helpers live in `scripts/` and `tools/` for board capture, replay, and bring-up.