nmarshall commited on
Commit
33aafbd
·
1 Parent(s): 190404e

qvm: firing animation priority

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -439,3 +439,6 @@ Research progress: RE-583 [report](research/QVM_FIRE_AVAILABILITY.md); remaining
439
 
440
 
441
  Research progress: RE-584 [report](research/QVM_FIRE_AMMO.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
439
 
440
 
441
  Research progress: RE-584 [report](research/QVM_FIRE_AMMO.md); remaining native/content/runtime/platform scope stays open.
442
+
443
+
444
+ Research progress: RE-585 [report](research/QVM_FIRE_POSE_PRIORITY.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -797,3 +797,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
797
 
798
 
799
  **RE-584 — Firing magazine debit and preserved mode flag:** 52154..52252 decrements only a nonzero selected magazine byte unless preserved local-mode flags4 suppress it; ID/mode/reserve and other slots remain unchanged. [Evidence](research/QVM_FIRE_AMMO.md).
 
 
 
 
797
 
798
 
799
  **RE-584 — Firing magazine debit and preserved mode flag:** 52154..52252 decrements only a nonzero selected magazine byte unless preserved local-mode flags4 suppress it; ID/mode/reserve and other slots remain unchanged. [Evidence](research/QVM_FIRE_AMMO.md).
800
+
801
+
802
+ **RE-585 — Firing animation priority before class dispatch:** 52253..52411 prioritizes masked legs25 over weaponIDs4/24, then action buttons8192/16384; resolved routes select conditional53/64/49 or timed61/51 and skip the class continuation. [Evidence](research/QVM_FIRE_POSE_PRIORITY.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -755,3 +755,6 @@ Research progress: RE-583 [report](research/QVM_FIRE_AVAILABILITY.md); remaining
755
 
756
 
757
  Research progress: RE-584 [report](research/QVM_FIRE_AMMO.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
755
 
756
 
757
  Research progress: RE-584 [report](research/QVM_FIRE_AMMO.md); remaining native/content/runtime/platform scope stays open.
758
+
759
+
760
+ Research progress: RE-585 [report](research/QVM_FIRE_POSE_PRIORITY.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -613,3 +613,8 @@ RE-580 additional regression: all19 reports from RE-560–569 and RE-571–579 r
613
  ## 2026-10-20 — RE-584 Firing magazine debit and preserved mode flag (separate task commit)
614
 
615
  52154..52252 decrements only a nonzero selected magazine byte unless preserved local-mode flags4 suppress it; ID/mode/reserve and other slots remain unchanged. 100 probes check slot0/15, magazines0/1/2/255, IDs1/22/27 and deliberately differing local versus packed modes with independent full-state oracles. Full suite: 851 tests pass. Report regenerates byte-identically (333406 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
613
  ## 2026-10-20 — RE-584 Firing magazine debit and preserved mode flag (separate task commit)
614
 
615
  52154..52252 decrements only a nonzero selected magazine byte unless preserved local-mode flags4 suppress it; ID/mode/reserve and other slots remain unchanged. 100 probes check slot0/15, magazines0/1/2/255, IDs1/22/27 and deliberately differing local versus packed modes with independent full-state oracles. Full suite: 851 tests pass. Report regenerates byte-identically (333406 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
616
+
617
+
618
+ ## 2026-10-20 — RE-585 Firing animation priority before class dispatch (separate task commit)
619
+
620
+ 52253..52411 prioritizes masked legs25 over weaponIDs4/24, then action buttons8192/16384; resolved routes select conditional53/64/49 or timed61/51 and skip the class continuation. 148 probes independently check toggle-bit aliases, priority conflicts, movement-leg alternatives, positive timers, kind3 and supplied duration0/−1 effects with actual animation children. Full suite: 855 tests pass. Report regenerates byte-identically (980744 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
@@ -796,3 +796,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
796
 
797
 
798
  - [x] RE-584 Firing magazine debit and preserved mode flag ([report](research/QVM_FIRE_AMMO.md)).
 
 
 
 
796
 
797
 
798
  - [x] RE-584 Firing magazine debit and preserved mode flag ([report](research/QVM_FIRE_AMMO.md)).
799
+
800
+
801
+ - [x] RE-585 Firing animation priority before class dispatch ([report](research/QVM_FIRE_POSE_PRIORITY.md)).
docs/research/QVM_FIRE_POSE_PRIORITY.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Firing animation priority before class dispatch
2
+
3
+ RE-585. Reproduce with `python3 scripts/analyze_qvm_fire_pose_priority.py`; check with `python3 scripts/test_qvm_fire_pose_priority.py`. The [machine report](qvm-fire-pose-priority.json) retains source identity and bounded fixtures.
4
+
5
+ Masked legs25 chooses conditional torso53 when selected weapon class0, otherwise64. For other legs, IDs4/24 choose timed61 on base legs38/43/24, otherwise51, before any action-button check. Remaining weapons with button8192/16384 request conditional49. All these paths jump52730. Unmatched input stops at52412 before class/tag dispatch.
6
+
7
+ Actual39482/39552 helpers enforce their different contracts: conditional animation retains a positive timer/current masked match, while timed animation loads a supplied duration and retriggers when kind permits.148 finite fixtures include aliases153, type3 and duration0/−1. No ammunition, counter, queue or request260/264 field changes occur here.
8
+
9
+ This task establishes priority only; the52412 class/tag continuation and subsequent published firing request are intentionally the next tasks. Numeric requests are not yet matched to skeletal assets or original playback.
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
@@ -356,3 +356,6 @@ The extension collector adds five focused tests for native tail calls, command-r
356
 
357
 
358
  [RE-584: Firing magazine debit and preserved mode flag](QVM_FIRE_AMMO.md). Reproduce with `python3 scripts/analyze_qvm_fire_ammo.py`; check with `python3 scripts/test_qvm_fire_ammo.py`.
 
 
 
 
356
 
357
 
358
  [RE-584: Firing magazine debit and preserved mode flag](QVM_FIRE_AMMO.md). Reproduce with `python3 scripts/analyze_qvm_fire_ammo.py`; check with `python3 scripts/test_qvm_fire_ammo.py`.
359
+
360
+
361
+ [RE-585: Firing animation priority before class dispatch](QVM_FIRE_POSE_PRIORITY.md). Reproduce with `python3 scripts/analyze_qvm_fire_pose_priority.py`; check with `python3 scripts/test_qvm_fire_pose_priority.py`.
docs/research/qvm-fire-pose-priority.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_fire_pose_priority.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """52253..52411 firing animation priority before class/tag continuation."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source
6
+ from qvm_firing_support import seed,segment
7
+ from analyze_qvm_animation_contacts import TABLE
8
+ from analyze_qvm_acceleration import PS,FRAME
9
+ from analyze_qvm import write_json
10
+
11
+ def priority(ins,m,cmd=(0,0,0),preserve_locals=False):
12
+ durations={str(r):m[TABLE+m[FRAME+248]*2560+r*32+28] for r in [51,61]};m,p=segment(ins,m,52253,[52412,52730],cmd,preserve_locals);p['durations']=durations;return m,p
13
+
14
+ def main():
15
+ q,raw,h,ins=source();rows=[]
16
+ for ident,legs,button,timer in itertools.product([1,4,22,24],[25,153,38,43,24,41],[0,8192,16384],[0,1]):
17
+ m=seed(raw,h,ident);m.update({PS+76:legs,PS+80:timer,FRAME+20:button});rows.append(priority(ins,m)[1])
18
+ for changes in [{PS+4:3},{TABLE+61*32+28:0},{TABLE+61*32+28:-1},{PS+84:189}]:
19
+ m=seed(raw,h,4);m[PS+76]=38;m.update(changes);rows.append(priority(ins,m)[1])
20
+ write_json(Path('docs/research/qvm-fire-pose-priority.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'52253..52411 priority routes only; class continuation stops52412, resolved routes stop52730. Supplied animation duration321 except marked0/−1; actual helpers, no skeletal playback/request publication.'})
21
+ if __name__=='__main__':main()
scripts/test_qvm_fire_pose_priority.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest,copy
2
+ from pathlib import Path
3
+ from test_qvm_torso_selector import signed
4
+
5
+ def pose_choice(p):
6
+ a=p['initial'];legs=a['legs']&~128;ident=a['packed']&255
7
+ if legs==25:return 39482,53 if p['config']['class']==0 else 64
8
+ if ident in [4,24]:return 39552,61 if legs in [38,43,24] else 51
9
+ if p['buttons']&(8192|16384):return 39482,49
10
+ return None,None
11
+
12
+ def pose_apply(p,choice):
13
+ a=copy.deepcopy(p['initial']);entry,r=choice
14
+ if entry==39552:
15
+ a['torso_timer']=p['durations'][str(r)]&0xffffffff
16
+ if p['kind']<3:a['torso']=((a['torso']&128)^128)|r
17
+ elif entry==39482 and p['kind']<3 and signed(a['torso_timer'])<=0 and a['torso']!=r and a['torso']&~128!=r:a['torso']=((a['torso']&128)^128)|r
18
+ return a
19
+ class FirePosePriorityTests(unittest.TestCase):
20
+ @classmethod
21
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-fire-pose-priority.json').read_text())
22
+ def test_priority_and_exact_animation_state(self):
23
+ self.assertEqual(len(self.r['probes']),148)
24
+ for p in self.r['probes']:self.assertEqual(p['final'],pose_apply(p,pose_choice(p)));self.assertEqual(p['execution']['stop'],52730 if pose_choice(p)[0] else 52412)
25
+ def test_actual_helper_and_request(self):
26
+ for p in self.r['probes']:
27
+ e,r=pose_choice(p);self.assertEqual([(c['target'],c['args']['8']) for c in p['execution']['calls']],[(e,r)] if e else [])
28
+ def test_no_ammo_counter_or_request_publication(self):
29
+ for p in self.r['probes']:
30
+ for k in ['weapons','request260','request264','counter204','resource','queue']:self.assertEqual(p['initial'][k],p['final'][k])
31
+ def test_masked_legs_and_precedence(self):
32
+ for p in self.r['probes']:
33
+ if p['initial']['legs']&~128==25:self.assertEqual(pose_choice(p)[0],39482)
34
+ elif p['initial']['packed']&255 in [4,24]:self.assertEqual(pose_choice(p)[0],39552)
35
+ if __name__=='__main__':unittest.main()