def modelstoFakeLZO(self, path, tabPath, outBinPath, outTabPath): """Convert a model file's contents to "fake LZO" format. path: input file to convert. tabPath: table for input file. outBinPath: output path for .bin file. outTabPath: output path for .tab file. """ inFile = BinaryFile(path, 'rb') tabFile = BinaryFile(tabPath, 'rb') outBin = BinaryFile(outBinPath, 'wb') outTab = BinaryFile(outTabPath, 'wb') inZlb = Zlb(inFile) tabCksum = 0 while True: offs = tabFile.readu32() if offs == 0xFFFFFFFF: break high = offs & 0xFF000000 if high & 0x10000000: #printf("Model %08X\r\n", offs) offs = offs & 0xFFFFFF inFile.seek(offs) data = inFile.read(4) if data == b'\xFA\xCE\xFE\xED': while data not in (b'ZLB\0', b'DIR\0', b'\xE0\xE0\xE0\xE0', b'\xF0\xF0\xF0\xF0'): outBin.write(data) data = inFile.read(4) inFile.seek(offs) data = inZlb.decompress() header = b'ZLB\0' + struct.pack('>3I', 1, len(data), len(data)) + b'Rena' data = header + data tabVal = outBin.tell() | high outBin.write(data) while outBin.tell() & 0xF: outBin.writeu8(0) else: # don't use this model tabVal = 0x00000000 tabCksum += ((tabVal >> 24) & 0xFF) tabCksum += ((tabVal >> 16) & 0xFF) tabCksum += ((tabVal >> 8) & 0xFF) tabCksum += ( tabVal & 0xFF) outTab.writeu32(tabVal) tabVal = outBin.tell() outTab.writeu32(tabVal) tabCksum += ((tabVal >> 24) & 0xFF) tabCksum += ((tabVal >> 16) & 0xFF) tabCksum += ((tabVal >> 8) & 0xFF) tabCksum += ( tabVal & 0xFF) outTab.writeu32(0xFFFFFFFF) tabCksum += (0xFF * 4) outTab.writeu32(tabCksum & 0xFFFFFFFF) for i in range(7): outTab.writeu32(0)
def _dumpRaw(self, binPath, tabPath, outPath, ignoreFlags=False, offsMask=0x0FFFFFFF, offsShift=0, nameFunc=None): """Dump raw data listed in table, where the next entry is used to calculate the size. """ try: file = BinaryFile(binPath+'.bin', 'rb') except FileNotFoundError: file = BinaryFile(binPath+'.BIN', 'rb') try: tbl = BinaryFile(tabPath+'.tab', 'rb') except FileNotFoundError: tbl = BinaryFile(tabPath+'.TAB', 'rb') if nameFunc is None: nameFunc = lambda idx, data: '%04X.bin' % idx idx = 0 entry = tbl.readu32() while True: if entry == 0xFFFFFFFF: break eNext = tbl.readu32() flags = entry >> 24 if flags != 0 or ignoreFlags: offs = entry & offsMask if offsShift >= 0: offs = offs >> offsShift else: offs = offs << -offsShift try: file.seek(offs) head = file.read(3) file.seek(offs) if head in (b'ZLB', b'DIR', b'\xFA\xCE\xFE'): data = Zlb(file).decompress() else: oNext = eNext & offsMask if offsShift >= 0: oNext = oNext >> offsShift else: oNext = oNext << -offsShift data = file.read(oNext - offs) name = '%s/%s' % (outPath, nameFunc(idx,data)) #printf("%04X %02X %06X %06X %s\n", idx, flags, offs, len(data), name) with open(name, 'wb') as outFile: outFile.write(data) except Exception as ex: printf("%04X %s ERROR: %s\n", idx, outPath, ex) idx += 1 entry = eNext
def mapstoFakeLZO(self, path, tabPath, outBinPath, outTabPath): """Convert MAPS.BIN file's contents to "fake LZO" format. path: input file to convert. tabPath: table for input file. outBinPath: output path for .bin file. outTabPath: output path for .tab file. """ inFile = BinaryFile(path, 'rb') tabFile = BinaryFile(tabPath, 'rb') outBin = BinaryFile(outBinPath, 'wb') outTab = BinaryFile(outTabPath, 'wb') inZlb = Zlb(inFile) offs = tabFile.readu32() while offs != 0xFFFFFFFF: nextOffs = tabFile.readu32() inLen = nextOffs - offs inFile.seek(offs) tabVal = outBin.tell() outTab.writeu32(tabVal) while offs < nextOffs: inFile.seek(offs) data = inFile.read(4) if len(data) == 0: break elif data == b'\xFA\xCE\xFE\xED': rawLen, zlbOffs, compLen = inFile.readStruct('3I') dOut = data + struct.pack('>3I', rawLen+0x28, zlbOffs, rawLen+4) printf("Write FACEFEED at %08X: %s\r\n", outBin.tell(), dOut.hex()) outBin.write(dOut) for i in range(zlbOffs): outBin.writeu16(inFile.readu16()) offs += len(data) elif data == b'ZLB\0': inFile.seek(offs) data = inZlb.decompress() dl = len(data) + 4 outBin.write(b'LZO\0' + struct.pack('3I', 0, 0, dl) + b'Rena' + data) else: outBin.write(data) offs = inFile.tell() offs = nextOffs tabVal = outBin.tell() outTab.writeu32(tabVal) outTab.writeu32(0xFFFFFFFF) for i in range(3): outTab.writeu32(0)
def dumpTexture(self, path, outPath, raw=False, offset=0): """Dump texture from file.""" if type(raw) is str: raw = (raw == '1') if type(offset) is str: offset = int(offset, 0) file = BinaryFile(path, 'rb', offset=offset) head = file.readStruct('3b') file.seek(0) if head in (b'ZLB', b'DIR', b'\xFA\xCE\xFE'): data = Zlb(file).decompress() else: size = file.readu32(offset=0x44) file.seek(0) data = file.read(size+0x60) if raw: with open(outPath, 'wb') as outFile: outFile.write(data) else: tex = SfaTexture.fromData(data) printf("Texture size: %dx%d, fmt %s, %d mipmaps\n", tex.width, tex.height, tex.format.name, tex.numMipMaps) tex.image.save(outPath)