Mario Kart 64
abi.h
Go to the documentation of this file.
1 #ifndef _ABI_H_
2 #define _ABI_H_
3 
4 /**************************************************************************
5  * *
6  * Copyright (C) 1994, Silicon Graphics, Inc. *
7  * *
8  * These coded instructions, statements, and computer programs contain *
9  * unpublished proprietary information of Silicon Graphics, Inc., and *
10  * are protected by Federal copyright law. They may not be disclosed *
11  * to third parties or copied or duplicated in any form, in whole or *
12  * in part, without the prior written consent of Silicon Graphics, Inc. *
13  * *
14  **************************************************************************/
15 
16 /**************************************************************************
17  *
18  * $Revision: 1.32 $
19  * $Date: 1997/02/11 08:16:37 $
20  * $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/abi.h,v $
21  *
22  **************************************************************************/
23 
24 /*
25  * Header file for the Audio Binary Interface.
26  * This is included in the Media Binary Interface file
27  * mbi.h.
28  *
29  * This file follows the framework used for graphics.
30  *
31  */
32 
33 /* Audio commands: */
34 #define A_SPNOOP 0
35 #define A_ADPCM 1
36 #define A_CLEARBUFF 2
37 #define A_RESAMPLE 5
38 #define A_SETBUFF 8
39 #define A_DMEMMOVE 10
40 #define A_LOADADPCM 11
41 #define A_MIXER 12
42 #define A_INTERLEAVE 13
43 #define A_SETLOOP 15
44 
45 #if !(defined(VERSION_SH) || defined(VERSION_US) || defined(VERSION_EU))
46 
47 #define A_ENVMIXER 3
48 #define A_LOADBUFF 4
49 #define A_RESAMPLE 5
50 #define A_SAVEBUFF 6
51 #define A_SEGMENT 7
52 #define A_SETVOL 9
53 #define A_POLEF 14
54 
55 #else
56 
57 #define A_ADDMIXER 4
58 #define A_RESAMPLE_ZOH 6
59 #define A_SEGMENT 7
60 #define A_DMEMMOVE2 16
61 #define A_DOWNSAMPLE_HALF 17
62 #define A_ENVSETUP1 18
63 #define A_ENVMIXER 19
64 #define A_LOADBUFF 20
65 #define A_SAVEBUFF 21
66 #define A_ENVSETUP2 22
67 #define A_S8DEC 23
68 #define A_HILOGAIN 24
69 #define A_UNK_25 25
70 #define A_DUPLICATE 26
71 #define A_FILTER 27
72 
73 #endif
74 
75 #define ACMD_SIZE 32
76 /*
77  * Audio flags
78  */
79 
80 #define A_INIT 0x01
81 #define A_CONTINUE 0x00
82 #define A_LOOP 0x02
83 #define A_OUT 0x02
84 #define A_LEFT 0x02
85 #define A_RIGHT 0x00
86 #define A_VOL 0x04
87 #define A_RATE 0x00
88 #define A_AUX 0x08
89 #define A_NOAUX 0x00
90 #define A_MAIN 0x00
91 #define A_MIX 0x10
92 
93 /*
94  * BEGIN C-specific section: (typedef's)
95  */
96 #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
97 
98 /*
99  * Data Structures.
100  */
101 
102 typedef struct {
103  unsigned int cmd:8;
104  unsigned int flags:8;
105  unsigned int gain:16;
106  unsigned int addr;
107 } Aadpcm;
108 
109 typedef struct {
110  unsigned int cmd:8;
111  unsigned int flags:8;
112  unsigned int gain:16;
113  unsigned int addr;
114 } Apolef;
115 
116 typedef struct {
117  unsigned int cmd:8;
118  unsigned int flags:8;
119  unsigned int pad1:16;
120  unsigned int addr;
121 } Aenvelope;
122 
123 typedef struct {
124  unsigned int cmd:8;
125  unsigned int pad1:8;
126  unsigned int dmem:16;
127  unsigned int pad2:16;
128  unsigned int count:16;
129 } Aclearbuff;
130 
131 typedef struct {
132  unsigned int cmd:8;
133  unsigned int pad1:8;
134  unsigned int pad2:16;
135  unsigned int inL:16;
136  unsigned int inR:16;
137 } Ainterleave;
138 
139 typedef struct {
140  unsigned int cmd:8;
141  unsigned int pad1:24;
142  unsigned int addr;
143 } Aloadbuff;
144 
145 typedef struct {
146  unsigned int cmd:8;
147  unsigned int flags:8;
148  unsigned int pad1:16;
149  unsigned int addr;
150 } Aenvmixer;
151 
152 typedef struct {
153  unsigned int cmd:8;
154  unsigned int flags:8;
155  unsigned int gain:16;
156  unsigned int dmemi:16;
157  unsigned int dmemo:16;
158 } Amixer;
159 
160 typedef struct {
161  unsigned int cmd:8;
162  unsigned int flags:8;
163  unsigned int dmem2:16;
164  unsigned int addr;
165 } Apan;
166 
167 typedef struct {
168  unsigned int cmd:8;
169  unsigned int flags:8;
170  unsigned int pitch:16;
171  unsigned int addr;
172 } Aresample;
173 
174 typedef struct {
175  unsigned int cmd:8;
176  unsigned int flags:8;
177  unsigned int pad1:16;
178  unsigned int addr;
179 } Areverb;
180 
181 typedef struct {
182  unsigned int cmd:8;
183  unsigned int pad1:24;
184  unsigned int addr;
185 } Asavebuff;
186 
187 typedef struct {
188  unsigned int cmd:8;
189  unsigned int pad1:24;
190  unsigned int pad2:2;
191  unsigned int number:4;
192  unsigned int base:24;
193 } Asegment;
194 
195 typedef struct {
196  unsigned int cmd:8;
197  unsigned int flags:8;
198  unsigned int dmemin:16;
199  unsigned int dmemout:16;
200  unsigned int count:16;
201 } Asetbuff;
202 
203 typedef struct {
204  unsigned int cmd:8;
205  unsigned int flags:8;
206  unsigned int vol:16;
207  unsigned int voltgt:16;
208  unsigned int volrate:16;
209 } Asetvol;
210 
211 typedef struct {
212  unsigned int cmd:8;
213  unsigned int pad1:8;
214  unsigned int dmemin:16;
215  unsigned int dmemout:16;
216  unsigned int count:16;
217 } Admemmove;
218 
219 typedef struct {
220  unsigned int cmd:8;
221  unsigned int pad1:8;
222  unsigned int count:16;
223  unsigned int addr;
224 } Aloadadpcm;
225 
226 typedef struct {
227  unsigned int cmd:8;
228  unsigned int pad1:8;
229  unsigned int pad2:16;
230  unsigned int addr;
231 } Asetloop;
232 
233 /*
234  * Generic Acmd Packet
235  */
236 
237 typedef struct {
238  uintptr_t w0;
239  uintptr_t w1;
240 } Awords;
241 
242 typedef union {
243  Awords words;
244 #if IS_BIG_ENDIAN && !IS_64_BIT
245  Aadpcm adpcm;
246  Apolef polef;
247  Aclearbuff clearbuff;
248  Aenvelope envelope;
249  Ainterleave interleave;
250  Aloadbuff loadbuff;
251  Aenvmixer envmixer;
252  Aresample resample;
253  Areverb reverb;
254  Asavebuff savebuff;
255  Asegment segment;
256  Asetbuff setbuff;
257  Asetvol setvol;
258  Admemmove dmemmove;
259  Aloadadpcm loadadpcm;
260  Amixer mixer;
261  Asetloop setloop;
262 #endif
263  long long int force_union_align; /* dummy, force alignment */
264 } Acmd;
265 
266 /*
267  * ADPCM State
268  */
269 typedef short ADPCM_STATE[16];
270 
271 /*
272  * Pole filter state
273  */
274 typedef short POLEF_STATE[4];
275 
276 /*
277  * Resampler state
278  */
279 typedef short RESAMPLE_STATE[16];
280 
281 /*
282  * Resampler constants
283  */
284 #define UNITY_PITCH 0x8000
285 #define MAX_RATIO 1.99996 /* within .03 cents of +1 octave */
286 
287 /*
288  * Enveloper/Mixer state
289  */
290 typedef short ENVMIX_STATE[40];
291 
292 /*
293  * Macros to assemble the audio command list
294  */
295 
296 /*
297  * Info about parameters:
298  *
299  * A "count" in the following macros is always measured in bytes.
300  *
301  * All volumes/gains are in Q1.15 signed fixed point numbers:
302  * 0x8000 is the minimum volume (-100%), negating the audio curve.
303  * 0x0000 is silent.
304  * 0x7fff is maximum volume (99.997%).
305  *
306  * All DRAM addresses refer to segmented addresses. A segment table shall
307  * first be set up by calling aSegment for each segment. When a DRAM
308  * address is later used as parameter, the 8 high bits will be an index
309  * to the segment table and the lower 24 bits are added to the base address
310  * stored in the segment table for this entry. The result is the physical address.
311  * With the newer rsp audio code, this segment table is not used. The address is
312  * used directly instead.
313  *
314  * Transfers to/from DRAM are executed using DMA and hence follow these restrictions:
315  * All DRAM addresses should be aligned by 8 bytes, or they will be
316  * rounded down to the nearest multiple of 8 bytes.
317  * All DRAM lengths should be aligned by 8 bytes, or they will be
318  * rounded up to the nearest multiple of 8 bytes.
319  */
320 
321 /*
322  * Decompresses ADPCM data.
323  * Possible flags: A_INIT and A_LOOP.
324  *
325  * First set up internal data in DMEM:
326  * aLoadADPCM(cmd++, nEntries * 16, physicalAddressOfBook)
327  * aSetLoop(cmd++, physicalAddressOfLoopState) (if A_LOOP is set)
328  *
329  * Then before this command, call:
330  * aSetBuffer(cmd++, 0, in, out, count)
331  *
332  * Note: count will be rounded up to the nearest multiple of 32 bytes.
333  *
334  * ADPCM decompression works on a block of 16 (uncompressed) samples.
335  * The previous 2 samples and 9 bytes of input are decompressed to
336  * 16 new samples using the code book previously loaded.
337  *
338  * Before the algorithm starts, the previous 16 samples are loaded according to flag:
339  * A_INIT: all zeros
340  * A_LOOP: the address set by aSetLoop
341  * no flags: the DRAM address in the s parameter
342  * These 16 samples are immediately copied to the destination address.
343  *
344  * The result of "count" bytes will be written after these 16 initial samples.
345  * The last 16 samples written to the destination will also be written to
346  * the state address in DRAM.
347  */
348 #define aADPCMdec(pkt, f, s) \
349 { \
350  Acmd *_a = (Acmd *)pkt; \
351  \
352  _a->words.w0 = _SHIFTL(A_ADPCM, 24, 8) | _SHIFTL(f, 16, 8); \
353  _a->words.w1 = (uintptr_t)(s); \
354 }
355 
356 /*
357  * Not used in SM64.
358  */
359 #define aPoleFilter(pkt, f, g, s) \
360 { \
361  Acmd *_a = (Acmd *)pkt; \
362  \
363  _a->words.w0 = (_SHIFTL(A_POLEF, 24, 8) | _SHIFTL(f, 16, 8) | \
364  _SHIFTL(g, 0, 16)); \
365  _a->words.w1 = (uintptr_t)(s); \
366 }
367 
368 /*
369  * Clears DMEM data, where d is address and c is count, by writing zeros.
370  *
371  * Note: c is rounded up to the nearest multiple of 16 bytes.
372  */
373 #define aClearBuffer(pkt, d, c) \
374 { \
375  Acmd *_a = (Acmd *)pkt; \
376  \
377  _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \
378  _a->words.w1 = (uintptr_t)(c); \
379 }
380 
381 /*
382  * Mixes an envelope with mono sound into 2 or 4 channels.
383  * Possible flags: A_INIT, A_AUX (indicates that 4 channels should be used).
384  *
385  * Before this command, call:
386  * aSetBuffer(cmd++, 0, inBuf, dryLeft, count)
387  * aSetBuffer(cmd++, A_AUX, dryRight, wetLeft, wetRight)
388  *
389  * The first time (A_INIT is set), volume also needs to be set:
390  * aSetVolume(cmd++, A_VOL | A_LEFT, initialVolumeLeft, 0, 0)
391  * aSetVolume(cmd++, A_VOL | A_RIGHT, initialVolumeRight, 0, 0)
392  * aSetVolume32(cmd++, A_RATE | A_LEFT, targetVolumeLeft, rampLeft)
393  * aSetVolume32(cmd++, A_RATE | A_RIGHT, targetVolumeRight, rampRight)
394  * aSetVolume(cmd++, A_AUX, dryVolume, 0, wetVolume)
395  *
396  * This command will now mix samples in inBuf into the destination buffers (dry and wet),
397  * but with the volume increased (or decreased) from initial volumes to target volumes,
398  * with the specified ramp rate. Once the target volume is reached, the volume stays
399  * at that level. Before the samples are finally mixed (added) into the destination
400  * buffers (dry and wet), the volume is changed according to dryVolume and wetVolume.
401  *
402  * Note: count will be rounded up to the nearest multiple of 16 bytes.
403  * Note: the wet channels are used for reverb.
404  *
405  */
406 #define aEnvMixer(pkt, f, s) \
407 { \
408  Acmd *_a = (Acmd *)pkt; \
409  \
410  _a->words.w0 = _SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL(f, 16, 8); \
411  _a->words.w1 = (uintptr_t)(s); \
412 }
413 
414 /*
415  * Interleaves two mono channels into stereo.
416  *
417  * First call:
418  * aSetBuffer(cmd++, 0, 0, output, count)
419  *
420  * The count refers to the size of each input. Hence 2 * count bytes will be written out.
421  * A left sample will be placed before the right sample.
422  *
423  * Note: count will be rounded up to the nearest multiple of 16 bytes.
424  */
425 #define aInterleave(pkt, l, r) \
426 { \
427  Acmd *_a = (Acmd *)pkt; \
428  \
429  _a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8); \
430  _a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \
431 }
432 
433 /*
434  * Loads a buffer from DRAM to DMEM.
435  *
436  * First call:
437  * aSetBuffer(cmd++, 0, in, 0, count)
438  *
439  * The in parameter to aSetBuffer is the destination in DMEM and the
440  * s parameter to this command is the source in DRAM.
441  */
442 #define aLoadBuffer(pkt, s) \
443 { \
444  Acmd *_a = (Acmd *)pkt; \
445  \
446  _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8); \
447  _a->words.w1 = (uintptr_t)(s); \
448 }
449 
450 /*
451  * Mixes audio.
452  * Possible flags: no flags used, although parameter present.
453  *
454  * First call:
455  * aSetBuffer(cmd++, 0, 0, 0, count)
456  *
457  * Input and output addresses are taken from the i and o parameters.
458  * The volume with which the input is changed is taken from the g parameter.
459  * After the volume of the input samples have been changed, the result
460  * is added to the output.
461  *
462  * Note: count will be rounded up to the nearest multiple of 32 bytes.
463  */
464 #define aMix(pkt, f, g, i, o) \
465 { \
466  Acmd *_a = (Acmd *)pkt; \
467  \
468  _a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | _SHIFTL(f, 16, 8) | \
469  _SHIFTL(g, 0, 16)); \
470  _a->words.w1 = _SHIFTL(i,16, 16) | _SHIFTL(o, 0, 16); \
471 }
472 
473 // Not present in the audio microcode.
474 #define aPan(pkt, f, d, s) \
475 { \
476  Acmd *_a = (Acmd *)pkt; \
477  \
478  _a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | \
479  _SHIFTL(d, 0, 16)); \
480  _a->words.w1 = (uintptr_t)(s); \
481 }
482 
483 /*
484  * Resamples audio.
485  * Possible flags: A_INIT, A_OUT? (not used in SM64).
486  *
487  * First call:
488  * aSetBuffer(cmd++, 0, in, out, count)
489  *
490  * This command resamples the audio using the given frequency ratio (pitch)
491  * using a filter that uses a window of 4 source samples. This can be used
492  * either for just resampling audio to be able to be played back at a different
493  * sample rate, or to change the pitch if the result is played back at
494  * the same sample rate as the input.
495  *
496  * The frequency ratio is given in UQ1.15 fixed point format.
497  * For no change in frequency, use pitch 0x8000.
498  * For 1 octave up or downsampling to (roughly) half number of samples, use pitch 0xffff.
499  * For 1 octave down or upsampling to double as many samples, use pitch 0x4000.
500  *
501  * Note: count represents the number of output sample bytes and is rounded up to
502  * the nearest multiple of 16 bytes.
503  *
504  * The state consists of the four following source samples when the algorithm stopped as
505  * well as a fractional position, and is initialized to all zeros if A_INIT is given.
506  * Otherwise it is loaded from DRAM at address s.
507  *
508  * The algorithm starts by writing the four source samples from the state (or zero)
509  * to just before the input address given. It then creates one output sample by examining
510  * the four next source samples and then moving the source position zero or more
511  * samples forward. The first output sample (when A_INIT is given) is always 0.
512  *
513  * When "count" bytes have been written, the following four source samples
514  * are written to the state in DRAM as well as a fractional position.
515  */
516 #define aResample(pkt, f, p, s) \
517 { \
518  Acmd *_a = (Acmd *)pkt; \
519  \
520  _a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | _SHIFTL(f, 16, 8) |\
521  _SHIFTL(p, 0, 16)); \
522  _a->words.w1 = (uintptr_t)(s); \
523 }
524 
525 /*
526  * Stores a buffer in DMEM to DRAM.
527  *
528  * First call:
529  * aSetBuffer(cmd++, 0, 0, out, count)
530  *
531  * The out parameter to aSetBuffer is the source in DMEM and the
532  * s parameter to this command is the destination in DRAM.
533  */
534 #define aSaveBuffer(pkt, s) \
535 { \
536  Acmd *_a = (Acmd *)pkt; \
537  \
538  _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8); \
539  _a->words.w1 = (uintptr_t)(s); \
540 }
541 
542 /*
543  * Sets up an entry in the segment table.
544  *
545  * The s parameter is a segment index, 0 to 15.
546  * The b parameter is the base offset.
547  */
548 #define aSegment(pkt, s, b) \
549 { \
550  Acmd *_a = (Acmd *)pkt; \
551  \
552  _a->words.w0 = _SHIFTL(A_SEGMENT, 24, 8); \
553  _a->words.w1 = _SHIFTL(s, 24, 8) | _SHIFTL(b, 0, 24); \
554 }
555 
556 /*
557  * Sets internal DMEM buffer addresses used for later commands.
558  * See each command for how to use aSetBuffer.
559  */
560 #define aSetBuffer(pkt, f, i, o, c) \
561 { \
562  Acmd *_a = (Acmd *)pkt; \
563  \
564  _a->words.w0 = (_SHIFTL(A_SETBUFF, 24, 8) | _SHIFTL(f, 16, 8) | \
565  _SHIFTL(i, 0, 16)); \
566  _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \
567 }
568 
569 /*
570  * Sets internal volume parameters.
571  * See aEnvMixer for more info.
572  */
573 #define aSetVolume(pkt, f, v, t, r) \
574 { \
575  Acmd *_a = (Acmd *)pkt; \
576  \
577  _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \
578  _SHIFTL(v, 0, 16)); \
579  _a->words.w1 = _SHIFTL(t, 16, 16) | _SHIFTL(r, 0, 16); \
580 }
581 
582 /*
583  * Sets the address to ADPCM loop state.
584  *
585  * The a parameter is a DRAM address.
586  * See aADPCMdec for more info.
587  */
588 #define aSetLoop(pkt, a) \
589 { \
590  Acmd *_a = (Acmd *)pkt; \
591  _a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \
592  _a->words.w1 = (uintptr_t)(a); \
593 }
594 
595 /*
596  * Copies memory in DMEM.
597  *
598  * Copies c bytes from address i to address o.
599  *
600  * Note: count is rounded up to the nearest multiple of 16 bytes.
601  *
602  * Note: This acts as memcpy where 16 bytes are moved at a time, therefore
603  * if input and output overlap, output address should be less than input address.
604  */
605 #define aDMEMMove(pkt, i, o, c) \
606 { \
607  Acmd *_a = (Acmd *)pkt; \
608  \
609  _a->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(i, 0, 24); \
610  _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \
611 }
612 
613 /*
614  * Loads ADPCM book from DRAM into DMEM.
615  *
616  * This command loads ADPCM table entries from DRAM to DMEM.
617  *
618  * The count parameter c should be a multiple of 16 bytes.
619  * The d parameter is a DRAM address.
620  */
621 #define aLoadADPCM(pkt, c, d) \
622 { \
623  Acmd *_a = (Acmd *)pkt; \
624  \
625  _a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \
626  _a->words.w1 = (uintptr_t) (d); \
627 }
628 
629 // This is a version of aSetVolume which takes a single 32-bit parameter
630 // instead of two 16-bit ones. According to AziAudio, it is used to set
631 // ramping values when neither bit 4 nor bit 8 is set in the flags parameter.
632 // It does not appear in the official abi.h header.
633 /*
634  * Sets internal volume parameters.
635  * See aEnvMixer for more info.
636  */
637 #define aSetVolume32(pkt, f, v, tr) \
638 { \
639  Acmd *_a = (Acmd *)pkt; \
640  \
641  _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \
642  _SHIFTL(v, 0, 16)); \
643  _a->words.w1 = (uintptr_t)(tr); \
644 }
645 
646 #if defined(VERSION_SH) || defined(VERSION_US) || defined (VERSION_EU)
647 #undef aLoadBuffer
648 #undef aSaveBuffer
649 #undef aMix
650 #undef aEnvMixer
651 // #undef aInterleave
652 
653 // New or modified operations in the new audio microcode below
654 
680 #define aS8Dec(pkt, f, s) \
681 { \
682  Acmd *_a = (Acmd *)pkt; \
683  \
684  _a->words.w0 = _SHIFTL(A_S8DEC, 24, 8) | _SHIFTL(f, 16, 8); \
685  _a->words.w1 = (uintptr_t)(s); \
686 }
687 
688 /*
689  * Mix two tracks by simple clamped addition.
690  *
691  * s: DMEM source track 1
692  * d: DMEM source track 2 and destination
693  * c: number of bytes to write
694  *
695  * Note: count is first rounded down to the nearest multiple of 16 bytes
696  * and then rounded up to the nearest multiple of 64 bytes.
697  */
698 #define aAddMixer(pkt, s, d, c) \
699 { \
700  Acmd *_a = (Acmd *)pkt; \
701  \
702  _a->words.w0 = (_SHIFTL(A_ADDMIXER, 24, 8) | \
703  _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(0x7fff, 0, 16)); \
704  _a->words.w1 = (_SHIFTL(s, 16, 16) | _SHIFTL(d, 0, 16)); \
705 }
706 
707 /*
708  * Loads a buffer from DRAM to DMEM.
709  *
710  * s: DRAM source
711  * d: DMEM destination
712  * c: number of bytes to copy (rounded down to 16 byte alignment)
713  */
714 #define aLoadBuffer(pkt, s, d, c) \
715 { \
716  Acmd *_a = (Acmd *)pkt; \
717  \
718  _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8) | \
719  _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(d, 0, 16); \
720  _a->words.w1 = (uintptr_t)(s); \
721 }
722 
723 /*
724  * Stores a buffer from DMEM to DRAM.
725  *
726  * s: DMEM source
727  * d: DRAM destination
728  * c: number of bytes to copy (rounded down to 16 byte alignment)
729  */
730 #define aSaveBuffer(pkt, s, d, c) \
731 { \
732  Acmd *_a = (Acmd *)pkt; \
733  \
734  _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8) | \
735  _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(s, 0, 16); \
736  _a->words.w1 = (uintptr_t)(d); \
737 }
738 
739 /*
740  * Duplicates 128 bytes of data a number of times.
741  *
742  * 128 bytes are read from source DMEM address s.
743  * Then c identical copies of these bytes are written to DMEM address d.
744  */
745 #define aDuplicate(pkt, s, d, c) \
746 { \
747  Acmd *_a = (Acmd *)pkt; \
748  \
749  _a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | \
750  _SHIFTL(c, 16, 8) | _SHIFTL(s, 0, 16)); \
751  _a->words.w1 = (_SHIFTL(d, 16, 16) | _SHIFTL(0x80, 0, 16)); \
752 }
753 
754 /*
755  * Copies memory in DMEM, second version.
756  *
757  * Copies t * c bytes from address i to address o.
758  *
759  * Note: count is first rounded up to the nearest multiple of 32 bytes,
760  * before the multiplication by t.
761  *
762  * Note: This acts as memcpy where 32 bytes are moved at a time, therefore
763  * if input and output overlap, output address should be less than input address.
764  *
765  * Not used in SM64.
766  */
767 #define aDMEMMove2(pkt, t, i, o, c) \
768 { \
769  Acmd *_a = (Acmd *)pkt; \
770  \
771  _a->words.w0 = _SHIFTL(A_DMEMMOVE2, 24, 8) | \
772  _SHIFTL(t, 16, 8) | _SHIFTL(i, 0, 16); \
773  _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \
774 }
775 
776 /*
777  * Fast resample.
778  *
779  * Before this command, call:
780  * aSetBuffer(cmd++, 0, in, out, count)
781  *
782  * This works like the other resample command but just takes the "nearest" sample,
783  * instead of a function of the four nearest samples.
784  *
785  * Initially the current position is calculated as (in << 16) + startFract.
786  * For every sample to create, the value is simply taken from the sample
787  * at address ((position >> 17) << 1). Then the current position is incremented
788  * by (pitch << 2).
789  *
790  * Note: count represents the number of output bytes to create, and is
791  * rounded up to the nearest multiple of 8 bytes.
792  */
793 #define aResampleZoh(pkt, pitch, startFract) \
794 { \
795  Acmd *_a = (Acmd *)pkt; \
796  \
797  _a->words.w0 = (_SHIFTL(A_RESAMPLE_ZOH, 24, 8) | \
798  _SHIFTL(pitch, 0, 16)); \
799  _a->words.w1 = _SHIFTL(startFract, 0, 16); \
800 }
801 
802 /*
803  * Fast downsampling by taking every other sample, discarding others.
804  *
805  * Note: nSamples refers to the number of output samples to create, and
806  * is first rounded up to the nearest multiple of 8.
807  */
808 #define aDownsampleHalf(pkt, nSamples, i, o) \
809 { \
810  Acmd *_a = (Acmd *)pkt; \
811  \
812  _a->words.w0 = (_SHIFTL(A_DOWNSAMPLE_HALF, 24, 8) | \
813  _SHIFTL(nSamples, 0, 16)); \
814  _a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \
815 }
816 
817 /*
818  * Mixes audio.
819  *
820  * Input and output addresses are taken from the i and o parameters.
821  * The volume with which the input is changed is taken from the g parameter.
822  * After the volume of the input samples have been changed, the result
823  * is added to the output.
824  *
825  * Note: count is first rounded down to the nearest multiple of 16 bytes
826  * and then rounded up to the nearest multiple of 32 bytes.
827  */
828 #define aMix(pkt, g, i, o, c) \
829 { \
830  Acmd *_a = (Acmd *)pkt; \
831  \
832  _a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | \
833  _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(g, 0, 16)); \
834  _a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \
835 }
836 
837 /*
838  * See aEnvMixer for more info.
839  */
840 #define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \
841 { \
842  Acmd *_a = (Acmd *)pkt; \
843  \
844  _a->words.w0 = (_SHIFTL(A_ENVSETUP1, 24, 8) | \
845  _SHIFTL(initialVolReverb, 16, 8) | \
846  _SHIFTL(rampReverb, 0, 16)); \
847  _a->words.w1 = _SHIFTL(rampLeft, 16, 16) | \
848  _SHIFTL(rampRight, 0, 16); \
849 }
850 
851 /*
852  * See aEnvMixer for more info.
853  */
854 #define aEnvSetup2(pkt, initialVolLeft, initialVolRight) \
855 { \
856  Acmd *_a = (Acmd *)pkt; \
857  \
858  _a->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8); \
859  _a->words.w1 = _SHIFTL(initialVolLeft, 16, 16) | \
860  _SHIFTL(initialVolRight, 0, 16); \
861 }
862 
863 /*
864  * Mixes an envelope with mono sound into 4 channels.
865  *
866  * To allow for many parameters, a sequence of aEnvSetup1, aEnvSetup2,
867  * aEnvMixer shall always be called.
868  *
869  * The function works in blocks of 8 samples.
870  * However, nSamples is rounded up to the nearest multiple of 16 samples.
871  *
872  * For each sample in a block:
873  * 1. sampleLeft = in * volLeft * (negLeft ? -1 : 1)
874  * 2. sampleRight = in * volRight * (negRight ? -1 : 1)
875  * 3. dryLeft += sampleLeft
876  * 4. dryRight += sampleRight
877  * 5. if swapReverb: swap sampleLeft and sampleRight
878  * 6. wetLeft += sampleLeft * volReverb
879  * 7. wetRight += sampleRight * volReverb
880  *
881  * After each block, all vol variables are added by their corresponding
882  * ramp value.
883  *
884  * Each volume variable is treated as a UQ0.16 number. Make sure
885  * the ramp additions don't overflow, or wrapping will occur.
886  * The initialVolReverb parameter is only 8 bits, but will be left
887  * shifted 8 bits by the rsp.
888  */
889 #define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, \
890  dryLeft, dryRight, wetLeft, wetRight) \
891 { \
892  Acmd *_a = (Acmd *)pkt; \
893  \
894  _a->words.w0 = (_SHIFTL(A_ENVMIXER, 24, 8) | \
895  _SHIFTL((inBuf) >> 4, 16, 8) | \
896  _SHIFTL(nSamples, 8, 8)) | \
897  _SHIFTL(swapReverb, 2, 1) | _SHIFTL(negLeft, 1, 1) |\
898  _SHIFTL(negRight, 0, 1); \
899  _a->words.w1 = _SHIFTL((dryLeft) >> 4, 24, 8) | \
900  _SHIFTL((dryRight) >> 4, 16, 8) | \
901  _SHIFTL((wetLeft) >> 4, 8, 8) | \
902  _SHIFTL((wetRight) >> 4, 0, 8); \
903 }
904 
905 /*
906  * Interleaves two mono channels into stereo.
907  *
908  * The count refers to the size of each input. Hence 2 * count bytes
909  * will be written out.
910  *
911  * A left sample will be placed before the right sample.
912  * All addresses (output, left, right) are DMEM addresses.
913  *
914  * Note: count will be rounded up to the nearest multiple of 8 bytes.
915  * The previous version of this function rounded up to the nearest
916  * multiple of 16 bytes.
917  */
918 /*
919 #define aInterleave(pkt, o, l, r, c) \
920 { \
921  Acmd *_a = (Acmd *)pkt; \
922  \
923  _a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8) | \
924  _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(o, 0, 16); \
925  _a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \
926 }
927 */
928 
929 /*
930  * Linear filter function.
931  *
932  * Calculates out[i] = sum all elements in the vector in[i..i-7] * filter[0..7],
933  * where "*" represents dot multiplication. The input/output contains s16
934  * samples and filter contains Q1.15 signed fixed point numbers.
935  * Every result sample is rounded and clamped.
936  *
937  * First initiate by calling with the flag f set to 2, countOrBuf contains
938  * the length in bytes that shall be processed in the next call. The addr
939  * parameter shall contain the DRAM address to the filter table (16 bytes).
940  * The count will be rounded up to the nearest multiple of 16 bytes.
941  *
942  * The aFilter function shall then be called in direct succession, with flag
943  * set to either 0 or 1. The countOrBuf parameter shall contain the DMEM
944  * address for the input/output. The addr parameter shall contain the DRAM
945  * address for the state, containing the last previous 8 input samples.
946  * The state is always written to upon exit, but is only read at entry if
947  * the flag is 0 (otherwise all-zero samples are used instead).
948  */
949 #define aFilter(pkt, f, countOrBuf, addr) \
950 { \
951  Acmd *_a = (Acmd *)pkt; \
952  \
953  _a->words.w0 = _SHIFTL(A_FILTER, 24, 8) | _SHIFTL((f), 16, 8) | \
954  _SHIFTL((countOrBuf), 0, 16); \
955  _a->words.w1 = (uintptr_t)(addr); \
956 }
957 
958 /*
959  * Modifies the volume of samples using a simple UQ4.4 gain multiplier.
960  *
961  * Performs the following:
962  *
963  * 1. Count c is rounded up to 32 byte alignment
964  * 2. g is a u8 that contains a UQ4.4 number
965  * 3. Modify each sample s, so that s = clamp_s16(s * g >> 4)
966  */
967 #define aHiLoGain(pkt, g, buflen, i) \
968 { \
969  Acmd *_a = (Acmd *)pkt; \
970  \
971  _a->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | \
972  _SHIFTL((g), 16, 8) | _SHIFTL((buflen), 0, 16); \
973  _a->words.w1 = _SHIFTL((i), 16, 16); \
974 }
975 
976 /*
977  * Performs the following:
978  *
979  * 1. Count c is rounded up to 64 byte alignment
980  * 2. f is added to i
981  * 3. i and o are from now treated as s16 pointers
982  * 4. 32 s16 samples are loaded from i to tbl
983  * 5. for (u32 idx = 0; idx * sizeof(s16) < c; idx++)
984  * o[idx] = clamp_s16((s32)o[idx] * (s32)tbl[idx % 32]);
985  */
986 #define aUnknown25(pkt, f, c, o, i) \
987 { \
988  Acmd *_a = (Acmd *)pkt; \
989  \
990  _a->words.w0 = (_SHIFTL(A_UNK_25, 24, 8) | \
991  _SHIFTL((f), 16, 8) | _SHIFTL((c), 0, 16)); \
992  _a->words.w1 = _SHIFTL((o), 16, 16) | _SHIFTL((i), 0, 16); \
993 }
994 
995 #endif
996 
997 #endif /* _LANGUAGE_C */
998 
999 #endif /* !_ABI_H_ */