home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 9017 / doa5pc.7z / doa5pc.py
Encoding:
Python Source  |  2015-04-13  |  11.5 KB  |  247 lines

  1. #Script Version 1.01
  2. #Dead or Alive 5 LR PC
  3.  
  4. from inc_noesis import *
  5. import time
  6. import noesis
  7. import array
  8. import struct
  9.  
  10. #rapi methods should only be used during handler callbacks
  11. import rapi
  12.  
  13. texonly = 0         #load only the textures
  14. warn    = 0         #print logs
  15.  
  16. #registerNoesisTypes is called by Noesis to allow the script to register formats.
  17. #Do not implement this function in script files unless you want them to be dedicated format modules!
  18. def registerNoesisTypes():
  19.     handle = noesis.register("Dead Or Alive 5 LR PC", ".tmc")
  20.     noesis.setHandlerTypeCheck(handle, tmcCheckType)
  21.     noesis.setHandlerLoadModel(handle, tmcLoadModel)
  22.     if warn:
  23.         noesis.logPopup()
  24.     return 1
  25.  
  26. #check if it's this type based on the data
  27. def tmcCheckType(data):
  28.     bs = NoeBitStream(data)
  29.     if bs.readBytes(3) != b"TMC":
  30.         return 0
  31.     return 1
  32.  
  33. class tmchead():
  34.     BlockName = ''
  35.     Count1 = Count2 = Offset1 = Offset2 = Offset3 = base = 0
  36.     offsets = []
  37.     def __init__(self, base, bytestream):
  38.         bytestream.seek(base)
  39.         self.BlockName = bytestream.readBytes(8).decode("ASCII").rstrip("\0")
  40.         self.Flg1, self.HSize, self.Size, self.Count1, self.Count2, self.Count3, self.Offset1, self.Offset2, self.Offset3, self.Flg2 = bytestream.read("<10L")
  41.         self.base = base
  42.         bytestream.seek(base+self.Offset1)
  43.         self.offsets = [bytestream.readUInt() for i in range(self.Count1)]
  44.  
  45. #load the model
  46. def tmcLoadModel(data, mdlList):
  47.     starttime = time.time()
  48.     ctx = rapi.rpgCreateContext()
  49.     bs = NoeBitStream(data)
  50.     bs.setEndian(NOE_LITTLEENDIAN)
  51.  
  52.     #prepare the l file
  53.     lname = rapi.getInputName()
  54.     lname = lname[:-3] + {'TMC':'TMCL', 'GMD':'TTGL'}[lname[-3:].upper()]
  55.     if not rapi.checkFileExists(lname):
  56.         print("file not found:", lname)
  57.         return 0
  58.     tmclData = NoeBitStream(rapi.loadIntoByteArray(lname))
  59.     tmclData.setEndian(NOE_LITTLEENDIAN)
  60.  
  61.     tmch     = tmchead(0, bs)#0MdlGeo,1TTX,2VtxLay,3IdxLay,4MtrCol,5MdlInfo, ! 6HieLay,7LHeader,8NodeLay,9GlblMtx,10BnOfsMtx, !! 11cpf,12MCAPACK,13RENPACK
  62.     mdlgeoh, ttdm, vtxlayh, idxlayh, mtrcolh, mdlinfoh, hielayh, lheaderh, nodelayh, glbmtxh  = [tmchead(tmch.offsets[i], bs) for i in range(10)]           
  63.  
  64.     if warn:print('l ok')
  65.     
  66.     #load textures
  67.     texListM = []
  68.     texNameListM = []
  69.     if ttdm.Count1: #parse TTDM
  70.         bs.seek(ttdm.base + ttdm.Offset2)
  71.         txszs = [bs.readUInt() for i in range(ttdm.Count2)]
  72.         for i in range(ttdm.Count1):
  73.             texName = 'M_' + str(i) + '.dds'
  74.             bs.seek(ttdm.base + ttdm.offsets[i])
  75.             data = bs.readBytes(txszs[i])
  76.             Height = int.from_bytes(data[12:16], byteorder='little')
  77.             Width = int.from_bytes(data[16:20], byteorder='little')
  78.             if   data[87] == 49: texFmt = noesis.NOESISTEX_DXT1
  79.             elif data[87] == 51: texFmt = noesis.NOESISTEX_DXT3
  80.             elif data[87] == 53: texFmt = noesis.NOESISTEX_DXT5
  81.             data = data[128:]
  82.             texListM.append(NoeTexture(texName, Width, Height, data, texFmt))
  83.             texNameListM.append(texName)
  84.     texListL = []
  85.     texNameListL = []
  86.     ttdlh = tmchead(ttdm.base + ttdm.Offset3, bs) #parse TTDL
  87.     if ttdlh.Count1:
  88.         bs.seek(ttdlh.base + ttdlh.Offset2)
  89.         txszs = [bs.readUInt() for i in range(ttdlh.Count1)]
  90.         for i in range(ttdlh.Count1):
  91.             texName = 'L_' + str(i) + '.dds'
  92.             tmclData.seek(0x80 + ttdlh.offsets[i])
  93.             data = tmclData.readBytes(txszs[i])
  94.             Height = int.from_bytes(data[12:16], byteorder='little')
  95.             Width = int.from_bytes(data[16:20], byteorder='little')
  96.             if   data[87] == 49: texFmt = noesis.NOESISTEX_DXT1
  97.             elif data[87] == 51: texFmt = noesis.NOESISTEX_DXT3
  98.             elif data[87] == 53: texFmt = noesis.NOESISTEX_DXT5
  99.             data = data[128:]
  100.             texListL.append(NoeTexture(texName, Width, Height, data, texFmt))
  101.             texNameListL.append(texName)            
  102.     texList = []
  103.     texNameList = []
  104.     ttdhh = tmchead(ttdm.base + ttdm.HSize, bs) #parse TTDH
  105.     for offs in ttdhh.offsets:
  106.         bs.seek(ttdhh.base + offs)
  107.         texFlg, texId = (bs.readUInt(), bs.readUInt())
  108.         if texFlg: 
  109.             texList.append(texListL[texId])
  110.             texNameList.append(texNameListL[texId])
  111.         else: 
  112.             texList.append(texListM[texId])
  113.             texNameList.append(texNameListM[texId])
  114.             
  115.     if warn:print('tx ok')
  116.  
  117.     if texonly:
  118.         mdl = NoeModel([])
  119.         mdl.setModelMaterials(NoeModelMaterials(texList, []))
  120.         mdlList.append(mdl)
  121.         rapi.rpgClearBufferBinds()
  122.         return 1
  123.  
  124.     #parse matrices
  125.     #parse GlblMtx
  126.     GlblMtxs = []
  127.     for offs in glbmtxh.offsets:
  128.         bs.seek(glbmtxh.base + offs)
  129.         gmatrix = NoeMat44.fromBytes(bs.readBytes(0x40))
  130.         GlblMtxs.append(gmatrix)
  131.     #parse NodeLay
  132.     mtx44 = NoeMat44()
  133.     NodeLays_meshnodes = {}
  134.     for offidx ,offs in enumerate(nodelayh.offsets):
  135.         nodeobjh = tmchead(nodelayh.base + offs, bs)
  136.         bs.seek(nodeobjh.base + 0x40)
  137.         nodename = bs.readString()
  138.         for mtxoffs in nodeobjh.offsets:
  139.             bs.seek(nodeobjh.base + mtxoffs)
  140.             objectindex = bs.readUInt()
  141.             objmatrix = (None if GlblMtxs[offidx] == mtx44 else GlblMtxs[offidx])
  142.             NodeLays_meshnodes[objectindex] = (nodename, GlblMtxs[offidx].toMat43())
  143.  
  144.     #parse mesh data
  145.     matList = []
  146.     #mdlinfo
  147.     mdlinfos = {}
  148.     for objidx, objoffs in enumerate(mdlinfoh.offsets):#get the transparency from those
  149.         if objoffs == 0: continue
  150.         objh  = tmchead(mdlinfoh.base + objoffs, bs)
  151.         objinfos = {}
  152.         for matoffset in objh.offsets:#parse mats
  153.             if matoffset == 0: continue
  154.             bs.seek(objh.base + matoffset)
  155.             matindex, unkflags0, Unk0, fUnk0, v0_1, v00_1, v000_1 = bs.read("<3Lf3L")
  156.             objinfos[matindex] = [unkflags0, Unk0, fUnk0, v0_1, v00_1, v000_1]
  157.         mdlinfos[objidx] = objinfos
  158.     #mdlgeo
  159.     for objidx, objoffs in enumerate(mdlgeoh.offsets):
  160.         if objoffs == 0: continue #fix to support mods
  161.         objh  = tmchead(mdlgeoh.base + objoffs, bs)
  162.         declh = tmchead(mdlgeoh.base + objoffs + objh.Offset3, bs)
  163.         fixmatrix = None
  164.         if objidx in NodeLays_meshnodes:
  165.             objname, fixmatrix = NodeLays_meshnodes[objidx]
  166.         else:
  167.             bs.seek(objh.base + 0x50)
  168.             objname = bs.readString()
  169.         if warn:print(objname)
  170.         if 'sweat' in objname or "zdmodel" in objname or "OPTblur" in objname or "_after_" in objname:
  171.             continue
  172.         decls = []
  173.         for decloffset in declh.offsets:#parse decls
  174.             bs.seek(declh.base + decloffset + 0xC)
  175.             IDXBUFindex, IDXcount, VERTcount, unk0, unk1, VTXBUFindex, vsize, vdatalayerscount =  bs.read("<5L16xL2L4x")#this reach the 0x40 offset           
  176.             vdatalayers = [(bs.readUInt(), bs.readUInt()) for i in range(vdatalayerscount)]#vdatalayers[2, 30002, 1000D, 20005, 60003, 5000B, 105000B]            
  177.             decls.append([IDXBUFindex,vsize,vdatalayers, IDXcount, VERTcount, unk0, unk1, VTXBUFindex]) #vdatalayeroffset, vd3dtype, vusage+vusagelayer
  178.  
  179.         declmats = [[] for i in range(len(decls))]
  180.         for matoffset in objh.offsets:#parse mats
  181.             if matoffset == 0: continue #fix to support mods
  182.             bs.seek(objh.base + matoffset)
  183.             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")
  184.             texbase = objh.base + matoffset + 0xD0 #textures info in mat
  185.  
  186.             txrs = []
  187.             for texinfo in range(matTexCount):#parse material textures
  188.                 bs.seek(texbase + texinfo * 0x70)
  189.                 texSlot, texmaptype, texId = (bs.readUInt(), bs.readUInt(), bs.readUInt())
  190.                 txrs.append((texSlot, texmaptype, texId))
  191.  
  192.             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))
  193.  
  194.         #parse raw data
  195.         rapi.rpgSetTransform(fixmatrix)
  196.         for enumdecl, (IDXBUFindex,vsize,vdatalayers, IDXcount, VERTcount, unk0, unk1, VTXBUFindex) in enumerate(decls): #??unk1 is tritype??
  197.  
  198.             fvfdata = {fvf[1]:(fvf[0]//0x10000) for fvf in vdatalayers}
  199.             bs.seek(vtxlayh.base + vtxlayh.offsets[VTXBUFindex])
  200.             BUFdata = bs.readBytes(vsize * VERTcount)
  201.             if 2 in fvfdata:         rapi.rpgBindPositionBufferOfs(BUFdata, noesis.RPGEODATA_FLOAT, vsize, fvfdata[2])
  202.             elif 3 in fvfdata:       rapi.rpgBindPositionBufferOfs(BUFdata, noesis.RPGEODATA_FLOAT, vsize, fvfdata[3])
  203.             else:                    rapi.rpgBindPositionBuffer(None, noesis.RPGEODATA_FLOAT, vsize)
  204.             if 0x5000B in fvfdata:   rapi.rpgBindUV1BufferOfs(BUFdata, noesis.RPGEODATA_HALFFLOAT, vsize, fvfdata[0x5000B])
  205.             elif 0x5000A in fvfdata: rapi.rpgBindUV1BufferOfs(BUFdata, noesis.RPGEODATA_HALFFLOAT, vsize, fvfdata[0x5000A]) 
  206.             else:                    rapi.rpgBindUV1Buffer(None, noesis.RPGEODATA_HALFFLOAT, vsize)
  207.             if 0x30002 in fvfdata:   rapi.rpgBindNormalBufferOfs(BUFdata, noesis.RPGEODATA_FLOAT, vsize, fvfdata[0x30002])
  208.             else:                    rapi.rpgBindNormalBuffer(None, noesis.RPGEODATA_HALFFLOAT, vsize)
  209.  
  210.             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]:
  211.  
  212.                 #unkflags0, Unk0, fUnk0, v0_1i, v00_1, v000_1 = mdlinfos[objidx][matindex]
  213.  
  214.                 meshname = objname + ("_%x"%matindex if matindex else "")
  215.                 matname = objname + "_mat%x"%matindex
  216.                 rapi.rpgSetName(meshname)
  217.                 material = NoeMaterial(matname, "")
  218.                 if twosided:
  219.                     material.setFlags(noesis.NMATFLAG_TWOSIDED, 0)
  220.                 for texindex, (texSlot, texmaptype, texId) in enumerate(txrs):
  221.                     if texSlot == 0:
  222.                         material.setTexture(texNameList[texId])
  223.                         if not (transparentmat or transparentmasc):
  224.                             material.setDiffuseColor(NoeVec4([1.0, 1.0, 1.0, 0.0]))
  225.                             material.setDefaultBlend(0)
  226.                     elif texSlot == 1:
  227.                         if texmaptype == 0:
  228.                             pass
  229.                     elif texSlot == 2:
  230.                         if texmaptype == 1:
  231.                             material.setNormalTexture(texNameList[texId])
  232.                     elif texSlot == 3:
  233.                         material.setNormalTexture("")
  234.  
  235.                 matList.append(material)
  236.                 #read mat indices
  237.                 bs.seek(idxlayh.base + idxlayh.offsets[IDXBUFindex] + mIDXstart*2)
  238.                 idata = bs.readBytes(mIDXcount*2)
  239.                 rapi.rpgSetMaterial(matname)
  240.                 rapi.rpgCommitTriangles(idata, noesis.RPGEODATA_USHORT, mIDXcount, noesis.RPGEO_TRIANGLE_STRIP, 1)
  241.  
  242.     mdl = rapi.rpgConstructModel()
  243.     mdl.setModelMaterials(NoeModelMaterials(texList, matList))
  244.     mdlList.append(mdl)
  245.     rapi.rpgClearBufferBinds()
  246.  
  247.     return 1