SpinalHDL implementation of the 3dfx Voodoo Graphics GPU.
![]() Logo |
![]() Screamer 2 |
![]() Quake |
![]() Valley of Ra |
- Rasterization
- Triangle setup (bounding-box scan + edge function testing)
- Span generation (serpentine scan)
- Scissor clipping (clipLeftRight, clipLowYHighY)
- Y-origin transform (fbzMode bit 17, fbiInit3[31:22])
- Stipple patterns
- Gradient Interpolation
- Color (R, G, B, A) - 12.12 fixed-point
- Depth (Z) - 20.12 fixed-point
- Texture coordinates (S, T, W) - 14.18 / 2.30 fixed-point
- Parameter adjustment for sub-pixel vertices (fbzColorPath bit 26)
- Color Combine Unit (CCU)
- c_other source selection (iterated, texture, color1, LFB)
- c_local source selection (iterated, color0)
- cc_localselect_override (texture alpha bit 7 selects color0)
- zero_other, sub_clocal
- All mselect modes (ZERO, CLOCAL, AOTHER, ALOCAL, TEXTURE_ALPHA, TEXTURE_RGB)
- reverse_blend (factor inversion)
- Add modes (NONE, CLOCAL, ALOCAL)
- Invert output
- Alpha Combine Unit (ACU)
- a_other source selection (iterated, texture, color1, LFB)
- a_local source selection (iterated, color0, iterated_z)
- alpha_zero_other, alpha_sub_clocal
- All alpha mselect modes
- alpha_reverse_blend, alpha_add, alpha_invert_output
- Fog
- W-based fog table lookup
- Iterated fog (alpha/Z based)
- Fog color blending
- Alpha Test
- Comparison functions (never, <, ==, <=, >, !=, >=, always)
- Reference alpha
- Depth Buffer
- Z-buffer read/compare
- Depth function selection
- Z-buffer write
- W-buffer mode
- Depth bias
- Depth source select (iterated Z or W)
- Alpha Blending
- Source blend factors (10 modes)
- Destination blend factors (10 modes)
- Framebuffer read for blending (fork-queue-join BMB pattern)
- Chroma Key
- Color key comparison (post color-combine, matching real hardware)
- Chroma range
- Dithering
- 4x4 ordered dither (86Box ground-truth LUTs)
- 2x2 ordered dither (86Box ground-truth LUTs)
- Framebuffer Write
- 16-bit RGB565 output
- Draw buffer selection
- Depth/alpha planes selection (fbzMode bit 18)
- RGB write mask
- Aux write mask
- Linear Frame Buffer (LFB)
- Direct CPU writes (bypass mode, all write formats)
- Pixel format conversion (RGB565, RGB555, ARGB1555, XRGB8888, ARGB8888, Depth+color, Depth-only)
- Dual-pixel (16-bit formats) and single-pixel (32-bit formats) modes
- RGBA lane swizzle (ARGB, ABGR, RGBA, BGRA)
- Word swap and byte swizzle
- Dithering support
- Pipeline routing option (pixelPipelineEnable=1)
- LFB reads
- Commands
- triangleCMD / ftriangleCMD
- fastfillCMD (screen clear via clip rectangle, color1/zaColor, with dithering)
- nopCMD
- swapbufferCMD (immediate + vsync-synchronized, swapsPending tracking)
- Texture Coordinates
- S/T/W interpolation
- Perspective correction (S/W, T/W division via 257-entry reciprocal LUT)
- LOD (Level of Detail)
- LOD calculation from gradients (max gradient MSB position)
- Mipmap base offset calculation (per-LOD cumulative sizes)
- LOD bias (tLOD bits 17:12)
- LOD clamping (lodmin, lodmax)
- Per-pixel LOD adjustment (perspective-corrected W)
- Aspect ratio / non-square textures (tLOD lodAspect + lodSIsWider)
- Trilinear blending (lod_frac)
- Texture Address
- texBaseAddr register
- Texel address generation (row-major, 8/16-bit stride)
- Clamp and wrap modes (per-axis, textureMode bits 6-7)
- Clamp W (negative W forces S=T=0, textureMode bit 3)
- texBaseAddr_1/2/3_8 (per-LOD base addresses)
- Texture Filtering
- Point sampling (nearest)
- Bilinear filtering (min/mag)
- Texture Formats (decode logic)
- RGB332 (8-bit)
- A8 (8-bit, alpha only)
- I8 (8-bit, intensity)
- AI44 (8-bit, alpha + intensity)
- ARGB8332 (16-bit)
- RGB565 (16-bit)
- ARGB1555 (16-bit)
- ARGB4444 (16-bit)
- AI88 (16-bit, alpha + intensity)
- YIQ422 / AYIQ8422 (NCC compressed)
- P8 / AP88 (palettized)
- Texture Combine
- Texture output to color combine unit
- Multi-texture (TMU chaining)
- NCC table decode
- Palette RAM (256-entry, loaded via NCC table 0 I/Q registers)
- LOD dither
- Data swizzle/swap
- BMB bus adapter (BmbBusInterface)
- 64-entry PCI FIFO with categorized routing (fifoBypass / syncRequired)
- Pipeline drain blocking for sync registers (triangleCMD, swapbufferCMD, etc.)
- Address remapping (fbiInit3 bit 0, external bit 21)
- CPU bus address decode (PCI BAR regions: registers, LFB, texture)
- texBaseAddr write relocation (SST-1 spec 5.53)
- PCI configuration space (initEnable, busSnoop)
- Memory FIFO (off-screen framebuffer extension)
- 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)
# Run tests
scala-cli test .
# Format code
scalafmt
# Compile
scala-cli compile .Run the Glide2x test suite against the Verilator model:
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 dumpScreenshots are saved to output/<test>/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 |
The sim backend builds a 32-bit libglide2x, so DOSBox-X must also be
32-bit to dlopen() it.
# 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/dosboxCommon top-level commands:
make native/helpprints the Linux-hosted and trace command surface.make native/sim/buildbuilds all Linux-hosted Glide test binaries.make native/sim/build/<name>builds one Linux-hosted test binary.make native/sim/run/<name>runs one Linux-hosted test and writes screenshot output underoutput/.make native/trace/run/<name>rebuilds the host Glide runtime with the trace harness and capturestraces/<name>.bin.make native/sim/check/<name>replays an existing trace through the check pipeline.make native/sim/test/<name>captures and checks in one step.make native/sim/check-allreplays every existing trace undertraces/.make dos/helpprints the DOS and Tomb command surface.make dos/sim/buildbuilds all DOS SDK-style test binaries fromemu/glide/glide2x/sst1/glide/tests/Makefile.sdkwat.make dos/sim/build/<name>builds one DOS SDK-style binary, for examplemake dos/sim/build/df00sdk.make dos/sim/run/<name>mountsemu/glide/glide2x/sst1/glide/testsasC:in DOSBox-X and runs<name>.exewith the sim backend.make dos/sim/headless/<name>does the same withDOSBOXX32_HEADLESS=1.make dos/trace/run/<name>runs a DOS guest against the trace-capture Glide runtime and writestraces/dos/<name>.bin.make dos/trace/headless/<name>does the same headlessly.make dos/dosbox ARGS='...'launches DOSBox-X with the sim Glide backend and forwards extra DOSBox-X arguments.make tomb/helpprints 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, andmake tomb/sim/capturerun Tomb Raider against the sim backend.make tomb/sim/traceruns Tomb Raider against the live sim runtime and also dumps a trace totraces/tomb_live/trace.bin.make tomb/sim/trace/checkreplaystraces/tomb_live/trace.binintooutput/tomb/trace_replay_live/.make tomb/trace/runandmake tomb/trace/headlessrun Tomb Raider against the trace runtime and writetraces/tomb/trace.binautomatically.make tomb/trace/checkreplaystraces/tomb/trace.bindirectly intooutput/tomb/trace_replay/without pulling in any stalestate.binfrom an old trace directory.
The hierarchy is intentional:
native/<runtime>/<action>[/<name>]is for Linux-hosted test binaries.dos/<runtime>/<action>[/<name>]is for DOS guest binaries inside DOSBox-X.tomb/<runtime>/<action>is for Tomb Raider convenience flows.de10/<action>is for board-oriented workflows using thede10runtime.
Runtimes are explicit and non-stateful:
simmeans the normal in-process Verilator-backed Glide runtime.tracemeans the trace-capture Glide runtime.de10means the board/MMIO-backed Glide runtime.
In practice:
native/...anddos/...currently exposesimandtracedirectly in the command path.de10/...keeps the runtime implicit in the namespace because everyde10command already targets the board runtime.SIM_INTERFACE=de10is the closest host-side reproduction of the board interface: it still uses thesimruntime, but swaps the Verilated top-level fromCoreSimtoCoreDe10and drives the DE10-style MMIO plus Avalon memory ports from the host harness.
Examples:
make native/sim/run/test00 SIM_INTERFACE=de10
make dos/sim/run/df00sdk SIM_INTERFACE=de10The 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:
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.isoif 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:
/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/helpto print the current assumptions. - Run
make tomb/sim/runormake 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_SRCDOSBOX_TOMB_STAGE_ROOTDOSBOX_TOMB_GAME_DIRDOSBOX_TOMB_ISODOSBOX_TOMB_EXE
Notes:
scripts/run-dosboxx32-glideprefersDOSBOXX32_BINif set.- If
dosbox-xonPATHis already 32-bit, it uses that. - Otherwise it auto-resolves Nix
pkgsi686Linux.dosbox-x. - The script appends
scripts/dosboxx32-glide.conf(enablesglide=true,voodoo_card=false,lfb=full_noaux). - For low-level manual control you can still use
scripts/run-dosboxx32-glidedirectly.
Glide trace files (.bin) capture PCI bus operations for offline replay against both
the RTL simulation and a software reference model:
# 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-allReplay outputs are written to test-output/<trace>/ as <trace>_ref.png, <trace>_sim.png, and <trace>_diff.png.
Trace files are stored in traces/ and compared pixel-by-pixel against a reference model.
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:
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/tombUseful defaults and assumptions:
- Default board target is
fpga@debian-fpga.localunlessDE10_HOSTorDE10_USERoverride it. - Default deployed runtime prefix is
/home/fpga/spinalvoodoounlessDE10_REMOTE_PREFIXoverrides it. make de10/run/dos/<name>uses the deployed launcher on the board and mountsDE10_RUNTIME_DIR(default/home/fpga/de10-cross) asC:.make de10/run/tombexpects a prepared remote Tomb tree atDE10_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.



