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(flim): 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) return result[:size]
def untileTex(tex): surfInfo = tex.surfInfo data = tex.data[:surfInfo.surfSize] result = [] for mipLevel in range(tex.numMips): width = max(1, tex.width >> mipLevel) height = max(1, tex.height >> mipLevel) size = ceil(width / tex.blkWidth) * ceil( height / tex.blkHeight) * tex.bpp if mipLevel != 0: mipOffset = tex.mipOffsets[mipLevel - 1] if mipLevel == 1: mipOffset -= surfInfo.surfSize surfInfo = addrlib.getSurfaceInfo(tex.format, tex.width, tex.height, tex.depth, tex.dim, tex.tileMode, tex.aa, mipLevel) data = tex.mipData[mipOffset:mipOffset + surfInfo.surfSize] result_ = addrlib.deswizzle( width, height, surfInfo.height, tex.format, surfInfo.tileMode, tex.swizzle, surfInfo.pitch, surfInfo.bpp, data, ) result.append(result_[:size]) return result
def copySurface(src, dst): ### Check requirements ### assert dst.dim == src.dim assert dst.width == src.width assert dst.height == src.height assert dst.depth <= src.depth assert dst.numMips <= src.numMips assert dst.format == src.format ### Check if the two surfaces are the same ### ### (If they are, we can just copy the data over) ### # Conditions to check are: # 1. tileMode is the same (and swizzle is the same for non-linear tiling) # 2a. depth is the same (and mipmaps count is the same for depths higher than 1) # 2b. depth differs, but mipmaps count is 1 for both surfaces # These two conditions ensure we can safely slice the source data for the dest data # The depths condition can be ignored if we slice with the depth in mind, # but that is currently not supported if (src.tileMode == dst.tileMode and (src.tileMode in (GX2TileMode.Linear_Aligned, GX2TileMode.Linear_Special) or ((src.swizzle >> 8) & 7) == ((dst.swizzle >> 8) & 7)) and ((src.depth == dst.depth and (src.depth == 1 or src.numMips == dst.numMips)) or src.numMips == 1)): # No need to process anything, just copy the data over dst.imageData = src.imageData[:dst.imageSize] dst.mipData = src.mipData[:dst.mipSize] return ### Untile the source data ### levels = [] # Calculate the surface info for the base level surfInfo = addrlib.getSurfaceInfo( src.format.value, src.width, src.height, src.depth, src.dim.value, src.tileMode.value, src.aa.value, 0, ) # Get the depth used for tiling tileMode = GX2TileMode(surfInfo.tileMode) tilingDepth = surfInfo.depth if tileMode in (GX2TileMode.Tiled_1D_Thick, GX2TileMode.Tiled_2D_Thick, GX2TileMode.Tiled_2B_Thick, GX2TileMode.Tiled_3D_Thick, GX2TileMode.Tiled_3B_Thick): tilingDepth = divRoundUp(tilingDepth, 4) # Depths higher than 1 are currently not supported assert tilingDepth == 1 # Block width and height for the format blkWidth, blkHeight = (4, 4) if src.format.isCompressed() else (1, 1) # Bytes-per-pixel bpp = divRoundUp(surfInfo.bpp, 8) # Untile the base level result = addrlib.deswizzle( src.width, src.height, 1, src.format.value, 0, src.use.value, surfInfo.tileMode, src.swizzle, surfInfo.pitch, surfInfo.bpp, 0, 0, src.imageData, ) # Make sure it's the correct size size = divRoundUp(src.width, blkWidth) * divRoundUp(src.height, blkHeight) * bpp assert len(result) >= size levels.append(result[:size]) # Untile the other levels (mipmaps) offset = 0 for mipLevel in range(1, dst.numMips): # Calculate the width and height of the mip level width = max(1, src.width >> mipLevel) height = max(1, src.height >> mipLevel) # Calculate the surface info for the mip level surfInfo = addrlib.getSurfaceInfo( src.format.value, src.width, src.height, src.depth, src.dim.value, src.tileMode.value, src.aa.value, mipLevel, ) # Untile the mip level result = addrlib.deswizzle( width, height, 1, src.format.value, 0, src.use.value, surfInfo.tileMode, src.swizzle, surfInfo.pitch, surfInfo.bpp, 0, 0, src.mipData[offset:offset + surfInfo.surfSize], ) # Make sure it's the correct size size = divRoundUp(width, blkWidth) * divRoundUp(height, blkHeight) * bpp assert len(result) >= size levels.append(result[:size]) # Set the offset of the next level if mipLevel < src.numMips - 1: offset = src.mipOffset[mipLevel] ### Tile the destination data ### # Calculate the surface info for the base level surfInfo = addrlib.getSurfaceInfo( dst.format.value, dst.width, dst.height, dst.depth, dst.dim.value, dst.tileMode.value, dst.aa.value, 0, ) # Get the depth used for tiling tileMode = GX2TileMode(surfInfo.tileMode) tilingDepth = surfInfo.depth if tileMode in (GX2TileMode.Tiled_1D_Thick, GX2TileMode.Tiled_2D_Thick, GX2TileMode.Tiled_2B_Thick, GX2TileMode.Tiled_3D_Thick, GX2TileMode.Tiled_3B_Thick): tilingDepth = divRoundUp(tilingDepth, 4) # Depths higher than 1 are currently not supported assert tilingDepth == 1 # Block width and height for the format blkWidth, blkHeight = (4, 4) if dst.format.isCompressed() else (1, 1) # Bytes-per-pixel bpp = divRoundUp(surfInfo.bpp, 8) # Tile the base level dst.imageData = addrlib.swizzle( dst.width, dst.height, 1, dst.format.value, 0, dst.use.value, surfInfo.tileMode, dst.swizzle, surfInfo.pitch, surfInfo.bpp, 0, 0, levels[0].ljust(surfInfo.surfSize, b'\0'), )[:surfInfo.surfSize] # Tile the other levels (mipmaps) mipData = bytearray() for mipLevel in range(1, dst.numMips): # Calculate the width and height of the mip level width = max(1, dst.width >> mipLevel) height = max(1, dst.height >> mipLevel) # Calculate the surface info for the mip level surfInfo = addrlib.getSurfaceInfo( dst.format.value, dst.width, dst.height, dst.depth, dst.dim.value, dst.tileMode.value, dst.aa.value, mipLevel, ) if mipLevel != 1: mipData += b'\0' * (dst.mipOffset[mipLevel - 1] - len(mipData)) # Untile the mip level mipData += addrlib.swizzle( width, height, 1, dst.format.value, 0, dst.use.value, surfInfo.tileMode, dst.swizzle, surfInfo.pitch, surfInfo.bpp, 0, 0, levels[mipLevel].ljust(surfInfo.surfSize, b'\0'), )[:surfInfo.surfSize] dst.mipData = bytes(mipData)
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 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] 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) 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 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) data = deswizzled[:size] result.append(data) if format_ == 8: result = [dds.form_conv.swapRB_RGB565(data) for data in result] elif format_ == 0xa: if majorVersion == 6: result = [ dds.form_conv.swapRB_RGB5A1(data) for data in result ] else: result = [ dds.form_conv.toDDSrgb5a1(data) for data in result ] elif format_ == 0xb: result = [dds.form_conv.swapRB_RGBA4(data) for data in result] 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