qvm: firing animation priority
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_FIRE_POSE_PRIORITY.md +11 -0
- docs/research/README.md +3 -0
- docs/research/qvm-fire-pose-priority.json +0 -0
- scripts/analyze_qvm_fire_pose_priority.py +21 -0
- scripts/test_qvm_fire_pose_priority.py +35 -0
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()
|