Download scripts/analyze_chat_items_time.py from nmarshall/urt-rs: direct link, hf CLI and curl.
- Browser
- Download file 4.84 kB
-
https://huggingface.co/nmarshall/urt-rs/resolve/main/scripts/analyze_chat_items_time.py
- Command line
-
hf download hf://nmarshall/urt-rs/scripts/analyze_chat_items_time.py
-
curl -L -o analyze_chat_items_time.py https://huggingface.co/nmarshall/urt-rs/resolve/main/scripts/analyze_chat_items_time.py
4.84 kB
| #!/usr/bin/env python3 | |
| """Recover packed chat ammo/item arguments and bounded timer substitutions.""" | |
| 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 name_candidates(data,h,count=30): | |
| """Read an explicitly sampled domain; this does not establish table length.""" | |
| if not 0<=count<=256:raise ValueError('sample outside low-byte domain') | |
| rows=[] | |
| for index in range(count): | |
| address=4020+432*index | |
| if address+4>h['data_length']:raise ValueError('sample word outside initialized data') | |
| if h['data_offset']+address+4>len(data):raise ValueError('truncated sampled word') | |
| pointer=struct.unpack_from('<I',data,h['data_offset']+address)[0] | |
| rows.append({'index':index,'word_address':address,'pointer':pointer, | |
| 'name':vm_string(data,h,pointer) if pointer else None}) | |
| return rows | |
| 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) | |
| c=json.loads(Path('docs/research/game-cvars.json').read_text()) | |
| if c['sha256']!=q['sha256']:raise ValueError('cvar provenance changed') | |
| timelimit=next(r for r in c['registry']['rows'] if r['mirror_address']+12==34088124) | |
| if timelimit['name']!='timelimit':raise ValueError('timer cvar identity changed') | |
| rows=name_candidates(data,h) | |
| entity,record=0x10000,0x20000 | |
| ammo=[] | |
| for key,start in [('clips',185415),('bullets',185502)]: | |
| for packed in [0,0x01020304,0xfffe001d,-1]: | |
| for state,override in [(0,0),(3,0),(4,0),(0,1)]: | |
| t=trace_slice(ins,start,186431,{entity+520:record,record+144:2, | |
| record+312+4*2:packed,record+4:state,record+4324:override},{1144:entity}) | |
| ammo.append({'key':key,'selected_word_index':2,'packed_word':packed,'raw_state':state, | |
| 'override':override,'trace':t}) | |
| weapons=[] | |
| for row in rows: | |
| index=row['index'];packed=0xaabbcc00|index | |
| for state in [0,3]: | |
| t=trace_slice(ins,185589,186431,{entity+520:record,record+144:1,record+316:packed, | |
| record+4:state,record+4324:0,row['word_address']:row['pointer']},{1144:entity}) | |
| weapons.append({'low_byte':index,'packed_word':packed,'raw_state':state,'trace':t}) | |
| game=[] | |
| for minutes,now,start in [(20,1000,0),(0,0,0),(-1,0,0),(1,0,0),(1,59999,0),(1,60000,0), | |
| (1,60001,0),(1,1000,2000),(35792,0,0),(1,2147483640,-2147483640)]: | |
| t=trace_slice(ins,185781,186431,{34088124:minutes,34992532:now,34992544:start},{}) | |
| game.append({'timelimit_integer':minutes,'now':now,'start':start,'trace':t}) | |
| round_time=[] | |
| for gt in range(0,12): | |
| for delta in [-1,0,1,59999,60000,61000]: | |
| t=trace_slice(ins,185850,186431,{34090788:gt,34992548:100000+delta,34992532:100000},{}) | |
| round_time.append({'gametype':gt,'deadline_minus_now':delta,'trace':t}) | |
| item=[] | |
| for gt in [0,7,8,9]: | |
| t=trace_slice(ins,185706,186431,{34090788:gt},{}) | |
| item.append({'gametype':gt,'trace':t}) | |
| random_tail=[] | |
| for value in [0,1,2,3,-1]: | |
| t=trace_slice(ins,185742,186431,{}, {68:value}) | |
| random_tail.append({'supplied_helper_36717_return':value,'trace':t}) | |
| addresses=[78068,78066,78042,78037,77972,77959,77936,78014,78009,78000,77991] | |
| out={'source':q['source'],'sha256':q['sha256'],'timelimit_registry':timelimit, | |
| 'sampled_name_words':rows,'sample_domain':{'first':0,'last':29,'complete_table':False}, | |
| 'ammo_traces':ammo,'weapon_traces':weapons,'gametime_traces':game,'roundtime_traces':round_time, | |
| 'gameitem_traces':item,'gameitem_bit_traces':random_tail, | |
| 'strings':{str(a):vm_string(data,h,a) for a in addresses}, | |
| 'lookup_function':partition_function(ins,185212,data,h), | |
| 'limitations':'Static file-backed samples and bounded synthetic slices, not original runtime/full ' | |
| 'QVM execution. CALLs have zero placeholder returns; helper-36717 bit-tail inputs are supplied, ' | |
| 'not RNG outputs. Formatter calls are arguments, not text. The name-word sample does not establish ' | |
| 'table extent, record layout or legal weapon IDs. Packed-field producers, timer global writers, ' | |
| 'cvar update/wrap behavior, item ownership and platform parity remain open.'} | |
| write_json(Path('docs/research/chat-items-time.json'),out) | |
| print(f'Recovered {len(ammo)} ammo, {len(weapons)} weapon and {len(game)+len(round_time)} timer slices') | |
| if __name__=='__main__':main() | |