re: the bark queue, Priority ordering, and Yes = a one-shot line

sub_822109B0 allocates 68-byte nodes from a pool capped at 128; the Pattern
byte at +23 doubles as the occupancy flag.  Priority orders the pending list
descending; the >=10 front-push arm is dead because the disc's range is 1..9.

The tick sub_8220FC50 does rule[+36] |= (1 << node[+25]) & rule[+32], so a
line enters the used mask only if its Yes bit is set: Yes = one-shot, No =
repeatable.  388 one-shot lines on the disc.  Closes what reads +32.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Claude (auto)
2026-08-27 17:17:01 +00:00
parent 8dc270091b
commit f78565fe9e
3 changed files with 121 additions and 6 deletions

View File

@@ -4298,3 +4298,49 @@ the unbounded one is what was refuted.**
queue, whether `Interval` is a per-event or per-speaker cooldown, what
`IntervalFluctuation` randomises, where `+36`'s bits get set, and what reads
`+32`. Also still open: which of the 49 speakers are wingmen.
---
## ✅ 2026-08-27 — the bark queue, `Priority`, and `Yes`/`No` settled
Continues the chatter thread, bounded to the CU as the previous entry proposed.
**Docs checked:** `preset-message-rules.md` (mine). Nothing else in the corpus
mentions `sub_822109B0`, `sub_8220FC50` or `sub_82210AF0`.
**The pending queue.** `sub_822109B0` allocates 68-byte nodes from a pool at
`this+32`; `[this+8740]` is the count and **the enqueue returns 0 once it reaches
128** — barks past that are dropped. A slot is free iff `[node+23] == 0`, and
`+23` holds **`Pattern`**, which is never 0 for a loaded rule: the presentation
field doubles as the occupancy flag. Node layout recorded in the doc.
**`Priority` orders the list, and its fast path is dead data-wise.**
Insertion tests `Priority` against **10**: ≥ 10 pushes straight to the front with
no ordering; < 10 splices ahead of the first node with a strictly smaller
`Priority`, leaving the list **descending by `Priority`**. **The disc's range is
1…9**, so the front-push arm never runs on retail data — every shipped bark takes
the ordered path. `sub_82210AF0` returns the largest `[node+20]` among pending
nodes of *higher* priority whose `[node+24] != 0x10`: a preemption/ducking query.
**`Yes`/`No` is a ONE-SHOT flag, and the `+32`/`+36` pair closes.** In the
per-frame tick `sub_8220FC50` (callers `sub_821AB650`, `sub_821B5FB8`), at
`0x82210160`:
rule[+36] = ((1 << node[+25]) & rule[+32]) | rule[+36]
The line just spoken enters the **used** mask **only if its `Yes` bit is set**.
`sub_82210670` picks only from messages whose `+36` bit is clear, so `Yes` = the
line is heard once and never again, `No` = it stays in the pool. That is what the
census counts: **8 940 `No`, 388 `Yes`** ⇒ 388 one-shot lines on the disc. It also
answers the previous entry's open question "what reads `+32`" — nothing, until a
line finishes, and then only to gate this AND.
✅ The tick branches on `Pattern < 3` (taken side uses `this+8776`), so `Window`
(3) is a different presentation path from `Sound` (1) — the two values the disc
actually ships.
**Still open, and now it is only two fields:** whether `Interval` (`+20`) is a
cooldown per event, per rule or per speaker, and what `IntervalFluctuation`
(`+24`) randomises against. Neither is read by the entry, pick, enqueue or tick
paths read so far — `sub_82210320` was checked as a candidate and is a different
structure (a deque at `this+8744`, with a divide-by-60 frames→seconds), not the
rule object. Also still open: which of the 49 speakers are wingmen.