Esempio n. 1
0
def writeGFD(data, width, height, compSel):
    imageData = bytes(data)

    surfOut = addrlib.getSurfaceInfo(0x1a, width, height, 1, 1, 4, 0, 0)
    alignment = surfOut.baseAlign
    imageSize = surfOut.surfSize
    pitch = surfOut.pitch

    imageData += b'\0' * (surfOut.surfSize - len(data))
    result = addrlib.swizzle(
        width,
        height,
        1,
        0x1a,
        0,
        1,
        surfOut.tileMode,
        0,
        surfOut.pitch,
        surfOut.bpp,
        0,
        0,
        imageData,
    )

    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, 1, 0x1a, 0, 1,
                                  imageSize, 0, 0, 0, 4, s, alignment, pitch)

    image_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 0xc, imageSize,
                                            0, 0)
    output = gx2surf_blk_head + gx2surf
    output += b'\0' * 56

    output += 1.to_bytes(4, 'big')
    output += b'\0' * 4
    output += 1.to_bytes(4, 'big')

    for value in compSel:
        output += value.to_bytes(1, 'big')

    output += makeRegsBytearray(width, height, 1, 0x1a, 4, 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 += result

    return output
Esempio n. 2
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)
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
Esempio n. 4
0
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
Esempio n. 6
0
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
Esempio n. 7
0
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
Esempio n. 8
0
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
Esempio n. 9
0
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 == []:
        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)

    imageData = data[:dataSize]
    mipData = data[dataSize:]
    numMips += 1

    mipAlign = 0
    align = 0

    if numImages == 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

    if numMips > 1:
        print("")
        print("Processing " + str(numMips - 1) + " mipmaps:")

    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)))

    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] == 0 and compSel[2] == 2:
            swizzled_data = [
                dds.form_conv.swapRB_RGB565(data) 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] == 0 and compSel[2] == 2:
            if format_ == 0xb:
                swizzled_data = [
                    dds.form_conv.swapRB_RGBA4(data) 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 format_ == 0x19 and compSel[3] == 5:
            warn_color()

        if compSel[0] == 2 and compSel[2] == 0:
            if format_ == 0x19:
                swizzled_data = [
                    dds.form_conv.swapRB_RGB10A2(data)
                    for data in swizzled_data
                ]

            else:
                swizzled_data = [
                    dds.form_conv.swapRB_RGBA8(data) 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)

    if align:
        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)

    if mipAlign:
        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

    if align:
        output += align_blk_head
        output += b"\x00" * align

    output += image_blk_head
    output += swizzled_data[0]

    if numMips > 1:
        if mipAlign:
            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