Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Cracking into Doom (1993) WAD Files

From a short talk I did about a hobby project - figuring out Doom's WAD format using a hex-editor. Originally just to play the music files, I got carried away and extracted all the data, rebuild all the images and audio, and rendered the maps in OpenGL, which required some triangulation tricks. Some tidbits of historical interest were discovered.

  • Login to see the comments

Cracking into Doom (1993) WAD Files

  1. 1. 
 .WAD files Anton Gerdelan
  2. 2. making our own doom WADs (maps/levels etc) in 1994-5 a port of DEU from
  3. 3. Here is all the data! - binary file, custom layout - Id released specs to help modders build tools ~1994 (I went in raw though) - IWAD and PWAD - combines all game data - parts of levels; { walls, floors, monsters… } - sound effects data (proprietary format) - music (proprietary format) - colour palettes, images for maps, enemies, panels… - images with transparent bits have custom format
  4. 4. tools - hexedit - C - fread() - fwrite() - fseek() - valgrind - Audacity - OpenGL - DosBox
  5. 5. binary sleuthing - figure out file structure - search for strings - determine directory structure - match hex-format address with values - h/w arch of 1993 machines - trial and error e.g. directory started at
 ~ 00 BC C5 00
 this 4-byte group says
 “C4 C5 BC 00”
  6. 6. printf() the directory - Directory entries in block at end of file: - entry string (good hint) - entry size in bytes - entry offset from file start - use fseek() - I was after the music but couldn’t resist - “VERTEX” “LINEDEF” “SECTOR” …
  7. 7. LINEDEF ~walls references 2 VERTEXES references 1-2 SIDEDEFS
 find height in SECTORS VERTEX
 has 2 (x,y) integer values SECTOR
 ~floor/ceiling bounded by SIDEDEFS
 not tessellated
 not always convex
 have holes
  8. 8. Walls and Floors - Create a struct for each type of map part and
 put them in arrays to do quick line->height etc. - Walls - just extrude them up? - lower lip - mid (sometimes a gap) - upper lip - Floors - tessellation algorithm - I used “Ear Clipping”
 extended for holes
  9. 9. Ear-Clipping Tessellation - David Eberly’s white paper is great Documentation/ TriangulationByEarClipping.pdf
 - breaks a simple polygon into triangles - single region bounded by loop of edges and verts
 - a group of 3 consecutive verts is reflex (angle > pi) or convex (angle < pi)
 - convex triplet = a polygon ear
 - but not if another vert is inside that triangle
 - and final line is fully inside poly
 - can recurse clipping until 3 vertices remain
 O(n^3) … but can improve on this The Two Ears Theorem A polygon of >3 sides always has at least 2 valid ears.
 vert a, vert b, vert c ); is_in_triangle(
 vert a, vert b, vert c, 
 vert x );
  10. 10. Ear-Clipping Tessellation - Loop around all n verts in polygon - use curr-1, curr, curr+1 (modulo n)
 - test all other verts - is_in_triangle()
 (pre-calc current reflex/convex status per triangle to reduce time complexity). ~O(n^2)
 - if (is_ear) { - remove curr vertex from polygon - add triangle to a list - decrement n. - if n == 3 found last triangle. HALT -
 shows algorithm on Doom E1M1 in steps
 - src (experiment 039)
  11. 11. - extend Ear Clipping for O-shapes (hole in middle): - outer vertices clockwise order - make inner loop CCW - add to end of loop’s vertex list - add a valid “cut” line between outer and inner (tricky) - proceed as normal - now treated as a C-shape Pool of toxic sludge inside
 another sector - gets obscured
  12. 12. modified ear clipping
 (sludge pool no longer
 paved over)
  13. 13. shader for ceilings with “sky” image texture is one half of a 180
 that wraps ~ proto-skybox mapped to 320x200 screen
 pixels so hard to map to
 arbitrary size/resolution

  14. 14. Secrets of Romero’s Head - found tiny ledges on wall that had big daemon head - clever way of splitting enormous image into many
  15. 15. Hacking the unpublished sound format - Custom 8-byte header - I just ditched it - Body is a blob of waveform data - Guess format based on original
 SoundBlaster - Trial and error in Audacity raw data import - unsigned 8-bit mono 11025Hz samples - 16 bytes additional padding at front and end that can all be trimmed, leaving raw sound data. - Seems to work.
  16. 16. Music format - Wasn’t MIDI! It was MIDI encoded into a proprietary format - 9 instruments - custom playback software (never released) - MIDI2MUS and MUS2MIDI (MS-DOS) - I don’t know enough about MIDI etc to work it out. - I used DosBox and an ancient MUS2MIDI - Sub-par results - need original playback software!
  17. 17. “Dude, you need to stop working on your vanity projects!” - How do other Doom renderers deal with the sector tessellation problem? - They didn’t! Specially prepared .WAD [cheating!]. - Better potential solution - try Delaunay triangulation instead - Source code - DeWad - - OpenGL renderer - Blog post about it -
  18. 18. Finding a good cut - find rightmost inner loop vertex - project vector right from it - intersect all outer edges - find closest vertex to projected line (except if vertex is not visible to first vertex). - if closest point is an outer point use this. HALT. - otherwise search the outer edge for valid visible vertex to first
 (many tests and conditions here) multiple holes or complex? create hierarchies of simple
 shapes, solve small, combine