aboutsummaryrefslogtreecommitdiff
path: root/docs/editor.html
diff options
context:
space:
mode:
authorAlexander Kassouni <alex@kassouni.net>2026-09-05 17:51:13 -0700
committerAlexander Kassouni <alex@kassouni.net>2026-09-05 17:51:13 -0700
commit46227e2003de28202cc4e82bca4f7f4745476c4e (patch)
treefe450ac33ffa13747613c3cfdf36ea24b3036c46 /docs/editor.html
init
Diffstat (limited to 'docs/editor.html')
-rw-r--r--docs/editor.html116
1 files changed, 116 insertions, 0 deletions
diff --git a/docs/editor.html b/docs/editor.html
new file mode 100644
index 0000000..8e46242
--- /dev/null
+++ b/docs/editor.html
@@ -0,0 +1,116 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>7. The editor path — Animalese</title>
+<link rel="stylesheet" href="style.css">
+</head>
+<body>
+
+<nav class="crumb"><a href="index.html">Animalese pipeline</a> / 7. The editor path</nav>
+
+<h1>7. The editor path</h1>
+<p class="lede">There is a third calling convention into <code>Na_VoiceSe</code> that skips
+the phonology engine entirely, and it explains what a third of the voice samples are
+for.</p>
+
+<h2>Mode 1</h2>
+
+<p>The text editor overlay — used for letters, town and player names, patterns, and
+anywhere else the player types — speaks each keystroke from
+<code>src/game/m_editor_ovl.c:712</code>:</p>
+
+<pre>if (command == mED_COMMAND_OUTPUT_CODE) {
+ int voice = mMsg_sound_voice_get_for_editor(editor_ovl-&gt;now_code);
+
+ if (voice == 0x85 || voice == 0x80 || voice == 0x81 ||
+ voice == 0x82 || voice == 0x83 || voice == -1)
+ voice = 0x86;
+
+ sAdo_VoiceSe(voice, 0xFF, 0xFF, 0, 32, 1); // ← mode 1
+}
+else if (command == mED_COMMAND_EXCHANGE_CODE) { // cursor moved onto a character
+ if (exchange_code != -1 &amp;&amp; mED_exchange_se_list[exchange_code])
+ sAdo_VoiceSe(mMsg_sound_voice_get_for_editor(exchange_code), 0xFF, 0xFF, 0, 32, 1);
+ else
+ sAdo_SysTrgStart(0x36);
+}</pre>
+
+<p>After both filters, only three things survive: letters (<code>0x5D</code>–<code>0x76</code>),
+digits (<code>0x53</code>–<code>0x5C</code>), and the click (<code>0x86</code>).</p>
+
+<h2>What mode 1 does inside Na_VoiceSe</h2>
+
+<p><code>Na_VoiceSe</code>'s two <code>switch (f)</code> blocks handle only cases 0 and 2.
+With <code>f == 1</code> both fall through, so:</p>
+
+<ul>
+ <li>no digraph merge, no vowel-length table, no silent&nbsp;e;</li>
+ <li><code>sou_num_org</code> etc. are never written, so <code>sou_last_num =
+ sou_num_org</code> further down just rewrites stale values — the message-path
+ history is not corrupted, but it is not updated either;</li>
+ <li><code>r28</code> is left uninitialised and never read;</li>
+ <li>nothing is queued for <code>Sou_SpecialRoutine10</code>;</li>
+ <li><strong><code>a</code> arrives at the playback stage as the raw voice code.</strong></li>
+</ul>
+
+<p>The editor always runs at spec 5 or 6 (see <a href="gating.html">gating</a>), which
+routes <code>0x86</code> to <code>NA_SE_BEBE</code> and passes everything else through. The
+final guard is <code>if (a != 0 &amp;&amp; a &lt;= 0x77)</code>, and letters and digits both
+satisfy it. So:</p>
+
+<pre>typing 'a' → Sou_VoiceStart(subtrack, 0x5D) → instrument 0x5C
+typing 'z' → Sou_VoiceStart(subtrack, 0x76) → instrument 0x75
+typing '0' → Sou_VoiceStart(subtrack, 0x53) → instrument 0x52</pre>
+
+<h2>What this tells us about the sample set</h2>
+
+<p>Trace the reachable phoneme codes across the whole engine:</p>
+
+<table>
+<tr><th>Code range</th><th>Instruments</th><th>Reached by</th></tr>
+<tr><td><code>0x01</code>–<code>0x52</code></td><td>0–81</td><td>the phonology engine — short/long vowels, consonants, all 52 two-character digraphs plus <code>you</code></td></tr>
+<tr><td><code>0x01</code>–<code>0x40</code></td><td></td><td>also the anti-repetition random substitution (<code>rand() &gt;&gt; 2</code>)</td></tr>
+<tr><td><code>0x53</code>–<code>0x76</code></td><td>82–117</td><td><strong>only mode 1</strong> — one entry per digit and letter, in order</td></tr>
+<tr><td><code>0x77</code></td><td>118</td><td>the <code>you</code> digraph, and nothing else</td></tr>
+</table>
+
+<p>The <code>0x53</code>–<code>0x76</code> block is exactly 36 codes: ten digits then
+twenty-six letters, in the same order as the voice-code alphabet, and it is
+unreachable through any dialogue. The obvious reading is that these 36 samples are the
+<strong>spoken names of the digits and letters</strong> — what you hear when typing a name
+one character at a time.</p>
+
+<div class="note">
+<strong>Confidence.</strong> The code path is unambiguous; the interpretation of the samples
+as letter names is inference. It is testable: extract instruments 82–117 from bank 156
+and listen. It also predicts that bank 157, which stops at 83 instruments, is a
+phonology-only bank — and that is exactly what it is.
+</div>
+
+<h2>Why bank 157 is short</h2>
+
+<p>Spec 3 (Wendell, Pete, Booker, Jack) uses sequence 244 / bank 157, which has 83
+instruments — codes <code>0x01</code>–<code>0x53</code>. That covers the entire phonology
+output range (<code>≤ 0x52</code>) with one to spare, and omits the letter-name block
+that spec 3 can never reach, since the editor is always spec 5 or 6.</p>
+
+<p>The one real casualty is <code>you</code> (<code>0x77</code>): the sequence's dynamic
+table clamps out-of-range entries to the last routine, so a spec-3 voice saying "you"
+plays instrument 82 instead. That is one wrong syllable on a common word, in four
+NPCs' voices.</p>
+
+<div class="note">
+This corrects an earlier reading of <code>extraction.md</code> §2.4, which described bank 157
+as "collapsing every digraph sample above <code>0x53</code> onto one sound". Nothing above
+<code>0x53</code> is a digraph — the block is not phonology at all.
+</div>
+
+<div class="pager">
+ <span><a href="soundfont.html">← 6. The soundfont lookup</a></span>
+ <span><a href="quirks.html">8. Quirks &amp; corrections →</a></span>
+</div>
+
+</body>
+</html>