Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import sys
- #Constants taken from insani tools.
- LITTLE_ENDIAN = 1
- BIG_ENDIAN = -1
- BYTE_LENGTH = 1
- SHORT_LENGTH = 2
- INT_LENGTH = 4
- LONG_LENGTH = 8
- ERROR_NONE = 0
- ERROR_WARNING = 1
- ERROR_ABORT = 2
- def readbytes(infile, bytecount, key=-1):
- ret = infile.read(bytecount)
- if (key != -1):
- mask = int('FF' * bytecount, 16)
- value = converttoint(ret, bytecount)
- value = (value - key)&mask
- value = (~value)&mask
- ret = convertfromint(value, bytecount)
- return ret
- def converttoint(bytes, size=INT_LENGTH, endian=LITTLE_ENDIAN):
- result = 0
- for i in xrange(size):
- temp=long(ord(bytes[i]))
- if endian == LITTLE_ENDIAN :
- result |= (temp << (8*i))
- elif endian == BIG_ENDIAN :
- result = (result << 8) | temp
- else :
- raise Exception('converttoint: Unknown endian specification')
- return result
- def convertfromint(value, size=INT_LENGTH, endian=LITTLE_ENDIAN):
- result = ""
- for i in xrange(size):
- if endian == LITTLE_ENDIAN :
- #result |= (temp << (8*i))
- temp = (value >> (8*i)) & 0x00FF
- elif endian == BIG_ENDIAN :
- #result = (result << 8) | temp
- temp = (value >> (8*(size-i-1))) & 0x00FF
- else :
- raise Exception('convertfromint: Unknown endian specification')
- result += chr(temp)
- return result
- #program
- files = sys.argv[1:]
- for filename in files:
- infile = open(filename, 'rb')
- print "Reading file", filename
- #Header:
- #4 bytes for the decryption key, 4 bytes for the number of files in the archive, then 8 bytes of I have no idea.
- #Decryption:
- #The first byte (padded to 4) is the decryption key. This game uses subtraction/addition and binary NOT.
- #To decrypt, convert the value to an int (this is done either on a 4 byte block or a single byte),
- #subtract the key (values roll over, e.g. 5 - 10 = 251 on single byte)
- #NOT the result (251 becomes 4)
- #Then this process is reversed on encryption: NOT the value, add the key.
- #Presumably any arbitrary key can be used when rebuilding the archive. Maybe even 0 (you still need to NOT it).
- #The encryption applies to everything but the files and the key itself. File entries and the last 12 bytes of header are encrypted.
- decryptkey = converttoint(readbytes(infile, 4))
- filecount = converttoint(readbytes(infile, 4, decryptkey))
- print "Expecting", filecount, "files. Decryption key is " + ("%02X" % decryptkey)
- #Almost certainly 2 4 byte ints. One might be a CRC. I can't be arsed to confirm this.
- unk = readbytes(infile, 8, decryptkey)
- #Each file entry is
- #4 bytes 2C bytes 4 bytes 4 bytes 4 bytes 4 bytes
- #Filename len Filename Filesize Filestart unk unk
- #Total of x40 bytes per entry.
- #Filename is encrypted one byte at a time. Everything else is 4 bytes at a time.
- entries = []
- for i in xrange(filecount):
- entry = {}
- namelen = converttoint(readbytes(infile, 4, decryptkey))
- nameraw = ""
- for i in xrange(0x2C):
- #Need to do this one byte at a time. Or write a separate function.
- nameraw += readbytes(infile, 1, decryptkey)
- entry['name'] = nameraw[0:namelen]
- entry['filesize'] = converttoint(readbytes(infile, 4, decryptkey))
- entry['filestart'] = converttoint(readbytes(infile, 4, decryptkey))
- entry['unk1'] = converttoint(readbytes(infile, 4, decryptkey)) #Neither of these is a CRC.
- entry['unk2'] = converttoint(readbytes(infile, 4, decryptkey)) #
- entries.append(entry)
- #print "Current position is now %d / %X" % (infile.tell(), infile.tell())
- #for entry in entries:
- # for i in entry:
- # print i + ":", entry[i]
- # print ""
- #sys.exit(0)
- dirname = filename[0:filename.find(".")]
- if not os.path.isdir(dirname):
- os.mkdir(dirname)
- i = 0
- for entry in entries:
- filename = entry['name'].strip(" \n\t\x00")
- dirsegment, filesegment = os.path.split(filename)
- #filename = os.path.join(dirsegment, ("%03d_" % i) + filesegment) #Can be done to enforce correct order on repacking
- if (not os.path.isdir(os.path.join(dirname, dirsegment))):
- os.makedirs(os.path.join(dirname, dirsegment))
- infile.seek(entry['filestart'])
- data = readbytes(infile, entry['filesize'])
- outfile = open(os.path.join(dirname, filename), 'wb')
- outfile.write(data)
- outfile.close()
- print "Created file %s of size %08X from position %08X" % (filename, entry['filesize'], entry['filestart'])
- #print "Unks are %08X and %08X" % (entry['unk1'], entry['unk2'])
- i += 1
- infile.close()
Advertisement
Add Comment
Please, Sign In to add comment