aboutsummaryrefslogtreecommitdiff
path: root/doc/esf.txt
blob: d35d17348492a853958f160f997989566cec4b04 (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
=============================================================================

OVERVIEW

    ESF stands for "Echo Stream Format". This is the format in which BGM and
    SFX sequences are stored. Essentially this is the music arrangement data.
    The format is mostly the same for both BGM and SFX, with just a few
    exceptions.

FORMAT

    ESF is a streamed format (think MIDI without the useless complexity).
    It's stored as a sequence of events, where each event takes up between
    one and three bytes. An event could be something like "note on", "set
    volume", "stop", etc.

CHANNEL LOCKING

    When both BGM and SFX are being played, it's likely that some channels
    may get used by both. In this case, Echo will give the SFX privilege over
    those channels.
    
    This is achieved by channel "locking". When the SFX starts, it first
    locks the channels it needs to use. When the SFX ends, those channels get
    unlocked. BGM won't play on the locked channels while the SFX is playing.

=============================================================================

EVENT LIST

    $00nn ..... Note on FM channel #1
    $01nn ..... Note on FM channel #2
    $02nn ..... Note on FM channel #3
    $04nn ..... Note on FM channel #4
    $05nn ..... Note on FM channel #5
    $06nn ..... Note on FM channel #6
    $08nn ..... Note on PSG channel #1
    $09nn ..... Note on PSG channel #2
    $0Ann ..... Note on PSG channel #3
    $0Bnn ..... Note on PSG channel #4
    $0Cnn ..... Note on PCM channel
    
    $10 ....... Note off FM channel #1
    $11 ....... Note off FM channel #2
    $12 ....... Note off FM channel #3
    $14 ....... Note off FM channel #4
    $15 ....... Note off FM channel #5
    $16 ....... Note off FM channel #6
    $18 ....... Note off PSG channel #1
    $19 ....... Note off PSG channel #2
    $1A ....... Note off PSG channel #3
    $1B ....... Note off PSG channel #4
    $1C ....... Note off PCM channel
    
    $20nn ..... Set volume FM channel #1
    $21nn ..... Set volume FM channel #2
    $22nn ..... Set volume FM channel #3
    $24nn ..... Set volume FM channel #4
    $25nn ..... Set volume FM channel #5
    $26nn ..... Set volume FM channel #6
    $28nn ..... Set volume PSG channel #1
    $29nn ..... Set volume PSG channel #2
    $2Ann ..... Set volume PSG channel #3
    $2Bnn ..... Set volume PSG channel #4
    
    $30nnnn ... Set frequency FM channel #1
    $31nnnn ... Set frequency FM channel #2
    $32nnnn ... Set frequency FM channel #3
    $34nnnn ... Set frequency FM channel #4
    $35nnnn ... Set frequency FM channel #5
    $36nnnn ... Set frequency FM channel #6
    $38nnnn ... Set frequency PSG channel #1
    $39nnnn ... Set frequency PSG channel #2
    $3Annnn ... Set frequency PSG channel #3
    $3Bnn ..... Set noise type PSG channel #4
    
    $40nn ..... Set instrument FM channel #1
    $41nn ..... Set instrument FM channel #2
    $42nn ..... Set instrument FM channel #3
    $44nn ..... Set instrument FM channel #4
    $45nn ..... Set instrument FM channel #5
    $46nn ..... Set instrument FM channel #6
    $48nn ..... Set instrument PSG channel #1
    $49nn ..... Set instrument PSG channel #2
    $4Ann ..... Set instrument PSG channel #3
    $4Bnn ..... Set instrument PSG channel #4
    
    $Dn ....... Delay ticks (short)
    
    $E0 ....... [SFX] Lock FM channel #1
    $E1 ....... [SFX] Lock FM channel #2
    $E2 ....... [SFX] Lock FM channel #3
    $E4 ....... [SFX] Lock FM channel #4
    $E5 ....... [SFX] Lock FM channel #5
    $E6 ....... [SFX] Lock FM channel #6
    $E8 ....... [SFX] Lock PSG channel #1
    $E9 ....... [SFX] Lock PSG channel #2
    $EA ....... [SFX] Lock PSG channel #3
    $EB ....... [SFX] Lock PSG channel #4
    
    $F0nn ..... Set parameters FM channel #1
    $F1nn ..... Set parameters FM channel #2
    $F2nn ..... Set parameters FM channel #3
    $F4nn ..... Set parameters FM channel #4
    $F5nn ..... Set parameters FM channel #5
    $F6nn ..... Set parameters FM channel #6
    
    $F8rrnn ... Set FM register in bank 0
    $F9rrnn ... Set FM register in bank 1
    $FAnn ..... Set flags
    $FBnn ..... Clear flags
    
    $FC ....... [BGM] Go to loop
    $FD ....... [BGM] Set loop point
    $FEnn ..... Delay ticks (long)
    $FF ....... Stop playback

=============================================================================

$00nn: Note on FM channel #1
$01nn: Note on FM channel #2
$02nn: Note on FM channel #3
$04nn: Note on FM channel #4
$05nn: Note on FM channel #5
$06nn: Note on FM channel #6

    These events do a "note on" at the specified FM channel. The event is
    followed by a byte, which indicates which note to play. The value is as
    follows, where "octave" ranges from 0 to 7 and "semitone" ranges from 0
    to 11:
    
        32 * octave + 2 * semitone + 1

$08nn: Note on PSG channel #1
$09nn: Note on PSG channel #2
$0Ann: Note on PSG channel #3

    These events do a "note on" at the specified square wave PSG channel.
    The event is followed by a byte, which indicates which note to play. The
    value is as follows, where "octave" ranges from 0 to 5 and "semitone"
    ranges from 0 to 11:
    
        24 * octave + 2 * semitone

$0Bnn: Note on PSG channel #4

    This event does a "note on" at the noise PSG channel. The event is
    followed by a byte, which indicates what kind of noise to play. The
    following values are valid:
    
        $00 ... Periodic noise, high pitch
        $01 ... Periodic noise, medium pitch
        $02 ... Periodic noise, low pitch
        $03 ... Periodic noise, PSG3 frequency
        $04 ... White noise, high pitch
        $05 ... White noise, medium pitch
        $06 ... White noise, low pitch
        $07 ... White noise, PSG3 frequency
    
    When using values $03 and $07, the third square wave PSG channel controls
    the noise frequency. You can change this frequency using the events to
    change the frequency of that channel (usually you'd use event type $3A).

$0Cnn: Note on PCM channel

    This event does a "note on" at the PCM channel. More specifically, it
    starts playback of a PCM sample. This event is followed by a byte, that
    specifies an index in the pointer list indicating where's the sample
    data. Samples are stored as EWF (Echo Waveform Format).
    
    NOTE: FM channel #6 will be disabled. That channel will be re-enabled
    when PCM playback is over (either because the waveform is over or because
    the channel is stopped explicitly).

=============================================================================

$10: Note off FM channel #1
$11: Note off FM channel #2
$12: Note off FM channel #3
$14: Note off FM channel #4
$15: Note off FM channel #5
$16: Note off FM channel #6
$18: Note off PSG channel #1
$19: Note off PSG channel #2
$1A: Note off PSG channel #3
$1B: Note off PSG channel #4

    These events do a "note off" at the specified channel.

$1C: Note off PCM channel

    This event does a "note off" at the PCM channel. This means that any PCM
    playback is immediately stopped. FM channel #6 is immediately enabled as
    well.

=============================================================================

$20nn: Set volume FM channel #1
$21nn: Set volume FM channel #2
$22nn: Set volume FM channel #3
$24nn: Set volume FM channel #4
$25nn: Set volume FM channel #5
$26nn: Set volume FM channel #6

    These events set the volume of a specific FM channel. The event is
    followed by a byte, which indicates the new volume. A value of $00 is the
    loudest, a value of $7F is the quietest.

$28nn: Set volume PSG channel #1
$29nn: Set volume PSG channel #2
$2Ann: Set volume PSG channel #3
$2Bnn: Set volume PSG channel #4

    These events set the volume of a specific PSG channel. The event is
    followed by a byte, which indicates the new volume. A value of $00 is the
    loudest, a value of $0F is the quietest.

=============================================================================

$30nn/$30nnnn: Set frequency FM channel #1
$31nn/$31nnnn: Set frequency FM channel #2
$32nn/$32nnnn: Set frequency FM channel #3
$34nn/$34nnnn: Set frequency FM channel #4
$35nn/$35nnnn: Set frequency FM channel #5
$36nn/$36nnnn: Set frequency FM channel #6

    These events set the raw frequency of a specific FM channel, without
    triggering a new note. Meant for note slides. The format of this event
    depends on whether the second byte has its MSB set or not.

    If the 2nd byte's MSB is set, the event is two bytes long. The 2nd byte
    is the semitone in this format (where "octave" is from 0 to 7 and
    "semitone" is from 0 to 11):

        octave * 16 + semitone + 128

    If the 2nd byte's MSB is clear, the event is three bytes long. The 2nd
    and 3rd bytes specify the new frequency in the same format as the YM2612
    expects. The 2nd byte is register $A4+, the 3rd byte is register $A0+.

    Echo uses the following frequency values for each semitone:

        C  - 644 | E  - 810 | G# - 1021
        C# - 681 | F  - 858 | A  - 1081
        D  - 722 | F# - 910 | A# - 1146
        D# - 765 | G  - 964 | B  - 1214

$38nn/$38nnnn: Set frequency PSG channel #1
$39nn/$39nnnn: Set frequency PSG channel #2
$3Ann/$3Annnn: Set frequency PSG channel #3

    These events set the raw frequency of a specific square wave PSG channel,
    without triggering a new note. Meant for note slides. The format of this
    event depends on whether the second byte has its MSB set or not.

    If the 2nd byte's MSB is set, the event is two bytes long. The 2nd byte
    is the semitone in this format (where "octave" is from 0 to 5 and
    "semitone" is from 0 to 11):

        octave * 12 + semitone + 128

    If the 2nd byte's MSB is clear, the event is three bytes long. The 2nd
    and 3rd bytes specify the new frequency, the 2nd byte containing the
    four least significant bits (LSB aligned), and the 3rd byte containing
    the six most significant bits (LSB aligned too).

    IMPORTANT: using the 3-byte event prevents semitone shifting in PSG
    instruments from working. It will start working again whenever a new note
    or the 2-byte version of this event is used.

    Echo uses the following frequency values for each semitone:
    
           |Oct.0|Oct.1|Oct.2|Oct.3|Oct.4|Oct.5
        ---|-----|-----|-----|-----|-----|-----
        C  | 851 | 425 | 212 | 106 |  53 |  26
        C# | 803 | 401 | 200 | 100 |  50 |  25
        D  | 758 | 379 | 189 |  94 |  47 |  23
        D# | 715 | 357 | 178 |  89 |  44 |  22
        E  | 675 | 337 | 168 |  84 |  42 |  21
        F  | 637 | 318 | 159 |  79 |  39 |  19
        F# | 601 | 300 | 150 |  75 |  37 |  18
        G  | 568 | 284 | 142 |  71 |  35 |  17
        G# | 536 | 268 | 134 |  67 |  33 |  16
        A  | 506 | 253 | 126 |  63 |  31 |  15
        A# | 477 | 238 | 119 |  59 |  29 |  14
        B  | 450 | 225 | 112 |  56 |  28 |  14

$3Bnn: Set noise type PSG channel #4

    This event works like event $0Bnn, but it doesn't trigger a note attack
    (i.e. instrument envelope won't be reset, note won't start playing if it
    wasn't already).

=============================================================================

$40nn: Set instrument FM channel #1
$41nn: Set instrument FM channel #2
$42nn: Set instrument FM channel #3
$44nn: Set instrument FM channel #4
$45nn: Set instrument FM channel #5
$46nn: Set instrument FM channel #6

    These events are used to set the instrument to be used by a specific FM
    channel. The event is followed by a byte, which has an index in the
    pointer list that indicates where's the FM instrument data. Instruments
    are stored as EIF (Echo Instrument Format).

$48nn: Set instrument PSG channel #1
$49nn: Set instrument PSG channel #2
$4Ann: Set instrument PSG channel #3
$4Bnn: Set instrument PSG channel #4

    These events are used to set the instrument to be used by a specific PSG
    channel. The event is followed by a byte, which has an index in the
    pointer list that indicates where's the PSG instrument data. Instruments
    are stored as EEF (Echo Envelope Format).

=============================================================================

$D0~$DF: Delay ticks (short)

    Same as $FE01 to $FE10 ($D0 = $FE01, $D1 = $FE02, etc.). Just a shorter
    variant of the event to reduce space usage for shorter delays (which are
    the most common).

=============================================================================

$E0: Lock FM channel #1 [SFX ONLY]
$E1: Lock FM channel #2 [SFX ONLY]
$E2: Lock FM channel #3 [SFX ONLY]
$E4: Lock FM channel #4 [SFX ONLY]
$E5: Lock FM channel #5 [SFX ONLY]
$E6: Lock FM channel #6 [SFX ONLY]
$E8: Lock PSG channel #1 [SFX ONLY]
$E9: Lock PSG channel #1 [SFX ONLY]
$EA: Lock PSG channel #1 [SFX ONLY]
$EB: Lock PSG channel #1 [SFX ONLY]

    These events are used to "lock" specific channels. When a channel is
    locked, BGM can't mess up with it. All channels used by a SFX must be
    locked before they're used. Channels get unlocked when the SFX stream is
    over.
    
    To lock the PCM channel, you need to lock FM channel #6 (event $E6). Echo
    will behave accordingly.

=============================================================================

$F0: Set parameters FM channel #1
$F1: Set parameters FM channel #2
$F2: Set parameters FM channel #3
$F4: Set parameters FM channel #4
$F5: Set parameters FM channel #5
$F6: Set parameters FM channel #6

    These events set up some miscellaneous parameters for the FM channels.
    The event is followed by a byte, which speficies the new parameters to be
    used. The format of this byte is as follows:
    
        Bit 7 ..... 1 to enable left speaker, 0 to mute it
        Bit 6 ..... 1 to enable right speaker, 0 to mute it
        Bit 5-0 ... Must be 0

=============================================================================

$F8rrnn: Set FM register in bank 0
$F9rrnn: Set FM register in bank 1

    These events are used to change the value of a YM2612 register directly.
    The rr byte indicates the register, the nn byte is the value to be
    written into it ($F8 writes to $4000/1, $F9 writes to $4002/3).
    
    HERE BE DRAGONS, USE AT YOUR OWN RISK. The channel locking mechanism will
    *not* take care of this event, and if a SFX locks the channel then the
    register will *not* be restored properly once the SFX is over.
    
    More specifically:
    
        * If you use it on a BGM, don't let it touch any channels that may
          get locked by SFXs.
        
        * If you use it on a SFX for an effect on the SFX itself, use it only
          for channels locked by that SFX.
        
        * If you use it on a SFX to affect the music, use it only on channels
          that are *not* locked by any SFX (same as first rule, actually).
        
        * It's possible to touch the global registers ($22~$2B in bank 0).
          Do it at your own risk. You may mess up with Echo's functionality,
          so be careful about it and make sure you know what you're doing.
    
    Since version 1.64, writes to register $27 are handled specially: only
    bits 7-6 are passed as-is while bits 5-0 are left to Echo. This is
    because this register selects ch3 mode but also has the bits that trigger
    the timers. This way, streams can change ch3 mode without risking Echo
    undoing the changes.

=============================================================================

$FAnn: Set flags

    This event will set some of the flags. The value nn is a bitmask that is
    OR'd with the current flags.

$FBnn: Clear flags

    This event will clear some of the flags. The value nn is a bitmask that
    is AND'd with the current flags.

=============================================================================

$FC: Go to loop
$FD: Set loop point

    This event are used in streams to loop music. Put event $FD where the
    loop starts, and then end the stream using event $FC (don't use event
    $FF). This will tell Echo to loop the song instead of stopping playback.
    
    SFX support for this event was added in 1.5, if you loop a sound effect
    you'll have to either stop it manually or play another SFX.

$FEnn: Delay ticks

    This event is used for timing. It tells Echo to wait a specific amount of
    ticks before continuing with the stream. A byte follows this event, it's
    the amount of ticks to wait. If it's $00, then Echo waits 256 ticks
    instead.
    
    If you need to wait more than 256 ticks, you can trigger this event
    several times in a row. For example, to wait 320 ticks, use this event
    twice: $FE00FE40 --> 256 ticks + 64 ticks = 320 ticks.
    
    One tick lasts 1/60th of a second.

$FF: Stop playback

    This event indicates the end of the stream and tells Echo to stop
    playback from this stream. If the stream was a SFX, then any locked
    channels will be unlocked as well.

=============================================================================