Advertisement
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)
- 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 "PACK"
- #4 bytes number of files.
- pack = readbytes(infile, 4)
- assert(pack == "PACK")
- filecount = converttoint(readbytes(infile, 4, 0))
- print "Expecting", filecount, "files."
- #Each file entry is
- #40 bytes 4 bytes 4 bytes 4 bytes 4 bytes
- #Filename UNK UNK Filestart Filesize
- #Total of x50 bytes per entry.
- entries = []
- for i in xrange(filecount):
- entry = {}
- nameraw = readbytes(infile, 0x40)
- entry['name'] = nameraw[0:nameraw.find("\x00")] #Truncate to the first \0.
- entry['unk1'] = converttoint(readbytes(infile, 4)) #Sort key (CRC32 of the filename)
- entry['unk2'] = converttoint(readbytes(infile, 4)) #CRC32 of the file
- entry['filestart'] = converttoint(readbytes(infile, 4))
- entry['filesize'] = converttoint(readbytes(infile, 4))
- entries.append(entry)
- #Notes on the sort key;
- #The entries in the index are not in a logical order. The first entry in the index is not the first file in the contents.
- #Instead, each entry has a sort key. The actual files are arranged in alphabetical order (the first file is BGM\BGM02.ogg, followed by BGM\BGM02__.ogg, but these are nowhere near each other in the index)
- #This key is actually the CRC 32 of the filename (without any of the \0 bytes). Presumably it is used for indexing of the files.
- #When rebuilding the archive it is necessary to preserve the order of the sort keys and the correct value. If this is not done the
- #archive will not be loaded properly.
- #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 "Unk is %08X and %08X" % (entry['unk1'],entry['unk2']) #It's mostly 0012F79C, also a few 0012FAC4. No idea what it would be used for.
- i += 1
- infile.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement