mirror of
https://github.com/ctruLua/ctruLua.git
synced 2025-10-27 16:39:29 +00:00
682 lines
19 KiB
Python
682 lines
19 KiB
Python
import sys
|
|
import os
|
|
import re
|
|
import copy
|
|
import struct
|
|
|
|
#TODO : add parsing checks, handle errors more gracefully
|
|
|
|
def toFloat24(f):
|
|
f=bytearray(struct.pack('f', f))
|
|
s=f[3]>>7
|
|
tmp=(((f[3]<<1)|(f[2]>>7))&0xFF)-0x40
|
|
tmp2=(((f[0])|(f[1]<<8)|(f[2]<<16))>>7)&0xFFFF
|
|
if tmp>=0:
|
|
tmp2|=tmp<<16
|
|
tmp2|=s<<23
|
|
else:
|
|
tmp2=s<<23
|
|
return tmp2
|
|
|
|
vshMain=None
|
|
vshEndmain=None
|
|
gshMain=None
|
|
gshEndmain=None
|
|
|
|
class DVLE(object):
|
|
def __init__(self, type):
|
|
self._main = 0
|
|
self._endmain = 0
|
|
self._type = type
|
|
self._const = []
|
|
self._label = []
|
|
self._labelmap = {}
|
|
self._outmap = []
|
|
self._inmap = []
|
|
self._symbol = bytearray()
|
|
self._symbolnum = 0
|
|
|
|
def setMain(self, main):
|
|
self._main = main
|
|
|
|
def setEndmain(self, endmain):
|
|
self._endmain = endmain
|
|
|
|
#binary word tuple
|
|
def addConstant(self, const):
|
|
self._const.append(const)
|
|
|
|
#(reg, v)
|
|
def addConstantB(self, const):
|
|
self._const.append(((const[0]<<16)|(0x0), const[1], 0, 0, 0))
|
|
|
|
#(reg, x, y, z, w)
|
|
def addConstantI(self, const):
|
|
self._const.append(((const[0]<<16)|(0x1), ((const[1]&0xff)|((const[2]&0xff)<<8)|((const[3]&0xff)<<16)|(const[4]<<24)), (0), (0), (0)))
|
|
|
|
#(reg, x, y, z, w)
|
|
def addConstantF(self, const):
|
|
self._const.append(((const[0]<<16)|(0x2), toFloat24(const[1]), toFloat24(const[2]), toFloat24(const[3]), toFloat24(const[4])))
|
|
|
|
#string
|
|
def addSymbol(self, s):
|
|
ret=len(self._symbol)
|
|
self._symbol+=bytearray(s, "ascii")+bytearray(b"\x00")
|
|
self._symbolnum+=1
|
|
return ret
|
|
|
|
#(code offset, symbol offset)
|
|
def addLabel(self, label):
|
|
self._label.append((label[0],self.addSymbol(label[1])))
|
|
self._labelmap[label[1]]=label[0]
|
|
|
|
def getLabelAddress(self, label):
|
|
if label in self._labelmap:
|
|
return self._labelmap[label]
|
|
else:
|
|
return 0x0
|
|
|
|
#binary word tuple
|
|
def addOutput(self, out):
|
|
self._outmap.append(out)
|
|
|
|
#(startreg, endreg, symbol offset)
|
|
def addInput(self, ind):
|
|
self._inmap.append((ind[0],ind[1],self.addSymbol(ind[2])))
|
|
|
|
def toBinary(self):
|
|
ret=[]
|
|
|
|
offsetConst=0x40
|
|
offsetLabel=offsetConst+len(self._const)*0x14
|
|
offsetOutmap=offsetLabel+len(self._label)*0x10
|
|
offsetInmap=offsetOutmap+len(self._outmap)*0x8
|
|
offsetSymbol=offsetInmap+len(self._inmap)*0x8
|
|
|
|
ret.append(0x454C5644) #DVLE magic
|
|
ret.append((self._type&1)<<16)
|
|
ret.append(self._main)
|
|
ret.append(self._endmain)
|
|
ret.append(0x00000000) # ?
|
|
ret.append(0x00000000) # ?
|
|
ret.append(offsetConst)
|
|
ret.append(len(self._const))
|
|
ret.append(offsetLabel)
|
|
ret.append(len(self._label))
|
|
ret.append(offsetOutmap)
|
|
ret.append(len(self._outmap))
|
|
ret.append(offsetInmap)
|
|
ret.append(len(self._inmap))
|
|
ret.append(offsetSymbol)
|
|
ret.append(len(self._symbol))
|
|
|
|
for k in self._const:
|
|
ret.append(k[0])
|
|
ret.append(k[1])
|
|
ret.append(k[2])
|
|
ret.append(k[3])
|
|
ret.append(k[4])
|
|
|
|
i=0
|
|
for k in self._label:
|
|
ret.append(i)
|
|
ret.append(k[0])
|
|
ret.append(0x00000000) # ?
|
|
ret.append(k[1])
|
|
i+=1
|
|
|
|
for k in self._outmap:
|
|
ret.append(k[0])
|
|
ret.append(k[1])
|
|
|
|
for k in self._inmap:
|
|
ret.append(k[2])
|
|
ret.append(((k[1]&0xFFFF)<<16)|(k[0]&0xFFFF))
|
|
|
|
retb=bytearray()
|
|
for k in ret:
|
|
retb+=struct.pack("I",k)
|
|
retb+=self._symbol
|
|
|
|
return retb
|
|
|
|
|
|
class DVLP(object):
|
|
def __init__(self):
|
|
self._code = []
|
|
self._opdesc = []
|
|
|
|
def clearCode(self):
|
|
self._code[:] = []
|
|
|
|
def addInstruction(self, inst):
|
|
self._code.append(inst)
|
|
return len(self._code)
|
|
|
|
def addOpdesc(self, opdesc):
|
|
self._opdesc.append(opdesc)
|
|
return len(self._opdesc)
|
|
|
|
def getCodelength(self):
|
|
return len(self._code)
|
|
|
|
def toBinary(self):
|
|
ret=[]
|
|
|
|
offsetCode=0x28
|
|
offsetOpdesc=offsetCode+len(self._code)*0x4
|
|
symbolOffset=offsetOpdesc+len(self._opdesc)*0x8
|
|
|
|
ret.append(0x504C5644) #DVLP magic
|
|
ret.append(0x00000000) # ?
|
|
ret.append(offsetCode)
|
|
ret.append(len(self._code))
|
|
ret.append(offsetOpdesc)
|
|
ret.append(len(self._opdesc))
|
|
ret.append(symbolOffset)
|
|
ret.append(0x00000000) # ?
|
|
ret.append(0x00000000) # ?
|
|
ret.append(0x00000000) # ?
|
|
|
|
retb=bytearray()
|
|
for k in ret:
|
|
retb+=struct.pack("I",k)
|
|
for k in self._code:
|
|
retb+=struct.pack("I",k)
|
|
for k in self._opdesc:
|
|
retb+=struct.pack("I",k[0])
|
|
retb+=struct.pack("I",k[1])
|
|
|
|
return retb
|
|
|
|
|
|
class DVLB(object):
|
|
def __init__(self):
|
|
self._dvlp = DVLP()
|
|
self._dvle = []
|
|
|
|
def getDVLP(self):
|
|
return self._dvlp
|
|
|
|
def addDVLE(self, dvle):
|
|
self._dvle.append(dvle)
|
|
|
|
def toBinary(self):
|
|
ret=[]
|
|
|
|
ret.append(0x424C5644) #DVLB magic
|
|
ret.append(len(self._dvle))
|
|
|
|
off=len(self._dvle)*0x4+0x8
|
|
retb=bytearray()
|
|
retb+=self._dvlp.toBinary()
|
|
for k in self._dvle:
|
|
retb+=bytearray([0x00]*(0 if len(retb)%4==0 else 4-(len(retb)%4)))
|
|
ret.append(off+len(retb))
|
|
retb+=k.toBinary()
|
|
|
|
retb2=bytearray()
|
|
for k in ret:
|
|
retb2+=struct.pack("I",k)
|
|
|
|
return retb2+retb
|
|
|
|
|
|
def getRegisterFromNameDst(s):
|
|
if s[0]=="o": # output
|
|
return int(s[1:])
|
|
elif s[0]=="v": # attribute
|
|
print("error : "+s+" cannot be accessed from dst")
|
|
elif s[0]=="r": # temporary register
|
|
return int(s[1:])+0x10
|
|
elif s[0]=="c": # uniform
|
|
print("error : "+s+" cannot be accessed from dst")
|
|
elif s[0]=="d": # direct hex; unambiguous
|
|
return int("0x"+s[1:],0)
|
|
else:
|
|
print("error : "+s+" is not a valid register name")
|
|
|
|
def getRegisterFromNameSrc1(s):
|
|
index=0
|
|
if "[" in s:
|
|
i=s.index("[")
|
|
index=s[i+1:-1]
|
|
s=s[:i]
|
|
if index=="a0.x":
|
|
index=1
|
|
elif index=="a0.y":
|
|
index=2
|
|
elif index=="aL":
|
|
index=3
|
|
if s[0]=="o": # output
|
|
print("error : "+s+" cannot be accessed from src1")
|
|
elif s[0]=="v": # attribute
|
|
return (int(s[1:]), index)
|
|
elif s[0]=="r": # temporary register
|
|
return (int(s[1:])+0x10, index)
|
|
elif s[0]=="c": # uniform
|
|
return (int(s[1:])+0x20, index)
|
|
elif s[0]=="d": # direct hex; unambiguous
|
|
return (int("0x"+s[1:],0), index)
|
|
else:
|
|
print("error : "+s+" is not a valid register name")
|
|
|
|
def getRegisterFromNameSrc2(s):
|
|
if s[0]=="o": # output
|
|
print("error : "+s+" cannot be accessed from src2")
|
|
elif s[0]=="v": # attribute
|
|
return int(s[1:])
|
|
elif s[0]=="r": # temporary register
|
|
return int(s[1:])+0x10
|
|
elif s[0]=="c": # uniform
|
|
print("error : "+s+" cannot be accessed from src2")
|
|
elif s[0]=="d": # direct hex; unambiguous
|
|
return int("0x"+s[1:],0)
|
|
else:
|
|
print("error : "+s+" is not a valid register name")
|
|
|
|
def assembleFormat11(d):
|
|
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<24)|((d["src1"]&0x7F)<<17)|((d["src2"]&0x7F)<<10)|((d["src3"]&0x1F)<<5)|(d["extid"]&0x1F)
|
|
|
|
def parseFormat11(dvle, s):
|
|
operandFmt="[^\s,]*"
|
|
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
|
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
|
r=p.match(s)
|
|
if r:
|
|
src1 = getRegisterFromNameSrc1(r.group(2))
|
|
src2 = getRegisterFromNameSrc1(r.group(3))
|
|
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
|
"src1" : src1[0],
|
|
"src2" : src2[0],
|
|
"src3" : getRegisterFromNameSrc2(r.group(4)),
|
|
"extid" : int(r.group(5),0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction")
|
|
|
|
def assembleFormat12(d):
|
|
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<24)|((d["src1"]&0x7F)<<17)|((d["src2"]&0x1F)<<12)|((d["src3"]&0x7F)<<5)|(d["extid"]&0x1F)
|
|
|
|
def parseFormat12(dvle, s):
|
|
operandFmt="[^\s,]*"
|
|
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
|
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
|
r=p.match(s)
|
|
if r:
|
|
src1 = getRegisterFromNameSrc1(r.group(2))
|
|
src3 = getRegisterFromNameSrc1(r.group(4))
|
|
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
|
"src1" : src1[0],
|
|
"src2" : getRegisterFromNameSrc2(r.group(3)),
|
|
"src3" : src3[0],
|
|
"extid" : int(r.group(5),0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction")
|
|
|
|
def assembleFormat1(d):
|
|
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<21)|((d["idx"]&0x3)<<19)|((d["src1"]&0x7F)<<12)|((d["src2"]&0x1F)<<7)|(d["extid"]&0x7F)
|
|
|
|
def parseFormat1(dvle, s):
|
|
operandFmt="[^\s,]*"
|
|
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
|
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
|
r=p.match(s)
|
|
if r:
|
|
src1 = getRegisterFromNameSrc1(r.group(2))
|
|
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
|
"src1" : src1[0],
|
|
"idx" : src1[1],
|
|
"src2" : getRegisterFromNameSrc2(r.group(3)),
|
|
"extid" : int(r.group(4),0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction")
|
|
|
|
def assembleFormat2(d):
|
|
print(d)
|
|
return (d["opcode"]<<26)|((d["flags"]&0xF)<<22)|((d["addr"]&0xFFF)<<10)|(d["ret"]&0x3FF)
|
|
|
|
def parseFormat2(dvle, s):
|
|
operandFmt1="[^\s,]*"
|
|
# operandFmt3="0b[01]+"
|
|
operandFmt3="([!]?)cmp.([xy])"
|
|
operandFmt3=operandFmt3+"\s*(?:(&&|\|\|)\s*"+operandFmt3+")?"
|
|
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*"+operandFmt3+"\s*$")
|
|
# p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*("+operandFmt3+")\s*")
|
|
r=p.match(s)
|
|
if r:
|
|
neg = [0 if r.group(3)=="!" else 1, 0 if r.group(6)=="!" else 1]
|
|
comp = [2 if r.group(4)=="y" else 3, None if r.group(7)==None else (2 if r.group(7)=="y" else 3)]
|
|
op = r.group(5)
|
|
if comp[0]!=comp[1]:
|
|
flags=0
|
|
flags|=neg[0]<<comp[0]
|
|
flags|=neg[1]<<comp[1] if comp[1]!=None else 0
|
|
flags|=1 if op=="&&" else (0 if op=="||" else (3 if comp[0]==2 else 2))
|
|
# print(s)
|
|
# flags=int(r.group(3),0)
|
|
print(bin(flags))
|
|
return {"addr" : dvle.getLabelAddress(r.group(2)),
|
|
"ret" : dvle.getLabelAddress(r.group(1))-dvle.getLabelAddress(r.group(2)),
|
|
"flags" : flags}
|
|
else:
|
|
raise Exception("invalid or redundant condition "+s)
|
|
else:
|
|
raise Exception("encountered error while parsing instruction "+s)
|
|
|
|
def assembleFormat3(d):
|
|
return (d["opcode"]<<26)
|
|
|
|
def parseFormat3(dvle, s):
|
|
# doesn't check that there are no operands.
|
|
# (but really if you want to be an idiot and add useless operands to your code, go ahead)
|
|
return {}
|
|
|
|
def assembleFormat4(d):
|
|
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<21)|((d["idx"]&0x3)<<19)|((d["src1"]&0x7F)<<12)|(d["extid"]&0x7F)
|
|
|
|
def parseFormat4(dvle, s):
|
|
operandFmt="[^\s,]*"
|
|
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
|
p=re.compile("^\s*("+operandFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
|
r=p.match(s)
|
|
if r:
|
|
src1 = getRegisterFromNameSrc1(r.group(2))
|
|
return {"dst" : getRegisterFromNameDst(r.group(1)),
|
|
"src1" : src1[0],
|
|
"idx" : src1[1],
|
|
"extid" : int(r.group(3),0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction "+s)
|
|
|
|
def assembleFormat5(d):
|
|
return (d["opcode"]<<26)|((d["cmpx"]&0x7)<<24)|((d["cmpy"]&0x7)<<21)|((d["src1"]&0x7F)<<12)|((d["src2"]&0x1F)<<7)|(d["extid"]&0x7F)
|
|
|
|
cmpOp = {"eq" : 0x0, "ne" : 0x1, "lt" : 0x2, "le" : 0x3, "gt" : 0x4, "ge" : 0x5}
|
|
|
|
def parseFormat5(dvle, s):
|
|
operandFmt="[^\s,]*"
|
|
descFmt="(?:(?:0x)[0-9a-f]+)|[0-9a-f]+"
|
|
opFmt="[a-z]+"
|
|
p=re.compile("^\s*("+operandFmt+"),\s*("+opFmt+"),\s*("+opFmt+"),\s*("+operandFmt+")\s*\(("+descFmt+")\)")
|
|
r=p.match(s)
|
|
if r:
|
|
src1 = getRegisterFromNameSrc1(r.group(1))
|
|
return {"src1" : src1[0],
|
|
"idx" : src1[1],
|
|
"cmpx" : cmpOp[r.group(2)],
|
|
"cmpy" : cmpOp[r.group(3)],
|
|
"src2" : getRegisterFromNameSrc2(r.group(4)),
|
|
"extid" : int(r.group(5),0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction (5)")
|
|
|
|
def assembleFormat6(d):
|
|
return (d["opcode"]<<26)|((d["dst"]&0x1F)<<21)|((d["src2"]&0x7F)<<7)|((d["src1"]&0x1F)<<14)|(d["extid"]&0x7F)
|
|
|
|
def parseFormat7(dvle, s):
|
|
operandFmt1="[^\s,]*"
|
|
operandFmt3="i[0-9]+"
|
|
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt3+")")
|
|
r=p.match(s)
|
|
if r:
|
|
return {"addr" : dvle.getLabelAddress(r.group(1))-1,
|
|
"ret" : 0,
|
|
"int" : int(r.group(2).strip()[1:],0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction")
|
|
|
|
def assembleFormat7(d):
|
|
return (d["opcode"]<<26)|((d["int"]&0xF)<<22)|((d["addr"]&0xFFF)<<10)|(d["ret"]&0x3FF)
|
|
|
|
def parseFormat8(dvle, s):
|
|
operandFmt1="[^\s,]*"
|
|
operandFmt3="b[0-9]+"
|
|
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+"),\s*("+operandFmt3+")")
|
|
r=p.match(s)
|
|
if r:
|
|
return {"addr" : dvle.getLabelAddress(r.group(2)),
|
|
"ret" : dvle.getLabelAddress(r.group(1))-dvle.getLabelAddress(r.group(2)),
|
|
"bool" : int(r.group(3).strip()[1:],0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction")
|
|
|
|
def assembleFormat8(d):
|
|
return (d["opcode"]<<26)|((d["bool"]&0xF)<<22)|((d["addr"]&0xFFF)<<10)|(d["ret"]&0x3FF)
|
|
|
|
def parseFormat9(dvle, s):
|
|
operandFmt1="true|false"
|
|
operandFmt3="vtx[0-9]+"
|
|
p=re.compile("^\s*("+operandFmt3+"),\s*("+operandFmt1+"),\s*("+operandFmt1+")")
|
|
r=p.match(s)
|
|
if r:
|
|
return {"unk" : r.group(3)=="true",
|
|
"prim" : r.group(2)=="true",
|
|
"vtx" : int(r.group(1).strip()[3:],0)}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction")
|
|
|
|
def assembleFormat9(d):
|
|
return (d["opcode"]<<26)|((d["vtx"]&0x3)<<24)|((d["unk"]&0x1)<<22)|((d["prim"]&0x1)<<23)
|
|
|
|
def parseFormat10(dvle, s):
|
|
operandFmt1="[^\s,]*"
|
|
p=re.compile("^\s*("+operandFmt1+"),\s*("+operandFmt1+")")
|
|
r=p.match(s)
|
|
if r:
|
|
return {"addr" : dvle.getLabelAddress(r.group(1)),
|
|
"ret" : dvle.getLabelAddress(r.group(2))-dvle.getLabelAddress(r.group(1)),
|
|
"flags" : 0x0}
|
|
else:
|
|
raise Exception("encountered error while parsing instruction")
|
|
|
|
instList={}
|
|
fmtList=[(parseFormat1, assembleFormat1), (parseFormat2, assembleFormat2), (parseFormat3, assembleFormat3), (parseFormat4, assembleFormat4), (parseFormat5, assembleFormat5), (parseFormat1, assembleFormat6), (parseFormat7, assembleFormat7), (parseFormat8, assembleFormat8), (parseFormat9, assembleFormat9), (parseFormat10, assembleFormat2), (parseFormat11, assembleFormat11), (parseFormat12, assembleFormat12)]
|
|
|
|
instList["add"]={"opcode" : 0x00, "format" : 0}
|
|
instList["dp3"]={"opcode" : 0x01, "format" : 0}
|
|
instList["dp4"]={"opcode" : 0x02, "format" : 0}
|
|
instList["dph"]={"opcode" : 0x03, "format" : 0}
|
|
instList["op4"]={"opcode" : 0x04, "format" : 0}
|
|
instList["ex2"]={"opcode" : 0x05, "format" : 3}
|
|
instList["lg2"]={"opcode" : 0x06, "format" : 3}
|
|
instList["op7"]={"opcode" : 0x07, "format" : 3}
|
|
instList["mul"]={"opcode" : 0x08, "format" : 0}
|
|
instList["sge"]={"opcode" : 0x09, "format" : 0}
|
|
instList["slt"]={"opcode" : 0x0a, "format" : 0}
|
|
instList["flr"]={"opcode" : 0x0B, "format" : 3}
|
|
instList["max"]={"opcode" : 0x0C, "format" : 0}
|
|
instList["min"]={"opcode" : 0x0D, "format" : 0}
|
|
instList["rcp"]={"opcode" : 0x0E, "format" : 3}
|
|
instList["rsq"]={"opcode" : 0x0F, "format" : 3}
|
|
instList["mova"]={"opcode" : 0x12, "format" : 3}
|
|
instList["mov"]={"opcode" : 0x13, "format" : 3}
|
|
instList["dphi"]={"opcode" : 0x18, "format" : 5}
|
|
instList["op19"]={"opcode" : 0x19, "format" : 5}
|
|
instList["sgei"]={"opcode" : 0x1a, "format" : 5}
|
|
instList["slti"]={"opcode" : 0x1b, "format" : 5}
|
|
instList["nop"]={"opcode" : 0x21, "format" : 2}
|
|
instList["end"]={"opcode" : 0x22, "format" : 2}
|
|
instList["call"] ={"opcode" : 0x24, "format" : 9}
|
|
instList["ifu"] ={"opcode" : 0x27, "format" : 7}
|
|
instList["ifc"] ={"opcode" : 0x28, "format" : 1}
|
|
instList["loop"] ={"opcode" : 0x29, "format" : 6}
|
|
instList["emit"]={"opcode" : 0x2a, "format" : 2}
|
|
instList["setemit"]={"opcode" : 0x2b, "format" : 8}
|
|
instList["cmp"]={"opcode" : 0x2e, "format" : 4}
|
|
instList["madi"]={"opcode" : 0x30, "format" : 11}
|
|
instList["mad"]={"opcode" : 0x38, "format" : 10}
|
|
|
|
def parseConst(dvlp, dvle, s):
|
|
s=s.split(",")
|
|
s[0]=s[0].strip()
|
|
if s[0][0]=="b":
|
|
# bool constant
|
|
dvle.addConstantB((int(s[0][1:],0), int(s[1])))
|
|
elif s[0][0]=="i":
|
|
# int vec4 constant
|
|
dvle.addConstantI((int(s[0][1:],0), int(s[1],0), int(s[2],0), int(s[3],0), int(s[4],0)))
|
|
elif s[0][0]=="c":
|
|
# float vec4 constant
|
|
dvle.addConstantF((int(s[0][1:],0), float(s[1]), float(s[2]), float(s[3]), float(s[4])))
|
|
|
|
outputTypes={"result.position" : 0x0,
|
|
"result.normalquat" : 0x1,
|
|
"result.color" : 0x2,
|
|
"result.texcoord0" : 0x3,
|
|
"result.texcoord0w" : 0x4,
|
|
"result.texcoord1" : 0x5,
|
|
"result.texcoord2" : 0x6,
|
|
"result.view" : 0x8}
|
|
|
|
def parseOut(dvlp, dvle, s):
|
|
s=s.split(",")
|
|
s[0]=s[0].replace(" ", "")
|
|
s[1]=s[1].replace(" ", "")
|
|
s[2]=s[2].replace(" ", "")
|
|
reg=int(s[0][1:])
|
|
if s[1] in outputTypes:
|
|
type=outputTypes[s[1]]
|
|
mask=int(s[2], 0)
|
|
dvle.addOutput((type|(reg<<16), mask))
|
|
|
|
swizVal={"w":0x3,"z":0x2,"y":0x1,"x":0x0}
|
|
|
|
def parseOpdesc(dvlp, dvle, s):
|
|
s=s.split(",")
|
|
for k in range(len(s)):
|
|
s[k]=s[k].replace(" ", "")
|
|
#dst mask
|
|
mask=0
|
|
for k in range(4):
|
|
if s[0][k]!="_":
|
|
mask|=1<<(3-k)
|
|
swiz=[0,0,0]
|
|
neg=[0,0,0]
|
|
for i in range(len(s)-1):
|
|
l=s[1+i]
|
|
if l[0]=='-':
|
|
neg[i]=1
|
|
l=l[1:]
|
|
for k in range(4):
|
|
swiz[i]=((swiz[i]<<2)|swizVal[l[k]])
|
|
dvlp.addOpdesc(((1<<31)|(swiz[2]<<23)|(neg[2]<<22)|(swiz[1]<<14)|(neg[1]<<13)|(swiz[0]<<5)|(neg[0]<<4)|(mask),0x0000000F))
|
|
|
|
def parseUniform(dvlp, dvle, s):
|
|
s=s.split(",")
|
|
for k in range(len(s)):
|
|
s[k]=s[k].replace(" ", "")
|
|
type=s[0][0]
|
|
if type!=s[1][0]:
|
|
print("inconsistent uniform register assignment !")
|
|
return
|
|
if type=="c":
|
|
offset=0x10
|
|
elif type=="i":
|
|
offset=0x70
|
|
elif type=="b":
|
|
offset=0x78
|
|
dvle.addInput((int(s[0][1:],0)+offset,int(s[1][1:],0)+offset,s[2]))
|
|
|
|
def parseVsh(dvlp, dvle, s):
|
|
global vshMain, vshEndmain
|
|
s=s.split(",")
|
|
for k in range(len(s)):
|
|
s[k]=s[k].replace(" ", "")
|
|
vshMain, vshEndmain = s[0], s[1]
|
|
|
|
def parseGsh(dvlp, dvle, s):
|
|
global gshMain, gshEndmain
|
|
s=s.split(",")
|
|
for k in range(len(s)):
|
|
s[k]=s[k].replace(" ", "")
|
|
gshMain, gshEndmain = s[0], s[1]
|
|
|
|
dirList={}
|
|
|
|
dirList["const"]=(parseConst)
|
|
dirList["out"]=(parseOut)
|
|
dirList["opdesc"]=(parseOpdesc)
|
|
dirList["uniform"]=(parseUniform)
|
|
dirList["vsh"]=(parseVsh)
|
|
dirList["gsh"]=(parseGsh)
|
|
|
|
def parseInstruction(dvle, s):
|
|
s=s.lower()
|
|
p=re.compile("^\s*([^\s]*)(.*)")
|
|
r=p.match(s)
|
|
if r:
|
|
name=r.group(1)
|
|
if name in instList:
|
|
fmt=instList[name]["format"]
|
|
out=fmtList[fmt][0](dvle, r.group(2))
|
|
out["opcode"]=instList[name]["opcode"]
|
|
v=fmtList[fmt][1](out)
|
|
return v
|
|
else:
|
|
print(name+" : no such instruction")
|
|
return None
|
|
|
|
def parseLabel(s):
|
|
s=s.lower()
|
|
p=re.compile("^\s*([a-z_0-9]*):")
|
|
r=p.match(s)
|
|
if r:
|
|
return r.group(1)
|
|
return None
|
|
|
|
def parseLine(dvlp, dvle, l, mode):
|
|
l=l.split(";")[0] #remove comments
|
|
|
|
k=0
|
|
while (k<len(l) and (l[k]==" " or l[k]==" ")):
|
|
k+=1
|
|
l=l[k:]
|
|
|
|
if len(l)>1:
|
|
if l[0]==".": #directive
|
|
if not(mode):
|
|
p=re.compile("^\s*\.([^\s]*)(.*)")
|
|
r=p.match(l)
|
|
if r:
|
|
name=r.group(1)
|
|
if name in dirList:
|
|
dirList[name](dvlp, dvle, r.group(2))
|
|
else:
|
|
print(name+" : no such directive")
|
|
else:
|
|
v=parseLabel(l)
|
|
if v: #label
|
|
if not(mode):
|
|
dvle.addLabel((dvlp.getCodelength(), v))
|
|
else: #instruction
|
|
v=parseInstruction(dvle, l)
|
|
if v:
|
|
dvlp.addInstruction(v)
|
|
|
|
if len(sys.argv)<3:
|
|
print("AEMSTRO AS :")
|
|
print(" aemstro_as.py <input.vsh> <output.shbin>")
|
|
else:
|
|
dvlb=DVLB()
|
|
vsh_dvle=DVLE(0x0)
|
|
|
|
with open(sys.argv[1], "r") as f:
|
|
for line in f:
|
|
parseLine(dvlb.getDVLP(), vsh_dvle, line, False)
|
|
dvlb.getDVLP().clearCode()
|
|
with open(sys.argv[1], "r") as f:
|
|
for line in f:
|
|
parseLine(dvlb.getDVLP(), vsh_dvle, line, True)
|
|
|
|
vsh_dvle.setMain(vsh_dvle.getLabelAddress(vshMain))
|
|
vsh_dvle.setEndmain(vsh_dvle.getLabelAddress(vshEndmain))
|
|
dvlb.addDVLE(vsh_dvle)
|
|
|
|
if gshMain!=None and gshEndmain!=None:
|
|
gsh_dvle=copy.deepcopy(vsh_dvle)
|
|
gsh_dvle._type=0x1
|
|
gsh_dvle.setMain(gsh_dvle.getLabelAddress(gshMain))
|
|
gsh_dvle.setEndmain(gsh_dvle.getLabelAddress(gshEndmain))
|
|
dvlb.addDVLE(gsh_dvle)
|
|
|
|
open(sys.argv[2],"wb").write(dvlb.toBinary())
|