qazmlpok

Touhou Sky Arena - Extract.py

May 15th, 2012
261
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.07 KB | None | 0 0
  1. from insani import *
  2. import os
  3. import sys
  4.  
  5. trans_table = "\x49\xF2\xD0\x20\x37\x5E\x77\x3E\x3C\xFB\x3E\x21\x33\xE9\xF2\x96\xD0\xE6\x89\x8E\x27\xD7\x3C\x45\x77\xDD\x32\x6B\x06\x78\xE1\x87\xBC\x10\xBB\x04\xE5\x7F\x63\x98\xB0\xEB\x78\x04\x58\x01\xA9\x51\xA6\xE8\xAD\x92\x8E\x87\x49\x4A\x3E\x64\x81\x7E\xC7\x37\xA3\x93\xC4\x8B\x3E\x01\x1F\xFA\x46\x79\x5D\xD4\x5F\x09\x99\x4E\xAA\xDC\x00\x89\xF5\x9B\x89\x89\x3C\x99\x43\xE2\xD5\xBF\xCC\xC7\x31\xFA\xFC\xB2\x16\x02\xC2\x57\xB0\xC7\xAA\x1E\x67\x7B\xAE\x40\x4E\x4F\x32\x69\xA9\x77\xD1\x52\xD0\x1B\xE7\xD0\xE8\x1F\xE6\xC8\x4C\x99\x73\x72\x93\x36\xE2\xFB\x8A\xEF\x75\xCE\x92\x6B\x89\x29\xBE\x48\x07\xC7\x22\x39\xD2\xBC\x96\xBC\x05\xC6\x8A\xCD\x22\xBC\x8B\x4C\xAE\xE1\x1B\x90\x45\x35\x8D\xE0\x10\x14\x7B\x2E\x4C\xBC\x7D\x66\xBD\x8C\x4E\x33\x2D\x09\x73\x71\xE4\x07\x9E\xC1\x3B\x8D\x57\xF6\xA5\x37\x23\x49\xE4\x33\x4A\x8E\xBD\xBF\x4F\xD9\x4F\x95\x5E\x4E\x87\x41\xAE\x01\xB6\x56\xA0\xAE\xC6\xF2\x1B\xB5\x24\x85\xEE\xFE\xC3\x4D\x3B\xDA\xF0\x0B\x22\x70\x38\x45\x50\x4C\x9E\x30\x88\xA9\x8A\x12\x5B\xFC\xF5\xAE\x2A\xEC\xDD\x11\x0D\xA6\x81\x54\xE2\x00"
  6.  
  7. def readbytes(infile, bytecount, xorkey, offset=0):
  8.     ret = ""
  9.     while (offset < bytecount):
  10.         byte = long(ord(infile.read(1)))
  11.         byte ^= xorkey
  12.         byte ^= ord(trans_table[offset&0xFF])
  13.  
  14.         ret += chr(byte)
  15.  
  16.         offset += 1
  17.         if (offset&0xF0000000):
  18.             print "Offset got huge. This functionality not implemented."
  19.             sys.exit()
  20.  
  21.     return ret
  22.  
  23. def converttoint(bytes, size=INT_LENGTH, endian=LITTLE_ENDIAN):
  24.     result = 0
  25.     for i in xrange(size):
  26.         temp=long(ord(bytes[i]))
  27.         if endian == LITTLE_ENDIAN :
  28.             result |= (temp << (8*i))
  29.         elif endian == BIG_ENDIAN :
  30.             result = (result << 8) | temp
  31.         else :
  32.                 raise 'converttoint', 'Unknown endian specification'
  33.  
  34.         return result
  35.  
  36. def convertfromint(value, size=INT_LENGTH, endian=LITTLE_ENDIAN):
  37.     result = ""
  38.     for i in xrange(size):
  39.         if endian == LITTLE_ENDIAN :
  40.             #result |= (temp << (8*i))
  41.             temp = (value >> (8*i)) & 0x00FF
  42.         elif endian == BIG_ENDIAN :
  43.             #result = (result << 8) | temp
  44.             temp = (value >> (8*(size-i-1))) & 0x00FF
  45.         else :
  46.                 raise 'convertfromint', 'Unknown endian specification'
  47.             result += chr(temp)
  48.  
  49.         return result
  50.  
  51. #program
  52.  
  53. files = sys.argv[1:]
  54. for filename in files:
  55.     if (os.path.isdir(filename)):
  56.         #Add recursion. If a directory is selected process all .gpk files within it
  57.         for (root, dirs, dirfiles) in os.walk(filename):
  58.             for name in dirfiles:
  59.                 if (name.endswith('.gpk')):
  60.                     files.append(os.path.join(root, name))
  61.         continue;
  62.     infile = open(filename, 'rb')
  63.  
  64.     print "Reading file ", filename
  65.     xorkey = read_unsigned(infile, 1) ^ 0x92
  66.     print "The key is %2X (from %2X)" % (xorkey, xorkey^0x92)
  67.  
  68.     header_unk = converttoint(readbytes(infile, 4, xorkey))
  69.     print "The unknown crap is %8X" % header_unk
  70.  
  71.     filecount = converttoint(readbytes(infile, 4, xorkey))
  72.     print "There are %d files" % filecount
  73.  
  74.     entries = []
  75.  
  76.     for i in xrange(filecount):
  77.         entry = {}
  78.         filedata = readbytes(infile, 0x10C, xorkey)
  79.         entry['name'] = filedata[0:0x104].strip(" \t\n\0")
  80.         #print "Name is %s - size %d" % (fname, len(fname))
  81.  
  82.         #block1 = converttoint(filedata[0x100:0x104])
  83.         entry['filesize'] = converttoint(filedata[0x104:0x108])
  84.         entry['filestart'] = converttoint(filedata[0x108:0x10C])
  85.  
  86.         #print "And the blocks are: %08X - %08X" % (filesize, filestart)
  87.  
  88.         entries.append(entry)
  89.  
  90.  
  91.     #print "Current position is now %d / %X" % (infile.tell(), infile.tell())
  92.  
  93.     xorkey = (header_unk % 0xFF)&0xFF
  94.  
  95.     dirname = filename[0:filename.find(".")]
  96.     if not os.path.isdir(dirname):
  97.         os.mkdir(dirname)
  98.  
  99.     i = 0
  100.     for entry in entries:
  101.         filename = ("%03d_" % i) + entry['name']
  102.         infile.seek(entry['filestart'])
  103.         data = readbytes(infile, entry['filesize'], xorkey)
  104.         outfile = open(dirname + '\\' + filename, 'wb')
  105.         outfile.write(data)
  106.         outfile.close()
  107.  
  108.         print "Created file", filename, "of size", entry['filesize'], "from position", entry['filestart']
  109.  
  110.         i += 1
  111.  
  112.     outfile = open(dirname + '\\' + 'crc.txt', 'wb')
  113.     outfile.write(convertfromint(header_unk))
  114.  
  115.  
  116.     infile.close()
Advertisement
Add Comment
Please, Sign In to add comment