qvm: firing sequences and publication
Browse files- docs/ASSET_PIPELINE_TODO.md +3 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +5 -0
- docs/RESEARCH_LEDGER.md +7 -0
- docs/REVERSE_ENGINEERING_TODO.md +8 -2
- docs/research/QVM_FIRE_SEQUENCES.md +11 -0
- docs/research/QVM_FIRING_BATCH.md +57 -0
- docs/research/QVM_WEAPON_BATCH.md +2 -0
- docs/research/README.md +5 -0
- docs/research/qvm-fire-sequences.json +0 -0
- scripts/analyze_qvm_fire_sequences.py +38 -0
- scripts/test_qvm_fire_sequences.py +47 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -457,3 +457,6 @@ Research progress: RE-589 [report](research/QVM_FIRE_DELAY.md); remaining native
|
|
| 457 |
|
| 458 |
|
| 459 |
Research progress: RE-590 [report](research/QVM_WEAPON_COMPLETE_BODY.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
|
| 458 |
|
| 459 |
Research progress: RE-590 [report](research/QVM_WEAPON_COMPLETE_BODY.md); remaining native/content/runtime/platform scope stays open.
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
Research progress: RE-591 [report](research/QVM_FIRE_SEQUENCES.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -815,3 +815,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 815 |
|
| 816 |
|
| 817 |
**RE-590 — Complete bounded weapon body and actual main consumer suffix:** The entire50746 QVM body now executes with recovered children and agrees with independent staged oracles; actual main54444..54463 resumes through firing and non-firing returns with live state handoffs. [Evidence](research/QVM_WEAPON_COMPLETE_BODY.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 815 |
|
| 816 |
|
| 817 |
**RE-590 — Complete bounded weapon body and actual main consumer suffix:** The entire50746 QVM body now executes with recovered children and agrees with independent staged oracles; actual main54444..54463 resumes through firing and non-firing returns with live state handoffs. [Evidence](research/QVM_WEAPON_COMPLETE_BODY.md).
|
| 818 |
+
|
| 819 |
+
|
| 820 |
+
**RE-591 — Timer-coupled firing sequences and actual outer publication:** Actual outer reset/timer/main-suffix/publication segments connect complete weapon effects to event31; three burst substeps retain one request and publish once, with independently checked selection/reload/last-round sequences. [Evidence](research/QVM_FIRE_SEQUENCES.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -773,3 +773,8 @@ Research progress: RE-589 [report](research/QVM_FIRE_DELAY.md); remaining native
|
|
| 773 |
|
| 774 |
|
| 775 |
Research progress: RE-590 [report](research/QVM_WEAPON_COMPLETE_BODY.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 773 |
|
| 774 |
|
| 775 |
Research progress: RE-590 [report](research/QVM_WEAPON_COMPLETE_BODY.md); remaining native/content/runtime/platform scope stays open.
|
| 776 |
+
|
| 777 |
+
The [RE-582–591 firing batch](research/QVM_FIRING_BATCH.md) completes the bounded50746 QVM producer, six-consumer main suffix and timer/publication sequences. Prioritize its next ten tasks for event31 consumers, native/reference contracts, complete step/scheduler composition, asset identity and Rust/Bevy/Solari macOS/Linux runtime work.
|
| 778 |
+
|
| 779 |
+
|
| 780 |
+
Research progress: RE-591 [report](research/QVM_FIRE_SEQUENCES.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -643,3 +643,10 @@ RE-580 additional regression: all19 reports from RE-560–569 and RE-571–579 r
|
|
| 643 |
## 2026-10-20 — RE-590 Complete bounded weapon body and actual main consumer suffix (separate task commit)
|
| 644 |
|
| 645 |
The entire50746 QVM body now executes with recovered children and agrees with independent staged oracles; actual main54444..54463 resumes through firing and non-firing returns with live state handoffs. 12 complete-body scenarios and two six-child main suffixes check every reached stage, complete final state, direct callee inventory and source-order event/animation effects. Full suite: 875 tests pass. Report regenerates byte-identically (1246760 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 643 |
## 2026-10-20 — RE-590 Complete bounded weapon body and actual main consumer suffix (separate task commit)
|
| 644 |
|
| 645 |
The entire50746 QVM body now executes with recovered children and agrees with independent staged oracles; actual main54444..54463 resumes through firing and non-firing returns with live state handoffs. 12 complete-body scenarios and two six-child main suffixes check every reached stage, complete final state, direct callee inventory and source-order event/animation effects. Full suite: 875 tests pass. Report regenerates byte-identically (1246760 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 646 |
+
|
| 647 |
+
|
| 648 |
+
## 2026-10-20 — RE-591 Timer-coupled firing sequences and actual outer publication (separate task commit)
|
| 649 |
+
|
| 650 |
+
Actual outer reset/timer/main-suffix/publication segments connect complete weapon effects to event31; three burst substeps retain one request and publish once, with independently checked selection/reload/last-round sequences. Four multi-call scenarios check every timer/reset handoff and explicit state timelines; actual93→21→31 publication verifies order, cached ID/magazine, parameters and ring wrap. Full suite: 879 tests pass. Report regenerates byte-identically (216110 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 651 |
+
|
| 652 |
+
RE-591 additional regression:19 related reports from RE-571–580 and RE-582–590 regenerate byte-identically. Complete-body composition and repeated suffix calls add no original assets or Rust runtime changes; native firing consumers and complete original/reference ticks remain explicitly outside the completed scope.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -750,7 +750,7 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 750 |
|
| 751 |
- [x] RE-568 Complete locomotion gait bob and footstep consumer ([report](research/QVM_LOCOMOTION.md)).
|
| 752 |
|
| 753 |
-
- [ ] RE-570 Partially closed by RE-571–580:48798/49028 selection/completion,50525 and pre-firing continuation through51801 are recovered.
|
| 754 |
|
| 755 |
|
| 756 |
- [x] RE-569 Main request and independently bounded animation consumer chains ([report](research/QVM_MAIN_CONSUMERS.md)).
|
|
@@ -783,7 +783,7 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 783 |
- [x] RE-579 Weapon lowering raising and frame gates ([report](research/QVM_WEAPON_PHASES.md)).
|
| 784 |
|
| 785 |
|
| 786 |
-
- [ ] RE-581
|
| 787 |
|
| 788 |
|
| 789 |
- [x] RE-580 Pre-firing weapon return chains and actual main suffix handoff ([report](research/QVM_WEAPON_RETURN_CHAINS.md)).
|
|
@@ -814,3 +814,9 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 814 |
|
| 815 |
|
| 816 |
- [x] RE-590 Complete bounded weapon body and actual main consumer suffix ([report](research/QVM_WEAPON_COMPLETE_BODY.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 750 |
|
| 751 |
- [x] RE-568 Complete locomotion gait bob and footstep consumer ([report](research/QVM_LOCOMOTION.md)).
|
| 752 |
|
| 753 |
+
- [ ] RE-570 Partially closed by RE-571–580:48798/49028 selection/completion,50525 and pre-firing continuation through51801 are recovered. RE-582–591 subsequently closes the finite firing body and publication. Resource/config writers, native firing consumers, main final vector snap, original reference ticks, asset-ID mapping and Rust/Bevy/Solari macOS/Linux runtime stay open. See [weapon batch](research/QVM_WEAPON_BATCH.md).
|
| 754 |
|
| 755 |
|
| 756 |
- [x] RE-569 Main request and independently bounded animation consumer chains ([report](research/QVM_MAIN_CONSUMERS.md)).
|
|
|
|
| 783 |
- [x] RE-579 Weapon lowering raising and frame gates ([report](research/QVM_WEAPON_PHASES.md)).
|
| 784 |
|
| 785 |
|
| 786 |
+
- [ ] RE-581 Partially closed by RE-582–591: finite50746, charge/availability/ammo/pose/accounting, main consumer suffix and outer publication are recovered. Native firing/event31 consumers, final vector snap, complete step/scheduler, original reference validation and full native/content/rendering/platform implementation remain open. See [firing batch](research/QVM_FIRING_BATCH.md).
|
| 787 |
|
| 788 |
|
| 789 |
- [x] RE-580 Pre-firing weapon return chains and actual main suffix handoff ([report](research/QVM_WEAPON_RETURN_CHAINS.md)).
|
|
|
|
| 814 |
|
| 815 |
|
| 816 |
- [x] RE-590 Complete bounded weapon body and actual main consumer suffix ([report](research/QVM_WEAPON_COMPLETE_BODY.md)).
|
| 817 |
+
|
| 818 |
+
|
| 819 |
+
- [ ] RE-592 Recover event31 consumers and actual projectile/hitscan/damage effects; native vector snap and full53418/54475 step/scheduler composition; validate original legal-state traces, map numerical weapon/animation/audio IDs to assets, and continue Rust/Bevy/Solari macOS/Linux gameplay. See the [next ten tasks](research/QVM_FIRING_BATCH.md#boundaries-and-next-ten-tasks).
|
| 820 |
+
|
| 821 |
+
|
| 822 |
+
- [x] RE-591 Timer-coupled firing sequences and actual outer publication ([report](research/QVM_FIRE_SEQUENCES.md)).
|
docs/research/QVM_FIRE_SEQUENCES.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Timer-coupled firing sequences and actual outer publication
|
| 2 |
+
|
| 3 |
+
RE-591. Reproduce with `python3 scripts/analyze_qvm_fire_sequences.py`; check with `python3 scripts/test_qvm_fire_sequences.py`. The [machine report](qvm-fire-sequences.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
The driver uses actual54528..54557 to reset per-outer-frame outputs, actual53048 timers before each complete six-consumer main suffix, and actual54855..54978 after all supplied substeps. Request260 remains set across substeps until the next outer reset. Publication emits optional93(landing),21(mode) and31(firing) in that order, with respective frame parameters. Firing caches selectedID and post-debit magazine and queues31 with FRAME264, supplied0 by the producer. Actual29913 writes the ring queue.
|
| 6 |
+
|
| 7 |
+
Four scenarios independently verify burst magazines4/3/2, counters2/1/0 and timers25/25/100 with a single outer31; last-round timer0 followed by empty timer500/event29 without stale firing publication; five-call selection lowering/raising; and released reload from2/2 to32/1 using an explicitly shortened timer. Each timer handoff checks movement-flag expiry and leg/torso countdowns, not only final outputs. A separate supplied fixture verifies93→21→31 and unsigned sequence wrap. Reports retain compact snapshots/trace hashes without duplicating whole-body machine reports.
|
| 8 |
+
|
| 9 |
+
Dt/buttons and selected configuration overrides are supplied. Actual scheduler clock/input cleanup, earlier main movement/environment/view setup and native snap54471 are omitted, so these are finite repeated suffix calls rather than full original ticks. Event31 consumer/projectile/hitscan/native outcomes remain open. See the [ten-task firing batch](QVM_FIRING_BATCH.md).
|
| 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/QVM_FIRING_BATCH.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Firing research batch: RE-582–591
|
| 2 |
+
|
| 3 |
+
Ten separate task commits extend the [weapon-state batch](QVM_WEAPON_BATCH.md). The entire finite50746 body now executes with recovered QVM children; repeated source suffix calls connect its published request to the actual outer event queue. This is not native shot simulation or full-game completion.
|
| 4 |
+
|
| 5 |
+
| Task | Scope | Findings |
|
| 6 |
+
| --- | --- | --- |
|
| 7 |
+
| RE-582 |51802..52084 charge/hold/release and ordinary input gate | [Input gate](QVM_FIRE_GATE.md) |
|
| 8 |
+
| RE-583 |52085..52153 availability failure/state1/ID27 exception | [Availability](QVM_FIRE_AVAILABILITY.md) |
|
| 9 |
+
| RE-584 |52154..52252 selected magazine debit | [Ammo](QVM_FIRE_AMMO.md) |
|
| 10 |
+
| RE-585 |52253..52411 firing pose priority | [Pose priority](QVM_FIRE_POSE_PRIORITY.md) |
|
| 11 |
+
| RE-586 | Complete52253..52729 class/tag/gait pose dispatch | [Pose](QVM_FIRE_POSE.md) |
|
| 12 |
+
| RE-587 |52730..52872 request publication and burst delay/counter | [Counter](QVM_FIRE_COUNTER.md) |
|
| 13 |
+
| RE-588 |52873..52988 resource snapshot/division/clamp/reset | [Resource](QVM_FIRE_RESOURCE.md) |
|
| 14 |
+
| RE-589 |52989..53045 post-debit final delay | [Delay](QVM_FIRE_DELAY.md) |
|
| 15 |
+
| RE-590 | Entire50746 body and actual54444..54463 main suffix | [Complete body](QVM_WEAPON_COMPLETE_BODY.md) |
|
| 16 |
+
| RE-591 | Actual outer reset, timer-coupled repeated main suffix calls and publication | [Sequences](QVM_FIRE_SEQUENCES.md) |
|
| 17 |
+
|
| 18 |
+
## Concrete behavior recovered
|
| 19 |
+
|
| 20 |
+
- Charge-mode availability uses packed mode, while parent branch/debit/accounting uses preserved local mode. IDs11/12 have command-weapon exceptions; literal asymmetry is retained.
|
| 21 |
+
- Ordinary nonzero burst counters bypass absent attack input. An unavailable non-ID27 weapon queues29, clears its counter and adds500 to the timer.
|
| 22 |
+
- Magazine debit preserves the other packed bytes and is suppressed by local-mode flag4. Empty magazine does not underflow.
|
| 23 |
+
- Pose priority precedes the class table; running-leg membership and tag22/25 select different timed requests. These remain numeric animation choices until asset mapping is verified.
|
| 24 |
+
- Firing publishes FRAME260=1, FRAME264=0 and PS148=3. Counter3 produces two burst delays before the normal terminal delay.
|
| 25 |
+
- Without flag16, resource188 is copied to PS216, incremented by signed truncated30000/capacity, upper-clamped30000 and given a mode cooldown. There is no lower clamp in that slice. Flag16 zeros all three and skips division. Capacity0 without the bypass is rejected rather than supplied a fake result.
|
| 26 |
+
- Final delay reads the post-debit magazine: an ordinary last round skips the timer addition; ID27 still adds it.
|
| 27 |
+
- Actual outer publication queues31 with FRAME264 as parameter, caching the selected low-byte ID and post-debit magazine. It runs after optional93 and21 events. The firing request can remain set across several substeps, yielding one publication at the outer boundary.
|
| 28 |
+
|
| 29 |
+
## Integration evidence
|
| 30 |
+
|
| 31 |
+
RE-590 evaluates the whole50746 body directly and compares its complete finite results against independent staged state/delay oracles. All direct call families are inventoried; no unresolved call is silently supplied a successful result. Twelve scenarios cover firing/last/empty, flag4, charge start/release, burst, lowering, reload, death, local-mode preservation and selection. Two actual six-child main suffix fixtures validate handoffs.
|
| 32 |
+
|
| 33 |
+
RE-591 uses actual reset54528..54557, timer53048, main consumer suffix54444..54463 and publication54855..54978. Four finite sequences cover:
|
| 34 |
+
|
| 35 |
+
1. Three burst substeps in one outer frame: magazines4/3/2, counters2/1/0, delays25/25/100 and one outer event31.
|
| 36 |
+
2. Last round followed by empty input: timer0 then500, queued31 then29, without stale request publication on the next outer frame.
|
| 37 |
+
3. Selection lowering/raising: slot/state/timer transitions(0,2,300)→(0,2,100)→(1,1,250)→(1,1,50)→(1,0,0), with event30 parameters0 then1.
|
| 38 |
+
4. Released reload with explicitly supplied shortened timer: magazine2/reserve2 becomes32/reserve1 without a firing publication.
|
| 39 |
+
|
| 40 |
+
A separate supplied publication fixture verifies93→21→31 order, parameters and unsigned ring-sequence wrap. Timers are independently checked at each handoff. The burst timing and shortened reload records are explicit fixture overrides, not claims about immutable shipped configuration.
|
| 41 |
+
|
| 42 |
+
The839-test baseline gains40 independent tests. All reports remain below the2MiB normal-Git cap and regenerate deterministically. Code/docs remain normal Git, asset filters remain in force, and no original assets enter these commits.
|
| 43 |
+
|
| 44 |
+
## Boundaries and next ten tasks
|
| 45 |
+
|
| 46 |
+
No original executable/native library, collision/physics or renderer runs. Animation durations and interaction trace replies are supplied. Repeated calls use supplied dt/buttons; scheduler clock/input cleanup, earlier main view/movement/environment setup and final native vector snap54471 are omitted. QVM function completeness does not imply exhaustive legal-state, reference, network or platform parity.
|
| 47 |
+
|
| 48 |
+
1. Locate and recover server/client event31 consumers, including how cached weapon/magazine and event parameters determine an actual firing action.
|
| 49 |
+
2. Recover reached projectile/hitscan, spread/recoil and ammunition side effects beyond the movement producer; inventory every unresolved child.
|
| 50 |
+
3. Recover trace/damage/material/contact contracts for those consumers and capture collision-consistent reference records.
|
| 51 |
+
4. Trace weapon/mode configuration initialization and writers; validate capacity, counter, timer, flag and resource domains against live state.
|
| 52 |
+
5. Map numeric weapons, torso/leg animations and event sounds to asset variants with provenance and conversion requirements.
|
| 53 |
+
6. Recover native vector snap54471, including actual rounding and ABI behavior from the supplied platform binaries.
|
| 54 |
+
7. Compose the complete53418 movement step with clock, inputs, view basis, environment, timers, movement and all six suffix consumers.
|
| 55 |
+
8. Compose outer54475 scheduling with the recovered step and event publication; check timestamp boundaries, substep aggregation and queue pressure.
|
| 56 |
+
9. Capture original/reference execution and compare legal multi-step behavior, then continue broader native/DLL/network/rendering/content coverage.
|
| 57 |
+
10. Start the Rust/Bevy/Solari executable slice with recorded fixture parity and measured macOS/Linux platform/rendering paths; this research does not count as a playable game.
|
docs/research/QVM_WEAPON_BATCH.md
CHANGED
|
@@ -46,3 +46,5 @@ The baseline799 tests gains40 independent checks. Every report is reproducible b
|
|
| 46 |
8. Recover final main native vector snapping54471 and compose the complete main tick, preserving byte inputs, locals and all event/animation order.
|
| 47 |
9. Capture original-execution references and collision-consistent responses; map numeric weapon/animation/event identities to actual assets and validate legal input domains.
|
| 48 |
10. Continue the broader native/DLL/protocol/rendering/content work and first Rust/Bevy/Solari runtime slice on macOS/Linux. Bounded research coverage is not playable-game completion.
|
|
|
|
|
|
|
|
|
| 46 |
8. Recover final main native vector snapping54471 and compose the complete main tick, preserving byte inputs, locals and all event/animation order.
|
| 47 |
9. Capture original-execution references and collision-consistent responses; map numeric weapon/animation/event identities to actual assets and validate legal input domains.
|
| 48 |
10. Continue the broader native/DLL/protocol/rendering/content work and first Rust/Bevy/Solari runtime slice on macOS/Linux. Bounded research coverage is not playable-game completion.
|
| 49 |
+
|
| 50 |
+
The subsequent [RE-582–591 firing batch](QVM_FIRING_BATCH.md) closes the finite50746 body and connects actual outer request publication. The remaining51802+ gap above describes this earlier report's scope; native shot consumers, complete movement ticks and reference/platform gameplay remain open.
|
docs/research/README.md
CHANGED
|
@@ -374,3 +374,8 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 374 |
|
| 375 |
|
| 376 |
[RE-590: Complete bounded weapon body and actual main consumer suffix](QVM_WEAPON_COMPLETE_BODY.md). Reproduce with `python3 scripts/analyze_qvm_weapon_complete_body.py`; check with `python3 scripts/test_qvm_weapon_complete_body.py`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 374 |
|
| 375 |
|
| 376 |
[RE-590: Complete bounded weapon body and actual main consumer suffix](QVM_WEAPON_COMPLETE_BODY.md). Reproduce with `python3 scripts/analyze_qvm_weapon_complete_body.py`; check with `python3 scripts/test_qvm_weapon_complete_body.py`.
|
| 377 |
+
|
| 378 |
+
[RE-582–591 firing batch and next ten tasks](QVM_FIRING_BATCH.md): complete finite weapon producer, actual outer publication and explicit native/full-tick boundaries.
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
[RE-591: Timer-coupled firing sequences and actual outer publication](QVM_FIRE_SEQUENCES.md). Reproduce with `python3 scripts/analyze_qvm_fire_sequences.py`; check with `python3 scripts/test_qvm_fire_sequences.py`.
|
docs/research/qvm-fire-sequences.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_fire_sequences.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Recovered outer reset, timers, repeated main suffixes and actual event publication."""
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from qvm_research_support import source,execute
|
| 5 |
+
from qvm_firing_support import seed,state,fire_handlers
|
| 6 |
+
from analyze_qvm_weapon_complete_body import main_suffix
|
| 7 |
+
from analyze_qvm_acceleration import PS,FRAME,word
|
| 8 |
+
from analyze_qvm import write_json
|
| 9 |
+
WRAPPER=0x79000000
|
| 10 |
+
TIMERS=WRAPPER+0x1000
|
| 11 |
+
|
| 12 |
+
def observed(m):return {**state(m),'movement_timer':m[PS+16]&0xffffffff}
|
| 13 |
+
|
| 14 |
+
def publish(ins,m,cmd=(0,0,0)):
|
| 15 |
+
before=observed(m);requests=[m[FRAME+o] for o in [48,252,256,260,264]];m[WRAPPER+72]=FRAME
|
| 16 |
+
m,c,r=execute(ins,54855,54979,m,cmd,WRAPPER,fire_handlers());cached=[m[WRAPPER+32],m[WRAPPER+36]] if requests[3] else None
|
| 17 |
+
return m,{'initial':before,'requests':requests,'execution':r,'cached_weapon_and_magazine':cached,'final':observed(m)}
|
| 18 |
+
|
| 19 |
+
def sequence(ins,m,frames):
|
| 20 |
+
initial=observed(m);rows=[]
|
| 21 |
+
for inputs in frames:
|
| 22 |
+
before=observed(m);m[WRAPPER+72]=FRAME;m,c,reset=execute(ins,54528,54558,m,(0,0,0),WRAPPER);after_reset=observed(m);steps=[]
|
| 23 |
+
for dt,buttons in inputs:
|
| 24 |
+
m.update({35023932:dt,35023928:word(dt/1000),FRAME+20:buttons});a=observed(m);m,c,timer=execute(ins,53049,53184,m,(0,0,0),TIMERS);after_timer=observed(m);m,main=main_suffix(ins,m);weapon=main['execution']['children'][2]['effect'];steps.append({'supplied_dt':dt,'buttons':buttons,'initial':a,'timer_execution':timer,'after_timers':after_timer,'main_calls':main['execution']['calls'],'weapon_calls':weapon['execution']['calls'],'weapon_trace_sha256':weapon['execution']['trace_sha256'],'final':observed(m)})
|
| 25 |
+
m,publication=publish(ins,m);rows.append({'initial':before,'reset_execution':reset,'after_reset':after_reset,'steps':steps,'publication':publication,'final':observed(m)})
|
| 26 |
+
return {'initial':initial,'frames':rows,'final':observed(m)}
|
| 27 |
+
|
| 28 |
+
def main():
|
| 29 |
+
q,raw,h,ins=source();rows=[]
|
| 30 |
+
def base(ident=22,mag=2):
|
| 31 |
+
m=seed(raw,h,ident,mag);m.update({PS+16:0,PS+72:0,PS+80:0,FRAME+212:0,35024028:0});return m
|
| 32 |
+
m=base(22,5);m.update({PS+16:33,PS+12:192,PS+72:50,4244+432*22+48:3,4244+432*22+8:100,4244+432*22+44:25});p=sequence(ins,m,[[(1,1),(25,0),(25,0)]]);p['name']='burst-one-outer-frame';p['supplied_configuration']={'burst_count':3,'burst_delay':25,'delay':100};rows.append(p)
|
| 33 |
+
m=base(22,1);p=sequence(ins,m,[[(1,1)],[(1,1)]]);p['name']='last-round-then-empty';rows.append(p)
|
| 34 |
+
m=base(1,2);m.update({FRAME+24:22,PS+316:22|(5<<8)|(3<<24)});p=sequence(ins,m,[[(16,0)],[(200,0)],[(100,0)],[(200,0)],[(50,0)]]);p['name']='selection-lower-raise';rows.append(p)
|
| 35 |
+
m=base(22,2);m.update({PS+312:22|(2<<8)|(2<<24),4056+432*22:30});p=sequence(ins,m,[[(1,32)],[(29,0)]]);p['name']='reload-released';p['supplied_configuration']={'reload_timer':30};rows.append(p)
|
| 36 |
+
m=base(22,2);m.update({FRAME+48:7,FRAME+252:1,FRAME+256:9,FRAME+260:1,FRAME+264:0,PS+108:0xffffffff});m,order=publish(ins,m)
|
| 37 |
+
write_json(Path('docs/research/qvm-fire-sequences.json'),{'source':q['source'],'sha256':q['sha256'],'sequences':rows,'supplied_publication_order':order,'limits':'Actual reset54528..54557, timer53048, main suffix54444..54463 and publication54855..54978 only. Step dt/buttons/config are supplied; scheduler clock/input cleanup, earlier movement/environment/native snap omitted. Repeated finite calls are not full original ticks or native shot execution.'})
|
| 38 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_fire_sequences.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest,copy
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_torso_selector import signed
|
| 4 |
+
|
| 5 |
+
def timer_state(p):
|
| 6 |
+
a=copy.deepcopy(p['initial']);dt=p['supplied_dt'];timer=signed(a['movement_timer'])
|
| 7 |
+
if timer:
|
| 8 |
+
if dt>=timer:a['movement_timer']=0;a['flags']&=~192
|
| 9 |
+
else:a['movement_timer']=(timer-dt)&0xffffffff
|
| 10 |
+
for field in ['leg_timer','torso_timer']:
|
| 11 |
+
if signed(a[field])>0:a[field]=max(signed(a[field])-dt,0)
|
| 12 |
+
return a
|
| 13 |
+
|
| 14 |
+
def publication_state(p):
|
| 15 |
+
a=copy.deepcopy(p['initial']);land,mode,old,fire,param=p['requests'];events=[]
|
| 16 |
+
if land:events.append((93,land))
|
| 17 |
+
if mode:events.append((21,old))
|
| 18 |
+
if fire:events.append((31,param))
|
| 19 |
+
for event,value in events:
|
| 20 |
+
q=a['queue'];slot=q['sequence']&1;q['events'][slot]=event;q['parameters'][slot]=value&0xffffffff;q['sequence']=(q['sequence']+1)&0xffffffff
|
| 21 |
+
return a,events
|
| 22 |
+
class FireSequencesTests(unittest.TestCase):
|
| 23 |
+
@classmethod
|
| 24 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-fire-sequences.json').read_text());cls.rows={p['name']:p for p in cls.r['sequences']}
|
| 25 |
+
def test_actual_timer_and_outer_reset_handoffs(self):
|
| 26 |
+
self.assertEqual(len(self.r['sequences']),4)
|
| 27 |
+
for p in self.r['sequences']:
|
| 28 |
+
previous=p['initial']
|
| 29 |
+
for frame in p['frames']:
|
| 30 |
+
self.assertEqual(frame['initial'],previous);a=copy.deepcopy(previous);a.update(mode_changed=0,old_mode=0,request260=0,request264=0);self.assertEqual(frame['after_reset'],a)
|
| 31 |
+
for step in frame['steps']:
|
| 32 |
+
self.assertEqual(step['initial'],a);self.assertEqual(step['after_timers'],timer_state(step));self.assertEqual([c['target'] for c in step['main_calls']],[49652,49918,50746,49117,47884,48716]);a=step['final']
|
| 33 |
+
self.assertEqual(frame['publication']['initial'],a);previous=frame['final']
|
| 34 |
+
self.assertEqual(previous,p['final'])
|
| 35 |
+
def test_burst_substeps_publish_one_outer_event(self):
|
| 36 |
+
frame=self.rows['burst-one-outer-frame']['frames'][0];steps=frame['steps'];self.assertEqual([p['final']['packed']>>8&255 for p in steps],[4,3,2]);self.assertEqual([p['final']['counter204'] for p in steps],[2,1,0]);self.assertEqual([p['final']['weapon_timer'] for p in steps],[25,25,100]);self.assertEqual([p['final']['resource'] for p in steps],[937,1874,2811]);self.assertEqual([p['initial']['request260'] for p in steps],[0,1,1]);self.assertEqual([c['args']['8'] for c in frame['publication']['execution']['calls']],[31]);self.assertEqual(frame['final']['queue']['sequence'],1)
|
| 37 |
+
def test_selection_reload_and_last_round_timelines(self):
|
| 38 |
+
steps=[f['steps'][0]['final'] for f in self.rows['selection-lower-raise']['frames']];self.assertEqual([(s['slot'],s['weapon_state'],s['weapon_timer']) for s in steps],[(0,2,300),(0,2,100),(1,1,250),(1,1,50),(1,0,0)]);self.assertEqual(steps[-1]['queue']['events'],[30,30]);self.assertEqual(steps[-1]['queue']['parameters'],[0,1])
|
| 39 |
+
steps=[f['steps'][0]['final'] for f in self.rows['reload-released']['frames']];self.assertEqual([(s['packed']>>8&255,s['packed']>>24,s['weapon_timer']) for s in steps],[(2,2,29),(32,1,0)]);self.assertFalse(steps[-1]['state220']&8)
|
| 40 |
+
frames=self.rows['last-round-then-empty']['frames'];self.assertEqual([f['final']['weapon_timer'] for f in frames],[0,500]);self.assertEqual(frames[-1]['final']['queue']['events'],[31,29]);self.assertEqual(frames[-1]['publication']['execution']['calls'],[])
|
| 41 |
+
def test_actual_publication_order_parameters_cache_and_wrap(self):
|
| 42 |
+
publications=[f['publication'] for p in self.r['sequences'] for f in p['frames']]+[self.r['supplied_publication_order']]
|
| 43 |
+
for p in publications:
|
| 44 |
+
a,events=publication_state(p);self.assertEqual(p['final'],a);self.assertEqual([(c['args']['8'],c['args']['12']) for c in p['execution']['calls']],events)
|
| 45 |
+
self.assertEqual(p['cached_weapon_and_magazine'],[p['initial']['packed']&255,p['initial']['packed']>>8&255] if p['requests'][3] else None)
|
| 46 |
+
p=self.r['supplied_publication_order'];self.assertEqual(p['final']['queue'],{'sequence':2,'events':[21,31],'parameters':[9,0]})
|
| 47 |
+
if __name__=='__main__':unittest.main()
|