47 lines
1.9 KiB
Python
47 lines
1.9 KiB
Python
import sys,os,math,collections,struct,glob,itertools
|
|||
|
|
sys.path.insert(0,os.path.dirname(os.path.abspath(__file__)))
|
||
|
|
import prt,psb
|
||
|
|
class TF(float):
|
||
|
|
pass
|
||
|
|
orig=psb.P.rdbl
|
||
|
|
def rdbl(s):
|
||
|
|
p0=s.p; t=s.b[p0]
|
||
|
|
v=orig(s)
|
||
|
|
if 0x49<=t<=0xdf and not isinstance(v,psb.Unk):
|
||
|
|
o=TF(v); o.tag=t; o.pl=bytes(s.b[p0+1:p0+7]); return o
|
||
|
|
return v
|
||
|
|
psb.P.rdbl=rdbl
|
||
|
|
OFFS=[0]+list(range(0x44,0x4d))
|
||
|
|
def mag(tf,off):
|
||
|
|
return struct.unpack('>d',(0x3f75+tf.tag-off).to_bytes(2,'big')+tf.pl)[0]
|
||
|
|
votes=collections.defaultdict(collections.Counter)
|
||
|
|
def walk(v,name=''):
|
||
|
|
if isinstance(v,psb.Node):
|
||
|
|
for n,x in v: walk(x,n)
|
||
|
|
elif isinstance(v,psb.Arr):
|
||
|
|
for x in v: walk(x,name)
|
||
|
|
elif isinstance(v,list) and v and isinstance(v[0],list) and len(v) in (3,4) and len(v[0])==3 and name in ('local_sys','orient','matrix','transf_to_local'):
|
||
|
|
rows=v[:3]
|
||
|
|
if any(isinstance(c,psb.Unk) for r in rows for c in r): return
|
||
|
|
vecs=rows+[[rows[i][j] for i in range(3)] for j in range(3)]
|
||
|
|
for r in vecs:
|
||
|
|
tf=[c for c in r if isinstance(c,TF)]
|
||
|
|
if not tf or len(tf)>2: continue
|
||
|
|
rest=sum(c*c for c in r if not isinstance(c,TF))
|
||
|
|
sols=[]
|
||
|
|
for offs in itertools.product(OFFS,repeat=len(tf)):
|
||
|
|
n=rest+sum(mag(c,o)**2 for c,o in zip(tf,offs))
|
||
|
|
if abs(n-1)<1e-9: sols.append(offs)
|
||
|
|
if len(sols)==1:
|
||
|
|
for c,o in zip(tf,sols[0]): votes[c.tag][o]+=1
|
||
|
|
for f in sys.argv[1:]:
|
||
|
|
for g in glob.glob(f):
|
||
|
|
try: d,secs,order=prt.load(g)
|
||
|
|
except Exception: continue
|
||
|
|
for nme in order:
|
||
|
|
o,l,fl=secs[nme]
|
||
|
|
if fl[2]!='9' or l<200: continue
|
||
|
|
p,root,e=psb.parse(d[o:o+l])
|
||
|
|
if root: walk(root[1])
|
||
|
|
for t in sorted(votes):
|
||
|
|
print(hex(t), {hex(o):n for o,n in votes[t].items()}, ' -> prefix', [hex((0x3f75+t-o) | (0x8000 if o else 0)) for o in votes[t]])
|