nmarshall commited on
Commit
c2db933
·
1 Parent(s): b694e5b

qvm: direction codec

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -342,3 +342,6 @@ Research progress: [ordinary air continuation](research/QVM_AIR_MODE.md) complet
342
 
343
 
344
  Research progress: RE-549 [report](research/QVM_MOVE_DIRECTION.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
342
 
343
 
344
  Research progress: RE-549 [report](research/QVM_MOVE_DIRECTION.md); remaining native/content/runtime/platform scope stays open.
345
+
346
+
347
+ Research progress: RE-550 [report](research/QVM_DIRECTION_CODEC.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -700,3 +700,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
700
 
701
 
702
  **RE-549 — Recover40679 movement direction classification:** Signed forward/right input selects all eight direction values; idle rewrites old2 to1 and6 to7, preserving other prior values. [Evidence](research/QVM_MOVE_DIRECTION.md).
 
 
 
 
700
 
701
 
702
  **RE-549 — Recover40679 movement direction classification:** Signed forward/right input selects all eight direction values; idle rewrites old2 to1 and6 to7, preserving other prior values. [Evidence](research/QVM_MOVE_DIRECTION.md).
703
+
704
+
705
+ **RE-550 — Recover162-vector direction codec60317 and60408:** Encoder uses strict-greater positive dot search initialized to score0/index0, so earliest ties survive and null/zero choose0. Decoder copies table entries0..161 or the initialized zero fallback. [Evidence](research/QVM_DIRECTION_CODEC.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -654,3 +654,6 @@ Research progress: [ordinary air continuation](research/QVM_AIR_MODE.md) complet
654
 
655
 
656
  Research progress: RE-549 [report](research/QVM_MOVE_DIRECTION.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
654
 
655
 
656
  Research progress: RE-549 [report](research/QVM_MOVE_DIRECTION.md); remaining native/content/runtime/platform scope stays open.
657
+
658
+
659
+ Research progress: RE-550 [report](research/QVM_DIRECTION_CODEC.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -447,3 +447,8 @@ Recovered ordinary air path after actual initial wall guard; unrecovered wall-sp
447
  ## 2026-10-19 — RE-549 Recover40679 movement direction classification (separate task commit)
448
 
449
  Signed forward/right input selects all eight direction values; idle rewrites old2 to1 and6 to7, preserving other prior values. 100 signed-byte/prior-state cases and four independent tests cover octants, idle exceptions, canary and source identity. Full suite: 723 tests pass. Report regenerates byte-identically (69217 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
447
  ## 2026-10-19 — RE-549 Recover40679 movement direction classification (separate task commit)
448
 
449
  Signed forward/right input selects all eight direction values; idle rewrites old2 to1 and6 to7, preserving other prior values. 100 signed-byte/prior-state cases and four independent tests cover octants, idle exceptions, canary and source identity. Full suite: 723 tests pass. Report regenerates byte-identically (69217 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
450
+
451
+
452
+ ## 2026-10-19 — RE-550 Recover162-vector direction codec60317 and60408 (separate task commit)
453
+
454
+ Encoder uses strict-greater positive dot search initialized to score0/index0, so earliest ties survive and null/zero choose0. Decoder copies table entries0..161 or the initialized zero fallback. 326 encode inputs,165 decode indices and four independent tests validate exact float32 dots, table provenance, null/zero and invalid bounds. Full suite: 727 tests pass. Report regenerates byte-identically (142623 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
@@ -691,3 +691,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
691
 
692
 
693
  - [x] RE-549 Recover40679 movement direction classification ([report](research/QVM_MOVE_DIRECTION.md)).
 
 
 
 
691
 
692
 
693
  - [x] RE-549 Recover40679 movement direction classification ([report](research/QVM_MOVE_DIRECTION.md)).
694
+
695
+
696
+ - [x] RE-550 Recover162-vector direction codec60317 and60408 ([report](research/QVM_DIRECTION_CODEC.md)).
docs/research/QVM_DIRECTION_CODEC.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Recover162-vector direction codec60317 and60408
2
+
3
+ RE-550. Reproduce with `python3 scripts/analyze_qvm_direction_codec.py`; check with `python3 scripts/test_qvm_direction_codec.py`. The [machine report](qvm-direction-codec.json) retains source identity and bounded fixtures.
4
+
5
+ All162 direction vectors are read from source data address21732 with12-byte stride.60317 does not normalize its input: it scans all entries, starting best dot0/index0, replacing only on strict greater. Negative inputs and zero inputs are retained as finite cases; a null pointer returns0 before any scan.60408 accepts signed indices0 through161 and copies the initialized21348 zero vector otherwise.326 encoder cases cover each vector, its negative, zero and null; decoder cases cover every valid index and three invalid controls. This recovers the numeric event-parameter producer needed by the wall-contact path; live table mutation and the event's user-visible meaning remain unverified.
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
@@ -255,3 +255,6 @@ The extension collector adds five focused tests for native tail calls, command-r
255
 
256
 
257
  [RE-549: Recover40679 movement direction classification](QVM_MOVE_DIRECTION.md). Reproduce with `python3 scripts/analyze_qvm_move_direction.py`; check with `python3 scripts/test_qvm_move_direction.py`.
 
 
 
 
255
 
256
 
257
  [RE-549: Recover40679 movement direction classification](QVM_MOVE_DIRECTION.md). Reproduce with `python3 scripts/analyze_qvm_move_direction.py`; check with `python3 scripts/test_qvm_move_direction.py`.
258
+
259
+
260
+ [RE-550: Recover162-vector direction codec60317 and60408](QVM_DIRECTION_CODEC.md). Reproduce with `python3 scripts/analyze_qvm_direction_codec.py`; check with `python3 scripts/test_qvm_direction_codec.py`.
docs/research/qvm-direction-codec.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_direction_codec.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Actual60317/60408 finite direction-table codec."""
3
+ from pathlib import Path
4
+ from qvm_research_support import source,constants
5
+ from analyze_deferred_auth import trace_slice
6
+ from analyze_bsp_references import trace_fields
7
+ from analyze_qvm import write_json
8
+ from analyze_qvm_acceleration import word,number
9
+
10
+ BASE=0x65000000
11
+ VEC=0x51000
12
+
13
+
14
+ def table(raw,h):return constants(raw,h,list(range(21732,21732+162*12,4))+[21348,21352,21356])
15
+
16
+
17
+ def encode(ins,m,vector):
18
+ m=dict(m)
19
+ if vector is not None:
20
+ for i,v in enumerate(vector):m[VEC+4*i]=v
21
+ t=trace_slice(ins,60318,60406,m,{40:0 if vector is None else VEC},local_base=BASE,halt_on_leave=True,capture_stack=True,limit=20000);return t['memory'],{'vector':vector,'result':t['stack'][-1],'calls':t['calls'],**trace_fields(t,False)}
22
+
23
+
24
+ def decode_vector(ins,m,index):
25
+ t=trace_slice(ins,60409,60436,m,{20:index,24:VEC},local_base=BASE+0x1000,limit=128);return {'index':index,'vector':[t['memory'][VEC+4*i]&0xffffffff for i in range(3)],**trace_fields(t,False)}
26
+
27
+
28
+ def main():
29
+ q,raw,h,ins=source();m=table(raw,h);vectors=[[m[21732+12*i+4*j] for j in range(3)] for i in range(162)];probes=[encode(ins,m,v)[1] for v in vectors+[[word(-number(x)) for x in v] for v in vectors]+[[0,0,0],None]]
30
+ write_json(Path('docs/research/qvm-direction-codec.json'),{'source':q['source'],'sha256':q['sha256'],'table':vectors,'fallback':[m[a] for a in [21348,21352,21356]],'encodes':probes,'decodes':[decode_vector(ins,m,i) for i in [-1,*range(162),162,2147483647]],'limits':'File-backed162-vector table; actual helpers with finite vector inputs. No normalization is performed. Native/live table mutation and runtime/event consumers remain open.'})
31
+
32
+
33
+ if __name__=='__main__':main()
scripts/test_qvm_direction_codec.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest,hashlib
2
+ from pathlib import Path
3
+ from test_qvm_ground import f,n
4
+
5
+
6
+ def best(v,table):
7
+ if v is None:return 0
8
+ a=list(map(n,v));chosen=0;score=0
9
+ for i,b in enumerate(table):
10
+ b=list(map(n,b));d=f(f(f(a[0]*b[0])+f(a[1]*b[1]))+f(a[2]*b[2]))
11
+ if d>score:chosen,score=i,d
12
+ return chosen
13
+
14
+
15
+ class DirectionCodecTests(unittest.TestCase):
16
+ @classmethod
17
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-direction-codec.json').read_text())
18
+ def test_all326_dot_searches_exact(self):
19
+ self.assertEqual(len(self.r['encodes']),326)
20
+ for p in self.r['encodes']:self.assertEqual(p['result'],best(p['vector'],self.r['table']));self.assertEqual(p['calls'],[])
21
+ def test_null_and_zero_keep_index0(self):self.assertEqual([p['result'] for p in self.r['encodes'][-2:]],[0,0])
22
+ def test_decode_all_indices_and_invalid_fallback(self):
23
+ for p in self.r['decodes']:self.assertEqual(p['vector'],self.r['table'][p['index']] if 0<=p['index']<162 else self.r['fallback'])
24
+ self.assertEqual(self.r['fallback'],[0,0,0])
25
+ def test_all_table_words_file_backed(self):
26
+ from analyze_qvm import decode
27
+ q=json.loads(Path('docs/research/qvm/qagame.json').read_text());raw=Path(q['source']['member']['output']).read_bytes();h,_=decode(raw);self.assertEqual(self.r['sha256'],hashlib.sha256(raw).hexdigest())
28
+ for i,v in enumerate(self.r['table']):
29
+ for j,w in enumerate(v):self.assertEqual(int.from_bytes(raw[h['data_offset']+21732+12*i+4*j:h['data_offset']+21736+12*i+4*j],'little'),w)