def get_deswizzled_data(flim): if flim.format == 0x01: format_ = 61 elif flim.format == 0x02: format_ = 112 elif flim.format == 0x07: format_ = 49 elif flim.format == 0x08: format_ = 85 elif flim.format == 0x0a: format_ = 86 elif flim.format == 0x0b: format_ = 115 elif flim.format in [0x1a, 0x41a]: format_ = 28 elif flim.format == 0x19: format_ = 24 elif flim.format in [0x31, 0x431]: format_ = flim.format_ elif flim.format in [0x32, 0x432]: format_ = "BC2" elif flim.format in [0x33, 0x433]: format_ = "BC3" elif flim.format == 0x34: format_ = "BC4U" elif flim.format == 0x35: format_ = "BC5U" result = addrlib.deswizzle(flim.width, flim.height, 1, flim.format, 0, 1, flim.surfOut.tileMode, flim.swizzle, flim.pitch, flim.surfOut.bpp, 0, 0, flim.data) if flim.format in BCn_formats: size = ((flim.width + 3) >> 2) * ((flim.height + 3) >> 2) * ( addrlib.surfaceGetBitsPerPixel(flim.format) >> 3) else: size = flim.width * flim.height * ( addrlib.surfaceGetBitsPerPixel(flim.format) >> 3) result = result[:size] hdr = dds.generateHeader(1, flim.width, flim.height, format_, flim.compSel, size, flim.format in BCn_formats) return hdr, result
def get_deswizzled_data(i, gfd): numImages = gfd.numImages numMips = gfd.numMips[i] width = gfd.width[i] height = gfd.height[i] depth = gfd.depth[i] dim = gfd.dim[i] format_ = gfd.format[i] aa = gfd.aa[i] tileMode = gfd.tileMode[i] swizzle_ = gfd.swizzle[i] compSel = gfd.compSel[i] data = gfd.data[i] mipSize = gfd.mipSize[i] realSize = gfd.realSize[i] surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, 0) bpp = (surfOut.bpp + 7) // 8 mipOffsets = gfd.mipOffsets[i] try: mipData = gfd.mipData[i] except KeyError: mipData = b'' if format_ in formats: if aa != 0: print("") print("Unsupported aa!") print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) return b'', [] else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if format_ == 0x00: print("") print("Invalid texture format!") print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) return b'', [] else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) else: if format_ == 0x1a or format_ == 0x41a: format__ = 28 elif format_ == 0x19: format__ = 24 elif format_ == 0x8: format__ = 85 elif format_ == 0xa: format__ = 86 elif format_ == 0xb: format__ = 115 elif format_ == 0x1: format__ = 61 elif format_ == 0x7: format__ = 49 elif format_ == 0x2: format__ = 112 elif format_ == 0x31 or format_ == 0x431: format__ = "BC1" elif format_ == 0x32 or format_ == 0x432: format__ = "BC2" elif format_ == 0x33 or format_ == 0x433: format__ = "BC3" elif format_ == 0x34: format__ = "BC4U" elif format_ == 0x234: format__ = "BC4S" elif format_ == 0x35: format__ = "BC5U" elif format_ == 0x235: format__ = "BC5S" if surfOut.depth != 1: print("") print("Unsupported depth!") print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) return b'', b'', b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) result = [] for level in range(numMips): if format_ in BCn_formats: size = ((max(1, width >> level) + 3) >> 2) * ( (max(1, height >> level) + 3) >> 2) * bpp else: size = max(1, width >> level) * max(1, height >> level) * bpp if level != 0: print( str(level) + ": " + str(max(1, width >> level)) + "x" + str(max(1, height >> level))) if level == 1: mipOffset = mipOffsets[level - 1] - surfOut.surfSize else: mipOffset = mipOffsets[level - 1] surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, level) data = mipData[mipOffset:mipOffset + surfOut.surfSize] deswizzled = addrlib.deswizzle(max(1, width >> level), max(1, height >> level), surfOut.height, format_, surfOut.tileMode, swizzle_, surfOut.pitch, surfOut.bpp, data) if format_ == 0xa: data = form_conv.toDDSrgb5a1(deswizzled[:size]) elif format_ == 0xb: data = form_conv.toDDSrgba4(deswizzled[:size]) else: data = deswizzled[:size] result.append(data) hdr = dds.generateHeader(numMips, width, height, format__, compSel, realSize, format_ in BCn_formats) else: print("") print("Unsupported texture format_: " + hex(format_)) print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) hdr, result = b'', [] else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) return hdr, result
def FTEXtoDDS(ftex_pos, f, name, folder): ftex = f[ftex_pos:ftex_pos + 0xC0] pos = 4 surface = GX2Surface() surface.data(ftex, pos) pos += surface.size format_ = surface.format_ if format_ in formats: if surface.numMips > 14: print('') print(name) print("Number of mipmaps exceeded 13") return 0, 0 mipOffsets = [] for i in range(13): mipOffsets.append(ftex[i * 4 + pos] << 24 | ftex[i * 4 + 1 + pos] << 16 | ftex[i * 4 + 2 + pos] << 8 | ftex[i * 4 + 3 + pos]) pos += 68 compSel = [] for i in range(4): comp = ftex[pos + i] if comp == 4: # Sorry, but this is unsupported. comp = i compSel.append(comp) dataSize = surface.imageSize mipSize = surface.mipSize data_pos = struct.unpack(">I", ftex[0xB0:0xB4])[0] + ftex_pos + 0xB0 mip_pos = struct.unpack(">I", ftex[0xB4:0xB8])[0] data = f[data_pos:data_pos + dataSize] if not (mip_pos and mipSize): mipData = b"" else: mip_pos += ftex_pos + 0xB4 mipData = f[mip_pos:mip_pos + mipSize] numMips = surface.numMips width = surface.width height = surface.height depth = surface.depth dim = surface.dim aa = surface.aa tileMode = surface.tileMode swizzle_ = surface.swizzle bpp = addrlib.surfaceGetBitsPerPixel(format_) >> 3 if format_ in BCn_formats: realSize = ((width + 3) >> 2) * ((height + 3) >> 2) * bpp else: realSize = width * height * bpp surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, 0) if aa: print('') print(name) print("Unsupported AA mode") return 0, 0 if format_ == 0x1a or format_ == 0x41a: format__ = 28 elif format_ == 0x19: format__ = 24 elif format_ == 0x8: format__ = 85 elif format_ == 0xa: format__ = 86 elif format_ == 0xb: format__ = 115 elif format_ == 0x1: format__ = 61 elif format_ == 0x7: format__ = 49 elif format_ == 0x2: format__ = 112 elif format_ == 0x31 or format_ == 0x431: format__ = "BC1" elif format_ == 0x32 or format_ == 0x432: format__ = "BC2" elif format_ == 0x33 or format_ == 0x433: format__ = "BC3" elif format_ == 0x34: format__ = "BC4U" elif format_ == 0x234: format__ = "BC4S" elif format_ == 0x35: format__ = "BC5U" elif format_ == 0x235: format__ = "BC5S" if surfOut.depth != 1: print('') print(name) print("Unsupported depth") return 0, 0 result = [] for level in range(numMips): if level != 0: if level == 1: mipOffset = mipOffsets[level - 1] - surfOut.surfSize else: mipOffset = mipOffsets[level - 1] surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, level) data = mipData[mipOffset:mipOffset + surfOut.surfSize] deswizzled = addrlib.deswizzle(max(1, width >> level), max(1, height >> level), surfOut.height, format_, surfOut.tileMode, swizzle_, surfOut.pitch, surfOut.bpp, data) if format_ in BCn_formats: size = ((max(1, width >> level) + 3) >> 2) * ( (max(1, height >> level) + 3) >> 2) * bpp else: size = max(1, width >> level) * max(1, height >> level) * bpp if format_ == 0xa: data = form_conv.toDDSrgb5a1(deswizzled[:size]) elif format_ == 0xb: data = form_conv.toDDSrgba4(deswizzled[:size]) else: data = deswizzled[:size] result.append(data) hdr = dds.generateHeader(numMips, width, height, format__, compSel, realSize, format_ in BCn_formats) with open(folder + "/" + name + ".dds", "wb") as output: output.write(hdr) for data in result: output.write(data) return format_, numMips else: print('') print(name) print("Unsupported format: " + hex(format_)) return format_, 0
def get_deswizzled_data(i, nv): numImages = nv.numImages numMips = nv.numMips[i] width = nv.width[i] height = nv.height[i] depth = nv.depth[i] format_ = nv.format[i] realSize = nv.realSize[i] data = nv.data[i][:realSize] bpp = nv.bpp[i] mipOffsets = nv.mipOffsets[i] if format_ in formats: if format_ in [0x25, 0x38]: format__ = 28 elif format_ == 0x3d: format__ = 24 elif format_ == 0x3c: format__ = 85 elif format_ == 0x3b: format__ = 86 elif format_ == 0x39: format__ = 115 elif format_ == 0x1: format__ = 61 elif format_ == 0xd: format__ = 49 elif format_ == 0x42: format__ = "BC1" elif format_ == 0x43: format__ = "BC2" elif format_ == 0x44: format__ = "BC3" elif format_ == 0x49: format__ = "BC4U" elif format_ == 0x4a: format__ = "BC4S" elif format_ == 0x4b: format__ = "BC5U" elif format_ == 0x4c: format__ = "BC5S" if depth != 1: print("") print("Unsupported depth!") print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) return b'', b'', b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if numMips - 1: print("") print("Processing " + str(numMips - 1) + " mipmaps:") result = [] for level in range(numMips): if format_ in BCn_formats: size = ((max(1, width >> level) + 3) >> 2) * ((max(1, height >> level) + 3) >> 2) * bpp else: size = max(1, width >> level) * max(1, height >> level) * bpp mipOffset = mipOffsets[level] if level != 0: print(str(level) + ": " + str(max(1, width >> level)) + "x" + str(max(1, height >> level))) print(hex(mipOffset)) data = nv.data[i][mipOffset:mipOffset + size] deswizzled = swizzle.deswizzle(max(1, width >> level), max(1, height >> level), format_, data) data = deswizzled[:size] result.append(data) hdr = dds.generateHeader(numMips, width, height, format__, nv.compSel[i], realSize, format_ in BCn_formats) else: print("") print("Unsupported texture format_: " + hex(format_)) print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) hdr, result = b'', [] else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) return hdr, result
def get_deswizzled_data(i, gfd): majorVersion = gfd.majorVersion numImages = gfd.numImages numMips = gfd.numMips[i] width = gfd.width[i] height = gfd.height[i] depth = gfd.depth[i] dim = gfd.dim[i] format_ = gfd.format[i] aa = gfd.aa[i] tileMode = gfd.tileMode[i] swizzle_ = gfd.swizzle[i] compSel = gfd.compSel[i] data = gfd.data[i] realSize = gfd.realSize[i] mipOffsets = gfd.mipOffsets[i] surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, 0) bpp = divRoundUp(surfOut.bpp, 8) try: mipData = gfd.mipData[i] except KeyError: mipData = b'' if format_ in formats: if aa != 0: print("") print("Unsupported aa!") print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) return b'', [] else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if format_ == 0x00: print("") print("Invalid texture format!") print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) return b'', [] else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) else: if format_ in [0x1a, 0x41a]: format__ = 28 elif format_ == 0x19: format__ = 24 elif format_ == 0x8: format__ = 85 elif format_ == 0xa: format__ = 86 elif format_ == 0xb: format__ = 115 elif format_ == 0x1: format__ = 61 elif format_ == 0x7: format__ = 49 elif format_ == 0x2: format__ = 112 elif format_ in [0x31, 0x431]: format__ = "BC1" elif format_ in [0x32, 0x432]: format__ = "BC2" elif format_ in [0x33, 0x433]: format__ = "BC3" elif format_ == 0x34: format__ = "BC4U" elif format_ == 0x234: format__ = "BC4S" elif format_ == 0x35: format__ = "BC5U" elif format_ == 0x235: format__ = "BC5S" if surfOut.depth != 1: print("") print("Unsupported depth!") print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) return b'', b'', b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if numMips > 1: print("") print("Processing " + str(numMips - 1) + " mipmap(s):") if format_ in BCn_formats: blkWidth, blkHeight = 4, 4 else: blkWidth, blkHeight = 1, 1 result = [] for mipLevel in range(numMips): width_ = max(1, width >> mipLevel) height_ = max(1, height >> mipLevel) size = divRoundUp(width_, blkWidth) * divRoundUp(height_, blkHeight) * bpp if mipLevel != 0: print(str(mipLevel) + ": " + str(width_) + "x" + str(height_)) mipOffset = mipOffsets[mipLevel - 1] if mipLevel == 1: mipOffset -= surfOut.surfSize surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, mipLevel) data = mipData[mipOffset:mipOffset + surfOut.surfSize] result_ = addrlib.deswizzle( width_, height_, surfOut.height, format_, surfOut.tileMode, swizzle_, surfOut.pitch, surfOut.bpp, data, ) result.append(result_[:size]) hdr = dds.generateHeader(numMips, width, height, format__, compSel, realSize, format_ in BCn_formats) else: print("") print("Unsupported texture format_: " + hex(format_)) print("") if i != (numImages - 1): print("Continuing in 5 seconds...") time.sleep(5) hdr, result = b'', [] else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) return hdr, result
def extract(self, index, BFRESPath, exportAs, dontShowMsg=False): texture = self.textures[index] if texture.format_ in globals.formats and texture.dim == 2 and texture.arrayLength < 2 and texture.tileMode in globals.tileModes: if texture.format_ == 0x101: format_ = "la4" elif texture.format_ == 0x201: format_ = "l8" elif texture.format_ == 0x301: format_ = "rgba4" elif texture.format_ == 0x401: format_ = "abgr4" elif texture.format_ == 0x501: format_ = "rgb5a1" elif texture.format_ == 0x601: format_ = "a1bgr5" elif texture.format_ == 0x701: format_ = "rgb565" elif texture.format_ == 0x801: format_ = "bgr565" elif texture.format_ == 0x901: format_ = "la8" elif (texture.format_ >> 8) == 0xb: format_ = "rgba8" elif (texture.format_ >> 8) == 0xc: format_ = "bgra8" elif texture.format_ == 0xe01: format_ = "bgr10a2" elif (texture.format_ >> 8) == 0x1a: format_ = "BC1" elif (texture.format_ >> 8) == 0x1b: format_ = "BC2" elif (texture.format_ >> 8) == 0x1c: format_ = "BC3" elif texture.format_ == 0x1d01: format_ = "BC4U" elif texture.format_ == 0x1d02: format_ = "BC4S" elif texture.format_ == 0x1e01: format_ = "BC5U" elif texture.format_ == 0x1e02: format_ = "BC5S" elif texture.format_ == 0x1f05: format_ = "BC6H_SF16" elif texture.format_ == 0x1f0a: format_ = "BC6H_UF16" elif (texture.format_ >> 8) == 0x20: format_ = "BC7" elif texture.format_ == 0x3b01: format_ = "bgr5a1" result_, blkWidth, blkHeight = self.rawData(texture) if exportAs: if (texture.format_ >> 8) in globals.ASTC_formats: file = QtWidgets.QFileDialog.getSaveFileName( None, "Save File", "", "ASTC (*.astc)")[0] else: file = QtWidgets.QFileDialog.getSaveFileName( None, "Save File", "", "DDS (*.dds)")[0] if not file: return False else: name = texture.name.replace('\\', '_').replace( '/', '_').replace(':', '_').replace('*', '_').replace( '?', '_').replace('"', '_').replace('<', '_').replace( '>', '_').replace('|', '_') if (texture.format_ >> 8) in globals.ASTC_formats: file = os.path.join(BFRESPath, name + '.astc') else: file = os.path.join(BFRESPath, name + '.dds') if (texture.format_ >> 8) in globals.ASTC_formats: outBuffer = b''.join([ b'\x13\xAB\xA1\x5C', blkWidth.to_bytes(1, "little"), blkHeight.to_bytes(1, "little"), b'\1', texture.width.to_bytes(3, "little"), texture.height.to_bytes(3, "little"), b'\1\0\0', result_[0], ]) with open(file, "wb+") as output: output.write(outBuffer) else: hdr = dds.generateHeader( texture.numMips, texture.width, texture.height, format_, texture.compSel, len(result_[0]), (texture.format_ >> 8) in globals.BCn_formats, ) with open(file, "wb+") as output: output.write(b''.join([hdr, b''.join(result_)])) elif not dontShowMsg: msg = "Can't convert: " + texture.name if texture.format_ not in globals.formats: context = "Unsupported format." elif texture.tileMode not in globals.tileModes: context = "Unsupported tiling mode." elif texture.dim != 2: context = "Unsupported image storage dimension." else: context = "Unsupported array length." QtWidgets.QMessageBox.warning(None, "Error", '\n'.join([msg, context])) return False
def extract(tex, BFRESPath, exportAs, dontShowMsg=False): if tex.format in globals.formats and not tex.aa and tex.surfInfo.depth == 1: if (tex.format & 0xFF) == 0x1a: format_ = "rgba8" elif tex.format == 0x19: format_ = "bgr10a2" elif tex.format == 0x8: format_ = "rgb565" elif tex.format == 0xa: format_ = "rgb5a1" elif tex.format == 0xb: format_ = "rgba4" elif tex.format == 0x1: format_ = "l8" elif tex.format == 0x7: format_ = "la8" elif tex.format == 0x2: format_ = "la4" elif (tex.format & 0xFF) == 0x31: format_ = "BC1" elif (tex.format & 0xFF) == 0x32: format_ = "BC2" elif (tex.format & 0xFF) == 0x33: format_ = "BC3" elif tex.format == 0x34: format_ = "BC4U" elif tex.format == 0x234: format_ = "BC4S" elif tex.format == 0x35: format_ = "BC5U" elif tex.format == 0x235: format_ = "BC5S" realSize = ceil(tex.width / tex.blkWidth) * ceil( tex.height / tex.blkWidth) * tex.bpp result = decode(tex) if exportAs: file = QtWidgets.QFileDialog.getSaveFileName( None, "Save File", "", "DDS (*.dds)")[0] if not file: return False else: file = os.path.join(BFRESPath, tex.name + '.dds') hdr = dds.generateHeader(tex.numMips, tex.width, tex.height, format_, tex.compSel, realSize, tex.format in globals.BCn_formats) with open(file, "wb+") as output: output.write(b''.join([hdr, b''.join(result)])) elif not dontShowMsg: msg = "Can't convert: " + tex.name if tex.aa: context = "Unsupported AA mode." elif tex.surfInfo.depth != 1: context = "Unsupported depth." else: context = "Format is not supported." QtWidgets.QMessageBox.warning(None, "Error", '\n'.join([msg, context])) return False
def saveTextures(textures): for tex in textures: if tex.format in formats and tex.numFaces < 2: if (tex.format >> 8) == 0xb: format_ = 28 elif tex.format == 0x701: format_ = 85 elif tex.format == 0x201: format_ = 61 elif tex.format == 0x901: format_ = 49 elif (tex.format >> 8) == 0x1a: format_ = "BC1" elif (tex.format >> 8) == 0x1b: format_ = "BC2" elif (tex.format >> 8) == 0x1c: format_ = "BC3" elif tex.format == 0x1d01: format_ = "BC4U" elif tex.format == 0x1d02: format_ = "BC4S" elif tex.format == 0x1e01: format_ = "BC5U" elif tex.format == 0x1e02: format_ = "BC5S" elif tex.format == 0x1f01: format_ = "BC6H_UF16" elif tex.format == 0x1f02: format_ = "BC6H_SF16" elif (tex.format >> 8) == 0x20: format_ = "BC7" if (tex.format >> 8) in blk_dims: blkWidth, blkHeight = blk_dims[tex.format >> 8] else: blkWidth, blkHeight = 1, 1 bpp = bpps[tex.format >> 8] size = DIV_ROUND_UP(tex.width, blkWidth) * DIV_ROUND_UP( tex.height, blkHeight) * bpp result = swizzle.deswizzle(tex.width, tex.height, blkWidth, blkHeight, bpp, tex.tileMode, tex.alignment, tex.sizeRange, tex.data) result = result[:size] if (tex.format >> 8) in ASTC_formats: outBuffer = b''.join([ b'\x13\xAB\xA1\x5C', blkWidth.to_bytes(1, "little"), blkHeight.to_bytes(1, "little"), b'\1', tex.width.to_bytes(3, "little"), tex.height.to_bytes(3, "little"), b'\1\0\0', result, ]) with open(tex.name + ".astc", "wb+") as output: output.write(outBuffer) else: hdr = dds.generateHeader(1, tex.width, tex.height, format_, list(reversed(tex.compSel)), size, (tex.format >> 8) in BCn_formats) with open(tex.name + ".dds", "wb+") as output: output.write(b''.join([hdr, result])) else: print("") print("Can't convert: " + tex.name) if tex.format not in formats: print("Format is not supported.") else: print("Unsupported number of faces.")