qvm: torso selection
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_TORSO_SELECTOR.md +11 -0
- docs/research/README.md +3 -0
- docs/research/qvm-torso-selector.json +0 -0
- scripts/analyze_qvm_torso_selector.py +26 -0
- scripts/qvm_suffix_support.py +8 -0
- scripts/test_qvm_torso_selector.py +28 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -376,3 +376,6 @@ Research progress: RE-560 [report](research/QVM_FREEFLIGHT.md); remaining native
|
|
| 376 |
|
| 377 |
|
| 378 |
Research progress: RE-561 [report](research/QVM_WATER_EVENTS.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 376 |
|
| 377 |
|
| 378 |
Research progress: RE-561 [report](research/QVM_WATER_EVENTS.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.
|
docs/FINDINGS.md
CHANGED
|
@@ -734,3 +734,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 734 |
|
| 735 |
|
| 736 |
**RE-561 — Water transition event matrix and queue composition:** 48716 independently emits entry100/101, exit6, full-submersion7 and resurfacing8. Entry101 requires vertical velocity strictly below−500;0→3 and3→0 each enqueue two ordered events. [Evidence](research/QVM_WATER_EVENTS.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 734 |
|
| 735 |
|
| 736 |
**RE-561 — Water transition event matrix and queue composition:** 48716 independently emits entry100/101, exit6, full-submersion7 and resurfacing8. Entry101 requires vertical velocity strictly below−500;0→3 and3→0 each enqueue two ordered events. [Evidence](research/QVM_WATER_EVENTS.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).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -688,3 +688,6 @@ Research progress: RE-560 [report](research/QVM_FREEFLIGHT.md); remaining native
|
|
| 688 |
|
| 689 |
|
| 690 |
Research progress: RE-561 [report](research/QVM_WATER_EVENTS.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 688 |
|
| 689 |
|
| 690 |
Research progress: RE-561 [report](research/QVM_WATER_EVENTS.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.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -506,3 +506,8 @@ RE-549–558 each has its own code/tests/report/documentation commit. All759 tes
|
|
| 506 |
## 2026-10-19 — RE-561 Water transition event matrix and queue composition (separate task commit)
|
| 507 |
|
| 508 |
48716 independently emits entry100/101, exit6, full-submersion7 and resurfacing8. Entry101 requires vertical velocity strictly below−500;0→3 and3→0 each enqueue two ordered events. 144 fixtures cover all16 legal level pairs, three velocity boundaries and sequence0/1/unsigned wrap; independent queue and mutation oracles pass. Full suite: 767 tests pass. Report regenerates byte-identically (588597 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
## 2026-10-19 — RE-561 Water transition event matrix and queue composition (separate task commit)
|
| 507 |
|
| 508 |
48716 independently emits entry100/101, exit6, full-submersion7 and resurfacing8. Entry101 requires vertical velocity strictly below−500;0→3 and3→0 each enqueue two ordered events. 144 fixtures cover all16 legal level pairs, three velocity boundaries and sequence0/1/unsigned wrap; independent queue and mutation oracles pass. Full suite: 767 tests pass. Report regenerates byte-identically (588597 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 509 |
+
|
| 510 |
+
|
| 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.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -728,3 +728,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 728 |
|
| 729 |
|
| 730 |
- [x] RE-561 Water transition event matrix and queue composition ([report](research/QVM_WATER_EVENTS.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 728 |
|
| 729 |
|
| 730 |
- [x] RE-561 Water transition event matrix and queue composition ([report](research/QVM_WATER_EVENTS.md)).
|
| 731 |
+
|
| 732 |
+
|
| 733 |
+
- [x] RE-562 Torso selector priority and weapon class dispatch ([report](research/QVM_TORSO_SELECTOR.md)).
|
docs/research/QVM_TORSO_SELECTOR.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Torso selector priority and weapon class dispatch
|
| 2 |
+
|
| 3 |
+
RE-562. Reproduce with `python3 scripts/analyze_qvm_torso_selector.py`; check with `python3 scripts/test_qvm_torso_selector.py`. The [machine report](qvm-torso-selector.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Complete49117 is interpreted through49325 with actual39482→39338 animation writes. A nonzero PS148 returns immediately. Base legs25 requests torso64 even when buttons8192/16384 are set; those buttons otherwise request50. The selected packed weapon low byte indexes432-byte records at4032(class)/4196(tag). The source jump table21256..21280 maps classes0/1/5 to67,2 to66,3 to78,4 to tag22?66:72,6 to tag25?66:65; values outside0..6 default67.
|
| 6 |
+
|
| 7 |
+
The image table loader retains initialized words, distinct from explicitly marked synthetic class/tag overrides. Animation child gates preserve torso when its timer is positive, kind is3+, or the masked current torso already matches the request. Toggle bit128 follows the recovered helper.93 fixtures include every initialized weapon index0..27; index0 is a source-defined empty record, not a claim of selectable gameplay.
|
| 8 |
+
|
| 9 |
+
Remaining: map numeric requests to animation assets and actual weapon identity, validate live table population and invoke this consumer in source-order main suffix integration. Native rendering and Rust animation retargeting remain open.
|
| 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
|
@@ -289,3 +289,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 289 |
|
| 290 |
|
| 291 |
[RE-561: Water transition event matrix and queue composition](QVM_WATER_EVENTS.md). Reproduce with `python3 scripts/analyze_qvm_water_events.py`; check with `python3 scripts/test_qvm_water_events.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
|
| 290 |
|
| 291 |
[RE-561: Water transition event matrix and queue composition](QVM_WATER_EVENTS.md). Reproduce with `python3 scripts/analyze_qvm_water_events.py`; check with `python3 scripts/test_qvm_water_events.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`.
|
docs/research/qvm-torso-selector.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_torso_selector.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""49117 state/button/legs priority and file-backed class jump dispatch."""
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from qvm_research_support import source,execute
|
| 5 |
+
from qvm_suffix_support import seed,state,handlers,weapon_config,weapon_words
|
| 6 |
+
from analyze_qvm_acceleration import PS,FRAME
|
| 7 |
+
from analyze_qvm import write_json
|
| 8 |
+
LOCAL=0x6c000000
|
| 9 |
+
|
| 10 |
+
def torso(ins,m,cmd=(0,0,0)):
|
| 11 |
+
before=state(m);ident=m[PS+312+4*m[PS+144]]&255;cfg=weapon_words(m,ident);buttons=m[FRAME+20]
|
| 12 |
+
m,c,r=execute(ins,49118,49325,m,cmd,LOCAL,handlers())
|
| 13 |
+
return m,{'initial':before,'buttons':buttons,'config':cfg,'execution':r,'final':state(m)}
|
| 14 |
+
|
| 15 |
+
def main():
|
| 16 |
+
q,raw,h,ins=source();rows=[]
|
| 17 |
+
for ident in range(28):
|
| 18 |
+
for timer in [0,1]:
|
| 19 |
+
m=weapon_config(seed(raw,h),raw,h);m.update({PS+312:ident,PS+80:timer});rows.append(torso(ins,m)[1])
|
| 20 |
+
for klass in range(-1,8):
|
| 21 |
+
for tag in [22,25,99]:
|
| 22 |
+
m=weapon_config(seed(raw,h),raw,h);m.update({PS+312:1,4032+432:klass,4196+432:tag});p=torso(ins,m)[1];p['supplied_config_override']={'class':klass,'tag':tag};rows.append(p)
|
| 23 |
+
for changes in [{PS+148:1},{PS+76:25},{PS+76:153},{FRAME+20:8192},{FRAME+20:16384},{PS+76:25,FRAME+20:8192},{PS+4:3},{PS+84:67},{PS+84:195},{PS+80:-1}]:
|
| 24 |
+
m=weapon_config(seed(raw,h),raw,h);m.update(changes);p=torso(ins,m)[1];p['supplied_changes']={str(k):v for k,v in changes.items()};p['kind']=m[PS+4];rows.append(p)
|
| 25 |
+
write_json(Path('docs/research/qvm-torso-selector.json'),{'source':q['source'],'sha256':q['sha256'],'jump_table':{str(a):weapon_config({},raw,h)[a] for a in range(21256,21284,4)},'probes':rows,'limits':'Complete finite49117 with actual39482/39338. File-backed weapon class/tag/jump words and explicitly marked synthetic overrides; no live weapon table or skeletal playback validation.'})
|
| 26 |
+
if __name__=='__main__':main()
|
scripts/qvm_suffix_support.py
CHANGED
|
@@ -23,3 +23,11 @@ def handlers():
|
|
| 23 |
def apply(i,m,a,c):m,r=event(i,m,entry,a);return m,c,0,r
|
| 24 |
return apply
|
| 25 |
return {**{e:animation(e) for e in [39338,39383,39439,39482,39525,39552]},**{e:queued(e) for e in [39238,45887,29913]}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
def apply(i,m,a,c):m,r=event(i,m,entry,a);return m,c,0,r
|
| 24 |
return apply
|
| 25 |
return {**{e:animation(e) for e in [39338,39383,39439,39482,39525,39552]},**{e:queued(e) for e in [39238,45887,29913]}}
|
| 26 |
+
|
| 27 |
+
def weapon_config(m,raw,h):
|
| 28 |
+
"""Initialized image words only; no claim these equal live native tables."""
|
| 29 |
+
from qvm_research_support import constants
|
| 30 |
+
m.update(constants(raw,h,range(4000,16400,4)));m.update(constants(raw,h,range(21236,21284,4)));return m
|
| 31 |
+
|
| 32 |
+
def weapon_words(m,ident):
|
| 33 |
+
return {k:m[a+432*ident]&0xffffffff for k,a in [('class',4032),('capacity',4052),('reload',4056),('reload_extra',4060),('tag',4196)]}
|
scripts/test_qvm_torso_selector.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest,copy
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
def signed(v):return v if v<0x80000000 else v-0x100000000
|
| 5 |
+
|
| 6 |
+
def request(p):
|
| 7 |
+
a=p['initial'];klass=signed(p['config']['class']);tag=p['config']['tag']
|
| 8 |
+
if a['weapon_state']:return None
|
| 9 |
+
if a['legs']&~128==25:return 64
|
| 10 |
+
if p['buttons']&(8192|16384):return 50
|
| 11 |
+
return {0:67,1:67,2:66,3:78,4:66 if tag==22 else 72,5:67,6:66 if tag==25 else 65}.get(klass,67)
|
| 12 |
+
class TorsoSelectorTests(unittest.TestCase):
|
| 13 |
+
@classmethod
|
| 14 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-torso-selector.json').read_text())
|
| 15 |
+
def test_source_table_targets(self):self.assertEqual(list(self.r['jump_table'].values()),[49217,49224,49231,49238,49245,49217,49286])
|
| 16 |
+
def test_all_weapon_classes_tags_and_guards(self):
|
| 17 |
+
self.assertEqual(len(self.r['probes']),93)
|
| 18 |
+
for p in self.r['probes']:
|
| 19 |
+
r=request(p);self.assertEqual([c['args']['8'] for c in p['execution']['calls']],[] if r is None else [r])
|
| 20 |
+
def test_animation_helper_exact_effect(self):
|
| 21 |
+
for p in self.r['probes']:
|
| 22 |
+
a=copy.deepcopy(p['initial']);r=request(p)
|
| 23 |
+
if r is not None and p.get('kind',0)<3 and signed(a['torso_timer'])<=0 and a['torso']&~128!=r:a['torso']=((a['torso']&128)^128)|r
|
| 24 |
+
self.assertEqual(p['final'],a)
|
| 25 |
+
def test_body_retains_packed_weapon_inventory_and_queue(self):
|
| 26 |
+
for p in self.r['probes']:
|
| 27 |
+
for key in ['packed','inventory','queue','weapon_timer','legs','state220']:self.assertEqual(p['initial'][key],p['final'][key])
|
| 28 |
+
if __name__=='__main__':unittest.main()
|