"""Export original authored background model DXBC, without running the shaders."""
from pathlib import Path
import ctypes,hashlib,json,re,struct

folder=Path('artifacts/galaxy-query-research/power-outer-sources')
source=folder/'effects/Effects_Win64_SM50.arc.raw'
data=source.read_bytes()
if hashlib.sha256(data).hexdigest()!='649e3107c868fe31ba23c9e1d19be2b99777b908431987f04f08cd39f0f798ca':raise ValueError('Pinned original effects changed')
out=folder/'authored-models/effects';out.mkdir(exist_ok=True)
names={'vs_Alpha_UnlitNoScale_Forward0_0_0_0_Win64_SM50',
       'ps_Alpha_UnlitNoScale_StarMapFacingAlpha_NearFade_Forward0_0_0_Win64_SM50',
       'vs_GalaxyGlow_Forward0_0_0_Win64_SM50','ps_GalaxyGlow_Forward0_0_0_Win64_SM50'}
dll=ctypes.WinDLL('d3dcompiler_47.dll');disassemble=dll.D3DDisassemble
disassemble.argtypes=[ctypes.c_void_p,ctypes.c_size_t,ctypes.c_uint,ctypes.c_char_p,ctypes.POINTER(ctypes.c_void_p)]
disassemble.restype=ctypes.c_int32
rows=[]
for match in re.finditer(b'DXBC',data):
    offset=match.start();size,chunks=struct.unpack_from('<II',data,offset+24)
    if not 32<=size<=1024*1024 or not 1<=chunks<=16 or offset+size>len(data):continue
    label=re.search(rb'(vs|ps)_[A-Za-z0-9_]+_Win64_SM50\0',data[offset+size:offset+size+256])
    if label is None:continue
    name=label.group()[:-1].decode('ascii')
    if name not in names:continue
    blob=data[offset:offset+size];(out/(name+'.dxbc')).write_bytes(blob)
    result=ctypes.c_void_p();buffer=ctypes.create_string_buffer(blob)
    if disassemble(buffer,len(blob),0,None,ctypes.byref(result))<0:raise ValueError('D3DDisassemble failed')
    table=ctypes.cast(result,ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p)))[0]
    try:
        p=ctypes.WINFUNCTYPE(ctypes.c_void_p,ctypes.c_void_p)(table[3])(result)
        n=ctypes.WINFUNCTYPE(ctypes.c_size_t,ctypes.c_void_p)(table[4])(result)
        text=ctypes.string_at(p,n).decode().rstrip('\0')
    finally:ctypes.WINFUNCTYPE(ctypes.c_uint,ctypes.c_void_p)(table[2])(result)
    (out/(name+'.txt')).write_text(text,encoding='utf-8')
    rows.append(dict(name=name,offset=offset,bytes=size,sha256=hashlib.sha256(blob).hexdigest()))
if {r['name'] for r in rows}!=names or len(rows)!=4:raise ValueError('Original model effect selection ambiguous')
result=dict(source=str(source),sourceSha256=hashlib.sha256(data).hexdigest(),gameProcessAccess=False,shaderExecution=False,
    shaders=rows,genericAlphaVertexShaderAssociationProven=False)
(out/'original-authored-model-effects.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print(json.dumps(rows))
