Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #How to use
- #Need shared.bin in the same folder as this tool and run. That's it.
- import struct
- import zlib
- ARCHIVE_TOC_POS = 0x17da00
- def I(f, offset = -1): #Function is supposed to unpack a 32-bit integer from a file-like object or from a bytes-like object
- if hasattr(f, 'read'): #File-like object
- if offset == -1: #If no 2nd parameter
- return struct.unpack('<I', f.read(4))[0] #Read data at current position
- else: #2nd parameter was specified
- origpos = f.tell() #Save original position
- f.seek(offset) #Go to specified position
- val = struct.unpack('<I', f.read(4))[0] #Read data
- f.seek(origpos) #Go back to original position
- return val
- elif isinstance(f, bytes): #Bytes-like object
- if len(f[offset:offset+4]) != 4: #Checking for EOF error
- raise Exception('Not enough data in file.')
- return struct.unpack('<I', f[offset:offset+4])[0] #Unpack data
- else: #Not a file or bytes object
- raise Exception('Unknown object type.')
- ptrs1 = [] #Archive TOC data container
- with open('shared.orig','rb') as f:
- #Stores the archive TOC data
- f.seek(ARCHIVE_TOC_POS + 4) #Go to entry for # of files
- num_of_files = I(f)
- for x in range(num_of_files): #Read TOC entries
- offset = I(f) #Offset 1st
- f.seek(4, 1) #We don't care about unzipped size (so seek past it)
- size = I(f) #Zipped size last
- ptrs1.append((offset, size))
- #This is the part that unpacks each file
- for i, (offset, size) in enumerate(ptrs1): #Loop over the list of TOC data
- #The offset and the zipped size are stored in the TOC data
- f.seek(ARCHIVE_TOC_POS + offset) #Go to data position
- filedata = zlib.decompress(f.read(size)) #Decompress data
- #The rest of these steps work with the decompressed data
- num_of_pointers = I(filedata, 0x38) #How many strings are in the file
- text_addr = I(filedata, 0x4c) #Where is the text located
- pos = I(filedata, 0x44) #Where is the text TOC located
- ptrs2 = [] #Container for text TOC data
- for x in range(num_of_pointers): #Repeat for as many times as there are strings in the text data
- ptrs2.append(I(filedata, pos)) #Save the pointer
- pos += 4
- filedata = filedata[text_addr:] #Cut off everything that isn't the text
- #Pointers are relative to start of text
- output = [] #Container for outputted data
- for ptr in ptrs2: #For each string pointer
- output.append(hex(ptr) + '\t') #Store position to output
- s = filedata[ptr:filedata.find(b'\x00',ptr)].decode('cp932') #Get the string
- lines = s.split('@') #Split by @ which is the game substring marker
- output.append(lines.pop(0) + '\t') #Add the "name" info (really 1st substring)
- for line in lines: #For each line, add it to the output
- output.append(line + '\n\t\t')
- if len(lines) == 0: #Special case where there is only one line
- output.append('\n')
- else: #Delete extra tabs from "output.append(line + '\n\t\t')"
- output[-1] = output[-1][:-2]
- #This outputs the text
- filename = '{:0>3d}'.format(i) #Formats the "file number" like 000, 001, etc...
- with open(filename + '.tsv','wb') as g:
- for x in output:
- g.write(x.encode('cp932'))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement