From 46227e2003de28202cc4e82bca4f7f4745476c4e Mon Sep 17 00:00:00 2001 From: Alexander Kassouni Date: Sat, 5 Sep 2026 17:51:13 -0700 Subject: init --- docs/quirks.html | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 docs/quirks.html (limited to 'docs/quirks.html') diff --git a/docs/quirks.html b/docs/quirks.html new file mode 100644 index 0000000..bb860c9 --- /dev/null +++ b/docs/quirks.html @@ -0,0 +1,157 @@ + + + + + +8. Quirks, dead code & corrections — Animalese + + + + + + +

8. Quirks, dead code & corrections

+

Things a faithful port has to reproduce, things a clean reimplementation +should drop, and where earlier notes were wrong.

+ +

Bugs that shipped

+ +

Glyph scale → volume is a dead store

+
if (scale > 0x20) {
+    scale = scale - 0x20;
+    f31 = scale;
+    f31 = f31 * 0.15f;
+    f30 = sou_voice_se[0]._08 + f31;   // computed…
+    f30 = 4.f;                          // …and immediately discarded
+    sou_voice_se[0]._08 = f30;
+} else {
+    scale = 0x1f - scale;
+    f31 = scale * 0.02f;
+    f30 = sou_voice_se[0]._08 - f31;    // computed…
+    f30 = 0.4f;                         // …and immediately discarded
+    sou_voice_se[0]._08 = f30;
+}
+

game64.c_inc:2994

+

The intent was clearly a smooth scale-to-volume ramp. What ships is a step function: +any glyph larger than normal slams volume to 4.0 (a 6× jump over the +0.65 baseline), anything smaller to 0.4. Normal-size text passes +scale == 32 and skips the block entirely, so this is only audible on +deliberately scaled dialogue.

+

This is in the matching decomp, so retail does it. A faithful port needs it; a clean +library does not.

+ +

The mode-2 dedup check is tautological

+
case 2: {
+    if (sou_num_org == sou_num_org && sou_num_org == sou_last_num2) i = 1;
+}
+

game64.c_inc:2711

+

The first comparison is always true. The intent was presumably a three-in-a-row check +mirroring mode 0; the effect is a two-in-a-row check. Deferred syllables therefore +trigger the random substitution more often than intended.

+ +

SHIIN2BOIN is dead, and would read out of bounds

+
const u8 SHIIN2BOIN[] = { 0, 1, 2, 3, 4, 5, 1, 2, … };   // 86 entries
+…
+sou_now_boin = SHIIN2BOIN[a];    // a can be up to 0x77 = 119
+

game64.c_inc:236, written at :2863

+

sou_now_boin is written here and initialised in Sou_InitAudio, and +never read anywhere in the tree. Same for sou_nobasu_count +("elongation count"), which is only ever set to 0. Both are vestigial mouth-shape / +vowel tracking, presumably live in the N64 Dōbutsu no Mori code this was ported +from. Because the table is 86 entries and a can reach 119, the write reads +past the array — harmless only because the result is discarded.

+

The table also has an obvious data oddity: entry 45 is the value 45, where +every neighbour is 0–5.

+ +

Design choices that surprise

+ + + +

Corrections to earlier notes

+ +

The following supersede statements in ../extraction.md as originally written.

+ + + + + + + + + + + + + + + + + + + + + + + + +
WasActually
"Bank 157 has only 83 instruments … that voice collapses every digraph sample +above 0x53 onto one sound."Nothing above 0x53 is a digraph. The phonology engine's maximum output is +0x52, plus 0x77. Bank 157 covers the phonology range exactly; the +missing block is the editor's letter names, unreachable at spec 3. +The only real loss is you.
"43 of the 119 codes are unreachable through normal text … only ever hit by the +anti-repetition random substitution."36 of them (0x53–0x76) are reachable — through the mode-1 +editor path — and the random substitution can not reach them, since it only +produces 0x00–0x3F.
"Sou_SpecialRoutine10 replays it on the next audio frame."It runs inside Na_GameFrame, which graph.c calls once per +game frame. Same ~17 ms at 60 fps, but the mechanism is the game loop, and it +halves under SetGameFrame(2).
"♪ … calls Na_MelodyVoice(npc_id) — the villager's tune."It plays a fixed 16-note pattern {13, 14 × 15}, not a tune. The per-NPC +part is which instrument: npc_voice_id selects a chunk of sequence +248 to copy in. It is the speaker's timbre playing a constant figure.
Specs 5 and 6 listed only in the spec→sequence table, unattributed.They are the player's own voice in text-entry menus — 5 male, 6 +female — set from m_submenu.c:364, and are special-cased throughout +Na_VoiceSe.
Voice mode not covered.Three modes gate the whole pipeline, and the gate depends on the message, not just +the config. See gating.
Mode f == 1 not covered.A third calling convention that bypasses phonology entirely. See +the editor path.
+ +

Everything else in extraction.md §1 was re-verified against the current tree +and holds: the voice table, the 55 digraph entries, both vowel tables, the per-spec +timbre values, and the spec→sequence→bank mapping.

+ +
+ ← 7. The editor path + 9. Reference tables → +
+ + + -- cgit v1.3.1