def writeGFD(f, tileMode, swizzle_, SRGB, n, numImages): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f, SRGB) if 0 in [width, dataSize] and data == []: if n != (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_ not in formats: print("") print("Unsupported DDS format!") print("") if n != (numImages - 1): print("") print("Continuing in 5 seconds...") time.sleep(5) return b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if numMips > 13: print("") print("Invalid number of mipmaps for " + f) print("") if n != (numImages - 1): print("") print("Continuing in 5 seconds...") time.sleep(5) return b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) imageData = data[:dataSize] mipData = data[dataSize:] numMips += 1 if format_ in BCn_formats: if format_ in [0x31, 0x431, 0x234, 0x34]: align = 0xEE4 mipAlign = 0xFC0 else: align = 0x1EE4 mipAlign = 0x1FC0 else: align = 0x6E4 mipAlign = 0x7C0 bpp = addrlib.surfaceGetBitsPerPixel(format_) >> 3 alignment = 512 * bpp surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, 0) pitch = surfOut.pitch if surfOut.depth != 1: print("") print("Unsupported depth!") print("") if n != (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 tileMode in [1, 2, 3, 16]: s = 0 else: s = 0xd0000 s |= swizzle_ << 8 swizzled_data = [] imageSize = 0 mipSize = 0 mipOffsets = [] for i in range(numMips): if i == 0: data = imageData imageSize = surfOut.surfSize else: print( str(i) + ": " + str(max(1, width >> i)) + "x" + str(max(1, height >> i))) offset, dataSize = get_curr_mip_off_size(width, height, bpp, i, format_ in BCn_formats) data = mipData[offset:offset + dataSize] surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, i) padSize = surfOut.surfSize - dataSize data += padSize * b"\x00" if i != 0: offset += padSize if i == 1: mipOffsets.append(imageSize) else: mipOffsets.append(offset) mipSize += len(data) swizzled_data.append( addrlib.swizzle(max(1, width >> i), max(1, height >> i), surfOut.height, format_, surfOut.tileMode, s, surfOut.pitch, surfOut.bpp, data)) compSels = ["R", "G", "B", "A", "0", "1"] """print("") print("// ----- GX2Surface Info ----- ") print(" dim = 1") print(" width = " + str(width)) print(" height = " + str(height)) print(" depth = 1") print(" numMips = " + str(numMips)) print(" format = " + formats[format_]) print(" aa = 0") print(" use = 1") print(" imageSize = " + str(imageSize)) print(" mipSize = " + str(mipSize)) print(" tileMode = " + str(tileMode)) print(" swizzle = " + str(s) + ", " + hex(s)) print(" alignment = " + str(alignment)) print(" pitch = " + str(pitch)) print("") print(" GX2 Component Selector:") print(" Red Channel: " + str(compSels[compSel[0]])) print(" Green Channel: " + str(compSels[compSel[1]])) print(" Blue Channel: " + str(compSels[compSel[2]])) print(" Alpha Channel: " + str(compSels[compSel[3]])) print("") print(" bits per pixel = " + str(bpp << 3)) print(" bytes per pixel = " + str(bpp)) print(" realSize = " + str(len(imageData)))""" block_head_struct = GFDBlockHeader() gx2surf_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xb, 0x9c, 0, 0) gx2surf_struct = GX2Surface() gx2surf = gx2surf_struct.pack(1, width, height, 1, numMips, format_, 0, 1, imageSize, 0, mipSize, 0, tileMode, s, alignment, pitch) align_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, align, 0, 0) image_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xc, imageSize, 0, 0) mipAlign_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, mipAlign, 0, 0) mip_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xd, mipSize, 0, 0) output = gx2surf_blk_head + gx2surf if numMips > 1: i = 0 for offset in mipOffsets: output += offset.to_bytes(4, 'big') i += 1 for z in range(14 - i): output += 0.to_bytes(4, 'big') else: output += b"\x00" * 56 output += numMips.to_bytes(4, 'big') output += b"\x00" * 4 output += 1.to_bytes(4, 'big') for value in compSel: output += value.to_bytes(1, 'big') output += b"\x00" * 20 output += align_blk_head output += b"\x00" * align output += image_blk_head output += swizzled_data[0] if numMips > 1: output += mipAlign_blk_head output += b"\x00" * mipAlign output += mip_blk_head i = 0 for data in swizzled_data: if i != 0: output += data i += 1 return output
def writeNv(f, SRGB, n, numImages, numBlocks): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS(f, SRGB) if 0 in [width, dataSize] and data == []: print("") if n != (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_ not in formats: print("") print("Unsupported DDS format!") print("") if n != (numImages - 1): print("") print("Continuing in 5 seconds...") time.sleep(5) return b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if numMips > 16: print("") print("Invalid number of mipmaps for " + f) print("") if n != (numImages - 1): print("") print("Continuing in 5 seconds...") time.sleep(5) return b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) imageData = data[:dataSize] mipData = data[dataSize:] numMips += 1 bpp = bpps[format_] alignment = 512 if numMips - 1: print("") print("Processing " + str(numMips - 1) + " mipmaps:") swizzled_data = bytearray() offset = 0 mipOffsets = [] for i in range(numMips): if not i: data = imageData else: print(str(i) + ": " + str(max(1, width >> i)) + "x" + str(max(1, height >> i))) mipOffset, dataSize = get_curr_mip_off_size(width, height, bpp, i, format_ in BCn_formats) data = mipData[mipOffset:mipOffset+dataSize] mipOffsets.append(offset) offset += len(data) swizzled_data += swizzle.swizzle(max(1, width >> i), max(1, height >> i), format_, data) print("") print("// ----- NvTextureHeader Info ----- ") print(" imageSize = " + str(offset)) print(" alignment = " + str(alignment)) print(" width = " + str(width)) print(" height = " + str(height)) print(" depth = 1") print(" target = 1") print(" format = " + formats[format_]) print(" numMips = " + str(numMips)) print(" sliceSize = " + str(offset)) print("") print(" bits per pixel = " + str(bpp * 8)) print(" bytes per pixel = " + str(bpp)) if format_ == 1: if compSel not in [[0, 0, 0, 5], [0, 5, 5, 5]]: warn_color() elif format_ == 0xd: if compSel not in [[0, 0, 0, 1], [0, 5, 5, 1]]: warn_color() elif format_ == 0x3c: if compSel != [0, 1, 2, 5]: warn_color() else: if compSel != [0, 1, 2, 3]: warn_color() block_head_struct = NvBlockHeader() tex_blk_head = block_head_struct.pack(0x4E764248, 0x24, 0x78, 0x24, 2, numBlocks, 0) numBlocks += 1 tex_head_struct = NvTextureHeader() tex_head = tex_head_struct.pack(offset, alignment, width, height, 1, 1, format_, numMips, offset) image_blk_head = block_head_struct.pack(0x4E764248, 0x24, offset, 0x154, 3, numBlocks, 0) numBlocks += 1 align_blk = b'\x00' * 0x130 output = tex_blk_head + tex_head i = 0 for offset in mipOffsets: output += offset.to_bytes(4, 'little') i += 1 for z in range(17 - i): output += 0 .to_bytes(4, 'little') output += 0x700000004.to_bytes(12, 'little') output += image_blk_head output += align_blk output += swizzled_data return output, numBlocks
def writeGX2Surface_Data(f, tileMode, swizzle_, SRGB): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f, SRGB) if 0 in [width, dataSize] and data == []: return False if format_ not in formats: print("Unsupported DDS format!") return b'', [] if numMips > 13: print("Invalid number of mipmaps!") return b'', [] imageData = data[:dataSize] mipData = data[dataSize:] numMips += 1 bpp = addrlib.surfaceGetBitsPerPixel(format_) >> 3 alignment = 512 * bpp surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, 0) pitch = surfOut.pitch if surfOut.depth != 1: print("Unsupported depth!") return b'', [] if tileMode in [1, 2, 3, 16]: s = 0 else: s = 0xd0000 s |= swizzle_ swizzled_data = [] imageSize = 0 mipSize = 0 mipOffsets = [] for i in range(numMips): if i == 0: data = imageData imageSize = surfOut.surfSize else: offset, dataSize = get_curr_mip_off_size(width, height, bpp, i, format_ in BCn_formats) data = mipData[offset:offset + dataSize] surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, i) padSize = surfOut.surfSize - dataSize data += padSize * b"\x00" if i != 0: if i == 1: mipOffsets.append(imageSize) else: mipOffsets.append(mipSize) mipSize += len(data) swizzled_data.append( addrlib.swizzle(max(1, width >> i), max(1, height >> i), surfOut.height, format_, surfOut.tileMode, s, surfOut.pitch, surfOut.bpp, data)) gx2surf_struct = GX2Surface() gx2surf = gx2surf_struct.pack(1, width, height, 1, numMips, format_, 0, 1, imageSize, 0, mipSize, 0, tileMode, s, alignment, pitch) if numMips > 1: i = 0 for offset in mipOffsets: gx2surf += offset.to_bytes(4, 'big') i += 1 for z in range(14 - i): gx2surf += 0.to_bytes(4, 'big') else: gx2surf += b"\x00" * 56 gx2surf += numMips.to_bytes(4, 'big') gx2surf += b"\x00" * 4 gx2surf += 1.to_bytes(4, 'big') for value in compSel: gx2surf += value.to_bytes(1, 'big') gx2surf += b"\x00" * 20 return gx2surf, swizzled_data
def writeFLIM(f, tileMode, swizzle_, SRGB): # Read the DDS file width, height, format__, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f, SRGB) # Check if it was read correctly if 0 in [width, dataSize] and data == []: return b'' # Check if the texture format is supported if format__ not in formats: return b'' # Remove the mipmap data if it exists data = data[:dataSize] # GTX format -> BFLIM format # GTX format: 1 # if alpha: BFLIM format: 0 # else: BFLIM format: 1 if format__ == 1: if compSel[3] == 0: format_ = 1 else: format_ = 0 # GTX format: 0x1a # if one value is 0: BFLIM format: 6 (BAD CHOICE) # else: BFLIM format: 9 elif format__ == 0x1a: if 5 in compSel: format_ = 6 else: format_ = 9 # GTX format: 0x31 # if ETC1: BFLIM format: 0xa # else: BFLIM format: 0xc elif format__ == 0x31: if fourcc == b'ETC1': format_ = 0xa else: format_ = 0xc # GTX format: (key) -> BFLIM format: (value) else: fmt = { 7: 3, 8: 5, 0xa: 7, 0xb: 8, 0x32: 0xd, 0x33: 0xe, 0x34: 0x10, 0x35: 0x11, 0x41a: 0x14, 0x431: 0x15, 0x432: 0x16, 0x433: 0x17, 0x19: 0x18, } format_ = fmt[format__] # Check if colors are messed up or if R and B are swapped if format_ == 0: if compSel not in [[0, 0, 0, 5], [0, 5, 5, 5]]: warn_color(f) elif format_ == 1: if compSel != [5, 5, 5, 0]: warn_color(f) elif format_ in [2, 3]: if compSel not in [[0, 0, 0, 1], [0, 5, 5, 1]]: warn_color(f) elif format_ == 5: if compSel != [2, 1, 0, 5]: if compSel == [0, 1, 2, 5]: # Swap R and B data = dds.form_conv.swapRB_16bpp(data, 'rgb565') else: warn_color(f) elif format_ == 6: if compSel != [0, 1, 2, 5]: if compSel == [2, 1, 0, 5]: # Swap R and B data = dds.form_conv.swapRB_32bpp(data, 'rgba8') else: warn_color(f) elif format_ == 7: if compSel != [0, 1, 2, 3]: if compSel == [2, 1, 0, 3]: # Swap R and B data = dds.form_conv.swapRB_16bpp(data, 'rgb5a1') else: warn_color(f) elif format_ == 8: if compSel != [2, 1, 0, 3]: if compSel == [0, 1, 2, 3]: # Swap R and B data = dds.form_conv.swapRB_16bpp(data, 'argb4') else: warn_color(f) elif format_ in [9, 0x14, 0x18]: if compSel != [0, 1, 2, 3]: if compSel == [2, 1, 0, 3]: if format_ == 0x18: # Swap R and B data = dds.form_conv.swapRB_32bpp(data, 'bgr10a2') else: # Swap R and B data = dds.form_conv.swapRB_32bpp(data, 'rgba8') else: warn_color(f) # Get the Surface Info surfOut = addrlib.getSurfaceInfo(format__, width, height, 1, 1, tileMode, 0, 0) # Depths other than 1 are not supported if surfOut.depth != 1: return b'' # Pad the data padSize = surfOut.surfSize - len(data) data += padSize * b"\x00" # Pack the swizzle value and tileMode z = (swizzle_, tileMode) swizzle_tileMode = computeSwizzleTileMode(z) # Get the swizzle value used for (de)swizzling if tileMode in [1, 2, 3, 16]: s = swizzle_ << 8 else: s = 0xd0000 | (swizzle_ << 8) # Swizzle the data swizzled_data = addrlib.swizzle(width, height, surfOut.height, format__, surfOut.tileMode, s, surfOut.pitch, surfOut.bpp, data) # Get the alignment value alignment = surfOut.baseAlign # Pack the file header head_struct = FLIMHeader() head = head_struct.pack(b"FLIM", 0xFEFF, 0x14, 0x2020000, len(swizzled_data) + 0x28, 1) # Pack the `imag` header img_head_struct = imagHeader() imag_head = img_head_struct.pack(b"imag", 16, width, height, alignment, format_, swizzle_tileMode, len(swizzled_data)) # Build the file output = b"".join([swizzled_data, head, imag_head]) return output
def writeGFD(f, tileMode, swizzle_, SRGB, n, pos, numImages): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS(f, SRGB) if 0 in [width, dataSize] and data == []: print("") if n != (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_ not in formats: print("") print("Unsupported DDS format!") print("") if n != (numImages - 1): print("") print("Continuing in 5 seconds...") time.sleep(5) return b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if numMips > 13: print("") print("Invalid number of mipmaps for " + f) print("") if n != (numImages - 1): print("") print("Continuing in 5 seconds...") time.sleep(5) return b'' else: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) numMips += 1 bpp = addrlib.surfaceGetBitsPerPixel(format_) >> 3 surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, 0) alignment = surfOut.baseAlign imageSize = surfOut.surfSize pitch = surfOut.pitch if surfOut.depth != 1: print("") print("Unsupported depth!") print("") if n != (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 tileMode in [1, 2, 3, 16]: s = swizzle_ << 8 else: s = 0xd0000 | swizzle_ << 8 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 swizzled_data = [] mipSize = 0 mipOffsets = [] for mipLevel in range(numMips): offset, size = getCurrentMipOffset_Size(width, height, blkWidth, blkHeight, bpp, mipLevel) data_ = data[offset:offset + size] width_ = max(1, width >> mipLevel) height_ = max(1, height >> mipLevel) if mipLevel: print(str(mipLevel) + ": " + str(width_) + "x" + str(height_)) surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, mipLevel) if mipLevel == 1: mipOffsets.append(imageSize) else: mipOffsets.append(mipSize) data_ += b'\0' * (surfOut.surfSize - size) dataAlignBytes = b'\0' * (roundUp(mipSize, surfOut.baseAlign) - mipSize) if mipLevel: mipSize += surfOut.surfSize + len(dataAlignBytes) swizzled_data.append(bytearray(dataAlignBytes) + addrlib.swizzle( width_, height_, surfOut.height, format_, surfOut.tileMode, s, surfOut.pitch, surfOut.bpp, data_)) compSels = ["R", "G", "B", "A", "0", "1"] print("") print("// ----- GX2Surface Info ----- ") print(" dim = 1") print(" width = " + str(width)) print(" height = " + str(height)) print(" depth = 1") print(" numMips = " + str(numMips)) print(" format = " + formats[format_]) print(" aa = 0") print(" use = 1") print(" imageSize = " + str(imageSize)) print(" mipSize = " + str(mipSize)) print(" tileMode = " + str(tileMode)) print(" swizzle = " + str(s) + ", " + hex(s)) print(" alignment = " + str(alignment)) print(" pitch = " + str(pitch)) print("") print(" GX2 Component Selector:") print(" Red Channel: " + str(compSels[compSel[0]])) print(" Green Channel: " + str(compSels[compSel[1]])) print(" Blue Channel: " + str(compSels[compSel[2]])) print(" Alpha Channel: " + str(compSels[compSel[3]])) print("") print(" bits per pixel = " + str(bpp << 3)) print(" bytes per pixel = " + str(bpp)) print(" realSize = " + str(divRoundUp(width, blkWidth) * divRoundUp(height, blkHeight) * bpp)) if format_ == 1: if compSel not in [[0, 0, 0, 5], [0, 5, 5, 5]]: warn_color() compSel = [0, 5, 5, 5] elif format_ in [2, 7]: if compSel not in [[0, 0, 0, 1], [0, 5, 5, 1]]: warn_color() compSel = [0, 5, 5, 1] elif format_ == 8: if compSel not in [[0, 1, 2, 5], [2, 1, 0, 5]]: warn_color() if compSel[0] == 2 and compSel[2] == 0: swizzled_data = [dds.form_conv.swapRB_16bpp(data, 'rgb565') for data in swizzled_data] compSel = [0, 1, 2, 5] elif format_ in [0xa, 0xb]: if compSel not in [[0, 1, 2, 3], [2, 1, 0, 3]]: warn_color() if compSel[0] == 2 and compSel[2] == 0: if format_ == 0xb: swizzled_data = [dds.form_conv.swapRB_16bpp(data, 'rgba4') for data in swizzled_data] else: swizzled_data = [dds.form_conv.swapRB_16bpp(data, 'rgb5a1') for data in swizzled_data] compSel = [0, 1, 2, 3] elif format_ in [0x1a, 0x41a, 0x19]: if compSel not in [[0, 1, 2, 3], [2, 1, 0, 3], [0, 1, 2, 5], [2, 1, 0, 5]]: warn_color() if compSel[0] == 2 and compSel[2] == 0: if format_ == 0x19: swizzled_data = [dds.form_conv.swapRB_32bpp(data, 'bgr10a2') for data in swizzled_data] else: swizzled_data = [dds.form_conv.swapRB_32bpp(data, 'rgba8') for data in swizzled_data] compSel = [0, 1, 2, 3] block_head_struct = GFDBlockHeader() gx2surf_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xb, 0x9c, 0, 0) gx2surf_struct = GX2Surface() gx2surf = gx2surf_struct.pack(1, width, height, 1, numMips, format_, 0, 1, imageSize, 0, mipSize, 0, tileMode, s, alignment, pitch) image_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xc, imageSize, 0, 0) mip_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xd, mipSize, 0, 0) output = gx2surf_blk_head + gx2surf if numMips > 1: i = 0 for offset in mipOffsets: output += offset.to_bytes(4, 'big') i += 1 for z in range(14 - i): output += 0 .to_bytes(4, 'big') else: output += b'\0' * 56 output += numMips.to_bytes(4, 'big') output += b'\0' * 4 output += 1 .to_bytes(4, 'big') for value in compSel: output += value.to_bytes(1, 'big') if format_ in BCn_formats: output += makeRegsBytearray(width, height, numMips, format_, tileMode, pitch * 4, compSel) else: output += makeRegsBytearray(width, height, numMips, format_, tileMode, pitch, compSel) alignSize = getAlignBlockSize(pos + len(output) + 32, alignment) align_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, alignSize, 0, 0) output += align_blk_head output += b'\0' * alignSize output += image_blk_head output += swizzled_data[0] if numMips > 1: mipAlignSize = getAlignBlockSize(pos + len(output) + 32, alignment) mipAlign_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, mipAlignSize, 0, 0) output += mipAlign_blk_head output += b'\0' * mipAlignSize output += mip_blk_head for i in range(1, len(swizzled_data)): output += swizzled_data[i] return output
def writeFLIM(f, tileMode, swizzle_, SRGB): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f, SRGB) if 0 in [width, dataSize] and data == []: print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if format_ not in formats: print("") print("Unsupported DDS format!") print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) data = data[:dataSize] if format_ == 0xb: data = dds.form_conv.rgba4_to_argb4(data) if not tileMode: tileMode = addrlib.getDefaultGX2TileMode(1, width, height, 1, format_, 0, 1) bpp = addrlib.surfaceGetBitsPerPixel(format_) >> 3 surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, 0) alignment = surfOut.baseAlign padSize = surfOut.surfSize - dataSize data += padSize * b"\x00" tilingDepth = surfOut.depth if surfOut.tileMode == 3: tilingDepth //= 4 if tilingDepth != 1: print("") print("Unsupported depth!") print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) swizzle_tileMode = computeSwizzleTileMode((swizzle_, tileMode)) s = swizzle_ << 8 if tileMode not in [1, 2, 3, 16]: s |= 0xd0000 print("") print(" width = " + str(width)) print(" height = " + str(height)) print(" format = " + formats[format_]) print(" imageSize = " + str(len(data))) print(" tileMode = " + str(tileMode)) print(" swizzle = " + str(s) + ", " + hex(s)) print(" alignment = " + str(alignment)) print(" pitch = " + str(surfOut.pitch)) print("") print(" bits per pixel = " + str(bpp << 3)) print(" bytes per pixel = " + str(bpp)) print(" realSize = " + str(dataSize)) swizzled_data = addrlib.swizzle(width, height, 1, format_, 0, 1, surfOut.tileMode, s, surfOut.pitch, surfOut.bpp, 0, 0, data) if format_ == 1: if compSel[3] == 0: format_ = 1 else: format_ = 0 elif format_ == 0x1a: if 5 in compSel: format_ = 6 else: format_ = 9 elif format_ == 0x31: if fourcc == b'ETC1': format_ = 0xa else: format_ = 0xc else: fmt = { 2: 2, 7: 3, 8: 5, 0xa: 7, 0xb: 8, 0x32: 0xd, 0x33: 0xe, 0x34: 0x10, 0x35: 0x11, 0x41a: 0x14, 0x431: 0x15, 0x432: 0x16, 0x433: 0x17, 0x19: 0x18, } format_ = fmt[format_] if format_ == 0: if compSel not in [[0, 0, 0, 5], [0, 5, 5, 5]]: warn_color() elif format_ == 1: if compSel != [5, 5, 5, 0]: warn_color() elif format_ in [2, 3]: if compSel not in [[0, 0, 0, 1], [0, 5, 5, 1]]: warn_color() elif format_ == 5: if compSel != [2, 1, 0, 5]: if compSel == [0, 1, 2, 5]: swizzled_data = dds.form_conv.swapRB_16bpp( swizzled_data, 'rgb565') else: warn_color() elif format_ == 6: if compSel != [0, 1, 2, 5]: if compSel == [2, 1, 0, 5]: swizzled_data = dds.form_conv.swapRB_32bpp( swizzled_data, 'rgba8') else: warn_color() elif format_ == 7: if compSel != [0, 1, 2, 3]: if compSel == [2, 1, 0, 3]: swizzled_data = dds.form_conv.swapRB_16bpp( swizzled_data, 'rgb5a1') else: warn_color() elif format_ == 8: if compSel != [2, 1, 0, 3]: if compSel == [0, 1, 2, 3]: swizzled_data = dds.form_conv.swapRB_16bpp( swizzled_data, 'argb4') else: warn_color() elif format_ in [9, 0x14, 0x18]: if compSel != [0, 1, 2, 3]: if compSel == [2, 1, 0, 3]: if format_ == 0x18: swizzled_data = dds.form_conv.swapRB_32bpp( swizzled_data, 'bgr10a2') else: swizzled_data = dds.form_conv.swapRB_32bpp( swizzled_data, 'rgba8') else: warn_color() head_struct = FLIMHeader('>') head = head_struct.pack(b"FLIM", 0xFEFF, 0x14, 0x2020000, len(swizzled_data) + 0x28, 1) img_head_struct = imagHeader('>') imag_head = img_head_struct.pack(b"imag", 16, width, height, alignment, format_, swizzle_tileMode, len(swizzled_data)) output = swizzled_data + head + imag_head return output
def writeGFD(f): tileMode = 4 width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS(f) imageData = data[:dataSize] mipData = data[dataSize:] numMips += 1 if format_ == 0x33: align = 0x1EE4 mipAlign = 0x1FC0 else: align = 0x6E4 mipAlign = 0x7C0 bpp = addrlib.surfaceGetBitsPerPixel(format_) >> 3 alignment = 512 * bpp surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, 0) pitch = surfOut.pitch if format_ == 0x33: s = 0x40000 else: s = 0xd0000 swizzled_data = [] imageSize = 0 mipSize = 0 mipOffsets = [] for i in range(numMips): if i == 0: data = imageData imageSize = surfOut.surfSize else: offset, dataSize = get_curr_mip_off_size(width, height, bpp, i, format_ == 0x33) data = mipData[offset:offset + dataSize] surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, i) padSize = surfOut.surfSize - dataSize data += padSize * b"\x00" if i != 0: offset += padSize if i == 1: mipOffsets.append(imageSize) else: mipOffsets.append(offset) mipSize += len(data) swizzled_data.append(addrlib.swizzle(max(1, width >> i), max(1, height >> i), surfOut.height, format_, surfOut.tileMode, s, surfOut.pitch, surfOut.bpp, data)) block_head_struct = GFDBlockHeader() gx2surf_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xb, 0x9c, 0, 0) gx2surf_struct = GX2Surface() gx2surf = gx2surf_struct.pack(1, width, height, 1, numMips, format_, 0, 1, imageSize, 0, mipSize, 0, tileMode, s, alignment, pitch) align_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, align, 0, 0) image_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xc, imageSize, 0, 0) mipAlign_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, mipAlign, 0, 0) mip_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xd, mipSize, 0, 0) output = gx2surf_blk_head + gx2surf if numMips > 1: i = 0 for offset in mipOffsets: output += offset.to_bytes(4, 'big') i += 1 for z in range(14 - i): output += (0).to_bytes(4, 'big') else: output += b"\x00" * 56 output += numMips.to_bytes(4, 'big') output += b"\x00" * 4 output += (1).to_bytes(4, 'big') for value in compSel: output += value.to_bytes(1, 'big') output += b"\x00" * 20 output += align_blk_head output += b"\x00" * align output += image_blk_head output += swizzled_data[0] if numMips > 1: output += mipAlign_blk_head output += b"\x00" * mipAlign output += mip_blk_head i = 0 for data in swizzled_data: if i != 0: output += data i += 1 return output
def writeGFD(f): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f) numMips += 1 tileMode = addrlib.getDefaultGX2TileMode(1, width, height, 1, format_, 0, 1) bpp = addrlib.surfaceGetBitsPerPixel(format_) >> 3 surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, 0) alignment = surfOut.baseAlign imageSize = surfOut.surfSize pitch = surfOut.pitch tilingDepth = surfOut.depth if surfOut.tileMode == 3: tilingDepth //= 4 s = 0 if format_ == 0x33: blkWidth, blkHeight = 4, 4 else: blkWidth, blkHeight = 1, 1 swizzled_data = [] mipSize = 0 mipOffsets = [] tiling1dLevel = 0 tiling1dLevelSet = False for mipLevel in range(numMips): offset, size = getCurrentMipOffset_Size(width, height, blkWidth, blkHeight, bpp, mipLevel) data_ = data[offset:offset + size] width_ = max(1, width >> mipLevel) height_ = max(1, height >> mipLevel) if mipLevel: surfOut = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, mipLevel) if mipLevel == 1: mipOffsets.append(imageSize) else: mipOffsets.append(mipSize) data_ += b'\0' * (surfOut.surfSize - size) dataAlignBytes = b'\0' * (roundUp(mipSize, surfOut.baseAlign) - mipSize) if mipLevel: mipSize += surfOut.surfSize + len(dataAlignBytes) swizzled_data.append( bytearray(dataAlignBytes) + addrlib.swizzle( width_, height_, 1, format_, 0, 1, surfOut.tileMode, s, surfOut.pitch, surfOut.bpp, 0, 0, data_)) if surfOut.tileMode in [1, 2, 3, 16]: tiling1dLevelSet = True if not tiling1dLevelSet: tiling1dLevel += 1 if tiling1dLevelSet: s |= tiling1dLevel << 16 else: s |= 13 << 16 block_head_struct = GFDBlockHeader() gx2surf_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xb, 0x9c, 0, 0) gx2surf_struct = GX2Surface() gx2surf = gx2surf_struct.pack(1, width, height, 1, numMips, format_, 0, 1, imageSize, 0, mipSize, 0, tileMode, s, alignment, pitch) image_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xc, imageSize, 0, 0) mip_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xd, mipSize, 0, 0) output = gx2surf_blk_head + gx2surf if numMips > 1: i = 0 for offset in mipOffsets: output += offset.to_bytes(4, 'big') i += 1 for z in range(14 - i): output += 0.to_bytes(4, 'big') else: output += b'\0' * 56 output += numMips.to_bytes(4, 'big') output += b'\0' * 4 output += 1.to_bytes(4, 'big') for value in compSel: output += value.to_bytes(1, 'big') if format_ == 0x33: output += makeRegsBytearray(width, height, numMips, format_, tileMode, pitch * 4, compSel) else: output += makeRegsBytearray(width, height, numMips, format_, tileMode, pitch, compSel) alignSize = getAlignBlockSize(len(output) + 64, alignment) align_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, alignSize, 0, 0) output += align_blk_head output += b'\0' * alignSize output += image_blk_head output += swizzled_data[0] if numMips > 1: mipAlignSize = getAlignBlockSize(len(output) + 64, alignment) mipAlign_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 2, mipAlignSize, 0, 0) output += mipAlign_blk_head output += b'\0' * mipAlignSize output += mip_blk_head for i in range(1, len(swizzled_data)): output += swizzled_data[i] return output
def replace(self, texture, tileMode, SRGB, sparseBinding, sparseResidency, importMips, f): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f, SRGB) if 0 in [width, dataSize] and data == []: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported DDS file!") return False if format_ not in globals.formats: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported DDS format!") return False if not importMips: numMips = 1 else: numMips = max(1, numMips + 1) if tileMode == 1: alignment = 1 else: alignment = 512 if (format_ >> 8) in globals.blk_dims: blkWidth, blkHeight = globals.blk_dims[format_ >> 8] else: blkWidth, blkHeight = 1, 1 bpp = globals.bpps[format_ >> 8] if tileMode == 1: blockHeight = 1 blockHeightLog2 = 0 linesPerBlockHeight = 1 else: blockHeight = swizzle.getBlockHeight( DIV_ROUND_UP(height, blkHeight)) blockHeightLog2 = len(bin(blockHeight)[2:]) - 1 linesPerBlockHeight = blockHeight * 8 result = [] surfSize = 0 mipOffsets = [] blockHeightShift = 0 target = 1 if self.target == "NX " else 0 for mipLevel in range(numMips): offset, size = self.getCurrentMipOffset_Size( width, height, blkWidth, blkHeight, bpp, mipLevel) data_ = data[offset:offset + size] width_ = max(1, width >> mipLevel) height_ = max(1, height >> mipLevel) width__ = DIV_ROUND_UP(width_, blkWidth) height__ = DIV_ROUND_UP(height_, blkHeight) dataAlignBytes = b'\0' * (round_up(surfSize, alignment) - surfSize) surfSize += len(dataAlignBytes) mipOffsets.append(surfSize) if tileMode == 1: pitch = width__ * bpp if target == 1: pitch = round_up(width__ * bpp, 32) surfSize += pitch * height__ else: if pow2_round_up(height__) < linesPerBlockHeight: blockHeightShift += 1 pitch = round_up(width__ * bpp, 64) surfSize += pitch * round_up( height__, max(1, blockHeight >> blockHeightShift) * 8) result.append( bytearray(dataAlignBytes) + swizzle.swizzle( width_, height_, blkWidth, blkHeight, target, bpp, tileMode, max(0, blockHeightLog2 - blockHeightShift), data_, )) texture.readTexLayout = 1 if tileMode == 0 else 0 texture.sparseBinding = sparseBinding texture.sparseResidency = sparseResidency texture.dim = 2 texture.tileMode = tileMode texture.numMips = numMips texture.mipOffsets = mipOffsets texture.width = width texture.height = height texture.format_ = format_ texture.accessFlags = 0x20 texture.arrayLength = 1 texture.blockHeightLog2 = blockHeightLog2 texture.imageSize = surfSize texture.compSel = compSel texture.alignment = alignment texture.imgDim = 1 texture.data = b''.join(result) return texture
def inject(tex, tileMode, swizzle_, SRGB, importMips, oldImageSize, oldMipSize, f): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f, SRGB) if 0 in [width, dataSize] and data == []: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported DDS file.") return False if format_ not in globals.formats: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported DDS format.") return False elif numMips > 13: QtWidgets.QMessageBox.warning(None, "Error", "Invalid number of mipmaps.") return False if not importMips: numMips = 1 else: if tex.numMips < numMips + 1: QtWidgets.QMessageBox.warning( None, "Warning", "This DDS file has more mipmaps (%d) than the original image (%d)!\n" "Not all mipmaps might be imported." % (numMips, tex.numMips - 1), ) numMips += 1 bpp = addrlib.surfaceGetBitsPerPixel(format_) // 8 surfInfo = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, 0) if surfInfo.depth != 1: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported depth.") return False elif surfInfo.surfSize > oldImageSize: QtWidgets.QMessageBox.warning( None, "Error", 'This DDS has a larger filesize than the original image!', ) return False tex.surfInfo = surfInfo alignment = surfInfo.baseAlign imageSize = surfInfo.surfSize pitch = surfInfo.pitch if tileMode in [1, 2, 3, 16]: s = swizzle_ << 8 else: s = 0xd0000 | swizzle_ << 8 if format_ in globals.BCn_formats: blkWidth, blkHeight = 4, 4 else: blkWidth, blkHeight = 1, 1 mipSize = 0 numMips_ = 1 mipOffsets = [] result = [] for mipLevel in range(numMips): offset, size = getCurrentMipOffset_Size(width, height, blkWidth, blkHeight, bpp, mipLevel) data_ = data[offset:offset + size] width_ = max(1, width >> mipLevel) height_ = max(1, height >> mipLevel) if mipLevel: surfInfo = addrlib.getSurfaceInfo(format_, width, height, 1, 1, tileMode, 0, mipLevel) if mipLevel == 1: mipOffsets.append(imageSize) else: mipOffsets.append(mipSize) data_ += b'\0' * (surfInfo.surfSize - size) dataAlignBytes = b'\0' * (roundUp(mipSize, surfInfo.baseAlign) - mipSize) if mipLevel: mipSize += surfInfo.surfSize + len(dataAlignBytes) if mipSize > oldMipSize: mipSize -= surfInfo.surfSize + len(dataAlignBytes) mipLevel -= 1 break result.append( bytearray(dataAlignBytes) + addrlib.swizzle(width_, height_, surfInfo.height, format_, surfInfo .tileMode, s, surfInfo.pitch, surfInfo.bpp, data_)) tex.dim = 1 tex.width = width tex.height = height tex.depth = 1 tex.numMips = mipLevel + 1 tex.format = format_ tex.aa = 0 tex.use = 1 tex.imageSize = imageSize tex.mipSize = mipSize tex.tileMode = tileMode tex.swizzle = s tex.alignment = alignment tex.pitch = pitch tex.compSel = tex.compSel2 = compSel tex.mipOffsets = mipOffsets tex.blkWidth, tex.blkHeight = blkWidth, blkHeight tex.bpp = bpp tex.data = bytes(result[0]) tex.mipData = b''.join(result[1:]) return tex
def writeGFD(f): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS(f) numMips += 1 return writeGFDRaw(width, height, format_, fourcc, dataSize, compSel, numMips, data)
def inject(tex, tileMode, SRGB, sparseBinding, sparseResidency, importMips, oldImageSize, f): width, height, format_, fourcc, dataSize, compSel, numMips, data = dds.readDDS( f, SRGB) if 0 in [width, dataSize] and data == []: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported DDS file!") return False if format_ not in globals.formats: QtWidgets.QMessageBox.warning(None, "Error", "Unsupported DDS format!") return False if not importMips: numMips = 1 else: if tex.numMips < numMips + 1: QtWidgets.QMessageBox.warning( None, "Warning", "This DDS file has more mipmaps (%d) than the original image (%d)!" "\n%d mipmaps will be imported." % (numMips, tex.numMips - 1, tex.numMips - 1), ) numMips = max(1, min(tex.numMips, numMips + 1)) if tileMode == 1: alignment = 1 else: alignment = 512 if (format_ >> 8) in globals.blk_dims: blkWidth, blkHeight = globals.blk_dims[format_ >> 8] else: blkWidth, blkHeight = 1, 1 bpp = globals.bpps[format_ >> 8] if tileMode == 1: blockHeight = 1 blockHeightLog2 = 0 linesPerBlockHeight = 1 else: blockHeight = swizzle.getBlockHeight(DIV_ROUND_UP(height, blkHeight)) blockHeightLog2 = len(bin(blockHeight)[2:]) - 1 linesPerBlockHeight = blockHeight * 8 blockHeightShift = 0 surfSize = 0 for mipLevel in range(numMips): width_ = DIV_ROUND_UP(max(1, width >> mipLevel), blkWidth) height_ = DIV_ROUND_UP(max(1, height >> mipLevel), blkHeight) dataAlignBytes = b'\0' * (round_up(surfSize, alignment) - surfSize) surfSize += len(dataAlignBytes) if tileMode == 1: pitch = width_ * bpp if tex.target == 1: pitch = round_up(pitch, 32) surfSize += pitch * height_ else: if pow2_round_up(height_) < linesPerBlockHeight: blockHeightShift += 1 pitch = round_up(width_ * bpp, 64) surfSize += pitch * round_up( height_, max(1, blockHeight >> blockHeightShift) * 8) if surfSize > oldImageSize: QtWidgets.QMessageBox.warning( None, "Error", 'This DDS has a larger filesize than the original image!' '\nFor lowest filesize possible, use tiling mode "Linear".', ) return False result = [] surfSize = 0 mipOffsets = {} blockHeightShift = 0 for mipLevel in range(numMips): offset, size = getCurrentMipOffset_Size(width, height, blkWidth, blkHeight, bpp, mipLevel) data_ = data[offset:offset + size] width_ = max(1, width >> mipLevel) height_ = max(1, height >> mipLevel) width__ = DIV_ROUND_UP(width_, blkWidth) height__ = DIV_ROUND_UP(height_, blkHeight) dataAlignBytes = b'\0' * (round_up(surfSize, alignment) - surfSize) surfSize += len(dataAlignBytes) mipOffsets[mipLevel] = surfSize if tileMode == 1: pitch = width__ * bpp if tex.target == 1: pitch = round_up(pitch, 32) surfSize += pitch * height__ else: if pow2_round_up(height__) < linesPerBlockHeight: blockHeightShift += 1 pitch = round_up(width__ * bpp, 64) surfSize += pitch * round_up( height__, max(1, blockHeight >> blockHeightShift) * 8) result.append( bytearray(dataAlignBytes) + swizzle.swizzle( width_, height_, blkWidth, blkHeight, tex.target, bpp, tileMode, max(0, blockHeightLog2 - blockHeightShift), data_, )) tex.readTexLayout = 1 if tileMode == 0 else 0 tex.sparseBinding = sparseBinding tex.sparseResidency = sparseResidency tex.dim = 2 tex.tileMode = tileMode tex.numMips = numMips tex.mipOffsets = mipOffsets tex.width = width tex.height = height tex.format = format_ tex.accessFlags = 0x20 tex.arrayLength = 1 tex.blockHeightLog2 = blockHeightLog2 tex.imageSize = surfSize tex.compSel = compSel tex.compSel.reverse() tex.compSel2 = tex.compSel.copy() tex.alignment = alignment tex.type = 1 tex.data = b''.join(result) return tex