Mario Kart 64
Loading...
Searching...
No Matches
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
102typedef struct {
103 unsigned int cmd:8;
104 unsigned int flags:8;
105 unsigned int gain:16;
106 unsigned int addr;
107} Aadpcm;
108
109typedef struct {
110 unsigned int cmd:8;
111 unsigned int flags:8;
112 unsigned int gain:16;
113 unsigned int addr;
114} Apolef;
115
116typedef struct {
117 unsigned int cmd:8;
118 unsigned int flags:8;
119 unsigned int pad1:16;
120 unsigned int addr;
121} Aenvelope;
122
123typedef 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
131typedef 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
139typedef struct {
140 unsigned int cmd:8;
141 unsigned int pad1:24;
142 unsigned int addr;
143} Aloadbuff;
144
145typedef struct {
146 unsigned int cmd:8;
147 unsigned int flags:8;
148 unsigned int pad1:16;
149 unsigned int addr;
150} Aenvmixer;
151
152typedef 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
160typedef struct {
161 unsigned int cmd:8;
162 unsigned int flags:8;
163 unsigned int dmem2:16;
164 unsigned int addr;
165} Apan;
166
167typedef struct {
168 unsigned int cmd:8;
169 unsigned int flags:8;
170 unsigned int pitch:16;
171 unsigned int addr;
172} Aresample;
173
174typedef struct {
175 unsigned int cmd:8;
176 unsigned int flags:8;
177 unsigned int pad1:16;
178 unsigned int addr;
179} Areverb;
180
181typedef struct {
182 unsigned int cmd:8;
183 unsigned int pad1:24;
184 unsigned int addr;
185} Asavebuff;
186
187typedef 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
195typedef 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
203typedef 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
211typedef 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
219typedef struct {
220 unsigned int cmd:8;
221 unsigned int pad1:8;
222 unsigned int count:16;
223 unsigned int addr;
224} Aloadadpcm;
225
226typedef 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
237typedef struct {
238 uintptr_t w0;
239 uintptr_t w1;
240} Awords;
241
242typedef 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 */
269typedef short ADPCM_STATE[16];
270
271/*
272 * Pole filter state
273 */
274typedef short POLEF_STATE[4];
275
276/*
277 * Resampler state
278 */
279typedef 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 */
290typedef 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_ */