home *** CD-ROM | disk | FTP | other *** search
- from inc_noesis import *
- import noesis
- import rapi
-
- def registerNoesisTypes():
- handle = noesis.register("Spike Chunsoft FTG .NPK",".npk")
- noesis.setHandlerTypeCheck(handle, noepyCheckType)
- noesis.setHandlerLoadModel(handle, noepyLoadModel)
-
- return 1
-
- NOEPY_HEADER = "npak"
- FORM2_SIGN = b'$PSD'
- SKL_SIGN = b'$SKL'
- MAT_SIGN = b'$MAT'
- VTX_SIGN = b'$VTX'
- SCN_SIGN = b'$SCN'
- TXR_SIGN = b'$TXR'
- TXI_SIGN = b'$TXI'
- RSF_SIGN = b'$RSF'
- matList = []
-
- def readStringt(bs):
- chars = b''
- while True:
- c = bs.readBytes(1)
- if c == b'\x00':
- return chars
- chars += c
-
- def Align(bs, n):
- value = bs.tell() % n
- if (value):
- bs.seek(n - value, 1)
-
- def noepyCheckType(data):
- bs = NoeBitStream(data)
- if len(data) < 4:
- return 0
- if bs.readBytes(4).decode("ASCII") != NOEPY_HEADER:
- return 0
- return 1
-
- def noepyLoadModel(data, mdlList):
- fn = rapi.getExtensionlessName(rapi.getInputName())
- ctx = rapi.rpgCreateContext()
- bs = NoeBitStream(data)
- buff = bs.getBuffer(0x20,bs.dataSize)
-
- try:
- TXRBuff = buff[buff.index(TXR_SIGN):buff.index(TXI_SIGN)]
- TXRbs=NoeBitStream(TXRBuff)
-
- parserT1 = parseTXR(TXRbs,fn)
- textureList1 = parserT1[0]
- NPKVTempOffset = parserT1[1]
- Platf = parserT1[2]
- except:
- print("Textures for 1st form were not found")
- textureList1 = []
- NPKVTempOffset = 0
- Platf = 2
-
- try:
- BoneBuff = buff[buff.index(SKL_SIGN):buff.index(MAT_SIGN)]
- Bonebs = NoeBitStream(BoneBuff)
-
- parserB1 = parseBones(Bonebs)
- bones1 = parserB1[0]
- boneDict1 = parserB1[1]
- except:
- print("Bones were not found")
- bones1 = []
- boneDict1 = {}
-
- VTXBuff = buff[buff.index(VTX_SIGN):buff.index(SCN_SIGN)]
- VTXbs = NoeBitStream(VTXBuff)
-
- parserV1 = parseVTX(VTXbs, fn, bones1, boneDict1)
- mdl1 = parserV1[0]
- NPKITempOffset = parserV1[1]
-
- mdl1.setModelMaterials(NoeModelMaterials(textureList1, matList))
- mdlList.append(mdl1)
-
- bs.seek(0x7c)
- form2 = bs.readString()
- if form2 == "FormChangeModel1.srd":
- print("There's a 2nd form")
- tempbuff = buff[buff.index(FORM2_SIGN):]
- tempbuff = tempbuff[tempbuff.index(RSF_SIGN):]
- bs2 = NoeBitStream(tempbuff)
- buff2 = bs2.getBuffer(0x20,bs2.dataSize)
-
- extra2 = extraForm(buff2, NPKVTempOffset, NPKITempOffset, fn)
- mdl2 = extra2[0]
- NPKVTempOffset = extra2[1]
- NPKITempOffset = extra2[2]
-
- mdlList.append(mdl2)
- else:
- print("NO 2nd form\n")
-
- bs.seek(0x94)
- form3 = bs.readString()
- if form3 == "FormChangeModel2.srd":
- print("There's a 3rd form")
- tempbuff = buff2[buff2.index(RSF_SIGN):]
- if NPKITempOffset in [0x1298d4, 0xf9dc8, 0x59274] :
- tempbuff = tempbuff[0x20:]
- tempbuff = tempbuff[tempbuff.index(RSF_SIGN):]
- bs3 = NoeBitStream(tempbuff)
- buff3 = bs3.getBuffer(0x20,bs3.dataSize)
-
- extra3 = extraForm(buff3, NPKVTempOffset, NPKITempOffset, fn)
- mdl3 = extra3[0]
- NPKVTempOffset = extra3[1]
- NPKITempOffset = extra3[2]
-
- mdlList.append(mdl3)
-
- bs.seek(0xac)
- form4 = bs.readString()
- if form4 == "FormChangeModel3.srd":
- print("There's a 4th form")
- tempbuff = buff3[buff3.index(RSF_SIGN):]
- bs4 = NoeBitStream(tempbuff)
- buff4 = bs4.getBuffer(0x20,bs4.dataSize)
-
- extra4 = extraForm(buff4, NPKVTempOffset, NPKITempOffset, fn)
- mdl4 = extra4[0]
- NPKVTempOffset = extra4[1]
- NPKITempOffset = extra4[2]
-
- mdlList.append(mdl4)
-
- bs.seek(0xc4)
- form5 = bs.readString()
- if form5 == "FormChangeModel4.srd":
- print("There's a 5th form")
- tempbuff = buff4[buff4.index(RSF_SIGN):]
- bs5 = NoeBitStream(tempbuff)
- buff5 = bs5.getBuffer(0x20,bs5.dataSize)
-
- extra5 = extraForm(buff5, NPKVTempOffset, NPKITempOffset, fn)
- mdl5 = extra5[0]
- NPKVTempOffset = extra5[1]
- NPKITempOffset = extra5[2]
-
- mdlList.append(mdl5)
-
- return 1
-
- def parseTXR(TXRbs,fn, NPKVbsOffset = 0):
- TexInfo = []
- texList = []
- while True:
- TXRbs.readBytes(0x16)
- width = TXRbs.readUShort()
- height = TXRbs.readUShort()
- TXRbs.readUShort()
- type1 = TXRbs.readUByte()
- num = TXRbs.readUByte()
- TXRbs.readBytes(0x12)
- platFlag = TXRbs.readUInt()
- TXRbs.readBytes(0xc)
- offset = TXRbs.readUInt() - 0x40000000
-
- if platFlag == 0x1300506 or num == 1:
- length = TXRbs.readUInt()
- TXRbs.readUInt64()
- if platFlag == 0x1300506:
- Platform = 1
- else:
- Platform = 2
- else:
- TXRbs.readBytes(0xc)
- count = num - 1
- for i in range(count):
- offs2 = TXRbs.readUInt() - 0x40000000
- le = TXRbs.readUInt()
- TXRbs.readUInt64()
- length = offs2 + le - offset
- Platform = 2
- offset += NPKVbsOffset
- texName = readStringt(TXRbs).decode('shift_jisx0213')
- Align(TXRbs,16)
- TXRbs.readBytes(0x10)
- TexInfo.append((rapi.getExtensionlessName(texName), width, height, type1, offset, length, Platform))
- if TXRbs.tell() == TXRbs.dataSize:
- break
- if (rapi.checkFileExists(fn + ".npkv")):
- npkvData = rapi.loadIntoByteArray(fn + ".npkv")
- NPKVbs = NoeBitStream(npkvData)
- print("NPKV found")
- for i, info in enumerate(TexInfo):
- textureName = info[0]
- width2 = info[1]
- height2 = info[2]
- type2 = info[3]
- offset2 = info[4]
- length2 = info[5]
- plat = info[6]
- NPKVbs.seek(offset2)
- textureData = NPKVbs.readBytes(length2)
- if type2 == 0xf:
- if plat == 1:
- textureData = rapi.callExtensionMethod("untile_1dthin", textureData, width2, height2, 4, 1)
- format = noesis.FOURCC_DXT1
- elif type2 == 0x14:
- if plat == 1:
- textureData = rapi.callExtensionMethod("untile_1dthin", textureData, width2, height2, 8, 1)
- format = noesis.FOURCC_ATI2
- elif type2 == 0x11:
- if plat == 1:
- textureData = rapi.callExtensionMethod("untile_1dthin", textureData, width2, height2, 8, 1)
- format = noesis.FOURCC_DXT5
- elif type2 == 0x10:
- format = noesis.FOURCC_DXT3
- textureData = rapi.imageDecodeDXT(textureData, width2, height2, format)
- format = noesis.NOESISTEX_RGBA32
- texture = NoeTexture(textureName, width2, height2, textureData, format)
- texList.append(texture)
- return (texList, NPKVbs.tell(), plat)
- else:
- print("NPKV not found")
- return (texList, 0,0)
-
- def parseVTX(VTXbs,fn,bones,boneDict, NPKIbsOffset = 0):
- VTXInfo = []
- bindBoneList = []
- UVSize = 8
-
- while True:
- VTXbs.readUInt()
- VTXSize = VTXbs.read(">i")[0]
- RSISize = VTXbs.read(">i")[0]
- VTXbs.readUInt()
- tempOffset = VTXbs.tell()
- VTXbs.readBytes(0x6)
- cond = VTXbs.readUShort()
- VCount = VTXbs.readUInt()
- if cond == 520:
- VTXbs.readBytes(0x54)
- elif cond == 519:
- VTXbs.readBytes(0x4c)
- elif cond == 518:
- VTXbs.readBytes(0x44)
- elif cond == 517:
- VTXbs.readBytes(0x3C)
- elif cond == 516:
- VTXbs.readBytes(0x34)
- VBSize = VTXbs.readUInt()
- if cond not in [516, 517]:
- WeightAddress = VTXbs.readUInt()
- WeightSize = VTXbs.readUInt()
- UVAddress = VTXbs.readUInt()
- UVSize = VTXbs.readUInt()
- VTXbs.readUShort()
- bindboneListOfs = VTXbs.readUShort()
- if bindboneListOfs:
- VTXbs.seek(tempOffset+bindboneListOfs)
- bb = []
- while (VTXbs.tell() < tempOffset+VTXSize):
- name = VTXbs.readString()
- if name not in ["uvset","map1","map11", "map12", "damage_00", "damage_00(0)", "UVMap", "Col", "colorSet1","SculptFreezeColorTemp"]:
- bb.append(name)
- bindBoneList = bb
- else:
- VTXbs.seek(tempOffset+VTXSize)
- Align(VTXbs,16)
- VTXbs.readBytes(0x20)
- VAddress = VTXbs.readUInt() - 0x20000000 + NPKIbsOffset
- VEndAddress = VTXbs.readUInt()
- VTXbs.readUInt64()
- FaceAddress = VTXbs.readUInt() - 0x20000000 + NPKIbsOffset
- FCount = VTXbs.readUInt() // 2
- VTXbs.readUInt64()
- MeshName = VTXbs.readString()
- Align(VTXbs,16)
- VTXbs.readBytes(0x10)
- VTXInfo.append((MeshName, VAddress, VCount, VBSize, UVSize, FaceAddress, FCount, bindBoneList, cond))
- if VTXbs.tell() == VTXbs.dataSize:
- break
-
- if (rapi.checkFileExists(fn + ".npki")):
- npkiData = rapi.loadIntoByteArray(fn + ".npki")
- NPKIbs = NoeBitStream(npkiData)
- print("NPKI found\n")
- for i, info in enumerate(VTXInfo):
- submeshName = info[0]
- VertAddress = info[1]
- VertCount = info[2]
- VertBSize = info[3]
- UVsSize = info[4]
- FAddress = info[5]
- FICount = info[6]
- BindBoneList = info[7]
- Flag = info[8]
- rapi.rpgSetName(submeshName)
- matList.append(NoeMaterial(submeshName, ""))
- rapi.rpgSetMaterial(submeshName)
- NPKIbs.seek(VertAddress)
- VertBuff = NPKIbs.readBytes(VertCount * VertBSize)
- rapi.rpgBindPositionBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 0)
-
- bidx = []
- bwgt = []
- if (Flag not in [516, 517]):
- for j in range(VertCount):
- for k in range(4):
- bwgt.append(NPKIbs.readFloat())
- for k in range(4):
- bidx.append(NPKIbs.readUInt())
-
- for j in range (len(bidx)):
- acutalIdx = boneDict[BindBoneList[bidx[j]]]
- bidx[j] = acutalIdx
- bidxList = struct.pack("iiii"*VertCount, *bidx)
- bwgtList = struct.pack("ffff"*VertCount, *bwgt)
- rapi.rpgBindBoneIndexBuffer(bidxList, noesis.RPGEODATA_INT, 16, 4)
- rapi.rpgBindBoneWeightBuffer(bwgtList, noesis.RPGEODATA_FLOAT, 16, 4)
- else:
- bidxList = struct.pack("i"*VertCount, *[0]*VertCount)
- bwgtList = struct.pack("f"*VertCount, *[1.0]*VertCount)
- rapi.rpgBindBoneIndexBuffer(bidxList, noesis.RPGEODATA_INT, 4, 1)
- rapi.rpgBindBoneWeightBuffer(bwgtList, noesis.RPGEODATA_FLOAT, 4, 1)
-
-
- if Flag not in [516, 517]:
- UVBuff = NPKIbs.readBytes(VertCount * UVsSize)
- rapi.rpgBindNormalBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 16)
- rapi.rpgBindTangentBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, VertBSize-16)
- if UVsSize >= 8 and UVsSize < 16:
- rapi.rpgBindUV1BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-8)
- elif UVsSize >= 16 and UVsSize < 24:
- rapi.rpgBindUV1BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-16)
- rapi.rpgBindUV2BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-8)
- elif UVsSize >= 24 and UVsSize < 32:
- rapi.rpgBindUV1BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-24)
- rapi.rpgBindUVXBufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, 1, 2, UVsSize-16)
- rapi.rpgBindUVXBufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, 2, 2, UVsSize-8)
- else:
- rapi.rpgBindNormalBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 12)
- if VertBSize == 0x34:
- rapi.rpgBindUV1BufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 28)
- rapi.rpgBindUVXBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 1, 2, 36)
- rapi.rpgBindUVXBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 2, 2, 44)
- else:
- rapi.rpgBindUV1BufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 24)
-
- NPKIbs.seek(FAddress)
- FaceBuff = NPKIbs.readBytes(FICount * 2)
- rapi.rpgCommitTriangles(FaceBuff, noesis.RPGEODATA_USHORT, FICount, noesis.RPGEO_TRIANGLE, 1)
- rapi.rpgClearBufferBinds()
-
- rapi.rpgSetOption(noesis.RPGOPT_SWAPHANDEDNESS, 1)
- model = rapi.rpgConstructModel()
- model.setBones(bones)
- rapi.rpgReset()
- return (model,NPKIbs.tell())
- else:
- print("NPKI not found\n")
- model = NoeModel()
- return (model,0)
-
- def parseBones(Bonebs):
- bones0 = []
- boneDict0 = {}
-
- Bonebs.readUInt64()
- Bonebs.readUInt64()
- tempOffset2 = Bonebs.tell()
- Bonebs.readBytes(0x6)
- BCount = Bonebs.readUShort()
- Bonebs.readUInt()
- boneData = [None]*200
- lastFlag = 255
-
- for i in range(BCount):
- BoneNameOffset = Bonebs.readUInt()
- tempOffset3 = Bonebs.tell()
- Bonebs.seek(tempOffset2 + BoneNameOffset)
- BoneName = Bonebs.readString()
- Bonebs.seek(tempOffset3)
- currentID = Bonebs.read(">h")[0]
- parentID = currentID - 1
- currentFlag = Bonebs.readShort()
- Bonebs.readBytes(0x30) #localBoneMtx
- worldBoneMtx = NoeMat43.fromBytes(Bonebs.readBytes(0x30)).transpose().inverse().swapHandedness()
- boneData[currentID] = i
-
- if lastFlag != 255:
- bones0.append(NoeBone(i,BoneName, worldBoneMtx, None, boneData[parentID]))
- else:
- bones0.append(NoeBone(i,BoneName, worldBoneMtx, None, i-1))
-
- Bonebs.readBytes(0x18)
- lastFlag = currentFlag
-
- for b in range (BCount):
- boneDict0[bones0[b].name] = b
-
- return (bones0, boneDict0)
-
- def extraForm(buff2, NPKVTempOffset, NPKITempOffset, fn):
- if NPKVTempOffset:
- NPKV_TEMP_BYTES = NPKVTempOffset.to_bytes(4, byteorder='little')
- values2 = bytearray(NPKV_TEMP_BYTES)
- if values2[0] > 0x80:
- values2[0] = 0x00
- values2[1] +=1
- elif values2[0] != 0x00:
- values2[0] = 0x80
- NPKVTempOffset = int.from_bytes(bytes(values2), byteorder='little', signed=False)
-
- try:
- TXRBuff2 = buff2[buff2.index(TXR_SIGN):buff2.index(TXI_SIGN)]
- TXRbs2 = NoeBitStream(TXRBuff2)
-
- parserT2 = parseTXR(TXRbs2,fn,NPKVTempOffset)
- textureList2 = parserT2[0]
- NPKVTempOffset = parserT2[1]
- except:
- print("There's no texture for this extra form")
- textureList2 = []
-
- try:
- BoneBuff2 = buff2[buff2.index(SKL_SIGN):buff2.index(MAT_SIGN)]
- Bonebs2 = NoeBitStream(BoneBuff2)
-
- parserB2 = parseBones(Bonebs2)
- bones2 = parserB2[0]
- boneDict2 = parserB2[1]
- except:
- print("Bones were not found")
- bones2 = []
- boneDict2 = {}
-
- NPKI_TEMP_BYTES = NPKITempOffset.to_bytes(4, byteorder='little')
- values = bytearray(NPKI_TEMP_BYTES)
- if values[0] > 0x80:
- values[0] = 0x00
- values[1] +=1
- elif values[0] != 0x00:
- values[0] = 0x80
- NPKIOffset_num = int.from_bytes(bytes(values), byteorder='little', signed=False)
- VTXBuff2 = buff2[buff2.index(VTX_SIGN):buff2.index(SCN_SIGN)]
- VTXbs2 = NoeBitStream(VTXBuff2)
- parserV2 = parseVTX(VTXbs2, fn, bones2, boneDict2, NPKIOffset_num)
- model2 = parserV2[0]
- NPKITempOffset = parserV2[1]
-
- model2.setModelMaterials(NoeModelMaterials(textureList2, matList))
- return (model2, NPKVTempOffset, NPKITempOffset)