1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus-rsp-hle - ucode1.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2009 Richard Goedeken *
5 * Copyright (C) 2002 Hacktarux *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
21 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
26 #include "m64p_plugin.h"
28 #include "alist_internal.h"
30 /******** DMEM Memory Map for ABI 1 ***************
31 Address/Range Description
32 ------------- -------------------------------
33 0x000..0x2BF UCodeData
34 0x000-0x00F Constants - 0000 0001 0002 FFFF 0020 0800 7FFF 4000
35 0x010-0x02F Function Jump Table (16 Functions * 2 bytes each = 32) 0x20
36 0x030-0x03F Constants - F000 0F00 00F0 000F 0001 0010 0100 1000
37 0x040-0x03F Used by the Envelope Mixer (But what for?)
38 0x070-0x07F Used by the Envelope Mixer (But what for?)
39 0x2C0..0x31F <Unknown>
41 0x360 Audio In Buffer (Location)
42 0x362 Audio Out Buffer (Location)
43 0x364 Audio Buffer Size (Location)
44 0x366 Initial Volume for Left Channel
45 0x368 Initial Volume for Right Channel
46 0x36A Auxillary Buffer #1 (Location)
47 0x36C Auxillary Buffer #2 (Location)
48 0x36E Auxillary Buffer #3 (Location)
49 0x370 Loop Value (shared location)
50 0x370 Target Volume (Left)
53 0x376 Target Volume (Right)
58 0x380..0x4BF Alist data
59 0x4C0..0x4FF ADPCM CodeBook
60 0x500..0x5BF <Unknown>
61 0x5C0..0xF7F Buffers...
62 0xF80..0xFFF <Unknown>
63 ***************************************************/
65 #define MEMMASK 0x7FFFFF
67 #define MEMMASK 0x3FFFFF
70 static void SPNOOP(uint32_t inst1, uint32_t inst2)
74 uint16_t AudioInBuffer; /* 0x0000(T8) */
75 uint16_t AudioOutBuffer; /* 0x0002(T8) */
76 uint16_t AudioCount; /* 0x0004(T8) */
77 int16_t Vol_Left; /* 0x0006(T8) */
78 int16_t Vol_Right; /* 0x0008(T8) */
79 static uint16_t AudioAuxA; /* 0x000A(T8) */
80 static uint16_t AudioAuxC; /* 0x000C(T8) */
81 static uint16_t AudioAuxE; /* 0x000E(T8) */
82 uint32_t loopval; /* 0x0010(T8) - Value set by A_SETLOOP : Possible conflict with SETVOLUME??? */
83 int16_t VolTrg_Left; /* 0x0010(T8) */
84 int32_t VolRamp_Left; /* m_LeftVolTarget */
85 int16_t VolTrg_Right; /* m_RightVol */
86 int32_t VolRamp_Right; /* m_RightVolTarget */
87 int16_t Env_Dry; /* 0x001C(T8) */
88 int16_t Env_Wet; /* 0x001E(T8) */
90 uint8_t BufferSpace[0x10000];
92 short hleMixerWorkArea[256];
93 uint16_t adpcmtable[0x88];
95 const uint16_t ResampleLUT [0x200] = {
96 0x0C39, 0x66AD, 0x0D46, 0xFFDF, 0x0B39, 0x6696, 0x0E5F, 0xFFD8,
97 0x0A44, 0x6669, 0x0F83, 0xFFD0, 0x095A, 0x6626, 0x10B4, 0xFFC8,
98 0x087D, 0x65CD, 0x11F0, 0xFFBF, 0x07AB, 0x655E, 0x1338, 0xFFB6,
99 0x06E4, 0x64D9, 0x148C, 0xFFAC, 0x0628, 0x643F, 0x15EB, 0xFFA1,
100 0x0577, 0x638F, 0x1756, 0xFF96, 0x04D1, 0x62CB, 0x18CB, 0xFF8A,
101 0x0435, 0x61F3, 0x1A4C, 0xFF7E, 0x03A4, 0x6106, 0x1BD7, 0xFF71,
102 0x031C, 0x6007, 0x1D6C, 0xFF64, 0x029F, 0x5EF5, 0x1F0B, 0xFF56,
103 0x022A, 0x5DD0, 0x20B3, 0xFF48, 0x01BE, 0x5C9A, 0x2264, 0xFF3A,
104 0x015B, 0x5B53, 0x241E, 0xFF2C, 0x0101, 0x59FC, 0x25E0, 0xFF1E,
105 0x00AE, 0x5896, 0x27A9, 0xFF10, 0x0063, 0x5720, 0x297A, 0xFF02,
106 0x001F, 0x559D, 0x2B50, 0xFEF4, 0xFFE2, 0x540D, 0x2D2C, 0xFEE8,
107 0xFFAC, 0x5270, 0x2F0D, 0xFEDB, 0xFF7C, 0x50C7, 0x30F3, 0xFED0,
108 0xFF53, 0x4F14, 0x32DC, 0xFEC6, 0xFF2E, 0x4D57, 0x34C8, 0xFEBD,
109 0xFF0F, 0x4B91, 0x36B6, 0xFEB6, 0xFEF5, 0x49C2, 0x38A5, 0xFEB0,
110 0xFEDF, 0x47ED, 0x3A95, 0xFEAC, 0xFECE, 0x4611, 0x3C85, 0xFEAB,
111 0xFEC0, 0x4430, 0x3E74, 0xFEAC, 0xFEB6, 0x424A, 0x4060, 0xFEAF,
112 0xFEAF, 0x4060, 0x424A, 0xFEB6, 0xFEAC, 0x3E74, 0x4430, 0xFEC0,
113 0xFEAB, 0x3C85, 0x4611, 0xFECE, 0xFEAC, 0x3A95, 0x47ED, 0xFEDF,
114 0xFEB0, 0x38A5, 0x49C2, 0xFEF5, 0xFEB6, 0x36B6, 0x4B91, 0xFF0F,
115 0xFEBD, 0x34C8, 0x4D57, 0xFF2E, 0xFEC6, 0x32DC, 0x4F14, 0xFF53,
116 0xFED0, 0x30F3, 0x50C7, 0xFF7C, 0xFEDB, 0x2F0D, 0x5270, 0xFFAC,
117 0xFEE8, 0x2D2C, 0x540D, 0xFFE2, 0xFEF4, 0x2B50, 0x559D, 0x001F,
118 0xFF02, 0x297A, 0x5720, 0x0063, 0xFF10, 0x27A9, 0x5896, 0x00AE,
119 0xFF1E, 0x25E0, 0x59FC, 0x0101, 0xFF2C, 0x241E, 0x5B53, 0x015B,
120 0xFF3A, 0x2264, 0x5C9A, 0x01BE, 0xFF48, 0x20B3, 0x5DD0, 0x022A,
121 0xFF56, 0x1F0B, 0x5EF5, 0x029F, 0xFF64, 0x1D6C, 0x6007, 0x031C,
122 0xFF71, 0x1BD7, 0x6106, 0x03A4, 0xFF7E, 0x1A4C, 0x61F3, 0x0435,
123 0xFF8A, 0x18CB, 0x62CB, 0x04D1, 0xFF96, 0x1756, 0x638F, 0x0577,
124 0xFFA1, 0x15EB, 0x643F, 0x0628, 0xFFAC, 0x148C, 0x64D9, 0x06E4,
125 0xFFB6, 0x1338, 0x655E, 0x07AB, 0xFFBF, 0x11F0, 0x65CD, 0x087D,
126 0xFFC8, 0x10B4, 0x6626, 0x095A, 0xFFD0, 0x0F83, 0x6669, 0x0A44,
127 0xFFD8, 0x0E5F, 0x6696, 0x0B39, 0xFFDF, 0x0D46, 0x66AD, 0x0C39
130 static void CLEARBUFF(uint32_t inst1, uint32_t inst2)
132 uint32_t addr = (uint32_t)(inst1 & 0xffff);
133 uint32_t count = (uint32_t)(inst2 & 0xffff);
135 memset(BufferSpace + addr, 0, (count + 3) & 0xFFFC);
138 static void ENVMIXER(uint32_t inst1, uint32_t inst2)
140 uint8_t flags = (uint8_t)((inst1 >> 16) & 0xff);
141 uint32_t addy = (inst2 & 0xFFFFFF);
142 short *inp = (short *)(BufferSpace + AudioInBuffer);
143 short *out = (short *)(BufferSpace + AudioOutBuffer);
144 short *aux1 = (short *)(BufferSpace + AudioAuxA);
145 short *aux2 = (short *)(BufferSpace + AudioAuxC);
146 short *aux3 = (short *)(BufferSpace + AudioAuxE);
151 int i1, o1, a1, a2 = 0, a3 = 0;
152 unsigned short AuxIncRate = 1;
159 int32_t RRamp, LRamp;
160 int32_t LAdderStart, RAdderStart, LAdderEnd, RAdderEnd;
161 int32_t oMainR, oMainL, oAuxR, oAuxL;
164 memset(zero, 0, sizeof(zero));
166 if (flags & A_INIT) {
167 LVol = ((Vol_Left * (int32_t)VolRamp_Left));
168 RVol = ((Vol_Right * (int32_t)VolRamp_Right));
169 Wet = (int16_t)Env_Wet;
170 /* Save Wet/Dry values */
171 Dry = (int16_t)Env_Dry;
172 /* Save Current Left/Right Targets */
173 LTrg = (VolTrg_Left << 16);
174 RTrg = (VolTrg_Right << 16);
175 LAdderStart = Vol_Left << 16;
176 RAdderStart = Vol_Right << 16;
179 RRamp = VolRamp_Right;
180 LRamp = VolRamp_Left;
182 /* Load LVol, RVol, LAcc, and RAcc (all 32bit)
183 * Load Wet, Dry, LTrg, RTrg
185 memcpy((uint8_t *)hleMixerWorkArea, (rsp.RDRAM + addy), 80);
186 Wet = *(int16_t *)(hleMixerWorkArea + 0); /* 0-1 */
187 Dry = *(int16_t *)(hleMixerWorkArea + 2); /* 2-3 */
188 LTrg = *(int32_t *)(hleMixerWorkArea + 4); /* 4-5 */
189 RTrg = *(int32_t *)(hleMixerWorkArea + 6); /* 6-7 */
190 LRamp = *(int32_t *)(hleMixerWorkArea + 8); /* 8-9 (hleMixerWorkArea is a 16bit pointer) */
191 RRamp = *(int32_t *)(hleMixerWorkArea + 10); /* 10-11 */
192 LAdderEnd = *(int32_t *)(hleMixerWorkArea + 12); /* 12-13 */
193 RAdderEnd = *(int32_t *)(hleMixerWorkArea + 14); /* 14-15 */
194 LAdderStart = *(int32_t *)(hleMixerWorkArea + 16); /* 12-13 */
195 RAdderStart = *(int32_t *)(hleMixerWorkArea + 18); /* 14-15 */
198 if (!(flags & A_AUX)) {
203 oMainL = (Dry * (LTrg >> 16) + 0x4000) >> 15;
204 oAuxL = (Wet * (LTrg >> 16) + 0x4000) >> 15;
205 oMainR = (Dry * (RTrg >> 16) + 0x4000) >> 15;
206 oAuxR = (Wet * (RTrg >> 16) + 0x4000) >> 15;
208 for (y = 0; y < AudioCount; y += 0x10) {
210 if (LAdderStart != LTrg) {
212 LVol = (LAdderEnd - LAdderStart) >> 3;
213 LAdderEnd = (int32_t)(((int64_t)LAdderEnd * (int64_t)LRamp) >> 16);
214 LAdderStart = (int32_t)(((int64_t)LAcc * (int64_t)LRamp) >> 16);
220 if (RAdderStart != RTrg) {
222 RVol = (RAdderEnd - RAdderStart) >> 3;
223 RAdderEnd = (int32_t)(((int64_t)RAdderEnd * (int64_t)RRamp) >> 16);
224 RAdderStart = (int32_t)(((int64_t)RAcc * (int64_t)RRamp) >> 16);
230 for (x = 0; x < 8; x++) {
231 i1 = (int)inp[ptr ^ S];
232 o1 = (int)out[ptr ^ S];
233 a1 = (int)aux1[ptr ^ S];
235 a2 = (int)aux2[ptr ^ S];
236 a3 = (int)aux3[ptr ^ S];
254 MainL = (Dry * ((int32_t)LAcc >> 16) + 0x4000) >> 15;
255 AuxL = (Wet * ((int32_t)LAcc >> 16) + 0x4000) >> 15;
264 MainL = (Dry * ((int32_t)LAcc >> 16) + 0x4000) >> 15;
265 AuxL = (Wet * ((int32_t)LAcc >> 16) + 0x4000) >> 15;
277 MainR = (Dry * ((int32_t)RAcc >> 16) + 0x4000) >> 15;
278 AuxR = (Wet * ((int32_t)RAcc >> 16) + 0x4000) >> 15;
287 MainR = (Dry * ((int32_t)RAcc >> 16) + 0x4000) >> 15;
288 AuxR = (Wet * ((int32_t)RAcc >> 16) + 0x4000) >> 15;
292 o1 += ((i1 * MainR) + 0x4000) >> 15;
293 a1 += ((i1 * MainL) + 0x4000) >> 15;
301 a2 += ((i1 * AuxR) + 0x4000) >> 15;
302 a3 += ((i1 * AuxL) + 0x4000) >> 15;
314 *(int16_t *)(hleMixerWorkArea + 0) = Wet; /* 0-1 */
315 *(int16_t *)(hleMixerWorkArea + 2) = Dry; /* 2-3 */
316 *(int32_t *)(hleMixerWorkArea + 4) = LTrg; /* 4-5 */
317 *(int32_t *)(hleMixerWorkArea + 6) = RTrg; /* 6-7 */
318 *(int32_t *)(hleMixerWorkArea + 8) = LRamp; /* 8-9 (hleMixerWorkArea is a 16bit pointer) */
319 *(int32_t *)(hleMixerWorkArea + 10) = RRamp; /* 10-11 */
320 *(int32_t *)(hleMixerWorkArea + 12) = LAdderEnd; /* 12-13 */
321 *(int32_t *)(hleMixerWorkArea + 14) = RAdderEnd; /* 14-15 */
322 *(int32_t *)(hleMixerWorkArea + 16) = LAdderStart; /* 12-13 */
323 *(int32_t *)(hleMixerWorkArea + 18) = RAdderStart; /* 14-15 */
324 memcpy(rsp.RDRAM + addy, (uint8_t *)hleMixerWorkArea, 80);
327 static void RESAMPLE(uint32_t inst1, uint32_t inst2)
329 unsigned char Flags = (uint8_t)((inst1 >> 16) & 0xff);
330 unsigned int Pitch = ((inst1 & 0xffff)) << 1;
331 uint32_t addy = (inst2 & 0xffffff);
332 unsigned int Accum = 0;
333 unsigned int location;
335 short *dst = (short *)(BufferSpace);
336 int16_t *src = (int16_t *)(BufferSpace);
337 uint32_t srcPtr = (AudioInBuffer / 2);
338 uint32_t dstPtr = (AudioOutBuffer / 2);
344 if ((Flags & 0x1) == 0) {
345 for (x = 0; x < 4; x++)
346 src[(srcPtr + x)^S] = ((uint16_t *)rsp.RDRAM)[((addy / 2) + x)^S];
347 Accum = *(uint16_t *)(rsp.RDRAM + addy + 10);
349 for (x = 0; x < 4; x++)
350 src[(srcPtr + x)^S] = 0;
353 for (i = 0; i < ((AudioCount + 0xf) & 0xFFF0) / 2; i++) {
354 /* location is the fractional position between two samples */
355 location = (Accum >> 0xa) * 4;
356 lut = (int16_t *)ResampleLUT + location;
359 temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 0)^S)) * ((int32_t)((int16_t)lut[0])));
360 accum = (int32_t)(temp >> 15);
362 temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 1)^S)) * ((int32_t)((int16_t)lut[1])));
363 accum += (int32_t)(temp >> 15);
365 temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 2)^S)) * ((int32_t)((int16_t)lut[2])));
366 accum += (int32_t)(temp >> 15);
368 temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 3)^S)) * ((int32_t)((int16_t)lut[3])));
369 accum += (int32_t)(temp >> 15);
371 accum = clamp_s16(accum);
373 dst[dstPtr ^ S] = (accum);
376 srcPtr += (Accum >> 16);
379 for (x = 0; x < 4; x++)
380 ((uint16_t *)rsp.RDRAM)[((addy / 2) + x)^S] = src[(srcPtr + x)^S];
381 *(uint16_t *)(rsp.RDRAM + addy + 10) = Accum;
384 static void SETVOL(uint32_t inst1, uint32_t inst2)
386 /* Might be better to unpack these depending on the flags... */
387 uint8_t flags = (uint8_t)((inst1 >> 16) & 0xff);
388 uint16_t vol = (int16_t)(inst1 & 0xffff);
389 uint16_t volrate = (uint16_t)((inst2 & 0xffff));
392 Env_Dry = (int16_t)vol; /* m_MainVol */
393 Env_Wet = (int16_t)volrate; /* m_AuxVol */
397 /* Set the Source(start) Volumes */
400 Vol_Left = (int16_t)vol;
403 Vol_Right = (int16_t)vol;
407 /* 0x370 Loop Value (shared location)
408 * 0x370 Target Volume (Left)
411 /* Set the Ramping values Target, Ramp */
412 if (flags & A_LEFT) {
413 VolTrg_Left = (int16_t)inst1;
414 VolRamp_Left = (int32_t)inst2;
415 } else { /* A_RIGHT */
416 VolTrg_Right = (int16_t)inst1;
417 VolRamp_Right = (int32_t)inst2;
421 static void UNKNOWN(uint32_t inst1, uint32_t inst2) {}
423 static void SETLOOP(uint32_t inst1, uint32_t inst2)
425 loopval = (inst2 & 0xffffff);
428 /* TODO Work in progress! :) */
429 static void ADPCM(uint32_t inst1, uint32_t inst2)
431 unsigned char Flags = (uint8_t)(inst1 >> 16) & 0xff;
432 unsigned int Address = (inst2 & 0xffffff);
433 unsigned short inPtr = 0;
434 short *out = (short *)(BufferSpace + AudioOutBuffer);
435 short count = (short)AudioCount;
439 unsigned short index;
442 short *book1, *book2;
450 if (!(Flags & 0x1)) {
452 memcpy(out, &rsp.RDRAM[loopval & MEMMASK], 32);
454 memcpy(out, &rsp.RDRAM[Address], 32);
461 /* the first interation through, these values are
462 * either 0 in the case of A_INIT, from a special
463 * area of memory in the case of A_LOOP or just
464 * the values we calculated the last time
467 code = BufferSpace[(AudioInBuffer + inPtr)^S8];
469 /* index into the adpcm code table */
471 book1 = (short *)&adpcmtable[index];
473 /* upper nibble is scale */
475 /* very strange. 0x8000 would be .5 in 16:16 format
476 * so this appears to be a fractional scale based
477 * on the 12 based inverse of the scale value. note
478 * that this could be negative, in which case we do
479 * not use the calculated vscale value... see the
480 * if(code>12) check below
482 vscale = (0x8000 >> ((12 - code) - 1));
484 /* coded adpcm data lies next */
487 /* loop of 8, for 8 coded nibbles from 4 bytes
488 * which yields 8 short pcm values
491 icode = BufferSpace[(AudioInBuffer + inPtr)^S8];
494 /* this will in effect be signed */
495 inp1[j] = (int16_t)((icode & 0xf0) << 8);
497 inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16);
500 inp1[j] = (int16_t)((icode & 0xf) << 12);
502 inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16);
507 icode = BufferSpace[(AudioInBuffer + inPtr)^S8];
510 /* this will in effect be signed */
511 inp2[j] = (short)((icode & 0xf0) << 8);
513 inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16);
516 inp2[j] = (short)((icode & 0xf) << 12);
518 inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16);
522 a[0] = (int)book1[0] * (int)l1;
523 a[0] += (int)book2[0] * (int)l2;
524 a[0] += (int)inp1[0] * (int)2048;
526 a[1] = (int)book1[1] * (int)l1;
527 a[1] += (int)book2[1] * (int)l2;
528 a[1] += (int)book2[0] * inp1[0];
529 a[1] += (int)inp1[1] * (int)2048;
531 a[2] = (int)book1[2] * (int)l1;
532 a[2] += (int)book2[2] * (int)l2;
533 a[2] += (int)book2[1] * inp1[0];
534 a[2] += (int)book2[0] * inp1[1];
535 a[2] += (int)inp1[2] * (int)2048;
537 a[3] = (int)book1[3] * (int)l1;
538 a[3] += (int)book2[3] * (int)l2;
539 a[3] += (int)book2[2] * inp1[0];
540 a[3] += (int)book2[1] * inp1[1];
541 a[3] += (int)book2[0] * inp1[2];
542 a[3] += (int)inp1[3] * (int)2048;
544 a[4] = (int)book1[4] * (int)l1;
545 a[4] += (int)book2[4] * (int)l2;
546 a[4] += (int)book2[3] * inp1[0];
547 a[4] += (int)book2[2] * inp1[1];
548 a[4] += (int)book2[1] * inp1[2];
549 a[4] += (int)book2[0] * inp1[3];
550 a[4] += (int)inp1[4] * (int)2048;
552 a[5] = (int)book1[5] * (int)l1;
553 a[5] += (int)book2[5] * (int)l2;
554 a[5] += (int)book2[4] * inp1[0];
555 a[5] += (int)book2[3] * inp1[1];
556 a[5] += (int)book2[2] * inp1[2];
557 a[5] += (int)book2[1] * inp1[3];
558 a[5] += (int)book2[0] * inp1[4];
559 a[5] += (int)inp1[5] * (int)2048;
561 a[6] = (int)book1[6] * (int)l1;
562 a[6] += (int)book2[6] * (int)l2;
563 a[6] += (int)book2[5] * inp1[0];
564 a[6] += (int)book2[4] * inp1[1];
565 a[6] += (int)book2[3] * inp1[2];
566 a[6] += (int)book2[2] * inp1[3];
567 a[6] += (int)book2[1] * inp1[4];
568 a[6] += (int)book2[0] * inp1[5];
569 a[6] += (int)inp1[6] * (int)2048;
571 a[7] = (int)book1[7] * (int)l1;
572 a[7] += (int)book2[7] * (int)l2;
573 a[7] += (int)book2[6] * inp1[0];
574 a[7] += (int)book2[5] * inp1[1];
575 a[7] += (int)book2[4] * inp1[2];
576 a[7] += (int)book2[3] * inp1[3];
577 a[7] += (int)book2[2] * inp1[4];
578 a[7] += (int)book2[1] * inp1[5];
579 a[7] += (int)book2[0] * inp1[6];
580 a[7] += (int)inp1[7] * (int)2048;
582 for (j = 0; j < 8; j++) {
584 a[j ^ S] = clamp_s16(a[j ^ S]);
590 a[0] = (int)book1[0] * (int)l1;
591 a[0] += (int)book2[0] * (int)l2;
592 a[0] += (int)inp2[0] * (int)2048;
594 a[1] = (int)book1[1] * (int)l1;
595 a[1] += (int)book2[1] * (int)l2;
596 a[1] += (int)book2[0] * inp2[0];
597 a[1] += (int)inp2[1] * (int)2048;
599 a[2] = (int)book1[2] * (int)l1;
600 a[2] += (int)book2[2] * (int)l2;
601 a[2] += (int)book2[1] * inp2[0];
602 a[2] += (int)book2[0] * inp2[1];
603 a[2] += (int)inp2[2] * (int)2048;
605 a[3] = (int)book1[3] * (int)l1;
606 a[3] += (int)book2[3] * (int)l2;
607 a[3] += (int)book2[2] * inp2[0];
608 a[3] += (int)book2[1] * inp2[1];
609 a[3] += (int)book2[0] * inp2[2];
610 a[3] += (int)inp2[3] * (int)2048;
612 a[4] = (int)book1[4] * (int)l1;
613 a[4] += (int)book2[4] * (int)l2;
614 a[4] += (int)book2[3] * inp2[0];
615 a[4] += (int)book2[2] * inp2[1];
616 a[4] += (int)book2[1] * inp2[2];
617 a[4] += (int)book2[0] * inp2[3];
618 a[4] += (int)inp2[4] * (int)2048;
620 a[5] = (int)book1[5] * (int)l1;
621 a[5] += (int)book2[5] * (int)l2;
622 a[5] += (int)book2[4] * inp2[0];
623 a[5] += (int)book2[3] * inp2[1];
624 a[5] += (int)book2[2] * inp2[2];
625 a[5] += (int)book2[1] * inp2[3];
626 a[5] += (int)book2[0] * inp2[4];
627 a[5] += (int)inp2[5] * (int)2048;
629 a[6] = (int)book1[6] * (int)l1;
630 a[6] += (int)book2[6] * (int)l2;
631 a[6] += (int)book2[5] * inp2[0];
632 a[6] += (int)book2[4] * inp2[1];
633 a[6] += (int)book2[3] * inp2[2];
634 a[6] += (int)book2[2] * inp2[3];
635 a[6] += (int)book2[1] * inp2[4];
636 a[6] += (int)book2[0] * inp2[5];
637 a[6] += (int)inp2[6] * (int)2048;
639 a[7] = (int)book1[7] * (int)l1;
640 a[7] += (int)book2[7] * (int)l2;
641 a[7] += (int)book2[6] * inp2[0];
642 a[7] += (int)book2[5] * inp2[1];
643 a[7] += (int)book2[4] * inp2[2];
644 a[7] += (int)book2[3] * inp2[3];
645 a[7] += (int)book2[2] * inp2[4];
646 a[7] += (int)book2[1] * inp2[5];
647 a[7] += (int)book2[0] * inp2[6];
648 a[7] += (int)inp2[7] * (int)2048;
650 for (j = 0; j < 8; j++) {
652 a[j ^ S] = clamp_s16(a[j ^ S]);
661 memcpy(&rsp.RDRAM[Address], out, 32);
664 /* TODO memcpy causes static... endianess issue :( */
665 static void LOADBUFF(uint32_t inst1, uint32_t inst2)
670 v0 = (inst2 & 0xfffffc);
671 memcpy(BufferSpace + (AudioInBuffer & 0xFFFC), rsp.RDRAM + v0, (AudioCount + 3) & 0xFFFC);
674 /* TODO memcpy causes static... endianess issue :( */
675 static void SAVEBUFF(uint32_t inst1, uint32_t inst2)
680 v0 = (inst2 & 0xfffffc);
681 memcpy(rsp.RDRAM + v0, BufferSpace + (AudioOutBuffer & 0xFFFC), (AudioCount + 3) & 0xFFFC);
684 /* NOTE Should work ;-) */
685 static void SETBUFF(uint32_t inst1, uint32_t inst2)
687 if ((inst1 >> 0x10) & 0x8) {
688 /* A_AUX - Auxillary Sound Buffer Settings */
689 AudioAuxA = (uint16_t)(inst1);
690 AudioAuxC = (uint16_t)((inst2 >> 0x10));
691 AudioAuxE = (uint16_t)(inst2);
693 /* A_MAIN - Main Sound Buffer Settings */
694 AudioInBuffer = (uint16_t)(inst1); /* 0x00 */
695 AudioOutBuffer = (uint16_t)((inst2 >> 0x10)); /* 0x02 */
696 AudioCount = (uint16_t)(inst2); /* 0x04 */
700 /* TODO Doesn't sound just right?... will fix when HLE is ready - 03-11-01 */
701 static void DMEMMOVE(uint32_t inst1, uint32_t inst2)
704 uint32_t v0 = (inst1 & 0xFFFF);
705 uint32_t v1 = (inst2 >> 0x10);
706 uint32_t count = ((inst2 + 3) & 0xfffc);
708 if ((inst2 & 0xffff) == 0)
711 for (cnt = 0; cnt < count; cnt++)
712 *(uint8_t *)(BufferSpace + ((cnt + v1)^S8)) = *(uint8_t *)(BufferSpace + ((cnt + v0)^S8));
715 /* NOTE Loads an ADPCM table - Works 100% Now 03-13-01 */
716 static void LOADADPCM(uint32_t inst1, uint32_t inst2)
718 uint32_t v0 = (inst2 & 0xffffff);
721 uint16_t *table = (uint16_t *)(rsp.RDRAM + v0);
722 for (x = 0; x < ((inst1 & 0xffff) >> 0x4); x++) {
723 adpcmtable[(0x0 + (x << 3))^S] = table[0];
724 adpcmtable[(0x1 + (x << 3))^S] = table[1];
726 adpcmtable[(0x2 + (x << 3))^S] = table[2];
727 adpcmtable[(0x3 + (x << 3))^S] = table[3];
729 adpcmtable[(0x4 + (x << 3))^S] = table[4];
730 adpcmtable[(0x5 + (x << 3))^S] = table[5];
732 adpcmtable[(0x6 + (x << 3))^S] = table[6];
733 adpcmtable[(0x7 + (x << 3))^S] = table[7];
739 /* NOTE Works... - 3-11-01 */
740 static void INTERLEAVE(uint32_t inst1, uint32_t inst2)
743 uint16_t *outbuff = (uint16_t *)(AudioOutBuffer + BufferSpace);
746 uint16_t Left, Right, Left2, Right2;
749 inL = inst2 & 0xFFFF;
750 inR = (inst2 >> 16) & 0xFFFF;
752 inSrcR = (uint16_t *)(BufferSpace + inR);
753 inSrcL = (uint16_t *)(BufferSpace + inL);
755 for (x = 0; x < (AudioCount / 4); x++) {
759 Right2 = *(inSrcR++);
761 #ifdef M64P_BIG_ENDIAN
762 *(outbuff++) = Right;
764 *(outbuff++) = Right2;
765 *(outbuff++) = Left2;
767 *(outbuff++) = Right2;
768 *(outbuff++) = Left2;
769 *(outbuff++) = Right;
775 /* NOTE Fixed a sign issue... 03-14-01 */
776 static void MIXER(uint32_t inst1, uint32_t inst2)
778 uint32_t dmemin = (uint16_t)(inst2 >> 0x10);
779 uint32_t dmemout = (uint16_t)(inst2 & 0xFFFF);
780 int32_t gain = (int16_t)(inst1 & 0xFFFF);
787 for (x = 0; x < AudioCount; x += 2) { /* I think I can do this a lot easier */
788 temp = (*(int16_t *)(BufferSpace + dmemin + x) * gain) >> 15;
789 temp += *(int16_t *)(BufferSpace + dmemout + x);
791 temp = clamp_s16((int32_t)temp);
793 *(uint16_t *)(BufferSpace + dmemout + x) = (uint16_t)(temp & 0xFFFF);
797 /* TOP Performance Hogs:
798 * Command: ADPCM - Calls: 48 - Total Time: 331226 - Avg Time: 6900.54 - Percent: 31.53%
799 * Command: ENVMIXER - Calls: 48 - Total Time: 408563 - Avg Time: 8511.73 - Percent: 38.90%
800 * Command: LOADBUFF - Calls: 56 - Total Time: 21551 - Avg Time: 384.84 - Percent: 2.05%
801 * Command: RESAMPLE - Calls: 48 - Total Time: 225922 - Avg Time: 4706.71 - Percent: 21.51%
803 * Command: ADPCM - Calls: 48 - Total Time: 391600 - Avg Time: 8158.33 - Percent: 32.52%
804 * Command: ENVMIXER - Calls: 48 - Total Time: 444091 - Avg Time: 9251.90 - Percent: 36.88%
805 * Command: LOADBUFF - Calls: 58 - Total Time: 29945 - Avg Time: 516.29 - Percent: 2.49%
806 * Command: RESAMPLE - Calls: 48 - Total Time: 276354 - Avg Time: 5757.38 - Percent: 22.95%
809 /* NOTE TOP Performace Hogs: MIXER, RESAMPLE, ENVMIXER */
810 const acmd_callback_t ABI1[0x10] = {
811 SPNOOP , ADPCM , CLEARBUFF, ENVMIXER , LOADBUFF, RESAMPLE , SAVEBUFF, UNKNOWN,
812 SETBUFF, SETVOL, DMEMMOVE , LOADADPCM , MIXER , INTERLEAVE, UNKNOWN , SETLOOP