Last active
May 6, 2016 23:19
-
-
Save svanellewee/5c0b0059f5e593e47f7753ffced7b724 to your computer and use it in GitHub Desktop.
Wad reader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import logging | |
import struct | |
logging.basicConfig(level=logging.DEBUG) | |
logger =logging.getLogger(__name__) | |
def get_int(data): | |
return struct.unpack("<I", data)[0] | |
DIR_HEADER_SIZE=12 | |
def get_header(data_stream): | |
retval = {} | |
header = data_stream.read(DIR_HEADER_SIZE) | |
retval.update(dict(wad_type = header[:4])) | |
retval.update(dict(num_entries = get_int(header[4:8]))) | |
retval.update(dict(directory_absolute_location = get_int(header[8:DIR_HEADER_SIZE]))) | |
retval.update(dict(data_size = retval['directory_absolute_location'] - DIR_HEADER_SIZE)) | |
return retval | |
def get_data(data_stream, directory_location): | |
return { "data": data_stream.read(directory_location)} | |
def get_directory_entries(data_stream): | |
while True: | |
retval = {} | |
item = data_stream.read(16) | |
if len(item) != 16: | |
raise StopIteration | |
retval.update(dict(start = get_int(item[:4]))) | |
retval.update(dict(size = get_int(item[4:8]))) | |
retval.update(dict(name = item[8:16])) | |
yield retval | |
def build_directory(file_name): | |
with open(file_name, 'r') as wad_file: | |
header = get_header(wad_file) | |
wad_file.seek(header['directory_absolute_location']) | |
return [ i for i in get_directory_entries(wad_file)] | |
directory = build_directory(sys.argv[1]) | |
print len(directory) | |
def extract_data(file_name, directory, lumps_of_interest=None): | |
retval = {} | |
with open(file_name, 'r') as wad_file: | |
for lump in directory: | |
if lumps_of_interest and lump['start'] not in lumps_of_interest: | |
continue | |
wad_file.seek(lump['start']) | |
data = wad_file.read(lump['size']) | |
#print lump, len(data) | |
retval[lump['name'].strip('\0')] = data | |
return retval | |
E1M1_lumps = [ 67500, 68880, 75532, 94972, 96840, 105624, 106572, 113180, 115392, 116296 ] | |
data = extract_data(sys.argv[1], directory, E1M1_lumps) | |
for key, value in data.items(): | |
print key, len(value) | |
import io | |
def get_vertexes(byte_stream): | |
while True: | |
byte_elem = byte_stream.read(4) | |
if len(byte_elem) != 4: | |
raise StopIteration | |
yield struct.unpack("<hh", byte_elem) | |
def get_linedefs(byte_stream): | |
while True: | |
byte_elem = byte_stream.read(14) | |
if len(byte_elem) != 14: | |
raise StopIteration | |
retval = [] | |
#yield [ ord(i) for i in byte_elem] # 16 bytes | |
with io.BytesIO(byte_elem) as b: | |
retval.append(struct.unpack("<hh", b.read(4))) | |
# ignore the rest | |
yield retval | |
# a = struct.unpack("<hh", byte_elem[:4]) | |
# a = struct.unpack("<hh", byte_elem[:4]) | |
# a = struct.unpack("<hh", byte_elem[:4]) | |
# a = struct.unpack("<hh", byte_elem[:4]) | |
def get_dims(vertex_data): | |
lower_left = None | |
with io.BytesIO(vertex_data) as bio: | |
low = min(v[0] for v in get_vertexes(bio)) | |
bio.seek(0) | |
left = min(v[1] for v in get_vertexes(bio)) | |
bio.seek(0) | |
high = max(v[0] for v in get_vertexes(bio)) | |
bio.seek(0) | |
right = max(v[1] for v in get_vertexes(bio)) | |
lower_left = (low, left) | |
upper_right = (high, right) | |
return lower_left,upper_right | |
lower_left, upper_right = get_dims(data['VERTEXES']) | |
import svgwrite | |
dwg = svgwrite.Drawing('test.svg', size = (abs(upper_right[0]), abs(upper_right[1]))) | |
verts = [] | |
with io.BytesIO(data['VERTEXES']) as bio: | |
for v in get_vertexes(bio): | |
x, y = (v[0] - lower_left[0])/10.0, (v[1] - lower_left[1])/10.0 | |
verts.append((x,y)) | |
dwg.add(svgwrite.shapes.Rect((x,y),size=(0.5,0.5), stroke='#333', stroke_width=3)) | |
print len(verts),'LENG!' | |
count = 0 | |
with io.BytesIO(data['LINEDEFS']) as bio: | |
for v in get_linedefs(bio): | |
count += 1 | |
a,b = v[0] | |
print v, verts[a], verts[b] | |
dwg.add(dwg.line(verts[a],verts[b],stroke='#333', stroke_width=1)) | |
print count | |
dwg.save() | |
# some node fun. | |
with io.BytesIO(data['NODES']) as nodedata: | |
idx = 0 | |
while True: | |
dat = nodedata.read(8) | |
if not dat: | |
break | |
print idx,struct.unpack("<hhhh", dat) | |
idx +=1 | |
nodedata.read(16) | |
nodedata.read(4) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import logging | |
import struct | |
logging.basicConfig(level=logging.DEBUG) | |
logger =logging.getLogger(__name__) | |
# def getbytes(data): | |
# return struct.unpack('<I', data)[0] | |
DIR_HEADER_SIZE=12 | |
def get_directory(file_stream): | |
''' | |
0x00-0x03 string "PWAD" or "IWAD", defines whether the WAD is a PWAD or an IWAD | |
0x04-0x07 An integer specifying the number of entries in the directory | |
0x08-0x0b An integer holding a pointer to the location of the directory | |
''' | |
retval = {} | |
directory_raw = file_stream.read(DIR_HEADER_SIZE) | |
retval.update({"wad_type": directory_raw[:4]}) | |
retval.update({"num_entries": getbytes(directory_raw[4:8])[0]}) | |
retval.update({"location": getbytes(directory_raw[8:12])[0]}) | |
data_size = retval['location'] - DIR_HEADER_SIZE | |
retval.update({'data': file_stream.read(data_size)}) | |
return retval | |
def get_lump(file_stream): | |
lump = file_stream.read(16) | |
if len(lump) != 16: | |
return None | |
retval = {} | |
retval.update({"start": getbytes(lump[0:4])[0] - DIR_HEADER_SIZE}) | |
retval.update({"size": getbytes(lump[4:8])[0]}) | |
name = lump[8:16] | |
retval.update({"name": name}) | |
return retval | |
def getbytes(data): | |
return struct.unpack("<I", data) | |
with open(sys.argv[1],'rb') as wadfile: | |
directory_data = get_directory(wadfile) | |
print directory_data['wad_type'], directory_data['location'], directory_data['num_entries'], len(directory_data['data']) | |
while True: | |
lump = get_lump(wadfile) | |
if not lump: | |
break | |
data = directory_data['data'][lump['start']:lump['start']+lump['size']] | |
print lump, len(data) | |
if lump['name'] == 'VERTEXES': | |
print struct.unpack("<hh", data[0:4]) | |
print struct.unpack("<hh", data[4:8]) | |
# print struct.unpack("<hh", data[0:4]) | |
# print struct.unpack("<hh", data[0:4]) | |
# lump_start = getbytes(data[0:4]) | |
# lump_size = getbytes(data[4:8]) | |
# lump_name = data[8:16] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
get_linedefs gets linedef packets of 14 (doom version) and only uses the first 4 bytes (start vertex index -end vertex index)
Code then ignores the rest for now
From http://zdoom.org/wiki/Linedef... read it as follows : 0-1 means byte 0 AND byte 1, 2-3 means byte 2 AND byte 3 etc.
Bytes Data type Description
0-1 Unsigned short Beginning vertex
2-3 Unsigned short Ending vertex
4-5 Unsigned short Flags
6-7 Unsigned short Line type
8-9 Unsigned short Sector tag
10-11 Unsigned short Right sidedef - 0xFFFF means there is no sidedef
12-13 Unsigned short Left sidedef - 0xFFFF means there is no sidedef