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) | _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) | _SHIFTL(g, 0, 16)); \
468 _a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \
469 }
470
471// Not present in the audio microcode.
472#define aPan(pkt, f, d, s) \
473 { \
474 Acmd* _a = (Acmd*) pkt; \
475 \
476 _a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | _SHIFTL(d, 0, 16)); \
477 _a->words.w1 = (uintptr_t) (s); \
478 }
479
480/*
481 * Resamples audio.
482 * Possible flags: A_INIT, A_OUT? (not used in SM64).
483 *
484 * First call:
485 * aSetBuffer(cmd++, 0, in, out, count)
486 *
487 * This command resamples the audio using the given frequency ratio (pitch)
488 * using a filter that uses a window of 4 source samples. This can be used
489 * either for just resampling audio to be able to be played back at a different
490 * sample rate, or to change the pitch if the result is played back at
491 * the same sample rate as the input.
492 *
493 * The frequency ratio is given in UQ1.15 fixed point format.
494 * For no change in frequency, use pitch 0x8000.
495 * For 1 octave up or downsampling to (roughly) half number of samples, use pitch 0xffff.
496 * For 1 octave down or upsampling to double as many samples, use pitch 0x4000.
497 *
498 * Note: count represents the number of output sample bytes and is rounded up to
499 * the nearest multiple of 16 bytes.
500 *
501 * The state consists of the four following source samples when the algorithm stopped as
502 * well as a fractional position, and is initialized to all zeros if A_INIT is given.
503 * Otherwise it is loaded from DRAM at address s.
504 *
505 * The algorithm starts by writing the four source samples from the state (or zero)
506 * to just before the input address given. It then creates one output sample by examining
507 * the four next source samples and then moving the source position zero or more
508 * samples forward. The first output sample (when A_INIT is given) is always 0.
509 *
510 * When "count" bytes have been written, the following four source samples
511 * are written to the state in DRAM as well as a fractional position.
512 */
513#define aResample(pkt, f, p, s) \
514 { \
515 Acmd* _a = (Acmd*) pkt; \
516 \
517 _a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | _SHIFTL(f, 16, 8) | _SHIFTL(p, 0, 16)); \
518 _a->words.w1 = (uintptr_t) (s); \
519 }
520
521/*
522 * Stores a buffer in DMEM to DRAM.
523 *
524 * First call:
525 * aSetBuffer(cmd++, 0, 0, out, count)
526 *
527 * The out parameter to aSetBuffer is the source in DMEM and the
528 * s parameter to this command is the destination in DRAM.
529 */
530#define aSaveBuffer(pkt, s) \
531 { \
532 Acmd* _a = (Acmd*) pkt; \
533 \
534 _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8); \
535 _a->words.w1 = (uintptr_t) (s); \
536 }
537
538/*
539 * Sets up an entry in the segment table.
540 *
541 * The s parameter is a segment index, 0 to 15.
542 * The b parameter is the base offset.
543 */
544#define aSegment(pkt, s, b) \
545 { \
546 Acmd* _a = (Acmd*) pkt; \
547 \
548 _a->words.w0 = _SHIFTL(A_SEGMENT, 24, 8); \
549 _a->words.w1 = _SHIFTL(s, 24, 8) | _SHIFTL(b, 0, 24); \
550 }
551
552/*
553 * Sets internal DMEM buffer addresses used for later commands.
554 * See each command for how to use aSetBuffer.
555 */
556#define aSetBuffer(pkt, f, i, o, c) \
557 { \
558 Acmd* _a = (Acmd*) pkt; \
559 \
560 _a->words.w0 = (_SHIFTL(A_SETBUFF, 24, 8) | _SHIFTL(f, 16, 8) | _SHIFTL(i, 0, 16)); \
561 _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \
562 }
563
564/*
565 * Sets internal volume parameters.
566 * See aEnvMixer for more info.
567 */
568#define aSetVolume(pkt, f, v, t, r) \
569 { \
570 Acmd* _a = (Acmd*) pkt; \
571 \
572 _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | _SHIFTL(v, 0, 16)); \
573 _a->words.w1 = _SHIFTL(t, 16, 16) | _SHIFTL(r, 0, 16); \
574 }
575
576/*
577 * Sets the address to ADPCM loop state.
578 *
579 * The a parameter is a DRAM address.
580 * See aADPCMdec for more info.
581 */
582#define aSetLoop(pkt, a) \
583 { \
584 Acmd* _a = (Acmd*) pkt; \
585 _a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \
586 _a->words.w1 = (uintptr_t) (a); \
587 }
588
589/*
590 * Copies memory in DMEM.
591 *
592 * Copies c bytes from address i to address o.
593 *
594 * Note: count is rounded up to the nearest multiple of 16 bytes.
595 *
596 * Note: This acts as memcpy where 16 bytes are moved at a time, therefore
597 * if input and output overlap, output address should be less than input address.
598 */
599#define aDMEMMove(pkt, i, o, c) \
600 { \
601 Acmd* _a = (Acmd*) pkt; \
602 \
603 _a->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(i, 0, 24); \
604 _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \
605 }
606
607/*
608 * Loads ADPCM book from DRAM into DMEM.
609 *
610 * This command loads ADPCM table entries from DRAM to DMEM.
611 *
612 * The count parameter c should be a multiple of 16 bytes.
613 * The d parameter is a DRAM address.
614 */
615#define aLoadADPCM(pkt, c, d) \
616 { \
617 Acmd* _a = (Acmd*) pkt; \
618 \
619 _a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \
620 _a->words.w1 = (uintptr_t) (d); \
621 }
622
623// This is a version of aSetVolume which takes a single 32-bit parameter
624// instead of two 16-bit ones. According to AziAudio, it is used to set
625// ramping values when neither bit 4 nor bit 8 is set in the flags parameter.
626// It does not appear in the official abi.h header.
627/*
628 * Sets internal volume parameters.
629 * See aEnvMixer for more info.
630 */
631#define aSetVolume32(pkt, f, v, tr) \
632 { \
633 Acmd* _a = (Acmd*) pkt; \
634 \
635 _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | _SHIFTL(v, 0, 16)); \
636 _a->words.w1 = (uintptr_t) (tr); \
637 }
638
639#if defined(VERSION_SH) || defined(VERSION_US) || defined(VERSION_EU)
640#undef aLoadBuffer
641#undef aSaveBuffer
642#undef aMix
643#undef aEnvMixer
644// #undef aInterleave
645
646// New or modified operations in the new audio microcode below
647
673#define aS8Dec(pkt, f, s) \
674 { \
675 Acmd* _a = (Acmd*) pkt; \
676 \
677 _a->words.w0 = _SHIFTL(A_S8DEC, 24, 8) | _SHIFTL(f, 16, 8); \
678 _a->words.w1 = (uintptr_t) (s); \
679 }
680
681/*
682 * Mix two tracks by simple clamped addition.
683 *
684 * s: DMEM source track 1
685 * d: DMEM source track 2 and destination
686 * c: number of bytes to write
687 *
688 * Note: count is first rounded down to the nearest multiple of 16 bytes
689 * and then rounded up to the nearest multiple of 64 bytes.
690 */
691#define aAddMixer(pkt, s, d, c) \
692 { \
693 Acmd* _a = (Acmd*) pkt; \
694 \
695 _a->words.w0 = (_SHIFTL(A_ADDMIXER, 24, 8) | _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(0x7fff, 0, 16)); \
696 _a->words.w1 = (_SHIFTL(s, 16, 16) | _SHIFTL(d, 0, 16)); \
697 }
698
699/*
700 * Loads a buffer from DRAM to DMEM.
701 *
702 * s: DRAM source
703 * d: DMEM destination
704 * c: number of bytes to copy (rounded down to 16 byte alignment)
705 */
706#define aLoadBuffer(pkt, s, d, c) \
707 { \
708 Acmd* _a = (Acmd*) pkt; \
709 \
710 _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8) | _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(d, 0, 16); \
711 _a->words.w1 = (uintptr_t) (s); \
712 }
713
714/*
715 * Stores a buffer from DMEM to DRAM.
716 *
717 * s: DMEM source
718 * d: DRAM destination
719 * c: number of bytes to copy (rounded down to 16 byte alignment)
720 */
721#define aSaveBuffer(pkt, s, d, c) \
722 { \
723 Acmd* _a = (Acmd*) pkt; \
724 \
725 _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8) | _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(s, 0, 16); \
726 _a->words.w1 = (uintptr_t) (d); \
727 }
728
729/*
730 * Duplicates 128 bytes of data a number of times.
731 *
732 * 128 bytes are read from source DMEM address s.
733 * Then c identical copies of these bytes are written to DMEM address d.
734 */
735#define aDuplicate(pkt, s, d, c) \
736 { \
737 Acmd* _a = (Acmd*) pkt; \
738 \
739 _a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | _SHIFTL(c, 16, 8) | _SHIFTL(s, 0, 16)); \
740 _a->words.w1 = (_SHIFTL(d, 16, 16) | _SHIFTL(0x80, 0, 16)); \
741 }
742
743/*
744 * Copies memory in DMEM, second version.
745 *
746 * Copies t * c bytes from address i to address o.
747 *
748 * Note: count is first rounded up to the nearest multiple of 32 bytes,
749 * before the multiplication by t.
750 *
751 * Note: This acts as memcpy where 32 bytes are moved at a time, therefore
752 * if input and output overlap, output address should be less than input address.
753 *
754 * Not used in SM64.
755 */
756#define aDMEMMove2(pkt, t, i, o, c) \
757 { \
758 Acmd* _a = (Acmd*) pkt; \
759 \
760 _a->words.w0 = _SHIFTL(A_DMEMMOVE2, 24, 8) | _SHIFTL(t, 16, 8) | _SHIFTL(i, 0, 16); \
761 _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \
762 }
763
764/*
765 * Fast resample.
766 *
767 * Before this command, call:
768 * aSetBuffer(cmd++, 0, in, out, count)
769 *
770 * This works like the other resample command but just takes the "nearest" sample,
771 * instead of a function of the four nearest samples.
772 *
773 * Initially the current position is calculated as (in << 16) + startFract.
774 * For every sample to create, the value is simply taken from the sample
775 * at address ((position >> 17) << 1). Then the current position is incremented
776 * by (pitch << 2).
777 *
778 * Note: count represents the number of output bytes to create, and is
779 * rounded up to the nearest multiple of 8 bytes.
780 */
781#define aResampleZoh(pkt, pitch, startFract) \
782 { \
783 Acmd* _a = (Acmd*) pkt; \
784 \
785 _a->words.w0 = (_SHIFTL(A_RESAMPLE_ZOH, 24, 8) | _SHIFTL(pitch, 0, 16)); \
786 _a->words.w1 = _SHIFTL(startFract, 0, 16); \
787 }
788
789/*
790 * Fast downsampling by taking every other sample, discarding others.
791 *
792 * Note: nSamples refers to the number of output samples to create, and
793 * is first rounded up to the nearest multiple of 8.
794 */
795#define aDownsampleHalf(pkt, nSamples, i, o) \
796 { \
797 Acmd* _a = (Acmd*) pkt; \
798 \
799 _a->words.w0 = (_SHIFTL(A_DOWNSAMPLE_HALF, 24, 8) | _SHIFTL(nSamples, 0, 16)); \
800 _a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \
801 }
802
803/*
804 * Mixes audio.
805 *
806 * Input and output addresses are taken from the i and o parameters.
807 * The volume with which the input is changed is taken from the g parameter.
808 * After the volume of the input samples have been changed, the result
809 * is added to the output.
810 *
811 * Note: count is first rounded down to the nearest multiple of 16 bytes
812 * and then rounded up to the nearest multiple of 32 bytes.
813 */
814#define aMix(pkt, g, i, o, c) \
815 { \
816 Acmd* _a = (Acmd*) pkt; \
817 \
818 _a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(g, 0, 16)); \
819 _a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \
820 }
821
822/*
823 * See aEnvMixer for more info.
824 */
825#define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \
826 { \
827 Acmd* _a = (Acmd*) pkt; \
828 \
829 _a->words.w0 = (_SHIFTL(A_ENVSETUP1, 24, 8) | _SHIFTL(initialVolReverb, 16, 8) | _SHIFTL(rampReverb, 0, 16)); \
830 _a->words.w1 = _SHIFTL(rampLeft, 16, 16) | _SHIFTL(rampRight, 0, 16); \
831 }
832
833/*
834 * See aEnvMixer for more info.
835 */
836#define aEnvSetup2(pkt, initialVolLeft, initialVolRight) \
837 { \
838 Acmd* _a = (Acmd*) pkt; \
839 \
840 _a->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8); \
841 _a->words.w1 = _SHIFTL(initialVolLeft, 16, 16) | _SHIFTL(initialVolRight, 0, 16); \
842 }
843
844/*
845 * Mixes an envelope with mono sound into 4 channels.
846 *
847 * To allow for many parameters, a sequence of aEnvSetup1, aEnvSetup2,
848 * aEnvMixer shall always be called.
849 *
850 * The function works in blocks of 8 samples.
851 * However, nSamples is rounded up to the nearest multiple of 16 samples.
852 *
853 * For each sample in a block:
854 * 1. sampleLeft = in * volLeft * (negLeft ? -1 : 1)
855 * 2. sampleRight = in * volRight * (negRight ? -1 : 1)
856 * 3. dryLeft += sampleLeft
857 * 4. dryRight += sampleRight
858 * 5. if swapReverb: swap sampleLeft and sampleRight
859 * 6. wetLeft += sampleLeft * volReverb
860 * 7. wetRight += sampleRight * volReverb
861 *
862 * After each block, all vol variables are added by their corresponding
863 * ramp value.
864 *
865 * Each volume variable is treated as a UQ0.16 number. Make sure
866 * the ramp additions don't overflow, or wrapping will occur.
867 * The initialVolReverb parameter is only 8 bits, but will be left
868 * shifted 8 bits by the rsp.
869 */
870#define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight) \
871 { \
872 Acmd* _a = (Acmd*) pkt; \
873 \
874 _a->words.w0 = (_SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL((inBuf) >> 4, 16, 8) | _SHIFTL(nSamples, 8, 8)) | \
875 _SHIFTL(swapReverb, 2, 1) | _SHIFTL(negLeft, 1, 1) | _SHIFTL(negRight, 0, 1); \
876 _a->words.w1 = _SHIFTL((dryLeft) >> 4, 24, 8) | _SHIFTL((dryRight) >> 4, 16, 8) | \
877 _SHIFTL((wetLeft) >> 4, 8, 8) | _SHIFTL((wetRight) >> 4, 0, 8); \
878 }
879
880/*
881 * Interleaves two mono channels into stereo.
882 *
883 * The count refers to the size of each input. Hence 2 * count bytes
884 * will be written out.
885 *
886 * A left sample will be placed before the right sample.
887 * All addresses (output, left, right) are DMEM addresses.
888 *
889 * Note: count will be rounded up to the nearest multiple of 8 bytes.
890 * The previous version of this function rounded up to the nearest
891 * multiple of 16 bytes.
892 */
893/*
894#define aInterleave(pkt, o, l, r, c) \
895{ \
896 Acmd *_a = (Acmd *)pkt; \
897 \
898 _a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8) | \
899 _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(o, 0, 16); \
900 _a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \
901}
902*/
903
904/*
905 * Linear filter function.
906 *
907 * Calculates out[i] = sum all elements in the vector in[i..i-7] * filter[0..7],
908 * where "*" represents dot multiplication. The input/output contains s16
909 * samples and filter contains Q1.15 signed fixed point numbers.
910 * Every result sample is rounded and clamped.
911 *
912 * First initiate by calling with the flag f set to 2, countOrBuf contains
913 * the length in bytes that shall be processed in the next call. The addr
914 * parameter shall contain the DRAM address to the filter table (16 bytes).
915 * The count will be rounded up to the nearest multiple of 16 bytes.
916 *
917 * The aFilter function shall then be called in direct succession, with flag
918 * set to either 0 or 1. The countOrBuf parameter shall contain the DMEM
919 * address for the input/output. The addr parameter shall contain the DRAM
920 * address for the state, containing the last previous 8 input samples.
921 * The state is always written to upon exit, but is only read at entry if
922 * the flag is 0 (otherwise all-zero samples are used instead).
923 */
924#define aFilter(pkt, f, countOrBuf, addr) \
925 { \
926 Acmd* _a = (Acmd*) pkt; \
927 \
928 _a->words.w0 = _SHIFTL(A_FILTER, 24, 8) | _SHIFTL((f), 16, 8) | _SHIFTL((countOrBuf), 0, 16); \
929 _a->words.w1 = (uintptr_t) (addr); \
930 }
931
932/*
933 * Modifies the volume of samples using a simple UQ4.4 gain multiplier.
934 *
935 * Performs the following:
936 *
937 * 1. Count c is rounded up to 32 byte alignment
938 * 2. g is a u8 that contains a UQ4.4 number
939 * 3. Modify each sample s, so that s = clamp_s16(s * g >> 4)
940 */
941#define aHiLoGain(pkt, g, buflen, i) \
942 { \
943 Acmd* _a = (Acmd*) pkt; \
944 \
945 _a->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL((g), 16, 8) | _SHIFTL((buflen), 0, 16); \
946 _a->words.w1 = _SHIFTL((i), 16, 16); \
947 }
948
949/*
950 * Performs the following:
951 *
952 * 1. Count c is rounded up to 64 byte alignment
953 * 2. f is added to i
954 * 3. i and o are from now treated as s16 pointers
955 * 4. 32 s16 samples are loaded from i to tbl
956 * 5. for (u32 idx = 0; idx * sizeof(s16) < c; idx++)
957 * o[idx] = clamp_s16((s32)o[idx] * (s32)tbl[idx % 32]);
958 */
959#define aUnknown25(pkt, f, c, o, i) \
960 { \
961 Acmd* _a = (Acmd*) pkt; \
962 \
963 _a->words.w0 = (_SHIFTL(A_UNK_25, 24, 8) | _SHIFTL((f), 16, 8) | _SHIFTL((c), 0, 16)); \
964 _a->words.w1 = _SHIFTL((o), 16, 16) | _SHIFTL((i), 0, 16); \
965 }
966
967#endif
968
969#endif /* _LANGUAGE_C */
970
971#endif /* !_ABI_H_ */