Documenta il formato PSB dei file Creo e aggiungi il parser di riferimento
Reverse engineering di 9253000117a.prt.35: contenitore (offset dall'ultimo campo dell'intestazione, indice a catena), grammatica completa delle sezioni (id progressivi dei campi, tabella "dopo X viene Y", marcatori di chiusura), tabella dei double verificata sulla norma delle matrici, sezioni compresse e catalogo del contenuto. Parser Python in scripts/psb/. docs/history.md raccoglie stato, metodo e punti aperti per riprendere il lavoro. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
1eac3ccaa7
commit
2d7ace07e2
15 files changed
+1309
No files matched your search
@@ -0,0 +1,47 @@
|
||||
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]])
|
||||
Reference in new issue
Block a user