qvm: hitscan spread parameters
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_SPREAD_PARAMETERS.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-spread-parameters.json +0 -0
- scripts/analyze_qvm_spread_parameters.py +24 -0
- scripts/test_qvm_spread_parameters.py +26 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -505,3 +505,6 @@ Research progress: RE-607 [report](research/QVM_ALLOCATED_EVENT.md); remaining n
|
|
| 505 |
|
| 506 |
|
| 507 |
Research progress: RE-608 [report](research/QVM_ALLOCATED_GRENADE.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
|
| 506 |
|
| 507 |
Research progress: RE-608 [report](research/QVM_ALLOCATED_GRENADE.md); remaining native/content/runtime/platform scope stays open.
|
| 508 |
+
|
| 509 |
+
|
| 510 |
+
Research progress: RE-609 [report](research/QVM_SPREAD_PARAMETERS.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -863,3 +863,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 863 |
|
| 864 |
|
| 865 |
**RE-608 — Grenade constructor with actual entity allocation:** 285971 now composes recovered277165/277125 before grenade descriptor and inherited velocity writes, preserving slot identity and in-use fields. [Evidence](research/QVM_ALLOCATED_GRENADE.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 863 |
|
| 864 |
|
| 865 |
**RE-608 — Grenade constructor with actual entity allocation:** 285971 now composes recovered277165/277125 before grenade descriptor and inherited velocity writes, preserving slot identity and in-use fields. [Evidence](research/QVM_ALLOCATED_GRENADE.md).
|
| 866 |
+
|
| 867 |
+
|
| 868 |
+
**RE-609 — Shared hitscan spread parameter calculation:** 290493 reads current packed slot/mode and weapon table stride432/mode stride52 to calculate base, counter-scaled and modifier-adjusted spread terms. [Evidence](research/QVM_SPREAD_PARAMETERS.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -825,3 +825,6 @@ Research progress: RE-607 [report](research/QVM_ALLOCATED_EVENT.md); remaining n
|
|
| 825 |
|
| 826 |
|
| 827 |
Research progress: RE-608 [report](research/QVM_ALLOCATED_GRENADE.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 825 |
|
| 826 |
|
| 827 |
Research progress: RE-608 [report](research/QVM_ALLOCATED_GRENADE.md); remaining native/content/runtime/platform scope stays open.
|
| 828 |
+
|
| 829 |
+
|
| 830 |
+
Research progress: RE-609 [report](research/QVM_SPREAD_PARAMETERS.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -727,3 +727,8 @@ Full-pool retry relaxes the recent-free guard; source count1022 enters diagnosti
|
|
| 727 |
## 2026-10-20 — RE-608 Grenade constructor with actual entity allocation (separate task commit)
|
| 728 |
|
| 729 |
285971 now composes recovered277165/277125 before grenade descriptor and inherited velocity writes, preserving slot identity and in-use fields. Eight mode/reuse/ground-query combinations compare all220 record words to an independent grenade oracle. Existing supplied-allocation reports remain unchanged. Full suite: 935 tests pass. Report regenerates byte-identically (372396 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 727 |
## 2026-10-20 — RE-608 Grenade constructor with actual entity allocation (separate task commit)
|
| 728 |
|
| 729 |
285971 now composes recovered277165/277125 before grenade descriptor and inherited velocity writes, preserving slot identity and in-use fields. Eight mode/reuse/ground-query combinations compare all220 record words to an independent grenade oracle. Existing supplied-allocation reports remain unchanged. Full suite: 935 tests pass. Report regenerates byte-identically (372396 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 730 |
+
|
| 731 |
+
|
| 732 |
+
## 2026-10-20 — RE-609 Shared hitscan spread parameter calculation (separate task commit)
|
| 733 |
+
|
| 734 |
+
290493 reads current packed slot/mode and weapon table stride432/mode stride52 to calculate base, counter-scaled and modifier-adjusted spread terms. 144 weapon/mode/flag/ground/modifier/counter fixtures match an independent source-order f32 oracle for eight locals and the velocity copy. Full suite: 938 tests pass. Report regenerates byte-identically (150821 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
|
@@ -868,3 +868,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 868 |
|
| 869 |
|
| 870 |
- [x] RE-608 Grenade constructor with actual entity allocation ([report](research/QVM_ALLOCATED_GRENADE.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 868 |
|
| 869 |
|
| 870 |
- [x] RE-608 Grenade constructor with actual entity allocation ([report](research/QVM_ALLOCATED_GRENADE.md)).
|
| 871 |
+
|
| 872 |
+
|
| 873 |
+
- [x] RE-609 Shared hitscan spread parameter calculation ([report](research/QVM_SPREAD_PARAMETERS.md)).
|
docs/research/QVM_SPREAD_PARAMETERS.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Shared hitscan spread parameter calculation
|
| 2 |
+
|
| 3 |
+
RE-609. Reproduce with `python3 scripts/analyze_qvm_spread_parameters.py`; check with `python3 scripts/test_qvm_spread_parameters.py`. The [machine report](qvm-spread-parameters.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Actual290494–290806 copies PS32 velocity and selects the current slot from PS144, with low-byte ID and bits16–23 mode. Table base4244+ID×432+mode×52 supplies offsets16/20/32/36/40. The prefix converts degrees by file literal1016003125, conditionally zeroes local56 when PS216==0, scales it under PS12 bit1 by0.75 grounded or1.25 airborne, and applies the PS4296 modifier. Counter×table40 is capped before its modifier. Locals40/88 are distinct scaled counter terms; field semantics remain offset-based. Independent f32 formulas reproduce all144 fixtures, including counter zero and a high value that exercises the cap. No random samples, endpoint, collision or damage execute here.
|
| 6 |
+
|
| 7 |
+
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
|
@@ -426,3 +426,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 426 |
|
| 427 |
|
| 428 |
[RE-608: Grenade constructor with actual entity allocation](QVM_ALLOCATED_GRENADE.md). Reproduce with `python3 scripts/analyze_qvm_allocated_grenade.py`; check with `python3 scripts/test_qvm_allocated_grenade.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
|
| 428 |
[RE-608: Grenade constructor with actual entity allocation](QVM_ALLOCATED_GRENADE.md). Reproduce with `python3 scripts/analyze_qvm_allocated_grenade.py`; check with `python3 scripts/test_qvm_allocated_grenade.py`.
|
| 429 |
+
|
| 430 |
+
|
| 431 |
+
[RE-609: Shared hitscan spread parameter calculation](QVM_SPREAD_PARAMETERS.md). Reproduce with `python3 scripts/analyze_qvm_spread_parameters.py`; check with `python3 scripts/test_qvm_spread_parameters.py`.
|
docs/research/qvm-spread-parameters.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_spread_parameters.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Actual290493 parameter prefix, preserving source f32 operation order."""
|
| 3 |
+
import itertools
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from qvm_research_support import source,execute
|
| 6 |
+
from qvm_server_fire_support import seed,ENTITY
|
| 7 |
+
from analyze_qvm_acceleration import PS
|
| 8 |
+
from analyze_qvm_slide_prefix import vec
|
| 9 |
+
from analyze_qvm import write_json
|
| 10 |
+
LOCAL=0x79400000
|
| 11 |
+
OFFSETS=[36,64,56,48,68,80,40,88]
|
| 12 |
+
|
| 13 |
+
def parameters(ins,m):
|
| 14 |
+
m=dict(m);m[LOCAL+216]=ENTITY;slot=m[PS+144];packed=m[PS+312+4*slot];ident=packed&255;mode=(packed>>16)&255;address=4244+ident*432+mode*52
|
| 15 |
+
initial={'slot':slot,'packed':packed,'id':ident,'mode':mode,'flags12':m[PS+12],'ground':m[PS+68],'counter216':m[PS+216],'modifier4296':m[PS+4296],'velocity':vec(m,PS+32),'table_address':address,'table':{str(o):m[address+o]&0xffffffff for o in [16,20,32,36,40]}}
|
| 16 |
+
m,_,r=execute(ins,290494,290807,m,(0,0,0),LOCAL)
|
| 17 |
+
return m,{'initial':initial,'execution':r,'locals':{str(o):m[LOCAL+o]&0xffffffff for o in OFFSETS},'velocity_copy':vec(m,LOCAL+12)}
|
| 18 |
+
|
| 19 |
+
def main():
|
| 20 |
+
q,raw,h,ins=source();rows=[]
|
| 21 |
+
for ident,mode,flags,ground,modifier,counter in itertools.product([2,14,22],[0,1],[0,1],[0,1023],[0,1],[0,10,100000]):
|
| 22 |
+
m=seed(raw,h,ident);m[PS+144]=0;m[PS+312]=ident|(mode<<16);m[PS+12]=flags;m[PS+68]=ground;m[PS+4296]=modifier;m[PS+216]=counter;rows.append(parameters(ins,m)[1])
|
| 23 |
+
write_json(Path('docs/research/qvm-spread-parameters.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Actual290494–290806 only. File-backed weapon/mode table. Field names remain offsets where semantics unverified; speed normalization, PRNG, endpoint, trace and damage remain later boundaries.'})
|
| 24 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_spread_parameters.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_ground import word,n,f
|
| 4 |
+
|
| 5 |
+
def expected(p):
|
| 6 |
+
a=p['initial'];t={int(k):n(v) for k,v in a['table'].items()};rad=n(1016003125);base=f(rad*t[16]) if a['counter216'] else 0.0
|
| 7 |
+
if a['flags12']&1:base=f(base*n(1067450368 if a['ground']==1023 else 1061158912))
|
| 8 |
+
if a['modifier4296']:base=f(base*n(1058642330))
|
| 9 |
+
counter=min(f(f(float(a['counter216']))*t[40]),n(1189765120))
|
| 10 |
+
if a['modifier4296']:counter=f(counter*n(1063675494))
|
| 11 |
+
x=f(rad*t[36]);y=f(rad*t[32])
|
| 12 |
+
if a['modifier4296']:x=f(x*n(1061997773));y=f(y*n(1061997773))
|
| 13 |
+
return {'36':a['id'],'64':a['mode'],'56':word(base),'48':word(counter),'68':word(x),'80':word(y),'40':word(f(counter*n(940298085))),'88':word(f(float(a['counter216'])*n(940298085)))}
|
| 14 |
+
class SpreadParameterTests(unittest.TestCase):
|
| 15 |
+
@classmethod
|
| 16 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-spread-parameters.json').read_text())
|
| 17 |
+
def test_independent_scalar_oracle(self):
|
| 18 |
+
self.assertEqual(len(self.r['probes']),144)
|
| 19 |
+
for p in self.r['probes']:self.assertEqual(p['locals'],expected(p))
|
| 20 |
+
def test_layout_and_velocity_copy(self):
|
| 21 |
+
for p in self.r['probes']:
|
| 22 |
+
a=p['initial'];self.assertEqual(a['table_address'],4244+432*a['id']+52*a['mode']);self.assertEqual(p['velocity_copy'],a['velocity']);self.assertEqual(p['execution']['calls'],[])
|
| 23 |
+
def test_zero_counter_base(self):
|
| 24 |
+
for p in self.r['probes']:
|
| 25 |
+
if p['initial']['counter216']==0:self.assertEqual(p['locals']['56'],0);self.assertEqual(p['locals']['40'],0)
|
| 26 |
+
if __name__=='__main__':unittest.main()
|