urt-rs / scripts /analyze_chat_locations.py
nmarshall's picture
Recover team leader and location lookup paths
31f9605
Raw History Blame Contribute Delete
5.07 kB
#!/usr/bin/env python3
"""Recover leader scan, cached location formatting and location-list registration."""
import json
import struct
from pathlib import Path
from analyze_deferred_auth import partition_function, trace_slice
from analyze_game_cvars import vm_string
from analyze_qvm import decode,write_json
from analyze_vm_extensions import verified
def main():
q=json.loads(Path('docs/research/qvm/qagame.json').read_text())
d=verified(Path(q['source']['member']['output']).read_bytes(),q['sha256']);h,ins=decode(d)
leader=[]
cases=[(0,[]),(-1,[]),(3,[(0,1,1),(1,2,1),(2,1,1)]),
(3,[(1,1,1),(2,1,1),(2,1,1)]),(3,[(2,1,0),(2,1,0),(2,2,1)]),
(3,[(1,1,-1),(0,1,1),(2,1,1)])]
for count,records in cases:
memory={34992496:0x10000,34992524:count}
for i,(state,team,flag) in enumerate(records):
a=0x10000+i*6336
memory.update({a+468:state,a+3096:team,a+3124:flag})
t=trace_slice(ins,169398,169460,memory,{20:1},halt_on_leave=True,capture_stack=True,limit=1024)
leader.append({'count':count,'record_state_team_flag':records,'requested_team':1,'trace':t})
leader_format=[]
for slot in [-1,0,2]:
memory={} if slot==-1 else {34091888+slot*880:0x50000}
t=trace_slice(ins,185947,186431,memory,{76:slot})
leader_format.append({'supplied_leader_return':slot,'trace':t})
cache=[]
obj,location=0x10000,0x20000
for pointer,now,expiry in [(0,1000,0),(location,999,1000),(location,1000,1000),
(location,1001,1000),(location,-2147483640,2147483640)]:
m={obj+848:pointer,34992532:now}
if pointer:m[pointer+596]=expiry
t=trace_slice(ins,268249,268279,m,{4236:obj},halt_on_leave=True,capture_stack=True)
cache.append({'pointer':pointer,'now':now,'expiry':expiry,'trace':t})
format_traces=[]
for result in [0,location]:
t=trace_slice(ins,268649,268676,{} if not result else {location+592:0x60000},
{24:result,44:0x70000,48:150},halt_on_leave=True,capture_stack=True)
format_traces.append({'supplied_lookup_return':result,'trace':t})
lists=[]
for guarded,count,fields in [(1,3,[]),(0,0,[]),
(0,3,[(1,8489281),(0,8489281),(1,0)]),
(0,3,[(1,8489281),(1,8489281),(1,8489281)])]:
m={34999636:guarded,34992508:count}
for i,(name_present,raw_tag) in enumerate(fields):
obj=34091368+i*880
m.update({obj+536:0x80000 if name_present else 0,obj+540:raw_tag,
obj+524:0x90000+i*64,obj+592:0xa0000+i*64})
t=trace_slice(ins,264977,265088,m,{36:34091368},limit=2048)
lists.append({'guard':guarded,'count':count,'name_present_raw_tag':fields,'trace':t})
references={}
for value in [169397,268248,268637,34999640]:
references[str(value)]=[]
for j,x in enumerate(ins):
if x['opcode']=='CONST' and x['operand']==value:
entry=next(k for k in range(j,-1,-1) if ins[k]['opcode']=='ENTER')
references[str(value)].append({'instruction':j,'containing_entry':entry,
'window':ins[max(entry,j-4):j+7]})
abi=json.loads(Path('docs/research/qvm/qagame.abi-candidates.json').read_text())
if abi['sha256']!=q['sha256']:raise ValueError('ABI provenance changed')
services=[r for r in abi['syscalls'] if r['number'] in [18,26,32]]
extent=[]
for address in [31128,31132,31136]:
if address+4>h['data_length']:raise ValueError('box extent outside initialized data')
offset=h['data_offset']+address
extent.append({'vm_address':address,'raw_bits':struct.unpack_from('<I',d,offset)[0],
'float_value':struct.unpack_from('<f',d,offset)[0]})
out={'box_extent_constants':extent,'abi_reference_revision':abi['reference_revision'],'service_candidates':services,'source':q['source'],'sha256':q['sha256'],
'functions':{str(e):partition_function(ins,e,d,h) for e in [169397,264976,268248,268637]},
'leader_scan_traces':leader,'leader_format_traces':leader_format,'cache_traces':cache,
'location_format_traces':format_traces,'registration_traces':lists,'literal_references':references,
'strings':{str(a):vm_string(d,h,a) for a in [93224,93227,92460,78042]},
'limitations':'Static partitions and bounded synthetic traces, not original runtime/full QVM '
'execution. Callees are recorded with zero placeholder returns; isolated lookup/leader returns are '
'supplied. Floating-point distance/geometry and engine box/visibility calls are retained but not '
'evaluated. Field types, cache writers, list lifecycle/ownership, real formatting and all-platform '
'behavior remain open. Literal scans exclude aliases/computed references.'}
write_json(Path('docs/research/chat-locations.json'),out)
print('Recovered leader selection, cached location formatting and list-building traces')
if __name__=='__main__':main()