Advertisement
qazmlpok

Fortune Star Panic extract

May 23rd, 2012
261
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.80 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, key=-1):
  18.     ret = infile.read(bytecount)
  19.  
  20.     return ret
  21.  
  22. def converttoint(bytes, size=INT_LENGTH, endian=LITTLE_ENDIAN):
  23.     result = 0
  24.     for i in xrange(size):
  25.         temp=long(ord(bytes[i]))
  26.         if endian == LITTLE_ENDIAN :
  27.             result |= (temp << (8*i))
  28.         elif endian == BIG_ENDIAN :
  29.             result = (result << 8) | temp
  30.         else :
  31.                 raise Exception('converttoint: Unknown endian specification')
  32.  
  33.         return result
  34.  
  35. def convertfromint(value, size=INT_LENGTH, endian=LITTLE_ENDIAN):
  36.     result = ""
  37.     for i in xrange(size):
  38.         if endian == LITTLE_ENDIAN :
  39.             #result |= (temp << (8*i))
  40.             temp = (value >> (8*i)) & 0x00FF
  41.         elif endian == BIG_ENDIAN :
  42.             #result = (result << 8) | temp
  43.             temp = (value >> (8*(size-i-1))) & 0x00FF
  44.         else :
  45.                 raise Exception('convertfromint: Unknown endian specification')
  46.             result += chr(temp)
  47.  
  48.         return result
  49.  
  50. #program
  51.  
  52. files = sys.argv[1:]
  53. for filename in files:
  54.     infile = open(filename, 'rb')
  55.  
  56.     print "Reading file", filename
  57.  
  58.     #Header:
  59.     #4 bytes "PACK"
  60.     #4 bytes number of files.
  61.  
  62.     pack = readbytes(infile, 4)
  63.     assert(pack == "PACK")
  64.  
  65.     filecount = converttoint(readbytes(infile, 4, 0))
  66.     print "Expecting", filecount, "files."
  67.  
  68.     #Each file entry is
  69.     #40 bytes   4 bytes     4 bytes     4 bytes     4 bytes
  70.     #Filename   UNK     UNK     Filestart   Filesize
  71.  
  72.     #Total of x50 bytes per entry.
  73.  
  74.     entries = []
  75.  
  76.     for i in xrange(filecount):
  77.         entry = {}
  78.         nameraw = readbytes(infile, 0x40)
  79.         entry['name'] = nameraw[0:nameraw.find("\x00")]     #Truncate to the first \0.
  80.         entry['unk1'] = converttoint(readbytes(infile, 4))  #Sort key (CRC32 of the filename)
  81.         entry['unk2'] = converttoint(readbytes(infile, 4))  #CRC32 of the file
  82.         entry['filestart'] = converttoint(readbytes(infile, 4))
  83.         entry['filesize'] = converttoint(readbytes(infile, 4))
  84.  
  85.         entries.append(entry)
  86.  
  87.     #Notes on the sort key;
  88.     #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.
  89.     #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)
  90.     #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.
  91.     #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
  92.     #archive will not be loaded properly.
  93.  
  94.     #print "Current position is now %d / %X" % (infile.tell(), infile.tell())
  95.  
  96.     #for entry in entries:
  97.     #   for i in entry:
  98.     #       print i + ":", entry[i]
  99.     #   print ""
  100.  
  101.     #sys.exit(0)
  102.  
  103.     dirname = filename[0:filename.find(".")]
  104.     if not os.path.isdir(dirname):
  105.         os.mkdir(dirname)
  106.  
  107.     i = 0
  108.     for entry in entries:
  109.         filename = entry['name'].strip(" \n\t\x00")
  110.  
  111.         dirsegment, filesegment = os.path.split(filename)
  112.         #filename = os.path.join(dirsegment, ("%03d_" % i) + filesegment)       #Can be done to enforce correct order on repacking
  113.         if (not os.path.isdir(os.path.join(dirname, dirsegment))):
  114.             os.makedirs(os.path.join(dirname, dirsegment))
  115.  
  116.         infile.seek(entry['filestart'])
  117.         data = readbytes(infile, entry['filesize'])
  118.         outfile = open(os.path.join(dirname, filename), 'wb')
  119.         outfile.write(data)
  120.         outfile.close()
  121.  
  122.         print "Created file %s of size %08X from position %08X" % (filename, entry['filesize'], entry['filestart'])
  123.         #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.
  124.  
  125.         i += 1
  126.  
  127.     infile.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement