1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus-rsp-hle - ucode1.cpp *
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 #include "alist_internal.h"
34 # define wr8 (src , address);
35 # define rd8 (dest, address);
36 # define wr16 (src, address);
37 # define rd16 (dest, address);
38 # define wr32 (src, address);
39 # define rd32 (dest, address);
40 # define wr64 (src, address);
41 # define rd64 (dest, address);
42 # define dmamem (dest, src, size) memcpy (dest, src, size);
43 # define clrmem (dest, size) memset (dest, 0, size);
45 void wr8 (u8 src, void *address);
46 void rd8 (u8 dest, void *address);
47 void wr16 (u16 src, void *address);
48 void rd16 (u16 dest, void *address);
49 void wr32 (u16 src, void *address);
50 void rd32 (u16 dest, void *address);
51 void wr64 (u16 src, void *address);
52 void rd64 (u16 dest, void *address);
53 void dmamem (void *dest, void *src, int size);
54 void clrmem (void *dest, int size);
57 /******** DMEM Memory Map for ABI 1 ***************
58 Address/Range Description
59 ------------- -------------------------------
60 0x000..0x2BF UCodeData
61 0x000-0x00F Constants - 0000 0001 0002 FFFF 0020 0800 7FFF 4000
62 0x010-0x02F Function Jump Table (16 Functions * 2 bytes each = 32) 0x20
63 0x030-0x03F Constants - F000 0F00 00F0 000F 0001 0010 0100 1000
64 0x040-0x03F Used by the Envelope Mixer (But what for?)
65 0x070-0x07F Used by the Envelope Mixer (But what for?)
66 0x2C0..0x31F <Unknown>
68 0x360 Audio In Buffer (Location)
69 0x362 Audio Out Buffer (Location)
70 0x364 Audio Buffer Size (Location)
71 0x366 Initial Volume for Left Channel
72 0x368 Initial Volume for Right Channel
73 0x36A Auxillary Buffer #1 (Location)
74 0x36C Auxillary Buffer #2 (Location)
75 0x36E Auxillary Buffer #3 (Location)
76 0x370 Loop Value (shared location)
77 0x370 Target Volume (Left)
80 0x376 Target Volume (Right)
85 0x380..0x4BF Alist data
86 0x4C0..0x4FF ADPCM CodeBook
87 0x500..0x5BF <Unknown>
88 0x5C0..0xF7F Buffers...
89 0xF80..0xFFF <Unknown>
90 ***************************************************/
92 #define MEMMASK 0x7FFFFF
94 #define MEMMASK 0x3FFFFF
97 static void SPNOOP (u32 inst1, u32 inst2) {
98 //MessageBox (NULL, "Unknown Audio Command in ABI 1", "Audio HLE Error", MB_OK);
101 u32 SEGMENTS[0x10]; // 0x0320
103 u16 AudioInBuffer; // 0x0000(T8)
104 u16 AudioOutBuffer; // 0x0002(T8)
105 u16 AudioCount; // 0x0004(T8)
106 s16 Vol_Left; // 0x0006(T8)
107 s16 Vol_Right; // 0x0008(T8)
108 u16 AudioAuxA; // 0x000A(T8)
109 u16 AudioAuxC; // 0x000C(T8)
110 u16 AudioAuxE; // 0x000E(T8)
111 u32 loopval; // 0x0010(T8) // Value set by A_SETLOOP : Possible conflict with SETVOLUME???
112 s16 VolTrg_Left; // 0x0010(T8)
113 s32 VolRamp_Left; // m_LeftVolTarget
114 //u16 VolRate_Left; // m_LeftVolRate
115 s16 VolTrg_Right; // m_RightVol
116 s32 VolRamp_Right; // m_RightVolTarget
117 //u16 VolRate_Right; // m_RightVolRate
118 s16 Env_Dry; // 0x001C(T8)
119 s16 Env_Wet; // 0x001E(T8)
121 u8 BufferSpace[0x10000];
123 short hleMixerWorkArea[256];
124 u16 adpcmtable[0x88];
126 extern const u16 ResampleLUT [0x200] = {
127 0x0C39, 0x66AD, 0x0D46, 0xFFDF, 0x0B39, 0x6696, 0x0E5F, 0xFFD8,
128 0x0A44, 0x6669, 0x0F83, 0xFFD0, 0x095A, 0x6626, 0x10B4, 0xFFC8,
129 0x087D, 0x65CD, 0x11F0, 0xFFBF, 0x07AB, 0x655E, 0x1338, 0xFFB6,
130 0x06E4, 0x64D9, 0x148C, 0xFFAC, 0x0628, 0x643F, 0x15EB, 0xFFA1,
131 0x0577, 0x638F, 0x1756, 0xFF96, 0x04D1, 0x62CB, 0x18CB, 0xFF8A,
132 0x0435, 0x61F3, 0x1A4C, 0xFF7E, 0x03A4, 0x6106, 0x1BD7, 0xFF71,
133 0x031C, 0x6007, 0x1D6C, 0xFF64, 0x029F, 0x5EF5, 0x1F0B, 0xFF56,
134 0x022A, 0x5DD0, 0x20B3, 0xFF48, 0x01BE, 0x5C9A, 0x2264, 0xFF3A,
135 0x015B, 0x5B53, 0x241E, 0xFF2C, 0x0101, 0x59FC, 0x25E0, 0xFF1E,
136 0x00AE, 0x5896, 0x27A9, 0xFF10, 0x0063, 0x5720, 0x297A, 0xFF02,
137 0x001F, 0x559D, 0x2B50, 0xFEF4, 0xFFE2, 0x540D, 0x2D2C, 0xFEE8,
138 0xFFAC, 0x5270, 0x2F0D, 0xFEDB, 0xFF7C, 0x50C7, 0x30F3, 0xFED0,
139 0xFF53, 0x4F14, 0x32DC, 0xFEC6, 0xFF2E, 0x4D57, 0x34C8, 0xFEBD,
140 0xFF0F, 0x4B91, 0x36B6, 0xFEB6, 0xFEF5, 0x49C2, 0x38A5, 0xFEB0,
141 0xFEDF, 0x47ED, 0x3A95, 0xFEAC, 0xFECE, 0x4611, 0x3C85, 0xFEAB,
142 0xFEC0, 0x4430, 0x3E74, 0xFEAC, 0xFEB6, 0x424A, 0x4060, 0xFEAF,
143 0xFEAF, 0x4060, 0x424A, 0xFEB6, 0xFEAC, 0x3E74, 0x4430, 0xFEC0,
144 0xFEAB, 0x3C85, 0x4611, 0xFECE, 0xFEAC, 0x3A95, 0x47ED, 0xFEDF,
145 0xFEB0, 0x38A5, 0x49C2, 0xFEF5, 0xFEB6, 0x36B6, 0x4B91, 0xFF0F,
146 0xFEBD, 0x34C8, 0x4D57, 0xFF2E, 0xFEC6, 0x32DC, 0x4F14, 0xFF53,
147 0xFED0, 0x30F3, 0x50C7, 0xFF7C, 0xFEDB, 0x2F0D, 0x5270, 0xFFAC,
148 0xFEE8, 0x2D2C, 0x540D, 0xFFE2, 0xFEF4, 0x2B50, 0x559D, 0x001F,
149 0xFF02, 0x297A, 0x5720, 0x0063, 0xFF10, 0x27A9, 0x5896, 0x00AE,
150 0xFF1E, 0x25E0, 0x59FC, 0x0101, 0xFF2C, 0x241E, 0x5B53, 0x015B,
151 0xFF3A, 0x2264, 0x5C9A, 0x01BE, 0xFF48, 0x20B3, 0x5DD0, 0x022A,
152 0xFF56, 0x1F0B, 0x5EF5, 0x029F, 0xFF64, 0x1D6C, 0x6007, 0x031C,
153 0xFF71, 0x1BD7, 0x6106, 0x03A4, 0xFF7E, 0x1A4C, 0x61F3, 0x0435,
154 0xFF8A, 0x18CB, 0x62CB, 0x04D1, 0xFF96, 0x1756, 0x638F, 0x0577,
155 0xFFA1, 0x15EB, 0x643F, 0x0628, 0xFFAC, 0x148C, 0x64D9, 0x06E4,
156 0xFFB6, 0x1338, 0x655E, 0x07AB, 0xFFBF, 0x11F0, 0x65CD, 0x087D,
157 0xFFC8, 0x10B4, 0x6626, 0x095A, 0xFFD0, 0x0F83, 0x6669, 0x0A44,
158 0xFFD8, 0x0E5F, 0x6696, 0x0B39, 0xFFDF, 0x0D46, 0x66AD, 0x0C39
161 static void CLEARBUFF (u32 inst1, u32 inst2) {
162 u32 addr = (u32)(inst1 & 0xffff);
163 u32 count = (u32)(inst2 & 0xffff);
165 memset(BufferSpace+addr, 0, (count+3)&0xFFFC);
168 //FILE *dfile = fopen ("d:\\envmix.txt", "wt");
170 static void ENVMIXER (u32 inst1, u32 inst2) {
171 //static int envmixcnt = 0;
172 u8 flags = (u8)((inst1 >> 16) & 0xff);
173 u32 addy = (inst2 & 0xFFFFFF);// + SEGMENTS[(inst2>>24)&0xf];
175 // ********* Make sure these conditions are met... ***********
176 /*if ((AudioInBuffer | AudioOutBuffer | AudioAuxA | AudioAuxC | AudioAuxE | AudioCount) & 0x3) {
177 MessageBox (NULL, "Unaligned EnvMixer... please report this to Azimer with the following information: RomTitle, Place in the rom it occurred, and any save state just before the error", "AudioHLE Error", MB_OK);
179 // ------------------------------------------------------------
180 short *inp=(short *)(BufferSpace+AudioInBuffer);
181 short *out=(short *)(BufferSpace+AudioOutBuffer);
182 short *aux1=(short *)(BufferSpace+AudioAuxA);
183 short *aux2=(short *)(BufferSpace+AudioAuxC);
184 short *aux3=(short *)(BufferSpace+AudioAuxE);
189 int i1,o1,a1,a2=0,a3=0;
190 unsigned short AuxIncRate=1;
199 s32 LAdderStart, RAdderStart, LAdderEnd, RAdderEnd;
200 s32 oMainR, oMainL, oAuxR, oAuxL;
204 //fprintf (dfile, "\n----------------------------------------------------\n");
205 if (flags & A_INIT) {
206 LVol = ((Vol_Left * (s32)VolRamp_Left));
207 RVol = ((Vol_Right * (s32)VolRamp_Right));
208 Wet = (s16)Env_Wet; Dry = (s16)Env_Dry; // Save Wet/Dry values
209 LTrg = (VolTrg_Left << 16); RTrg = (VolTrg_Right << 16); // Save Current Left/Right Targets
210 LAdderStart = Vol_Left << 16;
211 RAdderStart = Vol_Right << 16;
214 RRamp = VolRamp_Right;
215 LRamp = VolRamp_Left;
217 // Load LVol, RVol, LAcc, and RAcc (all 32bit)
218 // Load Wet, Dry, LTrg, RTrg
219 memcpy((u8 *)hleMixerWorkArea, (rsp.RDRAM+addy), 80);
220 Wet = *(s16 *)(hleMixerWorkArea + 0); // 0-1
221 Dry = *(s16 *)(hleMixerWorkArea + 2); // 2-3
222 LTrg = *(s32 *)(hleMixerWorkArea + 4); // 4-5
223 RTrg = *(s32 *)(hleMixerWorkArea + 6); // 6-7
224 LRamp= *(s32 *)(hleMixerWorkArea + 8); // 8-9 (hleMixerWorkArea is a 16bit pointer)
225 RRamp= *(s32 *)(hleMixerWorkArea + 10); // 10-11
226 LAdderEnd = *(s32 *)(hleMixerWorkArea + 12); // 12-13
227 RAdderEnd = *(s32 *)(hleMixerWorkArea + 14); // 14-15
228 LAdderStart = *(s32 *)(hleMixerWorkArea + 16); // 12-13
229 RAdderStart = *(s32 *)(hleMixerWorkArea + 18); // 14-15
237 oMainL = (Dry * (LTrg>>16) + 0x4000) >> 15;
238 oAuxL = (Wet * (LTrg>>16) + 0x4000) >> 15;
239 oMainR = (Dry * (RTrg>>16) + 0x4000) >> 15;
240 oAuxR = (Wet * (RTrg>>16) + 0x4000) >> 15;
242 for (int y = 0; y < AudioCount; y += 0x10) {
244 if (LAdderStart != LTrg) {
246 LVol = (LAdderEnd - LAdderStart) >> 3;
247 LAdderEnd = (s32) (((s64)LAdderEnd * (s64)LRamp) >> 16);
248 LAdderStart = (s32) (((s64)LAcc * (s64)LRamp) >> 16);
254 if (RAdderStart != RTrg) {
256 RVol = (RAdderEnd - RAdderStart) >> 3;
257 RAdderEnd = (s32) (((s64)RAdderEnd * (s64)RRamp) >> 16);
258 RAdderStart = (s32) (((s64)RAcc * (s64)RRamp) >> 16);
264 for (int x = 0; x < 8; x++) {
279 if (LVol <= 0) { // Decrementing
286 MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
287 AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
296 MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
297 AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
301 if (RVol <= 0) { // Decrementing
308 MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
309 AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
318 MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
319 AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
323 //fprintf (dfile, "%04X ", (LAcc>>16));
325 /*MainL = (((s64)Dry*2 * (s64)(LAcc>>16)) + 0x8000) >> 16;
326 MainR = (((s64)Dry*2 * (s64)(RAcc>>16)) + 0x8000) >> 16;
327 AuxL = (((s64)Wet*2 * (s64)(LAcc>>16)) + 0x8000) >> 16;
328 AuxR = (((s64)Wet*2 * (s64)(RAcc>>16)) + 0x8000) >> 16;*/
330 if (MainL>32767) MainL = 32767;
331 else if (MainL<-32768) MainL = -32768;
332 if (MainR>32767) MainR = 32767;
333 else if (MainR<-32768) MainR = -32768;
334 if (AuxL>32767) AuxL = 32767;
335 else if (AuxL<-32768) AuxR = -32768;
336 if (AuxR>32767) AuxR = 32767;
337 else if (AuxR<-32768) AuxR = -32768;*/
339 MainR = (Dry * RTrg + 0x10000) >> 15;
340 MainL = (Dry * LTrg + 0x10000) >> 15;
341 AuxR = (Wet * RTrg + 0x8000) >> 16;
342 AuxL = (Wet * LTrg + 0x8000) >> 16;*/
344 o1+=(/*(o1*0x7fff)+*/(i1*MainR)+0x4000)>>15;
345 a1+=(/*(a1*0x7fff)+*/(i1*MainL)+0x4000)>>15;
347 /* o1=((s64)(((s64)o1*0xfffe)+((s64)i1*MainR*2)+0x8000)>>16);
349 a1=((s64)(((s64)a1*0xfffe)+((s64)i1*MainL*2)+0x8000)>>16);*/
351 if(o1>32767) o1=32767;
352 else if(o1<-32768) o1=-32768;
354 if(a1>32767) a1=32767;
355 else if(a1<-32768) a1=-32768;
360 //a2=((s64)(((s64)a2*0xfffe)+((s64)i1*AuxR*2)+0x8000)>>16);
362 //a3=((s64)(((s64)a3*0xfffe)+((s64)i1*AuxL*2)+0x8000)>>16);
363 a2+=(/*(a2*0x7fff)+*/(i1*AuxR)+0x4000)>>15;
364 a3+=(/*(a3*0x7fff)+*/(i1*AuxL)+0x4000)>>15;
366 if(a2>32767) a2=32767;
367 else if(a2<-32768) a2=-32768;
369 if(a3>32767) a3=32767;
370 else if(a3<-32768) a3=-32768;
382 *(s16 *)(hleMixerWorkArea + 0) = Wet; // 0-1
383 *(s16 *)(hleMixerWorkArea + 2) = Dry; // 2-3
384 *(s32 *)(hleMixerWorkArea + 4) = LTrg; // 4-5
385 *(s32 *)(hleMixerWorkArea + 6) = RTrg; // 6-7
386 *(s32 *)(hleMixerWorkArea + 8) = LRamp; // 8-9 (hleMixerWorkArea is a 16bit pointer)
387 *(s32 *)(hleMixerWorkArea + 10) = RRamp; // 10-11
388 *(s32 *)(hleMixerWorkArea + 12) = LAdderEnd; // 12-13
389 *(s32 *)(hleMixerWorkArea + 14) = RAdderEnd; // 14-15
390 *(s32 *)(hleMixerWorkArea + 16) = LAdderStart; // 12-13
391 *(s32 *)(hleMixerWorkArea + 18) = RAdderStart; // 14-15
392 memcpy(rsp.RDRAM+addy, (u8 *)hleMixerWorkArea,80);
395 static void RESAMPLE (u32 inst1, u32 inst2) {
396 unsigned char Flags=(u8)((inst1>>16)&0xff);
397 unsigned int Pitch=((inst1&0xffff))<<1;
398 u32 addy = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
399 unsigned int Accum=0;
400 unsigned int location;
404 dst=(short *)(BufferSpace);
405 src=(s16 *)(BufferSpace);
406 u32 srcPtr=(AudioInBuffer/2);
407 u32 dstPtr=(AudioOutBuffer/2);
411 if (addy > (1024*1024*8))
412 addy = (inst2 & 0xffffff);
416 if ((Flags & 0x1) == 0) {
417 //memcpy (src+srcPtr, rsp.RDRAM+addy, 0x8);
418 for (int x=0; x < 4; x++)
419 src[(srcPtr+x)^S] = ((u16 *)rsp.RDRAM)[((addy/2)+x)^S];
420 Accum = *(u16 *)(rsp.RDRAM+addy+10);
422 for (int x=0; x < 4; x++)
423 src[(srcPtr+x)^S] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2));
426 for(int i=0;i < ((AudioCount+0xf)&0xFFF0)/2;i++) {
427 //location = (((Accum * 0x40) >> 0x10) * 8);
428 // location is the fractional position between two samples
429 location = (Accum >> 0xa) * 4;
430 lut = (s16*)ResampleLUT + location;
432 // mov eax, dword ptr [src+srcPtr];
433 // movsx edx, word ptr [lut];
444 temp = ((s32)*(s16*)(src+((srcPtr+0)^S))*((s32)((s16)lut[0])));
445 accum = (s32)(temp >> 15);
447 temp = ((s32)*(s16*)(src+((srcPtr+1)^S))*((s32)((s16)lut[1])));
448 accum += (s32)(temp >> 15);
450 temp = ((s32)*(s16*)(src+((srcPtr+2)^S))*((s32)((s16)lut[2])));
451 accum += (s32)(temp >> 15);
453 temp = ((s32)*(s16*)(src+((srcPtr+3)^S))*((s32)((s16)lut[3])));
454 accum += (s32)(temp >> 15);
456 if (accum > 32767) accum = 32767;
457 if (accum < -32768) accum = -32768;
459 dst[dstPtr^S] = (accum);
462 srcPtr += (Accum>>16);
465 for (int x=0; x < 4; x++)
466 ((u16 *)rsp.RDRAM)[((addy/2)+x)^S] = src[(srcPtr+x)^S];
467 //memcpy (RSWORK, src+srcPtr, 0x8);
468 *(u16 *)(rsp.RDRAM+addy+10) = Accum;
471 static void SETVOL (u32 inst1, u32 inst2) {
472 // Might be better to unpack these depending on the flags...
473 u8 flags = (u8)((inst1 >> 16) & 0xff);
474 u16 vol = (s16)(inst1 & 0xffff);
475 //u16 voltarg =(u16)((inst2 >> 16)&0xffff);
476 u16 volrate = (u16)((inst2 & 0xffff));
479 Env_Dry = (s16)vol; // m_MainVol
480 Env_Wet = (s16)volrate; // m_AuxVol
484 if(flags & A_VOL) { // Set the Source(start) Volumes
486 Vol_Left = (s16)vol; // m_LeftVolume
488 Vol_Right = (s16)vol; // m_RightVolume
493 //0x370 Loop Value (shared location)
494 //0x370 Target Volume (Left)
495 //u16 VolRamp_Left; // 0x0012(T8)
496 if(flags & A_LEFT) { // Set the Ramping values Target, Ramp
497 //loopval = (((u32)vol << 0x10) | (u32)voltarg);
498 VolTrg_Left = (s16)inst1; // m_LeftVol
499 //VolRamp_Left = (s32)inst2;
500 VolRamp_Left = (s32)inst2;//(u16)(inst2) | (s32)(s16)(inst2 << 0x10);
501 //fprintf (dfile, "Ramp Left: %f\n", (float)VolRamp_Left/65536.0);
502 //fprintf (dfile, "Ramp Left: %08X\n", inst2);
503 //VolRamp_Left = (s16)voltarg; // m_LeftVolTarget
504 //VolRate_Left = (s16)volrate; // m_LeftVolRate
506 VolTrg_Right = (s16)inst1; // m_RightVol
507 //VolRamp_Right = (s32)inst2;
508 VolRamp_Right = (s32)inst2;//(u16)(inst2 >> 0x10) | (s32)(s16)(inst2 << 0x10);
509 //fprintf (dfile, "Ramp Right: %f\n", (float)VolRamp_Right/65536.0);
510 //fprintf (dfile, "Ramp Right: %08X\n", inst2);
511 //VolRamp_Right = (s16)voltarg; // m_RightVolTarget
512 //VolRate_Right = (s16)volrate; // m_RightVolRate
516 static void UNKNOWN (u32 inst1, u32 inst2) {}
518 static void SETLOOP (u32 inst1, u32 inst2) {
519 loopval = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
520 //VolTrg_Left = (s16)(loopval>>16); // m_LeftVol
521 //VolRamp_Left = (s16)(loopval); // m_LeftVolTarget
524 static void ADPCM (u32 inst1, u32 inst2) { // Work in progress! :)
525 unsigned char Flags=(u8)(inst1>>16)&0xff;
526 //unsigned short Gain=(u16)(inst1&0xffff);
527 unsigned int Address=(inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
528 unsigned short inPtr=0;
529 //short *out=(s16 *)(testbuff+(AudioOutBuffer>>2));
530 short *out=(short *)(BufferSpace+AudioOutBuffer);
531 //unsigned char *in=(unsigned char *)(BufferSpace+AudioInBuffer);
532 short count=(short)AudioCount;
536 unsigned short index;
541 if (Address > (1024*1024*8))
542 Address = (inst2 & 0xffffff);
549 memcpy(out,&rsp.RDRAM[loopval&MEMMASK],32);
551 memcpy(out,&rsp.RDRAM[Address],32);
562 // the first interation through, these values are
563 // either 0 in the case of A_INIT, from a special
564 // area of memory in the case of A_LOOP or just
565 // the values we calculated the last time
567 code=BufferSpace[(AudioInBuffer+inPtr)^S8];
569 index<<=4; // index into the adpcm code table
570 book1=(short *)&adpcmtable[index];
572 code>>=4; // upper nibble is scale
573 vscale=(0x8000>>((12-code)-1)); // very strange. 0x8000 would be .5 in 16:16 format
574 // so this appears to be a fractional scale based
575 // on the 12 based inverse of the scale value. note
576 // that this could be negative, in which case we do
577 // not use the calculated vscale value... see the
578 // if(code>12) check below
580 inPtr++; // coded adpcm data lies next
582 while(j<8) // loop of 8, for 8 coded nibbles from 4 bytes
583 // which yields 8 short pcm values
585 icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
588 inp1[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
590 inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
595 inp1[j]=(s16)((icode&0xf)<<12);
597 inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
605 icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
608 inp2[j]=(short)((icode&0xf0)<<8); // this will in effect be signed
610 inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
615 inp2[j]=(short)((icode&0xf)<<12);
617 inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
623 a[0]= (int)book1[0]*(int)l1;
624 a[0]+=(int)book2[0]*(int)l2;
625 a[0]+=(int)inp1[0]*(int)2048;
627 a[1] =(int)book1[1]*(int)l1;
628 a[1]+=(int)book2[1]*(int)l2;
629 a[1]+=(int)book2[0]*inp1[0];
630 a[1]+=(int)inp1[1]*(int)2048;
632 a[2] =(int)book1[2]*(int)l1;
633 a[2]+=(int)book2[2]*(int)l2;
634 a[2]+=(int)book2[1]*inp1[0];
635 a[2]+=(int)book2[0]*inp1[1];
636 a[2]+=(int)inp1[2]*(int)2048;
638 a[3] =(int)book1[3]*(int)l1;
639 a[3]+=(int)book2[3]*(int)l2;
640 a[3]+=(int)book2[2]*inp1[0];
641 a[3]+=(int)book2[1]*inp1[1];
642 a[3]+=(int)book2[0]*inp1[2];
643 a[3]+=(int)inp1[3]*(int)2048;
645 a[4] =(int)book1[4]*(int)l1;
646 a[4]+=(int)book2[4]*(int)l2;
647 a[4]+=(int)book2[3]*inp1[0];
648 a[4]+=(int)book2[2]*inp1[1];
649 a[4]+=(int)book2[1]*inp1[2];
650 a[4]+=(int)book2[0]*inp1[3];
651 a[4]+=(int)inp1[4]*(int)2048;
653 a[5] =(int)book1[5]*(int)l1;
654 a[5]+=(int)book2[5]*(int)l2;
655 a[5]+=(int)book2[4]*inp1[0];
656 a[5]+=(int)book2[3]*inp1[1];
657 a[5]+=(int)book2[2]*inp1[2];
658 a[5]+=(int)book2[1]*inp1[3];
659 a[5]+=(int)book2[0]*inp1[4];
660 a[5]+=(int)inp1[5]*(int)2048;
662 a[6] =(int)book1[6]*(int)l1;
663 a[6]+=(int)book2[6]*(int)l2;
664 a[6]+=(int)book2[5]*inp1[0];
665 a[6]+=(int)book2[4]*inp1[1];
666 a[6]+=(int)book2[3]*inp1[2];
667 a[6]+=(int)book2[2]*inp1[3];
668 a[6]+=(int)book2[1]*inp1[4];
669 a[6]+=(int)book2[0]*inp1[5];
670 a[6]+=(int)inp1[6]*(int)2048;
672 a[7] =(int)book1[7]*(int)l1;
673 a[7]+=(int)book2[7]*(int)l2;
674 a[7]+=(int)book2[6]*inp1[0];
675 a[7]+=(int)book2[5]*inp1[1];
676 a[7]+=(int)book2[4]*inp1[2];
677 a[7]+=(int)book2[3]*inp1[3];
678 a[7]+=(int)book2[2]*inp1[4];
679 a[7]+=(int)book2[1]*inp1[5];
680 a[7]+=(int)book2[0]*inp1[6];
681 a[7]+=(int)inp1[7]*(int)2048;
686 if(a[j^S]>32767) a[j^S]=32767;
687 else if(a[j^S]<-32768) a[j^S]=-32768;
693 a[0]= (int)book1[0]*(int)l1;
694 a[0]+=(int)book2[0]*(int)l2;
695 a[0]+=(int)inp2[0]*(int)2048;
697 a[1] =(int)book1[1]*(int)l1;
698 a[1]+=(int)book2[1]*(int)l2;
699 a[1]+=(int)book2[0]*inp2[0];
700 a[1]+=(int)inp2[1]*(int)2048;
702 a[2] =(int)book1[2]*(int)l1;
703 a[2]+=(int)book2[2]*(int)l2;
704 a[2]+=(int)book2[1]*inp2[0];
705 a[2]+=(int)book2[0]*inp2[1];
706 a[2]+=(int)inp2[2]*(int)2048;
708 a[3] =(int)book1[3]*(int)l1;
709 a[3]+=(int)book2[3]*(int)l2;
710 a[3]+=(int)book2[2]*inp2[0];
711 a[3]+=(int)book2[1]*inp2[1];
712 a[3]+=(int)book2[0]*inp2[2];
713 a[3]+=(int)inp2[3]*(int)2048;
715 a[4] =(int)book1[4]*(int)l1;
716 a[4]+=(int)book2[4]*(int)l2;
717 a[4]+=(int)book2[3]*inp2[0];
718 a[4]+=(int)book2[2]*inp2[1];
719 a[4]+=(int)book2[1]*inp2[2];
720 a[4]+=(int)book2[0]*inp2[3];
721 a[4]+=(int)inp2[4]*(int)2048;
723 a[5] =(int)book1[5]*(int)l1;
724 a[5]+=(int)book2[5]*(int)l2;
725 a[5]+=(int)book2[4]*inp2[0];
726 a[5]+=(int)book2[3]*inp2[1];
727 a[5]+=(int)book2[2]*inp2[2];
728 a[5]+=(int)book2[1]*inp2[3];
729 a[5]+=(int)book2[0]*inp2[4];
730 a[5]+=(int)inp2[5]*(int)2048;
732 a[6] =(int)book1[6]*(int)l1;
733 a[6]+=(int)book2[6]*(int)l2;
734 a[6]+=(int)book2[5]*inp2[0];
735 a[6]+=(int)book2[4]*inp2[1];
736 a[6]+=(int)book2[3]*inp2[2];
737 a[6]+=(int)book2[2]*inp2[3];
738 a[6]+=(int)book2[1]*inp2[4];
739 a[6]+=(int)book2[0]*inp2[5];
740 a[6]+=(int)inp2[6]*(int)2048;
742 a[7] =(int)book1[7]*(int)l1;
743 a[7]+=(int)book2[7]*(int)l2;
744 a[7]+=(int)book2[6]*inp2[0];
745 a[7]+=(int)book2[5]*inp2[1];
746 a[7]+=(int)book2[4]*inp2[2];
747 a[7]+=(int)book2[3]*inp2[3];
748 a[7]+=(int)book2[2]*inp2[4];
749 a[7]+=(int)book2[1]*inp2[5];
750 a[7]+=(int)book2[0]*inp2[6];
751 a[7]+=(int)inp2[7]*(int)2048;
756 if(a[j^S]>32767) a[j^S]=32767;
757 else if(a[j^S]<-32768) a[j^S]=-32768;
766 memcpy(&rsp.RDRAM[Address],out,32);
769 static void LOADBUFF (u32 inst1, u32 inst2) { // memcpy causes static... endianess issue :(
774 v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
775 memcpy (BufferSpace+(AudioInBuffer&0xFFFC), rsp.RDRAM+v0, (AudioCount+3)&0xFFFC);
778 static void SAVEBUFF (u32 inst1, u32 inst2) { // memcpy causes static... endianess issue :(
783 v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
784 memcpy (rsp.RDRAM+v0, BufferSpace+(AudioOutBuffer&0xFFFC), (AudioCount+3)&0xFFFC);
787 static void SETBUFF (u32 inst1, u32 inst2) { // Should work ;-)
788 if ((inst1 >> 0x10) & 0x8) { // A_AUX - Auxillary Sound Buffer Settings
789 AudioAuxA = u16(inst1);
790 AudioAuxC = u16((inst2 >> 0x10));
791 AudioAuxE = u16(inst2);
792 } else { // A_MAIN - Main Sound Buffer Settings
793 AudioInBuffer = u16(inst1); // 0x00
794 AudioOutBuffer = u16((inst2 >> 0x10)); // 0x02
795 AudioCount = u16(inst2); // 0x04
799 static void DMEMMOVE (u32 inst1, u32 inst2) { // Doesn't sound just right?... will fix when HLE is ready - 03-11-01
802 if ((inst2 & 0xffff)==0)
804 v0 = (inst1 & 0xFFFF);
805 v1 = (inst2 >> 0x10);
806 //assert ((v1 & 0x3) == 0);
807 //assert ((v0 & 0x3) == 0);
808 u32 count = ((inst2+3) & 0xfffc);
809 //v0 = (v0) & 0xfffc;
810 //v1 = (v1) & 0xfffc;
812 //memcpy (BufferSpace+v1, BufferSpace+v0, count-1);
813 for (cnt = 0; cnt < count; cnt++) {
814 *(u8 *)(BufferSpace+((cnt+v1)^S8)) = *(u8 *)(BufferSpace+((cnt+v0)^S8));
818 static void LOADADPCM (u32 inst1, u32 inst2) { // Loads an ADPCM table - Works 100% Now 03-13-01
820 v0 = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf];
821 /* if (v0 > (1024*1024*8))
822 v0 = (inst2 & 0xffffff);*/
823 //memcpy (dmem+0x4c0, rsp.RDRAM+v0, inst1&0xffff); // Could prolly get away with not putting this in dmem
824 //assert ((inst1&0xffff) <= 0x80);
825 u16 *table = (u16 *)(rsp.RDRAM+v0);
826 for (u32 x = 0; x < ((inst1&0xffff)>>0x4); x++) {
827 adpcmtable[(0x0+(x<<3))^S] = table[0];
828 adpcmtable[(0x1+(x<<3))^S] = table[1];
830 adpcmtable[(0x2+(x<<3))^S] = table[2];
831 adpcmtable[(0x3+(x<<3))^S] = table[3];
833 adpcmtable[(0x4+(x<<3))^S] = table[4];
834 adpcmtable[(0x5+(x<<3))^S] = table[5];
836 adpcmtable[(0x6+(x<<3))^S] = table[6];
837 adpcmtable[(0x7+(x<<3))^S] = table[7];
843 static void INTERLEAVE (u32 inst1, u32 inst2) { // Works... - 3-11-01
845 u16 *outbuff = (u16 *)(AudioOutBuffer+BufferSpace);
848 u16 Left, Right, Left2, Right2;
850 inL = inst2 & 0xFFFF;
851 inR = (inst2 >> 16) & 0xFFFF;
853 inSrcR = (u16 *)(BufferSpace+inR);
854 inSrcL = (u16 *)(BufferSpace+inL);
856 for (int x = 0; x < (AudioCount/4); x++) {
862 #ifdef M64P_BIG_ENDIAN
877 static void MIXER (u32 inst1, u32 inst2) { // Fixed a sign issue... 03-14-01
878 u32 dmemin = (u16)(inst2 >> 0x10);
879 u32 dmemout = (u16)(inst2 & 0xFFFF);
880 //u8 flags = (u8)((inst1 >> 16) & 0xff);
881 s32 gain = (s16)(inst1 & 0xFFFF);
887 for (int x=0; x < AudioCount; x+=2) { // I think I can do this a lot easier
888 temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 15;
889 temp += *(s16 *)(BufferSpace+dmemout+x);
891 if ((s32)temp > 32767)
893 if ((s32)temp < -32768)
896 *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
900 // TOP Performance Hogs:
901 //Command: ADPCM - Calls: 48 - Total Time: 331226 - Avg Time: 6900.54 - Percent: 31.53%
902 //Command: ENVMIXER - Calls: 48 - Total Time: 408563 - Avg Time: 8511.73 - Percent: 38.90%
903 //Command: LOADBUFF - Calls: 56 - Total Time: 21551 - Avg Time: 384.84 - Percent: 2.05%
904 //Command: RESAMPLE - Calls: 48 - Total Time: 225922 - Avg Time: 4706.71 - Percent: 21.51%
906 //Command: ADPCM - Calls: 48 - Total Time: 391600 - Avg Time: 8158.33 - Percent: 32.52%
907 //Command: ENVMIXER - Calls: 48 - Total Time: 444091 - Avg Time: 9251.90 - Percent: 36.88%
908 //Command: LOADBUFF - Calls: 58 - Total Time: 29945 - Avg Time: 516.29 - Percent: 2.49%
909 //Command: RESAMPLE - Calls: 48 - Total Time: 276354 - Avg Time: 5757.38 - Percent: 22.95%
912 extern "C" const acmd_callback_t ABI1[0x10] = { // TOP Performace Hogs: MIXER, RESAMPLE, ENVMIXER
913 SPNOOP , ADPCM , CLEARBUFF, ENVMIXER , LOADBUFF, RESAMPLE , SAVEBUFF, UNKNOWN,
914 SETBUFF, SETVOL, DMEMMOVE , LOADADPCM , MIXER , INTERLEAVE, UNKNOWN , SETLOOP
918 void MIXER (u32 inst1, u32 inst2) { // Fixed a sign issue... 03-14-01
919 u16 dmemin = (u16)(inst2 >> 0x10);
920 u16 dmemout = (u16)(inst2 & 0xFFFF);
921 u16 gain = (u16)(inst1 & 0xFFFF);
922 u8 flags = (u8)((inst1 >> 16) & 0xff);
928 for (int x=0; x < AudioCount; x+=2) { // I think I can do this a lot easier
929 temp = (s64)(*(s16 *)(BufferSpace+dmemout+x)) * (s64)((s16)(0x7FFF)*2);
932 temp = (temp^0x8000) + 0x10000;
934 temp = (temp^0x8000);
936 temp = (temp & 0xFFFFFFFFFFFF);
938 temp += ((*(s16 *)(BufferSpace+dmemin+x) * (s64)((s16)gain*2))) & 0xFFFFFFFFFFFF;
940 temp = (s32)(temp >> 16);
941 if ((s32)temp > 32767)
943 if ((s32)temp < -32768)
946 *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);