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 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 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 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
else: aSurfIn.flags.value = aSurfIn.flags.value & 0xFFFFEFFF pSurfOut.size = 96 computeSurfaceInfo(aSurfIn, pSurfOut) pSurfOut = pOut return pSurfOut import pyximport pyximport.install() import addrlib_cy surfOut = addrlib_cy.getSurfaceInfo(0x1a, 2048, 512, 1, 1, 4, 0, 0) print(surfOut.size) print(surfOut.pitch) print(surfOut.height) print(surfOut.depth) print(surfOut.surfSize) print(surfOut.tileMode) print(surfOut.baseAlign) print(surfOut.pitchAlign) print(surfOut.heightAlign) print(surfOut.depthAlign) print(surfOut.bpp) print(surfOut.pixelPitch) print(surfOut.pixelHeight) print(surfOut.pixelBits) print(surfOut.sliceSize)
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 readGFD(f): gfd = GFDData() pos = 0 header = GFDHeader() header.data(f, pos) if header.magic != b'Gfx2': raise ValueError("Invalid file header!") pos += header.size blockB = False blockC = False images = 0 imgInfo = 0 gfd.dim = [] gfd.width = [] gfd.height = [] gfd.depth = [] gfd.numMips = [] gfd.format = [] gfd.aa = [] gfd.use = [] gfd.imageSize = [] gfd.imagePtr = [] gfd.mipSize = [] gfd.mipPtr = [] gfd.tileMode = [] gfd.swizzle = [] gfd.alignment = [] gfd.pitch = [] gfd.compSel = [] gfd.surfOut = [] gfd.realSize = [] gfd.dataSize = [] gfd.data = [] while pos < len(f): # Loop through the entire file, stop if reached the end of the file. block = GFDBlockHeader() block.data(f, pos) if block.magic != b'BLK{': raise ValueError("Invalid block header!") pos += block.size if block.type_ == 0x0B: imgInfo += 1 blockB = True surface = GX2Surface() surface.data(f, pos) pos += surface.size pos += 68 compSel = [] for i in range(4): compSel.append(f[pos + i]) pos += 24 if surface.format_ in BCn_formats: width = surface.width // 4 height = surface.height // 4 else: width = surface.width height = surface.height surfOut = addrlib.getSurfaceInfo(surface.format_, width, height, surface.depth, surface.dim, surface.tileMode, surface.aa, 0) gfd.dim.append(surface.dim) gfd.width.append(surface.width) gfd.height.append(surface.height) gfd.depth.append(surface.depth) gfd.numMips.append(surface.numMips) gfd.format.append(surface.format_) gfd.aa.append(surface.aa) gfd.use.append(surface.use) gfd.imageSize.append(surface.imageSize) gfd.imagePtr.append(surface.imagePtr) gfd.mipSize.append(surface.mipSize) gfd.mipPtr.append(surface.mipPtr) gfd.tileMode.append(surface.tileMode) gfd.swizzle.append(surface.swizzle) gfd.alignment.append(surface.alignment) gfd.pitch.append(surfOut.pitch) gfd.compSel.append(compSel) gfd.surfOut.append(surfOut) if surface.format_ in BCn_formats: gfd.realSize.append(((surface.width + 3) >> 2) * ((surface.height + 3) >> 2) * ( addrlib.surfaceGetBitsPerPixel(surface.format_) // 8)) else: gfd.realSize.append( surface.width * surface.height * (addrlib.surfaceGetBitsPerPixel(surface.format_) // 8)) elif block.type_ == 0x0C: images += 1 blockC = True gfd.dataSize.append(block.dataSize) gfd.data.append(f[pos:pos + block.dataSize]) pos += block.dataSize else: pos += block.dataSize if images != imgInfo: print("") print("Whoops, fail! XD") print("") print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if blockB: if not blockC: print("") print("Image info was found but no Image data was found.") print("") print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) if not blockB: if not blockC: print("") print("No Image was found in this file.") print("") print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) elif blockC: print("") print("Image data was found but no Image info was found.") print("") print("Exiting in 5 seconds...") time.sleep(5) sys.exit(1) gfd.numImages = images return gfd