sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

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_ */