def Extract_Menu(src, dst): table = normal_table('mmbn2.tbl') with open(src, "rb") as data: # Não preciso disso aqui na verdade... # main_pointers = [] # fd.seek( 0x2282c ) # print ">> Buffering pointer to pointers..." # while fd.tell() < 0x228a8 : # main_pointers.append(struct.unpack("<L", fd.read(4))[0] & 0xFFFFFF) text_pointers = [0x7d7bc8,] # fd.seek( 0x228a8 ) # print ">> Buffering pointer to text..." # while fd.tell() < 0x22b34 : # text_pointers.append(struct.unpack("<L", fd.read(4))[0] & 0xFFFFFF) i = 0 for j, pointer_2 in enumerate(text_pointers): if pointer_2 == 0: continue print ">> Extracting {0} {1} text".format(i,j) #ret = lzss.uncompress( fd, pointer_2 ) # data = mmap.mmap( -1, len(ret) ) # data.write(ret) data.seek(pointer_2) # Bufferiza os ponteiros entries = struct.unpack("<H" , data.read(2))[0]/ 2 pointers = [] data.seek(pointer_2) for _ in range(entries): pointers.append(struct.unpack("<H", data.read(2))[0]) buffer = array.array("c") while True: p = data.tell() - pointer_2 if p in pointers: for k, ptr in enumerate( pointers ): if p == ptr: # Coloca labels no texto buffer.extend( "<@PointerIdx%d>\n" % k ) b = data.read(1) c = struct.unpack("B", b)[0] if c >= 0xE5: # É uma tag.. esse teste é o mesmo do jogo if c in tagsdict: tagsdict[c][1](data, buffer, tagsdict[c][0]) else: buffer.extend( "<"+str(hex(c))+">" ) else: if b in table: buffer.append( table[b] ) else: buffer.extend( "<"+str(hex(c))+">") if data.tell() == 0x7d8d8f: break data.close() output = open(os.path.join(dst, "%03d_%03d.txt" %(i,j)), "w") buffer.tofile(output) output.close()
def Insert_NPC(src, dst): global BASE_PTR table = normal_table('mmbn2.tbl') table.set_mode('inverted') files = filter(lambda x: x.__contains__('.txt'), scandirs(src)) # Cria o dicionário invertido de tags itagsdict = dict([[v[0],k] for k,v in tagsdict.items()]) print hex(BASE_PTR) dest = open(dst, 'r+b') dest.seek( BASE_PTR ) pointer_files = [] for i, txtname in enumerate(files): print ">> Convertendo e comprimindo " + txtname buffer = array.array("c") with open(txtname, 'rb') as fd: pointer_idx = [] for j, line in enumerate(fd): #try: line = line.strip('\r\n') if not line: continue elif line in ( "!---------------------!","!+++++++++++++++++++++!","!*********************!" ): continue else: splitted = re.split( TAG_IN_LINE, line ) for string in splitted: tag = re.match( GET_TAG, string ) # Se não for uma tag, é texto plano if not tag: for char in string: try: buffer.extend( table[char] ) except: print "Line {0} Char {1} Text {2}".format(j, ord(char), line) raise Exception() # Se for uma tag else: tag = tag.groups()[0] argv = [] # Tag com argumentos if ": " in tag: tag,argv = tag.split(": ") argv = argv.split(" ") if tag.startswith("@"): # São labels if "PointerIdx" in tag: pointer_idx.append( len(buffer) ) else: print "Line {0} Label {1} Text {2}".format(j, tag, line) raise Exception() else: if tag in itagsdict: buffer.extend( struct.pack("B", itagsdict[tag]) ) for arg in argv: buffer.extend( struct.pack("B", int(arg)) ) else: buffer.extend( struct.pack("B", int(tag,16)) ) # except: # print "<< Error" # sys.exit() size = len(pointer_idx) * 2 + len(buffer) temp = mmap.mmap(-1, size) offset = len(pointer_idx) * 2 for ptr in pointer_idx: temp.write( struct.pack("<H", offset+ptr) ) temp.write(buffer.tostring()) ret = lzss.compress(temp) temp.close() b,name = os.path.split( txtname ) i, j = name.replace(".txt", "").split("_") pointer_files.append( [int(i), int(j), dest.tell()] ) ret.tofile(dest) BASE_PTR = dest.tell() print ">> Updating pointer table..." for desc in pointer_files: dest.seek( 0x228a8 + 4*desc[1] ) dest.write( struct.pack("<L", desc[2] | 0x08000000) ) dest.close()
def Extract_Main(src, dst): table = normal_table('mmbn2.tbl') main_pointers = [(0x77d71c, 0x79cb18),] with open(src, "rb") as fd: # Não preciso disso aqui na verdade... # main_pointers = [] # fd.seek( 0x2282c ) # print ">> Buffering pointer to pointers..." # while fd.tell() < 0x228a8 : # main_pointers.append(struct.unpack("<L", fd.read(4))[0] & 0xFFFFFF) for i, pp in enumerate(main_pointers): text_pointers = [] fd.seek( pp[0] ) print ">> Buffering pointer to text..." ret = fd.read(pp[1]-pp[0]) data = mmap.mmap( -1, len(ret) ) data.write(ret) data.seek(0) j = 0 while True: # Bufferiza os ponteiros while data.tell() % 4 != 0: data.read(1) offset = data.tell() entries = data.read(2) if len(entries) == 0: break print ">> Extracting {0} {1} text".format(i,j) entries = struct.unpack("<H" , entries)[0]/ 2 pointers = [] data.seek(-2,1) for _ in range(entries): pointers.append(struct.unpack("<H", data.read(2))[0]) buffer = array.array("c") buffer.extend( "<@AbsoluteAddr %d>\n" % (pp[0]+offset) ) new_eb = True while True: p = data.tell() - offset if p in pointers: for k, ptr in enumerate( pointers ): if p == ptr: # Coloca labels no texto buffer.extend( "<@PointerIdx%d>\n" % k ) b = data.read(1) if len(b) == 0: break c = struct.unpack("B", b)[0] # Após a tag 0xE7, sempre devemos ler uma nova tag. Se não, podemos dizer que o bloco de leitura acabou if new_eb: if c < 0xE5: data.seek(-1,1) break new_eb = False if c >= 0xE5: # É uma tag.. esse teste é o mesmo do jogo if c in tagsdict: tagsdict[c][1](data, buffer, tagsdict[c][0]) else: buffer.extend( "<"+str(hex(c))+">" ) else: if b in table: buffer.append( table[b] ) else: buffer.extend( "<"+str(hex(c))+">") if c == 0xE7: new_eb = True output = open(os.path.join(dst, "%03d_%03d.txt" %(i,j)), "w") buffer.tofile(output) output.close() j += 1 data.close()
def Insert_Main(src, dst): global BASE_PTR table = normal_table('mmbn2.tbl') table.set_mode('inverted') files = filter(lambda x: x.__contains__('.txt'), scandirs(src)) # Cria o dicionário invertido de tags itagsdict = dict([[v[0],k] for k,v in tagsdict.items()]) #base_ptr = 0x800000 print hex(BASE_PTR) dest = open(dst, 'r+b') dest.seek( BASE_PTR ) pointer_old = [] pointer_new = [] for i, txtname in enumerate(files): print ">> Convertendo e comprimindo " + txtname while dest.tell() % 4 != 0: dest.write("\x00") buffer = array.array("c") with open(txtname, 'rb') as fd: pointer_idx = [] for j, line in enumerate(fd): #try: line = line.strip('\r\n') if not line: continue elif line in ( "!---------------------!","!+++++++++++++++++++++!","!*********************!" ): continue else: splitted = re.split( TAG_IN_LINE, line ) for string in splitted: tag = re.match( GET_TAG, string ) # Se não for uma tag, é texto plano if not tag: for char in string: try: buffer.extend( table[char] ) except: print "Line {0} Char {1} Text {2}".format(j, ord(char), line) raise Exception() # Se for uma tag else: tag = tag.groups()[0] argv = [] # Tag com argumentos if ": " in tag: tag,argv = tag.split(": ") argv = argv.split(" ") if tag.startswith("@"): # São labels if "PointerIdx" in tag: pointer_idx.append( len(buffer) ) elif "AbsoluteAddr" in tag: t,c = tag.split(" ") # Errei .. faltou o : na tag, para aproveitar o split mais acima pointer_old.append( struct.pack("<L", int(c) | 0x08000000) ) pointer_new.append( struct.pack("<L", dest.tell() | 0x08000000) ) else: print "Line {0} Label {1} Text {2}".format(j, tag, line) raise Exception() else: if tag in itagsdict: buffer.extend( struct.pack("B", itagsdict[tag]) ) for arg in argv: buffer.extend( struct.pack("B", int(arg)) ) else: buffer.extend( struct.pack("B", int(tag,16)) ) # except: # print "<< Error" # sys.exit() size = len(pointer_idx) * 2 + len(buffer) offset = len(pointer_idx) * 2 for ptr in pointer_idx: dest.write( struct.pack("<H", offset+ptr) ) dest.write(buffer.tostring()) b,name = os.path.split( txtname ) i, j = name.replace(".txt", "").split("_") BASE_PTR = dest.tell() print ">> Updating pointer table..." dest.seek( 0 ) while dest.tell() < 0x800000: ptr = dest.read(4) if ptr in pointer_old: idx = pointer_old.index(ptr) dest.seek(-4,1) print ">> Updated %s to %s [%s]" % ( hex(struct.unpack("<L",ptr)[0]) , hex(struct.unpack("<L",pointer_new[idx])[0]) , hex( dest.tell()) ) dest.write( pointer_new[pointer_old.index(ptr)]) dest.close()