nmarshall commited on
Commit
482cba7
·
1 Parent(s): 0e8b282

qvm: selection caller handoff

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -412,3 +412,6 @@ Research progress: RE-573 [report](research/QVM_WEAPON_COMPLETE.md); remaining n
412
 
413
 
414
  Research progress: RE-574 [report](research/QVM_SPECIAL_QUERY.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
412
 
413
 
414
  Research progress: RE-574 [report](research/QVM_SPECIAL_QUERY.md); remaining native/content/runtime/platform scope stays open.
415
+
416
+
417
+ Research progress: RE-575 [report](research/QVM_WEAPON_SELECTION_CALLER.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -770,3 +770,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
770
 
771
 
772
  **RE-574 — Helper50525 native trace gates and event contract:** 50525 clears PS12 bit8192 on low up input or, after ordered gates, traces30 units ahead from originZ+30; contents33554432 sets state4096 and queues14 with native record+52 as parameter. [Evidence](research/QVM_SPECIAL_QUERY.md).
 
 
 
 
770
 
771
 
772
  **RE-574 — Helper50525 native trace gates and event contract:** 50525 clears PS12 bit8192 on low up input or, after ordered gates, traces30 units ahead from originZ+30; contents33554432 sets state4096 and queues14 with native record+52 as parameter. [Evidence](research/QVM_SPECIAL_QUERY.md).
773
+
774
+
775
+ **RE-575 — Weapon prefix to actual selection handoff:** 50746 re-decodes the current ID after mode processing, requests48798 only when it differs from command byte24, and suppresses that request for currentID27 while its decremented timer is positive. [Evidence](research/QVM_WEAPON_SELECTION_CALLER.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -726,3 +726,6 @@ Research progress: RE-573 [report](research/QVM_WEAPON_COMPLETE.md); remaining n
726
 
727
 
728
  Research progress: RE-574 [report](research/QVM_SPECIAL_QUERY.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
726
 
727
 
728
  Research progress: RE-574 [report](research/QVM_SPECIAL_QUERY.md); remaining native/content/runtime/platform scope stays open.
729
+
730
+
731
+ Research progress: RE-575 [report](research/QVM_WEAPON_SELECTION_CALLER.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -566,3 +566,8 @@ Actual54444 reload/interaction order exposes timer interference before the weapo
566
  ## 2026-10-20 — RE-574 Helper50525 native trace gates and event contract (separate task commit)
567
 
568
  50525 clears PS12 bit8192 on low up input or, after ordered gates, traces30 units ahead from originZ+30; contents33554432 sets state4096 and queues14 with native record+52 as parameter. 80 fixtures check level/type/input priority, strict vertical speed, suppression fields, native request geometry/ABI and signed parameter preservation; direct main caller54020 is inventoried. Full suite: 815 tests pass. Report regenerates byte-identically (271030 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
566
  ## 2026-10-20 — RE-574 Helper50525 native trace gates and event contract (separate task commit)
567
 
568
  50525 clears PS12 bit8192 on low up input or, after ordered gates, traces30 units ahead from originZ+30; contents33554432 sets state4096 and queues14 with native record+52 as parameter. 80 fixtures check level/type/input priority, strict vertical speed, suppression fields, native request geometry/ABI and signed parameter preservation; direct main caller54020 is inventoried. Full suite: 815 tests pass. Report regenerates byte-identically (271030 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
569
+
570
+
571
+ ## 2026-10-20 — RE-575 Weapon prefix to actual selection handoff (separate task commit)
572
+
573
+ 50746 re-decodes the current ID after mode processing, requests48798 only when it differs from command byte24, and suppresses that request for currentID27 while its decremented timer is positive. 41 source-order compositions check prefix oracles, equality and ID27 timer16/17 boundary, present/missing requested slot, helper rejection and actual early exits. Full suite: 819 tests pass. Report regenerates byte-identically (1148636 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
@@ -766,3 +766,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
766
 
767
 
768
  - [x] RE-574 Helper50525 native trace gates and event contract ([report](research/QVM_SPECIAL_QUERY.md)).
 
 
 
 
766
 
767
 
768
  - [x] RE-574 Helper50525 native trace gates and event contract ([report](research/QVM_SPECIAL_QUERY.md)).
769
+
770
+
771
+ - [x] RE-575 Weapon prefix to actual selection handoff ([report](research/QVM_WEAPON_SELECTION_CALLER.md)).
docs/research/QVM_WEAPON_SELECTION_CALLER.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Weapon prefix to actual selection handoff
2
+
3
+ RE-575. Reproduce with `python3 scripts/analyze_qvm_weapon_selection_caller.py`; check with `python3 scripts/test_qvm_weapon_selection_caller.py`. The [machine report](qvm-weapon-selection-caller.json) retains source identity and bounded fixtures.
4
+
5
+ Actual50747..50922 now composes the recovered weapon prefix and selection request in the same parent local frame. After49327 it re-decodes the selected low-byte ID. If it equals the command weapon byte, selection is skipped. Otherwise currentID27 with PS44>0 skips the request; all other mismatches call actual48798. The child observes the already-decremented timer and live latch/mode/resource state.
6
+
7
+ 41 fixtures cover current IDs0/1/22/27, command1/22/27 and timers0/16/17 with dt16, plus death/flag early exits and rejected/missing requests. At timer16, ID27 becomes0 and can request selection; at17 it remains1 and suppresses it. A successful request starts state2 but leaves active slot unchanged.
8
+
9
+ The entire parent stops at50923 before the next guards, or at its actual early exit53046. This does not yet complete transition lowering/raising, reload or firing. Reports retain actual nested child handoffs and explicit byte24 inputs without executing original/native game code.
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
@@ -327,3 +327,6 @@ The extension collector adds five focused tests for native tail calls, command-r
327
 
328
 
329
  [RE-574: Helper50525 native trace gates and event contract](QVM_SPECIAL_QUERY.md). Reproduce with `python3 scripts/analyze_qvm_special_query.py`; check with `python3 scripts/test_qvm_special_query.py`.
 
 
 
 
327
 
328
 
329
  [RE-574: Helper50525 native trace gates and event contract](QVM_SPECIAL_QUERY.md). Reproduce with `python3 scripts/analyze_qvm_special_query.py`; check with `python3 scripts/test_qvm_special_query.py`.
330
+
331
+
332
+ [RE-575: Weapon prefix to actual selection handoff](QVM_WEAPON_SELECTION_CALLER.md). Reproduce with `python3 scripts/analyze_qvm_weapon_selection_caller.py`; check with `python3 scripts/test_qvm_weapon_selection_caller.py`.
docs/research/qvm-weapon-selection-caller.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_weapon_selection_caller.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """50746 prefix through actual weapon-selection handoff, stopping at50923."""
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 weapon_prefix,LOCAL
8
+ from analyze_qvm_weapon_select import select
9
+ from analyze_qvm_acceleration import PS,FRAME
10
+ from analyze_qvm import write_json
11
+
12
+ def selection_caller(ins,m,cmd=(0,0,0)):
13
+ initial=weapon_state(m);m,p=weapon_prefix(ins,m,cmd);before=weapon_state(m);tail=None
14
+ def selected(i,m,a,c):m,r=select(i,m,a[8],c);return m,c,0,r
15
+ if p['execution']['stop']==50872:m,c,tail=execute(ins,50872,53046,m,cmd,LOCAL,{48798:selected},boundaries=[50923],byte_inputs={FRAME+24:m[FRAME+24]&255})
16
+ return m,{'initial':initial,'prefix':p,'before_selection':before,'selection_execution':tail,'stop':50923 if tail else 53046,'final':weapon_state(m)}
17
+
18
+ def main():
19
+ q,raw,h,ins=source();rows=[]
20
+ for old,desired,timer,present in itertools.product([0,1,22,27],[1,22,27],[0,16,17],[True]):
21
+ m=weapon_seed(raw,h,desired=desired);m.update({PS+312:old|(2<<8),PS+44:timer,FRAME+20:0,35023932:16})
22
+ if present:m[PS+312+15*4]=desired
23
+ rows.append(selection_caller(ins,m)[1])
24
+ for changes in [{PS+12:256},{PS+208:0},{PS+148:2},{PS+220:1},{PS+316:0}]:
25
+ m=weapon_seed(raw,h,desired=22);m.update({PS+312:1,PS+316:22,FRAME+20:0});m.update(changes);rows.append(selection_caller(ins,m)[1])
26
+ write_json(Path('docs/research/qvm-weapon-selection-caller.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Actual50747..50922 with recovered prefix and48798; early exit53046 honored. Parent remains stopped before50923 guards and firing/reload body. No assumed weapon completion or native effects.'})
27
+ if __name__=='__main__':main()
scripts/test_qvm_weapon_selection_caller.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest
2
+ from pathlib import Path
3
+ from test_qvm_main_consumers import weapon_state as prefix_state
4
+ from test_qvm_weapon_select import select_state
5
+ from test_qvm_torso_selector import signed
6
+ class WeaponSelectionCallerTests(unittest.TestCase):
7
+ @classmethod
8
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-weapon-selection-caller.json').read_text())
9
+ def test_prefix_composition_regression(self):
10
+ self.assertEqual(len(self.r['probes']),41)
11
+ for p in self.r['probes']:
12
+ self.assertEqual(p['prefix']['final'],prefix_state(p['prefix']))
13
+ for key,v in p['prefix']['final'].items():self.assertEqual(p['before_selection'][key],v)
14
+ def test_source_id_and_timer_guard(self):
15
+ for p in self.r['probes']:
16
+ a=p['before_selection'];active=p['selection_execution'] is not None;called=active and a['packed']&255!=a['command_weapon'] and not(a['packed']&255==27 and signed(a['weapon_timer'])>0);calls=p['selection_execution']['calls'] if active else [];self.assertEqual([c['target'] for c in calls],[48798] if called else [])
17
+ def test_exact_actual_child_state_handoff(self):
18
+ for p in self.r['probes']:
19
+ tail=p['selection_execution']
20
+ if tail and tail['children']:
21
+ child=tail['children'][0]['effect'];self.assertEqual(child['initial'],p['before_selection']);self.assertEqual(child['requested'],p['initial']['command_weapon']);self.assertEqual(child['final'],select_state(child));self.assertEqual(p['final'],child['final'])
22
+ else:self.assertEqual(p['final'],p['before_selection'])
23
+ def test_dispatch_boundaries_and_timer_expiry(self):
24
+ self.assertTrue(any(p['initial']['packed']&255==27 and p['initial']['weapon_timer']==16 and p['selection_execution']['calls'] for p in self.r['probes']))
25
+ for p in self.r['probes']:self.assertEqual(p['stop'],50923 if p['selection_execution'] else 53046)
26
+ if __name__=='__main__':unittest.main()