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, xorkey):
- ret = ""
- count = 0
- while (count < bytecount):
- byte = long(ord(infile.read(1)))
- byte ^= xorkey
- ret += chr(byte)
- count += 1
- 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 (From d100.bin)
- #NFA0 01 00 00 00 D5 00 00 00 01 00 00 00
- #Const Const File count Const
- xorkey = 0x08 #Single byte constant for all encrypted portions of the file.
- header = infile.read(4)
- assert(header == "NFA0")
- const01 = converttoint(readbytes(infile, 4, 0))
- assert(const01 == 1)
- filecount = converttoint(readbytes(infile, 4, 0))
- print "Expecting", filecount, "files."
- const01 = converttoint(readbytes(infile, 4, 0))
- assert(const01 == 1)
- #Each file entry is
- #4 bytes 4 bytes 4 bytes 4 bytes 4 bytes x80 bytes
- #unk unk File size File start const of 0? Filename (UTF-16)
- #Total of x94 bytes per entry.
- #Everything after the header is XORed with x08. This is constant for every file, at least in Origin.
- entries = []
- for i in xrange(filecount):
- entry = {}
- entry['unk1'] = converttoint(readbytes(infile, 4, xorkey))
- entry['unk2'] = converttoint(readbytes(infile, 4, xorkey)) #CRC32 of the entire file (after XOR decryption)
- entry['filesize'] = converttoint(readbytes(infile, 4, xorkey))
- entry['filestart'] = converttoint(readbytes(infile, 4, xorkey))
- unk3 = converttoint(readbytes(infile, 4, xorkey)) #Appears to be either 0 or 1, but I have no idea what either should mean. Every .lua.lcd has this as 1, if that's relevant.
- entry['name'] = unicode(readbytes(infile, 0x80, xorkey), 'utf-16')
- entries.append(entry)
- #print "Current position is now %d / %X" % (infile.tell(), infile.tell())
- 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'], xorkey)
- 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