abi.h (38437B)
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_CN) 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_CN) 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_ */