Advertisement
Guest User

Untitled

a guest
Jan 12th, 2015
475
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.35 KB | None | 0 0
  1. import os,sys,struct
  2.  
  3. def get_data(filename):
  4.     totalbytes = os.path.getsize(filename)
  5.     infile = open(filename, 'rb')
  6.     totalfiledata = infile.read(totalbytes)
  7.     return totalfiledata
  8.  
  9. def extract_linkdata(filename):
  10.     filedata = open(filename,'rb')
  11.     if not os.path.exists(filename.rsplit('.',1)[0]):
  12.         os.mkdir(filename.rsplit('.',1)[0])
  13.     filecnt = struct.unpack('<I',filedata.read(4))[0]
  14.  
  15.     for i in range(0,filecnt):
  16.         print 'Extracting file %d' % i
  17.         filepos = struct.unpack('<I',filedata.read(4))[0]
  18.         filelen = struct.unpack('<I',filedata.read(4))[0]
  19.  
  20.         currpos = filedata.tell()
  21.         filedata.seek(filepos,0)
  22.  
  23.         outfile = open(filename.rsplit('.',1)[0] + '\\%d' % i,'wb')
  24.         outfile.write(filedata.read(filelen))
  25.         outfile.close()
  26.  
  27.         filedata.seek(currpos,0)
  28.     return
  29.  
  30. def compile_linkdata_full(foldername):
  31.     newfiledata = ''
  32.     newfiles = ''
  33.     outfile = open(foldername + '_new.bin','wb')
  34.     outfile.close()
  35.    
  36.     filecnt = 0
  37.     for root, dirs, files in os.walk(foldername):
  38.         for filename in files:
  39.             filecnt += 1
  40.  
  41.     newfiledata += struct.pack('<I',filecnt)
  42.     datapos = (filecnt*0x8) + 0x4
  43.     while datapos % 0x800 != 00:
  44.         datapos += 4
  45.  
  46.     outfile = open(foldername + '_new.bin','ab')
  47.     newdatasize = 0
  48.     for root, dirs, files in os.walk(foldername):
  49.         for filename in sorted(files,key=int):
  50.             print 'Adding %s' % filename
  51.             filedata = get_data(root + '\\' + filename)
  52.             newfiledata += struct.pack('<I',datapos+newdatasize)
  53.             newfiledata += struct.pack('<I',len(filedata))
  54.  
  55.             while len(filedata) % 0x800 != 0:
  56.                 filedata += '\x00'
  57.             newdatasize += len(filedata)
  58.  
  59.             outfile.write(filedata)
  60.             filedata = None
  61.     outfile.close()
  62.     while len(newfiledata) < datapos:
  63.         newfiledata += '\x00\x00\x00\x00'
  64.     filedata = get_data(foldername + '_new.bin')
  65.     outfile = open(foldername + '_new.bin','wb')
  66.     outfile.write(newfiledata + filedata)
  67.     outfile.close()
  68.            
  69.     return
  70.  
  71. def append_linkdata(foldername,binname):
  72.     filedata = get_data(binname)
  73.     for root, dirs, files in os.walk(foldername):
  74.         for filename in sorted(files,key=int):
  75.             print 'Appending %s' % filename
  76.             newfiledata = get_data(root + '\\' + filename)
  77.            
  78.             filepos = (int(filename)*0x8) + 4
  79.             filedata = filedata[:filepos] + struct.pack('<I',len(filedata)) + struct.pack('<I',len(newfiledata)) + filedata[filepos+0x8:]
  80.  
  81.             while len(newfiledata) % 0x800 != 0:
  82.                 newfiledata += '\x00'
  83.  
  84.             filedata += newfiledata
  85.  
  86.     outfile = open(binname,'wb')
  87.     outfile.write(filedata)
  88.     outfile.close()
  89.    
  90.     return
  91.  
  92. def extract_text(filedata):
  93.     datatypecount = struct.unpack('<H',filedata[0x2:0x4])[0]
  94.     entrycount = struct.unpack('<H',filedata[0x4:0x6])[0]
  95.     datablocksize = struct.unpack('<H',filedata[0x6:0x8])[0]
  96.     tablesizelowerword = struct.unpack('<H',filedata[0x8:0xa])[0]
  97.     tablesizeupperword = struct.unpack('<H',filedata[0xa:0xc])[0]
  98.     headersize = struct.unpack('<I',filedata[0xc:0x10])[0]
  99.  
  100.     datatypes = []
  101.     strings = 'data_types = { '
  102.     for i in range(0x10,0x10+datatypecount):
  103.         datatypes.append(struct.unpack('<B',filedata[i:i+1])[0])
  104.         strings += '%x ' % struct.unpack('<B',filedata[i:i+1])[0]
  105.     strings += '}\n'
  106.  
  107.     pos = headersize
  108.    
  109.     strcnt = 0
  110.     while pos < headersize+(entrycount*datablocksize):
  111.         lenmoved = 0
  112.         totalstr = ''
  113.         strings += '='*20 + '\n' + (' %d\n' % strcnt) + '='*20 + '\n'
  114.         for a in range(0,len(datatypes)):
  115.             if datatypes[a] == 0:
  116.                
  117.                 var = struct.unpack('<I',filedata[pos+lenmoved:pos+lenmoved+4])[0]
  118.                 if int(sys.argv[2]) < 10:
  119.                     string = filedata[headersize + var:filedata.find('\x00',headersize + var)]
  120.                 else:
  121.                     if lenmoved == 0:
  122.                         #name
  123.                         string = filedata[headersize + var:filedata.find('\x00',headersize + var)]
  124.                     elif lenmoved == 4:
  125.                         #string
  126.                         string = filedata[headersize + var:filedata.find('\x00',headersize + var)]
  127.                         string = string.replace('\x1b\x4e','[player]')
  128.                        
  129.                         while string.find('\x1b\x43') != -1:
  130.                             string = string.replace('\x1b\x43','[1b43%x]+' % struct.unpack('<B',string[string.find('\x1b\x43')+2:string.find('\x1b\x43')+3])[0])
  131.                             while string.find(']+') != -1:
  132.                                 string = string[:string.find(']+')+1] + string[string.find(']+')+3:]
  133.                         string = string.replace('\x1b\x52','[1b52]')
  134.                        
  135.                         while string.find('\x1b\x54') != -1:
  136.                             string = string.replace('\x1b\x54','[1b54%x]+' % struct.unpack('<B',string[string.find('\x1b\x54')+2:string.find('\x1b\x54')+3])[0])
  137.                             while string.find(']+') != -1:
  138.                                 string = string[:string.find(']+')+1] + string[string.find(']+')+3:]
  139.                         string = string.replace('\x1b\x58','[/colour]')
  140.  
  141.                 strings += ('%s\n------\n' % string)
  142.                 lenmoved += 4
  143.             elif datatypes[a] == 2:
  144.                 var = struct.unpack('<H',filedata[pos+lenmoved:pos+lenmoved+2])[0]
  145.                 strings += '%x\n' % var
  146.                 lenmoved += 2
  147.             else:
  148.                 print 'Unknown data type: %x' % datatypes[a]
  149.                 sys.exit()
  150.         strings += '\n'
  151.         strcnt += 1
  152.         pos += lenmoved
  153.  
  154.     return strings
  155.  
  156. def extract_multitable(filedata,filename):
  157.     tablecount = struct.unpack('<I',filedata[:4])[0]
  158.     filepos = (tablecount * 0x4) + 0x4
  159.     while filepos % 0x10 != 0:
  160.         filepos += 4
  161.  
  162.     strings = ''
  163.     sectioncnt = 1
  164.     for i in range(0x4,0x4+(tablecount*0x4),0x4):
  165.         strings += '='*30 + '\n' + ('== Section %d ==' % sectioncnt) + '\n' + '='*30 + '\n\n'
  166.  
  167.         if i+0x4 == 0x4+(tablecount*0x4):
  168.             filelen = len(filedata)
  169.         else:
  170.             filelen = struct.unpack('<I',filedata[i:i+0x4])[0] * 0x10
  171.  
  172.         strings += extract_text(filedata[filepos:filepos+filelen])
  173.         sectioncnt += 1
  174.         filepos += filelen
  175.                                    
  176.     outfile = open(filename.rsplit('.',1)[0] + '.txt','wb')
  177.     outfile.write(strings)
  178.     outfile.close()
  179.    
  180.     return
  181.  
  182. def compile_strings(filedata):
  183.     datatypes = []
  184.     datas = filedata[0].split('{')[1].split(' ')
  185.     datas.pop(0)
  186.     datas.pop(len(datas)-1)
  187.     datablocksize = 0
  188.     for i in range(0,len(datas)):
  189.         datatype = int(datas[i],16)
  190.         datatypes.append(datatype)
  191.         if datatype == 0:
  192.             datablocksize += 4
  193.         elif datatype == 2:
  194.             datablocksize += 2
  195.         else:
  196.             print 'Unknown type %x' % datatype
  197.     filedata.pop(0)
  198.  
  199.    
  200.     newfiledata = '\x4c\x14' + struct.pack('<H',len(datas)) + struct.pack('<H',0x0) + struct.pack('<H',datablocksize)
  201.     newfiledata += struct.pack('<H',0x0) + struct.pack('<H',0x0) + struct.pack('<I',0x0)
  202.     for i in range(0,len(datatypes)):
  203.         newfiledata += struct.pack('<B',datatypes[i])
  204.     while len(newfiledata) % 0x4 != 0:
  205.         newfiledata += '\xFF'
  206.     newfiledata = newfiledata[:0xc] + struct.pack('<I',len(newfiledata)) + newfiledata[0x10:]
  207.     toclen = len(newfiledata)
  208.    
  209.     fixlocs = []
  210.     entrycnt = 0
  211.     i = 0
  212.     while i < len(filedata):
  213.         if filedata[i] != '' and filedata[i].find('===') != -1:
  214.             if filedata[i+1].find('== Section') != -1:
  215.                 break;
  216.             i += 3
  217.             for a in range(0,len(datatypes)):
  218.                 if datatypes[a] == 0:
  219.                     #dword
  220.                     #get a string
  221.                     string = ''
  222.                     #print 'string line %d line: %s' % (i,filedata[i])
  223.                     while filedata[i].find('------') == -1:
  224.                         string += filedata[i] + '\x0a'
  225.                         i += 1
  226.                     string = string[:-1]
  227.                     #print 'AFTER string line %d line: %s' % (i,filedata[i])
  228.                     string = string.replace('[player]','\x1b\x4e')
  229.                     string = string.replace('[/colour]','\x1b\x58')
  230.  
  231.                     while string.find('[1b54') != -1:
  232.                         strfindpos = string.find('[1b54') + 5
  233.                         val = ''
  234.                         while string[strfindpos] != ']':
  235.                             val += string[strfindpos]
  236.                             strfindpos += 1
  237.                         val = int(val,16)
  238.                        
  239.                         nstring = string[:string.find('[1b54')] + '\x1b\x54' + struct.pack('<B',val) + string[strfindpos+1:]
  240.                         string = nstring
  241.  
  242.                     while string.find('[1b43') != -1:
  243.                         strfindpos = string.find('[1b43') + 5
  244.                         val = ''
  245.                         while string[strfindpos] != ']':
  246.                             val += string[strfindpos]
  247.                             strfindpos += 1
  248.                         val = int(val,16)
  249.                        
  250.                         nstring = string[:string.find('[1b43')] + '\x1b\x43' + struct.pack('<B',val) + string[strfindpos+1:]
  251.                         string = nstring
  252.                        
  253.                     string = string.replace('[1b52]','\x1b\x52')
  254.                     fixlocs.append([len(newfiledata),string])
  255.                     newfiledata += struct.pack('<I',0x0) # fix placeholder
  256.                    
  257.                 elif datatypes[a] == 2:
  258.                     #word
  259.                     newfiledata += struct.pack('<H',int(filedata[i],16))
  260.                 i += 1
  261.             entrycnt += 1
  262.         i += 1
  263.  
  264.     strings = ''
  265.     for i in range(0,len(fixlocs)):
  266.         newfiledata = newfiledata[:fixlocs[i][0]] + struct.pack('<I',len(newfiledata)+len(strings)-toclen) + newfiledata[fixlocs[i][0]+0x4:]
  267.         strings += fixlocs[i][1] + '\x00'
  268.  
  269.     newfiledata = newfiledata[:0x4] + struct.pack('<H',entrycnt) + newfiledata[0x6:0x8] + struct.pack('<H',len(newfiledata)+len(strings) & 0xFFFF) + struct.pack('<H',len(newfiledata)+len(strings) >> 16) + newfiledata[0xc:]
  270.     return newfiledata + strings
  271.  
  272. def compile_multitable(filedata):
  273.     filedata = filedata.split(' ==\n')
  274.     filedata.pop(0)
  275.     toc = struct.pack('<I',len(filedata))
  276.     for i in range(0,len(filedata)):
  277.         toc += struct.pack('<I',0x0)
  278.     fileloc = (len(filedata) * 0x4) + 0x4
  279.     while fileloc % 0x10 != 0:
  280.         fileloc += 4
  281.  
  282.     nnewfiledata = ''
  283.     for i in range(0,len(filedata)):
  284.         tmpdata = filedata[i].splitlines()
  285.         tmpdata.pop(0)
  286.         tmpdata.pop(0)
  287.         newfiledata = compile_strings(tmpdata)
  288.         while (len(toc) + len(newfiledata)) % 0x10 != 0:
  289.             newfiledata += '\x00'
  290.         nnewfiledata += newfiledata
  291.         toc = toc[:0x4+(i*0x4)] + struct.pack('<I',(len(newfiledata) / 0x10)) + toc[0x4+(i*0x4)+0x4:]
  292.  
  293.     return toc + nnewfiledata
  294.  
  295. if __name__ == '__main__':
  296.     if sys.argv[1] == '-e1':
  297.         extract_linkdata(sys.argv[2])
  298.     elif sys.argv[1] == '-e2':
  299.         filedata = get_data(sys.argv[2])
  300.         if filedata[:2] == '\x4c\x14':
  301.             strings = extract_text(filedata)
  302.             outfile = open(sys.argv[2].rsplit('.',1)[0] + '.txt','wb')
  303.             outfile.write(strings)
  304.             outfile.close()
  305.         else:
  306.             extract_multitable(filedata,sys.argv[2])
  307.     elif sys.argv[1] == '-c1':
  308.         append_linkdata(sys.argv[2],sys.argv[3])
  309.     elif sys.argv[1] == '-c2':
  310.         compile_linkdata_full(sys.argv[2])
  311.     elif sys.argv[1] == '-a1':
  312.         filedata = get_data(sys.argv[2])
  313.         if filedata[:0xa] == 'data_types':
  314.             newfiledata = compile_strings(filedata.splitlines())
  315.         else:
  316.             newfiledata = compile_multitable(filedata)
  317.         outfile = open(sys.argv[2].rsplit('.',1)[0] + '_new','wb')
  318.         outfile.write(newfiledata)
  319.         outfile.close()
  320.     else:
  321.         print 'Arg error'
  322.         sys.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement