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-images.

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, use SOME-NEAT-TYPE-P.
  • No tabs. Only spaces.