Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/include/PR/abi.h
7858 views
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
#ifndef VERSION_SH
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
#ifdef VERSION_SH
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
654
/**
655
* Decompresses S8 data.
656
* Possible flags: A_INIT and A_LOOP.
657
*
658
* First set up internal data in DMEM:
659
* aSetLoop(cmd++, physicalAddressOfLoopState) (if A_LOOP is set)
660
*
661
* Then before this command, call:
662
* aSetBuffer(cmd++, 0, in, out, count)
663
*
664
* Note: count will be rounded up to the nearest multiple of 32 bytes.
665
*
666
* S8 decompression works by expanding s8 bytes into s16 numbers,
667
* by performing a left shift of 8 steps.
668
*
669
* Before the algorithm starts, the previous 16 samples are loaded according to flag:
670
* A_INIT: all zeros
671
* A_LOOP: the address set by aSetLoop
672
* no flags: the DRAM address in the s parameter
673
* These 16 samples are immediately copied to the destination address.
674
*
675
* The result of "count" bytes will be written after these 16 initial samples.
676
* The last 16 samples written to the destination will also be written to
677
* the state address in DRAM.
678
*/
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_ */
997
998