home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 20106 / fmt_SpikeChunsoftFTG_npk.7z / fmt_SpikeChunsoftFTG_npk.py
Encoding:
Python Source  |  2021-05-11  |  13.6 KB  |  455 lines

  1. from inc_noesis import *
  2. import noesis
  3. import rapi
  4.  
  5. def registerNoesisTypes():
  6.     handle = noesis.register("Spike Chunsoft FTG .NPK",".npk")
  7.     noesis.setHandlerTypeCheck(handle, noepyCheckType)
  8.     noesis.setHandlerLoadModel(handle, noepyLoadModel)
  9.     
  10.     return 1
  11.     
  12. NOEPY_HEADER = "npak"
  13. FORM2_SIGN = b'$PSD'
  14. SKL_SIGN = b'$SKL'
  15. MAT_SIGN = b'$MAT'
  16. VTX_SIGN = b'$VTX'
  17. SCN_SIGN = b'$SCN'
  18. TXR_SIGN = b'$TXR'
  19. TXI_SIGN = b'$TXI'
  20. RSF_SIGN = b'$RSF'
  21. matList = []
  22.  
  23. def readStringt(bs):
  24.     chars = b''
  25.     while True:
  26.         c = bs.readBytes(1)
  27.         if c == b'\x00':
  28.             return chars
  29.         chars += c
  30.  
  31. def Align(bs, n):
  32.     value = bs.tell() % n
  33.     if (value):
  34.         bs.seek(n - value, 1)
  35.  
  36. def noepyCheckType(data):
  37.    bs = NoeBitStream(data)
  38.    if len(data) < 4:
  39.       return 0
  40.    if bs.readBytes(4).decode("ASCII") != NOEPY_HEADER:
  41.       return 0
  42.    return 1  
  43.  
  44. def noepyLoadModel(data, mdlList):
  45.     fn = rapi.getExtensionlessName(rapi.getInputName())
  46.     ctx = rapi.rpgCreateContext()
  47.     bs = NoeBitStream(data)
  48.     buff = bs.getBuffer(0x20,bs.dataSize)
  49.         
  50.     try:
  51.         TXRBuff = buff[buff.index(TXR_SIGN):buff.index(TXI_SIGN)]
  52.         TXRbs=NoeBitStream(TXRBuff)
  53.     
  54.         parserT1 = parseTXR(TXRbs,fn)
  55.         textureList1 = parserT1[0]
  56.         NPKVTempOffset = parserT1[1]
  57.         Platf = parserT1[2]
  58.     except:
  59.         print("Textures for 1st form were not found")
  60.         textureList1 = []
  61.         NPKVTempOffset = 0
  62.         Platf = 2
  63.     
  64.     try:
  65.         BoneBuff = buff[buff.index(SKL_SIGN):buff.index(MAT_SIGN)]
  66.         Bonebs = NoeBitStream(BoneBuff)
  67.     
  68.         parserB1 = parseBones(Bonebs)
  69.         bones1 = parserB1[0]
  70.         boneDict1 = parserB1[1]
  71.     except:
  72.         print("Bones were not found")
  73.         bones1 = []
  74.         boneDict1 = {}
  75.     
  76.     VTXBuff = buff[buff.index(VTX_SIGN):buff.index(SCN_SIGN)]
  77.     VTXbs = NoeBitStream(VTXBuff)
  78.     
  79.     parserV1 = parseVTX(VTXbs, fn, bones1, boneDict1)
  80.     mdl1 = parserV1[0]
  81.     NPKITempOffset = parserV1[1]    
  82.     
  83.     mdl1.setModelMaterials(NoeModelMaterials(textureList1, matList))
  84.     mdlList.append(mdl1)    
  85.     
  86.     bs.seek(0x7c)
  87.     form2 = bs.readString()
  88.     if form2 == "FormChangeModel1.srd":
  89.         print("There's a 2nd form")
  90.         tempbuff = buff[buff.index(FORM2_SIGN):]
  91.         tempbuff = tempbuff[tempbuff.index(RSF_SIGN):]
  92.         bs2 = NoeBitStream(tempbuff)
  93.         buff2 = bs2.getBuffer(0x20,bs2.dataSize)
  94.         
  95.         extra2 = extraForm(buff2, NPKVTempOffset, NPKITempOffset, fn)
  96.         mdl2 = extra2[0]
  97.         NPKVTempOffset = extra2[1]
  98.         NPKITempOffset = extra2[2]
  99.         
  100.         mdlList.append(mdl2)
  101.     else:
  102.         print("NO 2nd form\n")
  103.     
  104.     bs.seek(0x94)
  105.     form3 = bs.readString()
  106.     if form3 == "FormChangeModel2.srd":
  107.         print("There's a 3rd form")
  108.         tempbuff = buff2[buff2.index(RSF_SIGN):]
  109.         if NPKITempOffset in [0x1298d4, 0xf9dc8, 0x59274] :
  110.             tempbuff = tempbuff[0x20:]
  111.             tempbuff = tempbuff[tempbuff.index(RSF_SIGN):]
  112.         bs3 = NoeBitStream(tempbuff)
  113.         buff3 = bs3.getBuffer(0x20,bs3.dataSize)
  114.         
  115.         extra3 = extraForm(buff3, NPKVTempOffset, NPKITempOffset, fn)
  116.         mdl3 = extra3[0]
  117.         NPKVTempOffset = extra3[1]
  118.         NPKITempOffset = extra3[2]
  119.         
  120.         mdlList.append(mdl3)
  121.     
  122.     bs.seek(0xac)
  123.     form4 = bs.readString()
  124.     if form4 == "FormChangeModel3.srd":
  125.         print("There's a 4th form")
  126.         tempbuff = buff3[buff3.index(RSF_SIGN):]
  127.         bs4 = NoeBitStream(tempbuff)
  128.         buff4 = bs4.getBuffer(0x20,bs4.dataSize)
  129.         
  130.         extra4 = extraForm(buff4, NPKVTempOffset, NPKITempOffset, fn)
  131.         mdl4 = extra4[0]
  132.         NPKVTempOffset = extra4[1]
  133.         NPKITempOffset = extra4[2]
  134.         
  135.         mdlList.append(mdl4)
  136.     
  137.     bs.seek(0xc4)
  138.     form5 = bs.readString()
  139.     if form5 == "FormChangeModel4.srd":
  140.         print("There's a 5th form")
  141.         tempbuff = buff4[buff4.index(RSF_SIGN):]
  142.         bs5 = NoeBitStream(tempbuff)
  143.         buff5 = bs5.getBuffer(0x20,bs5.dataSize)
  144.         
  145.         extra5 = extraForm(buff5, NPKVTempOffset, NPKITempOffset, fn)
  146.         mdl5 = extra5[0]
  147.         NPKVTempOffset = extra5[1]
  148.         NPKITempOffset = extra5[2]
  149.         
  150.         mdlList.append(mdl5)
  151.     
  152.     return 1
  153.     
  154. def parseTXR(TXRbs,fn, NPKVbsOffset = 0):
  155.     TexInfo = []
  156.     texList = []
  157.     while True:
  158.         TXRbs.readBytes(0x16)
  159.         width = TXRbs.readUShort()
  160.         height = TXRbs.readUShort()
  161.         TXRbs.readUShort()
  162.         type1 = TXRbs.readUByte()
  163.         num = TXRbs.readUByte()
  164.         TXRbs.readBytes(0x12)
  165.         platFlag = TXRbs.readUInt()
  166.         TXRbs.readBytes(0xc)
  167.         offset = TXRbs.readUInt() - 0x40000000
  168.         
  169.         if platFlag == 0x1300506 or num == 1:
  170.             length = TXRbs.readUInt()
  171.             TXRbs.readUInt64()
  172.             if platFlag == 0x1300506:
  173.                 Platform = 1
  174.             else:
  175.                 Platform = 2
  176.         else:
  177.             TXRbs.readBytes(0xc)
  178.             count = num - 1
  179.             for i in range(count):
  180.                 offs2 = TXRbs.readUInt() - 0x40000000
  181.                 le = TXRbs.readUInt()
  182.                 TXRbs.readUInt64()
  183.             length = offs2 + le - offset
  184.             Platform = 2
  185.         offset += NPKVbsOffset
  186.         texName = readStringt(TXRbs).decode('shift_jisx0213')
  187.         Align(TXRbs,16)
  188.         TXRbs.readBytes(0x10)
  189.         TexInfo.append((rapi.getExtensionlessName(texName), width, height, type1, offset, length, Platform))
  190.         if TXRbs.tell() == TXRbs.dataSize:
  191.             break
  192.     if (rapi.checkFileExists(fn + ".npkv")):
  193.         npkvData = rapi.loadIntoByteArray(fn + ".npkv")
  194.         NPKVbs = NoeBitStream(npkvData)
  195.         print("NPKV found")
  196.         for i, info in enumerate(TexInfo):
  197.             textureName = info[0]
  198.             width2 = info[1]
  199.             height2 = info[2]
  200.             type2 = info[3]
  201.             offset2 = info[4]
  202.             length2 = info[5]
  203.             plat = info[6]
  204.             NPKVbs.seek(offset2)
  205.             textureData = NPKVbs.readBytes(length2)
  206.             if type2 == 0xf:
  207.                 if plat == 1:
  208.                     textureData = rapi.callExtensionMethod("untile_1dthin", textureData, width2, height2, 4, 1)
  209.                 format = noesis.FOURCC_DXT1
  210.             elif type2 == 0x14:
  211.                 if plat == 1:
  212.                     textureData = rapi.callExtensionMethod("untile_1dthin", textureData, width2, height2, 8, 1)
  213.                 format = noesis.FOURCC_ATI2
  214.             elif type2 == 0x11:
  215.                 if plat == 1:
  216.                     textureData = rapi.callExtensionMethod("untile_1dthin", textureData, width2, height2, 8, 1)
  217.                 format = noesis.FOURCC_DXT5
  218.             elif type2 == 0x10:
  219.                 format = noesis.FOURCC_DXT3
  220.             textureData = rapi.imageDecodeDXT(textureData, width2, height2, format)
  221.             format = noesis.NOESISTEX_RGBA32
  222.             texture = NoeTexture(textureName, width2, height2, textureData, format)
  223.             texList.append(texture)
  224.         return (texList, NPKVbs.tell(), plat)
  225.     else:
  226.         print("NPKV not found")
  227.         return (texList, 0,0)
  228.     
  229. def parseVTX(VTXbs,fn,bones,boneDict, NPKIbsOffset = 0):
  230.     VTXInfo = []
  231.     bindBoneList = []
  232.     UVSize = 8
  233.     
  234.     while True:
  235.         VTXbs.readUInt()
  236.         VTXSize = VTXbs.read(">i")[0]
  237.         RSISize = VTXbs.read(">i")[0]
  238.         VTXbs.readUInt()
  239.         tempOffset = VTXbs.tell()
  240.         VTXbs.readBytes(0x6)
  241.         cond = VTXbs.readUShort()
  242.         VCount = VTXbs.readUInt()
  243.         if cond == 520:
  244.             VTXbs.readBytes(0x54)
  245.         elif cond == 519:
  246.             VTXbs.readBytes(0x4c)
  247.         elif cond == 518:
  248.             VTXbs.readBytes(0x44)
  249.         elif cond == 517:
  250.             VTXbs.readBytes(0x3C)
  251.         elif cond == 516:
  252.             VTXbs.readBytes(0x34)
  253.         VBSize = VTXbs.readUInt()
  254.         if cond not in [516, 517]:
  255.             WeightAddress = VTXbs.readUInt()
  256.             WeightSize = VTXbs.readUInt()
  257.             UVAddress = VTXbs.readUInt()
  258.             UVSize = VTXbs.readUInt()
  259.         VTXbs.readUShort()
  260.         bindboneListOfs = VTXbs.readUShort()
  261.         if bindboneListOfs:
  262.             VTXbs.seek(tempOffset+bindboneListOfs)
  263.             bb = []
  264.             while (VTXbs.tell() < tempOffset+VTXSize):
  265.                 name = VTXbs.readString()
  266.                 if name not in ["uvset","map1","map11", "map12", "damage_00", "damage_00(0)", "UVMap", "Col", "colorSet1","SculptFreezeColorTemp"]:
  267.                     bb.append(name)
  268.             bindBoneList = bb
  269.         else:
  270.             VTXbs.seek(tempOffset+VTXSize)
  271.         Align(VTXbs,16)
  272.         VTXbs.readBytes(0x20)
  273.         VAddress = VTXbs.readUInt() - 0x20000000 + NPKIbsOffset
  274.         VEndAddress = VTXbs.readUInt()
  275.         VTXbs.readUInt64()
  276.         FaceAddress = VTXbs.readUInt() - 0x20000000 + NPKIbsOffset
  277.         FCount = VTXbs.readUInt() // 2
  278.         VTXbs.readUInt64()
  279.         MeshName = VTXbs.readString()
  280.         Align(VTXbs,16)
  281.         VTXbs.readBytes(0x10)
  282.         VTXInfo.append((MeshName, VAddress, VCount, VBSize, UVSize, FaceAddress, FCount, bindBoneList, cond))
  283.         if VTXbs.tell() == VTXbs.dataSize:
  284.             break
  285.     
  286.     if (rapi.checkFileExists(fn + ".npki")):
  287.         npkiData = rapi.loadIntoByteArray(fn + ".npki")
  288.         NPKIbs = NoeBitStream(npkiData)
  289.         print("NPKI found\n")
  290.         for i, info in enumerate(VTXInfo):
  291.             submeshName = info[0]
  292.             VertAddress = info[1]
  293.             VertCount = info[2]
  294.             VertBSize = info[3]
  295.             UVsSize = info[4]
  296.             FAddress = info[5]
  297.             FICount = info[6]
  298.             BindBoneList = info[7]
  299.             Flag = info[8]
  300.             rapi.rpgSetName(submeshName)
  301.             matList.append(NoeMaterial(submeshName, ""))
  302.             rapi.rpgSetMaterial(submeshName)
  303.             NPKIbs.seek(VertAddress)
  304.             VertBuff = NPKIbs.readBytes(VertCount * VertBSize)
  305.             rapi.rpgBindPositionBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 0)
  306.             
  307.             bidx = []
  308.             bwgt = []
  309.             if (Flag not in [516, 517]):
  310.                 for j in range(VertCount):
  311.                     for k in range(4):
  312.                         bwgt.append(NPKIbs.readFloat())
  313.                     for k in range(4):
  314.                         bidx.append(NPKIbs.readUInt())
  315.                 
  316.                 for j in range (len(bidx)):
  317.                     acutalIdx = boneDict[BindBoneList[bidx[j]]]
  318.                     bidx[j] = acutalIdx
  319.                 bidxList = struct.pack("iiii"*VertCount, *bidx)
  320.                 bwgtList = struct.pack("ffff"*VertCount, *bwgt)
  321.                 rapi.rpgBindBoneIndexBuffer(bidxList, noesis.RPGEODATA_INT, 16, 4)
  322.                 rapi.rpgBindBoneWeightBuffer(bwgtList, noesis.RPGEODATA_FLOAT, 16, 4) 
  323.             else:
  324.                 bidxList = struct.pack("i"*VertCount, *[0]*VertCount)
  325.                 bwgtList = struct.pack("f"*VertCount, *[1.0]*VertCount)
  326.                 rapi.rpgBindBoneIndexBuffer(bidxList, noesis.RPGEODATA_INT, 4, 1)
  327.                 rapi.rpgBindBoneWeightBuffer(bwgtList, noesis.RPGEODATA_FLOAT, 4, 1)
  328.             
  329.             
  330.             if Flag not in [516, 517]:
  331.                 UVBuff = NPKIbs.readBytes(VertCount * UVsSize)
  332.                 rapi.rpgBindNormalBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 16)
  333.                 rapi.rpgBindTangentBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, VertBSize-16)
  334.                 if UVsSize >= 8 and UVsSize < 16:
  335.                     rapi.rpgBindUV1BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-8)
  336.                 elif UVsSize >= 16 and UVsSize < 24:
  337.                     rapi.rpgBindUV1BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-16)
  338.                     rapi.rpgBindUV2BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-8)
  339.                 elif UVsSize >= 24 and UVsSize < 32:
  340.                     rapi.rpgBindUV1BufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, UVsSize-24)
  341.                     rapi.rpgBindUVXBufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, 1, 2, UVsSize-16)
  342.                     rapi.rpgBindUVXBufferOfs(UVBuff, noesis.RPGEODATA_FLOAT, UVsSize, 2, 2, UVsSize-8)
  343.             else:
  344.                 rapi.rpgBindNormalBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 12)
  345.                 if VertBSize == 0x34:
  346.                     rapi.rpgBindUV1BufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 28)
  347.                     rapi.rpgBindUVXBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 1, 2, 36)
  348.                     rapi.rpgBindUVXBufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 2, 2, 44)
  349.                 else:
  350.                     rapi.rpgBindUV1BufferOfs(VertBuff, noesis.RPGEODATA_FLOAT, VertBSize, 24)
  351.             
  352.             NPKIbs.seek(FAddress)
  353.             FaceBuff = NPKIbs.readBytes(FICount * 2)
  354.             rapi.rpgCommitTriangles(FaceBuff, noesis.RPGEODATA_USHORT, FICount, noesis.RPGEO_TRIANGLE, 1)
  355.             rapi.rpgClearBufferBinds()
  356.         
  357.         rapi.rpgSetOption(noesis.RPGOPT_SWAPHANDEDNESS, 1)
  358.         model = rapi.rpgConstructModel()
  359.         model.setBones(bones)
  360.         rapi.rpgReset()
  361.         return (model,NPKIbs.tell())
  362.     else:
  363.         print("NPKI not found\n")
  364.         model = NoeModel()
  365.         return (model,0)
  366.  
  367. def parseBones(Bonebs):
  368.     bones0 = []
  369.     boneDict0 = {}    
  370.     
  371.     Bonebs.readUInt64()
  372.     Bonebs.readUInt64()
  373.     tempOffset2 = Bonebs.tell()
  374.     Bonebs.readBytes(0x6)
  375.     BCount = Bonebs.readUShort()
  376.     Bonebs.readUInt()
  377.     boneData = [None]*200
  378.     lastFlag = 255
  379.     
  380.     for i in range(BCount):
  381.         BoneNameOffset = Bonebs.readUInt()
  382.         tempOffset3 = Bonebs.tell()
  383.         Bonebs.seek(tempOffset2 + BoneNameOffset)
  384.         BoneName = Bonebs.readString()
  385.         Bonebs.seek(tempOffset3)
  386.         currentID = Bonebs.read(">h")[0]
  387.         parentID = currentID - 1
  388.         currentFlag = Bonebs.readShort()
  389.         Bonebs.readBytes(0x30) #localBoneMtx
  390.         worldBoneMtx = NoeMat43.fromBytes(Bonebs.readBytes(0x30)).transpose().inverse().swapHandedness()
  391.         boneData[currentID] = i
  392.         
  393.         if lastFlag != 255:
  394.             bones0.append(NoeBone(i,BoneName, worldBoneMtx, None, boneData[parentID]))
  395.         else:
  396.             bones0.append(NoeBone(i,BoneName, worldBoneMtx, None, i-1))
  397.         
  398.         Bonebs.readBytes(0x18)
  399.         lastFlag = currentFlag
  400.         
  401.     for b in range (BCount):
  402.         boneDict0[bones0[b].name] = b
  403.     
  404.     return (bones0, boneDict0)
  405.  
  406. def extraForm(buff2, NPKVTempOffset, NPKITempOffset, fn):
  407.     if NPKVTempOffset:
  408.         NPKV_TEMP_BYTES = NPKVTempOffset.to_bytes(4, byteorder='little')
  409.         values2 = bytearray(NPKV_TEMP_BYTES)
  410.         if values2[0] > 0x80:
  411.             values2[0] = 0x00
  412.             values2[1] +=1
  413.         elif values2[0] != 0x00:
  414.             values2[0] = 0x80
  415.         NPKVTempOffset = int.from_bytes(bytes(values2), byteorder='little', signed=False)
  416.         
  417.     try:
  418.         TXRBuff2 = buff2[buff2.index(TXR_SIGN):buff2.index(TXI_SIGN)]
  419.         TXRbs2 = NoeBitStream(TXRBuff2)
  420.         
  421.         parserT2 = parseTXR(TXRbs2,fn,NPKVTempOffset)
  422.         textureList2 = parserT2[0]
  423.         NPKVTempOffset = parserT2[1]
  424.     except:
  425.         print("There's no texture for this extra form")
  426.         textureList2 = []
  427.     
  428.     try:
  429.         BoneBuff2 = buff2[buff2.index(SKL_SIGN):buff2.index(MAT_SIGN)]
  430.         Bonebs2 = NoeBitStream(BoneBuff2)
  431.         
  432.         parserB2 = parseBones(Bonebs2)
  433.         bones2 = parserB2[0]
  434.         boneDict2 = parserB2[1]
  435.     except:
  436.         print("Bones were not found")
  437.         bones2 = []
  438.         boneDict2 = {}
  439.     
  440.     NPKI_TEMP_BYTES = NPKITempOffset.to_bytes(4, byteorder='little')
  441.     values = bytearray(NPKI_TEMP_BYTES)
  442.     if values[0] > 0x80:
  443.         values[0] = 0x00
  444.         values[1] +=1
  445.     elif values[0] != 0x00:
  446.         values[0] = 0x80    
  447.     NPKIOffset_num = int.from_bytes(bytes(values), byteorder='little', signed=False)
  448.     VTXBuff2 = buff2[buff2.index(VTX_SIGN):buff2.index(SCN_SIGN)]
  449.     VTXbs2 = NoeBitStream(VTXBuff2)        
  450.     parserV2 = parseVTX(VTXbs2, fn, bones2, boneDict2, NPKIOffset_num)
  451.     model2 = parserV2[0]
  452.     NPKITempOffset = parserV2[1]
  453.     
  454.     model2.setModelMaterials(NoeModelMaterials(textureList2, matList))
  455.     return (model2, NPKVTempOffset, NPKITempOffset)