home *** CD-ROM | disk | FTP | other *** search
- #Script Version 1.01
- #Dead or Alive 5 LR PC
-
- from inc_noesis import *
- import time
- import noesis
- import array
- import struct
-
- #rapi methods should only be used during handler callbacks
- import rapi
-
- texonly = 0 #load only the textures
- warn = 0 #print logs
-
- #registerNoesisTypes is called by Noesis to allow the script to register formats.
- #Do not implement this function in script files unless you want them to be dedicated format modules!
- def registerNoesisTypes():
- handle = noesis.register("Dead Or Alive 5 LR PC", ".tmc")
- noesis.setHandlerTypeCheck(handle, tmcCheckType)
- noesis.setHandlerLoadModel(handle, tmcLoadModel)
- if warn:
- noesis.logPopup()
- return 1
-
- #check if it's this type based on the data
- def tmcCheckType(data):
- bs = NoeBitStream(data)
- if bs.readBytes(3) != b"TMC":
- return 0
- return 1
-
- class tmchead():
- BlockName = ''
- Count1 = Count2 = Offset1 = Offset2 = Offset3 = base = 0
- offsets = []
- def __init__(self, base, bytestream):
- bytestream.seek(base)
- self.BlockName = bytestream.readBytes(8).decode("ASCII").rstrip("\0")
- self.Flg1, self.HSize, self.Size, self.Count1, self.Count2, self.Count3, self.Offset1, self.Offset2, self.Offset3, self.Flg2 = bytestream.read("<10L")
- self.base = base
- bytestream.seek(base+self.Offset1)
- self.offsets = [bytestream.readUInt() for i in range(self.Count1)]
-
- #load the model
- def tmcLoadModel(data, mdlList):
- starttime = time.time()
- ctx = rapi.rpgCreateContext()
- bs = NoeBitStream(data)
- bs.setEndian(NOE_LITTLEENDIAN)
-
- #prepare the l file
- lname = rapi.getInputName()
- lname = lname[:-3] + {'TMC':'TMCL', 'GMD':'TTGL'}[lname[-3:].upper()]
- if not rapi.checkFileExists(lname):
- print("file not found:", lname)
- return 0
- tmclData = NoeBitStream(rapi.loadIntoByteArray(lname))
- tmclData.setEndian(NOE_LITTLEENDIAN)
-
- tmch = tmchead(0, bs)#0MdlGeo,1TTX,2VtxLay,3IdxLay,4MtrCol,5MdlInfo, ! 6HieLay,7LHeader,8NodeLay,9GlblMtx,10BnOfsMtx, !! 11cpf,12MCAPACK,13RENPACK
- mdlgeoh, ttdm, vtxlayh, idxlayh, mtrcolh, mdlinfoh, hielayh, lheaderh, nodelayh, glbmtxh = [tmchead(tmch.offsets[i], bs) for i in range(10)]
-
- if warn:print('l ok')
-
- #load textures
- texListM = []
- texNameListM = []
- if ttdm.Count1: #parse TTDM
- bs.seek(ttdm.base + ttdm.Offset2)
- txszs = [bs.readUInt() for i in range(ttdm.Count2)]
- for i in range(ttdm.Count1):
- texName = 'M_' + str(i) + '.dds'
- bs.seek(ttdm.base + ttdm.offsets[i])
- data = bs.readBytes(txszs[i])
- Height = int.from_bytes(data[12:16], byteorder='little')
- Width = int.from_bytes(data[16:20], byteorder='little')
- if data[87] == 49: texFmt = noesis.NOESISTEX_DXT1
- elif data[87] == 51: texFmt = noesis.NOESISTEX_DXT3
- elif data[87] == 53: texFmt = noesis.NOESISTEX_DXT5
- data = data[128:]
- texListM.append(NoeTexture(texName, Width, Height, data, texFmt))
- texNameListM.append(texName)
- texListL = []
- texNameListL = []
- ttdlh = tmchead(ttdm.base + ttdm.Offset3, bs) #parse TTDL
- if ttdlh.Count1:
- bs.seek(ttdlh.base + ttdlh.Offset2)
- txszs = [bs.readUInt() for i in range(ttdlh.Count1)]
- for i in range(ttdlh.Count1):
- texName = 'L_' + str(i) + '.dds'
- tmclData.seek(0x80 + ttdlh.offsets[i])
- data = tmclData.readBytes(txszs[i])
- Height = int.from_bytes(data[12:16], byteorder='little')
- Width = int.from_bytes(data[16:20], byteorder='little')
- if data[87] == 49: texFmt = noesis.NOESISTEX_DXT1
- elif data[87] == 51: texFmt = noesis.NOESISTEX_DXT3
- elif data[87] == 53: texFmt = noesis.NOESISTEX_DXT5
- data = data[128:]
- texListL.append(NoeTexture(texName, Width, Height, data, texFmt))
- texNameListL.append(texName)
- texList = []
- texNameList = []
- ttdhh = tmchead(ttdm.base + ttdm.HSize, bs) #parse TTDH
- for offs in ttdhh.offsets:
- bs.seek(ttdhh.base + offs)
- texFlg, texId = (bs.readUInt(), bs.readUInt())
- if texFlg:
- texList.append(texListL[texId])
- texNameList.append(texNameListL[texId])
- else:
- texList.append(texListM[texId])
- texNameList.append(texNameListM[texId])
-
- if warn:print('tx ok')
-
- if texonly:
- mdl = NoeModel([])
- mdl.setModelMaterials(NoeModelMaterials(texList, []))
- mdlList.append(mdl)
- rapi.rpgClearBufferBinds()
- return 1
-
- #parse matrices
- #parse GlblMtx
- GlblMtxs = []
- for offs in glbmtxh.offsets:
- bs.seek(glbmtxh.base + offs)
- gmatrix = NoeMat44.fromBytes(bs.readBytes(0x40))
- GlblMtxs.append(gmatrix)
- #parse NodeLay
- mtx44 = NoeMat44()
- NodeLays_meshnodes = {}
- for offidx ,offs in enumerate(nodelayh.offsets):
- nodeobjh = tmchead(nodelayh.base + offs, bs)
- bs.seek(nodeobjh.base + 0x40)
- nodename = bs.readString()
- for mtxoffs in nodeobjh.offsets:
- bs.seek(nodeobjh.base + mtxoffs)
- objectindex = bs.readUInt()
- objmatrix = (None if GlblMtxs[offidx] == mtx44 else GlblMtxs[offidx])
- NodeLays_meshnodes[objectindex] = (nodename, GlblMtxs[offidx].toMat43())
-
- #parse mesh data
- matList = []
- #mdlinfo
- mdlinfos = {}
- for objidx, objoffs in enumerate(mdlinfoh.offsets):#get the transparency from those
- if objoffs == 0: continue
- objh = tmchead(mdlinfoh.base + objoffs, bs)
- objinfos = {}
- for matoffset in objh.offsets:#parse mats
- if matoffset == 0: continue
- bs.seek(objh.base + matoffset)
- matindex, unkflags0, Unk0, fUnk0, v0_1, v00_1, v000_1 = bs.read("<3Lf3L")
- objinfos[matindex] = [unkflags0, Unk0, fUnk0, v0_1, v00_1, v000_1]
- mdlinfos[objidx] = objinfos
- #mdlgeo
- for objidx, objoffs in enumerate(mdlgeoh.offsets):
- if objoffs == 0: continue #fix to support mods
- objh = tmchead(mdlgeoh.base + objoffs, bs)
- declh = tmchead(mdlgeoh.base + objoffs + objh.Offset3, bs)
- fixmatrix = None
- if objidx in NodeLays_meshnodes:
- objname, fixmatrix = NodeLays_meshnodes[objidx]
- else:
- bs.seek(objh.base + 0x50)
- objname = bs.readString()
- if warn:print(objname)
- if 'sweat' in objname or "zdmodel" in objname or "OPTblur" in objname or "_after_" in objname:
- continue
- decls = []
- for decloffset in declh.offsets:#parse decls
- bs.seek(declh.base + decloffset + 0xC)
- IDXBUFindex, IDXcount, VERTcount, unk0, unk1, VTXBUFindex, vsize, vdatalayerscount = bs.read("<5L16xL2L4x")#this reach the 0x40 offset
- vdatalayers = [(bs.readUInt(), bs.readUInt()) for i in range(vdatalayerscount)]#vdatalayers[2, 30002, 1000D, 20005, 60003, 5000B, 105000B]
- decls.append([IDXBUFindex,vsize,vdatalayers, IDXcount, VERTcount, unk0, unk1, VTXBUFindex]) #vdatalayeroffset, vd3dtype, vusage+vusagelayer
-
- declmats = [[] for i in range(len(decls))]
- for matoffset in objh.offsets:#parse mats
- if matoffset == 0: continue #fix to support mods
- bs.seek(objh.base + matoffset)
- matindex, mtrcolindex, matTexCount, declfvfindex, transparentmat,v0_ff,transparentmasc,Pad2,fUnk0,fUnk1,Pad3,Pad4, v0_1,v3_4_5,v1_2, twosided, mIDXstart, mIDXcount, mVERTstart, mVERTcount = bs.read("<2L4xL40xL4xL3L2f2L4L4L")
- texbase = objh.base + matoffset + 0xD0 #textures info in mat
-
- txrs = []
- for texinfo in range(matTexCount):#parse material textures
- bs.seek(texbase + texinfo * 0x70)
- texSlot, texmaptype, texId = (bs.readUInt(), bs.readUInt(), bs.readUInt())
- txrs.append((texSlot, texmaptype, texId))
-
- declmats[declfvfindex].append((matindex, mtrcolindex, transparentmat, v0_ff,transparentmasc,Pad2,fUnk0,fUnk1,Pad3,Pad4, v0_1,v3_4_5,v1_2, twosided, mIDXstart,mIDXcount, mVERTstart, mVERTcount, txrs))
-
- #parse raw data
- rapi.rpgSetTransform(fixmatrix)
- for enumdecl, (IDXBUFindex,vsize,vdatalayers, IDXcount, VERTcount, unk0, unk1, VTXBUFindex) in enumerate(decls): #??unk1 is tritype??
-
- fvfdata = {fvf[1]:(fvf[0]//0x10000) for fvf in vdatalayers}
- bs.seek(vtxlayh.base + vtxlayh.offsets[VTXBUFindex])
- BUFdata = bs.readBytes(vsize * VERTcount)
- if 2 in fvfdata: rapi.rpgBindPositionBufferOfs(BUFdata, noesis.RPGEODATA_FLOAT, vsize, fvfdata[2])
- elif 3 in fvfdata: rapi.rpgBindPositionBufferOfs(BUFdata, noesis.RPGEODATA_FLOAT, vsize, fvfdata[3])
- else: rapi.rpgBindPositionBuffer(None, noesis.RPGEODATA_FLOAT, vsize)
- if 0x5000B in fvfdata: rapi.rpgBindUV1BufferOfs(BUFdata, noesis.RPGEODATA_HALFFLOAT, vsize, fvfdata[0x5000B])
- elif 0x5000A in fvfdata: rapi.rpgBindUV1BufferOfs(BUFdata, noesis.RPGEODATA_HALFFLOAT, vsize, fvfdata[0x5000A])
- else: rapi.rpgBindUV1Buffer(None, noesis.RPGEODATA_HALFFLOAT, vsize)
- if 0x30002 in fvfdata: rapi.rpgBindNormalBufferOfs(BUFdata, noesis.RPGEODATA_FLOAT, vsize, fvfdata[0x30002])
- else: rapi.rpgBindNormalBuffer(None, noesis.RPGEODATA_HALFFLOAT, vsize)
-
- for matindex, mtrcolindex, transparentmat, v0_ff,transparentmasc,Pad2,fUnk0,fUnk1,Pad3,Pad4, v0_1,v3_4_5,v1_2, twosided, mIDXstart,mIDXcount, mVERTstart, mVERTcount, txrs in declmats[enumdecl]:
-
- #unkflags0, Unk0, fUnk0, v0_1i, v00_1, v000_1 = mdlinfos[objidx][matindex]
-
- meshname = objname + ("_%x"%matindex if matindex else "")
- matname = objname + "_mat%x"%matindex
- rapi.rpgSetName(meshname)
- material = NoeMaterial(matname, "")
- if twosided:
- material.setFlags(noesis.NMATFLAG_TWOSIDED, 0)
- for texindex, (texSlot, texmaptype, texId) in enumerate(txrs):
- if texSlot == 0:
- material.setTexture(texNameList[texId])
- if not (transparentmat or transparentmasc):
- material.setDiffuseColor(NoeVec4([1.0, 1.0, 1.0, 0.0]))
- material.setDefaultBlend(0)
- elif texSlot == 1:
- if texmaptype == 0:
- pass
- elif texSlot == 2:
- if texmaptype == 1:
- material.setNormalTexture(texNameList[texId])
- elif texSlot == 3:
- material.setNormalTexture("")
-
- matList.append(material)
- #read mat indices
- bs.seek(idxlayh.base + idxlayh.offsets[IDXBUFindex] + mIDXstart*2)
- idata = bs.readBytes(mIDXcount*2)
- rapi.rpgSetMaterial(matname)
- rapi.rpgCommitTriangles(idata, noesis.RPGEODATA_USHORT, mIDXcount, noesis.RPGEO_TRIANGLE_STRIP, 1)
-
- mdl = rapi.rpgConstructModel()
- mdl.setModelMaterials(NoeModelMaterials(texList, matList))
- mdlList.append(mdl)
- rapi.rpgClearBufferBinds()
-
- return 1