mirror of
https://github.com/ctruLua/ctruLua.git
synced 2025-10-27 16:39:29 +00:00
Added missing dependicies
This commit is contained in:
parent
03baa21c10
commit
ebcd9f00ed
47 changed files with 18405 additions and 0 deletions
27
libs/aemstro/README.md
Normal file
27
libs/aemstro/README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
aemstro
|
||||
=======
|
||||
|
||||
''THE ORIGINAL'' pica200 shader (dis)assembly toolkit !
|
||||
|
||||
set of tools used to disassemble and assemble shader code for DMP's MAESTRO shader extension used in the 3DS's PICA200 GPU
|
||||
see http://3dbrew.org/wiki/Shader_Instruction_Set for more information
|
||||
|
||||
it is meant for rapid iteration and experimentation as I reverse engineer the instruction set. as such, the code is dirty and ugly and poorly organized. functionality is also lacking and overall it is not recommended that you use this for your own homebrew projects unless they involve reverse engineering. for more user friendly implementations, see neobrain's nihstro and fincs's picasso.
|
||||
|
||||
requires python 3. sorry !
|
||||
|
||||
please note that the current iteration of aemstro is very experimental as we are still in the process of reverse engineering the instruction set. the current version is a prototype meant to be iterated upon quickly; not a well thought out piece of clean software. so basically don't fret if you think the code looks like shit and could be written in a much more efficient manner; you're not alone.
|
||||
|
||||
aemstro.py :
|
||||
|
||||
- disassembles shbin/bcsdr files
|
||||
- usage : aemstro.py <input.shbin/input.bcsdr>
|
||||
- outputs to stdout
|
||||
|
||||
aemstro_as.py :
|
||||
|
||||
- assembles vertex shaders
|
||||
- usage : aemstro_as.py <input.vsh> <output.shbin>
|
||||
- see test.vsh for sample code
|
||||
- can *not* assemble output from aemstro.py
|
||||
- is currently much less up to date than aemstro.py (mostly the instruction format thing is all wrong)
|
||||
749
libs/aemstro/aemstro.py
Executable file
749
libs/aemstro/aemstro.py
Executable file
|
|
@ -0,0 +1,749 @@
|
|||
import struct
|
||||
import os
|
||||
import sys
|
||||
|
||||
input={}
|
||||
# '''0x0 : "vertex.position",
|
||||
# 0x1 : "vertex.texcoord",
|
||||
# 0x4 : "vertex.color?"}'''
|
||||
|
||||
output={}
|
||||
# {0x0 : "glPosition",
|
||||
# 0x2 : "glTexcoord",
|
||||
# 0x4 : "glTexcoord",
|
||||
# 0x6 : "glColor?",
|
||||
# 0x8 : "glTexcoord?"}
|
||||
|
||||
lineIndentLevel={}
|
||||
|
||||
def indentLine(k):
|
||||
if not(k in lineIndentLevel):
|
||||
lineIndentLevel[k]=0
|
||||
lineIndentLevel[k]+=1
|
||||
|
||||
def unindentLine(k):
|
||||
if not(k in lineIndentLevel):
|
||||
lineIndentLevel[k]=0
|
||||
lineIndentLevel[k]-=1
|
||||
|
||||
def resetIndentLevel():
|
||||
for k in lineIndentLevel:
|
||||
lineIndentLevel[k]=0
|
||||
|
||||
def getWord(b, k, n=4):
|
||||
return sum(list(map(lambda c: b[k+c]<<(c*8),range(n))))
|
||||
|
||||
def convFloat24(f):
|
||||
#seee eeee mmmm mmmm mmmm mmmm
|
||||
if f==0x0:
|
||||
return 0.0
|
||||
s=f>>23
|
||||
e=(f>>16)&0x7F
|
||||
m=f&0xffff
|
||||
x=pow(2.0,e-63)*(1 + m*pow(2.0,-16))
|
||||
if f&0x800000!=0:
|
||||
return -x
|
||||
return x
|
||||
|
||||
# # doesn't quite work, but could be a more accurate approach ?
|
||||
# def convFloat24(val):
|
||||
# if val==0x0:
|
||||
# return 0.0
|
||||
# tmp=((val>>16)&0xFF)+0x40
|
||||
# out=(tmp<<23)|((val&0x800000)<<31)|((val&0xFFFF)<<7)
|
||||
# try:
|
||||
# return (struct.unpack("f",struct.pack("I",out)))[0]
|
||||
# except:
|
||||
# return (val)
|
||||
|
||||
def parseSymbol(b,o):
|
||||
len=0
|
||||
while getWord(b,o+len,1)!=0x00:
|
||||
len+=1
|
||||
return(b[o:o+len].decode("ascii"))
|
||||
|
||||
def parseExtTable(data):
|
||||
l=len(data)
|
||||
out=[]
|
||||
for i in range(0,l,8):
|
||||
out+=[(getWord(data, i), getWord(data, i+0x4))]
|
||||
return out
|
||||
|
||||
def getRegisterNameSRC(v):
|
||||
if v<0x80:
|
||||
return getRegisterNameSRC1(v)
|
||||
elif v<0x88:
|
||||
return "i"+str(v-0x80)
|
||||
else:
|
||||
return "b"+str(v-0x88)
|
||||
|
||||
def getRegisterNameSRC1(v):
|
||||
if v<0x10:
|
||||
return "v"+str(v&0xF)
|
||||
elif v<0x20:
|
||||
return "r"+str(v-0x10)
|
||||
elif v<0x80:
|
||||
return "c"+str(v-0x20)
|
||||
else:
|
||||
return ("r%02X"%(v))
|
||||
|
||||
def getRegisterNameSRC2(v):
|
||||
return getRegisterNameSRC1(v)
|
||||
|
||||
def getRegisterNameDST(v):
|
||||
if v<0x10:
|
||||
return ("o%X"%(v))
|
||||
elif v<0x20:
|
||||
return "r"+str(v-0x10)
|
||||
else:
|
||||
return ("r%02X"%(v))
|
||||
|
||||
def getRegisterName(v):
|
||||
return ("r%02X"%(v))
|
||||
# if v<16:
|
||||
# return "v"+str(v&0xF)
|
||||
# elif v<120:
|
||||
# return "c"+str(v-16)
|
||||
# else:
|
||||
# return "b"+str(v-0x88)
|
||||
|
||||
|
||||
def getInputSymbol(v, vt, ut, idx):
|
||||
src=getRegisterNameSRC(v)
|
||||
return getInputSymbolFromString(src, vt, ut, idx)
|
||||
|
||||
def getInputSymbolFromString(src, vt, ut, idx):
|
||||
idxstr=""
|
||||
|
||||
if idx==1:
|
||||
idxstr="[idx1]"
|
||||
elif idx==2:
|
||||
idxstr="[idx2]"
|
||||
elif idx==3:
|
||||
idxstr="[lcnt]"
|
||||
|
||||
if src in vt:
|
||||
return vt[src]+idxstr
|
||||
if src in ut:
|
||||
return ut[src]+idxstr
|
||||
else:
|
||||
f=src.find(".")
|
||||
if f>=0:
|
||||
src=getInputSymbolFromString(src[:f], vt, ut, idx)+src[f:]
|
||||
idxstr=""
|
||||
return src+idxstr
|
||||
|
||||
def getOutputSymbol(v, ot):
|
||||
dst=getRegisterNameDST(v)
|
||||
return ot[dst] if dst in ot else dst
|
||||
|
||||
def getLabelSymbol(v, t):
|
||||
return t[v][1] if v in t else hex(v)
|
||||
|
||||
def initIndent():
|
||||
global numIdent
|
||||
numIdent=0
|
||||
|
||||
def indentOut():
|
||||
global numIdent
|
||||
numIdent=numIdent+1
|
||||
|
||||
def unindentOut():
|
||||
global numIdent
|
||||
numIdent=numIdent-1
|
||||
|
||||
def iprint(s, e=False):
|
||||
global numIdent
|
||||
if e:
|
||||
print(" "*numIdent+s,end='')
|
||||
else:
|
||||
print(" "*numIdent+s)
|
||||
|
||||
comp=["x", "y", "z", "w"]
|
||||
def parseComponentMask(v):
|
||||
out=""
|
||||
for i in range(4):
|
||||
if v&(1<<(3-i))!=0x0:
|
||||
out+=comp[i]
|
||||
else:
|
||||
out+="_"
|
||||
return out
|
||||
|
||||
def parseExt(v):
|
||||
return {"src1" : (v>>5)&0xFF,
|
||||
"src2" : (v>>14)&0xFF,
|
||||
"src3" : (v>>23)&0xFF,
|
||||
"nsrc1" : (v>>4)&0x1, #negation bit
|
||||
"nsrc2" : (v>>13)&0x1, #negation bit
|
||||
"nsrc3" : (v>>22)&0x1, #negation bit
|
||||
"dst" : (v)&0x1F,
|
||||
"dstcomp" : parseComponentMask(v&0xF),
|
||||
"rest" : (v>>22)}
|
||||
|
||||
def parseComponentSwizzle(v):
|
||||
out=""
|
||||
for i in range(4):
|
||||
out+=comp[(v>>((3-i)*2))&0x3]
|
||||
return out
|
||||
|
||||
def parseInstFormat10(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>7)&0x1F,
|
||||
"src1" : (v>>12)&0x7F,
|
||||
"idx_1" : (v>>19)&0x3,
|
||||
"idx_2" : 0x0,
|
||||
"cmpY" : (v>>21)&0x7,
|
||||
"cmpX" : (v>>24)&0x7,
|
||||
"extid" : (v)&0x7F}
|
||||
|
||||
def parseInstFormat1(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>7)&0x1F,
|
||||
"src1" : (v>>12)&0x7F,
|
||||
"idx_1" : (v>>19)&0x3,
|
||||
"idx_2" : 0x0,
|
||||
"dst" : (v>>21)&0x1F,
|
||||
"extid" : (v)&0x7F}
|
||||
|
||||
def parseInstFormat8(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>7)&0x7F,
|
||||
"src1" : (v>>14)&0x1F,
|
||||
"idx_1" : 0x0,
|
||||
"idx_2" : (v>>19)&0x3,
|
||||
"dst" : (v>>21)&0x1F,
|
||||
"extid" : (v)&0x7F}
|
||||
|
||||
def parseInstFormat9(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"dst" : (v>>24)&0x1F,
|
||||
"src1" : (v>>17)&0x7F,
|
||||
"src2" : (v>>10)&0x7F,
|
||||
"src3" : (v>>5)&0x1F,
|
||||
"idx_1" : 0x0,
|
||||
"idx_2" : 0x0,
|
||||
"extid" : (v)&0x1F}
|
||||
|
||||
def parseInstFormat12(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"dst" : (v>>24)&0x1F,
|
||||
"src1" : (v>>17)&0x7F,
|
||||
"src2" : (v>>12)&0x1F,
|
||||
"src3" : (v>>5)&0x7F,
|
||||
"idx_1" : 0x0,
|
||||
"idx_2" : 0x0,
|
||||
"extid" : (v)&0x1F}
|
||||
|
||||
def parseInstFormat2(k, v, lt={}):
|
||||
ret={"opcode" : v>>26,
|
||||
"addr" : (v>>8)&0x3FFC,
|
||||
"flags" : (v>>22)&0xF,
|
||||
"ret" : (v)&0x3FF}
|
||||
if ret["opcode"]==0x28: #IF?
|
||||
for i in range(k+4,ret["addr"],4):
|
||||
indentLine(i)
|
||||
for i in range(ret["addr"],ret["addr"]+ret["ret"]*4,4):
|
||||
indentLine(i)
|
||||
if ret["ret"]>0:
|
||||
lt[ret["addr"]]=(-1,"ELSE_%X"%(k))
|
||||
return ret
|
||||
|
||||
#?
|
||||
def parseInstFormat3(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src2" : (v>>0)&0x1F,
|
||||
"src1" : (v>>7)&0x7F,
|
||||
"dst" : (v>>14)&0x1F}
|
||||
|
||||
#?
|
||||
def parseInstFormat6(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"vtxid" : (v>>24)&0x3,
|
||||
"primid" : (v>>22)&0x3}
|
||||
# MOV?
|
||||
def parseInstFormat4(k, v, lt={}):
|
||||
return {"opcode" : v>>26,
|
||||
"src1" : (v>>7)&0x7F,
|
||||
"dst" : (v>>14)&0x1F,
|
||||
"extid" : (v)&0x3F}
|
||||
# CONDJUMP
|
||||
def parseInstFormat5(k, v, lt={}):
|
||||
ret={"opcode" : v>>26,
|
||||
"addr" : (v>>8)&0x3FFC,
|
||||
"bool" : (v>>22)&0xF,
|
||||
"ret" : (v)&0x3FF}
|
||||
if ret["opcode"]==0x27: #IFU
|
||||
for i in range(k+4,ret["addr"],4):
|
||||
indentLine(i)
|
||||
for i in range(ret["addr"],ret["addr"]+ret["ret"]*4,4):
|
||||
indentLine(i)
|
||||
if ret["ret"]>0:
|
||||
lt[ret["addr"]]=(-1,"ELSE_%X"%(k))
|
||||
elif ret["opcode"]==0x29: #LOOP
|
||||
for i in range(k+4,ret["addr"]+4,4):
|
||||
indentLine(i)
|
||||
return ret
|
||||
|
||||
def outputStringList(k, strl, fmtl):
|
||||
l=len(strl)
|
||||
if k in lineIndentLevel and lineIndentLevel[k]>0:
|
||||
out=" "*lineIndentLevel[k]
|
||||
else:
|
||||
out=""
|
||||
if l==len(fmtl):
|
||||
for i in range(l):
|
||||
str=strl[i]
|
||||
fmt=fmtl[i]
|
||||
if fmt:
|
||||
v=len(str)
|
||||
if v<fmt:
|
||||
str+=" "*(fmt-v)
|
||||
out+=str
|
||||
iprint(out)
|
||||
|
||||
|
||||
def printInstFormat1(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
getOutputSymbol(inst["dst"], ot)+"."+extd["dstcomp"],
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" , ",
|
||||
nsrc2+getInputSymbol(inst["src2"], vt, ut, inst["idx_2"])+"."+(parseComponentSwizzle(extd["src2"])),
|
||||
" ("+hex(inst["extid"])+" "+hex(extd["rest"])+")"],
|
||||
[8, 32, None, 32, None, 32, None])
|
||||
|
||||
cmpOp={0x0 : "EQ", 0x1 : "NE", 0x2 : "LT", 0x3 : "LE", 0x4 : "GT", 0x5 : "GE", 0x6 : "??", 0x7 : "??"}
|
||||
|
||||
def printInstFormat10(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
"("+cmpOp[inst["cmpX"]]+", "+cmpOp[inst["cmpY"]]+")",
|
||||
nsrc2+getInputSymbol(inst["src2"], vt, ut, inst["idx_2"])+"."+(parseComponentSwizzle(extd["src2"])),
|
||||
" ("+hex(inst["extid"])+")"],
|
||||
[8, 32, 12, 32, None])
|
||||
|
||||
def printInstFormat9(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
nsrc3="-" if extd["nsrc3"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
getOutputSymbol(inst["dst"], ot)+"."+extd["dstcomp"],
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" , ",
|
||||
nsrc2+getInputSymbol(inst["src2"], vt, ut, inst["idx_2"])+"."+(parseComponentSwizzle(extd["src2"])),
|
||||
" , ",
|
||||
nsrc3+getInputSymbol(inst["src3"], vt, ut, 0)+"."+(parseComponentSwizzle(extd["src3"])),
|
||||
" ("+hex(extd["rest"])+")"],
|
||||
[8, 32, None, 16, None, 16, None, 16, None])
|
||||
|
||||
def printInstFormat4(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
getOutputSymbol(inst["dst"], ot)+"."+extd["dstcomp"],
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" ", "",
|
||||
" ("+hex(inst["extid"])+")"],
|
||||
[8, 32, None, 32, None, 32, None])
|
||||
|
||||
def printInstFormat7(k, n, inst, e, lt, vt, ut, ot):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
nsrc1="-" if extd["nsrc1"]==1 else ""
|
||||
nsrc2="-" if extd["nsrc2"]==1 else ""
|
||||
outputStringList(k, [n,
|
||||
"idx.xy__",
|
||||
" <- ",
|
||||
nsrc1+getInputSymbol(inst["src1"], vt, ut, inst["idx_1"])+"."+(parseComponentSwizzle(extd["src1"])),
|
||||
" ", "",
|
||||
" ("+hex(inst["extid"])+")"],
|
||||
[8, 32, None, 32, None, 32, None])
|
||||
|
||||
def printInstFormat6(k, n, inst, e, lt, vt, ut, ot):
|
||||
outputStringList(k, [n,
|
||||
"vtx%02X," % inst["vtxid"],
|
||||
"PRIM_EMIT" if inst["primid"]&2==2 else "",
|
||||
"UNK_FLAG" if inst["primid"]&1==1 else ""],
|
||||
[8, 8, 12, 16])
|
||||
|
||||
def printInstFormat2(k, n, inst, e, lt, vt, ut, ot):
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" ("+str(inst["ret"])+ " words, flags: "+bin(inst['flags'])+")"],
|
||||
[8, 32, 32])
|
||||
|
||||
# CONDJUMP (uniform)
|
||||
def printInstFormat5(k, n, inst, e, lt, vt, ut, ot):
|
||||
if inst["opcode"]==0x29: #LOOP
|
||||
reg=getRegisterNameSRC((inst['bool']&0xF)+0x80)
|
||||
start=getInputSymbolFromString(reg+".y", vt, ut, 0)
|
||||
end=start+"+"+getInputSymbolFromString(reg+".x", vt, ut, 0)
|
||||
stride=getInputSymbolFromString(reg+".z", vt, ut, 0)
|
||||
outputStringList(k, [n,
|
||||
"(lcnt = "+start+"; lcnt <= "+end+"; lcnt += "+stride+")",
|
||||
" (adr "+getLabelSymbol(inst["addr"], lt)+", "+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, 16])
|
||||
elif inst["opcode"]==0x27: #IFU
|
||||
outputStringList(k, [n,
|
||||
"("+getInputSymbol((inst['bool']&0xF)+0x88, vt, ut, 0)+")",
|
||||
" ("+getLabelSymbol(inst["addr"], lt)+", "+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, 16])
|
||||
elif inst["opcode"]==0x2d: #JMPU
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" , ",
|
||||
("!" if inst["ret"]==1 else "")+getInputSymbol((inst['bool']&0xF)+0x88, vt, ut, 0),
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
else:
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" , ",
|
||||
getInputSymbol((inst['bool']&0xF)+(0x80 if inst["opcode"]==0x29 else 0x88), vt, ut, 0),
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['bool']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
|
||||
# CONDJUMP (dynamic)
|
||||
def printInstFormat11(k, n, inst, e, lt, vt, ut, ot):
|
||||
cond=""
|
||||
if inst["flags"]&0x3==0x0: #OR
|
||||
cond=("!" if inst["flags"]&0x8 == 0 else "")+"cmp.x"+" || "+("!" if inst["flags"]&0x4 == 0 else "")+"cmp.y"
|
||||
elif inst["flags"]&0x3==0x1: #AND
|
||||
cond=("!" if inst["flags"]&0x8 == 0 else "")+"cmp.x"+" && "+("!" if inst["flags"]&0x4 == 0 else "")+"cmp.y"
|
||||
elif inst["flags"]&0x3==0x2: #X
|
||||
cond=("!" if inst["flags"]&0x8 == 0 else "")+"cmp.x"
|
||||
elif inst["flags"]&0x3==0x3: #Y
|
||||
cond=("!" if inst["flags"]&0x4 == 0 else "")+"cmp.y"
|
||||
|
||||
if inst["opcode"]==0x23: #BREAK
|
||||
outputStringList(k, [n,
|
||||
"("+cond+")",
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['flags']&0xF)+")"],
|
||||
[8, 16, None, 16, None])
|
||||
elif inst["opcode"]==0x28: #IF
|
||||
outputStringList(k, [n,
|
||||
"("+cond+")",
|
||||
" , ",
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['flags']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
else:
|
||||
outputStringList(k, [n,
|
||||
getLabelSymbol(inst["addr"], lt),
|
||||
" , ",
|
||||
"("+cond+")",
|
||||
" ", "",
|
||||
" ("+str(inst["ret"])+ " words, "+str(inst['flags']&0xF)+")"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
|
||||
instList={}
|
||||
fmtList=[(parseInstFormat1, printInstFormat1), (parseInstFormat2, printInstFormat2), (parseInstFormat2, printInstFormat2), (parseInstFormat1, printInstFormat4), (parseInstFormat5, printInstFormat5), (parseInstFormat6, printInstFormat6), (parseInstFormat1, printInstFormat7), (parseInstFormat8, printInstFormat1), (parseInstFormat9, printInstFormat9), (parseInstFormat10, printInstFormat10), (parseInstFormat2, printInstFormat11), (parseInstFormat12, printInstFormat9)]
|
||||
|
||||
instList[0x00]={"name" : "ADD", "format" : 0} #really SUB ?
|
||||
instList[0x01]={"name" : "DP3", "format" : 0}
|
||||
instList[0x02]={"name" : "DP4", "format" : 0}
|
||||
instList[0x03]={"name" : "DPH", "format" : 0} #tested, definitely
|
||||
instList[0x05]={"name" : "EX2", "format" : 3} #tested, definitely
|
||||
instList[0x06]={"name" : "LG2", "format" : 3} #tested, definitely
|
||||
instList[0x08]={"name" : "MUL", "format" : 0}
|
||||
instList[0x09]={"name" : "SGE", "format" : 0}
|
||||
instList[0x0A]={"name" : "SLT", "format" : 0}
|
||||
instList[0x0B]={"name" : "FLR", "format" : 3} #tested, definitely FLR and not FRC
|
||||
instList[0x0C]={"name" : "MAX", "format" : 0} #definitely
|
||||
instList[0x0D]={"name" : "MIN", "format" : 0} #definitely
|
||||
instList[0x0E]={"name" : "RCP", "format" : 3} #1/op1
|
||||
instList[0x0F]={"name" : "RSQ", "format" : 3} #1/sqrt(op1)
|
||||
instList[0x12]={"name" : "SETIDX", "format" : 6}
|
||||
instList[0x13]={"name" : "MOV", "format" : 3}
|
||||
instList[0x18]={"name" : "DPHI", "format" : 7}
|
||||
instList[0x1A]={"name" : "SGEI", "format" : 7}
|
||||
instList[0x1B]={"name" : "SLTI", "format" : 7}
|
||||
instList[0x23]={"name" : "BREAKC", "format" : 10} #conditional break
|
||||
instList[0x24]={"name" : "CALL", "format" : 1} #unconditional call
|
||||
instList[0x25]={"name" : "CALLC", "format" : 10} #conditional call
|
||||
instList[0x26]={"name" : "CALLU", "format" : 4} #conditional call (uniform bool)
|
||||
instList[0x27]={"name" : "IFU", "format" : 4} #if/else statement (uniform bool)
|
||||
instList[0x28]={"name" : "IFC", "format" : 10}
|
||||
instList[0x29]={"name" : "LOOP", "format" : 4}
|
||||
instList[0x2b]={"name" : "SETEMIT", "format" : 5}
|
||||
instList[0x2c]={"name" : "JMPC", "format" : 10} #conditional jump
|
||||
instList[0x2d]={"name" : "JMPU", "format" : 4} #conditional jump (uniform bool)
|
||||
for i in range(0x2):
|
||||
instList[0x2e+i]={"name" : "CMP", "format" : 9}
|
||||
for i in range(0x8):
|
||||
instList[0x30+i]={"name" : "MADI", "format" : 11}
|
||||
for i in range(0x8):
|
||||
instList[0x38+i]={"name" : "MAD", "format" : 8}
|
||||
|
||||
def parseCode(data, e, lt, vt, ut, ot):
|
||||
l=len(data)
|
||||
for k in range(0,l,4):
|
||||
v=getWord(data,k)
|
||||
opcode=v>>26
|
||||
|
||||
if k in lt:
|
||||
iprint("%08x [--------] "%(k), True)
|
||||
unindentLine(k)
|
||||
outputStringList(k, [lt[k][1]+":"], [8])
|
||||
indentLine(k)
|
||||
|
||||
iprint("%08x [%08x] "%(k,v), True)
|
||||
|
||||
if opcode in instList:
|
||||
fmt=instList[opcode]["format"]
|
||||
inst=fmtList[fmt][0](k, v, lt)
|
||||
fmtList[fmt][1](k, instList[opcode]["name"], inst, e, lt, vt, ut, ot)
|
||||
elif opcode==0x21:
|
||||
# outputStringList(k,["END"],[8])
|
||||
outputStringList(k,["NOP"],[8])
|
||||
elif opcode==0x22:
|
||||
outputStringList(k,["END"],[8])
|
||||
elif opcode==0x2A:
|
||||
inst=parseInstFormat1(k, v)
|
||||
outputStringList(k,["EMITVERTEX"],[10])
|
||||
else:
|
||||
inst=parseInstFormat1(k, v)
|
||||
if inst["extid"] < len(e):
|
||||
ext=e[inst["extid"]][0]
|
||||
extd=parseExt(ext)
|
||||
printInstFormat1(k, "???%02X"%(inst["opcode"]), inst, e, lt, vt, ut, ot)
|
||||
else:
|
||||
inst=parseInstFormat3(k, v)
|
||||
outputStringList(k,["???%02X"%(inst["opcode"]),
|
||||
getOutputSymbol(inst["dst"], ot),
|
||||
" <- ",
|
||||
getInputSymbol(inst["src1"], vt, ut, 0),
|
||||
" , ",
|
||||
getInputSymbol(inst["src2"], vt, ut, 0),
|
||||
"(invalid extension id)"],
|
||||
[8, 16, None, 16, None, 16, None])
|
||||
|
||||
k+=0x4
|
||||
|
||||
def parseDVLP(data, lt, vt, ut, ot, k):
|
||||
l=len(data)
|
||||
extOffset=getWord(data, 0x10)
|
||||
fnOffset=getWord(data, 0x18)
|
||||
# for i in range(fnOffset, l):
|
||||
# if k==0:
|
||||
# break
|
||||
# elif data[i]==0:
|
||||
# k-=1
|
||||
# print(parseSymbol(data,i))
|
||||
extSize=getWord(data, 0x14)*8
|
||||
ext=parseExtTable(data[extOffset:(extOffset+extSize)])
|
||||
codeOffset=getWord(data, 0x8)
|
||||
codeSize=getWord(data, 0xC)*4
|
||||
parseCode(data[codeOffset:(codeOffset+codeSize)], ext, lt, vt, ut, ot)
|
||||
|
||||
def parseLabelTable(data, sym):
|
||||
l=len(data)
|
||||
out={}
|
||||
for i in range(0,l,0x10):
|
||||
id=getWord(data,i,1)
|
||||
loc=getWord(data,i+0x4)*4
|
||||
off=getWord(data,i+0xC)
|
||||
out[loc]=(id,parseSymbol(sym,off))
|
||||
return out
|
||||
|
||||
def transformRegisterValue(v):
|
||||
if v<16:
|
||||
return (v&0xF)
|
||||
return v+16
|
||||
|
||||
def parseVarTable(data, sym):
|
||||
l=len(data)
|
||||
iprint("Uniforms :")
|
||||
indentOut()
|
||||
src={}
|
||||
for i in range(0,l,0x8):
|
||||
off=getWord(data,i)
|
||||
v1=getWord(data,i+4,2)
|
||||
v2=getWord(data,i+6,2)
|
||||
|
||||
base=transformRegisterValue(v1)
|
||||
end=transformRegisterValue(v2)
|
||||
|
||||
# iprint(getRegisterNameSRC(base)+" - "+getRegisterNameSRC(end)+" : "+parseSymbol(sym,off))
|
||||
iprint(getRegisterNameSRC(base)+" - "+getRegisterNameSRC(end)+" : "+parseSymbol(sym,off)+" ("+hex(getWord(data,i))+", "+hex(getWord(data,i+4))+")")
|
||||
if base==end:
|
||||
name=parseSymbol(sym,off)
|
||||
src[getRegisterNameSRC(base)]=name
|
||||
else:
|
||||
for k in range(base, end+1):
|
||||
name=parseSymbol(sym,off)+"["+str(k-base)+"]"
|
||||
src[getRegisterNameSRC(k)]=name
|
||||
|
||||
unindentOut()
|
||||
print("")
|
||||
return src
|
||||
|
||||
def parseConstTable(data, sym):
|
||||
l=len(data)
|
||||
iprint("Constants :")
|
||||
indentOut()
|
||||
out={}
|
||||
for i in range(0,l,0x14):
|
||||
type=getWord(data,i,2)
|
||||
r=getWord(data,i+2,2)
|
||||
name=None
|
||||
if type==0x0:
|
||||
#constant bool
|
||||
vec=False if getWord(data,i+4)==0x0 else True
|
||||
r+=0x88
|
||||
name=str(vec)
|
||||
elif type==0x1:
|
||||
#constant integer vec4
|
||||
vec=[hex(getWord(data,i+k,1)) for k in range(4,8,1)]
|
||||
r+=0x80
|
||||
out[getRegisterNameSRC(r)+".x"]=vec[0]
|
||||
out[getRegisterNameSRC(r)+".y"]=vec[1]
|
||||
out[getRegisterNameSRC(r)+".z"]=vec[2]
|
||||
out[getRegisterNameSRC(r)+".w"]=vec[3]
|
||||
else:
|
||||
#constant float24 vec4 (should be type==0x2 but would rather output potential unknowns too)
|
||||
vec=[convFloat24(getWord(data,i+k)) for k in range(4,0x14,4)]
|
||||
r+=0x20
|
||||
name="["+", ".join(["%4.2f"%(v) for v in vec])+"]"
|
||||
# iprint(getRegisterNameSRC(r)+" = "+str(vec)+" ("+str([hex(getWord(data,i+k)) for k in range(0,0x14,4)])+")")
|
||||
iprint(getRegisterNameSRC(r)+" = "+str(vec))
|
||||
if name!=None:
|
||||
out[getRegisterNameSRC(r)]=name
|
||||
|
||||
unindentOut()
|
||||
print("")
|
||||
return out
|
||||
|
||||
outputTypes={0x0 : "result.position",
|
||||
0x1 : "result.normalquat", #maybe
|
||||
0x2 : "result.color",
|
||||
0x3 : "result.texcoord0",
|
||||
0x4 : "result.texcoord0w",
|
||||
0x5 : "result.texcoord1",
|
||||
0x6 : "result.texcoord2",
|
||||
# 0x7 : "?", #sets outreg info to 0x1f1f1f1f...
|
||||
0x8 : "result.view", #"result.view" seems to be pre-projmatrix vertex coordinates
|
||||
}
|
||||
|
||||
def parseOutputTable(data, sym):
|
||||
l=len(data)
|
||||
iprint("Output :")
|
||||
indentOut()
|
||||
out={}
|
||||
for i in range(0,l,0x8):
|
||||
off=getWord(data,i+4)
|
||||
v1=getWord(data,i,2)
|
||||
v2=getWord(data,i+2,2)
|
||||
|
||||
dst=getRegisterNameDST(v2)
|
||||
|
||||
if v1 in outputTypes:
|
||||
out[dst]=outputTypes[v1]
|
||||
|
||||
iprint("o"+str(v2)+" = "+(outputTypes[v1] if v1 in outputTypes else hex(v1))+" ("+hex(off)+", "+hex(v1)+", "+hex(v2)+")")
|
||||
|
||||
unindentOut()
|
||||
print("")
|
||||
return out
|
||||
|
||||
def parseDVLE(data,dvlp, k):
|
||||
l=len(data)
|
||||
|
||||
iprint("DVLE "+str(k))
|
||||
|
||||
shaderType=getWord(data, 0x6, 1)
|
||||
mainStart=getWord(data, 0x8)*4
|
||||
mainEnd=getWord(data, 0xC)*4
|
||||
|
||||
resetIndentLevel()
|
||||
|
||||
iprint("unkval "+hex(getWord(data, 0x4, 2)))
|
||||
iprint("vertex shader" if shaderType==0x0 else "geometry shader")
|
||||
iprint("main : "+hex(mainStart)+"-"+hex(mainEnd))
|
||||
print("")
|
||||
|
||||
# # temporarily filter out geometry shaders
|
||||
# if shaderType!=0x0:
|
||||
# return
|
||||
|
||||
# # temporarily filter out vertex shaders
|
||||
# if shaderType==0x0:
|
||||
# return
|
||||
|
||||
codeStartOffset=getWord(data, 0x8)
|
||||
codeEndOffset=getWord(data, 0xC)
|
||||
|
||||
unifOffset=getWord(data, 0x18)
|
||||
unifSize=getWord(data, 0x1C)*0x14
|
||||
|
||||
labelOffset=getWord(data, 0x20)
|
||||
labelSize=getWord(data, 0x24)*0x10
|
||||
|
||||
outputOffset=getWord(data, 0x28)
|
||||
outputSize=getWord(data, 0x2C)*0x8
|
||||
|
||||
varOffset=getWord(data, 0x30)
|
||||
varSize=getWord(data, 0x34)*0x8
|
||||
|
||||
symbolOffset=getWord(data, 0x38)
|
||||
symbolSize=getWord(data, 0x3C)
|
||||
|
||||
sym=data[symbolOffset:(symbolOffset+symbolSize)]
|
||||
labelTable=parseLabelTable(data[labelOffset:(labelOffset+labelSize)],sym)
|
||||
varTable=parseVarTable(data[varOffset:(varOffset+varSize)],sym)
|
||||
unifTable=parseConstTable(data[unifOffset:(unifOffset+unifSize)],sym)
|
||||
outputTable=parseOutputTable(data[outputOffset:(outputOffset+outputSize)],sym)
|
||||
|
||||
parseDVLP(dvlp, labelTable, varTable, unifTable, outputTable, k)
|
||||
print("")
|
||||
|
||||
return (labelTable,varTable,unifTable,range(codeStartOffset,codeEndOffset))
|
||||
|
||||
def parseDVLB(data):
|
||||
l=len(data)
|
||||
n=getWord(data, 0x4)
|
||||
dvleTable={}
|
||||
labelTable={}
|
||||
varTable={}
|
||||
unifTable={}
|
||||
dvlp=data[(0x8+0x4*n):l]
|
||||
for i in range(n):
|
||||
offset=getWord(data, 0x8+0x4*i)
|
||||
r=parseDVLE(data[offset:l],dvlp,i)
|
||||
# for k in r[3]:
|
||||
# dvleTable[k*4]=i
|
||||
# labelTable.update(r[0])
|
||||
# varTable[i]=r[1]
|
||||
# unifTable[i]=r[2]
|
||||
# parseDVLP(dvlp,labelTable,varTable,unifTable,dvleTable)
|
||||
|
||||
if len(sys.argv)<2:
|
||||
print("AEMSTRO :")
|
||||
print(" aemstro.py <input.shbin/input.bcsdr>")
|
||||
else:
|
||||
initIndent()
|
||||
src1fn=sys.argv[1]
|
||||
data=bytearray(open(src1fn, "rb").read())
|
||||
l=len(data)
|
||||
|
||||
for i in range(0,l-4,4):
|
||||
if getWord(data, i)==0x424C5644:
|
||||
parseDVLB(data[i:l])
|
||||
682
libs/aemstro/aemstro_as.py
Normal file
682
libs/aemstro/aemstro_as.py
Normal file
|
|
@ -0,0 +1,682 @@
|
|||
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())
|
||||
43
libs/aemstro/test.vsh
Normal file
43
libs/aemstro/test.vsh
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
; setup constants
|
||||
.const 5, 0.0, 1.0, 2.0, 3.0
|
||||
|
||||
; setup outmap
|
||||
.out o0, result.position
|
||||
.out o1, result.color
|
||||
.out o2, result.texcoord0
|
||||
.out o3, result.texcoord1
|
||||
.out o4, result.texcoord2
|
||||
|
||||
; setup uniform map (not required)
|
||||
.uniform 0x10, 0x13, mdlvMtx
|
||||
.uniform 0x14, 0x17, projMtx
|
||||
|
||||
;code
|
||||
main:
|
||||
; result.pos = mdlvMtx * in.pos
|
||||
dp4 d40, d40, d00 (0x0)
|
||||
dp4 d40, d41, d00 (0x1)
|
||||
dp4 d40, d42, d00 (0x2)
|
||||
mov d40, d25 (0x4)
|
||||
; result.pos = projMtx * in.pos
|
||||
dp4 d00, d44, d40 (0x0)
|
||||
dp4 d00, d45, d40 (0x1)
|
||||
dp4 d00, d46, d40 (0x2)
|
||||
dp4 d00, d47, d40 (0x3)
|
||||
; result.color = in.pos
|
||||
mov d04, d25 (0x5)
|
||||
; result.texcoord = const
|
||||
mov d08, d25 (0x5)
|
||||
mov d0C, d25 (0x5)
|
||||
mov d10, d25 (0x5)
|
||||
flush
|
||||
end
|
||||
endmain:
|
||||
|
||||
;operand descriptors
|
||||
.opdesc x___, xyzw, xyzw ; 0x0
|
||||
.opdesc _y__, xyzw, xyzw ; 0x1
|
||||
.opdesc __z_, xyzw, xyzw ; 0x2
|
||||
.opdesc ___w, xyzw, xyzw ; 0x3
|
||||
.opdesc ___w, yyyy, xyzw ; 0x4
|
||||
.opdesc xyzw, xyzw, xyzw ; 0x5
|
||||
Loading…
Add table
Add a link
Reference in a new issue