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
Esempio n. 2
0
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]
Esempio n. 3
0
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
Esempio n. 4
0
    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)
Esempio n. 5
0
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
Esempio n. 6
0
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