"""Bounded exact service-summary owner/getter proof; offline PE bytes only."""
import hashlib,importlib.util,json,struct
from pathlib import Path
spec=importlib.util.spec_from_file_location('audit',Path(__file__).with_name('Audit-GalaxyClientCompatibility.py'))
audit=importlib.util.module_from_spec(spec);spec.loader.exec_module(audit)
old=audit.Image(Path('artifacts/ship-model-reference/client-copy/EliteDangerous64.exe'))
new=audit.Image(Path('D:/SteamLibrary/steamapps/common/Elite Dangerous/Products/elite-dangerous-odyssey-64/EliteDangerous64.exe'))
hashes=[hashlib.sha256(i.raw).hexdigest() for i in (old,new)]
assert hashes==['6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93','ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63']
functions=[];references=[]
for before in [0x1DD2560,0x1E22170,0x3B26860]:
fn=old.function(before);assert fn and fn[0]==before
row=audit.match(old,new,before,fn[1]-before);assert row['status']=='unique',(hex(before),row)
row['oldRva']=hex(before);functions.append(row)
references.extend(audit.references(old,new,before,int(row['newRva'],16),row['length']))
binding={a:b for a,b,_,_ in references}
tables=[dict(oldRva=hex(v),newRva=hex(binding[v])) for v in [0x5242418,0x5242460,0x5242560]]
assert binding[0x5F856E8]==0x5F856E8
slots=[]
for offset in [0,8,0x50]:
before=int.from_bytes(old.data(0x5242560+offset,8),'little')-old.base
after=int.from_bytes(new.data(binding[0x5242560]+offset,8),'little')-new.base
# The ctor-paired actual typed vtable independently supplies short leaf
# destinations. Never pick one of many normalized getter candidates.
old_ins=[]
for i in old.instructions(before,64):
old_ins.append(i)
if i.mnemonic=='ret':break
length=old.function(before)[1]-before if offset==0x50 else sum(i.size for i in old_ins)
left=audit.signature(old,before,length);right=audit.signature(new,after,length)
normalized=bytes(a&b for a,b in zip(left[0],left[1]));other=bytes(a&b for a,b in zip(right[0],right[1]))
assert left[1]==right[1] and normalized==other
row=dict(oldRva=hex(before),newRva=hex(after),length=length,status='unique',method='actual-ctor-paired-typed-vtable-slot-and-full-body',normalizedSha256=hashlib.sha256(normalized).hexdigest())
functions.append(row);references.extend(audit.references(old,new,before,after,length))
slots.append(dict(oldVtable='0x5242560',newVtable=hex(binding[0x5242560]),slot=hex(offset),oldRva=hex(before),newRva=hex(after),length=length))
selection_targets=struct.unpack('<10I',old.data(0x3B269D4,40))
assert selection_targets==(0x3B26962,0x3B26962,0x3B26962,0x3B26962,0x3B26972,0x3B26972,0x3B2695B,0x3B26990,0x3B26982,0x3B26989)
result=dict(runtimeNeutral=True,gameProcessAccess=False,gameCalls=0,networkRequests=0,canInstallHooks=False,runtimeValidated=False,
oldImageSha256=hashes[0],newImageSha256=hashes[1],functions=functions,references=[list(map(hex,row)) for row in references],
vtables=tables,slots=slots,typeGlobal=dict(oldRva='0x5f856e8',newRva='0x5f856e8'),
source=dict(interfaceOffset='0x58',summaryMap='interface+0x118',count='map+8',capacity='map+0x10',storage='map+0x18',
records='storage+(((capacity>>3)+7)&~7)',stride=16,keyOffset=0,summaryOffset=8,summaryBytes=6),
selection=dict(originalGetter='0x3b26860',jumpTable='0x3b269d4',targets=[hex(v) for v in selection_targets],indexSource='explicit tool index, never original Settings34',
materialTrader='byte2 == index+1 for index0..3',technologyBroker='byte3 == index-3 for index4..5',
booleans={'6':'byte1!=0','7':'byte0!=0','8':'byte4!=0','9':'byte5!=0'}),
absence='Actual1E22170 returns six zero bytes for absent key. Initial zero-capacity source remains unknown in this adapter; no network/completeness claim.')
out=Path('artifacts/galaxy-query-research/service-facts/compatibility.json');out.parent.mkdir(parents=True,exist_ok=True)
out.write_text(json.dumps(result,indent=2)+'\n',encoding='utf8')
print(json.dumps(dict(output=str(out),functions=[{k:r[k] for k in ['oldRva','newRva','length']} for r in functions],vtables=tables,slots=slots),indent=2))
"""Bounded exact service-summary owner/getter proof; offline PE bytes only."""
import hashlib,importlib.util,json,struct
from pathlib import Path
spec=importlib.util.spec_from_file_location('audit',Path(__file__).with_name('Audit-GalaxyClientCompatibility.py'))
audit=importlib.util.module_from_spec(spec);spec.loader.exec_module(audit)
old=audit.Image(Path('artifacts/ship-model-reference/client-copy/EliteDangerous64.exe'))
new=audit.Image(Path('D:/SteamLibrary/steamapps/common/Elite Dangerous/Products/elite-dangerous-odyssey-64/EliteDangerous64.exe'))
hashes=[hashlib.sha256(i.raw).hexdigest() for i in (old,new)]
assert hashes==['6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93','ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63']
functions=[];references=[]
for before in [0x1DD2560,0x1E22170,0x3B26860]:
fn=old.function(before);assert fn and fn[0]==before
row=audit.match(old,new,before,fn[1]-before);assert row['status']=='unique',(hex(before),row)
row['oldRva']=hex(before);functions.append(row)
references.extend(audit.references(old,new,before,int(row['newRva'],16),row['length']))
binding={a:b for a,b,_,_ in references}
tables=[dict(oldRva=hex(v),newRva=hex(binding[v])) for v in [0x5242418,0x5242460,0x5242560]]
assert binding[0x5F856E8]==0x5F856E8
slots=[]
for offset in [0,8,0x50]:
before=int.from_bytes(old.data(0x5242560+offset,8),'little')-old.base
after=int.from_bytes(new.data(binding[0x5242560]+offset,8),'little')-new.base
# The ctor-paired actual typed vtable independently supplies short leaf
# destinations. Never pick one of many normalized getter candidates.
old_ins=[]
for i in old.instructions(before,64):
old_ins.append(i)
if i.mnemonic=='ret':break
length=old.function(before)[1]-before if offset==0x50 else sum(i.size for i in old_ins)
left=audit.signature(old,before,length);right=audit.signature(new,after,length)
normalized=bytes(a&b for a,b in zip(left[0],left[1]));other=bytes(a&b for a,b in zip(right[0],right[1]))
assert left[1]==right[1] and normalized==other
row=dict(oldRva=hex(before),newRva=hex(after),length=length,status='unique',method='actual-ctor-paired-typed-vtable-slot-and-full-body',normalizedSha256=hashlib.sha256(normalized).hexdigest())
functions.append(row);references.extend(audit.references(old,new,before,after,length))
slots.append(dict(oldVtable='0x5242560',newVtable=hex(binding[0x5242560]),slot=hex(offset),oldRva=hex(before),newRva=hex(after),length=length))
selection_targets=struct.unpack('<10I',old.data(0x3B269D4,40))
assert selection_targets==(0x3B26962,0x3B26962,0x3B26962,0x3B26962,0x3B26972,0x3B26972,0x3B2695B,0x3B26990,0x3B26982,0x3B26989)
result=dict(runtimeNeutral=True,gameProcessAccess=False,gameCalls=0,networkRequests=0,canInstallHooks=False,runtimeValidated=False,
oldImageSha256=hashes[0],newImageSha256=hashes[1],functions=functions,references=[list(map(hex,row)) for row in references],
vtables=tables,slots=slots,typeGlobal=dict(oldRva='0x5f856e8',newRva='0x5f856e8'),
source=dict(interfaceOffset='0x58',summaryMap='interface+0x118',count='map+8',capacity='map+0x10',storage='map+0x18',
records='storage+(((capacity>>3)+7)&~7)',stride=16,keyOffset=0,summaryOffset=8,summaryBytes=6),
selection=dict(originalGetter='0x3b26860',jumpTable='0x3b269d4',targets=[hex(v) for v in selection_targets],indexSource='explicit tool index, never original Settings34',
materialTrader='byte2 == index+1 for index0..3',technologyBroker='byte3 == index-3 for index4..5',
booleans={'6':'byte1!=0','7':'byte0!=0','8':'byte4!=0','9':'byte5!=0'}),
absence='Actual1E22170 returns six zero bytes for absent key. Initial zero-capacity source remains unknown in this adapter; no network/completeness claim.')
out=Path('artifacts/galaxy-query-research/service-facts/compatibility.json');out.parent.mkdir(parents=True,exist_ok=True)
out.write_text(json.dumps(result,indent=2)+'\n',encoding='utf8')
print(json.dumps(dict(output=str(out),functions=[{k:r[k] for k in ['oldRva','newRva','length']} for r in functions],vtables=tables,slots=slots),indent=2))