qvm: ready weapon consumers
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_WEAPON_READY.md +11 -0
- docs/research/README.md +3 -0
- docs/research/qvm-weapon-ready.json +0 -0
- scripts/analyze_qvm_weapon_ready.py +25 -0
- scripts/test_qvm_weapon_ready.py +33 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -418,3 +418,6 @@ Research progress: RE-575 [report](research/QVM_WEAPON_SELECTION_CALLER.md); rem
|
|
| 418 |
|
| 419 |
|
| 420 |
Research progress: RE-576 [report](research/QVM_WEAPON_GUARDS.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 418 |
|
| 419 |
|
| 420 |
Research progress: RE-576 [report](research/QVM_WEAPON_GUARDS.md); remaining native/content/runtime/platform scope stays open.
|
| 421 |
+
|
| 422 |
+
|
| 423 |
+
Research progress: RE-577 [report](research/QVM_WEAPON_READY.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -776,3 +776,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 776 |
|
| 777 |
|
| 778 |
**RE-576 — Weapon continuation guards timer floors and cancellation:** 50923..51206 applies ordered traversal/action guards, floors timers at300, conditionally cancels state512 and returns while timer is positive; two ID checks literally assign localID12 on their fallback paths. [Evidence](research/QVM_WEAPON_GUARDS.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 776 |
|
| 777 |
|
| 778 |
**RE-576 — Weapon continuation guards timer floors and cancellation:** 50923..51206 applies ordered traversal/action guards, floors timers at300, conditionally cancels state512 and returns while timer is positive; two ID checks literally assign localID12 on their fallback paths. [Evidence](research/QVM_WEAPON_GUARDS.md).
|
| 779 |
+
|
| 780 |
+
|
| 781 |
+
**RE-577 — Ready weapon refill cadence and interaction re-entry:** 51207..51364 refills ID27 magazine from configured capacity, handles mode-flag1/counter cadence, then clears state1 before optional button64 interaction re-entry and exits. [Evidence](research/QVM_WEAPON_READY.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -732,3 +732,6 @@ Research progress: RE-575 [report](research/QVM_WEAPON_SELECTION_CALLER.md); rem
|
|
| 732 |
|
| 733 |
|
| 734 |
Research progress: RE-576 [report](research/QVM_WEAPON_GUARDS.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 732 |
|
| 733 |
|
| 734 |
Research progress: RE-576 [report](research/QVM_WEAPON_GUARDS.md); remaining native/content/runtime/platform scope stays open.
|
| 735 |
+
|
| 736 |
+
|
| 737 |
+
Research progress: RE-577 [report](research/QVM_WEAPON_READY.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -576,3 +576,8 @@ Actual54444 reload/interaction order exposes timer interference before the weapo
|
|
| 576 |
## 2026-10-20 — RE-576 Weapon continuation guards timer floors and cancellation (separate task commit)
|
| 577 |
|
| 578 |
50923..51206 applies ordered traversal/action guards, floors timers at300, conditionally cancels state512 and returns while timer is positive; two ID checks literally assign localID12 on their fallback paths. 90 independent probes check exact state/stop/local-ID results, timer−1/0/1/299/300, state512/button priority and literal assignment for IDs outside11/13. Full suite: 823 tests pass. Report regenerates byte-identically (260588 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 576 |
## 2026-10-20 — RE-576 Weapon continuation guards timer floors and cancellation (separate task commit)
|
| 577 |
|
| 578 |
50923..51206 applies ordered traversal/action guards, floors timers at300, conditionally cancels state512 and returns while timer is positive; two ID checks literally assign localID12 on their fallback paths. 90 independent probes check exact state/stop/local-ID results, timer−1/0/1/299/300, state512/button priority and literal assignment for IDs outside11/13. Full suite: 823 tests pass. Report regenerates byte-identically (260588 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 579 |
+
|
| 580 |
+
|
| 581 |
+
## 2026-10-20 — RE-577 Ready weapon refill cadence and interaction re-entry (separate task commit)
|
| 582 |
+
|
| 583 |
+
51207..51364 refills ID27 magazine from configured capacity, handles mode-flag1/counter cadence, then clears state1 before optional button64 interaction re-entry and exits. 88 probes independently check packed-byte preservation, signed counter boundary, source stop/call priority and actual interaction child state after bit1 clears. Full suite: 827 tests pass. Report regenerates byte-identically (321281 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
|
@@ -772,3 +772,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 772 |
|
| 773 |
|
| 774 |
- [x] RE-576 Weapon continuation guards timer floors and cancellation ([report](research/QVM_WEAPON_GUARDS.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 772 |
|
| 773 |
|
| 774 |
- [x] RE-576 Weapon continuation guards timer floors and cancellation ([report](research/QVM_WEAPON_GUARDS.md)).
|
| 775 |
+
|
| 776 |
+
|
| 777 |
+
- [x] RE-577 Ready weapon refill cadence and interaction re-entry ([report](research/QVM_WEAPON_READY.md)).
|
docs/research/QVM_WEAPON_READY.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ready weapon refill cadence and interaction re-entry
|
| 2 |
+
|
| 3 |
+
RE-577. Reproduce with `python3 scripts/analyze_qvm_weapon_ready.py`; check with `python3 scripts/test_qvm_weapon_ready.py`. The [machine report](qvm-weapon-ready.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Ready-entry51207 first handles selectedID27 by replacing magazine bits8..15 with configured capacity&255, preserving ID/mode/reserve. Then nonpositive PS204 plus state32 plus mode flags bit1 resets weapon timer/state to0 and exits. This cadence predicate precedes state1 handling.
|
| 6 |
+
|
| 7 |
+
If state1 is set, it clears before testing button64. With button64, actual49918 interaction runs and observes bit1 already clear; without it no child runs. Both paths exit53046. Otherwise execution reaches51365. The interaction child still enforces its own weapon-state/timer/action guards and supplied native trace behavior; clearing bit1 does not imply successful interaction.
|
| 8 |
+
|
| 9 |
+
88 finite fixtures use explicitly supplied entry locals and mode flags to isolate these conditions; they do not run earlier prefix/timer guards. ID27 special refill is not generalized to other weapons. Remaining: actual reload completion and ammo-unit accounting, lowering/raising completion, and full parent composition across these boundaries.
|
| 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
|
@@ -333,3 +333,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 333 |
|
| 334 |
|
| 335 |
[RE-576: Weapon continuation guards timer floors and cancellation](QVM_WEAPON_GUARDS.md). Reproduce with `python3 scripts/analyze_qvm_weapon_guards.py`; check with `python3 scripts/test_qvm_weapon_guards.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 333 |
|
| 334 |
|
| 335 |
[RE-576: Weapon continuation guards timer floors and cancellation](QVM_WEAPON_GUARDS.md). Reproduce with `python3 scripts/analyze_qvm_weapon_guards.py`; check with `python3 scripts/test_qvm_weapon_guards.py`.
|
| 336 |
+
|
| 337 |
+
|
| 338 |
+
[RE-577: Ready weapon refill cadence and interaction re-entry](QVM_WEAPON_READY.md). Reproduce with `python3 scripts/analyze_qvm_weapon_ready.py`; check with `python3 scripts/test_qvm_weapon_ready.py`.
|
docs/research/qvm-weapon-ready.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_weapon_ready.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""51207..51364 magazine27 refill, mode cadence and action re-entry."""
|
| 3 |
+
import itertools
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from qvm_research_support import source,execute
|
| 6 |
+
from qvm_weapon_support import weapon_seed,weapon_state
|
| 7 |
+
from analyze_qvm_weapon_prefix import LOCAL
|
| 8 |
+
from analyze_qvm_interaction_request import interaction
|
| 9 |
+
from analyze_qvm_acceleration import PS,FRAME
|
| 10 |
+
from analyze_qvm import write_json
|
| 11 |
+
|
| 12 |
+
def ready(ins,m,cmd=(0,0,0),contents=33554432):
|
| 13 |
+
initial=weapon_state(m);ident=initial['packed']&255;mode=(initial['packed']>>16)&255;m[LOCAL+12]=ident;m[LOCAL+16]=mode;cfg={'capacity':m[4052+432*ident],'mode_flags':m[4244+432*ident+52*mode+4]}
|
| 14 |
+
def action(i,m,a,c):m,r=interaction(i,m,contents,c);return m,c,0,r
|
| 15 |
+
m,c,r=execute(ins,51207,53046,m,cmd,LOCAL,{49918:action},boundaries=[51365])
|
| 16 |
+
return m,{'initial':initial,'buttons':m[FRAME+20],'config':cfg,'contents':contents,'execution':r,'final':weapon_state(m)}
|
| 17 |
+
|
| 18 |
+
def main():
|
| 19 |
+
q,raw,h,ins=source();rows=[]
|
| 20 |
+
for ident,mag,count,flags,state in itertools.product([1,22,27],[0,1],[-1,0,1],[0,1],[0,32]):
|
| 21 |
+
m=weapon_seed(raw,h);m.update({PS+312:ident|(mag<<8)|(3<<24),PS+204:count,PS+220:state,FRAME+20:0,4244+432*ident+4:flags});rows.append(ready(ins,m)[1])
|
| 22 |
+
for state,button,contents,ws in itertools.product([1,1|128],[0,64],[0,33554432],[0,1]):
|
| 23 |
+
m=weapon_seed(raw,h);m.update({PS+312:22,PS+220:state,PS+148:ws,FRAME+20:button});rows.append(ready(ins,m,contents=contents)[1])
|
| 24 |
+
write_json(Path('docs/research/qvm-weapon-ready.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Finite51207..51364 with supplied ready-entry locals, mode flags and trace replies. ID27 refill is not general reload behavior. Stops51365 or actual exit53046; firing/native action legality unverified.'})
|
| 25 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_weapon_ready.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest,copy
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_torso_selector import signed
|
| 4 |
+
from test_qvm_main_consumers import interaction_state
|
| 5 |
+
|
| 6 |
+
def ready_state(p):
|
| 7 |
+
a=copy.deepcopy(p['initial']);stop=51365
|
| 8 |
+
if a['packed']&255==27:a['packed']=(a['packed']&~65280)|((p['config']['capacity']&255)<<8);a['weapons'][a['slot']]=a['packed']
|
| 9 |
+
if signed(a['counter204'])<=0 and a['state220']&32 and p['config']['mode_flags']&1:a['weapon_timer']=a['weapon_state']=0;return a,53046
|
| 10 |
+
if a['state220']&1:
|
| 11 |
+
a['state220']&=~1;stop=53046
|
| 12 |
+
if p['buttons']&64:
|
| 13 |
+
child=p['execution']['children'][0]['effect']
|
| 14 |
+
for k,v in child['initial'].items():assert a[k]==v
|
| 15 |
+
a.update(interaction_state(child))
|
| 16 |
+
return a,stop
|
| 17 |
+
class WeaponReadyTests(unittest.TestCase):
|
| 18 |
+
@classmethod
|
| 19 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-weapon-ready.json').read_text())
|
| 20 |
+
def test_exact_refill_cadence_and_action_state(self):
|
| 21 |
+
self.assertEqual(len(self.r['probes']),88)
|
| 22 |
+
for p in self.r['probes']:a,stop=ready_state(p);self.assertEqual(p['final'],a);self.assertEqual(p['execution']['stop'],stop)
|
| 23 |
+
def test_actual_interaction_reentry_only_when_button64(self):
|
| 24 |
+
for p in self.r['probes']:
|
| 25 |
+
a=p['initial'];cadence=signed(a['counter204'])<=0 and a['state220']&32 and p['config']['mode_flags']&1;self.assertEqual([c['target'] for c in p['execution']['calls']],[49918] if not cadence and a['state220']&1 and p['buttons']&64 else [])
|
| 26 |
+
def test_magazine_refill_preserves_reserve_mode_and_id(self):
|
| 27 |
+
for p in self.r['probes']:
|
| 28 |
+
a=p['initial'];b=p['final'];self.assertEqual(a['packed']&~65280,b['packed']&~65280)
|
| 29 |
+
if a['packed']&255!=27:self.assertEqual(a['packed'],b['packed'])
|
| 30 |
+
def test_state1_clears_before_child_guard(self):
|
| 31 |
+
rows=[p for p in self.r['probes'] if p['execution']['children']];self.assertTrue(rows)
|
| 32 |
+
for p in rows:self.assertFalse(p['execution']['children'][0]['effect']['initial']['state220']&1)
|
| 33 |
+
if __name__=='__main__':unittest.main()
|