XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Pin the authored Galaxy plane/core meshes and their actual renderer transforms.

This is an offline evidence export. Packed attributes other than position remain
raw until the selected model VS/input layout has been checked independently.
"""
from pathlib import Path
import hashlib,json,math,struct
import pefile

root=Path('artifacts/galaxy-query-research/power-outer-sources')
out=root/'authored-models';out.mkdir(exist_ok=True)
image=Path('artifacts/ship-model-reference/client-copy/EliteDangerous64.exe')
raw=image.read_bytes();sha=hashlib.sha256(raw).hexdigest()
if sha!='6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93':raise ValueError('Pinned image changed')
pe=pefile.PE(data=raw,fast_load=True);base=pe.OPTIONAL_HEADER.ImageBase
if struct.unpack('<Q',pe.get_data(0x551F2D8+0x10,8))[0]!=base+0x3A5BAF0:raise ValueError('Galaxy initializer changed')
if pe.get_data(0x551F6D8,13)!=b'MilkyWayCore\0' or pe.get_data(0x551F6E8,14)!=b'MilkyWayPlane\0':raise ValueError('Original model names changed')
constants={}
for label,rva,n in [('centre',0x551F6B8,4),('origin',0x551F6C8,4),('coreScale',0x5529C00,1),('planeScale',0x4DEC680,1),
                    ('axisX',0x50CB0D0,4),('axisY',0x50CB0E0,4),('axisZ',0x50CB0F0,4),('signMask',0x4E32920,4)]:
    data=pe.get_data(rva,n*4);constants[label]=dict(rva=hex(rva),bytes=data.hex(),values=struct.unpack('<'+'f'*n,data))
if constants['centre']['values']!=(50000.,40955.,50000.,0.) or constants['origin']['values']!=(49985.,40985.,24105.,0.):raise ValueError('Original model origin changed')
if constants['coreScale']['values']!=(40000.,) or constants['planeScale']['values']!=(100000.,):raise ValueError('Original scale changed')
scope={};exec(Path('research/Extract-GalaxyRenderMaterials.py').read_text().split('for group,entry in enumerate(buffers):')[0],scope)
b=scope['b'];materials=json.loads((root/'material/original-materials.json').read_text())
def decode_position(v):
    packed=struct.unpack_from('<Q',v)[0];power=v[11]&127
    if power==64:
        radius=2**((packed>>48)*(16/65535))-1
        return [(((packed>>shift)&65535)*(2/65535)-1)*radius for shift in (0,16,32)]
    if power>19:raise ValueError('Unknown position encoding')
    scale=1/((1<<(20-power))-1);bias=1<<power
    return [((packed>>shift)&0x1fffff)*scale-bias for shift in (0,21,42)]
models=[]
for group,model_index,scale,axes in [(27,1,100000.,[-1,1,-1]),(28,0,40000.,[1,1,1])]:
    entry=scope['buffers'][group];parts=scope['buffer_offsets'][group]
    if entry[1]!=193499543 or [p['tag'] for p in parts]!=[0,1,2]:raise ValueError('Original mesh buffers changed')
    name=scope['names_by_id'][entry[0]];tag,meta,gpu=[b[p['offset']:p['offset']+p['size']] for p in parts]
    material_id=struct.unpack_from('<I',tag)[0];material_name=tag[4:-1].decode('ascii')
    material=next(m for m in materials['materials'] if m['name']==material_name.lower() and int(m['id'],16)==material_id)
    index_bytes=struct.unpack_from('<Q',meta,16)[0];vertex_bytes=struct.unpack_from('<Q',meta,32)[0]
    index_count,vertex_count,unused,format_id=struct.unpack_from('<4I',meta,256)
    if index_bytes!=index_count*2 or vertex_bytes!=vertex_count*40 or len(gpu)!=24+index_bytes+vertex_bytes or format_id!=8 or unused:raise ValueError('Original mesh layout changed')
    indices=list(struct.unpack_from('<'+'H'*index_count,gpu,24))
    if any(i>=vertex_count for i in indices):raise ValueError('Index outside original vertices')
    positions=[decode_position(gpu[24+index_bytes+i*40:24+index_bytes+(i+1)*40]) for i in range(vertex_count)]
    bounds=[[min(p[i] for p in positions) for i in range(3)],[max(p[i] for p in positions) for i in range(3)]]
    if not all(math.isfinite(v) for p in positions for v in p):raise ValueError('Nonfinite original mesh')
    mesh_file=out/(name+'.gpu');mesh_file.write_bytes(gpu)
    models.append(dict(name=name,root=scope['root_by_id'][entry[0],entry[1]],bufferGroup=group,sourceParts=parts,
        gpuSha256=hashlib.sha256(gpu).hexdigest(),gpuPath=str(mesh_file),indexOffset=24,indexCount=index_count,indexBytes=index_bytes,
        vertexOffset=24+index_bytes,vertexCount=vertex_count,vertexBytes=vertex_bytes,vertexStride=40,vertexFormat=8,
        decodedPositionBounds=bounds,positions=positions,indices=indices,materialId=hex(material_id),material=material,
        originalTransform=dict(modelArrayField='0x6D0',index=model_index,scale=scale,axes=axes,worldCentre=[50000,40955,50000],
            solRelativeCentre=[15,-30,25895],sourceFunction='0x3A5BAF0',helper='0x3B067D0')))
sources=[]
for relative in ['palette-resources/decompiled/solo-3a06740.c','power-outer-sources/background/solo-3a5baf0.c',
                 'power-outer-sources/background/solo-3a5c2d0.c','power-outer-sources/background/solo-3b067d0.c']:
    path=Path('artifacts/galaxy-query-research')/relative
    sources.append(dict(path=str(path),sha256=hashlib.sha256(path.read_bytes()).hexdigest()))
result=dict(gameImageSha256=sha,gameProcessAccess=False,gameCalls=0,resource='19b9e393c96329f63707aeade6a46e8cf3b71398',
    archiveSha256=materials['sourceArchiveSha256'],frozenSha256=materials['frozenSha256'],
    renderer=dict(constructor='0x3A06740',mainVtable='0x551F2D8',initializationSlot='0x10',initializer='0x3A5BAF0',
        slotBytes=pe.get_data(0x551F2D8+0x10,8).hex(),constructorAlsoCreates='actual galaxy renderer used by the cloud passes'),
    constants=constants,sourceFunctions=sources,models=models,
    unclosed=['selected original packed VS/input layout for every non-position attribute',
        'dynamic material override and final per-pass shader selection','frame fade/shared output and final HDR transform'],productionModelRenderingEnabled=False)
path=out/'original-authored-models.json';path.write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print(json.dumps(dict(path=str(path),models=[dict(name=m['name'],vertices=m['vertexCount'],indices=m['indexCount'],bounds=m['decodedPositionBounds'],shader=m['material']['shaderClass']) for m in models])))