qazmlpok

AQUASTYLE origin extraction

May 3rd, 2012
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.67 KB | None | 0 0
  1. import os
  2. import sys
  3.  
  4. #Constants taken from insani tools.
  5. LITTLE_ENDIAN = 1
  6. BIG_ENDIAN = -1
  7.  
  8. BYTE_LENGTH = 1
  9. SHORT_LENGTH = 2
  10. INT_LENGTH = 4
  11. LONG_LENGTH = 8
  12.  
  13. ERROR_NONE = 0
  14. ERROR_WARNING = 1
  15. ERROR_ABORT = 2
  16.  
  17. def readbytes(infile, bytecount, xorkey):
  18.     ret = ""
  19.     count = 0
  20.     while (count < bytecount):
  21.         byte = long(ord(infile.read(1)))
  22.         byte ^= xorkey
  23.  
  24.         ret += chr(byte)
  25.  
  26.         count += 1
  27.  
  28.     return ret
  29.  
  30. def converttoint(bytes, size=INT_LENGTH, endian=LITTLE_ENDIAN):
  31.     result = 0
  32.     for i in xrange(size):
  33.         temp=long(ord(bytes[i]))
  34.         if endian == LITTLE_ENDIAN :
  35.             result |= (temp << (8*i))
  36.         elif endian == BIG_ENDIAN :
  37.             result = (result << 8) | temp
  38.         else :
  39.                 raise Exception('converttoint: Unknown endian specification')
  40.  
  41.         return result
  42.  
  43. def convertfromint(value, size=INT_LENGTH, endian=LITTLE_ENDIAN):
  44.     result = ""
  45.     for i in xrange(size):
  46.         if endian == LITTLE_ENDIAN :
  47.             #result |= (temp << (8*i))
  48.             temp = (value >> (8*i)) & 0x00FF
  49.         elif endian == BIG_ENDIAN :
  50.             #result = (result << 8) | temp
  51.             temp = (value >> (8*(size-i-1))) & 0x00FF
  52.         else :
  53.                 raise Exception('convertfromint: Unknown endian specification')
  54.             result += chr(temp)
  55.  
  56.         return result
  57.  
  58. #program
  59.  
  60. files = sys.argv[1:]
  61. for filename in files:
  62.     infile = open(filename, 'rb')
  63.  
  64.     print "Reading file", filename
  65.  
  66.     #Header (From d100.bin)
  67.     #NFA0       01 00 00 00     D5 00 00 00     01 00 00 00
  68.     #Const      Const       File count  Const
  69.  
  70.     xorkey = 0x08   #Single byte constant for all encrypted portions of the file.
  71.  
  72.     header = infile.read(4)
  73.  
  74.     assert(header == "NFA0")
  75.  
  76.     const01 = converttoint(readbytes(infile, 4, 0))
  77.     assert(const01 == 1)
  78.  
  79.     filecount = converttoint(readbytes(infile, 4, 0))
  80.     print "Expecting", filecount, "files."
  81.  
  82.     const01 = converttoint(readbytes(infile, 4, 0))
  83.     assert(const01 == 1)
  84.  
  85.     #Each file entry is
  86.     #4 bytes    4 bytes     4 bytes     4 bytes     4 bytes     x80 bytes
  87.     #unk        unk     File size   File start  const of 0? Filename (UTF-16)
  88.  
  89.     #Total of x94 bytes per entry.
  90.     #Everything after the header is XORed with x08. This is constant for every file, at least in Origin.
  91.  
  92.     entries = []
  93.  
  94.     for i in xrange(filecount):
  95.         entry = {}
  96.         entry['unk1'] = converttoint(readbytes(infile, 4, xorkey))
  97.         entry['unk2'] = converttoint(readbytes(infile, 4, xorkey))      #CRC32 of the entire file (after XOR decryption)
  98.         entry['filesize'] = converttoint(readbytes(infile, 4, xorkey))
  99.         entry['filestart'] = converttoint(readbytes(infile, 4, xorkey))
  100.         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.
  101.         entry['name'] = unicode(readbytes(infile, 0x80, xorkey), 'utf-16')
  102.  
  103.  
  104.  
  105.         entries.append(entry)
  106.  
  107.  
  108.     #print "Current position is now %d / %X" % (infile.tell(), infile.tell())
  109.  
  110.     dirname = filename[0:filename.find(".")]
  111.     if not os.path.isdir(dirname):
  112.         os.mkdir(dirname)
  113.  
  114.     i = 0
  115.     for entry in entries:
  116.         filename = entry['name'].strip(" \n\t\x00")
  117.  
  118.         dirsegment, filesegment = os.path.split(filename)
  119.         #filename = os.path.join(dirsegment, ("%03d_" % i) + filesegment)       #Can be done to enforce correct order on repacking
  120.         if (not os.path.isdir(os.path.join(dirname, dirsegment))):
  121.             os.makedirs(os.path.join(dirname, dirsegment))
  122.  
  123.         infile.seek(entry['filestart'])
  124.         data = readbytes(infile, entry['filesize'], xorkey)
  125.         outfile = open(os.path.join(dirname, filename), 'wb')
  126.         outfile.write(data)
  127.         outfile.close()
  128.  
  129.         print "Created file %s of size %08X from position %08X" % (filename, entry['filesize'], entry['filestart'])
  130.         #print "Unks are %08X and %08X" % (entry['unk1'], entry['unk2'])
  131.  
  132.         i += 1
  133.  
  134.     infile.close()
Advertisement
Add Comment
Please, Sign In to add comment