def get_deswizzled_data(flim):
    if flim.format == 0x01:
        format_ = 61

    elif flim.format == 0x02:
        format_ = 112

    elif flim.format == 0x07:
        format_ = 49

    elif flim.format == 0x08:
        format_ = 85

    elif flim.format == 0x0a:
        format_ = 86

    elif flim.format == 0x0b:
        format_ = 115

    elif flim.format in [0x1a, 0x41a]:
        format_ = 28

    elif flim.format == 0x19:
        format_ = 24

    elif flim.format in [0x31, 0x431]:
        format_ = flim.format_

    elif flim.format in [0x32, 0x432]:
        format_ = "BC2"

    elif flim.format in [0x33, 0x433]:
        format_ = "BC3"

    elif flim.format == 0x34:
        format_ = "BC4U"

    elif flim.format == 0x35:
        format_ = "BC5U"

    result = addrlib.deswizzle(flim.width, flim.height, 1, flim.format, 0, 1,
                               flim.surfOut.tileMode, flim.swizzle, flim.pitch,
                               flim.surfOut.bpp, 0, 0, flim.data)

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

    else:
        size = flim.width * flim.height * (
            addrlib.surfaceGetBitsPerPixel(flim.format) >> 3)

    result = result[:size]

    hdr = dds.generateHeader(1, flim.width, flim.height, format_, flim.compSel,
                             size, flim.format in BCn_formats)

    return hdr, result
Exemple #2
0
def get_deswizzled_data(flim):
    result = addrlib.deswizzle(flim.width, flim.height, 1, flim.format, 0, 1,
                               flim.surfOut.tileMode, flim.swizzle, flim.pitch,
                               flim.surfOut.bpp, 0, 0, flim.data)

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

    else:
        size = flim.width * flim.height * (
            addrlib.surfaceGetBitsPerPixel(flim.format) >> 3)

    return result[:size]
Exemple #3
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
Exemple #4
0
def readGFD(f):
    gfd = GFDData()

    header = GFDHeader()
    header.data(f, 0)

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

    if header.majorVersion == 6:
        surfBlkType = 0x0A
        dataBlkType = 0x0B
        mipBlkType = 0x0C

    elif header.majorVersion == 7:
        surfBlkType = 0x0B
        dataBlkType = 0x0C
        mipBlkType = 0x0D

    else:
        raise ValueError("Unsupported GTX version!")

    if header.gpuVersion != 2:
        raise ValueError("Unsupported GPU version!")

    gfd.majorVersion = header.majorVersion

    pos = header.size

    blockB = False
    blockC = False

    images = 0
    imgInfo = 0

    gfd.dim = []
    gfd.width = []
    gfd.height = []
    gfd.depth = []
    gfd.numMips = []
    gfd.format = []
    gfd.aa = []
    gfd.use = []
    gfd.imageSize = []
    gfd.imagePtr = []
    gfd.mipSize = []
    gfd.mipPtr = []
    gfd.tileMode = []
    gfd.swizzle = []
    gfd.alignment = []
    gfd.pitch = []
    gfd.compSel = []
    gfd.bpp = []
    gfd.realSize = []

    gfd.dataSize = []
    gfd.data = []

    gfd.mipOffsets = []
    gfd.mipData = {}

    while pos < len(f):  # Loop through the entire file, stop if reached the end of the file.
        block = GFDBlockHeader()
        block.data(f, pos)

        if block.magic != b'BLK{':
            raise ValueError("Invalid block header!")

        pos += block.size

        if block.type_ == surfBlkType:
            imgInfo += 1
            blockB = True

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

            pos += surface.size

            if surface.numMips > 14:
                print("")
                print("Invalid number of mipmaps for image " + str(imgInfo - 1))
                print("")
                print("Exiting in 5 seconds...")
                time.sleep(5)
                sys.exit(1)

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

            gfd.mipOffsets.append(mipOffsets)

            pos += 68

            if surface.format_ in [0xa, 0xb, 0x19, 0x1a, 0x41a] or surface.format_ in BCn_formats:
                compSel = [0, 1, 2, 3]

            elif surface.format_ in [2, 7]:
                compSel = [0, 5, 5, 1]

            elif surface.format_ == 1:
                compSel = [0, 5, 5, 5]

            elif surface.format_ == 8:
                compSel = [0, 1, 2, 5]

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

            pos += 24

            gfd.dim.append(surface.dim)
            gfd.width.append(surface.width)
            gfd.height.append(surface.height)
            gfd.depth.append(surface.depth)
            gfd.numMips.append(surface.numMips)
            gfd.format.append(surface.format_)
            gfd.aa.append(surface.aa)
            gfd.use.append(surface.use)
            gfd.imageSize.append(surface.imageSize)
            gfd.imagePtr.append(surface.imagePtr)
            gfd.mipSize.append(surface.mipSize)
            gfd.mipPtr.append(surface.mipPtr)
            gfd.tileMode.append(surface.tileMode)
            gfd.swizzle.append(surface.swizzle)
            gfd.alignment.append(surface.alignment)
            gfd.pitch.append(surface.pitch)
            gfd.compSel.append(compSel)

            bpp = roundUp(addrlib.surfaceGetBitsPerPixel(surface.format_), 8)
            gfd.bpp.append(bpp)

            if surface.format_ in BCn_formats:
                gfd.realSize.append(divRoundUp(surface.width, 4) * divRoundUp(surface.height, 4) * (bpp // 8))

            else:
                gfd.realSize.append(surface.width * surface.height * (bpp // 8))

        elif block.type_ == dataBlkType:
            images += 1
            blockC = True

            gfd.dataSize.append(block.dataSize)
            gfd.data.append(f[pos:pos + block.dataSize])
            pos += block.dataSize

        elif block.type_ == mipBlkType:
            gfd.mipData[images - 1] = f[pos:pos + block.dataSize]
            pos += block.dataSize

        else:
            pos += block.dataSize

    if images != imgInfo:
        print("")
        print("GX2 Surface and Image data count mismatch.")
        print("")
        print("Exiting in 5 seconds...")
        time.sleep(5)
        sys.exit(1)

    if blockB:
        if not blockC:
            print("")
            print("GX2 Surface was found but no Image data was found.")
            print("")
            print("Exiting in 5 seconds...")
            time.sleep(5)
            sys.exit(1)
    if not blockB:
        if not blockC:
            print("")
            print("No Image was found in this file.")
            print("")
            print("Exiting in 5 seconds...")
            time.sleep(5)
            sys.exit(1)

        elif blockC:
            print("")
            print("Image data was found but no GX2 Surface was found.")
            print("")
            print("Exiting in 5 seconds...")
            time.sleep(5)
            sys.exit(1)

    gfd.numImages = images

    return gfd
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
def main():
    print("BFLIM Extractor v2.3")
    print("(C) 2016-2019 AboodXD")

    input_ = sys.argv[-1]

    if not (input_.endswith('.bflim') or input_.endswith('.dds')):
        printInfo()

    toFLIM = False

    if input_.endswith('.dds'):
        toFLIM = True

    if "-o" in sys.argv:
        output_ = sys.argv[sys.argv.index("-o") + 1]

    else:
        output_ = os.path.splitext(input_)[0] + (".bflim"
                                                 if toFLIM else ".dds")

    print("")
    print('Converting: ' + input_)

    if toFLIM:
        if "-tileMode" in sys.argv:
            tileMode = int(sys.argv[sys.argv.index("-tileMode") + 1], 0)

        else:
            tileMode = 0

        if "-swizzle" in sys.argv:
            swizzle = int(sys.argv[sys.argv.index("-swizzle") + 1], 0)

        else:
            swizzle = 0

        if "-SRGB" in sys.argv:
            SRGB = int(sys.argv[sys.argv.index("-SRGB") + 1], 0)

        else:
            SRGB = 0

        if SRGB > 1 or not 0 <= tileMode <= 16 or not 0 <= swizzle <= 7:
            printInfo()

        data = writeFLIM(input_, tileMode, swizzle, SRGB)

        with open(output_, "wb+") as output:
            output.write(data)

    else:
        with open(input_, "rb") as inf:
            inb = inf.read()

        flim = readFLIM(inb)

        print("")
        print("  width           = " + str(flim.width))
        print("  height          = " + str(flim.height))

        if flim.format in formats:
            print("  format          = " + formats[flim.format])

        else:
            print("  format          = " + hex(flim.format))

        print("  imageSize       = " + str(flim.imageSize))
        print("  tileMode        = " + str(flim.tileMode))
        print("  swizzle         = " + str(flim.swizzle) + ", " +
              hex(flim.swizzle))
        print("  alignment       = " + str(flim.alignment))
        print("  pitch           = " + str(flim.pitch))

        bpp = addrlib.surfaceGetBitsPerPixel(flim.format)

        print("")
        print("  bits per pixel  = " + str(bpp))
        print("  bytes per pixel = " + str(bpp // 8))
        print("  realSize        = " + str(flim.realSize))

        hdr, data = get_deswizzled_data(flim)

        with open(output_, "wb+") as output:
            output.write(hdr)
            output.write(data)

    print('')
    print('Finished converting: ' + 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
Exemple #8
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
Exemple #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
Exemple #10
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
Exemple #11
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
Exemple #12
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
Exemple #13
0
def main():
    print("GTX Extractor v5.3")
    print("(C) 2015-2018 AboodXD")

    input_ = sys.argv[-1]

    if not (input_.endswith('.gtx') or input_.endswith('.dds')):
        printInfo()

    toGTX = False

    if input_.endswith('.dds'):
        toGTX = True

    if "-o" in sys.argv:
        output_ = sys.argv[sys.argv.index("-o") + 1]
    else:
        output_ = os.path.splitext(input_)[0] + (".gtx" if toGTX else ".dds")

    if toGTX:
        if "-tileMode" in sys.argv:
            tileMode = int(sys.argv[sys.argv.index("-tileMode") + 1], 0)
        else:
            tileMode = 4

        if "-swizzle" in sys.argv:
            swizzle = int(sys.argv[sys.argv.index("-swizzle") + 1], 0)
        else:
            swizzle = 0

        if "-SRGB" in sys.argv:
            SRGB = int(sys.argv[sys.argv.index("-SRGB") + 1], 0)
        else:
            SRGB = 0

        multi = False
        if "-multi" in sys.argv:
            multi = True
            numImages = int(sys.argv[sys.argv.index("-multi") + 1], 0)

        if SRGB > 1 or not 0 <= tileMode <= 16 or not 0 <= swizzle <= 7:
            printInfo()

        if "-o" not in sys.argv and "-multi" in sys.argv:
            output_ = output_[:-5] + ".gtx"

        with open(output_, "wb+") as output:
            head_struct = GFDHeader()
            head = head_struct.pack(b"Gfx2", 32, 7, 1, 2, 1, 0, 0)

            output.write(head)

            if multi:
                input_ = input_[:-5]
                for i in range(numImages):
                    print("")
                    print('Converting: ' + input_ + str(i) + ".dds")

                    data = writeGFD(input_ + str(i) + ".dds", tileMode,
                                    swizzle, SRGB, i, numImages)
                    output.write(data)
            else:
                print("")
                print('Converting: ' + input_)

                data = writeGFD(input_, tileMode, swizzle, SRGB, 0, 1)
                output.write(data)

            block_head_struct = GFDBlockHeader()
            eof_blk_head = block_head_struct.pack(b"BLK{", 32, 1, 0, 1, 0, 0,
                                                  0)

            output.write(eof_blk_head)

    else:
        print("")
        print('Converting: ' + input_)

        with open(input_, "rb") as inf:
            inb = inf.read()

        compSel = ["R", "G", "B", "A", "0", "1"]

        gfd = readGFD(inb)

        for i in range(gfd.numImages):

            print("")
            print("// ----- GX2Surface Info ----- ")
            print("  dim             = " + str(gfd.dim[i]))
            print("  width           = " + str(gfd.width[i]))
            print("  height          = " + str(gfd.height[i]))
            print("  depth           = " + str(gfd.depth[i]))
            print("  numMips         = " + str(gfd.numMips[i]))
            if gfd.format[i] in formats:
                print("  format          = " + formats[gfd.format[i]])
            else:
                print("  format          = " + hex(gfd.format[i]))
            print("  aa              = " + str(gfd.aa[i]))
            print("  use             = " + str(gfd.use[i]))
            print("  imageSize       = " + str(gfd.imageSize[i]))
            print("  mipSize         = " + str(gfd.mipSize[i]))
            print("  tileMode        = " + str(gfd.tileMode[i]))
            print("  swizzle         = " + str(gfd.swizzle[i]) + ", " +
                  hex(gfd.swizzle[i]))
            print("  alignment       = " + str(gfd.alignment[i]))
            print("  pitch           = " + str(gfd.pitch[i]))
            bpp = addrlib.surfaceGetBitsPerPixel(gfd.format[i])
            print("")
            print("  GX2 Component Selector:")
            print("    Red Channel:    " + str(compSel[gfd.compSel[i][0]]))
            print("    Green Channel:  " + str(compSel[gfd.compSel[i][1]]))
            print("    Blue Channel:   " + str(compSel[gfd.compSel[i][2]]))
            print("    Alpha Channel:  " + str(compSel[gfd.compSel[i][3]]))
            print("")
            print("  bits per pixel  = " + str(bpp))
            print("  bytes per pixel = " + str(bpp // 8))
            print("  realSize        = " + str(gfd.realSize[i]))

            if gfd.numImages > 1:
                output_ = os.path.splitext(input_)[0] + str(i) + ".dds"

            hdr, result = get_deswizzled_data(i, gfd)

            if hdr == b'' or result == []:
                pass
            else:
                with open(output_, "wb+") as output:
                    output.write(hdr)
                    for data in result:
                        output.write(data)

    print('')
    print('Finished converting: ' + input_)
Exemple #14
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