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]])