Skip to content

Instantly share code, notes, and snippets.

@gschizas
Forked from jasonsperske/MIT-LICENSE
Created May 30, 2014 17:32

Revisions

  1. @jasonsperske jasonsperske revised this gist May 26, 2014. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions WADParser.py
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    #!/usr/bin/env python
    #!/usr/bin/env python3

    import struct
    import re
    @@ -19,11 +19,11 @@ def __init__(self, wadFile):
    current_level = Level(None) #The first few records of a WAD are not associated with a level

    lump = f.read(16) #Each offset is is part of a packet 16 bytes
    while lump != "":
    while len(lump) == 16:
    filepos = struct.unpack("<I", lump[0:4])[0] - header_size
    size = struct.unpack("<I", lump[4:8])[0]
    name = lump[8:16].rstrip('\0')

    name = lump[8:16].decode('UTF-8').rstrip('\0')
    print(name)
    if(re.match('E\dM\d|MAP\d\d', name)):
    #Level nodes are named things like E1M1 or MAP01
    if(current_level.is_valid()):
    @@ -55,7 +55,7 @@ def __init__(self, name):
    self.lines = []

    def is_valid(self):
    return self.name is not None and self.lumps.has_key('VERTEXES') and self.lumps.has_key('LINEDEFS')
    return self.name is not None and 'VERTEXES' in self.lumps and 'LINEDEFS' in self.lumps

    def normalize(self, point, padding=5):
    return (self.shift[0]+point[0]+padding,self.shift[1]+point[1]+padding)
    @@ -119,4 +119,4 @@ def packets_of_size(n, data):
    for level in wad.levels:
    level.save_svg()
    else:
    print 'You need to pass a WAD file as the only argument'
    print('You need to pass a WAD file as the only argument')
  2. @jasonsperske jasonsperske revised this gist May 26, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion WADParser.py
    Original file line number Diff line number Diff line change
    @@ -83,7 +83,7 @@ def save_svg(self):
    else:
    canvas_size = (int(1024*(float(view_box_size[0])/view_box_size[1])), 1024)

    dwg = svgwrite.Drawing(self.name+'.svg', profile='tiny', size=canvas_size , viewBox=('0 0 '+str(view_box_size[0])+' '+str(view_box_size[1])))
    dwg = svgwrite.Drawing(self.name+'.svg', profile='tiny', size=canvas_size , viewBox=('0 0 %d %d' % view_box_size))
    for line in self.lines:
    a = self.normalize(self.vertices[line.a])
    b = self.normalize(self.vertices[line.b])
  3. @jasonsperske jasonsperske revised this gist May 26, 2014. 1 changed file with 86 additions and 84 deletions.
    170 changes: 86 additions & 84 deletions WADParser.py
    Original file line number Diff line number Diff line change
    @@ -3,118 +3,120 @@
    import struct
    import re

    class Wad:
    def __init__(self,wadFile):
    self.Maps = []
    self._isHexenFormat = False
    class Wad(object):
    """Encapsulates the data found inside a WAD file"""

    def __init__(self, wadFile):
    """Each WAD files contains definitions for global attributes as well as map level attributes"""
    self.levels = []
    self.wad_format = 'DOOM' #Assume DOOM format unless 'BEHAVIOR'
    with open(wadFile, "rb") as f:
    identification = f.read(4)
    numlumps, infotableofs = struct.unpack("<II", f.read(8))
    data = f.read(infotableofs-12)

    currentMap = Map(None)

    lump = f.read(16)
    header_size = 12
    self.wad_type = f.read(4)[0]
    self.num_lumps = struct.unpack("<I", f.read(4))[0]
    data = f.read(struct.unpack("<I", f.read(4))[0] - header_size)

    current_level = Level(None) #The first few records of a WAD are not associated with a level

    lump = f.read(16) #Each offset is is part of a packet 16 bytes
    while lump != "":
    # Do stuff with byte.
    filepos, size = struct.unpack("<II", lump[0:8])
    filepos = struct.unpack("<I", lump[0:4])[0] - header_size
    size = struct.unpack("<I", lump[4:8])[0]
    name = lump[8:16].rstrip('\0')

    filepos = filepos-12

    if(re.match('E\dM\d|MAP\d\d', name)):
    if(currentMap.Name is not None):
    self.Maps.append(currentMap)
    currentMap = Map(name)
    #Level nodes are named things like E1M1 or MAP01
    if(current_level.is_valid()):
    self.levels.append(current_level)

    current_level = Level(name)
    elif name == 'BEHAVIOR':
    self._isHexenFormat = True
    #This node only appears in Hexen formated WADs
    self.wad_format = 'HEXEN'
    else:
    currentMap.Lumps[name] = data[filepos:filepos+size]
    current_level.lumps[name] = data[filepos:filepos+size]

    lump = f.read(16)
    self.Maps.append(currentMap)

    for level in self.Maps:
    level.load(self._isHexenFormat)

    @staticmethod
    def split(n, data):
    size = len(data)
    index = 0
    while index < size:
    yield data[index : index+n]
    index = index + n
    return

    class Map:
    def __init__(self,name):
    self.Name = name
    self.Lumps = dict()
    self._Vertices = []
    self.min = None
    self.max = None
    if(current_level.is_valid()):
    self.levels.append(current_level)

    for level in self.levels:
    level.load(self.wad_format)

    class Level(object):
    """Represents a level inside a WAD which is a collection of lumps"""
    def __init__(self, name):
    self.name = name
    self.lumps = dict()
    self.vertices = []
    self.lower_left = None
    self.upper_right = None
    self.shift = None
    self._Lines = []
    self.lines = []

    def _readVerticies(self):
    for vertex in Wad.split(4, self.Lumps['VERTEXES']):
    x,y = struct.unpack('<hh', vertex[0:4])

    self._Vertices.append((x,y))
    if self.min is None:
    self.min = (x,y)
    else:
    self.min = (min(x, self.min[0]), min(y, self.min[1]))
    if self.max is None:
    self.max = (x,y)
    else:
    self.max = (max(x, self.max[0]), max(y, self.max[1]))
    self.shift = (0-self.min[0],0-self.min[1])

    def _readLines(self,isHexenFormat):
    lineSize = 16 if isHexenFormat else 14
    def is_valid(self):
    return self.name is not None and self.lumps.has_key('VERTEXES') and self.lumps.has_key('LINEDEFS')

    for data in Wad.split(lineSize, self.Lumps['LINEDEFS']):
    self._Lines.append(Line(data))
    def normalize(self, point, padding=5):
    return (self.shift[0]+point[0]+padding,self.shift[1]+point[1]+padding)

    def readThings(self, data):
    print 'Reading things'
    def load(self, wad_format):
    for vertex in packets_of_size(4, self.lumps['VERTEXES']):
    x,y = struct.unpack('<hh', vertex[0:4])
    self.vertices.append((x,y))

    def normalize(self,point,padding=5):
    return (self.shift[0]+point[0]+padding,self.shift[1]+point[1]+padding)
    self.lower_left = (min((v[0] for v in self.vertices)), min((v[1] for v in self.vertices)))
    self.upper_right = (max((v[0] for v in self.vertices)), max((v[1] for v in self.vertices)))

    def load(self, isHexenFormat):
    self._readVerticies()
    self._readLines(isHexenFormat)
    self.shift = (0-self.lower_left[0],0-self.lower_left[1])

    packet_size = 16 if wad_format is 'HEXEN' else 14
    for data in packets_of_size(packet_size, self.lumps['LINEDEFS']):
    self.lines.append(Line(data))

    def saveSVG(self):
    def save_svg(self):
    """ Scale the drawing to fit inside a 1024x1024 canvas (iPhones don't like really large SVGs even if they have the same detail) """
    import svgwrite
    viewPortSize = self.normalize(self.max, 10)
    canvasSize = (1024,1024)

    dwg = svgwrite.Drawing(self.Name+'.svg', profile='tiny', size=canvasSize , viewBox=('0 0 '+str(viewPortSize[0])+' '+str(viewPortSize[1])))
    for line in self._Lines:
    a = self.normalize(self._Vertices[line.A])
    b = self.normalize(self._Vertices[line.B])
    if line.LeftSide == -1 or line.RightSide == -1:
    view_box_size = self.normalize(self.upper_right, 10)
    if view_box_size[0] > view_box_size[1]:
    canvas_size = (1024, int(1024*(float(view_box_size[1])/view_box_size[0])))
    else:
    canvas_size = (int(1024*(float(view_box_size[0])/view_box_size[1])), 1024)

    dwg = svgwrite.Drawing(self.name+'.svg', profile='tiny', size=canvas_size , viewBox=('0 0 '+str(view_box_size[0])+' '+str(view_box_size[1])))
    for line in self.lines:
    a = self.normalize(self.vertices[line.a])
    b = self.normalize(self.vertices[line.b])
    if line.is_one_sided():
    dwg.add(dwg.line(a, b, stroke='#333', stroke_width=10))
    else:
    dwg.add(dwg.line(a, b, stroke='#999', stroke_width=3))

    dwg.save()

    class Line:
    class Line(object):
    """Represents a Linedef inside a WAD"""
    def __init__(self,data):
    self.A, self.B = struct.unpack('<hh', data[0:4])
    self.LeftSide, self.RightSide = struct.unpack('<hh', data[-4:])
    self.a, self.b = struct.unpack('<hh', data[0:4])
    self.left_side, self.right_side = struct.unpack('<hh', data[-4:])

    def is_one_sided(self):
    return self.left_side == -1 or self.right_side == -1

    def __repr__(self):
    return '('+str(self.A)+','+str(self.B)+')'
    def packets_of_size(n, data):
    size = len(data)
    index = 0
    while index < size:
    yield data[index : index+n]
    index = index + n
    return

    if __name__ == "__main__":
    import sys

    if len(sys.argv) > 1:
    wad = Wad(sys.argv[1])
    for level in wad.Maps:
    level.saveSVG()
    for level in wad.levels:
    level.save_svg()
    else:
    print 'You need to pass a WAD file as the only argument'
  4. @jasonsperske jasonsperske revised this gist May 23, 2014. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions WADParser.py
    Original file line number Diff line number Diff line change
    @@ -87,14 +87,17 @@ def load(self, isHexenFormat):

    def saveSVG(self):
    import svgwrite
    dwg = svgwrite.Drawing(self.Name+'.svg', profile='tiny', size=self.normalize(self.max, 10))
    viewPortSize = self.normalize(self.max, 10)
    canvasSize = (1024,1024)

    dwg = svgwrite.Drawing(self.Name+'.svg', profile='tiny', size=canvasSize , viewBox=('0 0 '+str(viewPortSize[0])+' '+str(viewPortSize[1])))
    for line in self._Lines:
    a = self.normalize(self._Vertices[line.A])
    b = self.normalize(self._Vertices[line.B])
    if line.LeftSide == -1 or line.RightSide == -1:
    dwg.add(dwg.line(a, b, stroke=svgwrite.rgb(10, 10, 16, '%'), stroke_width=10))
    dwg.add(dwg.line(a, b, stroke='#333', stroke_width=10))
    else:
    dwg.add(dwg.line(a, b, stroke=svgwrite.rgb(10, 10, 16, '%'), stroke_width=3))
    dwg.add(dwg.line(a, b, stroke='#999', stroke_width=3))

    dwg.save()

  5. @jasonsperske jasonsperske created this gist May 22, 2014.
    117 changes: 117 additions & 0 deletions WADParser.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,117 @@
    #!/usr/bin/env python

    import struct
    import re

    class Wad:
    def __init__(self,wadFile):
    self.Maps = []
    self._isHexenFormat = False
    with open(wadFile, "rb") as f:
    identification = f.read(4)
    numlumps, infotableofs = struct.unpack("<II", f.read(8))
    data = f.read(infotableofs-12)

    currentMap = Map(None)

    lump = f.read(16)
    while lump != "":
    # Do stuff with byte.
    filepos, size = struct.unpack("<II", lump[0:8])
    name = lump[8:16].rstrip('\0')

    filepos = filepos-12
    if(re.match('E\dM\d|MAP\d\d', name)):
    if(currentMap.Name is not None):
    self.Maps.append(currentMap)
    currentMap = Map(name)
    elif name == 'BEHAVIOR':
    self._isHexenFormat = True
    else:
    currentMap.Lumps[name] = data[filepos:filepos+size]
    lump = f.read(16)
    self.Maps.append(currentMap)

    for level in self.Maps:
    level.load(self._isHexenFormat)

    @staticmethod
    def split(n, data):
    size = len(data)
    index = 0
    while index < size:
    yield data[index : index+n]
    index = index + n
    return

    class Map:
    def __init__(self,name):
    self.Name = name
    self.Lumps = dict()
    self._Vertices = []
    self.min = None
    self.max = None
    self.shift = None
    self._Lines = []

    def _readVerticies(self):
    for vertex in Wad.split(4, self.Lumps['VERTEXES']):
    x,y = struct.unpack('<hh', vertex[0:4])

    self._Vertices.append((x,y))
    if self.min is None:
    self.min = (x,y)
    else:
    self.min = (min(x, self.min[0]), min(y, self.min[1]))
    if self.max is None:
    self.max = (x,y)
    else:
    self.max = (max(x, self.max[0]), max(y, self.max[1]))
    self.shift = (0-self.min[0],0-self.min[1])

    def _readLines(self,isHexenFormat):
    lineSize = 16 if isHexenFormat else 14

    for data in Wad.split(lineSize, self.Lumps['LINEDEFS']):
    self._Lines.append(Line(data))

    def readThings(self, data):
    print 'Reading things'

    def normalize(self,point,padding=5):
    return (self.shift[0]+point[0]+padding,self.shift[1]+point[1]+padding)

    def load(self, isHexenFormat):
    self._readVerticies()
    self._readLines(isHexenFormat)

    def saveSVG(self):
    import svgwrite
    dwg = svgwrite.Drawing(self.Name+'.svg', profile='tiny', size=self.normalize(self.max, 10))
    for line in self._Lines:
    a = self.normalize(self._Vertices[line.A])
    b = self.normalize(self._Vertices[line.B])
    if line.LeftSide == -1 or line.RightSide == -1:
    dwg.add(dwg.line(a, b, stroke=svgwrite.rgb(10, 10, 16, '%'), stroke_width=10))
    else:
    dwg.add(dwg.line(a, b, stroke=svgwrite.rgb(10, 10, 16, '%'), stroke_width=3))

    dwg.save()

    class Line:
    def __init__(self,data):
    self.A, self.B = struct.unpack('<hh', data[0:4])
    self.LeftSide, self.RightSide = struct.unpack('<hh', data[-4:])

    def __repr__(self):
    return '('+str(self.A)+','+str(self.B)+')'

    if __name__ == "__main__":
    import sys

    if len(sys.argv) > 1:
    wad = Wad(sys.argv[1])
    for level in wad.Maps:
    level.saveSVG()
    else:
    print 'You need to pass a WAD file as the only argument'