aboutsummaryrefslogtreecommitdiff
path: root/docs/editor.html
blob: 8e462420f02a142af5ceaa384e1dded36ff18a8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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>