RSP: Added some missing files
[mupen64plus-pandora.git] / source / mupen64plus-rsp-hle / src / ucode2.c
diff --git a/source/mupen64plus-rsp-hle/src/ucode2.c b/source/mupen64plus-rsp-hle/src/ucode2.c
new file mode 100755 (executable)
index 0000000..0299fb8
--- /dev/null
@@ -0,0 +1,882 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Mupen64plus-rsp-hle - ucode2.c                                        *
+ *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
+ *   Copyright (C) 2009 Richard Goedeken                                   *
+ *   Copyright (C) 2002 Hacktarux                                          *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "m64p_plugin.h"
+#include "m64p_types.h"
+#include "hle.h"
+#include "alist_internal.h"
+#include "alist.h"
+
+static void SPNOOP(uint32_t inst1, uint32_t inst2)
+{
+    DebugMessage(M64MSG_ERROR, "Unknown/Unimplemented Audio Command %i in ABI 2", (int)(inst1 >> 24));
+}
+
+
+static bool isMKABI = false;
+static bool isZeldaABI = false;
+
+void init_ucode2(void)
+{
+    isMKABI = isZeldaABI = false;
+}
+
+/* Loads an ADPCM table
+ * NOTE Works 100% Now 03-13-01
+ */
+static void LOADADPCM2(uint32_t inst1, uint32_t inst2)
+{
+    uint32_t v0 = (inst2 & 0xffffff);
+    uint32_t x;
+    /* Zelda2 Specific... */
+    uint16_t *table = (uint16_t *)(rsp.RDRAM + v0);
+
+    for (x = 0; x < ((inst1 & 0xffff) >> 0x4); x++) {
+        adpcmtable[(0x0 + (x << 3))^S] = table[0];
+        adpcmtable[(0x1 + (x << 3))^S] = table[1];
+
+        adpcmtable[(0x2 + (x << 3))^S] = table[2];
+        adpcmtable[(0x3 + (x << 3))^S] = table[3];
+
+        adpcmtable[(0x4 + (x << 3))^S] = table[4];
+        adpcmtable[(0x5 + (x << 3))^S] = table[5];
+
+        adpcmtable[(0x6 + (x << 3))^S] = table[6];
+        adpcmtable[(0x7 + (x << 3))^S] = table[7];
+        table += 8;
+    }
+}
+
+static void SETLOOP2(uint32_t inst1, uint32_t inst2)
+{
+    loopval = inst2 & 0xffffff; /* No segment? */
+}
+
+static void SETBUFF2(uint32_t inst1, uint32_t inst2)
+{
+    AudioInBuffer   = (uint16_t)(inst1);            /* 0x00 */
+    AudioOutBuffer  = (uint16_t)((inst2 >> 0x10)); /* 0x02 */
+    AudioCount      = (uint16_t)(inst2);            /* 0x04 */
+}
+
+/* NOTE Verified to be 100% Accurate... */
+static void ADPCM2(uint32_t inst1, uint32_t inst2)
+{
+    unsigned char Flags = (uint8_t)(inst1 >> 16) & 0xff;
+    unsigned int Address = (inst2 & 0xffffff);
+    unsigned short inPtr = 0;
+    short *out = (short *)(BufferSpace + AudioOutBuffer);
+    short count = (short)AudioCount;
+    unsigned char icode;
+    unsigned char code;
+    int vscale;
+    unsigned short index;
+    unsigned short j;
+    int a[8];
+    short *book1, *book2;
+
+    uint8_t srange;
+    uint8_t mask1;
+    uint8_t mask2;
+    uint8_t shifter;
+
+    int l1;
+    int l2;
+    int inp1[8];
+    int inp2[8];
+
+    memset(out, 0, 32);
+
+    /* Tricky lil Zelda MM and ABI2!!! hahaha I know your secrets! :DDD */
+    if (Flags & 0x4) {
+        srange = 0xE;
+        mask1 = 0xC0;
+        mask2 = 0x30;
+        shifter = 10;
+    } else {
+        srange = 0xC;
+        mask1 = 0xf0;
+        mask2 = 0x0f;
+        shifter = 12;
+    }
+
+    if (!(Flags & 0x1)) {
+        if (Flags & 0x2)
+            memcpy(out, &rsp.RDRAM[loopval], 32);
+        else
+            memcpy(out, &rsp.RDRAM[Address], 32);
+    }
+
+    l1 = out[14 ^ S];
+    l2 = out[15 ^ S];
+    out += 16;
+    while (count > 0) {
+        code = BufferSpace[(AudioInBuffer + inPtr)^S8];
+        index = code & 0xf;
+        index <<= 4;
+        book1 = (short *)&adpcmtable[index];
+        book2 = book1 + 8;
+        code >>= 4;
+        vscale = (0x8000 >> ((srange - code) - 1));
+
+        inPtr++;
+        j = 0;
+
+        while (j < 8) {
+            icode = BufferSpace[(AudioInBuffer + inPtr)^S8];
+            inPtr++;
+
+            /* this will in effect be signed */
+            inp1[j] = (int16_t)((icode & mask1) << 8);
+            if (code < srange)
+                inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16);
+            j++;
+
+            inp1[j] = (int16_t)((icode & mask2) << shifter);
+            if (code < srange)
+                inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16);
+            j++;
+
+            if (Flags & 4) {
+                /* this will in effect be signed */
+                inp1[j] = (int16_t)((icode & 0xC) << 12);
+                if (code < 0xE)
+                    inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16);
+                j++;
+
+                inp1[j] = (int16_t)((icode & 0x3) << 14);
+                if (code < 0xE)
+                    inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16);
+                j++;
+            }
+        }
+
+
+
+        j = 0;
+        while (j < 8) {
+            icode = BufferSpace[(AudioInBuffer + inPtr)^S8];
+            inPtr++;
+
+            inp2[j] = (int16_t)((icode & mask1) << 8);
+            if (code < srange)
+                inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16);
+            j++;
+
+            inp2[j] = (int16_t)((icode & mask2) << shifter);
+            if (code < srange)
+                inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16);
+            j++;
+
+            if (Flags & 4) {
+                inp2[j] = (int16_t)((icode & 0xC) << 12);
+                if (code < 0xE)
+                    inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16);
+                j++;
+
+                inp2[j] = (int16_t)((icode & 0x3) << 14);
+                if (code < 0xE)
+                    inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16);
+                j++;
+            }
+        }
+
+        a[0] = (int)book1[0] * (int)l1;
+        a[0] += (int)book2[0] * (int)l2;
+        a[0] += (int)inp1[0] * (int)2048;
+
+        a[1] = (int)book1[1] * (int)l1;
+        a[1] += (int)book2[1] * (int)l2;
+        a[1] += (int)book2[0] * inp1[0];
+        a[1] += (int)inp1[1] * (int)2048;
+
+        a[2] = (int)book1[2] * (int)l1;
+        a[2] += (int)book2[2] * (int)l2;
+        a[2] += (int)book2[1] * inp1[0];
+        a[2] += (int)book2[0] * inp1[1];
+        a[2] += (int)inp1[2] * (int)2048;
+
+        a[3] = (int)book1[3] * (int)l1;
+        a[3] += (int)book2[3] * (int)l2;
+        a[3] += (int)book2[2] * inp1[0];
+        a[3] += (int)book2[1] * inp1[1];
+        a[3] += (int)book2[0] * inp1[2];
+        a[3] += (int)inp1[3] * (int)2048;
+
+        a[4] = (int)book1[4] * (int)l1;
+        a[4] += (int)book2[4] * (int)l2;
+        a[4] += (int)book2[3] * inp1[0];
+        a[4] += (int)book2[2] * inp1[1];
+        a[4] += (int)book2[1] * inp1[2];
+        a[4] += (int)book2[0] * inp1[3];
+        a[4] += (int)inp1[4] * (int)2048;
+
+        a[5] = (int)book1[5] * (int)l1;
+        a[5] += (int)book2[5] * (int)l2;
+        a[5] += (int)book2[4] * inp1[0];
+        a[5] += (int)book2[3] * inp1[1];
+        a[5] += (int)book2[2] * inp1[2];
+        a[5] += (int)book2[1] * inp1[3];
+        a[5] += (int)book2[0] * inp1[4];
+        a[5] += (int)inp1[5] * (int)2048;
+
+        a[6] = (int)book1[6] * (int)l1;
+        a[6] += (int)book2[6] * (int)l2;
+        a[6] += (int)book2[5] * inp1[0];
+        a[6] += (int)book2[4] * inp1[1];
+        a[6] += (int)book2[3] * inp1[2];
+        a[6] += (int)book2[2] * inp1[3];
+        a[6] += (int)book2[1] * inp1[4];
+        a[6] += (int)book2[0] * inp1[5];
+        a[6] += (int)inp1[6] * (int)2048;
+
+        a[7] = (int)book1[7] * (int)l1;
+        a[7] += (int)book2[7] * (int)l2;
+        a[7] += (int)book2[6] * inp1[0];
+        a[7] += (int)book2[5] * inp1[1];
+        a[7] += (int)book2[4] * inp1[2];
+        a[7] += (int)book2[3] * inp1[3];
+        a[7] += (int)book2[2] * inp1[4];
+        a[7] += (int)book2[1] * inp1[5];
+        a[7] += (int)book2[0] * inp1[6];
+        a[7] += (int)inp1[7] * (int)2048;
+
+        for (j = 0; j < 8; j++) {
+            a[j ^ S] >>= 11;
+            a[j ^ S] = clamp_s16(a[j ^ S]);
+            *(out++) = a[j ^ S];
+        }
+        l1 = a[6];
+        l2 = a[7];
+
+        a[0] = (int)book1[0] * (int)l1;
+        a[0] += (int)book2[0] * (int)l2;
+        a[0] += (int)inp2[0] * (int)2048;
+
+        a[1] = (int)book1[1] * (int)l1;
+        a[1] += (int)book2[1] * (int)l2;
+        a[1] += (int)book2[0] * inp2[0];
+        a[1] += (int)inp2[1] * (int)2048;
+
+        a[2] = (int)book1[2] * (int)l1;
+        a[2] += (int)book2[2] * (int)l2;
+        a[2] += (int)book2[1] * inp2[0];
+        a[2] += (int)book2[0] * inp2[1];
+        a[2] += (int)inp2[2] * (int)2048;
+
+        a[3] = (int)book1[3] * (int)l1;
+        a[3] += (int)book2[3] * (int)l2;
+        a[3] += (int)book2[2] * inp2[0];
+        a[3] += (int)book2[1] * inp2[1];
+        a[3] += (int)book2[0] * inp2[2];
+        a[3] += (int)inp2[3] * (int)2048;
+
+        a[4] = (int)book1[4] * (int)l1;
+        a[4] += (int)book2[4] * (int)l2;
+        a[4] += (int)book2[3] * inp2[0];
+        a[4] += (int)book2[2] * inp2[1];
+        a[4] += (int)book2[1] * inp2[2];
+        a[4] += (int)book2[0] * inp2[3];
+        a[4] += (int)inp2[4] * (int)2048;
+
+        a[5] = (int)book1[5] * (int)l1;
+        a[5] += (int)book2[5] * (int)l2;
+        a[5] += (int)book2[4] * inp2[0];
+        a[5] += (int)book2[3] * inp2[1];
+        a[5] += (int)book2[2] * inp2[2];
+        a[5] += (int)book2[1] * inp2[3];
+        a[5] += (int)book2[0] * inp2[4];
+        a[5] += (int)inp2[5] * (int)2048;
+
+        a[6] = (int)book1[6] * (int)l1;
+        a[6] += (int)book2[6] * (int)l2;
+        a[6] += (int)book2[5] * inp2[0];
+        a[6] += (int)book2[4] * inp2[1];
+        a[6] += (int)book2[3] * inp2[2];
+        a[6] += (int)book2[2] * inp2[3];
+        a[6] += (int)book2[1] * inp2[4];
+        a[6] += (int)book2[0] * inp2[5];
+        a[6] += (int)inp2[6] * (int)2048;
+
+        a[7] = (int)book1[7] * (int)l1;
+        a[7] += (int)book2[7] * (int)l2;
+        a[7] += (int)book2[6] * inp2[0];
+        a[7] += (int)book2[5] * inp2[1];
+        a[7] += (int)book2[4] * inp2[2];
+        a[7] += (int)book2[3] * inp2[3];
+        a[7] += (int)book2[2] * inp2[4];
+        a[7] += (int)book2[1] * inp2[5];
+        a[7] += (int)book2[0] * inp2[6];
+        a[7] += (int)inp2[7] * (int)2048;
+
+        for (j = 0; j < 8; j++) {
+            a[j ^ S] >>= 11;
+            a[j ^ S] = clamp_s16(a[j ^ S]);
+            *(out++) = a[j ^ S];
+        }
+        l1 = a[6];
+        l2 = a[7];
+
+        count -= 32;
+    }
+    out -= 16;
+    memcpy(&rsp.RDRAM[Address], out, 32);
+}
+
+static void CLEARBUFF2(uint32_t inst1, uint32_t inst2)
+{
+    uint16_t addr = (uint16_t)(inst1 & 0xffff);
+    uint16_t count = (uint16_t)(inst2 & 0xffff);
+    if (count > 0)
+        memset(BufferSpace + addr, 0, count);
+}
+
+/* TODO Needs accuracy verification... */
+static void LOADBUFF2(uint32_t inst1, uint32_t inst2)
+{
+    uint32_t v0;
+    uint32_t cnt = (((inst1 >> 0xC) + 3) & 0xFFC);
+    v0 = (inst2 & 0xfffffc);
+    memcpy(BufferSpace + (inst1 & 0xfffc), rsp.RDRAM + v0, (cnt + 3) & 0xFFFC);
+}
+
+/* TODO Needs accuracy verification... */
+static void SAVEBUFF2(uint32_t inst1, uint32_t inst2)
+{
+    uint32_t v0;
+    uint32_t cnt = (((inst1 >> 0xC) + 3) & 0xFFC);
+    v0 = (inst2 & 0xfffffc);
+    memcpy(rsp.RDRAM + v0, BufferSpace + (inst1 & 0xfffc), (cnt + 3) & 0xFFFC);
+}
+
+/* TODO Needs accuracy verification... */
+static void MIXER2(uint32_t inst1, uint32_t inst2)
+{
+    uint16_t dmemin  = (uint16_t)(inst2 >> 0x10);
+    uint16_t dmemout = (uint16_t)(inst2 & 0xFFFF);
+    uint32_t count   = ((inst1 >> 12) & 0xFF0);
+    int32_t gain    = (int16_t)(inst1 & 0xFFFF);
+    int32_t temp;
+    unsigned int x;
+
+    for (x = 0; x < count; x += 2) {
+        /* TODO I think I can do this a lot easier */
+        temp = (*(int16_t *)(BufferSpace + dmemin + x) * gain) >> 15;
+        temp += *(int16_t *)(BufferSpace + dmemout + x);
+
+        temp = clamp_s16((int32_t)temp);
+
+        *(uint16_t *)(BufferSpace + dmemout + x) = (uint16_t)(temp & 0xFFFF);
+    }
+}
+
+
+static void RESAMPLE2(uint32_t inst1, uint32_t inst2)
+{
+    unsigned char Flags = (uint8_t)((inst1 >> 16) & 0xff);
+    unsigned int Pitch = ((inst1 & 0xffff)) << 1;
+    uint32_t addy = (inst2 & 0xffffff);
+    unsigned int Accum = 0;
+    unsigned int location;
+    int16_t *lut;
+    short *dst;
+    int16_t *src;
+    uint32_t srcPtr = (AudioInBuffer / 2);
+    uint32_t dstPtr = (AudioOutBuffer / 2);
+    int32_t temp;
+    int32_t accum;
+    int x, i;
+
+    dst = (short *)(BufferSpace);
+    src = (int16_t *)(BufferSpace);
+
+    if (addy > (1024 * 1024 * 8))
+        addy = (inst2 & 0xffffff);
+
+    srcPtr -= 4;
+
+    if ((Flags & 0x1) == 0) {
+        for (x = 0; x < 4; x++)
+            src[(srcPtr + x)^S] = ((uint16_t *)rsp.RDRAM)[((addy / 2) + x)^S];
+        Accum = *(uint16_t *)(rsp.RDRAM + addy + 10);
+    } else {
+        for (x = 0; x < 4; x++)
+            src[(srcPtr + x)^S] = 0;
+    }
+
+    for (i = 0; i < ((AudioCount + 0xf) & 0xFFF0) / 2; i++)    {
+        location = (((Accum * 0x40) >> 0x10) * 8);
+        lut = (int16_t *)(((uint8_t *)ResampleLUT) + location);
+
+        temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 0)^S)) * ((int32_t)((int16_t)lut[0])));
+        accum = (int32_t)(temp >> 15);
+
+        temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 1)^S)) * ((int32_t)((int16_t)lut[1])));
+        accum += (int32_t)(temp >> 15);
+
+        temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 2)^S)) * ((int32_t)((int16_t)lut[2])));
+        accum += (int32_t)(temp >> 15);
+
+        temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 3)^S)) * ((int32_t)((int16_t)lut[3])));
+        accum += (int32_t)(temp >> 15);
+
+        accum = clamp_s16(accum);
+
+        dst[dstPtr ^ S] = (int16_t)(accum);
+        dstPtr++;
+        Accum += Pitch;
+        srcPtr += (Accum >> 16);
+        Accum &= 0xffff;
+    }
+    for (x = 0; x < 4; x++)
+        ((uint16_t *)rsp.RDRAM)[((addy / 2) + x)^S] = src[(srcPtr + x)^S];
+    *(uint16_t *)(rsp.RDRAM + addy + 10) = (uint16_t)Accum;
+}
+
+/* TODO Needs accuracy verification... */
+static void DMEMMOVE2(uint32_t inst1, uint32_t inst2)
+{
+    uint32_t cnt;
+    uint32_t v0 = (inst1 & 0xFFFF);
+    uint32_t v1 = (inst2 >> 0x10);
+    uint32_t count = ((inst2 + 3) & 0xfffc);
+
+    if ((inst2 & 0xffff) == 0)
+        return;
+
+    for (cnt = 0; cnt < count; cnt++)
+        *(uint8_t *)(BufferSpace + ((cnt + v1)^S8)) = *(uint8_t *)(BufferSpace + ((cnt + v0)^S8));
+}
+
+static uint32_t t3, s5, s6;
+static uint16_t env[8];
+
+static void ENVSETUP1(uint32_t inst1, uint32_t inst2)
+{
+    uint32_t tmp;
+
+    t3 = inst1 & 0xFFFF;
+    tmp = (inst1 >> 0x8) & 0xFF00;
+    env[4] = (uint16_t)tmp;
+    tmp += t3;
+    env[5] = (uint16_t)tmp;
+    s5 = inst2 >> 0x10;
+    s6 = inst2 & 0xFFFF;
+}
+
+static void ENVSETUP2(uint32_t inst1, uint32_t inst2)
+{
+    uint32_t tmp;
+
+    tmp = (inst2 >> 0x10);
+    env[0] = (uint16_t)tmp;
+    tmp += s5;
+    env[1] = (uint16_t)tmp;
+    tmp = inst2 & 0xffff;
+    env[2] = (uint16_t)tmp;
+    tmp += s6;
+    env[3] = (uint16_t)tmp;
+}
+
+static void ENVMIXER2(uint32_t inst1, uint32_t inst2)
+{
+    int16_t *bufft6, *bufft7, *buffs0, *buffs1;
+    int16_t *buffs3;
+    int32_t count;
+    uint32_t adder;
+
+    int16_t vec9, vec10;
+
+    int16_t v2[8];
+
+    buffs3 = (int16_t *)(BufferSpace + ((inst1 >> 0x0c) & 0x0ff0));
+    bufft6 = (int16_t *)(BufferSpace + ((inst2 >> 0x14) & 0x0ff0));
+    bufft7 = (int16_t *)(BufferSpace + ((inst2 >> 0x0c) & 0x0ff0));
+    buffs0 = (int16_t *)(BufferSpace + ((inst2 >> 0x04) & 0x0ff0));
+    buffs1 = (int16_t *)(BufferSpace + ((inst2 << 0x04) & 0x0ff0));
+
+
+    v2[0] = 0 - (int16_t)((inst1 & 0x2) >> 1);
+    v2[1] = 0 - (int16_t)((inst1 & 0x1));
+    v2[2] = 0 - (int16_t)((inst1 & 0x8) >> 1);
+    v2[3] = 0 - (int16_t)((inst1 & 0x4) >> 1);
+
+    count = (inst1 >> 8) & 0xff;
+
+    if (!isMKABI) {
+        s5 *= 2;
+        s6 *= 2;
+        t3 *= 2;
+        adder = 0x10;
+    } else {
+        inst1 = 0;
+        adder = 0x8;
+        t3 = 0;
+    }
+
+
+    while (count > 0) {
+        int temp, x;
+        for (x = 0; x < 0x8; x++) {
+            vec9  = (int16_t)(((int32_t)buffs3[x ^ S] * (uint32_t)env[0]) >> 0x10) ^ v2[0];
+            vec10 = (int16_t)(((int32_t)buffs3[x ^ S] * (uint32_t)env[2]) >> 0x10) ^ v2[1];
+            temp = bufft6[x ^ S] + vec9;
+            temp = clamp_s16(temp);
+            bufft6[x ^ S] = temp;
+            temp = bufft7[x ^ S] + vec10;
+            temp = clamp_s16(temp);
+            bufft7[x ^ S] = temp;
+            vec9  = (int16_t)(((int32_t)vec9  * (uint32_t)env[4]) >> 0x10) ^ v2[2];
+            vec10 = (int16_t)(((int32_t)vec10 * (uint32_t)env[4]) >> 0x10) ^ v2[3];
+            if (inst1 & 0x10) {
+                temp = buffs0[x ^ S] + vec10;
+                temp = clamp_s16(temp);
+                buffs0[x ^ S] = temp;
+                temp = buffs1[x ^ S] + vec9;
+                temp = clamp_s16(temp);
+                buffs1[x ^ S] = temp;
+            } else {
+                temp = buffs0[x ^ S] + vec9;
+                temp = clamp_s16(temp);
+                buffs0[x ^ S] = temp;
+                temp = buffs1[x ^ S] + vec10;
+                temp = clamp_s16(temp);
+                buffs1[x ^ S] = temp;
+            }
+        }
+
+        if (!isMKABI)
+            for (x = 0x8; x < 0x10; x++) {
+                vec9  = (int16_t)(((int32_t)buffs3[x ^ S] * (uint32_t)env[1]) >> 0x10) ^ v2[0];
+                vec10 = (int16_t)(((int32_t)buffs3[x ^ S] * (uint32_t)env[3]) >> 0x10) ^ v2[1];
+                temp = bufft6[x ^ S] + vec9;
+                temp = clamp_s16(temp);
+                bufft6[x ^ S] = temp;
+                temp = bufft7[x ^ S] + vec10;
+                temp = clamp_s16(temp);
+                bufft7[x ^ S] = temp;
+                vec9  = (int16_t)(((int32_t)vec9  * (uint32_t)env[5]) >> 0x10) ^ v2[2];
+                vec10 = (int16_t)(((int32_t)vec10 * (uint32_t)env[5]) >> 0x10) ^ v2[3];
+                if (inst1 & 0x10) {
+                    temp = buffs0[x ^ S] + vec10;
+                    temp = clamp_s16(temp);
+                    buffs0[x ^ S] = temp;
+                    temp = buffs1[x ^ S] + vec9;
+                    temp = clamp_s16(temp);
+                    buffs1[x ^ S] = temp;
+                } else {
+                    temp = buffs0[x ^ S] + vec9;
+                    temp = clamp_s16(temp);
+                    buffs0[x ^ S] = temp;
+                    temp = buffs1[x ^ S] + vec10;
+                    temp = clamp_s16(temp);
+                    buffs1[x ^ S] = temp;
+                }
+            }
+        bufft6 += adder;
+        bufft7 += adder;
+        buffs0 += adder;
+        buffs1 += adder;
+        buffs3 += adder;
+        count  -= adder;
+        env[0] += (uint16_t)s5;
+        env[1] += (uint16_t)s5;
+        env[2] += (uint16_t)s6;
+        env[3] += (uint16_t)s6;
+        env[4] += (uint16_t)t3;
+        env[5] += (uint16_t)t3;
+    }
+}
+
+static void DUPLICATE2(uint32_t inst1, uint32_t inst2)
+{
+    unsigned short Count = (inst1 >> 16) & 0xff;
+    unsigned short In  = inst1 & 0xffff;
+    unsigned short Out = (inst2 >> 16);
+
+    unsigned short buff[64];
+
+    memcpy(buff, BufferSpace + In, 128);
+
+    while (Count) {
+        memcpy(BufferSpace + Out, buff, 128);
+        Out += 128;
+        Count--;
+    }
+}
+
+static void INTERL2(uint32_t inst1, uint32_t inst2)
+{
+    short Count = inst1 & 0xffff;
+    unsigned short  Out   = inst2 & 0xffff;
+    unsigned short In     = (inst2 >> 16);
+
+    unsigned char *src, *dst;
+    src = (unsigned char *)(BufferSpace); /* [In]; */
+    dst = (unsigned char *)(BufferSpace); /* [Out]; */
+    while (Count) {
+        *(short *)(dst + (Out ^ S8)) = *(short *)(src + (In ^ S8));
+        Out += 2;
+        In  += 4;
+        Count--;
+    }
+}
+
+/* TODO Needs accuracy verification... */
+static void INTERLEAVE2(uint32_t inst1, uint32_t inst2)
+{
+    uint32_t inL, inR;
+    uint16_t *outbuff;
+    uint16_t *inSrcR;
+    uint16_t *inSrcL;
+    uint16_t Left, Right, Left2, Right2;
+    uint32_t count;
+    uint32_t x;
+
+    count   = ((inst1 >> 12) & 0xFF0);
+    if (count == 0) {
+        outbuff = (uint16_t *)(AudioOutBuffer + BufferSpace);
+        count = AudioCount;
+    } else
+        outbuff = (uint16_t *)((inst1 & 0xFFFF) + BufferSpace);
+
+    inR = inst2 & 0xFFFF;
+    inL = (inst2 >> 16) & 0xFFFF;
+
+    inSrcR = (uint16_t *)(BufferSpace + inR);
+    inSrcL = (uint16_t *)(BufferSpace + inL);
+
+    for (x = 0; x < (count / 4); x++) {
+        Left = *(inSrcL++);
+        Right = *(inSrcR++);
+        Left2 = *(inSrcL++);
+        Right2 = *(inSrcR++);
+
+#ifdef M64P_BIG_ENDIAN
+        *(outbuff++) = Right;
+        *(outbuff++) = Left;
+        *(outbuff++) = Right2;
+        *(outbuff++) = Left2;
+#else
+        *(outbuff++) = Right2;
+        *(outbuff++) = Left2;
+        *(outbuff++) = Right;
+        *(outbuff++) = Left;
+#endif
+    }
+}
+
+static void ADDMIXER(uint32_t inst1, uint32_t inst2)
+{
+    short Count   = (inst1 >> 12) & 0x00ff0;
+    uint16_t InBuffer  = (inst2 >> 16);
+    uint16_t OutBuffer = inst2 & 0xffff;
+    int cntr;
+
+    int16_t *inp, *outp;
+    int32_t temp;
+    inp  = (int16_t *)(BufferSpace + InBuffer);
+    outp = (int16_t *)(BufferSpace + OutBuffer);
+    for (cntr = 0; cntr < Count; cntr += 2) {
+        temp = *outp + *inp;
+        temp = clamp_s16(temp);
+        *(outp++) = temp;
+        inp++;
+    }
+}
+
+static void HILOGAIN(uint32_t inst1, uint32_t inst2)
+{
+    uint16_t cnt = inst1 & 0xffff;
+    uint16_t out = (inst2 >> 16) & 0xffff;
+    int16_t hi  = (int16_t)((inst1 >> 4) & 0xf000);
+    uint16_t lo  = (inst1 >> 20) & 0xf;
+    int16_t *src = (int16_t *)(BufferSpace + out);
+    int32_t tmp, val;
+
+    while (cnt) {
+        val = (int32_t) * src;
+        tmp = ((val * (int32_t)hi) >> 16) + (uint32_t)(val * lo);
+        tmp = clamp_s16(tmp);
+        *src = tmp;
+        src++;
+        cnt -= 2;
+    }
+}
+
+static void FILTER2(uint32_t inst1, uint32_t inst2)
+{
+    static int cnt = 0;
+    static int16_t *lutt6;
+    static int16_t *lutt5;
+    uint8_t *save = (rsp.RDRAM + (inst2 & 0xFFFFFF));
+    uint8_t t4 = (uint8_t)((inst1 >> 0x10) & 0xFF);
+    int x;
+    short *inp1, *inp2;
+    int32_t out1[8];
+    int16_t outbuff[0x3c0], *outp;
+    uint32_t inPtr;
+
+    if (t4 > 1) {
+        /* Then set the cnt variable */
+        cnt = (inst1 & 0xFFFF);
+        lutt6 = (int16_t *)save;
+        return;
+    }
+
+    if (t4 == 0)
+        lutt5 = (short *)(save + 0x10);
+
+    lutt5 = (short *)(save + 0x10);
+
+    for (x = 0; x < 8; x++) {
+        int32_t a;
+        a = (lutt5[x] + lutt6[x]) >> 1;
+        lutt5[x] = lutt6[x] = (short)a;
+    }
+    inPtr = (uint32_t)(inst1 & 0xffff);
+    inp1 = (short *)(save);
+    outp = outbuff;
+    inp2 = (short *)(BufferSpace + inPtr);
+    for (x = 0; x < cnt; x += 0x10) {
+        out1[1] =  inp1[0] * lutt6[6];
+        out1[1] += inp1[3] * lutt6[7];
+        out1[1] += inp1[2] * lutt6[4];
+        out1[1] += inp1[5] * lutt6[5];
+        out1[1] += inp1[4] * lutt6[2];
+        out1[1] += inp1[7] * lutt6[3];
+        out1[1] += inp1[6] * lutt6[0];
+        out1[1] += inp2[1] * lutt6[1]; /* 1 */
+
+        out1[0] =  inp1[3] * lutt6[6];
+        out1[0] += inp1[2] * lutt6[7];
+        out1[0] += inp1[5] * lutt6[4];
+        out1[0] += inp1[4] * lutt6[5];
+        out1[0] += inp1[7] * lutt6[2];
+        out1[0] += inp1[6] * lutt6[3];
+        out1[0] += inp2[1] * lutt6[0];
+        out1[0] += inp2[0] * lutt6[1];
+
+        out1[3] =  inp1[2] * lutt6[6];
+        out1[3] += inp1[5] * lutt6[7];
+        out1[3] += inp1[4] * lutt6[4];
+        out1[3] += inp1[7] * lutt6[5];
+        out1[3] += inp1[6] * lutt6[2];
+        out1[3] += inp2[1] * lutt6[3];
+        out1[3] += inp2[0] * lutt6[0];
+        out1[3] += inp2[3] * lutt6[1];
+
+        out1[2] =  inp1[5] * lutt6[6];
+        out1[2] += inp1[4] * lutt6[7];
+        out1[2] += inp1[7] * lutt6[4];
+        out1[2] += inp1[6] * lutt6[5];
+        out1[2] += inp2[1] * lutt6[2];
+        out1[2] += inp2[0] * lutt6[3];
+        out1[2] += inp2[3] * lutt6[0];
+        out1[2] += inp2[2] * lutt6[1];
+
+        out1[5] =  inp1[4] * lutt6[6];
+        out1[5] += inp1[7] * lutt6[7];
+        out1[5] += inp1[6] * lutt6[4];
+        out1[5] += inp2[1] * lutt6[5];
+        out1[5] += inp2[0] * lutt6[2];
+        out1[5] += inp2[3] * lutt6[3];
+        out1[5] += inp2[2] * lutt6[0];
+        out1[5] += inp2[5] * lutt6[1];
+
+        out1[4] =  inp1[7] * lutt6[6];
+        out1[4] += inp1[6] * lutt6[7];
+        out1[4] += inp2[1] * lutt6[4];
+        out1[4] += inp2[0] * lutt6[5];
+        out1[4] += inp2[3] * lutt6[2];
+        out1[4] += inp2[2] * lutt6[3];
+        out1[4] += inp2[5] * lutt6[0];
+        out1[4] += inp2[4] * lutt6[1];
+
+        out1[7] =  inp1[6] * lutt6[6];
+        out1[7] += inp2[1] * lutt6[7];
+        out1[7] += inp2[0] * lutt6[4];
+        out1[7] += inp2[3] * lutt6[5];
+        out1[7] += inp2[2] * lutt6[2];
+        out1[7] += inp2[5] * lutt6[3];
+        out1[7] += inp2[4] * lutt6[0];
+        out1[7] += inp2[7] * lutt6[1];
+
+        out1[6] =  inp2[1] * lutt6[6];
+        out1[6] += inp2[0] * lutt6[7];
+        out1[6] += inp2[3] * lutt6[4];
+        out1[6] += inp2[2] * lutt6[5];
+        out1[6] += inp2[5] * lutt6[2];
+        out1[6] += inp2[4] * lutt6[3];
+        out1[6] += inp2[7] * lutt6[0];
+        out1[6] += inp2[6] * lutt6[1];
+        outp[1] = /*CLAMP*/((out1[1] + 0x4000) >> 0xF);
+        outp[0] = /*CLAMP*/((out1[0] + 0x4000) >> 0xF);
+        outp[3] = /*CLAMP*/((out1[3] + 0x4000) >> 0xF);
+        outp[2] = /*CLAMP*/((out1[2] + 0x4000) >> 0xF);
+        outp[5] = /*CLAMP*/((out1[5] + 0x4000) >> 0xF);
+        outp[4] = /*CLAMP*/((out1[4] + 0x4000) >> 0xF);
+        outp[7] = /*CLAMP*/((out1[7] + 0x4000) >> 0xF);
+        outp[6] = /*CLAMP*/((out1[6] + 0x4000) >> 0xF);
+        inp1 = inp2;
+        inp2 += 8;
+        outp += 8;
+    }
+    memcpy(save, inp2 - 8, 0x10);
+    memcpy(BufferSpace + (inst1 & 0xffff), outbuff, cnt);
+}
+
+static void SEGMENT2(uint32_t inst1, uint32_t inst2)
+{
+    if (isZeldaABI) {
+        FILTER2(inst1, inst2);
+        return;
+    }
+    if ((inst1 & 0xffffff) == 0) {
+        isMKABI = true;
+    } else {
+        isMKABI = false;
+        isZeldaABI = true;
+        FILTER2(inst1, inst2);
+    }
+}
+
+static void UNKNOWN(uint32_t inst1, uint32_t inst2)
+{
+}
+
+const acmd_callback_t ABI2[0x20] = {
+    SPNOOP , ADPCM2, CLEARBUFF2, UNKNOWN, ADDMIXER, RESAMPLE2, UNKNOWN, SEGMENT2,
+    SETBUFF2 , DUPLICATE2, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, HILOGAIN, SETLOOP2,
+    SPNOOP, INTERL2 , ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP,
+    HILOGAIN , SPNOOP, DUPLICATE2 , UNKNOWN    , SPNOOP  , SPNOOP    , SPNOOP  , SPNOOP
+};
+/* NOTES:
+ *
+ * FILTER/SEGMENT - Still needs to be finished up... add FILTER?
+ * UNKNOWWN #27   - Is this worth doing?  Looks like a pain in the ass just for WaveRace64
+ */
+