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