Created
May 9, 2016 20:27
-
-
Save svanellewee/329733379072195b3288bb596782498f to your computer and use it in GitHub Desktop.
Rewriting doom into python. Wadfiles.
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
from __future__ import print_function | |
import unittest | |
import collections | |
import struct | |
''' | |
vertex test cases: | |
(10, FileLump(filepos=94972, size=1868, name='VERTEXES')) | |
(21, FileLump(filepos=179996, size=3768, name='VERTEXES')) | |
(32, FileLump(filepos=295644, size=3784, name='VERTEXES')) | |
(43, FileLump(filepos=394692, size=3120, name='VERTEXES')) | |
(54, FileLump(filepos=482536, size=2984, name='VERTEXES')) | |
(65, FileLump(filepos=601156, size=4828, name='VERTEXES')) | |
(76, FileLump(filepos=731496, size=3584, name='VERTEXES')) | |
(87, FileLump(filepos=804588, size=1312, name='VERTEXES')) | |
(98, FileLump(filepos=879156, size=2324, name='VERTEXES')) | |
''' | |
class IncorrectByteLength(Exception): | |
def __init__(self, message="Not correct byte count"): | |
super(IncorrectByteLength, self).__init__(message=message) | |
Header = collections.namedtuple("Header", ['identification', | |
'num_lumps', | |
'info_table_offset']) | |
def read_file(file_obj, size, handler, position=None): | |
if position: | |
file_obj.seek(position) | |
datum = file_obj.read(size) | |
if not datum: | |
return None | |
return handler(datum) | |
def convert_file_header(data): | |
# type: ([byte]) -> Header | |
""" | |
typedef struct | |
{ | |
// Should be "IWAD" or "PWAD". | |
char identification[4]; | |
int numlumps; | |
int infotableofs; | |
} PACKEDATTR wadinfo_t; | |
""" | |
if len(data) != 12: | |
raise IncorrectByteLength("byte length {} instead of 12".format(len(data))) | |
values = struct.unpack("<4sII", data) | |
name, numlumps, info_table_offset = values | |
return Header(name, | |
numlumps, | |
info_table_offset) | |
FileLump = collections.namedtuple("FileLump", ['filepos', | |
'size', | |
'name']) | |
def convert_filelump(data): | |
# type: ([byte]) -> FileLump | |
""" | |
typedef struct | |
{ | |
int filepos; | |
int size; | |
char name[8]; | |
} PACKEDATTR filelump_t; | |
""" | |
try: | |
filepos, size, name = struct.unpack("<II8s", data) | |
except Exception: | |
raise | |
return FileLump(filepos, size, name) | |
LumpInfo = collections.namedtuple("LumpInfo", ['position', | |
'size', | |
'name', | |
'wad_file']) | |
def convert_lumpinfo(wad_file_name, file_lump): | |
# type: (FileLump) -> LumpInfo | |
return LumpInfo(file_lump.filepos, | |
file_lump.size, | |
file_lump.name, | |
wad_file_name) | |
Vertex = collections.namedtuple("Vertex", ["x","y"]) | |
def read_vertex(data): | |
# type: ([byte]) -> Vertex | |
""" | |
typedef struct | |
{ | |
short x; | |
short y; | |
} PACKEDATTR mapvertex_t; | |
""" | |
try: | |
x, y = struct.unpack("<hh", data) | |
except Exception: | |
print("DDD", data) | |
raise | |
return Vertex(x,y) | |
def split_file(file_obj, size): | |
while True: | |
data = file_obj.read(size) | |
#print(data) | |
if not data: | |
break | |
yield data | |
MapLinedef = collections.namedtuple("MapLinedef", [ 'v1', | |
'v2', | |
'flags', | |
'special', | |
'tag', | |
'sidenum' ]) | |
def read_maplinedef(data): | |
# type: ([byte]) -> MapLinedef | |
""" | |
typedef struct | |
{ | |
short v1; //2 | |
short v2; //2 | |
short flags; //2 | |
short special; //2 | |
short tag; //2 | |
// sidenum[1] will be -1 if one sided | |
short sidenum[2]; //4 | |
# } PACKEDATTR maplinedef_t; | |
""" | |
sidenum = [-1, -1] | |
try: | |
v1, v2, flags, tag, special, sidenum[0], sidenum[1] = struct.unpack("<hhhhhhh", data) | |
except Exception: | |
raise | |
return MapLinedef(v1, v2, flags, tag, special, [sidenum[0], sidenum[1]]) | |
class TestWad(unittest.TestCase): | |
def test_add_file(self): | |
# need to make custom wad for tests... | |
test_file_name = '/Users/svanellewee/source/doom-stuff/doom1.wad' | |
with open(test_file_name, 'rb') as file_data: | |
header = read_file(file_data, | |
12, | |
convert_file_header) | |
file_data.seek(header.info_table_offset) | |
# LAZY LIZZARD!!! | |
file_lumps = (convert_filelump(i) for i in split_file(file_data, 16)) | |
lump_info = list(convert_lumpinfo(test_file_name, i) for i in file_lumps) | |
# map(print, enumerate(lump_info)) | |
def read_lump(lump_self, index, struct_size=1): | |
current_lump = lump_self[index] | |
with open(current_lump.wad_file, 'rb') as wad_file_data: | |
wad_file_data.seek(current_lump.position) | |
bytes_left = current_lump.size | |
while True: | |
datum = wad_file_data.read(struct_size) | |
if not datum: | |
break | |
if bytes_left <= 0: | |
break | |
bytes_left -= struct_size | |
yield datum | |
#vertexes are 4 bytes big in the file. | |
for i in read_lump(lump_info, 10, 4): | |
print(read_vertex(i)) | |
#linedefs are 14 bytes big in the file. | |
for i in read_lump(lump_info, 8, 14): | |
print(read_maplinedef(i)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment