CL-Dwaddle
CL-Dwaddle (or just Dwaddle) is both a library and command line program for manipulating Doom WAD files (and a few other things). It is written entirely in Common Lisp.
The library focuses primarily on stricter compliance to specifications, with a secondary focus of not being too slow. This is especially true for the UDMF-related functionality. It's meant to offer support for most mapping- and wad-related data structures through CLOS classes and generic functions.
The command line program isn't like most other Doom-related tools. Instead, it focuses on features that I didn't find in other tools, yet realized I still needed or wanted. The result is a set of "modes" that the command line program can run in.
How do I get set up?
Dwaddle is designed to work only with SBCL.
Most of the dependencies can be fetched with Quicklisp (though this hasn't been tested). However, there are a few that you will have to grab manually:
- cl-sdm: A utility library of mine that provides some extra batteries to Common Lisp. Basically my own personal standard lib.
Once you have the dependencies:
- Clone the repository locally where ASDF can find it.
- Use ASDF to load the system inside of your Lisp implementation (e.g.,
(asdf:load-system :dwaddle)
)
Building the command-line program
Just run build.rb
from the root Dwaddle directory - you can use --help
to see some options. The resulting
binaries will be in a new bin/
directory. Note that this has only been tested in Linux.
Development Info
Dwaddle is divided up into a few packages:
:dwaddle
: The core package that contains most of the code. Nickname is:dwaddle
.:dwaddle.maps
: The parsers for various level formats all live here. Nickname is:dwaddle-maps
.:dwaddle.cli
: The command line program lives in its own package. Each mode also gets its own package, such as:dwaddle.cli.levelimage
.
Map parsing is intended to generate a dwaddle:level
instance. This class, as well as the related classes
(dwaddle:vertex
, dwaddle:linedef
, dwaddle:sidedef
, dwaddle:sector
, dwaddle:thing
), form the superset of
all other map formats. This is currently a one-way street, though I plan to make it two-way eventually. The
dwaddle:level
class also holds references to two additional collections: dwaddle:level-data
and
dwaddle:gl-nodes-data
. These, when present, contain the rest of the parsed map data (dwaddle:node
,
dwaddle:seg
, dwaddle:gl-subsector
, etc.). Nearly all level-related functions expect to operate on these
classes.
On the graphics side, the dwaddle:dwaddle-image
class is used as an abstraction layer over whatever library I
decide to use this week. Its related methods provide some basic image operations. This class is used to represent
a final, composited image that can be written to PNG or JPEG or whatever. It does not represent the original
graphic data loaded from wads directly. Palette information is stored in a dwaddle:palette
, though it's only
used when writing a paletted image, or working with the original data directly.
The original data gets loaded into dwaddle:map-texture
, dwaddle:doom-picture
, and dwadle:flat
instances.
There's also an abstraction of the PNAMES and TEXTUREx lumps, and convenience methods for loading these into a set
of dwaddle:dwaddle-image
s.
All conditions that are intended to be catchable in the library derive from dwaddle:dwaddle-error
. This is also
the name of a macro that is used to conveniently construct them. Messages for the conditions can be grabbed using
dwaddle:error-text
. Conditions that are not ancestors of dwaddle:dwaddle-error
represent programming defects.
Logging
The library only uses rlog:vlog
and rlog:dlog
since, except for these purposes, the library should be quiet.
Style info
I use a slightly unorthodox style for my code. Aside from these differences, please use normal Lisp formatting.
- Keep lines 118 characters or shorter. Obviously sometimes you can't, but please try. Use 115 characters for Markdown files, though.
- I mark types using the form
T/....
. For example,T/SOME-NEAT-TYPE
. For predicates on these, useSOME-NEAT-TYPE-P
. - No tabs. Only spaces.