A level editor for Diablo II that allows creation and modification of game maps (.ds1 files). Built with Allegro 5 for GPU-accelerated rendering at 60+ FPS. Runs on Windows, Linux, and macOS.
DS1Edit is a continuation of Paul Siramy's win_ds1edit, the Diablo II community's DS1 editor since 2002, ported from Allegro 4 to Allegro 5 and extended. See Acknowledgments and NOTICE.
Download the latest release — Windows, Linux, and macOS builds are published for every tag.
| Platform | Package | Runtime dependency |
|---|---|---|
| Windows (x86) | ds1edit-<ver>-windows-x86.zip |
none — Allegro 5 DLLs are bundled |
| Linux (x86_64) | ds1edit-<ver>-linux-x86_64.tar.gz |
system Allegro 5 (see below) |
| macOS (arm64) | ds1edit-<ver>-macos-arm64.tar.gz |
brew install allegro |
Unpack anywhere and run ds1edit (ds1edit.exe on Windows). There is no installer.
Linux needs Allegro 5 from your package manager:
# Debian / Ubuntu
sudo apt install liballegro5.2 liballegro-image5.2 liballegro-ttf5.2 liballegro-dialog5.2
# Fedora
sudo dnf install allegro5 allegro5-addon-image allegro5-addon-ttfmacOS builds are not code-signed, so Gatekeeper will refuse the first launch. Either right-click the binary and choose Open, or clear the quarantine flag:
xattr -dr com.apple.quarantine ds1editYou need your own copy of Diablo II (Classic or LoD) — the editor reads tiles and sprites straight out of your MPQs and ships no game assets.
# Prerequisites: Visual Studio 2019+, vcpkg with Allegro 5
vcpkg install allegro5:x86-windows
# Build
cmake --preset default
cmake --build --preset release
# Configure (first run)
cd bin
copy Ds1edit.ini.sample Ds1edit.ini
# Edit Ds1edit.ini to set your Diablo II MPQ paths
# Run
bin\ds1edit.exe assets\act5_town.ini- DS1 Map Editing - Create and modify Diablo II level files for Acts 1-5
- GPU-Accelerated Rendering - VIDEO bitmap pipeline with ~1ms render time per frame
- D2 Blend Modes - Correct additive, multiply, and screen blending (reverse-engineered from D2CMP.dll)
- Object Animation - DCC/DC6 sprite rendering with shadow projection
- Multi-Zoom - 7 zoom levels from 1:1 to 1:16
- Reads your MPQs directly - maps, tiles, sprites, palettes and data tables, with a mod-directory overlay; nothing has to be extracted first
- Headless Mode - Command-line screenshot rendering for CI/testing
- Performance Profiling - Optional per-frame and per-section timing (
-DDS1EDIT_PERF_LOG=ON)
# Windows -- vcpkg + Visual Studio
cmake --preset default # Configure (uses vcpkg toolchain)
cmake --build --preset dev # Dev build (optimized + debug symbols)
cmake --build --preset release # Release build (full optimization + LTCG)
# Linux -- Ninja + system Allegro 5
sudo apt install build-essential ninja-build cmake pkg-config zlib1g-dev liballegro5-dev liballegro-image5-dev liballegro-ttf5-dev liballegro-dialog5-dev
cmake --preset linux && cmake --build --preset linux
# macOS -- Ninja + Homebrew Allegro 5
brew install allegro ninja pkg-config
cmake --preset macos && cmake --build --preset macos| Preset | Config | Use |
|---|---|---|
dev |
RelWithDebInfo | Day-to-day development, F5 debugging |
release |
Release | Distribution, maximum performance |
debug |
Debug | Deep debugging (slower rendering) |
- F5 builds and launches with the
devpreset - Launch dropdown has configs for every Act/area
- "Run DS1Edit" configs launch without debugger for full speed
ctest --preset default # Unit tests (4 tests, <0.2s)
python scripts/run_golden_tests.py --core # Golden screenshot teststest_palette- Palette color conversion and matchingtest_rgba_cache- Tile cache create/rebuild/converttest_dt1_decode- DT1 sub-tile pixel decodertest_placeholder- Test infrastructure validation
Renders maps in headless mode and compares against reference PNGs in test/golden/.
Run ds1edit help for the full verb list. The area-browser verbs:
ds1edit list-areas # every area, grouped by Act
ds1edit list-files [filter] # DS1 files with their LvlType / Def
ds1edit audit-lvltypes # LvlTypes rows whose name disagrees with its Act
ds1edit <file.ds1> <ID> <DEF> --headless out.png
ds1edit --area "Act 1 - Town" --headless out.pngThe legacy --list-areas / --list-files / --audit-lvltypes spellings still work.
audit-lvltypes prints every mismatch between a LvlTypes.txt row's Act X - ... name prefix and its authoritative Act column.
LvlTypes.txt's Act column is the source of truth, not the row name and not the
DS1. The chain is:
LvlPrest.txt (Def) -> Levels.txt (LevelType) -> LvlTypes.txt (Act + File 1..32)
| |
palette the DT1 set
palette_resolve_act() takes that Act when it is 1-5, falls back to the DS1's own
act, and defaults to 1. The palette index is act - 1, selecting Act1..Act5/Pal.pl2
straight from your MPQs.
Maps that no table names -- the maze and room fragments the game assembles procedurally -- are grouped per Act as Unlisted, with their tileset inferred from the folder (its listed neighbours first, then a group whose name matches the folder).
Copy Ds1edit.ini.sample to Ds1edit.ini and point it at your Diablo II install:
d2_install = C:\Diablo2That one line fills every MPQ slot. Nothing needs extracting -- maps, tiles,
sprites, palettes and the data tables are all read straight out of the archives, and
the whole map list appears in the browser. Set mod_dir and your mod's loose files
take priority over the base game without repacking anything.
Individual archives can still be named explicitly if you need to override the auto-detected set:
d2char = C:\Diablo2\d2char.mpq
d2data = C:\Diablo2\d2data.mpq
d2exp = C:\Diablo2\d2exp.mpq
patch_d2 = C:\Diablo2\patch_d2.mpqSee the sample file for all available settings (resolution, scroll speed, gamma, etc.).
The window opens but the map area is black. The status bar and the mouse cursor draw, the frame rate looks normal, and nothing appears in the logs.
This is the graphics driver, and switching it fixes it. Which way you switch depends on how you got the editor.
Allegro picks a backend per platform, and either choice can misbehave on a
given machine: Direct3D has been seen dropping to 0 fps, and OpenGL has been
seen rendering an all-black map exactly as described. An allegro5.cfg next
to the executable overrides the choice:
[graphics]
driver=opengl- From a release package, there is no
allegro5.cfgand you are on the platform default. Create the file next tods1editwithdriver=opengl, ordriver=direct3don Windows, and try the other one. - From a source build, the repository ships an
allegro5.cfgthat pins OpenGL, and CMake copies it next to the executable. Rename or delete it to fall back to the platform default.
The editor prints the driver it ended up on at startup, so check stderr.txt
(or the console) for:
display: 2560x1440, OpenGL driver
display: renderer "NVIDIA GeForce RTX 5060 Ti/PCIe/SSE2", vendor "NVIDIA Corporation"
The editor draws correctly but at well under one frame per second. The map
is right, the mouse works, nothing is in the logs except a very small number in
the [perf] block.
That is almost always the GPU not being used at all, and the renderer line
above says so. Two cases:
renderer "GDI Generic"(orllvmpipe/swraston Linux) is a software rasterizer, not a GPU. The editor now warns about this by name. It means no vendor driver is installed, or the OpenGL context could not reach the card -- a remote desktop session is the usual reason. Install the graphics vendor's driver and run on the machine's own console.- The renderer names an integrated chip (
Intel(R) UHD Graphics, say) on a laptop that also has a discrete card. The executable asks for the discrete GPU on both NVIDIA and AMD, but a per-application setting can override that: check NVIDIA Control Panel → Manage 3D Settings → Program Settings (or the Windows Graphics settings page) and setds1edit.exeto the high-performance GPU.
The [perf] block splits render from present, which narrows it further: time
in render is compositing the map, time in present is al_flip_display.
See docs/structure.md for detailed layout.
Key directories:
src/- C source code organized intocore/,render/,editor/,ui/,mpq/data/,assets/- Runtime data (copied tobin/at build time);assets/ui/holds the editor's interface imagestest/- Unit tests (Unity framework)scripts/- Golden test scripts (Python)bin/- Build output directory (gitignored)
7-pass compositing pipeline in src/render/preview.c, all GPU-accelerated:
- Base terrain (floors, lower walls, tile shadows)
- Object shadows (tinted black silhouettes)
- Objects behind walls
- Upper walls + objects in front
- Roofs
- Special tiles
- Walkable info overlay
- Game tick: 25 Hz (animation frame advancement)
- Display: Vsync rate (60-165 Hz depending on monitor)
- Render work: ~1ms per frame (GPU-bound, not CPU-bound)
COF layer transparency (trans_b field) mapped to Allegro 5 blender states:
| trans_b | Mode | Formula |
|---|---|---|
| 0 | 75% transparent | Alpha 0.25 |
| 1 | 50% transparent | Alpha 0.50 |
| 2 | 25% transparent | Alpha 0.75 |
| 3 | Additive | min(src + dst, 255) |
| 4 | Multiply | (src * dst) / 255 |
| 6 | Screen | src + dst - src*dst/255 |
- Fork the repository
- Create a feature branch
- Make changes and add tests
- Run
ctest --preset defaultto verify - Submit a pull request
MIT License - Copyright (c) 2025-2026 Ben Ethington, covering the modifications and additions made in this project.
The original win_ds1edit code this project grew out of was written by Paul
Siramy and released publicly with every build from 2002 to 2011, without a
formal license text; it is used here with attribution, not relicensed. The MPQ
reader in src/mpq/ is Tom Amigo's Stormless MPQ sample code. NOTICE
has the full attribution and file-by-file provenance, and ships in every release
package next to LICENSE.
This project stands entirely on Paul Siramy's original win_ds1edit — the DS1
map editor that the Diablo II modding community has relied on since 2002. Paul
wrote the DS1/DT1/DCC/DC6 format handling, the WYSIWYG editing model, and the
25,000+ lines this codebase grew out of, and released the source publicly
alongside every build. Everything here is a continuation of that work, not a
replacement for it. Every source file that descends from win_ds1edit carries
a header saying so; NOTICE lists them all.
- Original DS1Edit / win_ds1edit by Paul Siramy — download page · documentation
- MPQ reader (
src/mpq/) — Tom Amigo's Stormless MPQ sample code (2000), as adapted by Paul forwin_ds1edit - GUI Loader by Mark Nevill ('DarthDevilous')
- The Phrozen Keep community, for two decades of file-format documentation
- Built with the Allegro 5 game programming library
- D2 blend mode formulas reverse-engineered from D2CMP.dll via Ghidra