Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os,sys,struct
- def get_data(filename):
- totalbytes = os.path.getsize(filename)
- infile = open(filename, 'rb')
- totalfiledata = infile.read(totalbytes)
- return totalfiledata
- def extract_linkdata(filename):
- filedata = open(filename,'rb')
- if not os.path.exists(filename.rsplit('.',1)[0]):
- os.mkdir(filename.rsplit('.',1)[0])
- filecnt = struct.unpack('<I',filedata.read(4))[0]
- for i in range(0,filecnt):
- print 'Extracting file %d' % i
- filepos = struct.unpack('<I',filedata.read(4))[0]
- filelen = struct.unpack('<I',filedata.read(4))[0]
- currpos = filedata.tell()
- filedata.seek(filepos,0)
- outfile = open(filename.rsplit('.',1)[0] + '\\%d' % i,'wb')
- outfile.write(filedata.read(filelen))
- outfile.close()
- filedata.seek(currpos,0)
- return
- def compile_linkdata_full(foldername):
- newfiledata = ''
- newfiles = ''
- outfile = open(foldername + '_new.bin','wb')
- outfile.close()
- filecnt = 0
- for root, dirs, files in os.walk(foldername):
- for filename in files:
- filecnt += 1
- newfiledata += struct.pack('<I',filecnt)
- datapos = (filecnt*0x8) + 0x4
- while datapos % 0x800 != 00:
- datapos += 4
- outfile = open(foldername + '_new.bin','ab')
- newdatasize = 0
- for root, dirs, files in os.walk(foldername):
- for filename in sorted(files,key=int):
- print 'Adding %s' % filename
- filedata = get_data(root + '\\' + filename)
- newfiledata += struct.pack('<I',datapos+newdatasize)
- newfiledata += struct.pack('<I',len(filedata))
- while len(filedata) % 0x800 != 0:
- filedata += '\x00'
- newdatasize += len(filedata)
- outfile.write(filedata)
- filedata = None
- outfile.close()
- while len(newfiledata) < datapos:
- newfiledata += '\x00\x00\x00\x00'
- filedata = get_data(foldername + '_new.bin')
- outfile = open(foldername + '_new.bin','wb')
- outfile.write(newfiledata + filedata)
- outfile.close()
- return
- def append_linkdata(foldername,binname):
- filedata = get_data(binname)
- for root, dirs, files in os.walk(foldername):
- for filename in sorted(files,key=int):
- print 'Appending %s' % filename
- newfiledata = get_data(root + '\\' + filename)
- filepos = (int(filename)*0x8) + 4
- filedata = filedata[:filepos] + struct.pack('<I',len(filedata)) + struct.pack('<I',len(newfiledata)) + filedata[filepos+0x8:]
- while len(newfiledata) % 0x800 != 0:
- newfiledata += '\x00'
- filedata += newfiledata
- outfile = open(binname,'wb')
- outfile.write(filedata)
- outfile.close()
- return
- def extract_text(filedata):
- datatypecount = struct.unpack('<H',filedata[0x2:0x4])[0]
- entrycount = struct.unpack('<H',filedata[0x4:0x6])[0]
- datablocksize = struct.unpack('<H',filedata[0x6:0x8])[0]
- tablesizelowerword = struct.unpack('<H',filedata[0x8:0xa])[0]
- tablesizeupperword = struct.unpack('<H',filedata[0xa:0xc])[0]
- headersize = struct.unpack('<I',filedata[0xc:0x10])[0]
- datatypes = []
- strings = 'data_types = { '
- for i in range(0x10,0x10+datatypecount):
- datatypes.append(struct.unpack('<B',filedata[i:i+1])[0])
- strings += '%x ' % struct.unpack('<B',filedata[i:i+1])[0]
- strings += '}\n'
- pos = headersize
- strcnt = 0
- while pos < headersize+(entrycount*datablocksize):
- lenmoved = 0
- totalstr = ''
- strings += '='*20 + '\n' + (' %d\n' % strcnt) + '='*20 + '\n'
- for a in range(0,len(datatypes)):
- if datatypes[a] == 0:
- var = struct.unpack('<I',filedata[pos+lenmoved:pos+lenmoved+4])[0]
- if int(sys.argv[2]) < 10:
- string = filedata[headersize + var:filedata.find('\x00',headersize + var)]
- else:
- if lenmoved == 0:
- #name
- string = filedata[headersize + var:filedata.find('\x00',headersize + var)]
- elif lenmoved == 4:
- #string
- string = filedata[headersize + var:filedata.find('\x00',headersize + var)]
- string = string.replace('\x1b\x4e','[player]')
- while string.find('\x1b\x43') != -1:
- string = string.replace('\x1b\x43','[1b43%x]+' % struct.unpack('<B',string[string.find('\x1b\x43')+2:string.find('\x1b\x43')+3])[0])
- while string.find(']+') != -1:
- string = string[:string.find(']+')+1] + string[string.find(']+')+3:]
- string = string.replace('\x1b\x52','[1b52]')
- while string.find('\x1b\x54') != -1:
- string = string.replace('\x1b\x54','[1b54%x]+' % struct.unpack('<B',string[string.find('\x1b\x54')+2:string.find('\x1b\x54')+3])[0])
- while string.find(']+') != -1:
- string = string[:string.find(']+')+1] + string[string.find(']+')+3:]
- string = string.replace('\x1b\x58','[/colour]')
- strings += ('%s\n------\n' % string)
- lenmoved += 4
- elif datatypes[a] == 2:
- var = struct.unpack('<H',filedata[pos+lenmoved:pos+lenmoved+2])[0]
- strings += '%x\n' % var
- lenmoved += 2
- else:
- print 'Unknown data type: %x' % datatypes[a]
- sys.exit()
- strings += '\n'
- strcnt += 1
- pos += lenmoved
- return strings
- def extract_multitable(filedata,filename):
- tablecount = struct.unpack('<I',filedata[:4])[0]
- filepos = (tablecount * 0x4) + 0x4
- while filepos % 0x10 != 0:
- filepos += 4
- strings = ''
- sectioncnt = 1
- for i in range(0x4,0x4+(tablecount*0x4),0x4):
- strings += '='*30 + '\n' + ('== Section %d ==' % sectioncnt) + '\n' + '='*30 + '\n\n'
- if i+0x4 == 0x4+(tablecount*0x4):
- filelen = len(filedata)
- else:
- filelen = struct.unpack('<I',filedata[i:i+0x4])[0] * 0x10
- strings += extract_text(filedata[filepos:filepos+filelen])
- sectioncnt += 1
- filepos += filelen
- outfile = open(filename.rsplit('.',1)[0] + '.txt','wb')
- outfile.write(strings)
- outfile.close()
- return
- def compile_strings(filedata):
- datatypes = []
- datas = filedata[0].split('{')[1].split(' ')
- datas.pop(0)
- datas.pop(len(datas)-1)
- datablocksize = 0
- for i in range(0,len(datas)):
- datatype = int(datas[i],16)
- datatypes.append(datatype)
- if datatype == 0:
- datablocksize += 4
- elif datatype == 2:
- datablocksize += 2
- else:
- print 'Unknown type %x' % datatype
- filedata.pop(0)
- newfiledata = '\x4c\x14' + struct.pack('<H',len(datas)) + struct.pack('<H',0x0) + struct.pack('<H',datablocksize)
- newfiledata += struct.pack('<H',0x0) + struct.pack('<H',0x0) + struct.pack('<I',0x0)
- for i in range(0,len(datatypes)):
- newfiledata += struct.pack('<B',datatypes[i])
- while len(newfiledata) % 0x4 != 0:
- newfiledata += '\xFF'
- newfiledata = newfiledata[:0xc] + struct.pack('<I',len(newfiledata)) + newfiledata[0x10:]
- toclen = len(newfiledata)
- fixlocs = []
- entrycnt = 0
- i = 0
- while i < len(filedata):
- if filedata[i] != '' and filedata[i].find('===') != -1:
- if filedata[i+1].find('== Section') != -1:
- break;
- i += 3
- for a in range(0,len(datatypes)):
- if datatypes[a] == 0:
- #dword
- #get a string
- string = ''
- #print 'string line %d line: %s' % (i,filedata[i])
- while filedata[i].find('------') == -1:
- string += filedata[i] + '\x0a'
- i += 1
- string = string[:-1]
- #print 'AFTER string line %d line: %s' % (i,filedata[i])
- string = string.replace('[player]','\x1b\x4e')
- string = string.replace('[/colour]','\x1b\x58')
- while string.find('[1b54') != -1:
- strfindpos = string.find('[1b54') + 5
- val = ''
- while string[strfindpos] != ']':
- val += string[strfindpos]
- strfindpos += 1
- val = int(val,16)
- nstring = string[:string.find('[1b54')] + '\x1b\x54' + struct.pack('<B',val) + string[strfindpos+1:]
- string = nstring
- while string.find('[1b43') != -1:
- strfindpos = string.find('[1b43') + 5
- val = ''
- while string[strfindpos] != ']':
- val += string[strfindpos]
- strfindpos += 1
- val = int(val,16)
- nstring = string[:string.find('[1b43')] + '\x1b\x43' + struct.pack('<B',val) + string[strfindpos+1:]
- string = nstring
- string = string.replace('[1b52]','\x1b\x52')
- fixlocs.append([len(newfiledata),string])
- newfiledata += struct.pack('<I',0x0) # fix placeholder
- elif datatypes[a] == 2:
- #word
- newfiledata += struct.pack('<H',int(filedata[i],16))
- i += 1
- entrycnt += 1
- i += 1
- strings = ''
- for i in range(0,len(fixlocs)):
- newfiledata = newfiledata[:fixlocs[i][0]] + struct.pack('<I',len(newfiledata)+len(strings)-toclen) + newfiledata[fixlocs[i][0]+0x4:]
- strings += fixlocs[i][1] + '\x00'
- 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:]
- return newfiledata + strings
- def compile_multitable(filedata):
- filedata = filedata.split(' ==\n')
- filedata.pop(0)
- toc = struct.pack('<I',len(filedata))
- for i in range(0,len(filedata)):
- toc += struct.pack('<I',0x0)
- fileloc = (len(filedata) * 0x4) + 0x4
- while fileloc % 0x10 != 0:
- fileloc += 4
- nnewfiledata = ''
- for i in range(0,len(filedata)):
- tmpdata = filedata[i].splitlines()
- tmpdata.pop(0)
- tmpdata.pop(0)
- newfiledata = compile_strings(tmpdata)
- while (len(toc) + len(newfiledata)) % 0x10 != 0:
- newfiledata += '\x00'
- nnewfiledata += newfiledata
- toc = toc[:0x4+(i*0x4)] + struct.pack('<I',(len(newfiledata) / 0x10)) + toc[0x4+(i*0x4)+0x4:]
- return toc + nnewfiledata
- if __name__ == '__main__':
- if sys.argv[1] == '-e1':
- extract_linkdata(sys.argv[2])
- elif sys.argv[1] == '-e2':
- filedata = get_data(sys.argv[2])
- if filedata[:2] == '\x4c\x14':
- strings = extract_text(filedata)
- outfile = open(sys.argv[2].rsplit('.',1)[0] + '.txt','wb')
- outfile.write(strings)
- outfile.close()
- else:
- extract_multitable(filedata,sys.argv[2])
- elif sys.argv[1] == '-c1':
- append_linkdata(sys.argv[2],sys.argv[3])
- elif sys.argv[1] == '-c2':
- compile_linkdata_full(sys.argv[2])
- elif sys.argv[1] == '-a1':
- filedata = get_data(sys.argv[2])
- if filedata[:0xa] == 'data_types':
- newfiledata = compile_strings(filedata.splitlines())
- else:
- newfiledata = compile_multitable(filedata)
- outfile = open(sys.argv[2].rsplit('.',1)[0] + '_new','wb')
- outfile.write(newfiledata)
- outfile.close()
- else:
- print 'Arg error'
- sys.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement