qvm: reload requests
Browse files- docs/ASSET_PIPELINE_TODO.md +3 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +3 -0
- docs/RESEARCH_LEDGER.md +5 -0
- docs/REVERSE_ENGINEERING_TODO.md +3 -0
- docs/research/QVM_RELOAD_REQUEST.md +11 -0
- docs/research/README.md +3 -0
- docs/research/qvm-reload-request.json +0 -0
- scripts/analyze_qvm_reload_request.py +26 -0
- scripts/test_qvm_reload_request.py +28 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -379,3 +379,6 @@ Research progress: RE-561 [report](research/QVM_WATER_EVENTS.md); remaining nati
|
|
| 379 |
|
| 380 |
|
| 381 |
Research progress: RE-562 [report](research/QVM_TORSO_SELECTOR.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 379 |
|
| 380 |
|
| 381 |
Research progress: RE-562 [report](research/QVM_TORSO_SELECTOR.md); remaining native/content/runtime/platform scope stays open.
|
| 382 |
+
|
| 383 |
+
|
| 384 |
+
Research progress: RE-563 [report](research/QVM_RELOAD_REQUEST.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -737,3 +737,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 737 |
|
| 738 |
|
| 739 |
**RE-562 — Torso selector priority and weapon class dispatch:** 49117 first rejects nonzero weapon state, then prioritizes legs25 over button8192/16384, then selects torso requests from a file-backed class jump table and tag22/25 exceptions. [Evidence](research/QVM_TORSO_SELECTOR.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 737 |
|
| 738 |
|
| 739 |
**RE-562 — Torso selector priority and weapon class dispatch:** 49117 first rejects nonzero weapon state, then prioritizes legs25 over button8192/16384, then selects torso requests from a file-backed class jump table and tag22/25 exceptions. [Evidence](research/QVM_TORSO_SELECTOR.md).
|
| 740 |
+
|
| 741 |
+
|
| 742 |
+
**RE-563 — Reload request gates and timer animation event effects:** 49652 gates reload on button32, packed magazine/reserve bytes and state flags, sets state bit8 and a configured timer, requests torso56/57 and emits event3 without transferring ammunition. [Evidence](research/QVM_RELOAD_REQUEST.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -691,3 +691,6 @@ Research progress: RE-561 [report](research/QVM_WATER_EVENTS.md); remaining nati
|
|
| 691 |
|
| 692 |
|
| 693 |
Research progress: RE-562 [report](research/QVM_TORSO_SELECTOR.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 691 |
|
| 692 |
|
| 693 |
Research progress: RE-562 [report](research/QVM_TORSO_SELECTOR.md); remaining native/content/runtime/platform scope stays open.
|
| 694 |
+
|
| 695 |
+
|
| 696 |
+
Research progress: RE-563 [report](research/QVM_RELOAD_REQUEST.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -511,3 +511,8 @@ RE-549–558 each has its own code/tests/report/documentation commit. All759 tes
|
|
| 511 |
## 2026-10-19 — RE-562 Torso selector priority and weapon class dispatch (separate task commit)
|
| 512 |
|
| 513 |
49117 first rejects nonzero weapon state, then prioritizes legs25 over button8192/16384, then selects torso requests from a file-backed class jump table and tag22/25 exceptions. 93 probes cover initialized weapon IDs0..27, timer gates, classes−1..7, tag exceptions, toggle-bit aliases and priority conflicts with independent request/animation oracles. Full suite: 771 tests pass. Report regenerates byte-identically (545687 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 511 |
## 2026-10-19 — RE-562 Torso selector priority and weapon class dispatch (separate task commit)
|
| 512 |
|
| 513 |
49117 first rejects nonzero weapon state, then prioritizes legs25 over button8192/16384, then selects torso requests from a file-backed class jump table and tag22/25 exceptions. 93 probes cover initialized weapon IDs0..27, timer gates, classes−1..7, tag exceptions, toggle-bit aliases and priority conflicts with independent request/animation oracles. Full suite: 771 tests pass. Report regenerates byte-identically (545687 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 514 |
+
|
| 515 |
+
|
| 516 |
+
## 2026-10-19 — RE-563 Reload request gates and timer animation event effects (separate task commit)
|
| 517 |
+
|
| 518 |
+
49652 gates reload on button32, packed magazine/reserve bytes and state flags, sets state bit8 and a configured timer, requests torso56/57 and emits event3 without transferring ammunition. 108 probes independently check special IDs14/23, capacity equality, reserve, weapon states, action argument, timer overrides, timed animation and queue writes. Full suite: 775 tests pass. Report regenerates byte-identically (501354 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -731,3 +731,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 731 |
|
| 732 |
|
| 733 |
- [x] RE-562 Torso selector priority and weapon class dispatch ([report](research/QVM_TORSO_SELECTOR.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 731 |
|
| 732 |
|
| 733 |
- [x] RE-562 Torso selector priority and weapon class dispatch ([report](research/QVM_TORSO_SELECTOR.md)).
|
| 734 |
+
|
| 735 |
+
|
| 736 |
+
- [x] RE-563 Reload request gates and timer animation event effects ([report](research/QVM_RELOAD_REQUEST.md)).
|
docs/research/QVM_RELOAD_REQUEST.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Reload request gates and timer animation event effects
|
| 2 |
+
|
| 3 |
+
RE-563. Reproduce with `python3 scripts/analyze_qvm_reload_request.py`; check with `python3 scripts/test_qvm_reload_request.py`. The [machine report](qvm-reload-request.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Complete49652 runs to49916 with actual timed torso39552 and event39238 children. Selected weapon is the low byte of PS312+4×PS144; magazine is bits8..15 and reserve bits24..31. Button32, positive ID, magazine unequal to configured capacity, nonzero reserve, no PS12 bit8, no PS220 bits1024/8 and PS148 unequal2 are required. IDs14/23 additionally reject a nonempty magazine with nonzero PS148. Capacity is an equality test: an explicitly supplied over-capacity magazine still passes this predicate.
|
| 6 |
+
|
| 7 |
+
Accepted requests set state bit8 and replace PS44 with record4056+432×id, adding4060+432×id only when argument8 is nonzero. An existing positive weapon timer does not gate this function. Class4+ requests timed torso57, otherwise56, followed by event3. Timed-animation durations are supplied records, default321, with0/−1 fixtures. Kind3 blocks the torso animation child but the duration store still occurs. The body does not change packed ammunition or inventory.
|
| 8 |
+
|
| 9 |
+
108 finite fixtures cover initialized records and marked synthetic overrides. Remaining work: actual reload completion/ammo transfer, full weapon state machine, animation asset matching, source-order caller interference and live configuration validation.
|
| 10 |
+
|
| 11 |
+
No original executable/full QVM/native collision/physics/rendering executes. Native responses and legal input domains are supplied or unverified where stated; full runtime/macOS/Linux Rust/Bevy/Solari gameplay remains open.
|
docs/research/README.md
CHANGED
|
@@ -292,3 +292,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 292 |
|
| 293 |
|
| 294 |
[RE-562: Torso selector priority and weapon class dispatch](QVM_TORSO_SELECTOR.md). Reproduce with `python3 scripts/analyze_qvm_torso_selector.py`; check with `python3 scripts/test_qvm_torso_selector.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
|
| 293 |
|
| 294 |
[RE-562: Torso selector priority and weapon class dispatch](QVM_TORSO_SELECTOR.md). Reproduce with `python3 scripts/analyze_qvm_torso_selector.py`; check with `python3 scripts/test_qvm_torso_selector.py`.
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
[RE-563: Reload request gates and timer animation event effects](QVM_RELOAD_REQUEST.md). Reproduce with `python3 scripts/analyze_qvm_reload_request.py`; check with `python3 scripts/test_qvm_reload_request.py`.
|
docs/research/qvm-reload-request.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_reload_request.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Complete49652 reload request gates, packed bytes and timed animation/event."""
|
| 3 |
+
import itertools
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from qvm_research_support import source,execute
|
| 6 |
+
from qvm_suffix_support import seed,state,handlers,weapon_config,weapon_words
|
| 7 |
+
from analyze_qvm_acceleration import PS,FRAME
|
| 8 |
+
from analyze_qvm_animation_contacts import TABLE
|
| 9 |
+
from analyze_qvm import write_json
|
| 10 |
+
LOCAL=0x6d000000
|
| 11 |
+
|
| 12 |
+
def reload(ins,m,arg=1,cmd=(0,0,0)):
|
| 13 |
+
m=dict(m);before=state(m);ident=before['packed']&255;cfg=weapon_words(m,ident);m[LOCAL+48]=arg;duration=m[TABLE+m[FRAME+248]*2560+(57 if cfg['class']>=4 else 56)*32+28]
|
| 14 |
+
m,c,r=execute(ins,49653,49916,m,cmd,LOCAL,handlers())
|
| 15 |
+
return m,{'initial':before,'argument':arg,'buttons':m[FRAME+20],'kind':m[PS+4],'config':cfg,'supplied_animation_duration':duration,'execution':r,'final':state(m)}
|
| 16 |
+
|
| 17 |
+
def main():
|
| 18 |
+
q,raw,h,ins=source();rows=[]
|
| 19 |
+
for ident,arg,ws in itertools.product([0,1,14,22,23,27],[0,1],[0,1,2]):
|
| 20 |
+
cap=weapon_words(weapon_config({},raw,h),ident)['capacity']
|
| 21 |
+
for mag in sorted(set([0,1,cap])):
|
| 22 |
+
m=weapon_config(seed(raw,h),raw,h);m.update({PS+312:ident|(mag<<8)|(4<<24),FRAME+20:32,PS+148:ws,PS+44:99});rows.append(reload(ins,m,arg)[1])
|
| 23 |
+
for changes in [{FRAME+20:0},{PS+312:1|(1<<8)},{PS+12:8},{PS+220:8},{PS+220:1024},{PS+220:512},{PS+4:3},{PS+80:100},{PS+312:1|(6<<8)|(255<<24)},{4060+432:123},{TABLE+56*32+28:0},{TABLE+56*32+28:-1}]:
|
| 24 |
+
m=weapon_config(seed(raw,h),raw,h);m.update({PS+312:1|(1<<8)|(4<<24),FRAME+20:32,PS+44:99});m.update(changes);p=reload(ins,m)[1];p['supplied_changes']={str(k):v for k,v in changes.items()};rows.append(p)
|
| 25 |
+
write_json(Path('docs/research/qvm-reload-request.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Complete finite49652 with actual39552/39338/39238/29913; initialized weapon records and supplied animation duration321 except marked overrides. No actual ammo transfer, full weapon state machine or native animation playback.'})
|
| 26 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_reload_request.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest,copy
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_water_events import enqueue
|
| 4 |
+
|
| 5 |
+
def allowed(p):
|
| 6 |
+
a=p['initial'];packed=a['packed'];ident=packed&255;mag=(packed>>8)&255;reserve=packed>>24
|
| 7 |
+
return bool(p['buttons']&32) and not (ident in [14,23] and mag>0 and a['weapon_state']!=0) and ident>0 and mag!=p['config']['capacity'] and reserve!=0 and not a['flags']&8 and not a['state220']&(1024|8) and a['weapon_state']!=2
|
| 8 |
+
class ReloadRequestTests(unittest.TestCase):
|
| 9 |
+
@classmethod
|
| 10 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-reload-request.json').read_text())
|
| 11 |
+
def test_packed_gates_and_source_request_order(self):
|
| 12 |
+
self.assertEqual(len(self.r['probes']),108)
|
| 13 |
+
for p in self.r['probes']:
|
| 14 |
+
active=allowed(p);self.assertEqual([c['target'] for c in p['execution']['calls']],[39552,39238] if active else []);self.assertEqual([c['args']['8'] for c in p['execution']['calls']],[(57 if p['config']['class']>=4 else 56),3] if active else [])
|
| 15 |
+
def test_exact_timer_state_animation_and_queue(self):
|
| 16 |
+
for p in self.r['probes']:
|
| 17 |
+
a=copy.deepcopy(p['initial'])
|
| 18 |
+
if allowed(p):
|
| 19 |
+
a['state220']|=8;a['weapon_timer']=(p['config']['reload']+(p['config']['reload_extra'] if p['argument'] else 0))&0xffffffff;a['torso_timer']=p['supplied_animation_duration']&0xffffffff
|
| 20 |
+
if p['kind']<3:a['torso']=((a['torso']&128)^128)|(57 if p['config']['class']>=4 else 56)
|
| 21 |
+
a['queue']=enqueue(a['queue'],[3])
|
| 22 |
+
self.assertEqual(p['final'],a)
|
| 23 |
+
def test_capacity_is_equality_not_less_than_and_no_ammo_transfer(self):
|
| 24 |
+
self.assertTrue(any((p['initial']['packed']>>8)&255>p['config']['capacity'] and allowed(p) for p in self.r['probes']))
|
| 25 |
+
for p in self.r['probes']:self.assertEqual(p['final']['packed'],p['initial']['packed']);self.assertEqual(p['final']['inventory'],p['initial']['inventory'])
|
| 26 |
+
def test_existing_timer_does_not_gate_reload(self):
|
| 27 |
+
active=[p for p in self.r['probes'] if allowed(p)];self.assertTrue(active);self.assertTrue(any(p['initial']['weapon_timer']==99 and p['final']['weapon_timer']!=99 for p in active));self.assertTrue(any(p['config']['reload_extra']==123 and p['final']['weapon_timer']==523 for p in active))
|
| 28 |
+
if __name__=='__main__':unittest.main()
|