Dungeon Master Tools — extract data from Dungeon Master / Chaos Strikes Back files (GRAPHICS.DAT, DUNGEON.DAT)
Project description
Dungeon Master Tools
Dungeon Master Tools is a collection of Tools in Python for the Amiga/PC/Atari ST Game,
packaged as the importable dmcsb package (published on PyPI as dmcsb — pip install dmcsb):
dmcsb.dungeon(DungeonFile) - loads and extracts the data in DUNGEON.DAT (Big Endian only for now)dmcsb.graphics(GraphicsFile) - library for GRAPHICS.DAT handling
Installation
pip install dmcsb # optional: "dmcsb[pil]" enables GraphicsFile.to_pil()
or, from a source checkout, pip install -e . (or just run from the repo root —
the package is importable without installing).
Command line
Installing puts a dmcsb command on your PATH (equivalently python3 -m dmcsb):
dmcsb dump GRAPHICS.DAT [out_dir] # -> PNG/WAV/TXT/.bin + an HTML contact sheet
dmcsb dungeon DUNGEON.DAT --level 1 # print one dungeon level (map, things, champions)
dmcsb uncompress DUNGEON.DAT [out.dat] # write a decompressed copy (no parsing)
dmcsb dump also takes --map / --palettes / --zones to override the bundled
tables. The same three operations are available as standalone scripts in examples/
(thin wrappers over the library, runnable from a source checkout).
After loading a DungeonFile you can access all data from the object:
hdr-> header dictmaps[]/mapsinfo[str(level)]-> map descriptors (in file order / keyed by Level)thinglist[]-> 16 entries in storage order (Nonefor unused types)things[name]-> decoded list by type:"Door","Creature","Weapon","Sensor", ... (whole dungeon)things_on_level(level)-> things located on one level, grouped by typelocated_things(level)-> things on a level with their map(x, y)+ sub-square cell (dirN/E/S/W)item_name(category, type)-> human item name (Weapon/Armour/Potion/Junk/Container/Scroll)text(textstring)/texts()-> decoded message strings (signs, ...)scroll_text(scroll)-> the text a scroll points at (via its TextStringThingIndex)champions()-> all champion sheets in the dungeon (name, title, gender, stats, skills);champions_on_level(level)-> only those whose sheet sits on that level (e.g. the Hall of Champions), withx,y;champion(offset)decodes onetile_data-> raw tile bytes;tile_grid(level)-> 2-D tile arraytext_data-> raw encoded dungeon textchksum-> trailing checksum word, orNoneif the file has none
for more info see: http://dmweb.free.fr/?q=node/217
The library is silent (no prints); load from a path, bytes, or an open file. Little-endian
(PC) files are not supported yet and raise NotImplementedError.
from dmcsb import open_dungeon
d = open_dungeon("DUNGEON.DAT") # or open_dungeon(data=raw_bytes)
print(d.hdr['OrnamentRandomSeed'])
print(d.mapsinfo['1']['Difficulty'])
for door in d.things['Door']: # every door in the dungeon
print(door['Type'], door['OrnamentOrdinal'])
for name, items in d.things_on_level(1).items(): # only level 1, grouped by type
print(name, len(items))
for i, visible, msg in d.texts(): # decoded scroll/sign messages
print(i, repr(msg))
for c in d.champions(): # initial party champions
print(c['name'], c['title'], c['Health'], c['Strength'])
Text uses DM's 5-bit packing (3 codes per 16-bit word). The decoder handles
letters, spaces, ., line breaks and the standard DM/CSB escape tables (so e.g.
THE / YOU expand inside titles and messages); pass an escape= callback to
override them. It targets the normal/"new font" text used by the Amiga versions.
Champion statistics/skills are stored as hex nibbles and decoded to integers
(Stamina is kept as the raw value, i.e. 10x the number shown in-game).
When you run the demo, it prints one dungeon level:
python3 examples/demo_dungeon.py [level] [DUNGEON.DAT]
level defaults to 1; the optional second argument is the path to the file
(defaults to DUNGEON.DAT). For example python3 examples/demo_dungeon.py 5
shows Level 5. With no arguments, Level 1 is shown:
Map at Level 1 ----------------
RawMapDataByteOffset: 376
OffsetMapX: 0, OffsetMapY: 14
Width: 31, Height: 31, Level: 1
RandomFloorOrnamentCount: 2
FloorOrnamentCount: 3
RandomWallOrnamentCount: 3
WallOrnamentCount: 12
Difficulty: 1
CreatureTypeCount: 2
DoorOrnamentCount: 3
DoorSet1: 1, DoorSet0: 0
WallSet: 0, FloorSet: 0
Creatures/Wall/Floor/Doors used ----------------
Creature: 6, 10,
WallOrnate: 33, 4, 35, 51, 15, 1, 49, 38, 46, 45, 44, 5,
FloorOrnate: 2, 8, 1,
DoorDeco: 4, 8, 3,
MapData ----------------
1 4 1 1 1 1 1 1 1 1 4 1 1 1 1 1 1 1 1 4 1 1 1
1 3 4 1 1 1 1 1 1 4 4 1 1 1 1 1 1 1 5
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
4 1 1 1 1 1 1 1 1 1 1 1 1 5
1 1 1 1 1 1 1 1 1 5 4 1 1 4 1 1
1 1 1 4 1 4 1 1 1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 1 4
1 1 1 4 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 1
1 1 1 1 4 1 1 1 1 1 1 1 1 1
1 1 1 4 1 1 4 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 4 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1
1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 4 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 4 1 1 1 1 1 1 1 5
1 1 1 1 1 1 1 1 1 1 1 5 1 1 1 4 1 1 1 1 1 1 1
1 4 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 3 1 1 1 1 1 1 1 4 1 1 1 1
1 1 1 1 1 4 1 1 1 1 1 1 1 4 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 6 1 1 1 1 1 1 5 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
The demo also prints every Thing on the level (grouped by type) after the map.
To just decompress a compressed dungeon to a raw file (no parsing):
python3 examples/uncompress_dungeon.py DUNGEON.DAT [output.dat]
The output defaults to <input>.uncompressed.
dmcsb package — GRAPHICS.DAT library
The graphics handling lives in the installable dmcsb package. It loads the
Amiga 3.x GRAPHICS.DAT into memory and decodes IMG1 images, the FNT1 font, SND2
sounds, TXT2 text and the LAY1 screen layout. The data tables (image map, palettes,
zone names) are bundled inside the package and applied automatically — you can
override them by passing your own paths.
Use it in your own project (after pip install dmcsb — see Installation):
from dmcsb import open_graphics
g = open_graphics("GRAPHICS.DAT") # bundled map + palettes auto-applied
# overrides: open_graphics("GRAPHICS.DAT", map="my_map.txt", palettes="my_pal.txt")
# from memory: open_graphics(data=open("GRAPHICS.DAT","rb").read())
len(g) # number of items
list(g) # [(index, type_name), ...]
g.info(i) # {type, name, palette, sizes, compressed}
g.image(i) # IMG1/FNT1 -> (w, h, rgb_bytes)
g.image_indexed(i) # -> (w, h, palette_indices) for your own coloring
g.to_pil(i) # -> PIL.Image (needs Pillow)
g.font() # finds FNT1 -> (w, h, rgb_bytes)
g.sound(i) # SND2 -> signed 8-bit PCM
g.text(i) # TXT2 -> [str]
g.layout() # LAY1 -> {'signature','ranges','records'} (relative coords)
g.first_of_type("LAY1") / g.indices_of_type("SND")
To dump everything into a folder of PNG/WAV/TXT plus an HTML contact sheet, see the example app (it consumes the library):
python3 examples/dump_graphics.py GRAPHICS.DAT gfx/
# optional overrides: ... gfx/ graphics_map.txt palettes.txt zones.txt
Many Thanks to ChristopheF & Sphenx
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dmcsb-0.1.0.tar.gz.
File metadata
- Download URL: dmcsb-0.1.0.tar.gz
- Upload date:
- Size: 55.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5c2836023955888808fef9249d7a877d20b3dda360be6297030057813a56bc3
|
|
| MD5 |
23008cf964a1f58bcacbaf834ea61a1f
|
|
| BLAKE2b-256 |
443addbc325017d1ad1f2a6e807b6cc966c332376b6a3925716a068fd17730a0
|
File details
Details for the file dmcsb-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dmcsb-0.1.0-py3-none-any.whl
- Upload date:
- Size: 47.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
323a4858b27895800565b4a3ceeef520ab2c793f371b6aa1c094909d10e15e39
|
|
| MD5 |
44011162b4745dc52995eea0f9d45b2e
|
|
| BLAKE2b-256 |
97ce73b304b3b6b576ec0b2497b9ecc8cd26464614c540aaf1dee2c75e26f75f
|