Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import struct
- import ctypes as ct
- import sys
- import glob
- def unpackLE(typ,data): return struct.unpack("<"+typ,data)
- def unpackBE(typ,data): return struct.unpack(">"+typ,data)
- def convert(fname):
- f=open(fname,"rb")
- f2=open(fname[:-4]+".txt","w")
- magic=f.read(0x04)
- if magic==b"xDFP":
- unpacker=unpackLE
- struct=ct.LittleEndianStructure
- union=ct.LittleEndianUnion
- elif magic==b"PFDx":
- unpacker=unpackBE
- struct=ct.BigEndianStructure
- union=ct.BigEndianUnion
- else:
- raise ValueError("Bad header magic")
- f.seek(0x00)
- # Read header.
- class PATHFINDHEADER(struct):
- _fields_ = [
- ("id",ct.c_int32),
- ("majorRev",ct.c_uint8),
- ("minorRev",ct.c_uint8),
- ("release",ct.c_uint8),
- ("prerelease",ct.c_uint8),
- ("saveIncrement",ct.c_uint16),
- ("generateID",ct.c_uint16),
- ("projectID",ct.c_uint8),
- ("numtracks",ct.c_uint8),
- ("numsections",ct.c_uint8),
- ("numevents",ct.c_uint8),
- ("numrouters",ct.c_uint8),
- ("numnamedvars",ct.c_uint8),
- ("numnodes",ct.c_uint16),
- ("nodeoffsets",ct.c_uint32),
- ("nodedata",ct.c_uint32),
- ("eventoffsets",ct.c_uint32),
- ("eventdata",ct.c_uint32),
- ("namedvars",ct.c_uint32),
- ("noderouters",ct.c_uint32),
- ("trackoffsets",ct.c_uint32),
- ("trackinfos",ct.c_uint32),
- ("sampleoffsets",ct.c_uint32),
- ("mapfilelen",ct.c_uint32),
- ("v40reserve",ct.c_uint32*3)
- ]
- hdr=PATHFINDHEADER()
- f.readinto(hdr)
- if hdr.majorRev!=5:
- raise ValueError("Unsupported MPF version")
- namedvars=list()
- # Read named vars.
- class PATHNAMEDVAR(struct):
- _fields_ = [
- ("name",ct.c_char*16),
- ("value",ct.c_int32)
- ]
- f.seek(hdr.namedvars)
- for i in range(hdr.numnamedvars):
- var=PATHNAMEDVAR()
- f.readinto(var)
- namedvars.append((var.name.decode(),var.value))
- # Read nodes.
- class PATHNODEBEATS(struct):
- _fields_ = [
- ("forcesynch",ct.c_uint32,1),
- ("playbeats",ct.c_uint32,1)
- ]
- class PATHNODEEVENT(struct):
- _fields_ = [
- ("eventID",ct.c_uint32,24)
- ]
- class PATHNODECHANNEL(struct):
- _fields_ = [
- ("eventID",ct.c_uint32,24),
- ("channelset",ct.c_uint32,4)
- ]
- class PATHNODEEXTRA(union):
- _fields_ = [
- ("beat",PATHNODEBEATS),
- ("sendevent",PATHNODEEVENT),
- ("channelbranch",PATHNODECHANNEL)
- ]
- class PATHFINDNODE(struct):
- _fields_ = [
- ("index",ct.c_int32,16),
- ("trackID",ct.c_uint32,5),
- ("sectionID",ct.c_uint32,6),
- ("repeat",ct.c_int32,5),
- ("routerID",ct.c_uint32,12),
- ("numbranches",ct.c_uint32,5),
- ("controller",ct.c_uint32,3),
- ("beats",ct.c_uint32,4),
- ("bars",ct.c_uint32,8),
- ("partID",ct.c_uint32,16),
- ("synchevery",ct.c_uint32,4),
- ("synchoffset",ct.c_uint32,4),
- ("notes",ct.c_uint32,4),
- ("synch",ct.c_uint32,2),
- ("channelbranching",ct.c_uint32,1),
- ("unused",ct.c_uint32,1),
- #("extra",PATHNODEEXTRA)
- ]
- class PATHFINDBRANCH(struct):
- _fields_ = [
- ("controlmin",ct.c_int8),
- ("controlmax",ct.c_int8),
- ("dstnode",ct.c_uint16)
- ]
- f2.write("#"+"-"*72+"\n")
- f2.write("# Nodes\n")
- f2.write("#"+"-"*72+"\n")
- f.seek(hdr.nodeoffsets)
- nodeOffsets=list()
- for i in range(hdr.numnodes):
- offset=unpacker("H",f.read(0x02))[0]
- offset*=0x04
- nodeOffsets.append(offset)
- for i in range(hdr.numnodes):
- offset=nodeOffsets[i]
- f.seek(offset)
- f2.write("Node %d # 0x%08x\n" % (i,offset))
- f2.write("{\n")
- node=PATHFINDNODE()
- f.readinto(node)
- extra=PATHNODEEXTRA()
- f.readinto(extra)
- f2.write("\tWave %d\n" % node.index)
- f2.write("\tTrack %d\n" % node.trackID)
- f2.write("\tSection %d\n" % node.sectionID)
- f2.write("\tPart %d\n" % node.partID)
- f2.write("\tRouter %d\n" % (node.routerID-1))
- f2.write("\tController %s\n" % ("Normal" if node.controller==0 else "Random"))
- #f2.write("\tController %d\n" % node.controller)
- #f2.write("\tBeats %d\n" % node.beats)
- #f2.write("\tBars %d\n" % node.bars)
- if node.index==-1:
- f2.write("\tRepeat %d\n" % (node.repeat))
- if node.index==-3:
- sendevent=extra.sendevent
- f2.write("\tEvent 0x%08x\n" % (sendevent.eventID))
- else:
- pass
- f2.write("\tBranches\n")
- f2.write("\t{\n")
- for i in range(node.numbranches):
- branch=PATHFINDBRANCH()
- f.readinto(branch)
- f2.write("\t\tControl %d-%d -> %d\n" % (branch.controlmin,branch.controlmax,branch.dstnode))
- f2.write("\t}\n")
- f2.write("}\n")
- # Read events.
- class PATHEVENT(struct):
- _fields_ = [
- ("queued",ct.c_uint32),
- ("expiry",ct.c_uint32),
- ("lastact",ct.c_uint32),
- ("eventID",ct.c_uint32,24),
- ("numactions",ct.c_uint32,8),
- ("currentaction",ct.c_uint32,8),
- ("voices",ct.c_uint32,4),
- ("priority",ct.c_int32,4),
- ("bumplower",ct.c_uint32,1),
- ("beingFiltered",ct.c_uint32,1),
- ("project",ct.c_int32,3),
- ("unused",ct.c_int32,11)
- ]
- class PATHACTCONDITION(struct):
- _fields_ = [
- ("value",ct.c_int32,16),
- ("compareValue",ct.c_int32,16)
- ]
- class PATHACTBRANCHTO(struct):
- _fields_ = [
- ("node",ct.c_int32,16),
- ("ofsection",ct.c_int32,8),
- ("immediate",ct.c_int32,1)
- ]
- class PATHACTSETVALUE(struct):
- _fields_ = [
- ("towhat",ct.c_int32,16),
- ("setwhat",ct.c_uint32,8)
- ]
- class PATHACTEVENT(struct):
- _fields_ = [
- ("eventID",ct.c_uint32,24)
- ]
- class PATHACTCALC(struct):
- _fields_ = [
- ("value",ct.c_uint32,8),
- ("op",ct.c_uint32,8),
- ("by",ct.c_int32,16)
- ]
- class PATHACTWAITTIME(struct):
- _fields_ = [
- ("millisecs",ct.c_int32,16),
- ("lowest",ct.c_int32,16)
- ]
- class PATHACT(union):
- _fields_ = [
- ("only",PATHACTCONDITION),
- ("waittime",PATHACTWAITTIME),
- ("branch",PATHACTBRANCHTO),
- ("setval",PATHACTSETVALUE),
- ("event",PATHACTEVENT),
- ("calc",PATHACTCALC),
- ]
- class PATHACTION(struct):
- _fields_ = [
- ("track",ct.c_int32),
- ("sectionID",ct.c_int32,8),
- ("type",ct.c_uint32,7),
- ("done",ct.c_uint32,1),
- ("leftvaluetype",ct.c_uint32,2),
- ("rightvaluetype",ct.c_uint32,2),
- ("assess",ct.c_uint32,3),
- ("comparison",ct.c_uint32,3),
- ("indent",ct.c_uint32,3),
- ("unused",ct.c_uint32,3),
- #("act",PATHACT)
- ]
- specialTypes = [
- "SPECIALVALUE_BAD",
- "CONTROLLER",
- "CURRENTNODE",
- "CURRENTPART",
- "CURRENTSECTION",
- "EVENTEXPIRY",
- "EVENTPRIORITY",
- "FXBUS",
- "FXDRYLEVEL",
- "FXSENDLEVEL",
- "MAINVOICE",
- "NEXTNODE",
- "NOBRANCHING",
- "NODEDURATION",
- "PAUSE",
- "PITCHMULT",
- "PLAYINGNODE",
- "PLAYSTATUS",
- "RANDOMSHORT",
- "TIMENOW",
- "TIMETONEXTBEAT",
- "TIMETONEXTBAR",
- "TIMETONEXTNODE",
- "VOLUME",
- "TIMESTRETCH",
- "BARDURATION",
- "BEATDURATION",
- "CURRENTCHANNELSET",
- "PLAYINGCHANNELSET",
- ]
- def actValToString(val,typ):
- if typ==1:
- return specialTypes[val]
- elif typ==2:
- return "vars[\"%s\"]" % (namedvars[val][0])
- elif typ==3:
- return val
- raise Exception("Bad value type %d in event" % (typ))
- f2.write("\n")
- f2.write("#"+"-"*72+"\n")
- f2.write("# Events\n")
- f2.write("#"+"-"*72+"\n")
- f.seek(hdr.eventoffsets)
- eventOffsets=list()
- for i in range(hdr.numevents):
- offset=unpacker("H",f.read(0x02))[0]
- offset*=0x04
- eventOffsets.append(offset)
- for i in range(hdr.numevents):
- offset=eventOffsets[i]
- f.seek(offset)
- event=PATHEVENT()
- f.readinto(event)
- f2.write("Event 0x%08x # 0x%08x\n" % (event.eventID,offset))
- #f2.write("Event %d # 0x%08x\n" % (event.eventID,offset))
- f2.write("{\n")
- f2.write("\tActions\n")
- f2.write("\t{\n")
- indent=0
- for i in range(event.numactions):
- action=PATHACTION()
- f.readinto(action)
- act=PATHACT()
- f.readinto(act)
- if action.type==1 and action.assess>1:
- indent-=1
- f2.write("\t"*indent)
- if action.type==1:
- assessments = [
- None,
- "If",
- "Elif",
- "Else",
- "Endif"
- ]
- signs = [
- None,
- "==",
- "!=",
- ">",
- "<",
- ">=",
- "<="
- ]
- if action.assess in [1,2]:
- f2.write("\t\t%s %s %s %s\n" %
- (assessments[action.assess],
- actValToString(act.only.value,action.leftvaluetype),
- signs[action.comparison],
- actValToString(act.only.compareValue,action.rightvaluetype)))
- else:
- f2.write("\t\t%s\n" % (assessments[action.assess]))
- elif action.type==2:
- f2.write("\t\tWait %d\n" % (act.waittime.millisecs))
- elif action.type==4:
- f2.write("\t\tBranch %s (%s)" %
- (actValToString(act.branch.node,action.leftvaluetype),act.branch.ofsection))
- if act.branch.immediate:
- f2.write(" Immediate")
- f2.write("\n")
- elif action.type==8:
- f2.write("\t\tSet %s = %s\n" %
- (actValToString(act.setval.setwhat,action.leftvaluetype),
- actValToString(act.setval.towhat,action.rightvaluetype)))
- elif action.type==9:
- f2.write("\t\tEvent 0x%08x\n" % (act.event.eventID))
- elif action.type==14:
- signs = [
- None,
- "+",
- "-",
- "*",
- "/",
- "%"
- ]
- f2.write("\t\tCalc %s %s %s\n" %
- (actValToString(act.calc.value,action.leftvaluetype),
- signs[act.calc.op],
- actValToString(act.calc.by,action.rightvaluetype)))
- else:
- f2.write("\t\tAction %d\n" % (action.type))
- if action.type==1 and action.assess<4:
- indent+=1
- f2.write("\t}\n")
- f2.write("}\n")
- f2.write("#"+"-"*72+"\n")
- f2.write("# Named vars\n")
- f2.write("#"+"-"*72+"\n")
- for i in range(hdr.numnamedvars):
- var,val=namedvars[i]
- f2.write("Var %d\n" % i)
- f2.write("{\n")
- f2.write("\t%s = %d\n" % (var,val))
- f2.write("}\n")
- f2.write("#"+"-"*72+"\n")
- f2.write("# Routers\n")
- f2.write("#"+"-"*72+"\n")
- f.seek(hdr.noderouters)
- routerOffsets=list()
- for i in range(hdr.numrouters+1):
- offset=unpacker("I",f.read(0x04))[0] * 0x04
- routerOffsets.append(offset)
- for i in range(hdr.numrouters):
- offset=routerOffsets[i]
- nextOffset=routerOffsets[i+1]
- f.seek(offset)
- f2.write("Router %d\n" % i)
- f2.write("{\n")
- while f.tell()!=nextOffset:
- router=unpacker("I",f.read(0x04))[0]
- node1=router>>16
- node2=router&0xFFFF
- f2.write("\t%d -> %d\n" % (node1,node2))
- f2.write("}\n")
- f.close()
- f2.close()
- if __name__ == "__main__":
- if len(sys.argv)<2:
- print("Usage: ea_mpftotext.py <files> (wildcards accepted)")
- sys.exit()
- for arg in sys.argv[1:]:
- files=glob.glob(arg)
- for fname in files:
- if not fname.upper().endswith(".MPF"):
- continue
- if not os.path.isfile(fname):
- continue
- convert(fname)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement