Exemplo 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
Exemplo n.º 2
0
def untileTex(tex):
    surfInfo = tex.surfInfo
    data = tex.data[:surfInfo.surfSize]

    result = []
    for mipLevel in range(tex.numMips):
        width = max(1, tex.width >> mipLevel)
        height = max(1, tex.height >> mipLevel)

        size = ceil(width / tex.blkWidth) * ceil(
            height / tex.blkHeight) * tex.bpp

        if mipLevel != 0:
            mipOffset = tex.mipOffsets[mipLevel - 1]
            if mipLevel == 1:
                mipOffset -= surfInfo.surfSize

            surfInfo = addrlib.getSurfaceInfo(tex.format, tex.width,
                                              tex.height, tex.depth, tex.dim,
                                              tex.tileMode, tex.aa, mipLevel)
            data = tex.mipData[mipOffset:mipOffset + surfInfo.surfSize]

        result_ = addrlib.deswizzle(
            width,
            height,
            surfInfo.height,
            tex.format,
            surfInfo.tileMode,
            tex.swizzle,
            surfInfo.pitch,
            surfInfo.bpp,
            data,
        )

        result.append(result_[:size])

    return result
Exemplo n.º 3
0
def readFLIM(f):
    flim = FLIMData()

    pos = len(f) - 0x28

    if f[pos + 4:pos + 6] == b'\xFF\xFE':
        bom = '<'

    elif f[pos + 4:pos + 6] == b'\xFE\xFF':
        bom = '>'

    header = FLIMHeader(bom)
    header.data(f, pos)

    if header.magic != b'FLIM':
        raise ValueError("Invalid file header!")

    pos += header.size

    info = imagHeader(bom)
    info.data(f, pos)

    if info.magic != b'imag':
        raise ValueError("Invalid imag header!")

    flim.width = info.width
    flim.height = info.height

    if info.format_ == 0x00:
        flim.format = 0x01
        flim.compSel = [0, 0, 0, 5]

    elif info.format_ == 0x01:
        flim.format = 0x01
        flim.compSel = [5, 5, 5, 0]

    elif info.format_ == 0x02:
        flim.format = 0x02
        flim.compSel = [0, 0, 0, 1]

    elif info.format_ == 0x03:
        flim.format = 0x07
        flim.compSel = [0, 0, 0, 1]

    elif info.format_ in [0x05, 0x19]:
        flim.format = 0x08
        flim.compSel = [2, 1, 0, 5]

    elif info.format_ == 0x06:
        flim.format = 0x1a
        flim.compSel = [0, 1, 2, 5]

    elif info.format_ == 0x07:
        flim.format = 0x0a
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x08:
        flim.format = 0x0b
        flim.compSel = [2, 1, 0, 3]

    elif info.format_ == 0x09:
        flim.format = 0x1a
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0C:
        flim.format = 0x31
        flim.format_ = "BC1"
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0D:
        flim.format = 0x32
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0E:
        flim.format = 0x33
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0F:
        flim.format = 0x34
        flim.compSel = [0, 0, 0, 5]

    elif info.format_ == 0x10:
        flim.format = 0x34
        flim.compSel = [5, 5, 5, 0]

    elif info.format_ == 0x11:
        flim.format = 0x35
        flim.compSel = [0, 0, 0, 1]

    elif info.format_ == 0x14:
        flim.format = 0x41a
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x15:
        flim.format = 0x431
        flim.format_ = "BC1"
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x16:
        flim.format = 0x432
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x17:
        flim.format = 0x433
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x18:
        flim.format = 0x19
        flim.compSel = [0, 1, 2, 3]

    else:
        raise NotImplementedError("Unsupported texture format: " +
                                  hex(info.format_))

    flim.imageSize = info.imageSize

    # Calculate swizzle and tileMode
    flim.swizzle, flim.tileMode = computeSwizzleTileMode(info.swizzle_tileMode)

    flim.alignment = info.alignment

    surfOut = addrlib.getSurfaceInfo(flim.format, flim.width, flim.height, 1,
                                     1, flim.tileMode, 0, 0)

    if surfOut.depth != 1:
        raise NotImplementedError("Unsupported depth!")

    flim.pitch = surfOut.pitch

    flim.data = f[:info.imageSize]

    flim.surfOut = surfOut

    return flim
Exemplo 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
Exemplo n.º 5
0
def get_deswizzled_data(i, gfd):
    majorVersion = gfd.majorVersion
    numImages = gfd.numImages
    numMips = gfd.numMips[i]
    width = gfd.width[i]
    height = gfd.height[i]
    depth = gfd.depth[i]
    dim = gfd.dim[i]
    format_ = gfd.format[i]
    aa = gfd.aa[i]
    tileMode = gfd.tileMode[i]
    swizzle_ = gfd.swizzle[i]
    compSel = gfd.compSel[i]
    data = gfd.data[i]
    realSize = gfd.realSize[i]
    mipOffsets = gfd.mipOffsets[i]

    surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, 0)
    bpp = divRoundUp(surfOut.bpp, 8)

    try:
        mipData = gfd.mipData[i]

    except KeyError:
        mipData = b''

    if format_ in formats:
        if aa != 0:
            print("")
            print("Unsupported aa!")
            print("")

            if i != (numImages - 1):
                print("Continuing in 5 seconds...")
                time.sleep(5)
                return b'', []

            else:
                print("Exiting in 5 seconds...")
                time.sleep(5)
                sys.exit(1)

        if format_ == 0x00:
            print("")
            print("Invalid texture format!")
            print("")

            if i != (numImages - 1):
                print("Continuing in 5 seconds...")
                time.sleep(5)
                return b'', []

            else:
                print("Exiting in 5 seconds...")
                time.sleep(5)
                sys.exit(1)

        else:
            if format_ in [0x1a, 0x41a]:
                format__ = 28

            elif format_ == 0x19:
                format__ = 24

            elif format_ == 0x8:
                format__ = 85

            elif format_ == 0xa:
                format__ = 86

            elif format_ == 0xb:
                format__ = 115

            elif format_ == 0x1:
                format__ = 61

            elif format_ == 0x7:
                format__ = 49

            elif format_ == 0x2:
                format__ = 112

            elif format_ in [0x31, 0x431]:
                format__ = "BC1"

            elif format_ in [0x32, 0x432]:
                format__ = "BC2"

            elif format_ in [0x33, 0x433]:
                format__ = "BC3"

            elif format_ == 0x34:
                format__ = "BC4U"

            elif format_ == 0x234:
                format__ = "BC4S"

            elif format_ == 0x35:
                format__ = "BC5U"

            elif format_ == 0x235:
                format__ = "BC5S"

            if surfOut.depth != 1:
                print("")
                print("Unsupported depth!")
                print("")

                if i != (numImages - 1):
                    print("Continuing in 5 seconds...")
                    time.sleep(5)
                    return b'', b'', b''

                else:
                    print("Exiting in 5 seconds...")
                    time.sleep(5)
                    sys.exit(1)

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

            if format_ in BCn_formats:
                blkWidth, blkHeight = 4, 4

            else:
                blkWidth, blkHeight = 1, 1

            result = []
            for mipLevel in range(numMips):
                width_ = max(1, width >> mipLevel)
                height_ = max(1, height >> mipLevel)

                size = divRoundUp(width_, blkWidth) * divRoundUp(height_, blkHeight) * bpp

                if mipLevel != 0:
                    print(str(mipLevel) + ": " + str(width_) + "x" + str(height_))

                    mipOffset = mipOffsets[mipLevel - 1]
                    if mipLevel == 1:
                        mipOffset -= surfOut.surfSize

                    surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim, tileMode, aa, mipLevel)
                    data = mipData[mipOffset:mipOffset + surfOut.surfSize]

                result_ = addrlib.deswizzle(
                    width_, height_, surfOut.height, format_, surfOut.tileMode,
                    swizzle_, surfOut.pitch, surfOut.bpp, data,
                )

                result.append(result_[:size])

            hdr = dds.generateHeader(numMips, width, height, format__, compSel, realSize, format_ in BCn_formats)

    else:
        print("")
        print("Unsupported texture format_: " + hex(format_))
        print("")

        if i != (numImages - 1):
            print("Continuing in 5 seconds...")
            time.sleep(5)
            hdr, result = b'', []

        else:
            print("Exiting in 5 seconds...")
            time.sleep(5)
            sys.exit(1)

    return hdr, result
Exemplo n.º 6
0
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
Exemplo n.º 7
0
def readFLIM(f):
    flim = FLIMData()

    pos = len(f) - 0x28

    if f[pos + 4:pos + 6] == b'\xFF\xFE':
        bom = '<'

    elif f[pos + 4:pos + 6] == b'\xFE\xFF':
        bom = '>'

    header = FLIMHeader(bom)
    header.data(f, pos)

    if header.magic != b'FLIM':
        raise ValueError("Invalid file header!")

    pos += header.size

    info = imagHeader(bom)
    info.data(f, pos)

    if info.magic != b'imag':
        raise ValueError("Invalid imag header!")

    flim.width = info.width
    flim.height = info.height

    if info.format_ == 0x00:
        flim.format = 0x01
        flim.compSel = [0, 0, 0, 5]

    elif info.format_ == 0x01:
        flim.format = 0x01
        flim.compSel = [5, 5, 5, 0]

    elif info.format_ == 0x02:
        flim.format = 0x02
        flim.compSel = [0, 0, 0, 1]

    elif info.format_ == 0x03:
        flim.format = 0x07
        flim.compSel = [0, 0, 0, 1]

    elif info.format_ in [0x05, 0x19]:
        flim.format = 0x08
        flim.compSel = [2, 1, 0, 5]

    elif info.format_ == 0x06:
        flim.format = 0x1a
        flim.compSel = [0, 1, 2, 5]

    elif info.format_ == 0x07:
        flim.format = 0x0a
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x08:
        flim.format = 0x0b
        flim.compSel = [2, 1, 0, 3]

    elif info.format_ == 0x09:
        flim.format = 0x1a
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0a:
        flim.format = 0x31
        flim.format_ = "ETC1"
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0C:
        flim.format = 0x31
        flim.format_ = "BC1"
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0D:
        flim.format = 0x32
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x0E:
        flim.format = 0x33
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ in [0x0F, 0x10]:
        flim.format = 0x34
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x11:
        flim.format = 0x35
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x14:
        flim.format = 0x41a
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x15:
        flim.format = 0x431
        flim.format_ = "BC1"
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x16:
        flim.format = 0x432
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x17:
        flim.format = 0x433
        flim.compSel = [0, 1, 2, 3]

    elif info.format_ == 0x18:
        flim.format = 0x19
        flim.compSel = [0, 1, 2, 3]

    else:
        print("")
        print("Unsupported texture format: " + hex(info.format_))
        print("Exiting in 5 seconds...")
        time.sleep(5)
        sys.exit(1)

    flim.imageSize = info.imageSize

    # Calculate swizzle and tileMode
    flim.swizzle, flim.tileMode = computeSwizzleTileMode(info.swizzle_tileMode)
    if not 1 <= flim.tileMode <= 16:
        print("")
        print("Invalid tileMode!")
        print("Exiting in 5 seconds...")
        time.sleep(5)
        sys.exit(1)

    flim.alignment = info.alignment

    surfOut = addrlib.getSurfaceInfo(flim.format, flim.width, flim.height, 1,
                                     1, flim.tileMode, 0, 0)

    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)

    flim.pitch = surfOut.pitch

    flim.data = f[:info.imageSize]

    flim.surfOut = surfOut

    if flim.format in BCn_formats:
        flim.realSize = ((flim.width + 3) >> 2) * ((flim.height + 3) >> 2) * (
            addrlib.surfaceGetBitsPerPixel(flim.format) // 8)

    else:
        flim.realSize = flim.width * flim.height * (
            addrlib.surfaceGetBitsPerPixel(flim.format) // 8)

    return flim
Exemplo n.º 8
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
Exemplo n.º 9
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
Exemplo n.º 10
0
def read(bfresData):
    assert bfresData[:4] == b"FRES" and bfresData[4:8] != b'    '

    version = bfresData[4]
    assert version in [3, 4]

    group = empty()
    group.pos = struct.unpack(">i", bfresData[0x24:0x28])[0]

    if group.pos == 0:
        return False

    group.pos += 0x28
    group.count = struct.unpack(">i", bfresData[group.pos:group.pos + 4])[0]
    group.pos += 20

    textures = []

    for i in range(group.count):
        nameAddr = struct.unpack(
            ">i", bfresData[group.pos + 16 * i + 8:group.pos + 16 * i + 12])[0]
        nameAddr += group.pos + 16 * i + 8

        name = bytes_to_string(bfresData, nameAddr)

        pos = struct.unpack(
            ">i",
            bfresData[group.pos + 16 * i + 12:group.pos + 16 * i + 16])[0]
        pos += group.pos + 16 * i + 12

        ftex = empty()
        ftex.headAddr = pos

        pos += 4

        surface = GX2Surface()
        surface.data(bfresData, pos)
        pos += surface.size

        if version == 4:
            surface.numMips = 1

        elif surface.numMips > 14:
            continue

        mipOffsets = []
        for j in range(13):
            mipOffsets.append(bfresData[j * 4 + pos] << 24
                              | bfresData[j * 4 + 1 + pos] << 16
                              | bfresData[j * 4 + 2 + pos] << 8
                              | bfresData[j * 4 + 3 + pos])

        pos += 68

        compSel = []
        compSel2 = []
        for j in range(4):
            comp = bfresData[pos + j]
            compSel2.append(comp)
            if comp == 4:  # Sorry, but this is unsupported.
                comp = j

            compSel.append(comp)

        pos += 24

        ftex.name = name
        ftex.dim = surface.dim
        ftex.width = surface.width
        ftex.height = surface.height
        ftex.depth = surface.depth
        ftex.numMips = surface.numMips
        ftex.format = surface.format_
        ftex.aa = surface.aa
        ftex.use = surface.use
        ftex.imageSize = surface.imageSize
        ftex.imagePtr = surface.imagePtr
        ftex.mipSize = surface.mipSize
        ftex.mipPtr = surface.mipPtr
        ftex.tileMode = surface.tileMode
        ftex.swizzle = surface.swizzle
        ftex.alignment = surface.alignment
        ftex.pitch = surface.pitch
        ftex.compSel = compSel
        ftex.compSel2 = compSel2
        ftex.mipOffsets = mipOffsets

        ftex.surfInfo = addrlib.getSurfaceInfo(ftex.format, ftex.width,
                                               ftex.height, ftex.depth,
                                               ftex.dim, ftex.tileMode,
                                               ftex.aa, 0)

        if ftex.format in BCn_formats:
            ftex.blkWidth, ftex.blkHeight = 4, 4

        else:
            ftex.blkWidth, ftex.blkHeight = 1, 1

        ftex.bpp = addrlib.surfaceGetBitsPerPixel(surface.format_) // 8

        dataAddr = struct.unpack(
            ">i", bfresData[ftex.headAddr + 0xB0:ftex.headAddr + 0xB4])[0]
        dataAddr += ftex.headAddr + 0xB0

        ftex.dataAddr = dataAddr
        ftex.data = bfresData[dataAddr:dataAddr + ftex.imageSize]

        mipAddr = struct.unpack(
            ">i", bfresData[ftex.headAddr + 0xB4:ftex.headAddr + 0xB8])[0]
        if mipAddr and ftex.mipSize:
            mipAddr += ftex.headAddr + 0xB4
            ftex.mipData = bfresData[mipAddr:mipAddr + ftex.mipSize]

        else:
            ftex.mipData = b''

        textures.append((name, ftex))

    return textures
Exemplo n.º 11
0
def read(file):
    with open(file, "rb") as inf:
        f = inf.read()

    if f[:4] != b"FRES" or f[4:8] == b'    ':
        QtWidgets.QMessageBox.warning(None, "Error", "Invalid file header!")
        return False

    version = f[4]

    if version not in [3, 4]:
        QtWidgets.QMessageBox.warning(None, "Error",
                                      "Unsupported BFRES version!")
        return False

    group = empty()
    group.pos = struct.unpack(">i", f[0x24:0x28])[0]

    if group.pos == 0:
        return False

    group.pos += 0x28
    group.count = struct.unpack(">i", f[group.pos:group.pos + 4])[0]
    group.pos += 20

    textures = []
    texNames = []
    texSizes = []

    for i in range(group.count):
        nameAddr = struct.unpack(
            ">i", f[group.pos + 16 * i + 8:group.pos + 16 * i + 12])[0]
        nameAddr += group.pos + 16 * i + 8

        name = bytes_to_string(f, nameAddr)

        pos = struct.unpack(">i", f[group.pos + 16 * i + 12:group.pos +
                                    16 * i + 16])[0]
        pos += group.pos + 16 * i + 12

        ftex = empty()
        ftex.headAddr = pos

        pos += 4

        surface = GX2Surface()
        surface.data(f, pos)
        pos += surface.size

        if version == 4:
            surface.numMips = 1

        elif surface.numMips > 14:
            continue

        mipOffsets = []
        for j in range(13):
            mipOffsets.append(f[j * 4 + pos] << 24
                              | f[j * 4 + 1 + pos] << 16
                              | f[j * 4 + 2 + pos] << 8
                              | f[j * 4 + 3 + pos])

        pos += 68

        compSel = []
        compSel2 = []
        for j in range(4):
            comp = f[pos + j]
            compSel2.append(comp)
            if comp == 4:  # Sorry, but this is unsupported.
                comp = j

            compSel.append(comp)

        pos += 24

        ftex.name = name
        ftex.dim = surface.dim
        ftex.width = surface.width
        ftex.height = surface.height
        ftex.depth = surface.depth
        ftex.numMips = surface.numMips
        ftex.format = surface.format_
        ftex.aa = surface.aa
        ftex.use = surface.use
        ftex.imageSize = surface.imageSize
        ftex.imagePtr = surface.imagePtr
        ftex.mipSize = surface.mipSize
        ftex.mipPtr = surface.mipPtr
        ftex.tileMode = surface.tileMode
        ftex.swizzle = surface.swizzle
        ftex.alignment = surface.alignment
        ftex.pitch = surface.pitch
        ftex.compSel = compSel
        ftex.compSel2 = compSel2
        ftex.mipOffsets = mipOffsets

        ftex.surfInfo = addrlib.getSurfaceInfo(ftex.format, ftex.width,
                                               ftex.height, ftex.depth,
                                               ftex.dim, ftex.tileMode,
                                               ftex.aa, 0)

        if ftex.format in globals.BCn_formats:
            ftex.blkWidth, ftex.blkHeight = 4, 4

        else:
            ftex.blkWidth, ftex.blkHeight = 1, 1

        ftex.bpp = addrlib.surfaceGetBitsPerPixel(surface.format_) // 8

        dataAddr = struct.unpack(">i", f[ftex.headAddr + 0xB0:ftex.headAddr +
                                         0xB4])[0]
        dataAddr += ftex.headAddr + 0xB0

        ftex.dataAddr = dataAddr
        ftex.data = f[dataAddr:dataAddr + ftex.imageSize]

        mipAddr = struct.unpack(">i", f[ftex.headAddr + 0xB4:ftex.headAddr +
                                        0xB8])[0]
        if mipAddr and ftex.mipSize:
            mipAddr += ftex.headAddr + 0xB4
            ftex.mipData = f[mipAddr:mipAddr + ftex.mipSize]

        else:
            ftex.mipData = b''

        textures.append(ftex)
        texNames.append(name)
        texSizes.append([ftex.imageSize, ftex.mipSize])

    globals.fileData = bytearray(f)
    globals.texSizes = texSizes

    return textures, texNames
Exemplo n.º 12
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
Exemplo n.º 13
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
Exemplo n.º 14
0
    def calcSurfaceSizeAndAlignment(self):
        # Calculate the best tileMode if set to default
        if self.tileMode == GX2TileMode.Default:
            self.tileMode = GX2TileMode(addrlib.getDefaultGX2TileMode(
                self.dim.value, self.width, self.height, self.depth,
                self.format.value, self.aa.value, self.use.value,
            ))

        # Calculate the surface info for the base level
        surfInfo = addrlib.getSurfaceInfo(
            self.format.value, self.width, self.height, self.depth,
            self.dim.value, self.tileMode.value, self.aa.value, 0,
        )

        # Set the image size, alignment and pitch
        self.imageSize = surfInfo.surfSize
        self.alignment = surfInfo.baseAlign
        self.pitch = surfInfo.pitch

        # Ensure pipe and bank swizzle is valid
        self.swizzle &= 0x0700

        # Calculate the swizzle 1D tiling start level, mip size, mip offsets and 
        tiling1dLevel = 0
        tiling1dLevelSet = GX2TileMode(surfInfo.tileMode) in (
            GX2TileMode.Linear_Aligned, GX2TileMode.Linear_Special,
            GX2TileMode.Tiled_1D_Thin1, GX2TileMode.Tiled_1D_Thick,
        )
        if not tiling1dLevelSet:
            tiling1dLevel += 1

        self.mipSize = 0
        for mipLevel in range(1, self.numMips):
            # Calculate the surface info for the mip level
            surfInfo = addrlib.getSurfaceInfo(
                self.format.value, self.width, self.height, self.depth,
                self.dim.value, self.tileMode.value, self.aa.value, mipLevel,
            )

            # Make sure the level is aligned
            self.mipSize = roundUp(self.mipSize, surfInfo.baseAlign)

            # Set the offset of the level
            ## Level 1 offset is used to place the mip data (levels 1+) after the image data (level 0)
            ## The value is the minimum size of the image data + padding to ensure the mip data is aligned 
            if mipLevel == 1:
                # Level 1 alignment should suffice to ensure all the other levels are aligned as well
                self.mipOffset[0] = roundUp(self.imageSize, surfInfo.baseAlign)

            else:
                # Level offset should be the size of all previous levels (aligned)
                self.mipOffset[mipLevel - 1] = self.mipSize

            # Increase the total mip size by this level's size
            self.mipSize += surfInfo.surfSize

            # Calculate the swizzle 1D tiling start level for tiled surfaces
            if not tiling1dLevelSet:
                # Check if the tiling mode switched to 1D tiling
                tileMode = GX2TileMode(surfInfo.tileMode)
                if tileMode in (GX2TileMode.Tiled_1D_Thin1, GX2TileMode.Tiled_1D_Thick):
                    tiling1dLevelSet = True

                else:
                    tiling1dLevel += 1

        ## If the tiling mode never switched to 1D tiling, set the start level to 13 (observed from existing files)
        if not tiling1dLevelSet:
            tiling1dLevel = 13

        self.swizzle |= tiling1dLevel << 16

        # Clear the unused mip offsets
        for mipLevel in range(self.numMips, 14):
            self.mipOffset[mipLevel - 1] = 0
Exemplo n.º 15
0
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
Exemplo n.º 16
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)
Exemplo n.º 17
0
def get_deswizzled_data(i, gfd):
    majorVersion = gfd.majorVersion
    numImages = gfd.numImages
    numMips = gfd.numMips[i]
    width = gfd.width[i]
    height = gfd.height[i]
    depth = gfd.depth[i]
    dim = gfd.dim[i]
    format_ = gfd.format[i]
    aa = gfd.aa[i]
    tileMode = gfd.tileMode[i]
    swizzle_ = gfd.swizzle[i]
    compSel = gfd.compSel[i]
    data = gfd.data[i]
    realSize = gfd.realSize[i]
    surfOut = addrlib.getSurfaceInfo(format_, width, height, depth, dim,
                                     tileMode, aa, 0)
    bpp = (surfOut.bpp + 7) // 8
    mipOffsets = gfd.mipOffsets[i]

    try:
        mipData = gfd.mipData[i]

    except KeyError:
        mipData = b''

    if format_ in formats:
        if aa != 0:
            print("")
            print("Unsupported aa!")
            print("")

            if i != (numImages - 1):
                print("Continuing in 5 seconds...")
                time.sleep(5)
                return b'', []

            else:
                print("Exiting in 5 seconds...")
                time.sleep(5)
                sys.exit(1)

        if format_ == 0x00:
            print("")
            print("Invalid texture format!")
            print("")

            if i != (numImages - 1):
                print("Continuing in 5 seconds...")
                time.sleep(5)
                return b'', []

            else:
                print("Exiting in 5 seconds...")
                time.sleep(5)
                sys.exit(1)

        else:
            if format_ == 0x1a or format_ == 0x41a:
                format__ = 28

            elif format_ == 0x19:
                format__ = 24

            elif format_ == 0x8:
                format__ = 85

            elif format_ == 0xa:
                format__ = 86

            elif format_ == 0xb:
                format__ = 115

            elif format_ == 0x1:
                format__ = 61

            elif format_ == 0x7:
                format__ = 49

            elif format_ == 0x2:
                format__ = 112

            elif format_ == 0x31 or format_ == 0x431:
                format__ = "BC1"

            elif format_ == 0x32 or format_ == 0x432:
                format__ = "BC2"

            elif format_ == 0x33 or format_ == 0x433:
                format__ = "BC3"

            elif format_ == 0x34:
                format__ = "BC4U"

            elif format_ == 0x234:
                format__ = "BC4S"

            elif format_ == 0x35:
                format__ = "BC5U"

            elif format_ == 0x235:
                format__ = "BC5S"

            if surfOut.depth != 1:
                print("")
                print("Unsupported depth!")
                print("")

                if i != (numImages - 1):
                    print("Continuing in 5 seconds...")
                    time.sleep(5)
                    return b'', b'', b''

                else:
                    print("Exiting in 5 seconds...")
                    time.sleep(5)
                    sys.exit(1)

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

            result = []
            for level in range(numMips):
                if format_ in BCn_formats:
                    size = ((max(1, width >> level) + 3) >> 2) * (
                        (max(1, height >> level) + 3) >> 2) * bpp

                else:
                    size = max(1, width >> level) * max(1,
                                                        height >> level) * bpp

                if level != 0:
                    print(
                        str(level) + ": " + str(max(1, width >> level)) + "x" +
                        str(max(1, height >> level)))

                    if level == 1:
                        mipOffset = mipOffsets[level - 1] - surfOut.surfSize

                    else:
                        mipOffset = mipOffsets[level - 1]

                    surfOut = addrlib.getSurfaceInfo(format_, width, height,
                                                     depth, dim, tileMode, aa,
                                                     level)

                    data = mipData[mipOffset:mipOffset + surfOut.surfSize]

                deswizzled = addrlib.deswizzle(max(1, width >> level),
                                               max(1, height >> level),
                                               surfOut.height, format_,
                                               surfOut.tileMode, swizzle_,
                                               surfOut.pitch, surfOut.bpp,
                                               data)

                data = deswizzled[:size]
                result.append(data)

            if format_ == 8:
                result = [dds.form_conv.swapRB_RGB565(data) for data in result]

            elif format_ == 0xa:
                if majorVersion == 6:
                    result = [
                        dds.form_conv.swapRB_RGB5A1(data) for data in result
                    ]

                else:
                    result = [
                        dds.form_conv.toDDSrgb5a1(data) for data in result
                    ]

            elif format_ == 0xb:
                result = [dds.form_conv.swapRB_RGBA4(data) for data in result]

            hdr = dds.generateHeader(numMips, width, height, format__, compSel,
                                     realSize, format_ in BCn_formats)

    else:
        print("")
        print("Unsupported texture format_: " + hex(format_))
        print("")

        if i != (numImages - 1):
            print("Continuing in 5 seconds...")
            time.sleep(5)
            hdr, result = b'', []

        else:
            print("Exiting in 5 seconds...")
            time.sleep(5)
            sys.exit(1)

    return hdr, result