#!/usr/bin/env python3 """Recover chat modes, dead-chat decisions and bounded delivery/echo calls.""" import itertools import json from pathlib import Path from analyze_auth_announcements import recover_table 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 policy_allows(policy,mode,gametype,sub,spec,dead,target_spec,target_dead,bypass=0): """Independent readable interpretation checked against instruction traces.""" if bypass:return True if policy==1: if spec and not target_spec and gametype!=9:return False return not(sub or spec or dead) or target_spec or target_dead or mode==1 or gametype==9 if policy==2:return not spec or target_spec or gametype==9 return not(sub or spec or dead) or target_spec or target_dead or gametype==9 def main(): q=json.loads(Path('docs/research/qvm/qagame.json').read_text()) data=verified(Path(q['source']['member']['output']).read_bytes(),q['sha256']);h,ins=decode(data) reg=json.loads(Path('docs/research/game-cvars.json').read_text()) if reg['sha256']!=q['sha256']:raise ValueError('registry provenance mismatch') deadchat=next(r for r in reg['registry']['rows'] if r['name']=='g_deadchat') if deadchat['mirror_address']+12!=34067996:raise ValueError('deadchat identity changed') table=recover_table(data,h,ins,29376,0,4,187381,187911) targets={r['value']:r['target_instruction'] for r in table['rows']} memory={r['vm_address']:r['target_instruction'] for r in table['rows']} switches=[{'mode':m,'target':targets.get(m,187423), 'trace':trace_slice(ins,187403,targets.get(m,187423),memory,{436:m})} for m in range(-1,6)] policies=[] for policy,mode,gt,flags in itertools.product([0,1,2,3],[0,1],[0,9],itertools.product([0,1],repeat=5)): sub,spec,dead,ts,td=flags accepted=bool(policy_allows(policy,mode,gt,*flags)) t=trace_slice(ins,187058,187154 if accepted else 187379, {34999652:0,34067996:policy,34090788:gt},{56:sub,44:spec,60:dead,64:ts,68:td,124:mode}) policies.append({'policy':policy,'mode':mode,'gametype':gt,'flags':list(flags),'accepted':accepted, 'instructions':t['trace']}) bypass=trace_slice(ins,187058,187154,{34999652:1},{}) sender,recipient,sr,rr=34091368+2*880,34091368+3*880,0x30000,0x40000 derived=[] for sub,st,sd,sover,rt,rd,rover in [(0,1,0,0,1,0,0),(1,1,0,0,1,0,0),(0,3,0,0,3,0,0), (0,1,3,0,1,3,0),(0,1,0,1,4,0,1)]: t=trace_slice(ins,186920,187058,{sender+520:sr,recipient+520:rr,sr+3740:sub,sr+3096:st, sr+4:sd,sr+4324:sover,rr+3096:rt,rr+4:rd,rr+4324:rover},{116:sender,120:recipient}) derived.append({'raw_fields':[sub,st,sd,sover,rt,rd,rover],'trace':t}) formats=[] for mode,team,sub,spec,dead,self_target in [(0,1,0,0,0,False),(1,2,1,1,1,False), (0,0,0,1,1,False),(2,1,0,0,0,False),(2,1,0,0,0,True),(3,2,0,0,0,False),(4,2,0,0,0,False)]: target=sender if self_target else recipient t=trace_slice(ins,187154,187379,{sender+520:sr,sr+3096:team}, {116:sender,120:target,124:mode,128:51,132:0x50000,136:0x60000,56:sub,44:spec,60:dead}) formats.append({'mode':mode,'sender_team':team,'flags':[sub,spec,dead],'same_object':self_target, 'trace':t}) echoes=[] for same,flags in [(True,0),(False,0),(False,8)]: t=trace_slice(ins,187712,187909,{sender+424:flags}, {428:sender,432:sender if same else recipient,436:2,260:51,192:0}) echoes.append({'same_object':same,'sender_flags_raw':flags,'trace':t}) fanouts=[] for count,clean in [(0,0),(3,0),(3,1)]: t=trace_slice(ins,187834,187909,{34992524:count},{428:sender,436:0,260:51,192:clean},limit=1000) fanouts.append({'count':count,'clean_flag':clean,'trace':t}) addresses=[77798,77792,77785,77777,77776,77768,77765,77762,77725,77722,77696,77653,77619,77589, 77828,77805,77728] output={'source':q['source'],'sha256':q['sha256'],'deadchat_registry':deadchat,'mode_table':table, 'mode_switch_traces':switches,'deadchat_policy_traces':policies,'bypass_trace':bypass, 'derived_flag_traces':derived,'format_argument_traces':formats,'echo_traces':echoes,'fanout_traces':fanouts, 'strings':{str(a):vm_string(data,h,a) for a in addresses}, 'functions':{str(e):partition_function(ins,e,data,h) for e in [186435,186721,187381]}, 'limitations':'Static qagame and bounded synthetic slices, not complete QVM/game execution. Calls ' 'are recorded with zero placeholder returns. Format arguments/pointers are evidence, not formatted ' 'commands. Field identities are provisional except supplied strings/cvar mappings. Earlier recipient ' 'gates are excluded from the policy matrix; global lifetime, text expansion, reliable queues and ' 'rendered/platform conformance remain open.'} write_json(Path('docs/research/chat-delivery.json'),output) print(f'Recovered {len(policies)} deadchat policy paths, mode/format and echo/fanout evidence') if __name__=='__main__':main()