acdream/docs/research/2026-07-02-r1-csequence/P0-pins.md
Erik 1371c2a14c feat(R1-P0/P1): CSequence research base + verbatim AnimSequenceNode
P0 — research + pins: full CSequence-family verbatim extraction (1756
lines, per-function raw pseudo-C + cleaned flow, decomp line anchors),
ACE cross-reference (9 ranked divergences; headline: retail frame_number
is x87 long double — ACE's float is the worst case, our double the best
available; ACE's frame-boundary epsilon is an ACE fabrication, NOT
retail), current-sequencer map, and the R1 gap map (20 gaps, 13 keeps,
P0-P6 port order). Pinned the one decomp ambiguity (leftover-time carry
after advance_to_next_animation — ACE reading adopted; cdb confirmation
protocol recorded, non-blocking).

P1 — AnimSequenceNode verbatim (gap G1/G2/G16/G18):
- direction-aware BARE-INT boundary pair (get_starting_frame 0x00525c80 /
  get_ending_frame 0x00525cb0): reverse starts at high+1, ends at low —
  NO epsilon;
- multiply_framerate (0x00525be0) swaps low/high on negative factor;
- set_animation_id (0x00525d60) retail clamp order (high<0 -> num-1;
  low>=num -> num-1; high>=num -> num-1; low>high -> high=low);
- ctors with retail defaults (30f/-1/-1; AnimData copy + clamp);
- get_pos_frame null out-of-range (retail; ACE returns identity),
  floor double overload; get_part_frame same discipline;
- NO per-node IsLooping/Velocity/Omega — loop membership is list
  structure, physics accumulators live on the sequence (G16).

22 conformance tests (clamp table, boundary mirror table, swap
round-trip, bounds/floor semantics).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 19:45:56 +02:00

2.9 KiB
Raw Blame History

R1-P0 — pseudocode pins and ambiguity resolutions

The verbatim extraction lives in r1-csequence-decomp.md (1,756 lines, per- function raw pseudo-C + cleaned translation, line anchors into docs/research/named-retail/acclient_2013_pseudo_c.txt). This note records the corrections and pins the R1 port codes against, per the gap map (r1-gap-map.md).

Corrections to the extraction (verified against raw decomp + ACE)

  1. §21 update_internal cleaned flow is garbled in two places. The authoritative skeleton is ACE Sequence.cs:351-443 (verified verbatim, matches the raw decomp branch layout at 0x005255d0-0x005259ca): overshoot check → clamp frame_number to get_high_frame() (fwd) / get_low_frame() (rev) + compute frameTimeElapsed leftover + animDone = true → per-frame crossing loop → if (!animDone) return → AnimDone gate (anim_list.head != first_cyclic) → advance_to_next_animation → carry leftover → loop.
  2. Hook direction constants: forward crossings pass +1 (0x0052578c, counter ++ after), reverse pass 1 (0x0052590c, counter -- after). Retail encoding == ACE/DatReaderWriter AnimationHookDir (Backward=1 / Both=0 / Forward=1) — no remap.

PINNED ambiguity — leftover-time carry after node advance

Raw decomp at 0x0052598a-0x0052598d APPEARS to zero the elapsed argument after advance_to_next_animation before looping; ACE carries the leftover (timeElapsed = frameTimeElapsed, Sequence.cs:436-442).

PIN: the ACE reading (carry the leftover). Rationale: (a) Binary Ninja routinely loses x87 stack-slot reassignments (the same artifact class as the garbled setcc returns in is_newer); (b) zeroing would make a lag spike unable to fast-forward through multiple queued nodes in one tick, visibly freezing links under hitches — behavior nobody has ever reported on retail; (c) the loop structure (while(true) with the leftover recomputed per node) only makes sense with a carry.

Confirmation pending (not blocking): cdb breakpoints on acclient!CSequence::update + acclient!CSequence::advance_to_next_animation with hit counters (pattern tools/cdb/l2g-observer.cdb) under an induced stall — an advance/update ratio > 1 in a single update proves the carry. Fold into the next live retail session; if it DISPROVES the carry, the fix is one line in update_internal + rerun of the P4 conformance suite.

P0 addenda for later stages

  • The same cdb session should also capture append_animation / remove_cyclic_anims argument logs (P2/P5 goldens) — one session serves all of R1.
  • frame_number is x87 long double (acclient.h:30747); C# double is the closest available → divergence-register row lands with the P2 commit (G15).
  • ACE's PhysicsGlobals.EPSILON subtraction in get_starting/get_ending_frame is an ACE fabrication (compensating for ACE's float FrameNumber) — retail returns bare ints. Do NOT copy (G1).