python3 path/to/01.cat
to get a file listing, and
python3 path/to/01.cat foo/bar/filename
to extract that file from the dat to "foo/bar/filename". An existing file is overwritten.
Almost completely untested, use at your own risk.
Code: Select all
import sys
import os.path
class cat(object):
def __init__(self, catfilename):
with open(catfilename, "rb") as inputfile:
data = inputfile.read()
self.datfilename, *lines = self.cat_decrypt(data).splitlines()
self.entries = {}
nextpos = 0
for line in lines:
name, length = line.rsplit(" ", 1)
length = int(length)
self.entries[name] = (nextpos, length)
nextpos += length
try:
self.datfile = open(os.path.dirname(catfilename) + '/' + self.datfilename, "rb")
except FileNotFoundError:
self.datfile = open(os.path.dirname(catfilename) + '/' +
os.path.basename(catfilename).split(".")[0] + ".dat", "rb")
@staticmethod
def cat_magic():
magic = 0xDA
while True:
magic = (magic + 1) % 256
yield magic
@staticmethod
def cat_decrypt(data):
magic = cat.cat_magic()
return "".join([chr(b ^ next(magic)) for b in data])
def list(self):
return tuple(self.entries.keys())
def read_dat(self, pos, length):
self.datfile.seek(pos)
return bytes([b ^ 0x33 for b in self.datfile.read(length)])
def read_file(self, filename):
if not filename in self.entries:
return None
return self.read_dat(*self.entries[filename])
def copyfile(self, filename):
data = self.read_file(filename)
if not data:
sys.stderr.write("Could not file %s\n" % filename)
return
os.makedirs(os.path.dirname(filename), exist_ok=True)
with open(filename, "wb") as outputfile:
outputfile.write(data)
if len(sys.argv) == 1:
print("%s: <cat file name> [file to extract]")
sys.exit()
c = cat(sys.argv[1])
if len(sys.argv) == 2:
print("\n".join(c.list()))
elif len(sys.argv) == 3:
c.copyfile(sys.argv[2])