A Dune II RTS engine fork with the Tornie Mod integrated — a 16-phase Micropolis-style city simulation, 8th house (HOUSE_REBELS) faction, custom campaign bundle, custom units, and a per-house color tint system.
Status: Active development. Latest release v1.0.426 on main / tornie-beta. Tornie Mod loads via mods/Tornie/data/ and ships its own PAK (Tornie.PAK, 260+ entries).
# Clone
git clone https://github.com/moonbear-dev/dunecity.git
cd dunecity
# Configure + build (Linux)
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
# Run
./build/bin/dunecityThe Tornie Mod is enabled by default at mods/Tornie/. To switch mods (vanilla / dunecity / Tornie), use the in-game Mods menu.
| Component | Status | Notes |
|---|---|---|
| Dune Legacy engine (combat, units, structures) | ✅ Stable | Upstream v0.96 base + 576+ Tornie commits |
| 16-phase Micropolis city simulation | ✅ Integrated | Runs every tick alongside combat |
| 8th house HOUSE_REBELS | ✅ Stable | Dark grey tint from Custom_IBM.PAL |
| Tornie Mod (campaigns, units, sprites) | ✅ 260 PAK entries | 8 house campaigns × 22 scenarios + custom data |
| Per-house color tint (units/structures) | ✅ v1.0.426 | Vanilla v1.0.305 path + Custom_IBM.PAL for REBELS |
| Custom units (FlameTank, EliteSiegeTank, RocketTrike, etc.) | ✅ Loaded | 8-direction palette-indexed strips |
| Discord Rich Presence | ✅ Optional | Auto-shows current mod + version |
| Multiplayer (network + savegame) | ✅ | v1.0.367 multiplayer CustomGamePlayers |
| Save/load (v9820+ format) | ✅ | Backward-compat with v9818 saves |
| Map editor + advanced windtrap | ✅ | Per-house brush icons + pen size preview |
| Mentor portraits (Paul Atreides, Baron, etc.) | ✅ | Custom_IBM.PAL tint for REBELS + Neutral |
| Performance log | ✅ | FPS budget auto-tuning (15000→16000 tokens/cycle) |
Trunk-based development on main:
main= trunk, always deployabletornie-beta= pre-release branch for Tornie Mod builds (parallel CI pipeline)- Single source of truth (rebase, no long-lived branches)
# Make a change + test
git checkout main
# ... edit, cmake --build build, etc ...
# Commit with a descriptive message
git add -A
git commit -m "fix(color): Custom_IBM.PAL dark grey for HOUSE_REBELS"
# Bump version + tag
sed -i 's/DuneCity VERSION 1.0.426/DuneCity VERSION 1.0.427/' CMakeLists.txt
sed -i 's/"version": "1.0.426"/"version": "1.0.427"/' vcpkg.json
sed -i 's/#define VERSION "1.0.426"/#define VERSION "1.0.427"/' include/config.h
bash scripts/bump-version.sh --check # verify all 3 files agree
# Push
git push origin main --force
git tag -a v1.0.427 -m "v1.0.427 - ..."
git push origin v1.0.427 --force
git push origin tornie-beta --force # mirror to Tornie beta branchThe CI workflow (.github/workflows/build.yml) builds Windows ZIPs on every push to main or tornie-beta and uploads to https://dunelegacy.com/.
DuneCity is a fork of Dune Legacy (C++17/SDL2) with the Micropolis city-building simulation ported into the same game loop. The Tornie Mod is layered on top with custom campaigns, units, palettes, and a 8th faction (HOUSE_REBELS).
Game::updateGameState() [runs every tick at ~62.5 Hz]
├── cmdManager.executeCommands()
├── house[i]->update() // AI city-building
├── processObjects() // WindTrap registers power sources
├── citySimulation_->advancePhase() // one of 16 city phases per tick
└── economic victory check
| Phase | What Happens |
|---|---|
| 0 | Increment city time, clear census, reset power flags |
| 1-8 | Map scan — process 1/8 of zones per phase |
| 9 | Census, tax collection, growth valve calculation |
| 10 | Decay rate-of-growth, decay traffic density |
| 11 | Power flood-fill from WindTrap seeds |
| 12 | Pollution, terrain, land value analysis |
| 13 | Crime scan |
| 14 | Population density scan |
| 15 | Fire analysis, Arrakis disasters |
dunecity/
├── src/ # Dune Legacy + Tornie mod engine code
│ ├── FileClasses/
│ │ └── GFXManager.cpp # Per-house remap, Custom_IBM.PAL, palette write
│ ├── Menu/
│ │ ├── CustomGamePlayers.cpp # Color swap dropdown (Original/Teal/Custom 7)
│ │ └── SinglePlayerSkirmishMenu.cpp # 8-house carousel
│ ├── players/
│ │ └── SpectatorPlayer.cpp # 9th house type
│ ├── structures/
│ │ ├── ConstructionYard.cpp # 8th house build logic
│ │ └── AdvancedWindTrap.cpp # Custom super power plant
│ └── Game.cpp # Per-house color swap init, 8th house loading
├── include/
│ ├── globals.h # getHouseSDLColor(house) - REBELS reads Custom_IBM
│ ├── DataTypes.h # NUM_HOUSES=8, PALCOLOR_REBELS=192
│ └── Tile.h # lastAccess[NUM_HOUSES=8] (was NUM_TEAMS=7)
├── data/
│ ├── Custom_IBM.PAL # REBELS dark grey ramp at indices 192-199
│ ├── RREBELS.voc # House-name voice for 8th faction
│ ├── REGION*.INI + scen*.ini # 8 Tornie campaigns + 2 vanilla (mirrored in PAK)
│ ├── HeraldRebels.png # 8th house herald (dark grey)
│ ├── EliteSiegeTank.png # Custom unit (8-dir paletted)
│ ├── FlameTank.png # Custom unit (8-dir paletted)
│ ├── Tornie_AdvancedWindtrap_gfx.png # 2-frame animated in-world sprite
│ └── Tornie_AdvancedWindtrap_gfx_editor.png # 48x48 static editor icon
├── mods/Tornie/ # Active mod (mirrors data/ + custom config)
│ ├── data/ # 38 files mirrored from data/
│ └── campaign/ # REGION*.INI + scen*.ini per house
└── scripts/
└── make-tornie-pak.py # Builds data/Tornie.PAK (260 entries)
The engine reads from runtime palette[] (set at GFX init from Custom_IBM.PAL for indices 192-199). For each non-HARKONNEN house, sprites are remapped at render time via mapSurfaceColorRange(src, PALCOLOR_HARKONNEN, houseToPaletteIndex[house]):
PALCOLOR_HARKONNEN = 144(Harkonnen)PALCOLOR_ATREIDES = 160(Atreides)PALCOLOR_ORDOS = 176(Ordos)PALCOLOR_FREMEN = 192(Fremen, shared with REBELS)PALCOLOR_SARDAUKAR = 208(Sardaukar)PALCOLOR_MERCENARY = 224(Mercenary)PALCOLOR_NEUTRAL = 128(Neutral)
For HOUSE_REBELS, the surface palette at 192-199 is overwritten with customColorRamp[192..199] (the dark grey from Custom_IBM.PAL) so the engine reads the dark grey instead of vanilla Fremen orange.
The canonical app version lives in three source-controlled files, kept in sync by scripts/bump-version.sh:
scripts/bump-version.sh 1.0.427 # set version
scripts/bump-version.sh --check # verify all files agreeTag releases use vX.Y.Z (e.g. v1.0.426). CI verifies that source metadata already matches the tag before building.
- CMake 4.0+
- C++17 compiler (GCC 9+ on Linux, Clang on macOS, MSVC 2019+ on Windows)
- SDL2 + SDL2_mixer + SDL2_ttf + SDL2_gfx (vcpkg handles this)
- Original Dune II PAK files (ATRE.PAK, DUNE.PAK, HARK.PAK, MENTAT.PAK, MERC.PAK, ORDOS.PAK, SCENARIO.PAK, VOC.PAK, INTRO.PAK, FINALE.PAK, ENGLISH.PAK, SOUND.PAK, LEGACY.PAK, GFXHD.PAK, OPENSD2.PAK, INTROVOC.PAK) in
data/
# Install deps (Ubuntu)
sudo apt install cmake g++ libsdl2-dev libsdl2-mixer-dev libsdl2-ttf-dev \
libsdl2-gfx-dev libcurl4-openssl-dev
# Configure + build
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)brew install cmake sdl2 sdl2_mixer sdl2_ttf sdl2_gfx
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(sysctl -n hw.ncpu)
open build/bin/dunecity.appcmake -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release -j
build\bin\Release\dunecity.exe# Linux
./build/bin/dunecity
# macOS
open build/bin/dunecity.app
# Windows
build\bin\Release\dunecity.exeThe first time you run, the game seeds mods at ~/.local/share/DuneCity/mods/ (Linux) or %APPDATA%\DuneCity\mods\ (Windows). The Tornie Mod will be detected from mods/Tornie/ in the install directory.
This project is developed by moonbear (autonomous agent) and reviewed by syntox (principal). The Tornie Mod is steered by Tornie (Tornie Panther) for visual / asset / gameplay balance, and Quix is blocked at the gateway.
Rules:
- Trunk-based — work on
mainor short-lived branches - One authority per change — accept instructions from any of: Tornie (mods), syntox (release/git), or ggtothemax (ops/website)
- Small changes — prefer small compileable changes over broad refactors
- Versioned releases — every user-visible change bumps the version and tags a release
- Coordinate on hot files —
GFXManager.cpp,Game.cpp,CustomGamePlayers.cppare the most-edited
| Path | What It Is |
|---|---|
src/FileClasses/GFXManager.cpp |
Per-house remap, Custom_IBM.PAL, palette write, sprite load |
include/globals.h |
getHouseSDLColor(house) — REBELS reads Custom_IBM.PAL |
include/DataTypes.h |
NUM_HOUSES=8, PALCOLOR_REBELS=192, houseToPaletteIndex[] |
include/Tile.h |
lastAccess[NUM_HOUSES] (was NUM_TEAMS=7 before v1.0.360) |
src/Menu/CustomGamePlayers.cpp |
12-entry color swap dropdown (Original + Teal + 4 custom + 7 vanilla) |
src/Menu/SinglePlayerSkirmishMenu.cpp |
8-house carousel (9 entries, scroll max 6) |
src/players/SpectatorPlayer.cpp |
9th house type for non-playing slots |
src/Game.cpp |
Per-house color swap init at game start, save/load |
data/Custom_IBM.PAL |
REBELS dark grey ramp at 192-199 |
data/Tornie.PAK |
260+ entries: campaigns, units, sprites, voices |
scripts/make-tornie-pak.py |
Builds data/Tornie.PAK from data/ + mods/Tornie/data/ |
- v1.0.426 — HOUSE_REBELS dark grey written to surface palette (fixes orange tint)
- v1.0.425 — Removed v1.0.413 structure remap (diagnostic, restored v1.0.305 lazy remap)
- v1.0.424 — Suppress "UI Graphic not loaded" log spam (log once per ID)
- v1.0.423 — Rollback to v1.0.305 vanilla remap (regression fix)
- v1.0.418 — Multi-color ghost fix on units (write source + dest slots to surface palette)
- v1.0.415 — Advanced windtrap editor icon = in-map preview, Elite Siege Tank path fix
- v1.0.414 — Reactivated 7 vanilla house color swap slots in CustomGamePlayers
- v1.0.413 — Per-house structure sprite remap restored
- v1.0.411 — Per-house remap-on-demand restored (units + buildings)
- v1.0.408 — Tearnie campaign rewrite (8 houses + 2 vanilla × 22 scenarios)
- v1.0.405 — Crash fix for GFX init recursion
- v1.0.400 — Custom_IBM.PAL no longer applied as default
- v1.0.394 — 4 new custom colors (Fushia/Apple Green/Dark Purple/Light Pink)
- v1.0.358 — scenr001-022 Mercenary→Rebels re-routing (root cause of Rebels construction)
- Dune Legacy by the Dune Legacy team — base engine
- Micropolis (SimCity open-source port) by the SimHacker team — city simulation reference
- Tornie (Tornie Panther) — mod author, art direction, asset uploads
- moonbear — autonomous AI agent, port and integration
- syntox — principal, release coordination
- Original Westwood Studios — Dune II (1992)