Advertisement
Lavos

Akatsuki no Goei Trinity

Jan 16th, 2015
648
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.52 KB | None | 0 0
  1. import os,sys,struct,zlib
  2.  
  3. reload(sys)
  4. sys.setdefaultencoding('sjis')
  5.  
  6. def get_data(filename):
  7.     totalbytes = os.path.getsize(filename)
  8.     infile = open(filename, 'rb')
  9.     totalfiledata = infile.read(totalbytes)
  10.     return totalfiledata
  11.  
  12. def decrypt(filedata,adlr,start):
  13.     xor = (adlr >> 0xc) & 0xFF
  14.     for i in range(start,len(filedata)):
  15.         filedata[i] = filedata[i] ^ xor
  16.     return filedata
  17.  
  18. def decrypt_scenario(filedata):
  19.     newfiledata = ''
  20.     lenremaining = len(filedata) % 0x2
  21.     for i in range(0,len(filedata)-lenremaining,2):
  22.         word = struct.unpack('<H',filedata[i:i+2])[0]
  23.         word2 = word
  24.         word &= 0x5555
  25.         word2 &= 0xAAAAAAAA
  26.         word2 = word2 >> 1
  27.         word += word
  28.         word = (word2 & 0xFFFF) | (word & 0xFFFF)
  29.         newfiledata += struct.pack('<H',word)
  30.     newfiledata += filedata[len(filedata)-lenremaining:]
  31.     return newfiledata
  32.  
  33. def extract_xp3(filenam):
  34.     filedata = get_data(filenam)
  35.     if struct.unpack('<B',filedata[0xb:0xc])[0] == 0x17:
  36.         tocpos = struct.unpack('<Q',filedata[0x20:0x28])[0]
  37.     else:
  38.         tocpos = struct.unpack('<Q',filedata[0xb:0x13])[0]
  39.     compchk = struct.unpack('<B',filedata[tocpos:tocpos+1])[0]
  40.  
  41.     toccomplen = struct.unpack('<Q',filedata[tocpos+1:tocpos+1+8])[0]
  42.     if compchk == 1:
  43.         tocuncomplen = struct.unpack('<Q',filedata[tocpos+1+8:tocpos+1+8+8])[0]
  44.         tocpos += 17
  45.         toc = zlib.decompress(filedata[tocpos:tocpos+toccomplen])
  46.     else:
  47.         tocpos += 9
  48.         toc = filedata[tocpos:tocpos+toccomplen]
  49.  
  50.     pos = 0
  51.     filecnt = 0
  52.     while pos < len(toc):
  53.         filelen = struct.unpack('<Q',toc[pos+4:pos+4+8])[0]
  54.         pos += 12
  55.         endpos = pos+filelen
  56.         while pos < endpos:
  57.             if toc[pos:pos+4] == 'info':
  58.                 infolen = struct.unpack('<Q',toc[pos+4:pos+4+8])[0]
  59.                 pos += 12
  60.                 encryptchk = struct.unpack('<I',toc[pos:pos+4])[0]
  61.                 uncompsize = struct.unpack('<Q',toc[pos+4:pos+12])[0]
  62.                 compsize = struct.unpack('<Q',toc[pos+12:pos+20])[0]
  63.                 filenamelen = struct.unpack('<H',toc[pos+20:pos+22])[0]
  64.                 pos += 22
  65.  
  66.                 filename = toc[pos:pos+filenamelen*2]
  67.                 filename = filename.decode('utf-16')
  68.                 if filename.find('$$$') != -1:
  69.                     filename = '$$$ This is a protected archive $$$.txt'
  70.  
  71.                 print 'Extracting %s' % filename
  72.                 pos += filenamelen*2
  73.                 while toc[pos:pos+1] == '\x00':
  74.                     pos += 1
  75.                
  76.             elif toc[pos:pos+4] == 'segm':
  77.                 segmentcnt = struct.unpack('<Q',toc[pos+4:pos+4+8])[0] / 28
  78.                 pos += 12
  79.                 segments = []
  80.                 for i in range(0,segmentcnt):
  81.                     segcompchk = struct.unpack('<I',toc[pos:pos+4])[0]
  82.                     segoffset = struct.unpack('<Q',toc[pos+4:pos+12])[0]
  83.                     seguncompsize = struct.unpack('<Q',toc[pos+12:pos+20])[0]
  84.                     segcompsize = struct.unpack('<Q',toc[pos+20:pos+28])[0]
  85.                     segments.append([segcompchk,segoffset,seguncompsize,segcompsize])
  86.                     pos += 28
  87.                
  88.             elif toc[pos:pos+4] == 'adlr':
  89.                 adlr = struct.unpack('<I',toc[pos+0xc:pos+0xc+4])[0]
  90.                 pos += 0xc+4
  91.  
  92.             elif toc[pos:pos+4] == 'time':
  93.                 pos += 12 + struct.unpack('<Q',toc[pos+4:pos+12])[0]
  94.  
  95.             else:
  96.                 print 'Unknown .xp3 file type %s at pos %x in file %s' % (toc[pos:pos+4],pos,filenam)
  97.                 sys.exit()
  98.            
  99.         newfiledata = ''
  100.        
  101.         for i in range(0,segmentcnt):
  102.             if segments[i][0] == 0x1:
  103.                 newfiledata += zlib.decompress(filedata[segments[i][1]:segments[i][1]+segments[i][3]])
  104.             else:
  105.                 newfiledata += filedata[segments[i][1]:segments[i][1]+segments[i][3]]
  106.  
  107.         startdecryptpos = 5
  108.         scenariofile = False
  109.         if (newfiledata[:1] == '\xff' and newfiledata[1:2] == '\xfe'):
  110.             newfiledata = newfiledata[2:]
  111.             startdecryptpos = 3
  112.         elif (newfiledata[:1] == '\xfe' and newfiledata[1:2] == '\xfe'):
  113.             if ord(newfiledata[2:3]) == 0x2:
  114.                 newfiledata = zlib.decompress(newfiledata[0x5:])
  115.                 startdecryptpos = 0
  116.             else:
  117.                 newfiledata = newfiledata[5:]
  118.                 startdecryptpos = 0
  119.                 scenariofile = True
  120.        
  121.         #Encrypt var broken, just use adlr instead
  122.         if (adlr != zlib.adler32(newfiledata) & 0xFFFFFFFF) and (filename.find('$$$') == -1):
  123.             newfiledata = decrypt(bytearray(newfiledata),adlr,startdecryptpos)
  124.             if scenariofile == True:
  125.                 newfiledata = decrypt_scenario(newfiledata)      
  126.  
  127.         if not os.path.isdir(sys.argv[2].split('.',1)[0]):
  128.             os.mkdir(sys.argv[2].split('.',1)[0])
  129.            
  130.         filepath = filename.split('/')
  131.         newfolder = ''
  132.         currpath = sys.argv[2].split('.',1)[0]
  133.                              
  134.         for i in range(0,len(filepath)-1):
  135.             if filepath[i] != '':
  136.                 if not os.path.isdir(currpath + '\\' + filepath[i]):
  137.                     os.mkdir(currpath + '\\' + filepath[i])
  138.             currpath += '\\' + filepath[i]
  139.  
  140.  
  141.         outfile = open(currpath + '\\' + filepath[len(filepath)-1],'wb')
  142.         outfile.write(newfiledata)
  143.         outfile.close()
  144.        
  145.         filecnt += 1
  146.  
  147. def compile_xp3(infolder):
  148.     toc = ''
  149.     tochdr = '\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
  150.     #new ver
  151.     newfiledata = '\x58\x50\x33\x0D\x0A\x20\x0A\x1A\x8B\x67\x01\x17\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00'
  152.     #old ver
  153.     #newfiledata = '\x58\x50\x33\x0D\x0A\x20\x0A\x1A\x8B\x67\x01'
  154.     newfiledata += '\x00\x00\x00\x00\x00\x00\x00\x00' #toc loc
  155.     #don't need this protect file in old ver
  156.     newfiledata += '\x89\x50\x4E\x47\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53\xDE\x00\x00\x00\xA5\x74\x45\x58\x74\x57\x61\x72\x6E\x69\x6E\x67\x00'
  157.  
  158.     for root, dirs, files in os.walk(infolder):
  159.         for filename in files:
  160.             filedata = get_data(os.path.join(root,filename))
  161.             uncompfilesize = len(filedata)
  162.             adler = zlib.adler32(filedata) & 0xFFFFFFFF
  163.            
  164.             if filename.find('$$$') == -1:
  165.                 filedata = ''.join(map(chr,decrypt(bytearray(filedata),adler)))
  166.                 protectedfile = False
  167.             else:
  168.                 protectedfile = True
  169.                
  170.             if filename.find('$$$') == -1:
  171.                 notcompressed = False
  172.                 filedata = zlib.compress(filedata,9)
  173.             else:
  174.                 notcompressed = True
  175.                
  176.             compfilesize = len(filedata)
  177.  
  178.             filename1 = ''.join(os.path.join(root,filename)).encode('utf-16')
  179.             filename1 = filename1[(len(sys.argv[2])*2)+4:]
  180.             filename1 = filename1.replace('\\','/')
  181.             #print filename1
  182.  
  183.             if protectedfile == False:
  184.                 #new ver
  185.                 tmpinfo = struct.pack('<I',0x80000000) #encryption flag
  186.                 #old ver
  187.                 #tmpinfo = struct.pack('<I',0x00000000) #encryption flag
  188.             else:
  189.                 tmpinfo = struct.pack('<I',0x0) #encryption flag
  190.             tmpinfo += struct.pack('<Q',uncompfilesize) #uncomp filesize
  191.             tmpinfo += struct.pack('<Q',compfilesize) #comp filesize
  192.             tmpinfo += struct.pack('<H',len(filename1) / 2) #filename len
  193.             tmpinfo += filename1
  194.            
  195.             tmpsegm = 'segm'
  196.             tmpsegm += struct.pack('<Q',0x1c)
  197.             if notcompressed == False:
  198.                 tmpsegm += struct.pack('<I',0x1) #comp flag
  199.             else:
  200.                 tmpsegm += struct.pack('<I',0x0) #comp flag
  201.             tmpsegm += struct.pack('<Q',len(newfiledata)) #file offset
  202.             tmpsegm += struct.pack('<Q',uncompfilesize) #uncomp filesize
  203.             tmpsegm += struct.pack('<Q',compfilesize) #comp filesize
  204.            
  205.             tmpadlr = 'adlr'
  206.             tmpadlr += struct.pack('<Q',0x4)
  207.             tmpadlr += struct.pack('<I',adler)
  208.            
  209.             tmpfile = 'File'
  210.             tmpfile += struct.pack('<Q',len(tmpinfo)+12+len(tmpsegm)+len(tmpadlr)) #File section len
  211.             tmpfile += 'info'
  212.             tmpfile += struct.pack('<Q',len(tmpinfo)) #info section len
  213.  
  214.             toc += tmpfile + tmpinfo + tmpsegm + tmpadlr
  215.             newfiledata += filedata
  216.  
  217.     tochdr = tochdr[:9] + struct.pack('<Q',len(toc))
  218.     toc = zlib.compress(toc,9)
  219.     tochdr = tochdr[:1] + struct.pack('<Q',len(toc)) + tochdr[9:]
  220.  
  221.     #new ver
  222.     newfiledata = newfiledata[:0x20] + struct.pack('<Q',len(newfiledata)) + newfiledata[0x28:]
  223.     #old ver
  224.     #newfiledata = newfiledata[:0xb] + struct.pack('<Q',len(newfiledata)) + newfiledata[0x13:]
  225.     newfiledata += tochdr + toc
  226.     outfile = open(infolder + '.xp3','wb')
  227.     outfile.write(newfiledata)
  228.     outfile.close()
  229.  
  230. if __name__ == '__main__':
  231.     if sys.argv[1] == '-e':
  232.         extract_xp3(sys.argv[2])
  233.     elif sys.argv[1] == '-c':
  234.         compile_xp3(sys.argv[2])
  235.     else:
  236.         print 'Usage: -e/-c <filename/foldername>'
  237.         print '-e: Extract .xp3 archive'
  238.         print '-c: Compile a folder to .xp3 archive'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement