-
-
Save svanellewee/5c0b0059f5e593e47f7753ffced7b724 to your computer and use it in GitHub Desktop.
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) |
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] | |
(incomplete)
So it looks like WAD is a bit arse backwards, perhaps I'm wrong ?
The layout seems to be :
- header
- body
- index (dictionary)
Though my get_lump code is the thing that actually get's the index entries so that we can get the right stuff inside the body(ie the previous element)
I guess sqlite wasn't invented yet.
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
Rewrite of https://gist.github.com/jasonsperske/42284303cf6a7ef19dc3
and using http://zdoom.org/wiki/WAD as spec...
(just because I'm stupid and need things spelt out)