mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2025-12-16 12:08:36 +00:00
150 lines
4.6 KiB
Python
150 lines
4.6 KiB
Python
import struct
|
|
|
|
class Pack:
|
|
def __init__(self, bytes):
|
|
self.bytes = bytes
|
|
self.directory = self.BuildDirectory()
|
|
|
|
def BuildDirectory(self):
|
|
bytes = self.GetRecord(0)
|
|
directory = []
|
|
for index in xrange(len(bytes) / 32):
|
|
entrybytes = bytes[index * 32 : index * 32 + 32]
|
|
filename, count, first = struct.unpack('>29sBH', entrybytes)
|
|
directory.append((filename[:filename.find('\0')], first, count))
|
|
return directory
|
|
|
|
def Decompress(self, bytes):
|
|
out = ''
|
|
ib = 0
|
|
done = False
|
|
while not done:
|
|
flags, = struct.unpack('B', bytes[ib])
|
|
ib += 1
|
|
for ibit in xrange(7, -1, -1):
|
|
if (flags & (1 << ibit)) != 0:
|
|
out += bytes[ib]
|
|
ib += 1
|
|
continue
|
|
code, = struct.unpack('>H', bytes[ib:ib+2])
|
|
ib += 2
|
|
ibBack = code & 0x1fff
|
|
if (code & 0xe000) != 0:
|
|
cb = (((code & 0xe000) >> 13) & 0xff) + 1
|
|
else:
|
|
if ibBack == 0:
|
|
done = True
|
|
break;
|
|
part = struct.unpack('B', bytes[ib])[0] >> 7
|
|
ibBack = (code << 1) | part
|
|
cb = (struct.unpack('B', bytes[ib])[0] & 0x7f) + 2;
|
|
ib += 1
|
|
ibCopy = len(out) - ibBack
|
|
out += out[ibCopy : ibCopy + cb]
|
|
return out
|
|
|
|
def GetRecordOffset(self, index):
|
|
offset = 72 + 6 + index * 8
|
|
return struct.unpack('>L', self.bytes[offset:offset+4])[0]
|
|
|
|
def GetRecordCount(self):
|
|
offset = 72 + 4
|
|
return struct.unpack('>H', self.bytes[offset:offset+2])[0]
|
|
|
|
def GetRawRecord(self, index):
|
|
offset = self.GetRecordOffset(index)
|
|
if (index == self.GetRecordCount() - 1):
|
|
size = len(self.bytes) - offset
|
|
else:
|
|
size = self.GetRecordOffset(index + 1) - offset
|
|
return self.bytes[offset:offset+size]
|
|
|
|
def GetRecord(self, index):
|
|
record = self.GetRawRecord(index)
|
|
header = struct.unpack('>3H', record[0:6])
|
|
compressed, cbUncompressed, cbCompressed = header
|
|
if compressed == 0:
|
|
return record[6:]
|
|
else:
|
|
return self.Decompress(record[6:])
|
|
|
|
def FindDirectoryEntry(self, filename):
|
|
for entry in self.directory:
|
|
if entry[0] == filename:
|
|
return entry
|
|
return None
|
|
|
|
def GetFilenames(self):
|
|
filenames = []
|
|
for entry in self.directory:
|
|
filenames.append(entry[0])
|
|
return filenames
|
|
|
|
def GetFile(self, filename):
|
|
entry = self.FindDirectoryEntry(filename)
|
|
bytes = ''
|
|
for index in xrange(entry[2]):
|
|
bytes += self.GetRecord(entry[1] + index)
|
|
return bytes
|
|
|
|
class Ini:
|
|
def __init__(self, bytes):
|
|
self.bytes = bytes
|
|
self.sections = {}
|
|
|
|
pos = 0
|
|
while True:
|
|
nextSection, = struct.unpack('>H', bytes[pos : pos + 2])
|
|
pos += 2
|
|
countProps, = struct.unpack('>H', bytes[pos : pos + 2])
|
|
pos += 2
|
|
nameSection = bytes[pos : pos + bytes[pos:].find('\0')]
|
|
pos += len(nameSection) + 1
|
|
section = {}
|
|
for index in xrange(countProps):
|
|
key = bytes[pos : pos + bytes[pos:].find('\0')]
|
|
pos += len(key) + 1
|
|
value = bytes[pos : pos + bytes[pos:].find('\0')]
|
|
pos += len(value) + 1
|
|
section[key] = value
|
|
self.sections[nameSection] = section
|
|
if (pos & 1) != 0:
|
|
pos += 1
|
|
if nextSection == 0:
|
|
break
|
|
|
|
def __getitem__(self, key):
|
|
return self.sections[key]
|
|
|
|
if __name__ == '__main__':
|
|
filename = 'htdata832.pdb'
|
|
f = file(filename)
|
|
pack = Pack(f.read())
|
|
f.close()
|
|
|
|
# Get filename list
|
|
filenames = pack.GetFilenames()
|
|
|
|
# Look for missions
|
|
missions = []
|
|
for filename in filenames:
|
|
if not filename.endswith(".lvl"):
|
|
continue
|
|
|
|
print filename
|
|
bytes = pack.GetFile(filename)
|
|
ini = Ini(bytes)
|
|
print ini.sections
|
|
break
|
|
|
|
|
|
"""
|
|
ini = Ini(pack.GetFile(filename))
|
|
mission = {}
|
|
mission['filename'] = filename
|
|
mission['title'] = ini['General']['Title']
|
|
mission['minplayers'] = ini['General']['MinPlayers']
|
|
mission['maxplayers'] = ini['General']['MaxPlayers']
|
|
missions.append(mission)
|
|
"""
|