Jump to content

Noesis script for hgp files


Sluicer
 Share

Recommended Posts

I finally found some time to play around with LEGO SW2 again. Here is a noesis script to look into the hgp files:

from inc_noesis import *
import noesis
import rapi

def registerNoesisTypes():
    '''Register the plugin. Just change the Game name and extension.'''

    handle = noesis.register("LEGO Star Wars 2", ".hgp")
    noesis.setHandlerTypeCheck(handle, noepyCheckType)
    noesis.setHandlerLoadModel(handle, noepyLoadModel)
    return 1

def noepyCheckType(data):
    '''Verify that the format is supported by this plugin. Default yes'''
    bs = NoeBitStream(data)
    tmp = bs.readInt()
    tmp = bs.readInt()
    if tmp == 0x3032554e: #4e553230: # NU20
        return 1

    return 0

def noepyLoadModel(data, mdlList):

    bs = NoeBitStream(data)

    ctx = rapi.rpgCreateContext()
    stack = []
    textures = []
    materials = []

    fileSize = bs.readInt()
    #NU20
    fourCC = bs.readInt()
    numberTextures = bs.readInt()
    print("NumberTextures %d" % numberTextures)
    offsetTextures = bs.readInt()
    numberMaterials = bs.readInt()
    print("NumberMaterials %d" % numberMaterials)
    offsetMaterials = bs.readInt()

    numberMatix = bs.readInt()
    print("NumberMatix %d" % numberMatix)
    offsetMatix1 = bs.readInt()
    offsetMatix2 = bs.readInt()
    offsetMatix3 = bs.readInt()

    numberUnk1 = bs.readInt()
    print("NumberUnk1 %d" % numberUnk1)
    offsetUnk1 = bs.readInt()

    offsetText = bs.readInt()
    lenthText = bs.readInt()

    numberUnk = bs.readInt()
    #print("NumberBones %d" % numberBones)
    offsetUnk = bs.readInt()

    numberAttachment = bs.readInt()
    #print("NumberAttachment %d" % numberAttachment)
    offsetAttachment = bs.readInt()
    numberLayer = bs.readInt()
    print("NumberLayer %d" % numberLayer)
    offsetLayer = bs.readInt()

    offsetMini3D = bs.readInt()
    # end header

    bs.seek(offsetTextures, NOESEEK_ABS)
    offsetTextures2 = bs.readInt()
    bs.seek(offsetTextures2, NOESEEK_ABS)
    bs.readInt() #numberOfTextures =
    bs.readInt()
    textureHeaderSize = bs.readInt()
    textureDataOffset = bs.readInt()
    bs.readInt()
    bs.seek(offsetTextures2+textureHeaderSize, NOESEEK_ABS)

    for i in range (1, numberTextures+1):
        width = bs.readInt()
        height = bs.readInt()
        bs.readInt()
        ddsType = bs.readInt()

        if ddsType == 0x0C:
            size = width * height
            imgType = noesis.NOESISTEX_DXT3
        elif ddsType == 0x0F:
            size = width * height
            imgType = noesis.NOESISTEX_DXT5
        else:
            print('Unknown dds type: ' + repr(ddsType))
        imageOffset = bs.readInt()
        tmp = bs.tell()
        bs.seek(offsetTextures2+textureDataOffset+imageOffset+0x80, NOESEEK_ABS)
        print("Image{0} @ {1:8x}: width = {2:4d}; height = {3:4d}".format(i, offsetTextures2+textureDataOffset+imageOffset, width, height))
        data = bs.readBytes(size)
        #texture = rapi.loadTexByHandler(data, ".dds") #NoeTexture(str(i), width, height, data, imgType)
        texture = NoeTexture(str(i), width, height, data, imgType)
        texture.name = "tex%03i"%i
        textures.append(texture)
        bs.seek(tmp, NOESEEK_ABS)

    bs.seek(offsetMaterials, NOESEEK_ABS)
    materialOffsets = []
    for i in range (0, numberMaterials):
        materialOffsets.append(bs.readInt())

    i = 0
    for m in (materialOffsets):
        bs.seek(m, NOESEEK_ABS)
        material = NoeMaterial("mat%03i"%i, "") #create a material
        bs.seek(84, NOESEEK_REL) #
        red = bs.readFloat()
        green = bs.readFloat()
        blue = bs.readFloat()
        alpha = bs.readFloat()
        material.setDiffuseColor(NoeVec4([red, green, blue, alpha]))
        #print("DiffuseColor: ", i, red, green, blue, alpha)
        bs.seek(0x14, NOESEEK_REL) #
        texId = bs.readShort()
        #print("TexId: ", texId)
        if (texId != 0):
            material.setTexture("tex%03i"%texId)
        #else:
        #    material.setTexture(None)

        materials.append(material)
        i += 1


    bones = []
    bones0 = []
    bones1 = []
    bones2 = []
    boneNames = []
    bonePIndices = []
    bs.seek(offsetMatix1, NOESEEK_ABS)
    for i in range (0, numberMatix):
        boneMat = NoeMat44.fromBytes(bs.readBytes(0x40)).toMat43()
        bs.seek(0xc, NOESEEK_REL)
        offsetText = bs.readInt()
        mem = bs.tell()
        bs.seek(offsetText, NOESEEK_ABS)
        boneName = bs.readString()
        boneNames.append(boneName)
        bs.seek(mem, NOESEEK_ABS)
        bonePIndex = bs.readByte()
        bonePIndices.append(bonePIndex)
        bs.readByte()
        bs.readByte()
        bs.readByte()
        bs.readInt()
        bs.readInt()
        bs.readInt()
        print(boneName + ": " + repr(i) + "-->" + repr(bonePIndex))
        bones0.append(boneMat)

    for i in range (0, numberMatix):
        boneMat = NoeMat44.fromBytes(bs.readBytes(0x40)).toMat43()
        #print(boneMat)
        if (bonePIndices[i] != -1):
            boneMat = boneMat.__mul__(bones1[bonePIndices[i]])
        bone = NoeBone(i, boneNames[i], boneMat, None, bonePIndices[i])
        bones.append(bone)
        bones1.append(boneMat)

    for i in range (0, numberMatix):
        boneMat = NoeMat44.fromBytes(bs.readBytes(0x40)).toMat43()
        #print(boneMat)
        bones2.append(boneMat)

    layerList = []
    bs.seek(offsetLayer, NOESEEK_ABS)
    for i in range (0, numberLayer):
        print("Layer %d" % i)
        parseLayer(bs, numberMatix, layerList)

    bs.seek(offsetTextures, NOESEEK_ABS)
    offsetImages = bs.readInt()
    offsetMesh = bs.readInt()

    bs.seek(offsetMesh, NOESEEK_ABS)
    #print("MESH @ 0x%x" % (bs.tell()))

    numberVertexLists = bs.readInt()
    #print("{0:08x}     numberVertexLists: 0x{1:08x}".format(bs.tell()-4, numberVertexLists))
    numberUnk = bs.readInt()
    size = bs.readInt()
    type = bs.readInt()
    offsetMeshHeader = bs.readInt()
    sizeVertices = bs.readInt()
    bs.readInt()
    offsetIndices = bs.readInt()
    sizeIndices = bs.readInt()

    bs.seek(offsetMesh+0x30, NOESEEK_ABS)

    sizeList = []
    offsetList = []
    for i in range (0, numberVertexLists):
        sizeList.append(bs.readInt())
        id = bs.readInt()
        offsetList.append(bs.readInt())

    bs.seek(offsetMesh+offsetMeshHeader, NOESEEK_ABS)
    #print("Vertices @ 0x%x" % (bs.tell()))
    vertexLists = []
    for i in range (0, numberVertexLists):
        bs.seek(offsetMesh+offsetMeshHeader+offsetList[i], NOESEEK_ABS)
        vertexLists.append(bs.readBytes(sizeList[i]))

    bs.seek(offsetMesh+offsetIndices, NOESEEK_ABS)
    #print("Indices @ 0x%x" % (bs.tell()))

    indexLists = []
    indexLists.append(bs.readBytes(sizeIndices))
    #print("EOF @ 0x%x" % (bs.tell()))


    #for layer in (layerList):
    for i in range (0, numberLayer):
        layer = layerList[i]
        for part in (layer):

            #print("Part")
            #print("Indices @ 0x%x" % (part.VertexListType[0]))
            if (part.BoneId != -1):
                rapi.rpgSetTransform(bones1[part.BoneId])
            else:
                rapi.rpgSetTransform(None)

            if (part.VertexListType[0] == 0x5D):
                bytesForPositions = (vertexLists[part.VertexList[0]][part.offsetVertex*0x38:part.offsetVertex*0x38+part.numberVertex*0x38])
                rapi.rpgBindPositionBuffer(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x38, 0)
                rapi.rpgBindBoneWeightBufferOfs(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x38, 0x0c, 2)
                rapi.rpgBindBoneIndexBufferOfs(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x38, 0x14, 2)
                rapi.rpgBindUV1BufferOfs(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x38, 0x30)

            if (part.VertexListType[0] == 0x59):
                bytesForPositions = (vertexLists[part.VertexList[0]][part.offsetVertex*0x24:part.offsetVertex*0x24+part.numberVertex*0x24])
                rapi.rpgBindPositionBuffer(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x24, 0)
                rapi.rpgBindBoneWeightBufferOfs(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x24, 0x0c, 2)
                rapi.rpgBindBoneIndexBufferOfs(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x24, 0x14, 2)
                rapi.rpgBindUV1BufferOfs(bytesForPositions, noesis.RPGEODATA_FLOAT, 0x24, 0x1C)

            bytesForIndexBuffer = (indexLists[0][part.offsetIndex*2:part.offsetIndex*2+(part.numberIndex+2)*2])
            rapi.rpgSetMaterial("mat%03i"%part.MadId)
            rapi.rpgCommitTriangles(bytesForIndexBuffer, noesis.RPGEODATA_SHORT, part.numberIndex+2, noesis.RPGEO_TRIANGLE_STRIP, 1)
            rapi.rpgClearBufferBinds()

        mdl = rapi.rpgConstructModel()
        mdl.setModelMaterials(NoeModelMaterials(textures, materials))
        mdl.setBones(bones)
        mdlList.append(mdl)             #important, don't forget to put your loaded model in the mdlList

    return 1

def parseLayer(bs, numberMatix, layerList):
    partList = []
    layerMeta1 = bs.readInt()

    layerMeta2 = bs.readInt()
    #print("    layerMeta2 %d" % layerMeta2)
    mem = bs.tell()
    if (layerMeta2 != 0):
        bs.seek(layerMeta2, NOESEEK_ABS)
        parseLayerMeta2(bs, numberMatix, partList)
    bs.seek(mem, NOESEEK_ABS)

    layerMeta3 = bs.readInt()
    #print("    layerMeta3 %d" % layerMeta3)
    mem = bs.tell()
    if (layerMeta3 != 0):
        bs.seek(layerMeta3, NOESEEK_ABS)
        parsePartHeader(bs, partList, -1)
    bs.seek(mem, NOESEEK_ABS)

    layerMeta4 = bs.readInt()

    layerMeta5 = bs.readInt()
    #print("    layerMeta5 %d" % layerMeta5)
    mem = bs.tell()
    if (layerMeta5 != 0):
        bs.seek(layerMeta5, NOESEEK_ABS)
        parsePartHeader(bs, partList, -1)
    bs.seek(mem, NOESEEK_ABS)

    layerList.append(partList)

def parseLayerMeta2(bs, numberMatix, partList):
    for i in range (0, numberMatix):
        tmp = bs.readInt()
        mem = bs.tell()
        if (tmp != 0):
            bs.seek(tmp, NOESEEK_ABS)
            #print("        offsetLayerPart %d" % tmp)
            parsePartHeader(bs, partList, i)
            bs.seek(mem, NOESEEK_ABS)

def parsePartHeader(bs, partList, boneId):
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readFloat()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    pos = bs.tell()
    #print("        pos 4 next %x" % pos)
    next = bs.readInt()
    #print("        next %d" % next)
    parsePart(bs, partList, boneId)
    while (next != 0):
        bs.seek(next, NOESEEK_ABS)
        next = bs.readInt()
        #print("            next %d" % next)
        parsePart(bs, partList, boneId)


def parsePart(bs, partList, boneId):
    part = Part()
    part.BoneId = boneId
    pos = bs.tell()
    #print("        pos %x" % pos)
    bs.readInt()
    part.MadId = bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    fourCC = bs.readInt()
    bs.readInt()
    bs.readInt()
    ext = bs.readInt()
    bs.readInt()
    bs.readInt()
    numberVertexLists = bs.readInt()
    for i in range (0, 8):
        part.VertexList.append(bs.readInt())
    for i in range (0, 8):
        part.VertexListType.append(bs.readInt())
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    bs.readInt()
    chunk6 = bs.readInt()
    bs.readShort()
    bs.readShort()
    bs.readInt()
    bs.readInt()
    bs.readShort()
    bs.seek(17*2, NOESEEK_REL)
    chunk5 = bs.readInt()
    part.offsetVertex = bs.readInt()
    bs.readInt()
    part.numberVertex = bs.readInt()
    part.offsetIndex = bs.readInt()
    part.numberIndex = bs.readInt()
    pos = bs.tell()
    #print("        pos %x" % pos)
    print("        PartMeta: ", part.offsetVertex, part.numberVertex, part.offsetIndex, part.numberIndex)
    partList.append(part)


class Part():

    def __init__(self):
        self.VertexList = []
        self.VertexListType = []
        self.BoneId = 0
        self.MadId = -1
        self.offsetVertex = 0
        self.numberVertex = 0
        self.offsetIndex = 0
        self.numberIndex = 0

 

Link to comment
Share on other sites

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.