Xbox 360 .dds swizzling NOESIS

Textures, recreate headers, conversions, algorithms and parsing of image files
YAGAMI55
Posts: 55
Joined: Sun May 24, 2020 9:16 pm

Xbox 360 .dds swizzling NOESIS

Post by YAGAMI55 »

Hi guys, in general, it became interesting how swizzle works on X360. And its easy way how to get an image. I found a script for Noesis and fixed it a bit for textures of UE3 games, but downloading X360 sdk for the sake of one utility for converting dds is very inconvenient. I tried to export in the required format, the script does not give errors, but apparently I missed something. Can anyone help with this?)

I am attaching the script and the texture itself, which opens without problems. The script is universal, you can prescribe any width, height and offset. If you manage to export in the desired format, then you can forget about xtexconv.exe

Code: Select all

from inc_noesis import *

def registerNoesisTypes():
    handle = noesis.register("X360 texture SWIZZ", ".Texture2D")
    noesis.setHandlerTypeCheck(handle, noepyCheckType)
    noesis.setHandlerLoadRGBA(handle, noepyLoadRGBA)
    #noesis.logPopup()
    return 1

def noepyCheckType(data):
    return 1

def noepyLoadRGBA(data, texList):
    bs = NoeBitStream(data)
    dataOffset = 0x14D       #set the data offset
    datasize = bs.getSize() - dataOffset
    imgFmt = 3               #set image format (1 - 7)
    imgWidth = 512           #set image width
    imgHeight = 1024         #set image height
    bs.seek(dataOffset, NOESEEK_ABS)
    data = bs.readBytes(datasize)
    #DXT1
    if imgFmt == 1:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 8)
        texFmt = noesis.NOESISTEX_DXT1
    #DXT3
    elif imgFmt == 2:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        texFmt = noesis.NOESISTEX_DXT3
    #DXT5
    elif imgFmt == 3:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        texFmt = noesis.NOESISTEX_DXT5
    #DXT5 packed normal map
    elif imgFmt == 4:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        data = rapi.imageDecodeDXT(data, imgWidth, imgHeight, noesis.FOURCC_ATI2)
        texFmt = noesis.NOESISTEX_RGBA32
    #DXT5 packed normal map2
    elif imgFmt == 5:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        data = rapi.imageDecodeDXT(data, imgWidth, imgHeight, noesis.FOURCC_ATI1)
        texFmt = noesis.NOESISTEX_RGBA32
    #DXT1 packed normal map
    elif imgFmt == 6:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 8)
        data = rapi.imageDecodeDXT(data, imgWidth, imgHeight, noesis.FOURCC_DXT1NORMAL)
        texFmt = noesis.NOESISTEX_RGBA32
    #raw
    elif imgFmt == 7:
        data = rapi.imageUntile360Raw(data, imgWidth, imgHeight, 4)
        data = rapi.imageDecodeRaw(data, imgWidth, imgHeight, "a8r8g8b8")
        texFmt = noesis.NOESISTEX_RGBA32
    #unknown, not handled
    else:
        print("WARNING: Unhandled image format")
        return None
    texList.append(NoeTexture(rapi.getInputName(), imgWidth, imgHeight, data, texFmt))
    return 1
   
def Texture2DWriteRGBA(data, width, height, bs):


Texture2D
https://mega.nz/file/pThmwRRT#_Q2PdJ_OT ... -M3wY7Yuqg
YAGAMI55
Posts: 55
Joined: Sun May 24, 2020 9:16 pm

Re: Xbox 360 .dds swizzling NOESIS

Post by YAGAMI55 »

So. i add this line and export working

Code: Select all

noesis.setHandlerWriteRGBA(handle, texWriteRGBA)


But i cant understand how export in dds dxt format. My export texture always is RGBA32)))
YAGAMI55
Posts: 55
Joined: Sun May 24, 2020 9:16 pm

Re: Xbox 360 .dds swizzling NOESIS

Post by YAGAMI55 »

Ok. guys. Im not strong in Noesis API

And ill do something wrong

script export show error

Every sugestion or help will be grateful

Code: Select all

def texWriteRGBA(data, width, height, bs):
    width = 512
    height = 1024
    data = rapi.imageEncodeDXT(data, 2, width, height, noesis.NOE_ENCODEDXT_BC1)
    swizz = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), width, height, 16)
   
    bs.writeBytes(swizz)
    print("Export done!")
    return 1
Allen
Posts: 156
Joined: Tue Sep 01, 2015 9:44 am

Re: Xbox 360 .dds swizzling NOESIS

Post by Allen »

You can refer to the script I wrote.
xbox360 swizzle/unswizzle lib github.
YAGAMI55
Posts: 55
Joined: Sun May 24, 2020 9:16 pm

Re: Xbox 360 .dds swizzling NOESIS

Post by YAGAMI55 »

Allen wrote:You can refer to the script I wrote.
xbox360 swizzle/unswizzle lib github.

Thanx))) Now it work correctly)

This is complete script:
- Preview format dxt1, dxt5, rgba32, ATI
- Export format dxt1, dxt5

Code: Select all

from inc_noesis import *
from inc_xbox360_untile import *
import math

def registerNoesisTypes():
    handle = noesis.register("X360 texture SWIZZ", ".Texture2D")
    noesis.setHandlerTypeCheck(handle, noepyCheckType)
    noesis.setHandlerLoadRGBA(handle, noepyLoadRGBA)
    noesis.setHandlerWriteRGBA(handle, texWriteRGBA)
    return 1

def noepyCheckType(data):
    return 1

def noepyLoadRGBA(data, texList):
    bs = NoeBitStream(data)
    dataOffset = 0x14d       #set the data offset
    datasize = bs.getSize() - dataOffset
    imgFmt = 3               #set image format (1 - 7)
    imgWidth = 512          #set image width
    imgHeight = 1024          #set image height
    bs.seek(dataOffset, NOESEEK_ABS)
    data = bs.readBytes(datasize)
    #DXT1
    if imgFmt == 1:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 8)
        texFmt = noesis.NOESISTEX_DXT1
    #DXT3
    elif imgFmt == 2:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        texFmt = noesis.NOESISTEX_DXT3
    #DXT5
    elif imgFmt == 3:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        texFmt = noesis.NOESISTEX_DXT5
    #DXT5 packed normal map
    elif imgFmt == 4:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        data = rapi.imageDecodeDXT(data, imgWidth, imgHeight, noesis.FOURCC_ATI2)
        texFmt = noesis.NOESISTEX_RGBA32
    #DXT5 packed normal map2
    elif imgFmt == 5:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 16)
        data = rapi.imageDecodeDXT(data, imgWidth, imgHeight, noesis.FOURCC_ATI1)
        texFmt = noesis.NOESISTEX_RGBA32
    #DXT1 packed normal map
    elif imgFmt == 6:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), imgWidth, imgHeight, 8)
        data = rapi.imageDecodeDXT(data, imgWidth, imgHeight, noesis.FOURCC_DXT1NORMAL)
        texFmt = noesis.NOESISTEX_RGBA32
    #raw
    elif imgFmt == 7:
        data = rapi.imageUntile360Raw(data, imgWidth, imgHeight, 4)
        data = rapi.imageDecodeRaw(data, imgWidth, imgHeight, "a8r8g8b8")
        texFmt = noesis.NOESISTEX_RGBA32
    #unknown, not handled
    else:
        print("WARNING: Unhandled image format")
        return None
    texList.append(NoeTexture(rapi.getInputName(), imgWidth, imgHeight, data, texFmt))
    return 1
   
def texWriteRGBA(data, width, height, bs):
    DXT5Data = rapi.imageEncodeDXT(data,4,width,height,noesis.NOE_ENCODEDXT_BC3)
    DXT5Data = rapi.swapEndianArray(DXT5Data, 2)
    outData = XGTileSurfaceFromLinearTexture(DXT5Data,width, height,"DXT5")
    bs.writeBytes(outData)
    return 1
   
widthList = (2,4,8,16,32,64,128,256,512,1024,2048)   

def getWidthHeight(buffSize):
    tWidth = int(math.sqrt(buffSize * 2))
    if tWidth not in widthList:
        sizeList = []
        for i in range(len(widthList)):
            index = len(widthList) - 1 - i
            tWidth = widthList[index]
            for j in range(len(widthList)):
                tHeight = widthList[j]
                size = tWidth * tHeight // 2
                sizeList.append((size,tWidth,tHeight))
        for i in range(len(sizeList)):
            info = sizeList[i]
            if info[0] == buffSize:
                width = info[1]
                height = info[2]
                if (width // height) == 2 or (height // width) == 2:
                    return (info[1],info[2])
           
   
    return (tWidth,tWidth)