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
Example #2
0
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
Example #3
0
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
Example #5
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
Example #7
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
Example #8
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
Example #9
0
    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
Example #10
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
Example #11
0
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)
Example #12
0
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