No description
  • Zig 78.8%
  • Lua 13.8%
  • GLSL 4%
  • Python 1.7%
  • PowerShell 1.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
retro KKJ 3280644649 Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer
Port of beetle-engine to Raspberry Pi 4 Model B (VideoCore VI, Mesa v3dv,
labwc). Verified: selftest (90 frames, mesh + cutout foliage + text),
Euro City boots and runs, --benchmark: 35 fps avg / 21 worst-second at
480x270 internal res with 341 draws.

- Platform layer: src/win_linux.zig (from the steam-deck port), X11/XCB
  window + input, VK-code key mapping unchanged for Lua scripts
- WSI: VK_KHR_xcb_surface via vkGetInstanceProcAddr; present mode queried
  (FIFO default, MAILBOX for benchmarks); depth format queried D32/D16
- Device pick prefers non-CPU Vulkan devices (V3D over llvmpipe)
- CPU probe: AT_HWCAP (NEON/AES/SHA2/CRC32), board name from device tree
- Audio: miniaudio ALSA backend with vendored alsa headers (no dev pkgs)
- Build: Linux-only, ReleaseFast default, system libs via third_party/linux
  symlinks, UPX/dist step dropped; --script <path> override for benchmarks
- Dropped: blender/, art-direction/, districts/ authoring trees and
  Windows-only tooling (stay in beetle-engine)
2026-09-15 20:12:48 +02:00
.pi/tasks mv: fix van orientation (nose leads) and road-follow (glTF axis mirror) 2026-09-15 13:28:25 +02:00
assets forest: 2000 trees + 50 giants, denser warped terrain UVs 2026-09-13 20:04:54 +02:00
docs Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00
game Euro City defaults: rain off, fog 40 m (tests updated) 2026-09-15 14:13:36 +02:00
games Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00
src Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00
third_party Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00
tools Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00
.gitignore chore: ignore probe artifacts 2026-09-15 13:47:14 +02:00
agent.md Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00
BLENDER.md rigged companion pigeon: 240-tri walk/fly model generated in Blender, clips wired to the flight blend 2026-09-11 17:41:27 +02:00
build.zig Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00
build.zig.zon phase 0: zig 0.16.0 toolchain, skeleton, cpuid smoke check 2026-09-07 16:44:43 +02:00
PLAN.md MV: denser terrain UVs, LOD0 everywhere (setLodDistance), tree cutout fix, more trees 2026-09-15 13:59:50 +02:00
README.md Raspberry Pi 4 port: aarch64-linux, Vulkan 1.3 (v3dv), X11/XCB platform layer 2026-09-15 20:12:48 +02:00

Raspberry Engine

beetle-engine ported to Raspberry Pi 4 Model B (aarch64-linux, VideoCore VI). Same engine, same games, same Lua API — the whole PS1-style renderer survives, including the 480×270 internal-res post pipeline, CSM sun shadows, rig animation, streamed props, rain, time-of-day and the music-FFT games.

┌───────────────────────────────────────────┐
│  Raspberry Pi 4 Model B Rev 1.1           │
│  Cortex-A72 ×4 · 4 GB · VideoCore VI      │
│  Vulkan 1.3 (Mesa v3dv, V3D 4.2)          │
│  Raspberry Pi OS / labwc (Wayland)        │
└───────────────────────────────────────────┘

Status

Ported and running. Selftest presents 90 frames (mesh + cutout foliage + font + shadows, 8.8 MB VRAM); Euro City boots and runs; --benchmark works.

The machine vs the beetle

BEETLE /MIII (original) Pi 4 (this port)
CPU Celeron G3900, 2×2.8 GHz, SSE4.2 Cortex-A72, 4×1.8 GHz, NEON
GPU Quadro K620 (Maxwell, 2 GB DDR3, ~29 GB/s) VideoCore VI (shared RAM, ~4–8 GB/s effective)
API Vulkan 1.3 (NVIDIA) Vulkan 1.3 (Mesa v3dv, conformant)
OS Windows 10 IoT Raspberry Pi OS / labwc

The engine's design rules hold: two threads, fixed low-res scene target, instanced draws, batched uploads. V3D is a tiled GPU — the engine's single 480×270 render target and small uniform/push payloads suit it well. Everything is UMA here: "VRAM" is ordinary RAM, so vram_bytes is a budget metric, not a separate heap.

Building

Requires Zig 0.16.0 on PATH (aarch64-linux build). No other toolchain, no dev packages — system libraries are linked through symlinks in third_party/linux/ (libvulkan, libasound; recreate with ln -s if the sonames differ).

zig build            # ReleaseFast by default
zig build run        # launcher (games menu)
zig build test       # unit + Lua harness tests
./zig-out/bin/engine --selftest

Optional: zig build shaders regenerates the committed .spv files from GLSL (needs glslang; the committed SPIR-V builds fine without it).

Running

./zig-out/bin/engine                       # launcher
./zig-out/bin/engine --script games/eurocity/main.lua   # Euro City directly
./zig-out/bin/engine --script games/eurocity/main.lua --benchmark

--benchmark (with a game script): 2 s warmup, then 15 s flying a fixed line through the city, reporting avg fps, worst second, draws and tris.

Audio: miniaudio's ALSA backend with vendored headers (third_party/alsa/, LGPL headers from the freedesktop SDK — see its README), so sound works without installing alsa-lib dev files. ALSA reaches PipeWire via pipewire-alsa.

What was ported (differences from beetle-engine)

  • Platform layer: src/win.zig (Win32) → src/win_linux.zig — X11/XCB window + input, keys mapped to the same VK codes so Lua scripts are unchanged. Taken from the beetle-engine steam-deck branch (XWayland under labwc runs it natively). F11 fullscreen preserved (EWMH).
  • Vulkan WSI: VK_KHR_xcb_surface, surface created through vkGetInstanceProcAddr (the loader's export stub is unreliable); present mode is queried — FIFO by default, MAILBOX only when the driver lists it.
  • Device pick: prefers any non-CPU Vulkan device (V3D over llvmpipe); no NVIDIA vendor check. Depth format queried (D32 with D16 fallback).
  • CPU probe: cpuid/SSE bits → AT_HWCAP (NEON/AES/SHA2/CRC32); board name from the device tree.
  • FS/time: raw libc (open/read/clock_gettime//proc/self/exe) — same reason the Win32 impl skipped std churn.
  • Audio: vendored ALSA headers + -lasound; Pulse/JACK disabled.
  • Build: Linux-only; ReleaseFast by default (the beetle build shipped ReleaseSafe); no UPX step. Everything else (C deps, shaders, Lua, assets, tests) is unchanged.

Not carried over: the blender/, districts/ and art-direction/ authoring trees live in beetle-engine; tools/*.ps1 and third_party/upx are Windows tooling.

Performance notes (Pi 4)

  • The 480×270 internal res is the single biggest win on VideoCore — keep it.
  • Governor: the default ondemand clocks down between frames. For measurements or max fps: echo performance | sudo tee /sys/devices/system/cpu/cpufreq/policy0/scaling_governor.
  • --benchmark runs uncapped (MAILBOX) when v3dv offers it; FIFO is the vsync-locked default.
  • v3dv is a Vulkan 1.3 conformant driver; D32 depth and the D16 CSM array are both supported natively.