import struct def load(fn): return open(fn,"rb").read() def walk(d, p, end, depth, out): while p+3<=end: tw=struct.unpack_from("end:return ln=d[p] if lw==1 else (struct.unpack_from("end:return out.append((depth,cid,p,ln,d[p:p+ln])) # container ids if cid in (0x03,0x40,0x41,0x42,0x46,0x20,0x30,0x10,0x70,0x48,0x21): walk(d,p,p+ln,depth+1,out) p+=ln if cid==0x0005:break print("="*70) print("BLXSKIN.BMF materials — DIFFUSE/AMBIENT float decode") print("="*70) d=load("content/VIDEO/MAT/BLXSKIN.BMF") out=[]; walk(d,8,len(d),0,out) name=None for depth,cid,p,ln,body in out: if cid==0x2008: name=body.split(b'\x00')[0].decode(errors='replace') print(f"\nMATERIAL name: {name!r}") elif cid==0x23 and ln>=12: f=struct.unpack_from("<3f",body,0) print(f" AMBIENT = ({f[0]:.5f},{f[1]:.5f},{f[2]:.5f}) raw={body.hex()}") elif cid==0x24 and ln>=12: f=struct.unpack_from("<3f",body,0) print(f" DIFFUSE = ({f[0]:.5f},{f[1]:.5f},{f[2]:.5f}) raw={body.hex()}") elif cid==0x28: print(f" RAMP_REF = {body.split(chr(0).encode())[0].decode(errors='replace')!r}") elif cid==0x26 and ln>=12: f=struct.unpack_from("<3f",body,0) print(f" EMISSIVE = ({f[0]:.5f},{f[1]:.5f},{f[2]:.5f})") elif cid==0x21: print(f" MAT_TEXTURE chunk present len={ln}") elif cid==0x11: print(f" TEXTURE_MAP = {body.split(chr(0).encode())[0].decode(errors='replace')!r}") print() print("="*70) print("BLX_COP.BGF — vertex block tags + patch/material structure") print("="*70) d=load("content/VIDEO/GEO/BLX_COP.BGF") out=[]; walk(d,8,len(d),0,out) VTAG={0x80:"XYZ(12)",0x81:"XYZ_N(24)",0x82:"XYZ_RGBA(28)",0x88:"XYZ_UV(20)",0x89:"XYZ_N_UV(32)",0x8A:"XYZ_RGBA_UV(36)"} STRIDE={0x80:12,0x81:24,0x82:28,0x88:20,0x89:32,0x8A:36} for depth,cid,p,ln,body in out: ind=" "*depth if cid==0x2008: print(f"{ind}NAME={body.split(chr(0).encode())[0].decode(errors=chr(39)+'replace'+chr(39)) if False else body.split(bytes([0]))[0].decode(errors='replace')!r}") elif cid in (0x2030,0x2031): s=body[1:].split(bytes([0]))[0].decode(errors='replace') print(f"{ind}SV_{'F' if cid==0x2030 else 'B'}_MATERIAL mattype={body[0]} -> {s!r}") elif cid==0x2037: print(f"{ind}SV_SPECIAL {body.split(bytes([0]))[0].decode(errors='replace')!r}") elif cid in VTAG: cnt=ln//STRIDE[cid] print(f"{ind}VERTEX {VTAG[cid]} len={ln} count={cnt}") elif cid==0x0047: print(f"{ind}CONNECTION_LIST(tris) len={ln} ntris={ln//12}") elif cid==0x004d: ppf=body[0] if ln>0 else '?' print(f"{ind}PCONN_LIST ppf={ppf} len={ln}") elif cid==0x40: print(f"{ind}OBJECT") elif cid==0x41: print(f"{ind}LOD") elif cid==0x42: print(f"{ind}PATCH") elif cid==0x46: print(f"{ind}PMESH") elif cid==0x2046 and ln>=8: f=struct.unpack_from("<2f",body,0) print(f"{ind}LOD_DISTANCE in={f[0]:.2f} out={f[1]:.2f}")